Continuing a discussion that started in the DDD forum about how to display object in the UI layer, and a post from Sergio about his solution using the Builder pattern, I wanted to add a few thoughts to an already interesting issue.
First of all, I admit that the use of a Builder pattern doesn’t strike me as the best overall solution to all the view objects problems, but I liked the separation of concerns that it conveys. I would tend to keep the code away from the Façade because for me, the Façade is merely an entry point and a coordinator.
Maybe we could solve this problem as with any other domain related problem. I think we are guilty of focusing too hard on technical issues and wanting to solve the problem with a silver bullet instead of realizing that this is simply a different domain in which we, as developers, are the domain experts. Perhaps we have should try to face this issue having in mind that our existing model (Employees and Office) and our screen requirements are the data we have about this domain. In this context, each use-case (or screen) has the information necessary to help us build a model: a model composed of view objects and some sort of repositories (Sergio’s Builder?).
In several projects I was involved in it always surprised me how little one screen reuses view object code from the next (or most code except for UI components). It was like each developer coding a screen was living in complete isolation from the rest of the team. Perhaps giving the problem a more DDD approach we could start having a more supple design to this specific problem. At this stage, the use of a Builder pattern (or other pattern for that matter) could start to arise as deeper insight into our model.
Summing things up, I don’t think we will ever reach a consensus on what is the “best way” of solving this issue. Some UI domain will be better solved with a particular model subset, while other will not. Sergio’s solution is an already digested solution to his domain but it isn’t fitting Jesse’s needs any more than a generic Cargo Shipping model (like the one in the book) would fit a real cargo company software. Nevertheless I will keep Sergio’s proposal (as well as others) as Patterns and/or starting points to address my future UI domain modeling.
Sunday, July 30, 2006
Tuesday, July 11, 2006
Injecting into domain objects
As a proponent that a model should be rich and expressive I struggle in most project to avoid the anemic domain model anti-pattern. The post will use Eric Evans domain driven design terminology.
I've sometimes participate in DDD forum and the some of the most recurring question is whether using Repositories (aka DAO but from a model POV) inside Entites is a good thing. My belief is that most of the time it is a necessary thing if you want to avoid using services for everything but the simplest of operations inside your model. So if your are using an ORM and Spring (defacto web app architecture nowadays) the problem arises on how to inject the repository implementation (the DAO implementation) inside the instantiated objects hibernate or another ORM is doing the instantiation instead of Spring. I will not detail on how to do this but just point to 2 blog entries that explain this better than I do.
If you are using the newest Spring 2.0 this issue is actually addressed and is explained here and here. There are some things to note if you're using hibernate.
If you are using an older version on Spring you have other options which are discussed here
Hope it helps someone out there. I know it will help me again to have the information readily available here :)
I've sometimes participate in DDD forum and the some of the most recurring question is whether using Repositories (aka DAO but from a model POV) inside Entites is a good thing. My belief is that most of the time it is a necessary thing if you want to avoid using services for everything but the simplest of operations inside your model. So if your are using an ORM and Spring (defacto web app architecture nowadays) the problem arises on how to inject the repository implementation (the DAO implementation) inside the instantiated objects hibernate or another ORM is doing the instantiation instead of Spring. I will not detail on how to do this but just point to 2 blog entries that explain this better than I do.
If you are using the newest Spring 2.0 this issue is actually addressed and is explained here and here. There are some things to note if you're using hibernate.
If you are using an older version on Spring you have other options which are discussed here
Hope it helps someone out there. I know it will help me again to have the information readily available here :)
Wednesday, July 05, 2006
Custom data exception with Spring + hibernate
Today a colleague of mine (Poli) came asking for a way to convert error codes produced in stored procedures in an Oracle legacy database. The project was using hibernate and spring.
Out first reaction was to dig into hibernate and look for mechanisms to intercept exception but unfortunately neither hibernate interceptors or the new event system has support for a onException or onError pointcut. We quickly turned to spring and realized this was actually a better idea since spring already does it own convention of multiple exceptions into its coherent exception hierarchy.
What we ended up doing was this:
1) Create your own exception. Lets call it MyCustomException (what and original name)
2) Copy sql-error-codes.xml from Spring source to your classpath.
3) Modify the copied sql-error-codes.xml and add your own entry in the database dialect you are using (MS-SQL, Oracle, etc). We added the 20999 code to Oracle so our bean definition looked something like this:
Note the use of CustomSQLErrorCodesTranslation to set a special bean we will look at later. Later you input the errorCodes that you should trap and the exception it should throw. What puzzeles is why I need to copy the entire sql-error-codes.xml. Maybe someone can check if this actually is needed or not.
4) In you hibernate respository or DAO make:
a) If you make use of Spring hibernateTempalate and callback Spring will automatically wrap you exceptions. It will look something like this (in this case I’m not inheriting from HibernateDAOSupport from Spring that should make this could simpler)
b) If you don’t use callback you’ll have to tell Spring to do the exception convertion explicitly like:
As you can see, there is a call to convertHibernateAccessException that converts the hibernate exception to the defined Spring hierarchy.
Now you can have typed exceptions thrown from your repositories instead of nasty generic Hibernate or JDBC exceptions. Have fun!
Out first reaction was to dig into hibernate and look for mechanisms to intercept exception but unfortunately neither hibernate interceptors or the new event system has support for a onException or onError pointcut. We quickly turned to spring and realized this was actually a better idea since spring already does it own convention of multiple exceptions into its coherent exception hierarchy.
What we ended up doing was this:
1) Create your own exception. Lets call it MyCustomException (what and original name)
2) Copy sql-error-codes.xml from Spring source to your classpath.
3) Modify the copied sql-error-codes.xml and add your own entry in the database dialect you are using (MS-SQL, Oracle, etc). We added the 20999 code to Oracle so our bean definition looked something like this:
<bean id="Oracle" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="badSqlGrammarCodes"><value>900,903,904,917,936,942,17006</value></property>
<property name="dataIntegrityViolationCodes"><value>1400,1722,2291</value></property>
<property name="cannotAcquireLockCodes"><value>54</value></property>
<property name="customTranslations">
<list>
<bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
<property name="errorCodes"><value>20999</value></property>
<property name="exceptionClass"><value>MyCustom</value></property>
</bean>
</list>
</property>
</bean>
Note the use of CustomSQLErrorCodesTranslation to set a special bean we will look at later. Later you input the errorCodes that you should trap and the exception it should throw. What puzzeles is why I need to copy the entire sql-error-codes.xml. Maybe someone can check if this actually is needed or not.
4) In you hibernate respository or DAO make:
a) If you make use of Spring hibernateTempalate and callback Spring will automatically wrap you exceptions. It will look something like this (in this case I’m not inheriting from HibernateDAOSupport from Spring that should make this could simpler)
public Collection loadProductsByCategory(final String category) throws DataAccessException {
HibernateTemplate ht = new HibernateTemplate(this.sessionFactory);
return (Collection) ht.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery("from test.Product product where product.category=?");
query.setString(0, category);
return query.list();
}
});
}
b) If you don’t use callback you’ll have to tell Spring to do the exception convertion explicitly like:
public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
Session session = getSession(getSessionFactory(), false);
try {
List result = session.find("from test.Product product where product.category=?",category, Hibernate.STRING);
if (result == null) {
throw new MyException("invalid search result");
}
return result;
} catch (HibernateException ex) {
throw SessionFactoryUtils.convertHibernateAccessException(ex);
}
}
As you can see, there is a call to convertHibernateAccessException that converts the hibernate exception to the defined Spring hierarchy.
Now you can have typed exceptions thrown from your repositories instead of nasty generic Hibernate or JDBC exceptions. Have fun!
Monday, July 03, 2006
Cell phone carriers opening their gardens
It seems that we weren't so behind in South America vs. the US in matters of cell phone openness. It seems that in the US carrier also had a closed garden infrastructure like in other parts of the worlds fending off would-be startup to use their network to create new products to post content online.
A recent news has shown that at least this is changing an several 2 startups Q121 and Rabble are already taking advantage of this new scenario to create a better improve social networks using mobile phones. In an interesting analogy (similar to a previous link of mine) the article goes on saying that 'This "walled garden" concept harkens back to the closed dial-up computer networks of yesteryear, such as AOL, Compuserve, and Prodigy'
This is a great step forward for the mobile phone to become the next computing platform.
A recent news has shown that at least this is changing an several 2 startups Q121 and Rabble are already taking advantage of this new scenario to create a better improve social networks using mobile phones. In an interesting analogy (similar to a previous link of mine) the article goes on saying that 'This "walled garden" concept harkens back to the closed dial-up computer networks of yesteryear, such as AOL, Compuserve, and Prodigy'
This is a great step forward for the mobile phone to become the next computing platform.
Subscribe to:
Posts (Atom)