Gavin pointed out that he did not get
the separation between business logic and UI.
Which leads to the question of why are we layering in the first place?
I have heard many many bad reasons to justify layering. Actually, this is one of my favorite questions when I give a training. It's always fun to see the people sweating over a justification.
What are the problems layering is trying to solve:
- separation of concerns
- easier maintainability
- loose coupling
- reusability
- justifying yet another additional level of management in the organization
So what could be the problems of such static horizontal layers:
- the distinction between them could be fuzzy and lead to endless hair splitting discussions at the cafeteria
- they naturally force state conversion and state transfer across layers for the sake of isolation. State conversion and state transfer are hard to solve, slow and lead to duplication and maintainability nightmares: where did my loose coupling go?
- they have no real purpose half the time but to please the God of Architecture, tens of thousands of empty and meaningless classes are written to fill up layers implementing delegation patterns over delegation patterns.
Horizontal (hence static) layering in the standard sense of it (presentation, service, component, dao) is a notion inherited of the dark days where:
- the component model was bloated and unusable
- stateless applications were the golden goal because
it scales better
We need a way to define dynamic reusable concerns, interactions between them, avoid unnecessary state copy and duplication, and find more natural boundaries between concerns. A component model could achieve that if it were shared by the presentation, the business and the data access layer technology with no blind butcher axed boundaries.
Now, bare with me a second and imagine that you had at your disposal a lightweight component model, where components could depend on each other in a strongly and decoupled way, where components could interact with each other by sending events, where components could hold state and whose lifecycle would be handled automatically.
A component would describe and implement a business need
@Component
public class Checkout {
It would depend on other business components
@Component @Asynchronous @PayByCheque
public class ChequePaymentProcessor implements PaymentProcessor {
describing the dependency and its requirements with natural adjectives in a loosed coupled and type safe way
@In @Asynchronous @PayByCheque PaymentProcessor
It could have declarative behavior
@Transactional @Component
public class Checkout { ... }
It could notify other business components
@In @Notifier @New Event<Order> order;
And other components could listen to those events in a decoupled way
@Component
public class AuditAgent {
public void onOrder(@Observes @New Order order) { ... }
}
Oh, and finally it would be concise (check the previous examples :) )
Of course some components could be more technical than business oriented, some could be more DAO-ish others more Service-ish. But the point is that this component model and the declarative loose coupled type safe way to describe interactions with other components is very flexible and adjusts to your needs. It fits your needs, you have to fit in it.
So what do we have?
- separation of concern: loose coopling and declarative interations and behaviors
- easier maintainability: type safety and no state transfer
- loose coupling: interface / implementation runtime and type safe binding
- reusability: a component represents a use case, a story of your application
- justifying yet another additional level of management in the organization: if you really insist, we can find a way
Seam has paved the way of components describing a story shared across all the technologies in my system and Web Beans will bring it the elegant type safe declarative touch of Guice.
Hmmmm, it's not quite what I meant :-)
I don't mean to say that I don't believe in separating code that deals with defining screens and processing pageflow from re-usable business logic that defines the entities of the business domain and their interactions.
All I meant to say was that the /boundary/ is blurry, and that there's nothing /a priori/ wrong with the use of simple expressions involving model object attributes in a view.
OTOH, I share your views about over-layered architecture, of course.
Our business domain objects run under both J2SE and JEE runtimes. The J2SE applications include both headless batch applications and servlet web UI's.
Would Web Beans require us to use two separate frameworks to get all the magic - dependency injection, eventing, transaction support, etc? What about Seam?
I erased a comment from Ivan by mistake
The fact that a component model is based on POJOs is not enough per se to be a better alternative to the traditional layered model. Remember that a component is comprised of a class (POJO in our case), but is not just a class. What makes a component interesting is its interaction with the outside world :)
The short answer is no. You will be able to run in SE and EE (Seam can today, that's how we unit test :) ). Gavin will probably be able to elaborate more on the Web Beans side.
Web Beans no. Seam no in theory, but yes in practice as of today, but that's something we should fix (very easy fix actually).
Do you have anything to say about vertical layering as well? About separating parts of an web application with different operational requirements which you may not want to depend on each other? Do you have any medicine? :-)
I am really looking forward towards this WebBeans thingy. Though I very often see to my dislikings that it is the future you are working on and not tomorrow morning.
Patience young Jedi
It depends what you mean by different operational requirements and why they have been put in place (usually for organizational / political reasons). But generally speaking, a proper component model (including dependency, events and so on) is a much more flexible solution than horizontal layers or vertical layers: instead of having an inflexible grid, you have a flexible graph with well defined dependencies and no empty box.
Yes in a sense it's the future, but Seam already gives you a good taste and it's the present :)
Greetings.
I don't completely agree with the determination that layering is that useless. The solution that component-based frameworks like Seam provide is enough in a perfect world - meaning your team is either small enough, your developers are smart enough or your project is small enough. I am an architect in a small development team for a growing project in which at any given time about half of the developers are new, and so are unable to make good design decisions. I found that whenever there is a hole in my design, it can cause trouble in that developers are not clear about the boundaries between their classes or modules, such as two developers writing the same functionality in different layers or that both of them don't write it at all because they expect the other layer to do it. Also, our project will be composed of a large number of similar modules, so when we have a defined layering from the beginning the design of the following modules becomes very simple.
One more thing - layering is a very helpful when implementing AOP, for example we can decide that only the service layer is transactional, only the web layer provides security, etc. Again I agree that Seam handles these cases very nicely, but assuming that layering is useless just because a specific framework makes AOP easier means strongly coupling your application to the framework, and that is a bad thing in my opinion.