Follow treslines by email clicking Here!

Saturday, March 17, 2012

Making beans/data reusable and simultaneously reducing class size to only one method

Hi there! Today i wanna share an idea with you (generic bean/Data)

If there is one thing a hate is to write beans, getter and setters again, again and again. I was searching for a solution on how to make beans reusable and classes more readable, smaller and cleaner. A typical or common situation is when you need domain objects. I've caught myself constantly writting the "same  boring code" again and again. So i decided to search for a solution, which could help me saving time. I had an idea, which i would like to share with you. I've called it: "GenericBean".

IMPORTANT: After listening to the feedbacks from other developers I decided to let this post alive just to show to you, why this approach is not recommend and shall not be used. Stay with POJO's. 

Let's say we have a database table called "address". This address table may contain following attributes:
  • ID
  • FIRST_NAME
  • SECOND_NAME
  • STREET
  • HOUSE_NUMBER
  • ZIP_CODE
  • LAND
Let's say now, we need a domain class called: SimpleDomainAddress. The normal way would be to do something like this:

public class SimpleDomainAddress {
 
 private double addressId;
 private String firstName;
 private String secondName;
 private String street;
 private int houseNumber;
 private String zipCode;
 private String land;


 public double getAddressId() {
  return this.addressId;
 }

 public void setAddressId( double addressId ) {
  this.addressId = addressId;
 }

 public String getFirstName() {
  return this.firstName;
 }

 public void setFirstName( String firstName ) {
  this.firstName = firstName;
 }

 public String getSecondName() {
  return this.secondName;
 }

 public void setSecondName( String secondName ) {
  this.secondName = secondName;
 }

 public String getStreet() {
  return this.street;
 }

 public void setStreet( String street ) {

  this.street = street;
 }

 public int getHouseNumber() {
  return this.houseNumber;
 }

 public void setHouseNumber( int houseNumber ) {
  this.houseNumber = houseNumber;
 }

 public String getZipCode() {
  return this.zipCode;
 }

 public void setZipCode( String zipCode ) {
  this.zipCode = zipCode;
 }

 public String getLand() {
  return this.land;
 }

 public void setLand( String land ) {
  this.land = land;
 }
}

So this is the way everybody would do i think. Now if you have another domain object you'll do that again and so on generating a lot of unnescessary code lines in my point of view.

Let us hold on to what we do here:
  • We always define new variables
  • We always define new methods
  • We should have added "theoretically" some comments to it. 
The following UML diagram visualizes GenericBean approach:
 

Null Object
First of all we define a NULL object that could be written like this:

public class Null {
 // NullObject
}

GenericBean
Then we write the generic bean. This bean could be bigger then the example here. This is only a show case to visualize the idea behind it. I will intentionally violate some code conventions by writting variables very short and beginning with an underscore following by a number. I'll explain later why I am doing this way.

public class GenericBean<A, B, C, D, E, F, G, H, I, J> {
 private A _0;
 private B _1;
 private C _2;
 private D _3;
 private E _4;
 private F _5;
 private G _6;
 private H _7;
 private I _8;
 private J _9;

 public A get_0() {
  return this._0;
 }
 
 public void set_0( A _0 ) {
  this._0 = _0;
 }

 public B get_1() {
  return this._1;
 }

 public void set_1( B _1 ) {
  this._1 = _1;
 }

 public C get_2() {
  return this._2;
 }

 public void set_2( C _2 ) {
  this._2 = _2;
 }

 public D get_3() {
  return this._3;
 }

 public void set_3( D _3 ) {
  this._3 = _3;
 }

 public E get_4() {
  return this._4;
 }

 public void set_4( E _4 ) {
  this._4 = _4;
 }

 public F get_5() {
  return this._5;
 }

 public void set_5( F _5 ) {
  this._5 = _5;
 }

 public G get_6() {
  return this._6;
 }

 public void set_6( G _6 ) {
  this._6 = _6;
 }

 public H get_7() {
  return this._7;
 }

 public void set_7( H _7 ) {
  this._7 = _7;
 }

 public I get_8() {
  return this._8;
 }

 public void set_8( I _8 ) {
  this._8 = _8;
 }

 public J get_9() {
  return this._9;
 }

 public void set_9( J _9 ) {
  this._9 = _9;
 }
}

Shriking to only one method
Ok, at this point we have no profit of it right? Let's write know the same class SimpleDomainAddress again, but now using the GenericBean and Null Object.

public class SimpleDomainAddress {
 
 private GenericBean<Double, String, String, String, Integer, String, String, Null, Null, Null> genericBean;

