Generated getter and setter functions

thread: 4 messages  |  last: about 2 years ago  |  started: sunday, november 15, 2009, 8:19 am pst


#1  |  Julian Pustkuchen (Porta Westfalica, NRW (Germany)) Germany
Sunday, November 15, 2009, 8:19 AM PST

Hi,

I searched for generated getter and setter functions, so to not work on the class properties directly.

What do you think about generating those automatically?

Example:

Class: Person
Attributes: name, age

Now I receive and set the values by:

$person->Name; // $person->name = 'Peter';

Why not use a cleaner version like generated by Eclipse for example:

$person->getName();
$person->setName('Peter');

Advantages / Ideas:
- Generate them as comments in XX.class.php (might not be helpful in bigger projects -> much work to uncomment)
- Add the possibilty to add individual steps to generation, so this must not be generated for every user of Qcodo, but the ones who like to
- If not generated in XXGen.class.php you can add individual steps to setting value for example
- You can control the access rights and prevent usage of setting values directly, if you don't want to (by setting access level to protected/private)
- Anyway, getters and setters are generally recommended in design patterns and lead to more flexibility. Why not?

Would be nice to hear about it.
Thanks!

#2  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Monday, November 16, 2009, 7:48 AM PST

Julian, thanks for the post.

It's definitely a good idea, but it's likely something that won't necessarily make it back to the core distribution, for a couple of reasons:

As a standard, Qcodo has decided on using actual properties via the PHP magic _get and _set construct instead of explicitly defined getX() and setX() method calls.  There aren't necessarily huge pros and cons with either approach... except that in my experience and in my opinion (which folks can obviously be more than free to disagree with =) the direct property access is a bit cleaner than a get() and set() method call:

$objFoo = new Foo();
$objFoo->FirstName = 'Mike';
$objFoo->LastName = 'Ho';
$objFoo->Phone = '650-555-1212';
$objFoo->Save();

as opposed to

$objFoo = new Foo();
$objFoo->SetFirstName('Mike');
$objFoo->SetLastName('Ho');
$objFoo->SetPhone('650-555-1212');
$objFoo->Save();

I feel the former has a more natural look and feel in that setting properties feels more like setting variables.  While with the latter, the various set method calls and the save method call all look like method calls, making it less clear at quick glance which lines are property accessors and which lines are meant to be traditional method calls.

Again, not a big deal, and of course, folks are more then welcome to disagree with me here. =)  But it's just the way that was decided from early on for Qcodo.

Second, since the magic methods in and of themselves are methods that can be called directly, we have an added benefit of being able to programmatically setting and getting properties without having to have to use reflection or PHP func_call type functionality:

$objFoo = new Foo();
$strPropertyName = 'FirstName';
$objFoo->__set($strPropertyName, 'Mike');

Also, since all the classes (not just the codegen generated ones) use this same construct, it made sense to just be consistent, so that properties for generated data classes match the properties every where else (e.g. QControl classes, other framework classes, etc.).  To move away from _get and _set magic method-based properties and to go to explicit getX() and setX() method declarations everywhere would be quite a monumental task.

But you're right, getters and setters are definitely a great and recommended design pattern -- so I definitely encourage everyone to continue using them via the property accessors.

But for folks/teams/projects that actually prefer explicit getX() and setX() method declarations, I think it would actually be pretty easy and straightforward to do that by simply overriding one or two of the codegen templates to add the code snippets for you getX() and setX() calls.  I think if you really did want to go with that approach, there is no reason to go ahead and generate it as actual code (e.g. not as comments) within the Generated data classes, so that they'll all automatically be available to you as you code generate your classes.

#3  |  Julian Pustkuchen (Porta Westfalica, NRW (Germany)) Germany
Monday, November 16, 2009, 8:29 AM PST

Hi Mike,

thanks for your very fast response!

The points you make are clear to me and I accept them as reason for not implementing getters and setters in core functionality.

On the other hand you should perhaps not forget, that it might be interesting to preserve people from setting values directly. While using magic methods it would only be possible by throwing an exception/error in the case-switch, isn't it?

That's the main thing one should think about, especially because even if you use getters and setters (manually generated or whatever) you can only prevent people this way from using the direct setting option (->var = ...) instead of a business logic, which may lead to unexpected results.

I know... you can't prevent people from writing bad code, but on the other hand, that's what function visibility is made for. Furthermore you can use the magic methods in the future, but set visibility level to variables protected.

Anyway, as already said, I understand your oppinion, so let's not further discuss that. Would just be nice, if you and your team could take it into consideration later on. But...

What about a hook function or file  or configuration setting for additional individual generation processes?

This way you might give the opportunity to the community to implement addons (which might even be shared accross the project).
I think this might be a nice thing, which OpenSource lives from!

Would you think about it and perhaps discuss that in the development team?

Perhaps something like a module section, more or less seperated from core might build up.

I wouldn't like to use overriding for this, because this would not meet the needs I think and might lead to less clarity and more complicated code structure. Hooks or configuration settings (XML, Config, whatever...) might be more well structured.

Sorry for the long text.
Hope you will read it anyway.

#4  |  Mike Ho (Sunnyvale, CA) United States of America Qcodo Administrator
Thursday, November 19, 2009, 7:20 AM PST

Good points... yeah, to override a generated setter so that it no longer allows that value to be set (e.g. to change a property to be read-only) can be done by implementing that setter in the __set() method in your customizable subclass for your form.

In terms of the second question about hooks to easily implement this kind of functionality, fortunately, the hooks already do exist. =)  Anyone at any time can implement customizable templates which either add to or overrides the existing codegen templates.  So if you want to implement a set of templates/subtemplates which adds the above functionality you are wanting (or even replaces the existing magic method functionality), you can definitely do so.  For more info, see the _README.txt file in the includes/qcodo/codegen/templates directory.

And finally, you if you do end up making these customizations and want to share them with other, note that even codegen customizations is packagable and sharable using the Qcodo Package Manager (QPM) platform.... so you can feel free to use QPM to package and post your customizations, in order to get feedback from others and hopefully ongoing improvements from others as well. =)



Copyright © 2005 - 2012, Quasidea Development, LLC
This open-source framework for PHP is released under the terms of The MIT License.