Fog Creek Software
g
Discussion Board




Accessor Debate

Please state the # years OO experience and your preference:

(options in C# for shortage of lines)
#1:
public class Debate
{
public string HitMe;
};

#2
class Debate
{
private string hitMe;
public string HitMe { get/set }
};

#3 - Start w/ #1, add #2 "as needed"

#4 - Your thoughts?

Thanks!

Steve
Tuesday, April 6, 2004

been doing oo quite a few years now.

In Delphi, I use #1 which becomes 'properties' when I need get and/or set logic (and no recompile necessary).

In C++, I use #2 from the beginning because it is a hassle to migrate from #1 to #2.

i like i
Tuesday, April 6, 2004

Roughly 10 years of OO experience.

I prefer the getter/setter pattern, unless the language has the ability to treat member variable access the same way it treats method calls.  In other words, if the language has the ability to do something like this:

def class MyClass:
  public int foo;

def class MySubClass(MyClass):
  public int getFoo();
  public void setFoo(int ...);

o1 = new MyClass();
o1.foo = 4;
print o1.foo;

o2 = new MySubClass();
o2.foo = 4;
print o2.foo;

I think Python lets you do this sort of thing.

The reasoning behind this is that clients of the object shouldn't need to know how "foo" is implemented, and it also allows subclasses to derive a value instead of returning a stored value.

joev
Tuesday, April 6, 2004

did I say recompile?  I meant find/replace in the users obviously.

i like i
Tuesday, April 6, 2004

OO: since -95. Delphi.

Short answer, I've done both. Its really a matter of what you need. When writing components in Delphi, you have to do the get/set-method. The properties gets read/written using member methods.

Its sometimes more straight forward to declare variables public and change them directly from the code. If Im sure there is only one thread that call the instance of the class I usually go with public member variables.

When doing threaded tcp/ip programming, I usually tend to wrap the per thread socket data in simple data container objects, like this:

TSocketBuff = class(TObject)
  public
  DataFromSocket : String;
end;

and then create one TSocketBuff object per incoming socket.

When having a multithreaded application call a single instance of an object, you obviously need to to the set/get memeber methods, to be able to serialize calls from different threads.

TGlobalStuff = class(TObject)
  private
    LockedBy : THandle;
    ImportantGlobalStuff : String;
  public
    function Aquire(Caller: THandle) : boolean;
    function UpdateGlobalStuff(NewStuff:String) : boolean;
    function ReadGlobalStuff : String;
    procedure Release;
End;

Hope it made sense :)

Patrik
Tuesday, April 6, 2004

I've been doing OO long enough to be too opinionated to be taken seriously.

I'm a strong believer in less code = better code. A property with a getter and setter that do nothing except give full access to a member variable is fluff. Fluff is bad. Ditch the fluff.

Code that doesn't solve a real problem is one of the biggest threats to my sanity. This particular example is not a big deal, but if you had 20 of these properties on a class, you'd suddenly have a large amount of fluff for the next guy to read and wonder about.

Like I said...

Big B
Tuesday, April 6, 2004

As a Java programmer (5+ years), i've learned the hardway that #2 is worth the extra typing...

Some day you're going to have to change how hitMe relates to your program.  (Your customer will demand that whenever they type "i'm a moron" they really mean "you're a moron") You'll be able to modify your setter method instead of having to run through every line of code looking for Debate.hitMe.

Brian
Tuesday, April 6, 2004

Good point Brian...

...
Tuesday, April 6, 2004

To expand upon what Brian said, in .NET while a public Field and a public getter/setter pair may seem the same (and arguably perhaps they should be the same -- i.e. a basic public field could expose the basic getter/setter pair. Too bad there isn't a macro possible for this when a pair is nothing but the basic return/set logic), they are not, and it is a breaking change to switch from a field to a property (i.e. you class library will break previously compiled apps that use it if they expect to interact with a field and you've switched to a property, or vice verse).

