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!



Friday, May 16, 2014

consolidate Ajax Call

Suppose there is an ajax call which is issued each time when user is typing a character in a text box. If the end user types 10 characters, there will be 10 ajax call. However, only the result from last one is used by application. It is really wasteful to make the other 9 calls.

Here is one approach how you can cancel the uncessary ajax call. I am using $timeout service in angularjs. You can use standard timeout API.

$scope.ajaxcall=null;

if ($scope.ajaxcall!==null) {
 $timeout.cancel($scope.ajaxcall);
}
$scope.ajaxcall=$timeout(function() {
// my ajaxcall here
}, 300);


Here is all ajax call is queued by timeout. If the next call found an invoked call, it cancels the previous one. Of course, if the call is already made, the cancellation has no effects. If the end user types rapidly and do not care the intermediate results, you can cancel most of the unnecessary ajax call.


Dynamic Template for AngularJS

How can you use a context-dependent template?

Use ngInclude

<ng-include src="'mytemplate.html'"/>
Here the src for ngInclude is an expression. Here I use a static template file so it is a string quoted with single quote here. You can set use an expression instead of static string. The expression can be set up in parent scope/context, so the  template is dynamic.
E.G
<ng-include src="getMyTemplate(param)"/>

Use $compile in link function of directive

You can use this if you template is really dynamic and composed from various sources. You use the link function in a directive to manipulate the html.
E.g
instApp.directive("fxRelationEditor", function($compile, $templateCache){
    return {
        restrict:'E',

      link: function($scope, $element, $attrs, $templateCache){
            var topelement=angular.element($templateCache.get("template/report/relation_editor_top.html"));
            if ($scope.relationui.showselected){
                topelement.find(".selected").html($templateCache.get("template/report/relation_editor_showselected.html"));
            }
            var editorhtml=flexdms.query.originalrelationeditor;
            /
            //no report, default ui.
            if (!$scope.relationui.report){
                editorhtml=flexdms.query.originalrelationeditor
                topelement.find(".editor").html(editorhtml);
                $element.html(topelement.get(0).outerHTML);
                $compile($element.contents())($scope);
                return;
            }
            ...

}
};
});

In the example above, we create a DOM element dynamically from various sources and set it as new template.

Wednesday, April 9, 2014

Automated Arquillian Test with Managed Tomcat

I recent faces this issue. In my test code, I use JMockit for Mock and Arquillian to drive the server. In the beginning I used embedded tomcat for test. But there is one problem, Arquillian runs both Server(embedded Tomcat) and client code in the same JVM. If one class is mocked, it is mocked in both client and server. But I only want to mock at client side. I need to use Managed Tomcat for test. But  I do not want the hassle to manage the server. Moreover,  when code is downloaded by others, or tested in CI server, I want to the test to be run in an automatic fashion. To work towards this end, I automate the Tomcat download and configuration process.

First, use the maven-cargo plugin to download Tomcat automatically
    <!-- launch tomcat, deploy application before integration test -->
            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
                <version>1.4.6</version>
                <executions>
                    <!-- install tomcat
                    So it could be used by arquillion managed
                     -->
                    <execution>
                        <id>install-container</id>
                        <phase>generate-test-resources</phase>
                        <goals>
                            <goal>install</goal>
                        </goals>
                    </execution>
                     <configuration>                  

  <!-- Container configuration -->
                    <container>
                        <containerId>tomcat7x</containerId>
                        <zipUrlInstaller>
                            <url>http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.52/bin/apache-tomcat-7.0.52.zip</url>
                            <downloadDir>${project.build.directory}</downloadDir>
                              <extractDir>${project.build.directory}</extractDir>
                        </zipUrlInstaller>
                    </container>
            </plugin>


Then configure the download tomcat so that it can be managed remotely by Arquillian
<!--  copy customized tomcat configuration -->
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <executions>
                  <execution>
                    <id>copy-tomcat-config</id>
                    <!-- here the phase you need -->
                    <phase>process-test-resources</phase>
                    <goals>
                      <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                      <outputDirectory>${basedir}/target/apache-tomcat-7.0.52/apache-tomcat-7.0.52/conf</outputDirectory>
                      <resources>         
                        <resource>
                          <directory>${basedir}/src/test/resources/tomcat7x/conf</directory>
                        </resource>
                      </resources>             
                    </configuration>           
                  </execution>
                </executions>
              </plugin>

Here you prepare the configuration under /src/test/resources/tomcat7x/conf. They will be copied to installed Tomcat by this plugin.

Prepare the arquillian configuration so it knows how to communicate with managed tomcat: src/test/resources/arquillian.xml
<arquillian xmlns="http://jboss.org/schema/arquillian"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://jboss.org/schema/arquillian
        http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
      <!--
    https://docs.jboss.org/author/display/ARQ/Tomcat+7.0+-+Managed
     -->
    <container qualifier="tomcat-managed" default="true">
        <configuration>
            <property name="startupTimeoutInSeconds">20</property>
            <!-- The port to connect -->
            <property name="bindHttpPort">8888</property>
            <!--  the port to connect -->
