wickedcoolthoughts
Wednesday, January 30, 2008
  OR Mappers for .Net, NHibernate vs LLBLGen
In one of our previous projects we had to make a choice between the OR mappers NHibernate(1.x) and LLBLGen(2.5). It was a difficult decision and we ended up discussing various aspects. The decisive factors for the choice were mostly non-technical, like familiarity with the product, the clients willingness to pay/not to pay for a product, support requirements etc. Under such circumstances we may have to make a choice that we may not be quite happy with, as developers.

However a little time on the design and practices can help us to overcome some of the limitations. I would like to look at the differences/similarities and explain how some obvious design practices can solve some limitations.

1.What is?

NHibernate: OR Mapper. Works on plain objects.
NHibernate helps you to persist your domain objects.

LLBLGen: OR Mapper + Code generator.
Works on generated(from a database schema) entity classes.
LLBLGen helps you to deal with the data access tier.

2. Support: You know it :-). Its between free and paid software.

3. Documentation: There is quite a bit of documentation available for both LLBLGen and NHibenate. Also the source code is available for both.

4. Supported Databases: Both NHibernate and LLBLGen works for all major databases.

5. Mapping of objects to databases: NHibernate uses HBM(xml) files for database mappings while LLBLGen generates code using a visual OR mapping tool. While NHibernate XML mappings are not easily refactored the LLBLGens binary project file which makes it quite difficult to control the versions. This could be a serious limitation with big teams.


6. Database First or Domain Objetcs first: Its a matter of taste.

One argument is that, with LLBLGen typically the database is created first and the entity classes are generated. After any changes to the database the entity classes need to be generated again. Since the refactoring and IDE supports for the SQL is not as good as programming languages creating the database first may slow you down a bit.

Reallistically this problem(if at all) can be solved to some extent by creating a domain layer above the data acess layer and play around with your domain objects first and later think of the persistence.

7. Design style: In couple of projects using LLBLGen I have seen the entity classes are being passed between the client and server(across different layers). Using the entity classes as a replacement for your domain objects has some limitations.

The LLBLGen entity classes introduces coupling to the data access code and also has limitations to work with some frameworks (if I remember it correctly .. the LLBLGen documentation talks about this somewhere. eg: WCF support).

The interface of the generated classes is a little polluted to use them as domain objects.

This has nothing to do with LLBLGen, but is all result of using the data access entities as domain objects.

8.Productivity: If we use the LLBLGen generated entity classes to replace the domain objects we may save some time and effort. What percentage of the total effort? Does it provide enough value for you? ..need to consider these questions before we make a decision.

If we go with a domain layer over the entity classes there is not much productivity gain. Or am I missing something here???

Disclaimer: The above is based on some preliminary evaluation of the products.

I would like to hear from someone who has used both of these products seriously.
 
Thursday, January 17, 2008
  Classification of objects
Think no software for this post!

1. I have a collection of objects of different classes, some rectangles, some circles, some hexagons and few points. All of the above objects can be drawn and draw is the core/distinguishing behaviour of all the objects above. How can I classify the above objects/classes further? Is it possible to come up with a single common class that can represent all the objects? If so, is that class good enough to convey a concept without ambiquity?


2. I have another collection of objects lets say some humans, some robots and some cars. Lets say all the humans party on the weekends ;-), the robots assemble cars and the cars can be driven. Assume that these are core behaviour of the respective classes. Given the requirements above can I classify the objects further? With the above mentioned core/distinguishing behaviours of the objects further meaningful classification is not possible.


3. Now let us say there is a radar which needs to track all moving objects.

From problem 2 (above) the humans, robots and cars are all objects which can move and we were not interested in the move behaviour until the tracking requirement was introduced. Now we can say humans, robots and cars has ability to move and we are interested in this behaviour.

The objects which were otherwise unrelated is now related because of the new behaviour move. And move here is not the distinguishing behaviour of any of the objects/classes.


OK, now we can group objects/classes based on their distinguishing behaviours or some other common behaviour. When objects/classes are classified based on their distinguishing behaviour the resulting class is widely accepted and is applicable whereever the objects are used.

Eg: Rectangle is a kind of Shape and holds good always.