As such, if it's even remotely possibly that you may need some interception logic, then make it a property.

As an aside, you can see the difference between the interactions with a field and/or property using ildasm.

Dennis Forbes
Tuesday, April 6, 2004

As an aisde, it's usually a good practice to have your class materializing interfaces for the public facade. Interfaces allow properties, but not fields.

Dennis Forbes
Tuesday, April 6, 2004

Ask and yee shall receive (sometimes)

http://www.reflectionit.nl/Macro.aspx

GiorgioG
Tuesday, April 6, 2004

Thank you for the macro -- I will use that. Having said that, I was thinking more along the lines of a pre-compiler macro or language keyword to keep the source code as small as possible, but to expose simple fields as properties (to avoid the repetitious get { return myVal } set { myVal = value } type of blocks).

i.e.

  property public int myVal;

Which would automatically compile to the virtual get/set methods.

Dennis Forbes
Tuesday, April 6, 2004


11 years OO.

I always use #2 for mostly the same reasons given above. When you need to change from #1 to #2 it can be a major mess.

-- insert lame bathroom joke here--

Using a combination of #1 and #2 together just makes things more complicated. You'll have to keep track of when you use obj.getX() and when you just say obj.X (or whatever the preferred syntax is).

Also:
"This particular example is not a big deal, but if you had 20 of these properties on a class, you'd suddenly have a large amount of fluff for the next guy to read and wonder about."

In this case I'd prefer 20 getters. If I change the internal representation of a property I just modify the fluff to maintain the same interface to that class. User code  accessing variables directly creates a lot more to wonder about.

NathanJ
Tuesday, April 6, 2004

Hollub explains better than I could why they are bad: "http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html"

The point that Hollub mentions that Brian misses, is that using accessors often exposes your underlying implementation code in the same way as public fields, thus buying you  nothing while increasing the complexity of the code. 

Using getters and settors for properties is often symptomatic of bad design because the designers only consider the static nature of the class model  and not the *dynamic* nature, which is where all the work is being done.

Crimson
Tuesday, April 6, 2004

Well, Crimson, Hollub's point isn't that accessors are bad, per se. It's that classes that have a lot of properties that are visible are bad (regardless of the mechanism used to access them, directly or through accessor methods). So I don't think that it's really relevant to the original question.

But if, for whatever reason, one decides that visible properties are required, then I would agree with the posters above saying to use accessors because they let you change the implementation without requiring a change to the interface.

And most decent IDEs these days will generate the accessor methods for you and will tuck them away at the end of the class so you don't every really notice them.

Bill Tomlinson
Tuesday, April 6, 2004

>Well, Crimson, Hollub's point isn't that accessors are bad,
>per se. It's that classes that have a lot of properties that
>are visible are bad (regardless of the mechanism used to
>access them, directly or through accessor methods). So I
>don't think that it's really relevant to the original question.

