Monday, 03. September 2007

why DAO won't die

there were some statements and blog posts about the end of the DAO pattern in the last weeks, especially in conjunction with the rising of EJB 3 and it's EntityManager. those proposals suggest to use EntityManager directly inside your business oriented services instead of encapsulating data access logic through a DAO.

i strongly disagree with this opinion. Here are some of my thoughts, why DAOs will live on:

mixing business logic with data access logic

you are tangling data access logic with business logic, especially when you have to build not only simple queries (not talking about the simple CRUD operations) but introduce i.e. more complex query building logic next to your business logik.

violation of single responsibility principle

mixing business logic and data access logic in one place gives you at least two differents reasons / causes to change.
on the one side, you may have to adapt the core business logic due to new requirements. on the other side data access logic may also change (maybe joining another table for an aggregation because of changes in the data model)

reduced readability

when you mix business logic with more complex data access logic, readability of your business services core purpose is hindered.
EntityManager provides a fixed, generic API, agnostic to your current domain context. everything within data access logic that goes beyond simple CRUD- operations has to be implemented within the service. but i only want to 'see' my core business logic in first place, not worrying about the data access logic - you should only see the WHAT, not the HOW of that data access logic. the HOW should be hidden behind a reasonable, intention revealing interface for the sake of comprehensibility.

mixing business logic and infrastructure

you are binding your business services to a special technology. i rather wouldn't mix business logic with infrastructure / technology, even if the chance is very small that technology changes, but keeping business logic free of any infrastructure (ok, this seems to be a little bit dogmatic, but binding to a special technology fixes your business logic in a very hard way, especially if you want to reuse your business logic within another technical infrastruture).

harder to test

creating mocks for EntityManager is potentially harder, since you may pass complete queries (EJB QL expressions). your mock have to inspect those query statements on a semantic level in order to behave correctly, which may be not so trivial.

lacks uniform style of representing different data sources

in a system where you have to access not only one type of data source (i.e. a relational database, an ldap database, legacy integration via message queues, ...) you'll know have different styles / levels of integration. those access logic isn't hidden behind an abstract interface any longer. but the client of those data sources shouldn't worry about the kind of data source. this should be encapsulated.
(in this case it's not the question, that it's extremely rare to replace one kind of data source with another one, but having most of times different types of data sources in parallel)

lacks uniform style of data access strategies

using EntityManager directly bounds you to the offered possibilities of its API. should you like to use JDBC in special cases or an alternative qriteria API, you'll end up with different data access technologies within your service.

violation of open closed principle

your business service is not open for extensions due to data access logic without changes, because it depends directly to the technical API. for example you can't exchange an existing data access / query building strategy (i.e. building a query string dynamically vs. using a query API) - you have to modify the business service itself, since you don't hold control of the EntityManager's implementation.

violation of dependency inversion principle

