Question

Background

I m reading the "Clean Code book", and, in paralel, I m working on calisthenic objects Kata like the banker account, and I m stuck on that rule :

The 9th rule of calisthenic objects is that we don't use getter or setters.

It seems pretty fun, and I agree with this principle. Moreover, at page 98-99 of Clean Code, the author explains that getters / setters break abstraction, and that we don't have to ask our object, but we have to tell our object.

This makes perfect sense in my mind, and I fully agree with this principle. The problem comes in practice.

Context

For example, I m having an application in which I have to list some users, and to display the user details.

My user is composed of :

-> Name
   --> Firstname --> String
   --> Lastname --> String
-> PostalAddress
   --> Street --> String
   --> PostalCode --> String

Problem

How can I do, or what can I do to avoid getters when I only need to display a simple information (and I have to confirm that I don't need extra operation on that particular field) to display the Firstname value in a simple (random) output support ?

What comes up in my mind

One solution is to make :

user.getName().getFirstName().getStringValue()

Which is totatally terrible, breaking many rules of calisthenic objects, and breaking the Demeter Law.

Another one would be something like :

String firstName = user.provideFirstnameForOutput();
// That would have called in the user object =>
String firstName = name.provideFirstnameForOutput();
// That would have called in the name object =>
String firstName = firstname.provideFirstnameForOutput();

But I don't feel comfortable with this solution, that only seem to be a "higher order accessor" like bypassing standard getter/setter with a method that only aims to match Demeter law...

Any idea ?

Was it helpful?

Solution

The common misconception about the idea of avoiding getters and setters is to avoid them everywhere, which is impossible when you come to the surface of your architecture interacting with the user.

You should avoid using getters and setters in the business-logic part of your application, where objects should be protected using aggregates providing context, and methods should act as commands.

To avoid getters and setters you could design a solution similar to reactive programming, implementing reporting system through observable entities, but this extremely complicates architecture and makes no sense in CRUD level of your application, even though the design is really good for user interfaces.

Whether you should consider using getters/setters depends entirely on the part of application you are currently working at. If your concern is user interface using getters is completely fine, for business-logic, where you would run a part of a code based on a value retrieved through a getter, not so much (this screams that the logic should have been actually encapsulated within the class you are calling the getter on).

Also, law of demeter is not about counting dots, but merely about tearing apart a context-providing class by using getters on the class to obtain its components to which you shouldn't have access on its own.

If you feel like your user interface is going too deep within your business models, you can think about introducing view models to your system being responsible for transforming specific parts of models to visual representations.

OTHER TIPS

One direction to think would be to provide a generic string formatting member function, rather than providing access to the raw data. Something like this:

String lastName = user.formatDescription("$(Lastname)");
String fullName = user.formatDescription("$(Lastname), $(Firstname)");
String abbreviated = user.formatDescription("$(FnAbb). $(LnAbb).");

You see, with this approach, you are not restricted to just providing the full data as it is, you can provide means to transform the data in convenient, meaningful ways. For instance, you might need to play tricks with character case:

String accountName = user.formatDescription("$(firstname).$(lastname)");

You could also define some commonly used, possibly complex formats once, so you could say, for instance

String fullAddress = user.formatDescription(User.kAddressFormat);

The beauty of this approach is, that it keeps the individual strings internal to the User class, while actually providing significantly more functionality to the calling code. However, the downside is, that you need to implement the templating mechanism within formatDescription() which will be a few lines of code.

As such, this might be complete overkill: Never forget that programming principles are only guidelines. And whenever following another principle is in violation of the KISS principle, it's likely best to just do it the simple way. So, unless you have at least some need for such a formatting member, I wouldn't bother implementing it for the sake of simplicity, using the accessor based approach.

Licensed under: CC-BY-SA with attribution
scroll top