There are some classes where you need lots of getters/setters/(properties).
One example is class for a protocol header for some communication protocol, (yes, and i don't wont this to be a struct).

Public data members are not quite good, because you don't have a means of checking how they are used, where they are used. With get/set functions you can change the way how they are implemented.

Michael Moser
Tuesday, April 6, 2004

10 years OO experience: I'm currently prototyping my first C# assemblies, and using "#3 - Start w/ #1, add #2 'as needed'".

Sometimes I change my mind about what data is stored in each class, in which case having public data instead of properties means less retyping (no pun intended).

I like there being, in C#, no syntactic difference between data and a property: so that client code only needs to be recompiled, not editted, when you go from #1 to #2.

Christopher Wells
Tuesday, April 6, 2004

over 7 years experience with C++ and I prefer to do away with exposed properties as much as possible.

 
Tuesday, April 6, 2004

Crimson, here is a quote from another Hollub article:

"... an object's instance variables (member fields that aren't constants), should always be private. Period. No exceptions. Ever. I mean it... You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public (though access functions that return full-blown objects rather than a basic-type value are reasonable in situations where the returned object's class is a key abstraction in the design). "

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

For this question I think Hollub would say none of the above or else go with #2.

In any case, I think eliminating public accessors is a worthy goal, but I've never worked on any large project where it was done that way.

I'm also confused by Hollub's example of a "drawYourself()" method. I can see how it would help eliminate getters, but the idea of a drawYourself() method just makes me shudder. To me this shackles the business object to the UI. I don't understand how you would be able to reuse the same business object in multiple UI windows if your BO has a drawYourself() method.

NathanJ
Tuesday, April 6, 2004

> In any case, I think eliminating public accessors is a worthy goal

It is a goal, in the sense that people who have just started to use C++ after a lifetime of C may be inclined to expose too much internal data.

But I think that eliminating them entirely is nonsense: for example, imagine two class named Device and DeviceSettings. You have as many Device instances as you have hardware device on the machine, and you have any number of DeviceSettings stored in a configuration file. Client applications instantiate DeviceSettings instances, and edit them using the DeviceSettings accessors. And, the Device.setup(DeviceSettings) method also needs to read (access) the DeviceSettings data.

Christopher Wells
Tuesday, April 6, 2004

You have to take Allen Holub's world with a grain ... or a *bucket* of salt.  In his mind, every object is a part of the UI.

NoName
Tuesday, April 6, 2004

Given that the original question is posed with a C# implementation, I'd use #2 _always_ simply because C# treats properties as "special" entities  (i.e. _not_ just public fields).  You'll see how much of first-class-citizen properties are in C# when you touch alot of the class library.  I think the C# designers built properties this way so it was not just syntatic sugar to be debated about in on-line forums :-)

  On the philosophical side, my approach would be 1) does it need to be exposed at all? 2) if so, use a C# proeprty, does it need more than the "get" side? 3) only if necessary implement the "set" side.

  I wish Java would adopt C#-style property syntax and treatment in the reflection package.

$.02 more in the kiddy...

Russ
Tuesday, April 6, 2004

"You have to take Allen Holub's world with a grain ... or a *bucket* of salt. "

Indeed. If accessors expose too much information about the implementation class, then the corollary is that methods expose too much information about the class. The natural conclusion of this ridiculous line of thought is that the perfect "object oriented" class exposes no properties, fields, or methods, and therefore its implementation can be changed entirely without impact....

How many nonsensical blatherings have been proposed with an introduction of "...but that goes against object oriented methodologies...". Object oriented seems to be a phrase that people adopt and twist to their own pet idiosyncracies.

Dennis Forbes
Tuesday, April 6, 2004

I've been doing OO languages for ~12 years, but have only really drunk the OO kool-aid in the past 2 or 3 years.

Normally I would choose #2, because of flexibility (can add validity checks to methods, can move data to another class or a database, etc. without having to change the calling code).

On occasion, I want a "struct" to pass around, even though my current language of choice is Java.  In these cases I create a class with all public fields.

While I have mixed the two approaches, I think that is a bad idea because it results in inconsistancy in the use of the class which makes the resulting code harder to read.

madking
Tuesday, April 6, 2004

Eiffel seems to have solved this problem.

With Uniform access an attribute can easily be changed to an accessor without affecting the clients.

http://docs.eiffel.com/general/guided_tour/language/tutorial-07.html

I've read about Eiffel, but I haven't really used it.  It looks great on paper, is there any reason why this doesn't work as stated?

Or could all of this debate have been avoided with some decent langauge design?

Ged Byrne
Wednesday, April 7, 2004

Yeap, some languages let you change your mind later.

In C++, you have braces to denote functions.  In Object Pascal and C# (never played with it, but built by Mr Object Pascal himself) you have properties.  This makes all the code that accesses that 'variable' not look different regardless of whether it is a member variable or computed.  It even lets you put read/write constraints onto it.  Neat, no changes to all those Debate.hitMe calls scattered in the code.  (And refactoring tools just are common nor clever enough to help us here just yet..)

