💾 Archived View for capsule.dotslashme.com › gemlog › posts › 2017-12-02-the-clever-bean.gmi captured on 2024-05-12 at 15:01:42. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-02-05)
-=-=-=-=-=-=-
published on 2017-12-02
--//# best-practices # java
Beans come in many forms in Java. Session beans, message driven beans, entity beans, etc, but this time I will write about our dear old friend, the POJO. Despite being an integral part of Java for a long time, there still seems to be a bit of confusion about what it is and what its capabilities are. For you that don't know that there's actually an official specification for these objects[1]. In this article I will introduce the clever bean, a small extension to the POJO, but an extension that adds a tremendous amount of value.
Most of my readers will recognize a POJO on first sight, it's basically a value holder object, with private access members and public member access methods and a default constructor. A typical POJO for a rectangle might look like this:
class Rectangle { private int height; private int width; public Rectangle() {} public int getHeight() { return this.height; } public void setHeight(int height) { this.height = height; } public int getWidth() { return this.width; } public void setWidth(int width) { this.width = width; } }
Of course, writing code using these type of beans soon become both boring and extremely ugly, even with override constructors that take sensible arguments, the code will soon look untidy and you soon wish there was a way to create an empty bean and update multiple properties at the same time. That's why someone invented the builder pattern.
When your classes grow in size, meaning they contain more than a few members, it can really become cumbersome to use setters to set values for all properties and long segments in your logic may become dedicated to setting new values into your beans, or you start using constructors with a lot of parameters, which of course can be problematic if some values are not availble at the moment of creating the bean, since we cannot simply skip one value.
The solution to this was the builder pattern, a pattern usually implemented in Java with a static inner build class, something which of course is ugly as hell, hard to read and last but not least may cause you to break the Java bean standard itself. I'm not even going to give you an example of such use, because in my mind it is of no use, this blog aims for simplicity, readability and responsible coding and static inner classes should be avoided when not necessary.
The clever bean is by no means an invention of mine, various forms of it has been around for ages, but it is highly useful. Let us look at the Rectangle again, but this time implemented as a clever bean.
class Rectangle { private int height; private int width; public Rectangle() {} public Rectangle withHeigh(int height) { this.height = height; return this; } public Rectangle withWidth(int width) { this.width = width; return this; } public int getHeight() { return this.height; } public void setHeight(int height) { this.height = height; } public int getWidth() { return this.width; } public void setWidth(int width) { this.width = width; } }
The difference is minimal, but crucial. I have added two methods with the prefix _with_ and these methods declare a return of an instance of the class we're in. This is of course accomplished by returning _this_, you remember that magical variable, right?
Well, first of all, you are in no way even close to breaking the Java bean specification by doing this, it still has setters and getters, a public constructor, but most important of all, it can handle input like setters, meaning data can be set at any time, but it can also set multiple members if you wish it. Let's look at some examples, starting out with the classic way:
Rectangle rectangle = new Rectangle(); rectangle.setHeight(10); rectangle.setWidth(10);
The second example uses the the clever bean to accomplish the same thing:
Rectangle rectangle = new Rectangle() .withHeight(10) .withWidth(10);
Now, in this example the difference is not fantastic, but dealing with larger beans, or with a domain model, where a bean might contain multiple other beans, will make the code far more readable and easier to debug.
© dotslashme