[thelist] OOD question

Marcus Andersson marcus at bristav.se
Fri Oct 8 05:46:56 CDT 2004


The book "Design Patterns" (GoF) states that you should:
1) Program to interfaces
2) Favor object composition over class inheritance

These two statements has a couple of implications. One of them is that things might look rather complex. If 
you look on the example I written below you can see that there are a number of classes and interfaces to 
accomplish a single, simple task. The positive thing with doing like I've done here is that it actually 
gets... simpler. You focus each class on a core set of tasks. This in turn leads to that each and every class 
is simpler to handle than the big monolithic things that are quite common. Everything not related to these 
core tasks are refactored (see "Refactoring" by Martin Fowler) into another class/interface.

You then *assemble* all these little classes into your actual application.

If you've been a good boy and programmed to interfaces all the time you also get the ability to change 
implementations without impacting the users of these interfaces. You could switch a implementation from 
something that stored data in XML to use a real database instead with *no* impact on the application at all 
except from in the setup. Or you could go from an implementation that used local resources to do something to 
an implementation that act as a web service client to a remote service.

The assembling/config part of the application is best done with some sort of a Factory (see Design Patterns). 
There are actually frameworks out there today that do these things pretty damn good. There are two java 
implementations called Spring Framework and PicoContainer. I think there are ongoing efforts to port both of 
these to .Net. Then you can break out the assembling part from your application into a couple of config-files 
so you won't even have to recompile to change the dependencies of your application.

Well, these were my thoughts of the problem at hand. I hope they helped you with your thinking.

/Marcus

public class User {
   private int _id;
   private string _name;

   public int Id {
     get {return _id;}
     set {_id = value;}
   }

   public string Name {
     get {return _name;}
     set {_name = value;}
   }

   // more properties and perhaps some "real" logic to compute values
}

public interface IUserDao {
   public List FindUsers();
   public User FindUser(int id);
   public void InsertUser(User user);
   public void UpdateUser(User user);
   // etc...
}

public class UserDaoSqlImpl : SqlSupport, IUserDao {
   /* implementation of IUserDao that
      take advantage of SqlSupport (my highly fictional class
      with support to execute queries, handle connections etc..)

      You could even use delegates to implement methods such
      as eachRow(ResultSet rs) (in the support super class) etc
      to really abstract all of the connection handling, exception
      handling etc to the supporting super class

      Another implementation could take advantage of some framework like iBatis.Net
      or possibly even an OR-mapping tool such as Hibernate (or NHibernate on the .Net
      platform). This wouldn't cause any large implications on the overall application at
      all since these are mostly implementation concerns of the DAOs
   */
}

public interface IBusinessClass {
   public void ChangeNameOfUser(string name, int userId);
   // etc...
}

public class BusinessClassImpl : IBusinessClass {

   private IUserDao userDao;
   //.. more dao or other objects needed to perform the task at hand
   // the dao dependencies should not be included in the bussiness interfaces
   // since these are implementation details.

   public SomeBusinessClassUsingIUserDao(IUserDao dao) {
     userDao = dao;
   }

   public void ChangeNameOfUser(string name, int id) {
     User user = userDao.FindUser(id);
     user.Name = name;
     userDao.UpdateUser(user);
   }

   // you would probably demarcate transactions on these methods ( if transactions are
   // needed. You could possibly have even more coarse grained business facades to do that)
}

public class MainClassThatDoSetupAndTest {
   public static void Main() {
     IUserDao userDao = new UserDaoSqlImpl();
     // configure userDao with datasources etc., usually via setters
     // exposed via the SqlSupport class that the dao extended
     IBusinessClass bc = new IBusinessClassImpl(userDao);
     bc.ChangeNameOfUser("new name", 3);
   }
}


More information about the thelist mailing list