 public SimpleDomainAddress() {
/** 
Database table: Id, Firstname, Secondname, Street, HouseNumber, Zipcode, Land
(The last 3 entries doesn't exit in the database, so we set our generic bean to Null)
*/
  this.genericBean = new GenericBean<Double, String, String, String, Integer, String, String, Null, Null, Null>();
 }

 /**
  * This generic bean represents the database table. 
  * See bellow how to get and set the values from it.
  * <ul>
  * <li>get_0 <b>return</b> AddressId</li>
  * <li>get_1 <b>return</b> Firstname</li>
  * <li>get_2 <b>return</b> Secondname</li>
  * <li>get_3 <b>return</b> Street</li>
  * <li>get_4 <b>return</b> HouseNumber</li>
  * <li>get_5 <b>return</b> Zipcode</li>
  * <li>get_6 <b>return</b> Land</li>
  * <li>get_7 Null (not used)</li>
  * <li>get_8 Null (not used)</li>
  * <li>get_9 Null (not used)</li>
  * </ul>
  */
 public GenericBean<Double, String, String, String, Integer, String, String, Null, Null, Null> getGenericBean() {
  return this.genericBean;
 }
}

Good side effects:
  • With this approach, the class is shrinking to less than a few lines of code.
  • A good side effect is the comment that is gaining in importance and now is no longer redundant.
  • If we notice that the database needs to be expanded, we only need to replace a NULL entry with the new value and we're done. 
  • Easy to learn (this example says all), simple, reusable.
  • We always know which entry is the first and the last in the database (get_1 & get_6 in this example)
The reason why i wrote the variables like "_0", _1" and so on is that this way, when i type "get" or "set" in my IDE, i'll get the methods in the same order(sequence) as i defined the database fields in my constructor as you can see above. This make the usage in association with the comment more intuitive and powerful.

Advertising:
Optimized bets for playing EuroMillion's lottery on your Mobile Phone! 







Please rate this blog - Press +1


