- Unclear design;
- Poor re-usability (loads of copy and paste);
- Non-cohesive classes and methods;
- Business logic all over the place;
- Difficult to test;
- Difficult to measure the impact of changes and improvements;
- And people's favourite, actions (if using Struts-like web frameworks) with hundreds, if not thousands of lines.
Often called n-tier architecture, the multi-tier architecture is a logical way to separate the different responsibilities of your application. The most common multi-tier architecture is the three-tier architecture, which will be the one that I'll be focusing on.
The tree-tier architecture is divided in the following tiers:
- Presentation tier: It is responsible to interact with the user, displaying information and providing ways where the user can input data and perform actions.
- Application tier: It is responsible for the coordination of the application, its business logic, decisions, calculations and evaluations. It executes commands, actions and moves data between the presentation and data tiers. It is also known as business tier, logic tier or middle tier.
- Data tier: It is responsible to retrieve and store data. Data can be stored in a database, xml, file system or even other system. It is also known as persistence tier.
Each tier must be as independent as possible from each other, where a good practice would be to provide interfaces as "facades" to each tier. Organising your classes according to these logical tiers would make the code more cohesive, loosely coupled, easier to understand and easier to test. This approach would also help to improve greatly the re-usability and would make changes to be more localised, minimising the impact on the rest of the code.
A multi-tier architecture would be for applications that access other systems (RPCs, webservices, etc), access multiple sources of data, or uses any sort of middleware.
MVC and Java MVC frameworks.
I will assume that people reading this post already know MVC so I'll give just a brief and generic description of how MVC and its variations like Model 1 and Model 2 work. If you need more information about it, please refer to the links at the end of this post.
The general behaviour of the MVC pattern is:
- User performs an action on the view (screen, page). This action can be anything like clicking a button, clicking a link, selecting an item from a drop down list, etc. Data may be submitted, in case of a form.
- Controller receives the request or event and invokes the model.
- Model will perform some business logic, persist or fetch some data.
- Model return the result of this operation to the controller. This result may include some data.
- Controller, according to the result from the model, invokes the next view. The next view can be the same one that originated the request or a different one.
- View is rendered. The view may display any data returned from the model.
Fitting MVC into a Three-tier Architecture
In a traditional java web application, View and Controller will belong to the Presentation tier and Model will belong to the application and data tiers.
So far so good, but when using Java Web frameworks like Struts, Spring MVC, JSF, etc, the catch is to be able to identify what is controller and what is model.
Understanding the role of the "action" classes.
Struts was one of the first and one of the most used Java MVC frameworks. When it was released, back in 2000 (version 1.0 in 2001), many developers did not get the whole MVC Model 2 thing and very quickly started misusing the framework and sacrificing some important architectural patterns. The situation got worse when other frameworks also based on Model 2 were released, since the same bad old habits from Struts were used to develop applications with frameworks like WebWork, Spring MVC, etc.
In Struts, when some action is performed on the page, an "action" class is invoked. This action class is probably the source of the whole problem. What exactly is this action class? I mean, what's the purpose of this class and where does it belong, taking into consideration the MVC pattern and the three-tier application?
Since the View is done by the JSPs, the Controller is done by the servlet (that is configured on the web.xml), many would answer that this class is the model. This would explain why we find so many actions with thousands of lines and full of business logic.
However, the action class DOES NOT belong to the Model.
All requests are handled by the same servlet (Front Controller design pattern), and then the respective action is called (Command design pattern). The result of this action will be the view to be displayed. So, in summary, what is the responsibility of this action class? The action is triggered by the view, does some thing and decides which view will be displayed next. This is exactly what a MVC Controller does, meaning that action classes are also part of the Controller, working almost as an extension or helpers for the main servlet.
When Spring MVC came out, one of the first things that I noticed was that they called the equivalent Struts Action class, "Controller". That's right. In Spring MVC, you create controllers instead of actions, what makes much more sense. However, even naming the classes as controllers, some developers kept adding business logic to them.
In summary, the action class must just invoke the model (could be a service, session bean, business object, etc.), get the result, set it into a context (session, request, etc) and invoke the view. Action classes should be small, clean and without any business logic, as a Controller class should be.
Component-centric frameworks and its "backing bean" classes
In component-centric frameworks like JSF, Tapestry, Wicket and alike, the pages (generally XHTML) have components that are bound to Java classes (known as backing beans in JSF). These components can be input texts, drop down lists, tables, etc, or even the entire page. Basically each component on the page can be bound to a Java class, that would behave like a model and sometimes controller for these components.The backing beans are responsible to hold the state of the components and also handle events, validation, conversions, trigger business logic, update/refresh other components, fire events, listen to events, etc.
Now that we know that Struts Actions and Spring Controllers belong to the Controller part of the MVC, where do the backing bean classes (JSF like) belong to?
When we talk about component-centric web frameworks and also add AJAX into the mix, the line between controller and model becomes a little bit blurred.
The backing bean may handle navigation and in this case, it would act as a controller. When acting as model for its view component, although it is a model, it is a model for that specific view component. That means, the logic that this backing bean should perform would be related to rendering the view component or invoking other view components (events, re-render, etc) and not exactly application business logic, keeping this managed bean coherent. Any application business logic like making calculations, fetching or storing data, make a web service call, etc, should be delegated to a business class belonging to the application tier.
So in the case of a component-centric framework, managed beans would belong to the presentation tier, even being models for view components.
NOTE: All classes related to the java web frameworks like validators, converters, forms, etc, also belong to the Presentation tier.
When developing applications it is important to keep your code cohesive and loosely coupled. The first step is to make a quick analyses and define the logical tiers. In case of a web application with database access, it will not differ too much from a three-tier architecture. If integrating with other systems or accessing multiple data sources, application and data tiers may be broken down into more tiers.
When using Java web frameworks, regardless if they are page-centric (Struts like) or component-centric (JSF like), chances are that everything related to the framework (forms, converters, validators, actions, controllers, managed beans, etc) will belong to the presentation tier and should not have business logic. Business logic and data access should be delegated from the presentation tier to the application tier. This would allow us to keep our managed beans and actions (controllers) very small and clean.
In case of too much view logic (enabling/disabling components, populating tables and drop down lists, validations, etc), use helper classes for the actions and managed beans (see View Helper design pattern)
For the model, application and data tier, they will be covered in future posts since they can vary a lot from application to application.