Convert Dynamic to Static Construction


Refactoring contributed by Gerard M. Davison


You have code that loads other classes dynamically. This can introduce a un-waranted overhead and can produce code that is more fragile.


Replace the dynamic class loading with static code.


   try
   {
      DataProvider dp = (DataProvider)
         Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();
   }
   catch (IllegalAccessException iae)
   {
      // Convert exception to error to preseve the interface.
      //
      
      throw new IllegalAccessError(iae.getMessage());
   }
   catch (InstantiationException ie)
   {
      // Convert exception to error to preseve the interface.
      //
      
      throw new InstantiationError(ie.getMessage());      
   }
   catch (ClassNotFoundException cnfe)
   {
      // Convert exception to error to preseve the interface.
      //

      throw new NoClassDefFoundError(cnfe.getMessage());
   }



   import org.davison.data.jdbc.JDBCProvider;

   .
   .
   .
  
   DataProvider dp = new JDBCProvider();



Motivation


In some cases code is written with dynamic dependencies between parts of the code by utilising Java ability to load and instantiate arbitrary classes. If not properly managed, this can cause run-time errors. This design can impart a performance penalty because of the extra levels of indirection. It can also prevent the compiler from detecting certian types of error.

Mechanics


- Identify the places where the different classes are instantiated. If there is more than one place, you might like to make use of code consolidation refactorings to create one entry point.
- You can remove the code that instantiates the classes using java.lang.reflect. We will instead call the constructors directly.
Replace the code that selects the name of the class with simpler code that simply returns a new instance.
- Add in import statements as required for the classes being constructed.
- You are now ready to compile and test the code. Make sure that any dependant code is also tested properly.
- The refactoring is complete.

Example


Start with this code:

   try
   {
      DataProvider dp = (DataProvider)
         Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();
   }
   catch (IllegalAccessException iae)
   {
      // Convert exception to error to preseve the interface.
      //
      
      throw new IllegalAccessError(iae.getMessage());
   }
   catch (InstantiationException ie)
   {
      // Convert exception to error to preseve the interface.
      //
      
      throw new InstantiationError(ie.getMessage());      
   }
   catch (ClassNotFoundException cnfe)
   {
      // Convert exception to error to preseve the interface.
      //

      throw new NoClassDefFoundError(cnfe.getMessage());
   }



We can remove the error handling code and simply instantiate the class.



   DataProvider dp = new JDBCProvider();
  


The final step is to add in the correct import statement


   import org.davison.data.jdbc.JDBCProvider;

   .
   .
   .
  
   DataProvider dp = new JDBCProvider();
  


Compile and test at this point as we have code that is complete.

When this is finished and all dependent classes are re-tested, the refactoring is complete.

Another way of creating compile time dependencies is to use class literals. This would still have the overhead of dynamic instantiation. I would not recommend this unless you have good reason; but here is the code converted to use this method.




   try
   {
      DataProvider dp = (DataProvider)
         org.davison.data.jdbc.JDBCProvider.class.newInstance();
   }
   catch (IllegalAccessException iae)
   {
      // Convert exception to error to preseve the interface.
      //
      
      throw new IllegalAccessError(iae.getMessage());
   }
   catch (InstantiationException ie)
   {
      // Convert exception to error to preseve the interface.
      //
      
      throw new InstantiationError(ie.getMessage());      
   }
   catch (ClassNotFoundException cnfe)
   {
      // Convert exception to error to preseve the interface.
      //

      throw new NoClassDefFoundError(cnfe.getMessage());
   }





***** 아름다운프로님에 의해서 게시물 복사 + 카테고리변경되었습니다 (2003-12-18 17:27)
Posted by 아름프로
BLOG main image

카테고리

분류 전체보기 (539)
이야기방 (19)
토론/정보/사설 (16)
IBM Rational (9)
U-IT (0)
SOA/WS/ebXML (110)
개발방법론/모델링 (122)
J2SE (34)
J2EE (60)
DataBase (39)
Open Projects (30)
BP/표준화 (50)
Apache Projects (15)
Web/보안/OS (22)
Tools (7)
AJAX/WEB2.0 (1)
Linux/Unix (1)
영어 (0)
비공개방 (0)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

달력

«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30

글 보관함

Total :
Today : Yesterday :