Thursday, April 30, 2015

Rethink OO programming: encapsulation

Encapsulation is a important feature in OO programming.  What is encapsulation?  Here is explanation in wiki.

One important feature is that encapsulation can hide some data members and function members. The The purpose of hiding is to protect object integrity so caller will not accidentally modify the object state and corrupt the object. It is not a mechanism to protect secret information. I highlight the word "accidentally".   Hiding does not prevent you from access these hidden members intentionally. In java private members can be accessed or modified by reflection.  They can be modified  or replaced through instrument. This is how many mock frameworks works.   This principle sounds good, but there are other better ways to do it.

Here are one piece of code I have in one of my project:
static Field field;
static {
try {
field = DynamicClassWriter.class.getDeclaredField("parentClass");
field.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}


Do you see the problem? The class designer never thought other developers need accessing it. This is one side effect of encapsulation: over-hide.  Many object members are hidden without any thought. It become very difficult for library user when there is time library user really needs modifying the data member.

We could do this: prefix any object member we want to hide with "__". When developer saw "__" prefix, it is like a warning "use it as your own risk". IDE can treat any member with "__" prefix as it treats private member right now.  Compiler can also give a warning if "__" members are accessed externally.  At the same time, developer can access "__" member at his own risk.  Isn't this a better approach?

If you are reading this post, add your comment. I'd like to know what you think on this topic.



Rethink exception handling

This is how I handle exception as a typical Web Developer in Java.
try {
   Extract 500000 $.
} catch (SQLException e ) {
  throw new RuntimeException(e);
}

You see the issue here. This is the way how developer work around the checked exception requirement. Every checked Exception 1) has to declared in called method and 2)caught and handled by calling statement. How on the earth can I as a developer know  to handle exception like SQLException at coding time?  

Checked Exception is good idea by design and is a "best-practice" enforced at language level. In reality it is a bad idea.  At 99% time, developer does not know what to do with the exception, but report it to end user.   So do we need to enforce a programming pattern that is only useful in those 1% situation? 

Moreover when it is time to report exception, we do not have enough information to do the report?    For example, 
try  {
 ....
} catch (java.lang.NumberFormatException e){
  throw new WebExeption("xxx is not a number");
}.

Here NumberFormatException is not a checked exception, but I'd like to catch it and produce a detailed report so that the end user know it is his fault. But I do not know what number the end user entered since the exception is thrown deeply from some third party library. 

Here is something I learn from my programming experience about exception handling.
  • There should no be  Checked Exception since developers in most case just re-throw caught exception.  
  • In most web application, exception handling is centralized. For example, JSF has ExceptionHandler,  JAX-RS has ExceptionWriter, jsp has error page, etc. The only exception handling is producing a detailed error report so end user knows what is wrong and how to seek help. 
  • When it comes to error report, context information is needed to produce the report.  It is unfortunately lost in current throw re-throw cycle.
  • Every Exception should have a domain(super.flexdms.com) and an error code(355) so central error handler can find out the error information easily by looking up some property file.  This is how RDBMS and HTTP designs their error report.
Here is an real example developer is really bothered by checked exception.
In the beginning, Hibernate threw all database-level exception as checked exception.  It was accepted as good programming pattern.  Right now the java/jpa/PersistenceException is a RuntimeException. Superfluous catch and re-throw is not needed.
Cheer!