Channels ▼
RSS

Parallel

Saying No To Properties


The final test-related issue is something called The Law of Demeter, "Talk only to your friends." This means that your code should use only those objects that it can see directly: local variables, fields, and method arguments. Code like this:

dog.getBody().getTail().wag(); 

is considered bad form because it requires dependencies on too many interfaces to get work done. Translating that code into properties:

dog.tail.body.wag(); 

just obscures the problem.

In the test-driven-development (TDD) world, this sort of chain is called a train wreck. A program that follows The Law of Demeter would restate the chain like this:

dog.expressHappiness(); 

You'd leave it up to the dog to figure out how to tell you it's happy.

This sort of structure is particularly important in TDD because it lets you bring your mocking architecture under control. If you follow The Law of Demeter, the object that you're testing is always three layered:

  1. The outer layer (objects that you are passed).
  2. The object under test.
  3. The inner layer (objects that you create).

When you build the mocks, you may need to mock classes in layers 1 and 3, but that's it. In the train-wreck example, you'd have to mock every car in the train, which can be a very difficult and time-consuming process.

Mock Roles, Not Objects [PDF] is a great formal paper on this subject. In fact, I'd strongly recommend spending some time perusing http://static.mockobjects.com/. There's a lot of good information there.

Getting Rid of Getters/Setters

So, how to you eliminate the get/sets? The main key is rethinking the approach to objects. An object should be defined by what it does, not by what it contains. In fact, you shouldn't know what the object contains.

The first step, then, is to stop thinking of an object as a sort of fancy data structure that contains fields and methods that manipulate those fields. Instead, think of an object as something that does work. Money isn't a value and a currency. Rather, it's an abstract object that supports certain operations, such as addition. A dog's job is to express happiness. The way that it does it (by wagging its tail) is unimportant.

These work-centric objects will, of course, have to contain fields in order to do their work, but the outer world shouldn't care about that. The objects that have the information do the work, and if they can't do the work, they delegate to another object by calling one if its methods.

Some information has to pass between objects, of course, but a push (that is, an argument to the target object's method) is usually considered better than a pull (a get method on another object).

This approach is at the core of OO design and is too big a subject for a single article, but I have illustrated the basic concept. When you follow good design principles, the get/set methods (or the equivalent properties) tend to wither away. They don't creep into the code to begin with because getting something is rarely a bit of work that's worth modeling. Instead, you simply ask the object that has the information to do the work for you. Ken Arnold put it as "ask for help, not for information." The formal term for this sort of organization id delegation.

Conclusion

So, to put things succinctly. Properties are rarely necessary, and in the worst case, they make your classes hard to extend and hard to debug. They make client code much larger and more complex than it needs to be. That's not to say that there's never a valid application for properties, but they should be used judiciously, knowing what the downside is. The way that you go about eliminating the use of properties is by following well-established design practices, looking at your objects as black boxes that do work, not as data structures. I hope that's not stunning.


Allen Holub is a speaker, lecturer, and writer on software development. His recent books have discussed Java, multithreading, and the use of patterns. He is a frequent contributor to Dr. Dobb's.

More Articles by Allen Holub

Fixing the enum in C#

Testing OO Systems, Part 1

Testing OO Systems, Part 2

Type-Safe File-Based Configuration


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video