<!--             <property name="jmxPort">8089</property> -->
            <property name="catalinaHome">target/apache-tomcat-7.0.52/apache-tomcat-7.0.52</property>
            <property name="outputToConsole">true</property>
             <property name="user">tomcat</property>
            <property name="pass">manager</property>
             <property name="host">localhost</property>
        </configuration>
    </container>
</arquillian>

The name of this configuration is tomcat-managed here.
Finally Let maven-surefire to use this arquillian configuration
    <!-- Fire unit test -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>                        <arquillian.launch>tomcat-managed</arquillian.launch>
                        <arquillian>tomcat-managed</arquillian>
                    </systemProperties>
                </configuration>
            </plugin>

Do not forget let arqillian to launch your managed tomcat for you.
<profile>
            <id>tomcat-managed</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
              <dependency>
                <groupId>org.jboss.arquillian.container</groupId>
                  <artifactId>arquillian-tomcat-managed-7</artifactId>
                  <version>1.0.0.CR6</version>
                  <scope>test</scope>
              </dependency>
            </dependencies>
        </profile>    



a PickList component for angularjs

First, what is a PickList? See a demo here: http://www.primefaces.org/showcase/ui/picklist.jsf.

The example above is a PickList in JSF. In one of my project, I need such component working in angularjs fashion. I did not find one by googling around. I decided to code one by myself.  This is first version: https://github.com/jasonzhang2022/picklist.

Here is an exmaple how to use it.
<select name="pktest" size="20"  
data-ng-options="v.name for v in toptions"  
data-picklist="" multiple data-ng-model="tselected">  
</select>
data-ng-options and data-ng-model are directives from angularjs itself. data-picklist is from this component. Once <select> is decorated with all the three attributes, you have an PickList.

Angularjs V.S JSF implementation.

Use Component
For component user, angularjs approach is super easy, just one extra attribute for select element. PickList in PrimeFace is not so easy. First, you need to understand the data model behind the component. Second you need to add some classes and codes in server to work together with the PickList.

UI customization:
Again, angular js wins. All the html is a regular html template decorated with regular angularjs directives. You can replace with your own html template easily.  I usually customize JSF component from JSF libraries. It is just really tough.

Component creation:
Super easy in angular js. All I created is 300-line file including html template. Again, It is hard in JSF. You need to create html template, javascript, renderer, etc and configure them in one component.

Test:
I do not know how you test the JSF component. I guess you can use some end-to-end test code such as selenium. This angular component itself has test code. All javascript logic is tested thoroughly.





Thursday, March 20, 2014

Sorted List to height-balanced binary search tree.

There is elegant algorithm to convert a Sorted List to height-balanced binary search tree in leetcode. It is asked in stackoverflow and various other websites.  This algorithm is elegant. Here I give a proof that it is correct.


public TreeNode sortedListToBST(int start, int end) {
  if (start > end)
   return null;
 
  // mid
  int mid = (start + end) / 2;
 
//first recursion 
 TreeNode left = sortedListToBST(start, mid - 1); 
 
//constant 1. There is one advance for each node inserted into tree. 
 TreeNode root = new TreeNode(h.val);
  h = h.next; 
//second recursion 
 TreeNode right = sortedListToBST(mid + 1, end);
 
  root.left = left;
  root.right = right;
 
  return root;
 }
 
Here we want to prove 
 sortedListToBST(start, end) will consume exactly end-start+1 nodes. 
If this is true, we can be certain that 1) sortedListToBST does not consume more nodes 
than expected.  2) the h is positioned for next sortedListToBST call.
 Give i=end-start, we need to prove f(i)=i+1
first, it is observed that 
f(0)=1
f(1)=2 
f(2)=3;
f(3)=f(0)+f(1)+1=4
f(4)=f(1)+f(1)+1=5.
So the statement is true for i when i<=4.
 
When i is even and i>=5.
mid=i/2.
First recursion is equal to f(mid-1-start)=f(i/2-1-0)=f(i/2-1);
Second recursion=f(end-(mid+1))=f(i-(i/2+1))=f(i/2-1).
So f(i)=f(i/2-1)+f(i/2-1)+1. Given that f(i/2)=i/2+1. We can conclude that 
f(i)=(i/2-1+1)+1 +(i/2-1+1)=i+1
So this statement is true when i>4 and i is even.


When i is odd, and i>=5.
f(i)=f((i-1)/2-1)+1+f(i-((i-1)/2+1))=(i-1)/2-1+1 + 1 + (i+1)/2-1+1=i+1.
So this statement is true for i is odd and i>=5.
 
 
It is proved!