So can anyone flex their templating and operator overloading to give the equiv for C++?  I have to admit I shrink from the task!

i like i
Wednesday, April 7, 2004

And a relevant point from Martin Fowler re C#:

http://martinfowler.com/bliki/PublicCsharpFields.html

"When I first came across C# I liked the notion of properties right from the start. The getX and setX conventions of C++/Java always seems rather silly to me, it's much more natural to write obj.X = other.X. Providing a property with get and set methods turns a common convention into a naturally supported feature of the language.

Another thing about it I liked is that, from a language point of view, properties and fields look the same. So if I have a field x which I can just read and write to, I can just declare it as a field. I don't worry about this violating encapsulation, because should I wish to do something more fancy I can just replace it with a property later. It all saves a lot of typing of stupid accessor functions.

Alas, all is not so simple. Fields and properties do have the same access in terms of program text, but they are represented differently by reflection. As a result various tools that use reflection will be broken if you switch between fields and properties."

So unless you're sure you will never be using reflection to access properties, better to do #2 from the start, IMO.

Dave Hallett
Wednesday, April 7, 2004

~15y OO.

I am a lazy bastard. Although I am thouroughly convinced of the advantages of properties, and I started using them when I started C#, I still go for a public field in those quick 2 hour hacks.
I know, guilty as charged. Yes, I'm probably the sort of scum you guys believe should never be allowed near a compiler.
But tell me, if you were all alone on a business trip in a far away land where no one knows you and you are never likely to ever return to, with your fingers all stiff and dying for a quick hack in VS 2003, would you not be tempted to just skip the extra typing and go "public string ..."?

Just me (Sir to you)
Wednesday, April 7, 2004

say 5 year + of oo

Does the fact that in java (public) fields are shadowed by inheritence and getters overridden come into it?

See the somewhat dated
Thimbleby A critique of Java - the ducks lame ducks example.

Comments?

Karel
Wednesday, April 7, 2004

OO experience: ~2 years.

For anything complex, I'd go with getters/setters.

In my codebase, different subclasses of a class often implement the getters differently, sometimes to add intelligence, sometimes to save space/time.

e.g. DBElabPort::getDirection() const { return dir; }
DBTracedPort::getDirection() const { return genitor->getDirection(); }

The difference?  I don't want a direction field in the TracedPort.  Instead, for various properties, I query the genitor.  Both classes are subclasses of DBPort.

In other cases, I do on-the-fly transforms.  e.g. a name in a language can represent a data object, a type, or a chunk of code.  "integer" is a type name, represented initially by a data object.  If the getHdlType() method is called, then I will look up the type representation and cache it.

All of this is possible only if you have the foresight to implement getters/setters in your classes up front.

Of course, for classes that have one purpose only, it makes sense to frob the variables directly.  Experience will guide you.

David Jones
Wednesday, April 7, 2004

"So unless you're sure you will never be using reflection to access properties, better to do #2 from the start, IMO."

Reflection has been mentioned several times, but it gets even more rudimentary than that (although I suppose one could say that the project got the information from reflection of the class) -- If you have a class library with a class, say class A, and you have a public field in it, and you then add a reference from a Windows forms application, App B, and you use class A, interacting with a public field, and you then release the Windows application, you have "compiled in" the fact that class A is exposing a field, not a property: The accessor from a IL perspective is totally different.

You then realize that you should have made the public field a property (perhaps you want to put some range checking, or make it a computed value) so you go in and rewrite it and deploy the updated dll and you release that to go with the legacy Windows app -- App B will fail the moment it tries to access the field (which is now a property).

In other words you don't need to be explicitly using reflection programmatically for this to seriously impact your project. While properties and fields look similar, they are totally different under the hood.

Dennis Forbes
Wednesday, April 7, 2004

*  Recent Topics

*  Fog Creek Home