14 comments:

  1. Why not just use something like Lombok?

    ReplyDelete
  2. Tombok is a great project, no doubt, but my motivations were different: "Simplicity and reusability"

    Using another plugin projects means:
    - Having more external dependencies
    - Having other license types in your projects
    - Learning something new (which is not negative, but this makes the project more complex)

    Today everything is getting easier for the client, but more complex for us programmer. My goal is keeping it simple for both. With the approach above you create a bean or data object only once and will be able to reuse it for all bean/data objects you need without introducing more complexity in your project. If you already have tombok running in your projects and all programmers are familiar with that, then i agree with you.

    Leonardo Da Vinci said once: "Simplicity is the ultimate sophistication" the described approach above is only one of many ways to Rome. ;-)

    ReplyDelete
  3. Hi,I hope it is a joke!
    In the case it is not, no offence but I can't think to a solution worse than that.
    It is not very different from using arrays (or maps) instead of objects: what is the difference between simpleDomainAddress.getGenericBean().get_1() and simpleDomainAddress[1] ?? (I hope you won't answer 'type casts' :lol)
    In a such way you loose language self-descriptiveness, the possibility to refactor, and above all you loose the readability of your code.
    Moreover what about do I need beans inside beans, like, for example, person.getContactInformation().getAddress().getCity()? bean.getGenericBean().get_1().getGenericBean().get_2().getGenericBean().get_3()??? I don't belive it is the solution.

    If you need such "simplicity" maybe you should evaluate other languages. Maybe you are searching for a dynamic language, take a look at http://groovy.codehaus.org/Groovy+Beans .

    Sorry for my bad english, I hope it's correct enough to be understood.

    ReplyDelete
  4. The goal of this approach was reusability and simplicity. Refactoring is very simple here by just changing the generic type if needed.

    The point of bean over beans is a good one if i understand you right. The example above is only a show case. For sure we should not name the variable just "genericBean", but rather addressBean or addressData or what ever is more descriptive and readable. To be more specific the example above would change to: getPersonData.get_1().getAddressData().get_2().getCityData().get_3();

    This approach is intentionally favoring reusability over 100% readability, which is given thru the comment and recompensed thru the small class sizes.

    ReplyDelete
    Replies
    1. Sorry, but I can't see so much difference between getPersonData.get_1().getAddressData().get_2().getCityData().get_3() and getGenericBean().get_1().getGenericBean().get_2().getGenericBean().get_3().

      Why are you obsessed by class size?
      Do you code on a 6" monitor or is your hard disk size under 32kb?
      In the same manner, why don't you care about the bytes of RAM wasted in unused references?

      I agree that small classes are better, but this can't be the main influence when writing code.

      Note that:
      - Readability is definitely compromised
      - getGenericBean.get_X is in most cases longer than getXXX
      - Of course, it is not simpler than call methods with their names
      - To be more precise (maybe too much :lol), it is not even "cheaper" in terms of memory usage, even though you argue that classes will be shorter, during runtime a bunch of unused references will be allocated (32 to 64 bit + 32 to 64 bit per every per every instance)

      Concerning the reusability, what would you like to reuse? the GenericBean class?
      It does not seems very convenient, taking into account all the side effects: what would happen if, at any time of your project, you need to add two properties (i.e. get_10 and get_11) to you GenericBean? You will need to go and fix every point of your code where you had (re)used the GenericBean class, adding the missing generics (<....Null,Null>).

      If you let me give you an advice, use the IDE to write the boring set and get, and abandon permanently the GenericBean (...and remove this post, it's not a good advertising for you :lol -joke- )


      * For your approach you can use Void built-in type instead of your Null type

      Delete
    2. Hi Alessio! Thanks for the comments. Your last comment at the end of this post definitely convinced me. Why remote it? We can share our experience why not to do this way and why not to do this way. The title should be changed. That's true.

      Delete
    3. I was just kidding you, can you forgive me?
      As you know italians are always joking :lol

      Delete
  5. Sorry but I'd rather go back to assembly than use that. Scratch that - I'd rather 010010010100011001011100101011011 than use that.

    Better luck next time :)

    ReplyDelete
  6. I have to agree with Alessio, I see little value in this approach and a lot of harm. I have been exposed to similar ideas, such as flattening out a domain (or worse, mish mashing several domains together) into a HashMap (or pick a collection) with a the key being a string constant for the property and the value being some object.

    If you want to talk about crappy, un-typesafe code with a lot of boilerplate, you should see that code.

    Something a little cleaner along the lines of what you are attempting is Tuples:

    http://www.javatuples.org/

    However, these too can be misused and I would not use them to replace beans, only for "temporary" holders of disparate values I need to pass around together for a short period of time.

    I don't like writing a bunch of beans either, and maybe someday Java will have Properties like C# does, but until then I will stick with POJOs. If the object is immutable and I don't need to have extra logic in the setter/getters, I just make the properties final and public and access them directly.

    As for Lombok, not sure if the cure is worse than the disease or not.

    ReplyDelete
  7. this post really made me laugh out loud... what I like the most is the 'double addressId' so that you can now have all your addresses with IDs between 0 and 1.

    ReplyDelete
  8. Please, take a look at this class:

    public class SimpleDomainAddress {
    public long addressId;
    public String firstname;
    public String lastname;
    public String streetName;
    public int streatNumber;
    public int zipCode;
    public String country;
    }

    - There is no comments, but fields name are self explanatiory. If you want to put a real comment, you can of course if the comment is more than the name of the field.
    - There is no getter/setter but you don't need them. Just read/write the fields directly.
    - You fully benefit of static typing with fields name and types.
    - There is no boilerplate excepted the public keyword.

    Why do you want to invent something complicated?

    ReplyDelete
  9. Hi every body! Thanks for the comments!

    I think thats the best way to expose and validade ideas. Thats exactly what i wanted. A lot of ideas, feedbacks and other ideas on how to solve it or find a better solution for it.

    We have now: genericData, javatuples, lombok, pojos and public accessable properties.

    Thanks to all for giving feedback pointing out (+) and (-) of tuia approach!

    ReplyDelete
  10. We are really forcing a solution here.
    Strictly OOP speaking, the only acceptable solution for writing less code is Lombok (even though I prefer Eclipse creates set and get for me).
    Javatuples, as name suggests, is tuple implementation in Java, that has nothing to do with beans (we can then argue if tuples are useful or not).
    Indeed from documentation of javatuples library you can read that a tuple is an immutable object, while beans are not.

    Public access to object properties breakes the OOP fundamental of encapsulation, you should use that very carefully and only when you are sure enough that it is the only way to go.

    Then if you simply need a place to store data, use arrays, collections, maps, etc.
    If you need a more intelligent, easy to use, self-explanatory, reusable, expandable, change-tolerant and "cheaper" structure, definitely use pojos (with or without help of Lombok, it is only something similar to a code generator).
    Notice that pojos eventually can contain validation logic, that help your data to be consistent and your code to be less error prone.
    You can't validate your data with any of other proposed solutions.

    However if you like a list of these "spicy" solutions, I can add one more: http://commons.apache.org/beanutils/api/org/apache/commons/beanutils/DynaBean.html

    ReplyDelete
  11. @Alessio: That's a really good comment! thanks! That's exactly what i thing about lombok, javatuples and public accessible beans. Thanks for sharing your know-how with us and the world. You've convinced me. ;-) Let's wait for something like "Objective-j" where we can just write @property and @syntesize ... ;-)

    ReplyDelete