构造函数与太多的获取和设置
我拥有 18 处房产,创纪录。
在将该类提交到数据库之前,所有 18 个属性都必须具有经过验证的数据。
因为我正在 OOP 化一个工作程序 Web 应用程序,所以我进行了这种倒退。
首先,我讨论了修改现有记录的工作流程。当时,将所有 18 个属性放入 __construct 方法并避免 setter 的垃圾负载是有意义的。一个单独的加载器类处理数据库业务,并且可以返回单个对象或记录对象数组。一切顺利。
但是后来是时候解决新的记录创建工作流程了,突然我需要实例化一个空记录,除了我的记录构造函数是一个饥饿的野兽,需要 18 个参数......
所以你剥离构造函数?但随后我必须添加 18 个 setter,并在每次我想要处理现有记录时调用它们……
这似乎没有多大改进! :-/
真正的程序员如何处理这个问题? (我只是一个小小爱好者……)
I have a record class with 18 properties.
Before that class can be submitted to the database, all 18 properties must have validated data.
Because I'm OOP-ifying a working procedural webapp, I went about this sort of backwards.
First I addressed workflow for modifying existing records. At the time, it made sense to throw all 18 properties into the __construct
method and avoid craploads of setters. A separate loader
class handles the dbase business and can return either single objects or an array of record objects. That all worked ok.
But then it came time to address the new record creation workflow, and suddenly I needed to instantiate an empty record, except my record constructor is a hungry beast that wants 18 parameters...
...so you strip the constructor? But then I'd have to add 18 setters and call them all each time I want to work with an existing record...
doesn't seem like much of an improvement! :-/
How do real programmers handle this? (I'm just a weenie hobbyist...)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
默认参数都是一个选项,但是如果您只想使用第一个和最后一个参数,则必须填写大量空值。
再说一遍,您可以进行数组循环:
或者,如果您想保留旧的构造函数签名:
新版本还为您提供了简单的选项:
Either default arguments is one option, but then you have to fill out a large number of null's if you only want to use, say, the first and last.
Then again, you could do array looping:
Or, if you wanted to keep your old constructor signature:
The new version also gives you the option to simply:
在任何类型的函数中填充 18 个参数(包括构造函数)都是不好的。当您几个月甚至几天后查看代码时,您将永远不会记住正确的顺序。此外,正如您所经历的,当您需要扩展课程时,这很困难。
这就是为什么我通常更喜欢使用 getter 和 setter 进行课程。是的,这需要更多的打字,但是使用 getter 和 setter,用户可以轻松查看他们可以获取和设置哪些属性,而且 getter 和 setter 是 IDE 的自动完成友好型。
现在,下一个问题是您不想在从数据库读取现有记录时一直调用 setter 吗?你说你有一个
Loader
类,难道你不能把所有对setter的调用集中在Loder
类中吗?因此,当您想要使用现有的方法时,只需调用 Loader.getMyObject();
如果您不想在
createMyObjectFromDbData
中键入所有 18 个 setter 调用,那么只要您的 setter 遵循一些命名约定,您就可以执行您可能还需要添加一个
validate
方法来验证对象中的所有属性,以便您可以在提交要插入的对象之前调用该方法数据库。Stuffing 18 parameters in any sort of function is (constructor included) is bad. You'll never remember the correct order when you look at your code few months, or even few days from now on. Further more, as you experienced, when you need to extend the class it's hard.
That's why I usually prefer having classes with getters and setters. Yes it's more typing, but with getter and setters users can easily see what properties they can get and set, plus getter and setters are IDE's auto-complete friendly.
Now, the next problem is you don't want to call setters all the time when you read existing record from the database? You said you have a
Loader
class, can't you just centralize all the calls to setters in theLoder
class?So when you want to work with existing you can simply call
Loader.getMyObject();
If you don't feel like typing out all the 18 setter calls in
createMyObjectFromDbData
, then as long as your setter follows some naming convention you can doYou may also want to add a
validate
method to validate all the properties in the object so you can call that method before you submit it to be inserted into database.您可以将它们链接到构造函数。在哪里执行此操作...
$Record = Record()->Name('Mark')->Location('A-Town, NY')->Phone('123-345-6789' );
您可以通过创建一个与类同名的函数来返回类的新实例来实现此目的。
如果您需要验证某些数据,可以稍后添加该功能。
You can chain them to the constructor. Where you do this ...
$Record = Record()->Name('Mark')->Location('A-Town, NY')->Phone('123-345-6789');
You can do this by making a function that has the same name as your class that returns a new instances of your class.
If you need to validate some data, you can just add the function on later.
在完美的世界中,您的对象将允许您使用构造函数或设置器来指定值。为了简化事情,您可以做的是提供一个构造函数,它只接受 18 个值的子集,并将其余值设置为默认值。但这假设存在有意义的默认值,但情况可能并非如此。
In a perfect world your object would allow you to specify values using either the constructor or setters. What you could do to simplify things is provide a constructor that only accepts a subset of the 18 values and sets the rest to default values. But that assumes that there are default values that make sense, which may not be the case.
如果一个对象有很多属性,并且不想将它们全部包含在构造函数中,则可以使用 setter 返回对象本身来编写稍微更具可读性的代码:
同样,如果所有值都需要要在获得有效对象之前进行验证,可以使用构建器对象来执行相同的操作。基本上,您创建一个构建器对象,设置值,然后告诉构建器创建实际的对象。然后,它可以在构造对象的实际实例之前对所有值进行验证(包括使用多个字段的验证)。
If you have a lot of properties for an object and you don't want to include them all in the constructor, you can use setters return the object itself to make slightly more readable code:
Along the same lines, if all of the values need to be validated before you have a valid object, you can use a builder object to do the same thing. Basically, you create a builder object, set the values, and then tell the builder to create the actual object. It can then do the validation of all the values (including validation that uses multiple fields) right before it constructs the actual instance of the object.