Elegant Objects: Book Review

I have been reading these two books about Object Oriented Programming: Elegant Objects (Volume 1) and Elegant Objects (Volume 2), by Yegor Bugayenko. They both are great books. I really recommend you to read them. They are full of advises to make your code more maintainable (and elegant!).

In this post I will make a short review of the books, but before doing that, let’s go back in time, and let me explain how did I find these books and how I convinced myself that I had to buy them.

How did I arrived to these books?

If you have read this page you already know that I’m teaching Object Oriented Programming II (You can say that is a course about Object Oriented Design) at Universidad Nacional de Río Negro. This job keeps me busy reading papers, blog articles and books in order to give to my students better answers and illustrative code samples written in OOP (but well written, or with good style, or Elegant!).

A year ago, I was searching at amazon.com about object-oriented programming books. To be completely honest, I don’t think there are many good books about OOP. Indeed there are very few, and fewer with code samples. I have found good advises about Object Oriented Design on books that are not specific to that. For example, in the TDD book, there is a good example on how to create a Money Object. During the TDD exercise the author explains some design decisions he made. Going back to my searching on amazon.com I arrived to the Elegant Object book (Volume 1). The table of content caught my attention, specially the recommendation to not use getters and setters (which I mention to my students all the time) and also the recommendation on using checked exceptions (which I don’t like). Anyway, by that time I was not enough convinced to buy the book.

Few months later, I was trying to find new examples where the Decorator Pattern could be applied and I ended up at Yegor’s Blog, more specifically at this post. There Yegor suggest to use Decorators to apply defensive programming. I liked it, so I use it in classroom.

Some time after that, I arrive to a post called Printers Instead Getters. In this post, Yegor shows how strong his advice “don’t use getters” is. I tell to my students that it is only valid to use “getters” when you have to show a value on View. In any case, the name of the method should not be getSomthing(), just something(). But Yegor goes beyond that suggesting Printers instead, which looks elegant (and I thought that this is an example on how to take encapsulation very seriously).

I also found that Yegor suggest to read the book Object Thinking by David West. He was attracted specially by the definition of an object that David propose in his book, where objects are living organism and should be treated like a human being. I read David West’s book in 2012 and I wrote a post about that. Anyway, after that I found that Yegor interviewed David West. You can find the interview on YouTube: Yegor interviewing David West part 1, and Yegor interviewing David West part 2. Excellent talk, really!. You will learn from them. There are some funny moments, but one I really enjoy was when David expressed his love to the relational model :).

Well… too many good things. I decided to buy their books :).

My thoughts on these books

As I mention before, they are great books. It will open your mind and you will re-think some things you were doing. However, I’m not agree with everything he expose. There are few items which I have a different opinion.

Next you will see my review of these books, in two sections. The first one is about what I like it more and the second one is about the proposals that I’m not agree with. In both sections I will be talking about the two volumes as if they were just one book.

1. Items I Like it More
  • Never use -er names“. This is for class names. How many of you have named one of your classes like SomethingManager? Or Encoder?. The author explains why that is bad. His suggestion is supported by the idea of objects as living organisms. “Think of what he is, not what he does. See what his objects will encapsulate and come up with a name”.

  • Choose method names carefully“. The author divides methods in two categories: builders and manipulators (same as query and commands), proposing names for each of them. This item and the previous are simple rules, which are easy to apply to your code making it more elegant. Builders are nouns, manipulators are verbs.

  • Don’t use public constant“. I have learn something here. Very nice approach!

  • It’s all about prefixes“. This refers to getters and setters. After talking about all bad things about them, specially that treat objects as data structures, the author make a very appropriate distinction about naming methods that return something (getters in this case). It was good to see that is exactly what I say to my students. You can have methods that return data encapsulated in the object, but the name of that method should not reveal nothing about the internals of the object. There is a nice explanation about this. In addition, returning encapsulated data should be allowed only for very specific purposes, like presenting it in a View. And, if possible, return a copy of that, not a reference.

  • Algorithms“. I love this chapter. The author takes a program in Basic, then re-write it in Pascal, then in C and then in procedural Java. After that he re-write it using the Object Oriented Paradigm (in Java). Converting a clearly procedural and imperative program in an object-oriented and declarative program. I suggest that every introductory course in Object Oriented Programming should start with a demonstration like the one in this chapter. It will open student’s mind from the very beginning.

2. Items I have other opinion

Before start with the items, there are some things I would like to comment. The author does not mention anything about Smalltalk in their books. But if you check on the web, He is writing a new Object Oriented Language called eolang. He said that will be a pure Object Oriented Language (due to Smalltalk, Java, Ruby, and others have features that should not be included in a pure object-oriented language). But the guys who invented the term Object Oriented (Alan Kay and others) told us that Smalltalk is the pure object-oriented language. So? who is right?. And I don’t want to start a discussion here about if a pure object-oriented language should have static or dynamic typing… :). Eolang will have static typing. In any case, it is very valuable to contribute with these ideas implemented in a new language with only educational intentions.

There is another interesting point that the author mention that is different but somehow aligned with Smalltalk. He suggest that if statements/keywords are borrowed from procedural languages and should not be available in a pure object-oriented language (same as Smalltalk at this point). He propose that there should be a class called If, where by constructor accept a boolean expression, a then expression and an else expression. That differs from Smalltalk where Boolean is an object and ifTrue and ifFalse are methods of the Boolean class. Below is an example of how to write “if statements” in Smalltalk:

a < b
  ifTrue: [^'a is less than b']
  ifFalse: [^'a is greater than or equal to b']