your higher level component (your business service) is directly dependend on a lower level component (EntityManager)
even if EntityManager is an interface, since you don't hold control of it's implementation (not now, not in the future), you are directly bound to it's API and it's implementation. should the interface of EntityManager change - the service has to change, too.
(if using dependency inversion principle the right way, it's not relevant if the underlying DAO interface will change, because THERE IS NO DAO interface in its own right. there is no DAO interface in its own right since the clients define there data access needs, means that there may be many DAO interfaces which belong to the different clients and not to the DAO implementation. this goes along with the interface segregation principle - see Agile Software Development by 'Uncle Bob' Robert C. Martin)

 

of course - like most design decisions - it's a matter of choosing the one or other side of a trade off. So one is right to say it depends on the context whether to use a DAO or directly include data access logic inside a business service - but you have to be clear about the consequences (which should be aligned with the projects goals which in turn should be also clear). And 'killing' the DAO comes with the mentioned ones.

Posted by mario.gleichmann at 20:37:40 | Permanent Link | Comments (17) |

Wednesday, 15. August 2007

Are you pattern happy ?

i kept this secret deep inside of me for a long time. but now i can't stand any longer and so it must come out: yes ... i admit ... i was pattern happy ;o)

it startet soon after post-graduation at my first job as a consultant for a big it company. at that time i was half-baked with little experiance with respect to the design of software systems. but that should change! i wanted to be a good designer - a master designer! and deep inside of me i was afraid. afraid of producing bad design proposals. afraid that one could blame me for poorly designed software systems. and so i grabbed for every support that could help. at that time design patterns were a very hot topic. it looked like they should be the ultimate solution to all of my problems since it seems that those patterns conserved the wisdom and experiance of all those great developers - experiance that i could'nt exhibit at that time

the journey begins

and so i startet to study the gathered knowledge of the gang of four. i browsed the web. i bought books about patterns in java - volume 1 and 2 (and if there were volume 3 i had bought it, too), a book about patterns for J2EE development, architectural patterns, patterns in smalltalk (even i didn't know anything about the language at that time) - in essence patterns patterns patterns in order to compensate my inexperiance.
i startet to speak in patterns. that sounded professional and colleagues seemed to be impressed. whenever a task was given to me, i first of all tried to apply some matching patterns in order to solve the problem - it payed off when i used those pattern stereotypes inside of my uml diagrams that we had to create for our customers. yes - i was on my way to a rocking hell of a designer ...

what? me? pattern happy?

then - some day - i was meanwhile convident that a great knowledge of patterns means to be a good designer - i found another book about patterns that i had'nt heard of so far: 'Refactoring to Patterns' by Joshua Kerievsky.
it sounded (and still is) very good. it gave some considerably advices of how to apply refactorings in order to move your design to or towards well known patterns. that hit the spot for me! but wait - Joshua also talked about refactorings that moves away from patterns. i was puzzled! how could someone move voluntarily away from a pattern? then i read about 'Patterns Happy' for the first time and about the risk to over-engineer a design. could that be possible? could one over-engineer for a given problem? gentle doubt creeped in. i started to ruminate about the goal of design patterns and it hits me like a bolt from the blue: patterns aren't the goal - patterns are at most an instrument.
but if patterns are only the instrument, what are the right goals then? i started to realize a reasonable answer as i continued to read. Joshua gave a great example where it was obvious that you may lose sight of simpler ways to solve a problem. in this example a pattern based solution was applied to a small problem that - all in all - was more complicated than it needed to be. yes, the solution was very flexible, should there be future requirements. but it wasn't adequate for the given problem now and here. instead it introduced more complexity than needed so that the code wasn't simple any more, harder to read and took longer to understand.

goals

have you noticed it? the goals? simple, comprehensible code that is easy to understand (and maintain). those are surely valuable goals! and in the majority of cases it's a question of a trade off: upfront flexibility and a potential risk of a more complex code base on the one side and smaller, simpler, mostly better understandable code on the other.
and yes - as a pattern happy designer i ignored the deliberate decision for one side of those trade offs. i blindly followed the side of flexibility. not that it is the dark side, the easy side of the power per se. but i potentially was locked for the other side - i was blind for a perhaps more appropriate solution for a given problem space. yes - i was pattern happy!

how to recognize that you are pattern happy

following are some simple signs for an indication that you may be also pattern happy:

1. you cancel private events with friends because you preferably sit alone at home in your armchair and 'invent' some 'patterns'. yes, that's true. i heard of guys that are 'searching' for new patterns that they could proudly present to the pattern community.

2. 'pattern matching' almost works even at spare time.
'oh - you mean that i'm registering myself as an observer at your bookstore and you'll fire an event and give me a callback when the book arrives?
but why's the book still so expensive? is it a singleton or do you apply a special selling strategy in my case? hm, my internal state changed to doubt - perhaps i should visit all other stores in town that will apply to customers like me and collect their prices ...' ;o)

3. you'll use the ultimate 'big pattern hammer' even for the simplest tasks.
let me explain by a simple example. remember the fizzbuzz quiz? enumerate and print all numbers starting from 1 to 100. for all numbers that are divisible by three (without remainder) print 'fizz' instead of the number. for all numbers that are divisible by five print 'buzz'. should the number be divisible by three and five, print 'fizzbuzz'

here's a simple solution in java:

public void printFizzBuzzNumbers( int start, int end ){
    boolean fizz, buzz;
    for( int i=start; i<=end; i++ ){
        if( fizz = ( i%3 == 0 ) == true ) System.out.print( "fizz" );
        if( fizz = ( i%5 == 0 ) == true ) System.out.print( "buzz" );
        if( !( fizz || buzz ) ) System.out.print( i );
        System.out.println();
    }
}

if you should have a solution like the following hinted one in mind, you may be in slight, hard pressed to explain difficulties for your next simple design job:


public void printFizzBuzzNumbers( int start, int end ){
  // of course a singleton
 
SequenceFactory factory = SequenzeFactory.getFizzBuzzNumberInstance();
  // an internal iterator
  Sequence<FizzBuzzNumber> sequence = factory.sequenceFor( start, end );
  printNumbers( sequence );
}

public
void printNumbers( Sequence sequence ){
  finally StringWriterStrategy writer = new NewLineDecoratorWriter( new ConsoleWriter() );
  sequence.each( new ItemHandler
(){
    execOn( Number number ){
     
// a FizzBuzzNumber knows when to write 'fizz' or 'buzz' or ...
     
writer.write( number.toString() );
   
}
  });
}

ok - i may be pattern happy - and now?

meet the local support group. if it doesn't exist, found one and hope for like-minded people in your region.otherwise you're in big trouble.
no - seriously now. following are some guidelines that might help to find back to the right balance:

1. choose your instruments deliberately - become clear about the context of the given problem space and the intended goals.
what are the most valuated quality criterias?
is it flexibility over all? is it extensibility or reusability in different contexts? or is it simplicity, easy readability or clarity?
what are the intented goals und directions?
avoidance of code duplication? simplifying the complicated? communication of intention?
in which context will the solution be used?
is it a part of a core module that may stay stable for a long time? or is it used within a 'disposable' solution (maybe a prototype) where the code isn't the first benefit or of short relevance?
or is your surrounding work environment really agile, that management will give enough time for continous evaluation, continous refactoring and design evolution (avoiding the YAGNI syndrome)?

2. be rather pragmatic than dogmatic
this follows directly out of point one. don't be locked for only one possible way of a solution.
Don't blindly use patterns where a simpler solution is more appropriate.

3. don't turn of your brain!
this guideline applies actually for all kinds of activities you perform. as you've heard on other prominent location - there is no silver bullet. even not in the area of designing software. you can't turn of your brain and choose a pattern by reflex or by matching the forces of a given problem space. only the given goals and valued quality criterias will give the right direction. a solution that is perfectly right in one context might be completely over-engineered and inappropriate in another situation.

think!
maybe a pattern is the right choice.
maybe a simpler solution is the better choice.

Posted by mario.gleichmann at 20:04:13 | Permanent Link | Comments (3) |

Saturday, 25. November 2006

SpringContracts - Design By Contract with seamless integration into Spring is now Open Source

it's now about one and a half year ago that i was starting to deal with the question of how to increase the semantical expressiveness of software, mainly written in java.

of course you have interfaces in java to describe a kind of 'contract' on what methods an implementor of this contract have to provide to clients. but this kind of contract is way to poor in order to describe the semantical behaviour of a component, interface or class. it is easy to implement an interface with a completely different behaviour than the intended one (for example, i could implement a pop() method of an interface 'Stack' which delivers the first element at bottom of the Stack instead the one on top and though the interface 'contract' is statisfied).

we not only need contracts on a syntactical level but contracts on a semantical level in order to provide software with higher expressivenes and thus higher reliability.

Design by Contract to the rescue

Design by Contract (DBC) is a concept that tries to solve the mentioned problem in that it let's you express so called invariants, preconditions and postconditions (for further information have a look at wikipedia). first invented by Bertram Meyer and supported in the programming language Eiffel, the idea of DBC has nowadays reached out into the community of software development.
not for nothing the longing for DBC support in java stays at no. 2 in the top 25 of RFE's (request for enhancements) at Sun's Developer Network.

with the rising of the Spring framework and with it a new major recognition of AOP, there was one half of a solution for DBC. the other half comes with the tiger release of java, in that it provided support for Annotations.

SpringContracts - Design by Contract

given this, i startet to play with the offered features and ended up with a solution i called SpringContracts.
SpringContracts is based on the mentioned technologies. you can annotate invariants, preconditions and postconditions using annotations. the conditions itself can be expressed by a pluggable specification language (at this time, SpringContracts ships with support for Expression Language (EL), OGNL and Groovy, with Extensions due to first order logic - like all quantor, exist quantor or implication).
at runtime, there is an aspect which will check and validate the semantical compliance of the expressed contracts.

But why the Spring in SpringContracts?

Spring framework is the ideal partner when it comes to configuring SpringContracts.
for example you can define on how to react on contract violations. maybe you want to fail fast (maybe not the worst idea) and throw an exception, maybe you want to content yourself with a log entry - it's up to you and a question of a simple configuration setting in Spring's ApplicationContext.
mentioned Spring's ApplicationContext - you have (should you be in need of) a whole bunch of easy to configurable options:

you could deactivate for example preconditions (usually the part of the contract, the client have to fulfill) and only check invariants and postconditions.

you could switch from EL (default) to Groovy in order to use your preferred language to specify conditions.

you could define so called named constraints and use them all over in any of your conditions.

you could define your contracts in an external source (Spring's ApplicationContext) and apply them to any of your wanted classes or interfaces without touching them / 'polluting' them with annotations.

did i get you?

as you have certainly allready noticed, i did this enumeration of features to bark your interesst in SpringContracts ;o)
you now may have an idea that a solution like SpringContracts can add value, increasing the semantic expressiveness of software.
you can annotate your classes or interfaces with invariants, preconditions and postconditions, that helps you to express the required behaviour, which will reach out beyond syntactical correctness.
this kind of specification is more than a plain documentation in that it can be validated at runtime. this said, contracts are spec n' checks.

for all of you, who would like to take a closer look at SpringContracts - you will find the project homepage hosted at http://springcontracts.sourceforge.net.

every feedback is highly appreciated and ... by the way ... i'm in search of some 'combatants' who may like to contribute ... :o)

enjoy

Posted by mario.gleichmann at 02:51:50 | Permanent Link | Comments (0) |