However in the grouping based on a non-distinguishing behaviour the resulting group does not define a class will not be applicable always.

Eg: Robot is a kind of Movable (even if we say so) was not applicable till the tracking requirement was introduced.

So what is the distinguishing behaviour of the objects? Its up to YOU to decide as needed by the domain.

The design of the above in a programming languge is a personal preference and I prefer to maintain the conceptual integrity in the design. Some considerations are covered in the post Abstract Class vs Interface.

 
Monday, January 14, 2008
  Abstract class vs interface continued...
Hope to clarify some questions/confusions on my previous post on Abstract class Vs Interface. Here I am trying to look at the conceptual difference only.


"Of course an interface defines a type": Interesting thought. I would appreciate examples to have a better understanding of the statement.

If interface here refers to the java interface (Walkable as in my previous post), the behaviour walk specified by the interface is not sufficient to define a class/type of objects referred by the Walkable interface.

If interface is used to refer the messages you can send to an object, I would say the type defines the interface.

When modeling a problem say BankAccount,

we do not start from deposit(...) , withdraw(...) interfaces to define the type BankAccount. We would rather start from the BankAccount.

However when we do classification of objects we do start from the interfaces of the objects to create a class/type.

"just wanted to know if we cannot say "walk" as a behavior/type?":

Perfect to say, walk is a behaviour. However not sufficient to define a class/type of objects referred by the Walkable interface as mentioned above.
 
Thursday, January 10, 2008
  Again Abstract class vs Interface...
While pairing with a fellow thoughtworker (http://thoughtworker.in) we ended up discussing Abstract class vs Interface and he found this explanation useful.

A Class (abstract or not) defines a type while an interface does not.

In my domain anything that can be drawn is a shape(including a point) and thus behaviour defines a type.

abstract class Shape
{
public abstract draw();
}

In another domain which includes a Robots, Humans and Pets,
If I need to treat all objects that can walk similarly, I would like to have an abstract handle to of all the above and that ends up in a

interface Walkable{

void walk();

}

...Robot implements Walkable{...}
...Human implements Walkable{...}
...Pet implements Walkable{...}

and merely something that can walk does not define a type here. Its a mechanism to tie together otherwise unrelated types Robot, Human and Pet.
 
  Test your unit tests + 1 anna
There is no new idea here, however my priliminary search in google did not bring up something similar to what I want to write about.

This is just another observation I had with unit tests (applicable to others as well). When the tests were run in the build all of them passed always. However when I ran a single test there were some unexpected failures.

A close look into the tests revealed that the tests, the faling test had a dependency on some other test runs. Yes they are bad tests and tests are not supposed to be written that way. But they still exist!

Again how can we find them early?

Shuffle the test order. Write a RandomTestRunner Decorator?

BTW we were discussing the Decorator pattern (hammer) today and everythings seems like a nail ;)
 
Wednesday, January 9, 2008
  Test your Unit Tests?
When I was working on a project in the past I stopped the webserver and database before running the unit tests. To my surprise I found 40+ unit tests started failing. As you would guess the tests did not use the proper test doubles (mocks/stubs..).

The next interesting finding was some tests started failing when they were run repeatedly (the same test multiple times in a single build).

Both of the above problems are not typical in a fresh development project with people having the right experience with testing/TDD. However these problems could emerge when your team has

- less experience in testing or
- you are working on a legacy codebase which is not testable.

With the legacy codebase, refactoring the codebase is an option to make it testable. However you need tests to refactor with confidence. Its a cyclic dependency problem. So the idea should be to add tests as early as possible. Such tests may be often added at a higher level and may not be proper unit tests. Such tests should be refactored later as the refactoring of the legacy codebase progresses. Due to various reasons some of such tests remain unattended and remain in the codebase. Most of the times the reason why they continue to be in the system is because we do not know that they needs to be addressed.

So what can we do about it?

1.Automate your build scripts to shutdown all the integrating systems, as a part of your build script, before you run the unit tests. Stop the webserver, database server, disable network connections etc..

2.Automate the build script to repeat the tests (the same test multiple times in a single build) occassionally (may be with the nightly build). We can use a decorated TestRunner for this.