a < b is an instance of either True or False class (they both inherit from the Boolean abstract class). ifTrue and ifFalse are methods defined in both classes: True and False. In the example above, the Smalltalk runtime will call both methods, ifTrue and ifFalse, but the block passed as argument (the one in square brackets) will be evaluated only in the correct instance. This means, that if a < b evaluates to an instance of True, the runtime will call ifFalse and ifTrue in the True instance. Guess what now? Yes… the implementation of ifFalse in the True class just does nothing (return nil). And the implementation of the ifTrue method in the True class, does the evaluation of the block passed as argument. Very Object Oriented right?

Which design is better? if as an object or if as a method of a Boolean class? or which one is more object-oriented?. Maybe, a comparison of these approaches generates a new post in Yegor’s blog :). Anyway, these were few things that went through my head while reading the book.

Below you will find some topics that I have a different opinion than the author. I will describe a bit what is the author intention and then I will give my point. The item list is in no particular order.

  • Code free constructor“: The author suggest to not do more than an assignment of the input parameters in the constructor. My opinion is that validation of the parameters should be done there. See an example below:

    public class Person {
       ...
       public Person(String ssn) {
          this.ssn = new SocialSecurityNumber(ssn);
       }
       ...
    }
    
    public class SocialSecurityNumber {
       ...
       public SocialSecurityNumber(String ssn) {
          if (!this.validFormat(ssn)) {
                throw new RuntimeException("The ssn should
                  have the format: AAA-GG-SSSS");
          }
          this.ssn = ssn;
       }
       ...
    }
    

    If I have a SocialSecurityNumber class and one of their constructors accepts a Social Security Number in String type, I have to validate the format. As a client of the class I prefer to receive as soon as possible that there is a mistake, and that is right after I create the instance. If this is not done there, where should we put the validation? when a method of the class use the SSN? This is not clear in the book. In any case, I think that validations should be done in the constructor.

  • Be either final or abstract“: The author suggest that a class should be abstract or final, which means that if you want your clients inherit from your classes then those must be abstract, if not, declare them final (nobody will be able to inherit from them). In my opinion, most of the time that should be the rule to guide you. There are many reason why you should favor composition over inheritance (See Effective Java by Joshua Bloch). Few times we might have scenarios where inheritance is just fine and a good fit. You just need to apply it properly. I have written this post Use Inheritance Properly with my thoughts on this. Basically, don’t use inheritance for code reuse. Use it only if there is a true subtype relationship between the subclass and the superclass. What about the Object class of languages like Java or Smalltalk? Should that class be abstract then? In these languages Object is a concrete class and we extend from it. Another discussion.

  • Throw Only Checked Exceptions“: Yegor suggest to throw always checked exceptions. His argument is that they make pretty visible to the clients that a method might fail somehow. While that is true, it also force the client to handle the exceptions, using a catch block or re-declaring it. As a developer and client of different libraries, most of the time I have a top-level piece of code that handle any exception that may occur, in my code or in library’s code. Most of the time, I don’t care what exceptions the libraries I use may throw, I’m more interesting in log them properly when they occur and make my team aware of that as soon as possible (with proper monitoring). If for some reason, I have to know what exceptions a method might throw I go to the documentation. So, force me to do something else (writing additional lines of code) just to make the compiler happy is not something I like. I prefer runtime exceptions.

    This chapter in the book continues with sections named “Only one exception type is enough” and “Don’t catch unless you have to“, which are advises that I’m totally agree with.

  • ORM“: This is the chapter that it is the most controversial for me. The author hates ORMs because he says that treats objects as data containers. Well… that is true, ORMs needs access to your private members to create instances. It force you to generate getters and setters of each attribute. He also, along the ORM chapter, refers to ORM as the mapping from table rows to objects. He says that the entire concept of mapping tables rows to object is wrong, and he simple propose that objects should just use SQL. And there should be a persistent layer in your app with persistent objects, like DbBook, which encapsulate SQL statements. He does not mention anything about concepts related with Object Oriented Databases, which are the ones that a ORM tries to simulate.

    I agree with him about that objects should never be treating as data structure, that is procedural thinking. And it is also true that most bibliography when shows you how to use ORMs, happily presents “objects” full of getters and setters. However, you can take advantage of ORMs and using it in a better way. First of all, Objects should map to table rows, and not in the other way. That is the way of thinking. If you already have a relational model, then mapping them to “objects” will just create data structures. First you do object-oriented programming, taking that the volatile memory is just persistent. After you are happy with your design, you then think how that can be persisted in a real persistent storage. In the end, that is exactly what you do if you use an Object Oriented Database. I like to think persistence as transparent as possible to my objects (domain model). And transparent persistence is a great thing that can be achieved with a good use of a ORM like Hibernate. I wrote this post and this, and this describing the concept.

    Another bad thing that the author allude is that data is injected into the object without his knowledge. The objects don’t know about that because it happen outside his control. This is a phrase that he repeat several times along their books, the objects must be in control of what happens with the state they encapsulate. He takes this rule pretty seriously. For example, solving access control using annotations and having a framework that allows or not the invocation of that method (based on the information provided in the annotation) is something wrong. He suggest to use Decorators instead.

    This rule is good, but as always there are pros and cons. In the case of a ORM, we should not forget that the persistent storage was first populated with objects that we created, using the simple and beauty object’s constructor which contains the validations according to our business rules. So, we should be fine and trust our data storage (and the framework creating instances for us). You can also declare getters and setters protected and that will be enough for your ORM. And then make a rule with your dev team that those are only for the ORM, not for other reason.

    To sum up, I think what ORMs offer to us (which is taken from OODBMS): Transparent Persistence and Persistence by Reachability, help us with maintainability more than not using it.

That was all I have for now. Now I have to clarify to my wife why I’m saying that a piece of code should be treated as a living organism… :P

Posted in Object Oriented Programming