SitePoint Sponsor

User Tag List

View Poll Results: How do you implement properties?

Voters
41. You may not vote on this poll
  • Java style: getFoo(), setFoo($value)

    23 56.10%
  • Obj-C style: foo(), setFoo($value)

    0 0%
  • Php's magic methods: __get() and __set()

    9 21.95%
  • No getters/setters, just plain old properties

    7 17.07%
  • Other

    2 4.88%
Page 1 of 3 123 LastLast
Results 1 to 25 of 51
  1. #1
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How do you implement properties?

    Hi all,

    I've been doing a lot of thinking lately about how to go about implementing property access in my php models, and while I have some ideas to share with you, I'd like to know how other people handle this. Please feel free to describe your approach in greater detail, especially if you chose the last option in the poll.

  2. #2
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I prefer the Java style.

    In my opinion:
    The Obj-C style may cause conflicts if properties have the same name as a method, plus I prefer the explicitness of the "get" keyword.
    Plain old properties don't give you that encapsulation over data members, so it can cause problems if your implementation changes.
    I also try to avoid PHP's magic methods whenever possible, since they can cause headaches for others trying to understand your code.

  3. #3
    SitePoint Enthusiast
    Join Date
    May 2007
    Posts
    28
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I tend to use Java-Style: getFoo(), setFoo($value) and
    try to avoid Magic's whenever possible, because they are slow.

  4. #4
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I use the plain properties, but if a property has to be worked on before returning I prefer the magic methods.

  5. #5
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I debate with this myself at times. While the mantra "All properties should be private" sometimes seen as an unbreakable, the reason has became blurred in modern PHP (and new languages in general).

    In Java, the main reason for using methods instead of giving direct access to properties is that if you need to change something about the property (where it sources it data, needs some filtering, etc) you will break the interface.

    While this makes sense, it not very true to the object oriented paradigm. Methods are for behaviours, and say Person.getAge() is not a behaviour of a person, it is a property.

    In PHP, using the magic methods, if all of a sudden you need to change a property, you can introduce __get and __set then, and backwards compatibility is maintained.

    So, while I don't (not actively developing in PHP for a while) use magic methods, I think I would like too.

    Quote Originally Posted by Tarh
    I also try to avoid PHP's magic methods whenever possible, since they can cause headaches for others trying to understand your code.
    There well documented, especially for PHP5, so really the problems should be minimal. Good commenting could show any competent developer what is happening. PHP4's overload() function might seem a little strange (anyone know how realiable it is?).

    PHP magic methods are not the optimal solution. Implicit getters/setters like in C# would be better. These are pretty easy to emulate though using __get/__set, just remember to have them in every class.

    Quote Originally Posted by mr.vain
    [..] try to avoid Magic's whenever possible, because they are slow.
    Is there a significant overhead with __get/__set? I've seen it been said, but haven't came accross any benchmarks.

    Just thinking out loud.

  6. #6
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Tarh View Post
    The Obj-C style may cause conflicts if properties have the same name as a method, plus I prefer the explicitness of the "get" keyword.
    What kind of conflicts? If you're using getters and setters, you're usually making the properties they're accessing private, so there's no danger of getting your property when you meant the method.

    Quote Originally Posted by Tarh View Post
    I also try to avoid PHP's magic methods whenever possible, since they can cause headaches for others trying to understand your code.
    On the other hand, having a bunch of getters and setters that do nothing but access and write to a hidden property makes for very bloated code.

    Quote Originally Posted by Ryan Wray View Post
    In Java, the main reason for using methods instead of giving direct access to properties is that if you need to change something about the property (where it sources it data, needs some filtering, etc) you will break the interface.
    Fundamentally, the problem is the same as in php, which is simply that neither language supports native setters and getters. It's somewhat mitigated by php's __get and __set, but it's far from ideal.

    Quote Originally Posted by Ryan Wray View Post
    While this makes sense, it not very true to the object oriented paradigm. Methods are for behaviours, and say Person.getAge() is not a behaviour of a person, it is a property.
    Some languages, like ruby, do away with the distinction between properties and methods, and aren't any less OO for it. They tend to be a lot more OO than PHP in many other ways, as well, but that's another discussion.

    Quote Originally Posted by Ryan Wray View Post
    Is there a significant overhead with __get/__set? I've seen it been said, but haven't came accross any benchmarks.

    There's no reason why __get or __set should be significantly slower than a regular method call, although that would depend on the logic contained within the magic call. They're surely slower than regular property access, although I doubt the speed difference is is significant.

    Keep the comments coming, I'm enjoying the different points of view...

  7. #7
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Always via a method. I would regard the other options as bad practice. A class must have a clearly defined interface. How would you specify mock expectations without that?

  8. #8
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 33degrees View Post
    What kind of conflicts? If you're using getters and setters, you're usually making the properties they're accessing private, so there's no danger of getting your property when you meant the method.
    What I meant was, if you have an object like this:
    Code PHP:
    class Bar
    {
       //Getter
       public function getFoo() { return $this->foo; }
     
       //Standard method; "do foo"
       public function foo()
       {
          //Do whatever "foo" means
       }
    }

    Using the Obj-C style, you would not be able to have a "foo" property (where the accessor is named "foo()"), as well as a "foo" method. While the chances of this happening are very rare, I'd rather type the extra three letters than limit myself in that way

    Quote Originally Posted by 33degrees View Post
    On the other hand, having a bunch of getters and setters that do nothing but access and write to a hidden property makes for very bloated code.
    That's why, for accessors which simply return the value, I usually tuck them away in a large group of one-liners with a comment entitled "accessors". I prefer this explicitness (or "bloatedness") over the magic methods, since it may be very confusing for a beginner who doesn't know about the various magic methods in PHP. With explicit getters, the purpose of the functions would be quite clear, even to a beginner.

  9. #9
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff View Post
    Always via a method. I would regard the other options as bad practice. A class must have a clearly defined interface. How would you specify mock expectations without that?
    I don't really see what the problem would be. You have to manually set the expectations, so you're declaring the part of the interface you care about there, aren't you?

  10. #10
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Tarh View Post

    Using the Obj-C style, you would not be able to have a "foo" property (where the accessor is named "foo()"), as well as a "foo" method. While the chances of this happening are very rare, I'd rather type the extra three letters than limit myself in that way
    Right... I'm not sure what the rationale behind the convention is, but it seems to work well. The point will be moot for obj-c soon, though, as they're introducing a property syntax with 2.0

    Quote Originally Posted by Tarh View Post
    That's why, for accessors which simply return the value, I usually tuck them away in a large group of one-liners with a comment entitled "accessors". I prefer this explicitness (or "bloatedness") over the magic methods, since it may be very confusing for a beginner who doesn't know about the various magic methods in PHP. With explicit getters, the purpose of the functions would be quite clear, even to a beginner.
    It's a tradeoff. I'm lazy and a hate the extra typing

  11. #11
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ideally, each property name should be a noun, while each method name should be a verb. Also, I agree with McGruff that ideally no properties should be made public directly; instead an object should have a clearly defined interface -- i.e. a collection of public methods -- which all interactions should go through.

  12. #12
    SitePoint Guru
    Join Date
    Nov 2004
    Location
    Plano
    Posts
    643
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    it doesn't look like anyone is vouching for directly accessing your properties. while this is considered very bad practice, i have tested each method, and find that if you code correctly, accessing these properties from outside the class is no problem at all. i admit when setting a variable, it's best to have the explicit method setX.

    my reasoning is this: if you have a laundry list of set's and get's all crammed into every one of your classes, all one liners, all doing NOTHING but accessing your private data properties, aren't you REALLY making that information public but just adding a middle-man to it? sure, in theory you can add some filters at this level, but in practice I've rarely seen this happen (when i say rare, i mean never...but I'm not discounting the fact that it may happen).

    i've heard a few arguments AGAINST public instance variables, and most of them i find can be easily shot down, as they are NOT good reasons to have 2 methods for every instance variable. i will share my viewpoint about each argument here:

    Argument 1: if you change the variable somewhere else outside the class, and you find a bug in the program, it can be a headache to find the root of that bug as you accessed your variables EVERYWHERE. and this is different than using a middle-man...how? you either use the instance variable directly, or you use the instance method directly...but either way you are still accessing and modifying that information, so your "bug" isn't going to be magically centralized by adding an extra layer to your classes.

    Argument 2: you might need to add a filter to the property well what if you want to access that property WITHOUT the filter. for me, this usually proves to be the case, so having those extra accessors already there for me doesn't help since i need to make a new method anyways. why not just have the instance variables public, and in that case that you need to filter one, setup an accessor that filters that variable.

    lastly, (as someone mentioned before) methods are actions performed by the object. last time i checked, Person's do stuff like skip(), jump(), and play(), but they do not getName(). at least the people i associate with.

  13. #13
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In most of my applications, having a middle-man is an invaluable asset.

    Quote Originally Posted by XtrEM3 View Post
    aren't you REALLY making that information public but just adding a middle-man to it? sure, in theory you can add some filters at this level, but in practice I've rarely seen this happen
    With very few exceptions, I filter almost every value going into my class based on type and contents (ex. using PCRE for strings). Where possible, I also filter the data based on a known list of possible arguments (ex. a recent component to a class I wrote includes a wrapper to the PHP header() function. Instead of validating the name of the header based on valid header names, it only allows headers which are known to be defined in the HTTP 1.1 specs). This gives me extra security and comfort knowing that clients are using my class based on its defined interface.

    Quote Originally Posted by XtrEM3 View Post
    Argument 1: if you change the variable somewhere else outside the class, and you find a bug in the program, it can be a headache to find the root of that bug as you accessed your variables EVERYWHERE. and this is different than using a middle-man...how?
    When the bug involves setting valid data, it is no different. Both methods will give you headaches.

    However, if the bug is occurring because something somewhere in your application is setting your property to an invalid value, the middle man can become extremely helpful. In this case, it can easily be caught by the middle man. For repeatable bugs, this will be caught the moment that you write the invalid code. For bugs which occur in only certain paths through the application, a hook can be added to the middle man to implement debugging code, such as stack traces and variable context dumps to be placed in a debug file.

    Quote Originally Posted by XtrEM3 View Post
    Argument 2: you might need to add a filter to the property well what if you want to access that property WITHOUT the filter.
    If that's the case, your class is not updated with the latest interface design. Classes should have a very clearly defined interface in your documentation in order to maintain proper encapsulation. If you find the need to use your class in a way which it does not currently allow, it's time to re-factor your code -- not bypass it.

  14. #14
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by XtrEM3 View Post
    lastly, (as someone mentioned before) methods are actions performed by the object. last time i checked, Person's do stuff like skip(), jump(), and play(), but they do not getName(). at least the people i associate with.
    Actually, they do, although it would more correctly be called giveName() (a note: method names should be verbs with the object itself as the one who does the action). If I want to know your name, I have to ask you, as I can't pull it out of the thin air; and you may decide whether to give it to me or not.

    In other words, a class designer should know what properties can be passively observed by other objects and what cannot. If we continue our Person example, properties such as hairColor, hairLength, height itd are easily observable if the two Person objects are within Person::sightRange; information such as firstName, lastName or dateOfBirth are not, and you have to ask for them first.

    Now, generally I'd say that the first group of properties are all public while the second are private, but the current implementation of public and private is seriously broken in most major languages that employ them. Specifically, those keywords are used for both setting the visibility of object members as for their extendability, which is nonsense. All members should be extendable by default, and we should only be able to set whether they are visible to all other objects (public) or only the actual object itself (private).

  15. #15
    SitePoint Member etheon's Avatar
    Join Date
    Aug 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I prefer the Java like method, although more specifically for the setters, simply because it allows me to control what happens on modification of a property.

    I don't have any particular theoretical reason to do so, and I can see how magic methods could potentially be useful, although I've heard it been said they're quite slower.

  16. #16
    SitePoint Addict Jasper Bekkers's Avatar
    Join Date
    May 2007
    Location
    The Netherlands
    Posts
    282
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac View Post
    In other words, a class designer should know what properties can be passively observed by other objects and what cannot. If we continue our Person example, properties such as hairColor, hairLength, height itd are easily observable if the two Person objects are within Person::sightRange; information such as firstName, lastName or dateOfBirth are not, and you have to ask for them first.
    To me, the distinction between observable properties and non-observable properties is hardly a practical one because most of the objects in a system will be modeled after artificial concepts that usually regulate their access on object level.
    Design patterns: trying to do Smalltalk in Java.
    I blog too, you know.

  17. #17
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Jasper Bekkers View Post
    most of the objects in a system will be modeled after artificial concepts that usually regulate their access on object level.
    My point exactly.

  18. #18
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    United Kingdom
    Posts
    208
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Something I read once stated that all getters and setters are a sign of bad design, violating the Tell Don't Ask principle. That is, the same reason public instance variables are bad also applies to the getX() and setX() methods. Now you might say that PHP, or any dynamic language, does not suffer from the scenario in the article (e.g. an int return value becomes a float) but if that is the case then surely public instance variables can't be bad either.

    I imagine the common use of getters and setters in PHP are for CRUD-style applications where an object has a 1=1 mapping of properties to a database table. In this case then I think direct access to properties is really the right choice. In the past I've opted for __get() and __set() for the sake of convenience. The properties being accessed are in reality just contained in an array as a property of the object, rather than actual defined properties.

    If a class is designed to do more than simply map a database table then the Tell Don't Ask principle holds true. Accessor methods are a sign that logic which belongs to the class has moved away from the class.

  19. #19
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    United Kingdom
    Posts
    208
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As an aside, __get() has been written such that it is called when a private property is accessed, for example
    PHP Code:
    class Foo
    {
      private 
    $foo;
      function 
    __get$key )
      {
        echo 
    'got fake foo';
      }
    }
    $foo = new Foo;
    $foo->foo// Got fake foo 

  20. #20
    SitePoint Zealot Mau's Avatar
    Join Date
    Jan 2006
    Location
    California, USA
    Posts
    134
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I prefer the Java style for public access.

    Whenever I call a method, I know work is being done and it could be expensive. But, with a property, I tend to think that work is not being done and it's just being loaded from memory.

    That's why I generally don't like magic getters. In an ORM layer, you could be accessing the 'children' property over and over again, but each time you do, a new query is executed.

  21. #21
    SitePoint Addict Jasper Bekkers's Avatar
    Join Date
    May 2007
    Location
    The Netherlands
    Posts
    282
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Shrike View Post
    Something I read once stated that all getters and setters are a sign of bad design, violating the Tell Don't Ask principle.
    Just keep in mind that Allen Holub often takes a radical standpoint (that is correct, mind you) but is too theoretical to be more than good advice.

    Accessors violate more good principles than most other structures but they still exist due to non-object oriented thinking, bad design (time / money constraints), level of experience et cetera.
    Design patterns: trying to do Smalltalk in Java.
    I blog too, you know.

  22. #22
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Mau View Post
    I prefer the Java style for public access.

    Whenever I call a method, I know work is being done and it could be expensive. But, with a property, I tend to think that work is not being done and it's just being loaded from memory.
    This, however, is in direct opposition to the Uniform Access Principle, which states that "All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation." Knowing whether something is being computed or simply retrieved from memory is a violation of encapsulation, as it's an implementation detail, and relying on implementation details couples your code and makes it hard to change.


    Quote Originally Posted by Mau View Post
    That's why I generally don't like magic getters. In an ORM layer, you could be accessing the 'children' property over and over again, but each time you do, a new query is executed.
    If a query is being executed each time, then that's bad design, and not the fault of magic getters. I understand your concern that something you expect to be very light computation-wise is actually expensive, but again those are implementation issues, not interface ones.

  23. #23
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ryan Wray View Post
    In Java, the main reason for using methods instead of giving direct access to properties is that if you need to change something about the property (where it sources it data, needs some filtering, etc) you will break the interface.

    While this makes sense, it not very true to the object oriented paradigm. Methods are for behaviours, and say Person.getAge() is not a behaviour of a person, it is a property.
    While it's true that methods should be used for behaviors, I think the need for encapsulation supersedes it. Being true to the object oriented paradigm is highly dependent on the features of your language, and in the case of languages that don't natively support properties, the proper solution is to use methods. In fact, according to OO principles, a stored value in an object is a data member and not a property, properties being a construct that has the same usage syntax as a data member but are implemented like a method; the closest thing that PHP has to that is __get and __set.

  24. #24
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How do I implement properties? Simple: By using properties.

    I hate to write code I don't need. If there is no reason to modify data before getting or setting it, I won't. For times that I do, I will create methods for doing that processing. Why am I going to add 2 new functions to bloat my class with when I can easily just use properties for exactly what they were intended for - to return or set the value. It's easier, and it's using functionality that's already built in to the programming language. I'm not getting paid by the line here, so why add 10 extra lines of code for every property in the class? To me, that just doesn't make sense for most needs.

    If I am making a common interface or API, I would probably make the getter/setter methods, but in actual practice where time is money and you're always on a deadline, It's extra code that doesn't need to be there.

  25. #25
    SitePoint Addict
    Join Date
    Jun 2005
    Posts
    260
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac View Post
    I use the plain properties, but if a property has to be worked on before returning I prefer the magic methods.
    Are you referring to the __set magic method or __call magic method?

    I ask, because you can use either. For example, let's say the __set magic method were constructed like so:
    Code:
    public function __set($key, $value)
    {
        $method = 'set_' . $key;
        if (method_exists($this, $method)) {
            $this->$method($value);
        } else {
            $this->data[$key] = $value;
        }
    }
    You could have a set_something($something) method, which perform pre-processing/filtering:

    Code:
    public function set_something($something)
    {
    	$this->data['something'] = strtoupper($something);
    }
    Then setting a class property like so:
    Code:
    $object->something = 'uppercase me, then set me';
    would be intercepted by the __set magic method, which would silently call the set_something() method, which uppercase, then sets "something".

    Is anyone employing this usage of __set or the other magic methods in order to eliminate get_*, or set_* methods, even those dynamically called by the __call magic method?


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •