• bob (unregistered) in reply to Matthew Watson
    Matthew Watson:
    Well C# let's you just do:

    public int SomeProperty {get; set; }

    And then you can add any logic later on as the need arises.

    Also, people are overlooking a very useful thing about using public properties instead of public fields: You can set a debugger breakpoint in the property setter to determine when and by what it's being set. Try doing that with a public field...

    You could use a data breakpoint.

  • ralf (unregistered)

    I must admit: I am gulty of doing something very simmilar a couple of years back. But hey, we are here to learn.

    One thing I did not see mentioned is that in C# it it not possible to use properties as out parameters. WTF? Yeah, right.

    I am currently on a project where there are a lot of methods that have a zillion out parameters. I didn't design those interfaces so don't blame me. I just have to grin an bear it.

    Usally the out params of such a method are somewhat related to one another so there is a good chance they will end up together in one object. If the class of this object has public fields instead of props you can just use them like that:

     StupidMethod(inParam1, inParam2, out result.OutParam1, out result.OutParam2, ....)
    

    you get the drift. It saves me from declaring n local variables, it saves me from assembling the result. So I do it that way.

  • (cs) in reply to Jeh-fuh-fuh
    Jeh-fuh-fuh:
    Matthew Watson:
    Jeh-fuh-fuh:
    Matthew Watson:
    You can set a debugger breakpoint in the property setter to determine when and by what it's being set. Try doing that with a public field...
    Try learning how to use a debugger ;)

    Try learning how to use C#. You CANNOT set a memory change breakpoint when you're debugging C# code. Duh!

    That's just incorrect, but nice try. Conditional breakpoints are your friends. Among those conditions are "when changed" which most definitely can be set on a member variable. Check it out sometime.

    OK, guys, help me out here because that's a feature I really want to use. Are we talking Visual Studio? Because whenever I try to create a breakpoint, New->Data Breakpoint is grayed out, and only New->Function Breakpoint is available. So help me out here, because Google comes back with a lot of Microsoft MVPs that says "Data breakpoints are not supported by C# at this time".

  • ralf (unregistered)

    on another note: In an oo world some people think that "Getters and Setters are Evil" (http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?page=1).

    And hiding the access to some private data behind a property is like putting up a sign "Do not enter. You might see stuff that really interests you."

    my favorite class gets all of its state in the constructor and offers me methods. I don't want to know how the stuf works.

  • Michael (unregistered) in reply to jfp
    jfp:
    The real WTF is that you guys are actually advocating using public fields over public accessor methods.

    Agree. Accessor methods reduce code complexity because they can provide guarantees about what users of the object can and can't do. Public fields are insane because any code anywhere could be doing anything with them. If someone has actually worked on a medium or large scale project and still thought public fields were a good idea (outside of edge cases) I'd say they were too retarded for software development.

    I really have to disagree with this. I'd say the python programming language is a medium to large size project, and if you look at the code for the core language and associated libraries, it's got public fields all over the place. It trusts people not to do stupid things with the public fields, or else nothing will work (surprise surprise). It's the "we're all adults here" philosophy. Go try checking out the code sometime, you can get it through python.org.

  • Jimmy the Geek (unregistered)

    Never ever ever show any raw variable from the inside of an interface. People directly accessing properties makes it difficult to change those properties later, and makes it impossible to override the properties with a new class that inherits from the old class.

    And you will be 100% stuck with the implementation if you ever published this interface as a library that outside people use.

    It is idiotic that object oriented languages don't insist that every interface be completely opaque.

    I even make all my C interfaces completely opaque. When you make a new string in my c classes you get a handle that you have to use accessors on in order to access the data.

    What if later you need to retrieve that property from a database instead of a integer? What if you change how you are storing the value? What if you want to override the accessor functions in a new class? What if you want to send additional messages when that field changes?

    An example of this was a string class I had to work with a few years ago. The class exposed the members of the struct outside the interface. So when I changed the way memory was allocated in the string class I had to track down everywhere that let code mess with the inside of the class and pull the data processing of that class member back inside the class.

    A properly opaque interface would have enforced the need to make sure that all the string processing that was happening was going on side the string class and not spread out in 200 places. Yes, string processing was literally being done in different 200 places, with code that was subtly different in every place.

  • DMW (unregistered) in reply to Mike D.
    Mike D.:
    I'm wondering how this is done in Perl? Just one way to do it, please, I'm sure there are more. ^_-

    In modern Perl, you use Moose to handle properties. For example, this declares an integer property called "x" that's readable and writable:

    has 'x' => (isa => 'Int', is => 'rw');
  • bill (unregistered) in reply to Anonymous Coward
    Anonymous Coward:
    You have forgotten one of the most immediate benefits: Keeps others from messing with your internal fields.

    For example, if you have a method that defines a string. Using setters you can insure that the string is never set to an invalid valid. So the string might never be null, or it might always be twelve characters long. The setter can enforce the restrictions.

    The rest of the class no longer has to check that the string is not null before using it. The rest of the code can assume that the string will be valid.

    Getters and setters allow your method to protect itself from other programmers who will end up on this site someday.

    Also if you leave it with semantics equivalent to a public field, you have explicitly exposed the internal member. So when someone looks at the code later, they can infer that the original coder intended to expose it that way.

  • bob (unregistered) in reply to Michael
    Michael:
    jfp:
    The real WTF is that you guys are actually advocating using public fields over public accessor methods.

    Agree. Accessor methods reduce code complexity because they can provide guarantees about what users of the object can and can't do. Public fields are insane because any code anywhere could be doing anything with them. If someone has actually worked on a medium or large scale project and still thought public fields were a good idea (outside of edge cases) I'd say they were too retarded for software development.

    I really have to disagree with this. I'd say the python programming language is a medium to large size project, and if you look at the code for the core language and associated libraries, it's got public fields all over the place. It trusts people not to do stupid things with the public fields, or else nothing will work (surprise surprise). It's the "we're all adults here" philosophy. Go try checking out the code sometime, you can get it through python.org.

    That is just asinine, every time you code something like that, its one more thing the programmer has to remember when they use the class. As the project gets larger and larger, there will be more and more things to keep track of.

    Preventing people from doing stupid things is a secondary effect of data hiding; the primary effect is to help manage complexity.

    your "we're all adults here" philosophy is off. Adults should be responsible. In this case it means making your code robust, and knowing your limitations. I.e. trusting that people not to do stupid things, doesn't help is someone makes a mistake, people can and will fuck up.

  • Michael (unregistered) in reply to bob
    bob:
    Michael:
    I really have to disagree with this. I'd say the python programming language is a medium to large size project, and if you look at the code for the core language and associated libraries, it's got public fields all over the place. It trusts people not to do stupid things with the public fields, or else nothing will work (surprise surprise). It's the "we're all adults here" philosophy. Go try checking out the code sometime, you can get it through python.org.
    Preventing people from doing stupid things is a secondary effect of data hiding; the primary effect is to help manage complexity.

    your "we're all adults here" philosophy is off. Adults should be responsible. In this case it means making your code robust, and knowing your limitations. I.e. trusting that people not to do stupid things, doesn't help is someone makes a mistake, people can and will fuck up.

    If adults are responsible and follow conventions and read documentation and such as they're supposed to, mistakes will be minimized. But you can never prevent anyone from making mistakes all the time. You always have to find a balance between using an easy implementation, providing powerful capabilities, reducing complexity and many other things. I think you just have a different idea of where the best point on that balance lies. I think there are examples of complex projects that show you don't always need to have careful data hiding. Sure, that may cause problems sometimes, but so can hiding data that turns out to be necessary to fiddle with.

  • g (unregistered) in reply to Mike D.
    Mike D.:
    Yeah, I like the Python way, too. Start off just making things attributes.
    class Parrot(object):
      def __init__(self):
        self.alive = True
    

    If you need a getter and/or setter, just define them as a property.

    class Parrot(object):
      def __init__(self):
        self.alive = True
      def _GetAlive(self): return self.alive
      def _SetAlive(self, stillAlive):
        if not stillAlive:
          print "This parrot has expired!"
        self.alive = stillAlive
      alive = property(_GetAlive, _SetAlive, None, "Is the parrot alive?")
    

    Works just as well as the getter/setter combo, looks just like an attribute.

    I'm wondering how this is done in Perl? Just one way to do it, please, I'm sure there are more. ^_-

    {/n#^.9/\a.#2/[]1.v&^[email protected][/.z]*6.};

  • (cs) in reply to Michael
    Michael:
    If adults are responsible and follow conventions and read documentation and such as they're supposed to...
    Dude, sorry, but do you even read this blog? Good lord.

    Sorry, but there are just too many irresponsible programmers out there. Those who are responsible need to protect the product as much as we are able.

  • (cs) in reply to Michael

    amen!

    Every character in the source code should be there for a good reason and the source code should be readable. Build good code for the present, never code for a nebulous future and never code for the past.

    One good reason for getters/setters may be so that you can grep through it and quickly find the meaningful fields of a class. I tend not to prefer them, but it helps to know your audience.

  • Jeh-fuh-fuh (unregistered) in reply to Erzengel
    <quote>

    OK, guys, help me out here because that's a feature I really want to use. Are we talking Visual Studio? Because whenever I try to create a breakpoint, New->Data Breakpoint is grayed out, and only New->Function Breakpoint is available. So help me out here, because Google comes back with a lot of Microsoft MVPs that says "Data breakpoints are not supported by C# at this time".</quote> I did it by clicking on the border are to the left of the member var which created the breakpoint; then right clicking on the breakpoint itself to edit properties. This was in VS 2005 SP1.

  • Michael (unregistered) in reply to Erzengel
    Erzengel:
    Michael:
    If adults are responsible and follow conventions and read documentation and such as they're supposed to...
    Dude, sorry, but do you even read this blog? Good lord.

    Sorry, but there are just too many irresponsible programmers out there. Those who are responsible need to protect the product as much as we are able.

    Read the next sentence from my quote: "But you can never prevent anyone from making mistakes all the time." Do you really think the people who wrote the stuff posted here would have come up with nice, correct, clean code if data was hidden from them more thoroughly?

  • (cs) in reply to g

    Getter and setter in perl? Put this in a base class and perl has getters and setters automatically. Its dangerous, because it would work with mispellings, but life isn't a safe thing.

    sub AUTOLOAD { my $self = shift; my $sub_call = $AUTOLOAD; if( $sub_call =~ /^get_(.)/ ) { my $field = $1; return $self->{$field}; } elsif( $sub_call =~ /^set_(.)/ ) { my $val = shift; $self->{$field} = $val; } }

  • Michael (unregistered) in reply to Jeh-fuh-fuh
    Jeh-fuh-fuh:
    <quote>

    OK, guys, help me out here because that's a feature I really want to use. Are we talking Visual Studio? Because whenever I try to create a breakpoint, New->Data Breakpoint is grayed out, and only New->Function Breakpoint is available. So help me out here, because Google comes back with a lot of Microsoft MVPs that says "Data breakpoints are not supported by C# at this time".</quote> I did it by clicking on the border are to the left of the member var which created the breakpoint; then right clicking on the breakpoint itself to edit properties. This was in VS 2005 SP1.

    Have you tried using this breakpoint? I can't get it to break whenever a certain variable is changed like I'd want.
  • Neeneko (unregistered)

    Eh, while they have their place, I've often seen use of get/set functions as a form of over design or premature generalization. Making code more complex under the theory that said complexity will make other changes simpler IF they get requested later on. On the other hand, the increased complexity can be a problem for the whole lifespan of the project. You've just replaced a single line of code with nearly a dozen lines. That is 12 times as many places where a typo or a cut/copy/paste error can creep in, 12 times as much screen space used up making the class harder to visually scan.

  • Cbuttius (unregistered) in reply to Delmania
    Delmania:
    fusspawn:
    Agreed, and in the process of pointing out im not as "l337z Coderz" as some of you, How large is the performance hit for doing it with get/set over not bothering.

    Which language? In C++, you just declare the accessors and mutators as inline which enables you to maintain the benefits of encapsulation, but still removes the context switching.

    However, the real benefits for this practice is that it allows the implementation of that value to change which maintaining the definition. Sure, looking at something like

    private: CString m_name; public: inline void SetName( const CString& name ) {m_name = name;} inline CString GetName() {return m_name;}

    An you might wonder why you simply don't just let m_name be public. The reason is that by using the 2 functions, you've enabled someone to inherit your class, redefine the Set and Get functions, and still allow C++ to dynamically bind members of the class. You've also made it so that you change what happens when those functions are called and have that change impact nothing outside of the class itself.

    Oh dear, what a load of nonsense. I might forgive you for using CString as the string type rather than std::string - there can sometimes be good reasons to use CString. And I might forgive you for making the function name begin with an uppercase letter as that is style.

    The other issues are more problematic.

    Firstly you did not make the Get function const. This means that other const-correct problems will occur later on in the code, for example, if someone has a const reference or pointer to your class they cannot call GetName() which means they'll probably fix it by using a non-const reference or pointer (I have enough experience to know they'll do that). Which will cause other lack of const-correctness all over the project.

    Secondly your GetName() returns by value not const reference. In this case where it is inlined and where m_name appears clearly in the header, there is no reason to not use the more efficient option.

    By the way, if you think it might upset calling code if a subsequent implementation change caused you to change it to return by value, it would not. If the calling function binds it to a const reference that is fine as you can do that with a temporary.

    Finally your nonsensical comment about someone changing the implementation by inheriting from it... sorry but your Get and Set functions are non-virtual. I assume that the person who inherits from your class is not going to change your own header.

    There are reasons outlined in the responses already why having the methods is advantageous - particularly the Set() method, and then only if you want users to be able to set the value directly. And there is no way to make a member externally readable but not writable. (Actually there is but it's a bit of a hack. Make it a const reference to a private member!).

    As for actual encapsulation, that is best done (in C++) with a pImpl or abstract base classes, not with private data members (other than a private pImpl). (And in Java use interfaces for encapsulation).

  • Some Guy (unregistered)

    Ok, the real WTF: doing anything (use of getters and setters, refusal to use getters and setters) because that's the way you've always done it is the problem.

    And the reason why you've always done it that way is that you were taught by someone who thinks that C is the ultimate language and never became comfortable with objects as anything other than a good old C struct holding a bunch of data that's used by code in a dozen different places.

    People who do this are the same ones who try to write functional code with mutable data and bolt static typing onto duck-typed languages. It never works, but they keep on trying to do things the way they've always done it, no matter how different the language may be.

    This also explains why we need static typing and compilers - if you change the data type of a "property", you then get code in 50 different classes and only the compiler can hope to catch most of the bugs that will be introduced, and even then implicit casting will let a few get through. And unless you understand that Python is very very different to C, your efforts to write C code in Python will end in tears.

  • (cs) in reply to Michael
    Michael:
    It trusts people not to do stupid things with the public fields, or else nothing will work (surprise surprise). It's the "we're all adults here" philosophy.
    Oh, you mean like trusting people not to hack your website, and trusting emailed executables not to be viruses?
  • Mr.'; Drop Database -- (unregistered)
  • Real-modo (unregistered)

    So... apart from Shambo and Jason, nobody has a problem with the "jump-to-another-page inside a property-get" design?

    And you guys look down on PHP coders. Hmm.....

  • Sneaky Feelings (unregistered) in reply to Michael
    Michael:
    Michael:
    Erzengel:
    Michael:
    How does changing that metadata affect consumers of the class? This sounds like something I'm not familiar with; can you explain it or provide a link? I guess I could see if the consumer used reflection it might affect them, but other than that is there any impact on consumers?
    If this was a class library, now you have an unknown number of other class libraries or executables that you must recompile. If you had just used a property in the first place, no recompiling would be necessary, you would simply change the internal code without changing the external interface.
    Does this mean if I provide a DLL with a class that has a public field and later change that public field to a property that the DLL will no longer work with applications that were compiled using the old version?
    Well, I just checked that and it's true. The old executable won't work with the new class library. That's the most convincing reason I've seen yet. In C# at least, you really can't freely convert between properties and public fields if you want classes to be usable by external consumers. That's another vote for python in my book, and it's good to know when writing C# code.

    I've a sneaky feeling the .Net compiler converts all properties into function calls for compatibility with (potential) .Net languages that can't directly handle properties. MyProp { get; set } is made available as a property called MyProp and two functions called "getMyProp() and setMyProp()".

    That's another reason to use properties to avoid refactoring afetr introducing them.

  • randomo (unregistered)

    languages without implicit accessors/mutators, which allow you to create your own explicit accessors/mutators later, without any refactoring, suck.

  • MoffDub (unregistered)

    Oh joy, the timeless getter setter debate.

    After many arguments with myself, I have concluded that have public getters for every field is bad if it doesn't let you hide the type of the member. If you have a property called ID, declared as an int, and later you change it to long, the change ripples out to whomever is using that property. Either encapsulate ID into its own class, with behavior, or have the getter return a string.

    As far as setters, setters are OK if, again, you can hide the type, and the property you are setting can change alone during the lifecycle of the object. Anything else should be via constructors.

    That said, following these guidelines can still allow procedural OO to be written, where the work that should be done by the class itself is done outside of it. This is the real problem with Eclipse's "Generate Getters and Setters" option. It is a people problem that can't be solved by any language. However I think these guidelines make it harder for people to make the mistake.

  • (cs) in reply to DMW
    DMW:
    Mike D.:
    I'm wondering how this is done in Perl? Just one way to do it, please, I'm sure there are more. ^_-

    In modern Perl, you use Moose to handle properties. For example, this declares an integer property called "x" that's readable and writable:

    has 'x' => (isa => 'Int', is => 'rw');
    One more freakin module to download (plus dependencies), but until Perl 6 comes along, you're probably right. I understand that Perl 6 has not yet been released because Larry is waiting until he can "universalise the concept." You know that thing about "Perl will always try to guess what you wanted to do?" Well, Perl 6 will apparently be based around a non-deterministic quantum finite state engine -- the working name is "Schroedinger's Parrot" -- which is guaranteed tto make the right guess. Of course, if you dislike the current line-noise approach, just wait until you see the result of collapsing two super-positioned quantum regexps...

    In Perl, there's always more than one way to give only one answer. So here goes:

    (1) The Way Of Ancient Wisdom. Use Tie. This is the simplest way yet found to implement self-harm in a programming language. (2) The Junior Space Cadet Way. Use Class::Accessor. I guess if you got your design wrong the first time, or in other words you're writing programs in Perl, then this is the way to go. (3) The Senior Space Cadet Way. Use Class::Data::Accessor. Naturally, this incorporates the Junior Space Cadet Way, but it adds inheritance. Jamie Z's aphorism is applicable throughout Perl. (4) The Tin Foil Hat Way (as mentioned above). Use one of Perl's many "Oh fuck it ain't there" mechanisms. Personally I prefer a naked random redirect to a new page, which might at least be constructed in a language that isn't Perl. (5) ... Well, five. I can do no better than to repeat the Canonical Perl Way Of Oneness:

    g:
    {/n#^.*9/\a.#2/[*]1.v&^[email protected][/.z]*6.};
    And then there's (6) There is No Sixth One Way.

    Except in Perl, where (6) is the Pink Fairy Way. Just forget about accessors entirely. My language specifically invites you to touch my privates. But if you try to do so, I know where you live. I'll come round and rip yours off.

    That's the Spirit of Free Software, in a nut. Or two, if you're not Hitler.

  • Ant (unregistered)

    First ever post and captcha is saluto

    Part of OO I was taught is to tell don't ask. Compare fields internally within methods/derived properties rather then reference public properties as code is more extensible that way

  • (cs) in reply to Cbuttius
    Cbuttius:
    Oh dear, what a load of nonsense.
    Have you read the title of this site? Are you not aware that the lead article is simply a device to suck today's WTFiness out of the intertubes?

    Don't try the pontifex on us, matey. Actual facts and/or logic belong on sites like www.dummies-guide-to-partial-template-template-instantiation-programming.com, or at least in colleges that don't teach CompSci in hawk spit Java. (I wonder if they still teach J2EE? Maybe that's just in Metaphysics 101.)

    No, here we just deal in Pointless Vilification and Bad Humor. ("Hello, Ma'am; I'm the Bad Humor Man. May I shit on your doorstep today?") We'd also like Sex and Drugs, but, frankly, who would give them to us?

    BTW I agreed with everything you said.

  • Tim (unregistered)

    Obviously you didn't get the point of encapsulation - it's futureproofing the interface of the class. So you can change the internal implementation of the class (data structures, validation, etc) without breaking the interface.

    It's really freaking handy if you want to do something like switch to lazy initialisation of variables without worrying about the impact on someone else's code directly meddling with the internal state of the classes.

  • Anonymous Coward (unregistered) in reply to Sneaky Feelings
    Sneaky Feelings:

    I've a sneaky feeling the .Net compiler converts all properties into function calls for compatibility with (potential) .Net languages that can't directly handle properties. MyProp { get; set } is made available as a property called MyProp and two functions called "getMyProp() and setMyProp()".

    That's another reason to use properties to avoid refactoring afetr introducing them.

    Thats exactly what it does. Each of those little get/set delegates is already a function. The 'get' even requires a return statement. How cute.

    If you don't want to 'promote' a field to a property at a later date and risk breaking all external assemblies which depend on that code, you should encapsulate your fields in properties.

    If the dependant assembly was written in C#, or another language supporting properties, it would just need to be recompiled. If it was written in J# or MSC++, some major refactoring would need to take place. Whoops!

  • Sane Person (unregistered) in reply to Jimmy the Geek
    Jimmy the Geek:
    Never ever ever show any raw variable from the inside of an interface. People directly accessing properties makes it difficult to change those properties later, and makes it impossible to override the properties with a new class that inherits from the old class.

    ...

    What if later you need to retrieve that property from a database instead of a integer? What if you change how you are storing the value? What if you want to override the accessor functions in a new class? What if you want to send additional messages when that field changes?

    An example of this was a string class I had to work with a few years ago. The class exposed the members of the struct outside the interface. So when I changed the way memory was allocated in the string class I had to track down everywhere that let code mess with the inside of the class and pull the data processing of that class member back inside the class.

    A properly opaque interface would have enforced the need to make sure that all the string processing that was happening was going on side the string class and not spread out in 200 places. Yes, string processing was literally being done in different 200 places, with code that was subtly different in every place.

    Hey, wait now. There's a difference between "expose variables that legitimately make up part of the external interface as public rather than use getters and setters" and "expose the internal workings of the class as public variables".

    If for some reason I was creating my own String class, legitimate parts of the external interface would include the length of the string and some way to get the individual characters in and out. Anything related to how memory is allocated and how the string is stored internally are implementation details that should be invisible to callers. So even as an advocate of the "feel free to use public fields" school, I'd think the only legitimate public field in a String class would be the length. The contents of the string should be accessed through functions because the method of storing them is an implementation detail. Any other data should be completely invisible to the outside world because it's all implementation detail.

    I think this is an example of a little rule of thumb I have: The fact that somebody used X to do something stupid does not of itself make X a bad thing. The question is not, Is it possible to hurt yourself if you abuse this tool? The question is, Is it possible to help yourself if you use this tool properly? Yes, some tools have higher potential for abuse, and so should be used carefully and avoided when better alternatives are available. But just because some idiot tried to use his electric sander to scratch his poison ivy and injured himself, doesn't mean that I believe that electric sanders should be banned.

  • Not as DULL as you (unregistered) in reply to Patrick
    Patrick:
    Because in order to make them gets/sets, you have to rewrite all the code that ever accesses that public variable to account for it. If you used gets/sets to begin with, you change the get/set and you're done.

    ^ ^

    #1 reason

    This article made me feugiat what I was going to do next.

  • (cs) in reply to Mr.'; Drop Database --
    Mr.'; Drop Database --:
    Quoted for epic win and appropriateness.
  • fresch (unregistered) in reply to Meep3d
    In PHP I generally have an array global to the class, and the get/set can only set values of that array. If an external source tries to set a value that doesn't already exist (array keys are pre-declared) it'll throw a warning. It certainly beats having a massive case statement to handle every possibility, or let the external code blindly change any value it feels like.

    If I unterstand you correctly, you do essentially this:

    class A_Color {
      private $properties;
      public function __construct() {
        $this->properties = array(
          "red" => "", "green" => "", "blue" => "" );
      }
      public setRed( $value ) { $this->properties["red"] = $value; }
      public setGreen( $value ) { $this->properties["green"] = $value; }
      public setBlue( $value ) { $this->properties["blue"] = $value; }
      public getRed() { return $this->properties["red"]; }
      public getGreen() { return $this->properties["green"]; }
      public getBlue() { return $this->properties["blue"]; }
    }
    

    How is that any better than this:

    class B_Color {
      private $red;
      private $green;
      private $blue;
      public function __construct() {}
      public setRed( $value ) { $this->red = $value; }
      public setGreen( $value ) { $this->green = $value; }
      public setBlue( $value ) { $this->blue = $value; }
      public getRed() { return $this->red; }
      public getGreen() { return $this->green; }
      public getBlue() { return $this->blue; }
    }
    

    Or perhaps you meant the new "automagic" getter and setter overloaders:

    class A_Color {
      // ...
      public function __set( $name, $value ) {
        if ( array_key_exists( $name, $this->properties ) )
          $this->properties[ $name ] = $value;
      }
      public function __get( $name ) {
        if ( array_key_exists( $name, $this->properties ) )
          return $this->properties[ $name ];
      }
      // ...
    }
    

    But once again, how is that any better than:

    class B_Color {
      // ...
      public function __set( $name, $value ) {
        if ( property_exists( $this, $name ) )
          $this->$name = $value;
      }
      public function __get( $name ) {
        if ( property_exists( $this, $name ) )
          return $this->$name;
      }
      // ...
    }
    

    If I understood correctly, and you use the variation of "A_Color", I believe you have fallen for a "Anti-Pattern".

    The obvious drawbacks of variation "A_Color":

    • documenting; There is only one property in the class, so every possible key and its value has to be documented there.
    • IDE syntax checking, auto completion, type hinting; All these are effectively disabled for any value inside that array or any key of that array, since they're just strings. Less auto completion -> more typing -> more typing errors -> more hard-to-find bugs.

    But then again, maybe I interpreted your comment entirely wrong and you meant something else ;-)

  • Matthew Watson (unregistered) in reply to Erzengel
    Erzengel:
    Jeh-fuh-fuh:
    Matthew Watson:
    Jeh-fuh-fuh:
    Matthew Watson:
    You can set a debugger breakpoint in the property setter to determine when and by what it's being set. Try doing that with a public field...
    Try learning how to use a debugger ;)

    Try learning how to use C#. You CANNOT set a memory change breakpoint when you're debugging C# code. Duh!

    That's just incorrect, but nice try. Conditional breakpoints are your friends. Among those conditions are "when changed" which most definitely can be set on a member variable. Check it out sometime.

    OK, guys, help me out here because that's a feature I really want to use. Are we talking Visual Studio? Because whenever I try to create a breakpoint, New->Data Breakpoint is grayed out, and only New->Function Breakpoint is available. So help me out here, because Google comes back with a lot of Microsoft MVPs that says "Data breakpoints are not supported by C# at this time".

    They're talking out of their arses. You can't do that with C#. If they didn't have reading comprehension problems, they would have gleaned that already from my previous comments. :)

  • Matthew Watson (unregistered) in reply to Matthew Watson

    Oh, and by "they" I mean the dicks who think they know how to use Visual Studio to set conditional breakpoints when debugging Visual C#.

  • Matthew Watson (unregistered) in reply to Matthew Watson

    And yes, I'm Mr Grumpy today. ;)

  • fresch (unregistered)

    C-C-C-COMBOBREAKER'ing your monolog ;-P

  • Andrew (unregistered) in reply to MoffDub

    And you are sure changing the type of a filed won't break any code that uses it?

    Other reason for get/set :

    • Sometimes you must use them, so the only way to make your interface consistent, is to use them always.
    • You never can be really sure, you won't have to use get/set for a filed in the future. I'm speaking from experience. Using proper interface often saves me a lot of work.
  • Shambo (unregistered) in reply to Michael
    Michael:
    It trusts people not to do stupid things...

    Never, ever do this.

  • Michael (unregistered) in reply to Code Dependent
    Code Dependent:
    Michael:
    It trusts people not to do stupid things with the public fields, or else nothing will work (surprise surprise). It's the "we're all adults here" philosophy.
    Oh, you mean like trusting people not to hack your website, and trusting emailed executables not to be viruses?
    Of course not. When it comes to security, you have to be careful. But for 99% of the classes I write, I don't have to worry about privilege escalation or sanitizing my inputs or whatever, none of which necessarily have anything to do with fields being public anyway.
  • Michael (unregistered) in reply to Shambo
    Shambo:
    Michael:
    It trusts people not to do stupid things...

    Never, ever do this.

    I guess you should never give anyone a computer then, because they might drop it off a cliff and lose their important files. There will always be trade offs between power, flexibility, etc. At some point you have to give some trust. Where to draw the line is where people vary.

  • _dew_ (unregistered) in reply to Real-modo
    Real-modo:
    So... apart from Shambo and Jason, nobody has a problem with the "jump-to-another-page inside a property-get" design?
    It's just that it's too blatant a mistake to bother discussing it. (I hope.)
  • Weps (unregistered) in reply to ralf
    ralf:
    on another note: In an oo world some people think that "Getters and Setters are Evil" (http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?page=1).

    Thought it would never come up ;)

    +1

  • (cs)

    Many comments here say that the setter allows the module to protect itself from that stupid other programmer. Let me add that the stupid other programmer is ME, two years down the road when I forgot the detailed restrictions on the field.

  • Julien (unregistered) in reply to csrster

    at last, someone pointed out TRWTF. public get and set are most of time not necessary and they break encapsulation as well.

    You should tell the object to do something and ask information about the object to do something with it.

    As a exercise left to the readers : try to right your next project without public get and set in your API (you can use protected get/set method).

  • Uhh (unregistered) in reply to Michael
    Michael:
    Many people are posting many useful things that can be done with properties. I know all that, you can do all sorts of great things with them. But suppose you have a field in an object that you need to access like a regular public field with no validation rules. It's true, maybe someday I'll want to do some fancy tricks with the field and may want it to be a property, but not today. Is there any reason to go ahead and make this field a property right now?

    Well, if other people are going to be using your code/class, then the general approach to public fields should be that once you 'publish' a field, then it might be very hard for you to change any usage afterwards.

    In effect, you should make it a public field only if you really are 99% sure that it will not change; since there could (and very often will be) some code that you don't see that uses this public field, and that this change will break.

    Although the change there will be trivial to you, it won't be trivial to them, they will only see that the compile fails, and not care - so, instead of changing their code, they'll just stick to the previous version that worked. And of course, some time later some bugs will be fixed in your version of the class, but still remain in the version that is used in their code... A WTF-scenario, but such things really do happen. So just do NOT ever make public any fields/features if you are not commited to make this as 'carved-in-stone agreed interface that will stay that way'.

    Think of stuff like windows-3.11 compatibility function calls that still somehow persist in windows Vista...

  • Joan (unregistered) in reply to Michael

    You can, and you should but you need to make sure that you have a worst case scenario covered and that you know what you're doing.

    If you are using a thirst part framework or someone else's code, the worst thing you can do is to trust it not to scr*w you over. You need to look into it to make sure it doesn't do something stupid like issue a redirect. Or that you allow people to write code that access DB code straight from the JSP. It makes thing flexible, but it makes it unmanageable.

  • Abscissa (unregistered)

    For anyone who uses getters/setters and doesn't know why:

    The reason people had been taught to use getters and setters instead of public variables is because, at the time, that was necessary to provide a stable unchanging API in case later on you wanted to change the getting/setting to do something more than just trivial member access. But with modern languages that support accessors, that practice has (for the most part) become rendered an ugly and unnecessary kludge, since you can now add extra processing while maintaining variable-access syntax (which is a far more sensible syntax for "setting" and "getting" values anyway).

    The only snag though is that this can sometimes cause problems when the value being accessed is a non-trivial value type:

    // Psuedo-code assuming a language with value-semantics
    // for structs and C#-style accessors
    struct Point { public int x; public int y; }
    class Foo {
        private Point _location = {x: 10, y: 10};
        public Point location {
            get { return _location; }
            set { _location = value; }
        }
    }
    Foo f = new Foo();
    
    // FAIL! New value is only written to a temp,
    // f's location is unchanged.
    f.location.x = 20;

    Of course, even this snag could be avoided if the language allows return-by-reference (like in D).

    The moral of the story: Question everything. Conditions change and reasoning/advice that was once valid may no longer apply.

Leave a comment on “Try Doing That with a Field”

Log In or post as a guest

Replying to comment #:

« Return to Article