So we have added two parameters of the unit test quality to our build
the 'unitness' and 'repeatability'.
 
Friday, January 4, 2008
  Design Patterns : Explosion of strategies
"What could too many strategies in your application mean?", was an interesting question while we were discussing the Strategy pattern in ThoughtWorks(Bangalore) patterns study group.

The thoughts around this was there is a possibility to combine the strategies to higher level entities and behaviours.

Lets look at the example of Bank account and the evolution of the BankAccount object.


class BankAccount {

public Money withdraw(Money amount){

if(account_locked)
throw new AccountLockedException();

else if(transaction_limit_exceeded)
throw new AccountLockedException();

else {
//more logic
balance.subtract(amount);
//more logic
return amount;
}


}

}



Looking at the if-else structure the instant answer for this issue was a Strategy pattern. OK Now we have


abstract class WithdrawalStrategy {

abstract Money withdraw(Money money);

public static final ACCOUNT_LOCKED_WITHDRAWAL = new WithdrawalStrategy(){.......};
public static final LIMIT_EXCEEDED_WITHDRAWAL = new WithdrawalStrategy (){......};
public static final LIMIT_EXCEEDED_WITHDRAWAL = new WithdrawalStrategy (){......};

}



class BankAccount {

public BankAccount(){

this.withdrawalStrategy = .....;
}

public Money withdraw(Money amount){

return withdrawalStrategy.withdraw(amount);
}


}



Soon we we added a deposit operation to the BankAccount object. Again we ended up having strategies. Now we have


abstract class WithdrawalStrategy {

abstract Money withdraw(Money money);

public static final ACCOUNT_LOCKED_WITHDRAWAL = new WithdrawalStrategy(){.......};
public static final LIMIT_EXCEEDED_WITHDRAWAL = new WithdrawalStrategy (){......};
public static final EVERYTHING_OK_WITHDRAWAL = new WithdrawalStrategy (){......};

}

abstract class DepositStrategy {

abstract Money deposit(Money money);

public static final ACCOUNT_LOCKED_DEPOSIT = new DepositStrategy(){.......};
public static final LIMIT_EXCEEDED_DEPOSIT = new DepositStrategy (){......};
public static final EVERYTHING_OK_DEPOSIT = new DepositStrategy (){......};

}



class BankAccount {

public BankAccount(){
...........
this.withdrawalStrategy = .....;
this.depositStrategy = .....;
}

public Money withdraw(Money amount){

return withdrawalStrategy.withdraw(amount);
}

public Money deposit(Money amount){

return depositStrategy.deposit(amount);
}


}



Here both deposit and withdrwal strategies are decided by ACCOUNT_LOCKED,LIMIT_EXCEEDED or EVERYTHING_OK state. So lets try to unify deposit and withdraw.


abstract class WithdrawalStrategy_Plus_DepositStrategy {

abstract Money withdraw(Money money);
abstract Money deposit(Money money);

public static final ACCOUNT_LOCKED = new WithdrawalStrategy_Plus_DepositStrategy(){.......};
public static final LIMIT_EXCEEDED = new WithdrawalStrategy_Plus_DepositStrategy (){......};
public static final EVERYTHING = new WithdrawalStrategy_Plus_DepositStrategy (){......};


}




Here WithdrawalStrategy_Plus_DepositStrategy can be renamed as
AccountState
.



abstract class AccountState {

abstract Money withdraw(Money money);
abstract Money deposit(Money money);

public static final ACCOUNT_LOCKED = new AccountState(){.......};
public static final LIMIT_EXCEEDED = new AccountState (){......};
public static final EVERYTHING_OK = new AccountState (){......};


}




The idea here is to explain how the problem of explosion of strategies can be solved by unifying the strategies. ( No I never intend to discuss State vs Strategy here ;))
 

My Photo
Name:
Location: India

I am passionate about making Better Software Solutions,that helps businesses to stay agile, by applying Agile,Lean and Systems Thinking principles. Also I grow coffee,spices and in general has big interest in pesticide free food!

Archives
December 2007 / January 2008 / February 2008 / March 2008 / June 2011 /


Powered by Blogger

Subscribe to
Posts [Atom]