6

I've recently been reading about Object Calisthenics and I'm stuck on Rule 9.

My typical approach to code (I'm a C# .NET developer) is to model data as POCO classes which only exist to represent data schemas. Inevitably this means a set of properties exposed with getters and setters. These classes implement few, or more often no, methods. They are dumb objects and typically exist at a low level in my solution architecture. They have a singular responsibility: to model structured data e.g. a database table row.

Where I need logical functions, I'll introduce these as dedicated service classes in a business (or service) layer. These classes also observe the single-responsibility principle by each addressing a specific business requirement. For example, I may have a Customer class, and a CustomerRepository class charged with reading and writing to a persistent data store. This CustomerRepository will implement an IRepository contract to ensure I can inject it as a dependency, mock it in tests etc.

With this pattern, inevitably my Customer must expose its properties via getters and setters ("ejecting its own guts straight in your face"!) so that the repository can map it to a database table or whatever.

So my question is, why would a devotee of object calisthenics see this as so wrong? In all the examples I've seen, the authors keep properties private and introduce logical functions directly to the class which in my view breaks single responsibility, and could potentially lead to vast, unwieldy, untestable classes.

So, is Rule 9 really workable in real life? In one of the few detailed explanations I've found the author appears to argue against himself by defining an Account class, making the Balance private then introducing methods like Withdraw to encapsulate not just the property but any logic that works with that property. Fine, but what if the business requirement needs the programmer to write the account balance to a UI? How can Rule 9 be observed in that case?

  • 11
    Honestly, these "Object Calisthenics" rules seem pretty dumb if not dangerous. They build on sensible ideas, but turns them into hard rules without context, which in many cases will make code worse rather than better. I say forget you ever read about those rules, you will be happier in the long run. Read some quality texts instead. – JacquesB Oct 02 '17 at 17:38
  • 3
    @JacquesB Exactly. +1 Many of his principals are good, or rather have good reasoning behind them, but *highly contextual*. They cannot be applied nearly as universally as he implies. – TheCatWhisperer Oct 02 '17 at 17:40
  • 1
    see [Discuss this ${blog}](https://softwareengineering.meta.stackexchange.com/a/6418/31260) – gnat Oct 02 '17 at 17:42
  • 1
    @BenAaronson 's answer to this question is very good, prbly the best explanation I've seen. https://softwareengineering.stackexchange.com/questions/284215/how-do-you-avoid-getters-and-setters – TheCatWhisperer Oct 02 '17 at 19:20
  • Maybe this is better explained by [Jeff Bay](https://www.cs.helsinki.fi/u/luontola/tdd-2009/ext/ObjectCalisthenics.pdf). – Stop harming Monica Oct 02 '17 at 19:51
  • 5
    This post says that "Object Calisthenics are programming exercises". It sounds like these rules aren't *intended* to be used "in real life"; they're intended as something that you do on the side, in order to learn something. If you try writing a side project where you follow these rules 100%, it'll teach you about how these rules can be beneficial, as well as how these rules can be harmful. (A [rotation quaternion](https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation) should be implemented as a class with four fields; breaking that into multiple classes is thoroughly pointless.) – Tanner Swett Oct 02 '17 at 21:43
  • These rules are simply another form of cargo cult design. Ignore them. Just about any self-declared "principles" for general programming fall into this category. – Frank Hileman Oct 02 '17 at 22:24
  • I hope you take those rules with a huge grain of salt. While a couple of them are valid, and the explanation of a couple more is worth reading, there are some rules that will lead to very hard to maintain code when you get beyond "hello, world". – Bryan Oakley Oct 02 '17 at 22:57
  • The rules should probably be renamed, "Recipe for Ravioli Code". – Frank Hileman Oct 04 '17 at 23:28

2 Answers2

6

His #9 principal is incorrect. Objects need getters and setters to be used in most real life applications. However, they should be used as little as possible.

Displaying the properties of an objects to an end user will need getters.

Allowing an end user to edit an objects properties will need setters.

A persistence layer will need getters and setters to save the object to disk and read it again.

A builder will need setters.

A better rule would be:

Other logical entities within the domain layer should not use another entity's getters and setters if it can be practically avoided

Now, there are some work-arounds to avoid using getters and setters in the above exceptions, but they are overly complex for most situations.


Your approach to object design has its own problems, and is the other extreme. You are basically doing functional programming in an OO language without proper functional facilities. However, that is a topic for another discussion.


Please see Ben's answer, it is great: How do you avoid getters and setters?

Greg Bair
  • 345
  • 3
  • 10
TheCatWhisperer
  • 5,231
  • 1
  • 22
  • 41
  • 2
    Thank you. Good to know my cynicism was warranted. I know my approach isn't ideal; my skills are pretty rusty which is my main motivation for researching these more modern trends. – Tom Troughton Oct 02 '17 at 18:40
  • @TomTroughton As was said in comments, please ignore that article. It is not that it is *wrong*, just that it is not expressed properly or with enough context to be useful. – TheCatWhisperer Oct 02 '17 at 18:47
  • 1
    @TomTroughton check this out, this is a better explanation. The article you mentioned is taking a lot of previous knowledge and expressing it in a way that makes it seem wrong :D https://martinfowler.com/bliki/GetterEradicator.html – TheCatWhisperer Oct 02 '17 at 18:51
  • On the whole I see value in most of those rules. As a set of principles aimed at keeping code clean and easy to read, they have some value. But some more then others. And Rule 9, to me, is daft! – Tom Troughton Oct 02 '17 at 18:55
  • @TomTroughton #1 and #7 while both good rules of thumb, contradict each other. They are good principals but do not deserve to be presented as rules as he has presented them. #2 run directly contrary to other established rules, such as only one point of return, or certain safety procedures; I have heard of cases in which there must *always* be an else. I can't even use "else" to throw an exception if my method has received an input it does not know how to deal with? – TheCatWhisperer Oct 02 '17 at 19:03
  • @TomTroughton you can make almost any rule look good if you only present examples that it is a good fit for. At one point I believed applications should not have business layers because I had been working on crud only apps for a year XD http://thedailywtf.com/articles/The-Mythical-Business-Layer – TheCatWhisperer Oct 02 '17 at 19:05
  • A lot depends on the type of object. If it is to be displayed in a property grid and edited in a designer, for example in Visual Studio, the properties are the way developers and semi-developers configure the object. On the other hand, if it is an object that represents a function, properties could be no more than a convenience to avoid many arguments to a method. – Frank Hileman Oct 02 '17 at 22:20
  • 3
    I disagree with your assertion that this is "incorrect". The purpose of this exercise is to experience how the design changes if you impose a particular set of restrictions. Obviously, restricting your design to use no setters *will* change the design, so the rule works as intended, no? – Jörg W Mittag Oct 02 '17 at 22:21
3

From the link you provided:

In this case, you could keep the getScore() as you may want to display it somewhere on the UI, but keep in mind that setters should not be allowed.

So, in your example where the account balance would be shown on a UI, the getBalance() would be appropriate to keep.

Given your current model of writing POCO classes, you may not be able to reconcile the two. You may need to modify your design a bit to accommodate the lack of setters. Or, just realize what the spirit of Rule 9 is, and that is to prevent any object from wrecking your object. Given that your class only exists to map info from the DB, this seems to be a marginal concern.

mmathis
  • 5,398
  • 23
  • 33