On Fri, October 7, 2005 3:05 am, Leon Rosenberg said: > If by persistance layers you mean things like hibernate and/or ibatis, > I would 100% agree with you.
Yep, that's what I meant :) > But if you mean that if you have a BL > POJO, say IMessagingService, which uses two DBs (at least logical) > like the user db and the db for messages, and you are acessing the DBs > direct from the BL instead of defining a IUserPersistenceService and > IMessagingPersistenceService and providing DB-based Implementations > for this, than I must say, you are too lazy, and will pay the bill one > day :-) I'm not sure I'd call it laziness, but I don't disagree with your underlying point, so I won't argue the terminology too much :) > I don't see the point. Wouldn't using a > stateless-session-bean-like-Singleton-POJO with a ConnectionPool to DB > (which it manages by itself, or is managed by a central > ConnectioXYZManagementClass, but in backend) ensure the same? It might. I should note that our connection pool is container-managed, but that probably doesn't change the equation much. I'm in no way saying that what we implemented is perfect, or that there aren't a gazillion other ways to do it. My only point was to illustrate the approach we took, which has served us well, and which I don't feel breaks the separation of layers, at least not to a degree I am uncomfortable with. :) I don't know about you, but I see *WAY TOO MUCH* overengineering in many projects. People are so anal about coming up with the absolute perfect architectural solution. I'm not saying we shouldn't strive for perfection, of course we should, but it's no wonder so many projects run over deadline and/or over budget... sometimes bending a rule here or there isn't the worst thing. The trick is knowing when bending becomes breaking to the detriment of the future, as you alluded to earlier :) The app I was describing has been in production under heavy usage for almost 3 years now, was originally not even Struts-based (it is now), has given us very little trouble along the way and has been very extensible to boot in terms of new client usage and new feature implementation. It is a big success story by any measure that matters in my mind. I don't feel bad about the decisions we made, even if they aren't 100% "best practices" :) > I'd still consider this not optimal because your actions know things > they shouldn't. And if something knows a thing it shouldn't know, your > system is more complex than it could be. Agreed? 99 times out 100, absolutely agreed. > You can't switch from the DB to FileSystem for example without > changing the Actions... Not really true, although I have admittedly never had to do it. Because the factory is responsible for the persistence essentially, the Actions actually wouldn't have to change at all. The Actions don't know from database connections, they only know to instantiate a factory and pass it along to the real execute(). To illustrate the point, here's the import list for the base Action: import com.company.app.BDFactory; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; And, the minimum set of imports an extending Action must include: import com.company.app.BDFactory; import com.company.app.ClientsBD; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; See? Only the factory is common, and the extending Action of course imports the business delegate(s) that it uses. No mention of persistence in there. You are right though if I extend this further... the BUSINESS DELEGATES know too much about persistence. That *is* a flaw in the design that I didn't recognize when they were written. Hey, live and learn :) It's not as big a problem as the Actions knowing too much, but it's still a problem. Hasn't burnt us in 3 years, but it's a mistake I haven't made in subsequent projects. > Well, Rick Reumanns site, which was unfortunately down is last time, > had a good example for that. However it's said to be common rule, that > in a well designed application each layer can only see exceptions from > previous layers. > Example: > Something in the jdbc driver throws an SQLException, like connection > is lost or whatever > The persistence layer catches it, logs it and rethrows a > PersistencePOJOs Exception, like: DB is generally unavailable or > something. > The business layer catches it and rethrows: Persistencelayer is > unavailable (all names are just examples). > This is caught by the action, which then presents it to the user > (which can be done by throwing a presentation-layer exception and > proceeding it with your general error handler) "Sorry, currently we > can't proceed your request, try again later" or whatever. > The good thing about it: > - You don't need to import classes from other layers > - You don't need to care for exceptions you don't understand > (layer-technically, someone who writes an action doesn't care whether > its an SQLException or a FileNotFoundException) > - You can change the implementation of the complete layer without > changes in other layers (like switching from JDBC to JDO or FS, or > like changing from corba to rmi or ejb). > - You still can log at any point (or at all points) and mail and > notification will work even better. That's all good, but doesn't conflict with what I've done. The only difference is that I've chosen to not transform from one exception type to another anywhere along the way, and I don't log at the "lower" levels. But, you could do what I do and still do everything you outline here. That's the nice thing about the global exception handling mechanism. > Everything in this mail is just a private opinion :-) Same here of course :) The thing I always point out is that Best Practices are so named for good reason, but they are not called "Only Practices". We can recognize the "best" way to do something, but still recognize that there are other ways that are valid as well. Sometimes people get very closed-minded and only want to talk about best practices like there is no other way to do things (not implying you fall in that category by the way Leon, just saying some people do). I personally hate that. Best practices should be guidelines, a plan that should be the starting point and the preferred solution from the start, but not to the exclusion of other ideas. :) > Leon Frank --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]