Saturday, 7 February 2015

In defense of the 3-tier architecture

Lately, there's been a lot of buzz about Domain Driven Design, Rich Domain Models and the Onion Architecture. While this approach certainly has its merits, it often comes with a negative attitude towards the other, older alternative: the 3-tier architecture with an Lean Domain Model. In this article, I will explain why the old approach is not that bad at all and can be the preferred architecture in a lot of situations.

The good old 3-tier architecture consists out of the following components:

  • The frontend: The first tier. It does not matter what sub-architecture you use here, MVC or something else. That's beyond the scope of this article. All that matters is that the frontend talks to the service layer.

  • The service-layer: The second tier. It contains the business logic and talks to the DAO-layer.

  • The DAO-layer: The third tier. It connects to the database to store and retrieve data. This layer could also contain connectors to external systems, such as email or external webservices.

  • The domain entities: The domain entities contain all the data and are used throughout the three layers. Each entity often corresponds to a table in the database. The entities do not contain any logic, just data.
Let's compare this to the Onion architecture, which has no less than four layers (sometimes five, depending on who you ask), with numerous categories within each layer. I've created a comparison diagram between the two below (click for a larger version). Please note that the Onion architecture as depicted below is just one of many interpretations of the Domain Driven Design (DDD) approach, more complex versions exist!


If I look at the Onion architecture in this image, one word comes to mind: complexity. It is beyond the scope of this article to explain how the Onion architecture works, whole books have been written about it. In my opinion however, it is not a good thing if your developers have to read books before they can get started. The 3-tier architecture however, is clean, simple and understandable and has many other benefits compared to the Onion Architecture:

  • The 3-tier architecture is not truly object oriented, because in an object oriented design, each object contains both state and behaviour. Instead, the 3-tier architecture is more procedural: Upon user interaction, procedures run on data without holding any state. This is however, exactly what most applications need, since the vast majority of web applications is procedural in nature!

    The state is held in the database and when the user clicks a button, the necessary data is retrieved, changed, stored and the resulting page shown to the user. The application itself holds no state whatsoever. Compare this to a real-time strategy game, with buildings, tanks, soldiers, etc. Such an application lends itself very well for object oriented design, as each object in the game has both state and behaviour. Most web applications on the other hand, are better suited for a procedural programming style.

  • You know exactly where the business logic is. In the Onion Architecture, the logic could be anywhere and you might have to traverse a long call hierarchy to get to where you need to be. In the 3-tier architecture, the business logic can always be found in the service-layer.

  • If the requirements change, so that a piece of business logic suddenly needs an extra call to the database, you can simply do that. The logic is in the service-layer, which has access to the DAO's. In the Onion Architecture, when the logic is in a domain object, you have no access to the repositories. You have to solve it in either of two ways: Move the logic to a service, which is a significant refactoring, or pass in the needed data via a parameter. This leads to long lists of parameters being passed and will be difficult if you can only determine the required data halfway through the logic.

  • There's a very short learning curve. If a new developer joins the team, they can start working on their little part of the application almost immediately. They just have to know about a page, a service and a DAO. In the Onion Architecture, there's a long learning curve and new developers are required to understand the entire domain before they can make any changes.

  • There's only one way to do things, which will lead to simplicity and consistency throughout the application. In the Onion Architecture, different developers might have different ideas on how to model a certain use case, even if they're all OO-geniuses. This means that over time, the application becomes complex and inconsistent, increasing the learning curve even further. This will also become a problem if certain key developers leave the team.

    Simple rules lead to complex and intelligent behavior.
    Complex rules lead to simple and stupid behavior.

    - Dee Hock -

  • It's easier to enforce standards and guidelines, since each layer has very specific responsibilities. In the Onion Architecture, it's more difficult, as basically anything is allowed inside the domain objects.

  • There's a clear separation between logic and data. This makes it possible to accurately track changes in either, without being distracted by the other. Since logic changes often and data does not change very often, this can be quite useful.
Despite the benefits of the 3-tier architecture, the Onion Architecture also has some good practices that are worth mentioning. Each of them however, is not specific to the Onion Architecture, but can be applied in the 3-tier architecture as well:

  • In the Onion Architecture, there is no business logic in the repositories. This is a good practice, because the repositories are meant to be a thin layer above your database. In the 3-tier architecture, you can use the same practice for your DAO's: keep them lean and leave the business logic to the services.

  • Complex pieces of logic that are not specific to a single domain object and are therefore not inside a domain object, are separated out into components. These components can then be used by other classes. The benefit of this is that this complex logic can then be separately tested, instead of it being tested as part of the calling logic. In the 3-tier architecture, creating components that handle specific, complex pieces of logic is perfectly possible. These components live in the service layer and can be used by the services.
All in all, I think that the 3-tier architecture provides a lot of benefits for a typical web application and, equally important, a typical team where people come and go all the time. I'm not saying that the 3-tier architecture is always better than Domain Driven Design, but in most cases, the complexity that the Onion Architecture brings with it, is really not worth it. And when a web application becomes so large and complex that the 3-tier architecture no longer suffices, then, instead of moving to Domain Driven Design, it might be a better idea to look at SOA approaches and split up the application altogether.

A clever person solves a problem, a wise person avoids it.

- Albert Einstein -

If you would like to read another article that argues against complex multi-layers, then I can recommend this one from jOOQ.

Friday, 9 January 2015

Wicket + BEM: A powerful combination

In this article, I will explain how to combine Wicket, one of the leading Java frontend frameworks, with BEM, one of the leading CSS coding standards, to create a frontend architecture that makes creating and maintaining your HTML frontend a lot simpler, easier and faster.

Wicket
Java frontend frameworks come in two flavours: Action based and Component based. Action based frameworks focus on manually handling each HTTP request by figuring out which data and what markup to return to the client. The best known example of an Action based framework is Spring MVC, but there are many others.

Component based frameworks take this one step further, by allowing the developers to create components: reusable panels that are fully self contained and represent a single item on a website, for example a title bar or a registration form. These components contain both frontend logic (i.e. calls to the service layer to send and retrieve data) and markup and can then be reused on various pages without the page having to worry about the internals of the components. It's like playing with Lego: instead of having to retrieve all the right data and select all the right markup for each HTTP request, you can simply slap existing components on a page and the components will take care of themselves. Each page is then associated with a URL extension. This way, handling HTTP requests is hidden from the programmer.

When it comes to HTML, some Component based frameworks hide this as well by providing their own XML tags that get transformed into HTML. One example of this is JSF. In this article however, we will talk about my favourite Component based framework: Wicket. This framework does not hide HTML from the programmer. Instead, the programmer writes plain HTML, augmented with some Wicket specific tags and attributes to bind the appropriate HTML elements to the Java code. A Wicket component is known as a panel and consists of a Java file for the frontend logic and a corresponding HTML file for the markup. It looks like this:

TitleBarPanel.java:
public class TitleBarPanel extends Panel {
    public TitleBarPanel(String id) {
        super(id);
        this.add(new Label("titleLabel", "Hello World!"));
    }
    //...other frontend logic and communication with the backend goes here...
}
TitleBarPanel.html (matched to the Java file by fully qualified name):
Note: Due to Blogger's peculiarities, I can't use self-closing tags with a wicket:id attribute in the example code, but in reality, it's perfectly okay (and recommended) to use them.

    
    
        
        
Of course, panels can contain other panels as well in an unlimited container/component pattern:

TitleBarPanel.java:
public class TitleBarPanel extends Panel {
    public TitleBarPanel(String id) {
        super(id);
        this.add(new Label("titleLabel", "Hello World!"));
        this.add(new MenuPanel("menuPanel")); //MenuPanel is another panel that we've created
    }
}
TitleBarPanel.html:

    
        
If you don't have any experience with Wicket, you can read some tutorials on wicket.apache.org. A good article that further explores the differences between Action based and Component based frameworks is this one.

BEM
BEM is a CSS coding standard designed to solve the problem that arises when you create a large web application with lots of pages. If you change the CSS rules that correspond to a CSS class in order to change something on one page, then things all over the application suddenly change as well if that CSS class is used elsewhere. BEM solves this by defining so-called blocks. A block is a piece of the website that is independent from the rest of the website and can be designed and maintained separately, for example a title bar or a registration form. Hmmm, where have we heard that before?

BEM achieves this by enforcing a CSS class naming standard that guarantees that no naming conflicts will happen among the CSS classes of your application. For example:
Hello World!
What do we see there? The block is defined by a single outer div with the name of the block, in this case "b-NewsItems". Then, inside the block, each CSS-class starts with the name of the block! This way, we only have to take care of the uniqueness of the block name. If we make sure that each block name is unique across our application, then CSS naming conflicts will never occur and you can create and maintain each block independently from the rest of the application.

So what's with the "b-" prefix? In BEM, "b-" means that we're dealing with block classes. There are two more prefixes that you can use for other purposes:

  • The "p-" prefix means that it's a so-called pattern class: a class that can be applied to HTML elements regardless of which block they're in. For example, if you have designed a very unique border that needs to be applied to a lot of elements, then you put this into a pattern class "p-MyBorder", to be used throughout your application. In a way, this is the opposite of a block class, since it does not correspond to a specific part of the application and when we change it, we do want things to change everywhere.

  • The "js-" prefix means that it's a JavaScript class: a class that is applied to HTML elements so that you can identify these elements in your JavaScript code. Normally, you would use HTML id's for this, but since most Component based frameworks use the id to keep track of the various elements of the application, it's better to use classes for this.
In BEM, all CSS rules must be in a selector that starts with either a block class or a pattern class, to avoid any conflicts with other HTML tags in your application.

Combining Wicket and BEM
By now, you must have an idea of where we're heading. Both Wicket and BEM focus on components: pieces of a web application that are fully self contained and are created and maintained independently from the rest of the application. Wicket calls them panels and BEM calls them blocks. Sounds like they're an ideal match for one another! What if, in addition to the logic and the markup, we put the style of a component in a Wicket panel too, with the help of BEM? Let's see what that would look like!

TitleBarPanel.java:
public class TitleBarPanel extends Panel {
    public TitleBarPanel(String id) {
        super(id);
        this.add(new Label("titleLabel", "Hello World!"));
        this.add(new MenuPanel("menuPanel")); //MenuPanel is another panel that we've created
    }
}
TitleBarPanel.html:

    
    
        
    

    
        
        
Now, the TitleBarPanel is fully self contained: Logic, markup and style all in one place for a highly cohesive panel that is completely decoupled from the rest of our application and can be maintained independently of anything else.

But what if we want to change a tiny little thing in the MenuPanel? What if the MenuPanel has a <span> with the CSS class "b-MenuPanel-menuHeader" that has red text, but we want to make it blue in the TitleBarPanel? Well, we can simply override the color attribute of that span by using our own block name to create a higher CSS specificity than the default setting in MenuPanel.

MenuPanel.html:

    
        
    

    
        
    
TitleBarPanel.html:

    
        
    
    ...
You can do this cumulatively as many times as you like. Suppose the TitleBarPanel is used in six different panels and in one of those panels, say the FrontPanel, we want the menu header to be red again? Simple, put this in the <style> tag of the FrontPanel:
.b-FrontPanel-titleBarPanel .b-TitleBarPanel-menuPanel .b-MenuPanel-menuHeader {
    color: red;
}
Now, all the MenuPanels will have a red header, except when used in a TitleBarPanel, then it will be blue. Except when that TitleBarPanel is used in a FrontPanel, then it will be red again. This will never break, no matter how deep you go, since it will only ever affect panels that are contained inside the panel where you put this CSS selector.

From an architectural point of view, this is a very clean solution: The container has control over its children and can override certain CSS settings, but the children are completely unaware of this. Each panel focuses on itself and its children, but does not know where and how it is used in other panels and pages. In technical terms: Each HTML file only has CSS selectors that begin with its own top level BEM class and most certainly not others!

Benefits
Aside from the fact that this architecture makes developing and maintaining your application a lot simpler and easier, it has other benefits too:

  • All CSS that a page needs is present in the <style> tag of the HTML document. This reduces the amount of HTTP requests that would otherwise be necessary to retrieve the .css files. An exception to this are the pattern classes, of course. They are still in separate .css files, since they are not specific to a page.

  • Only the CSS that is needed to display the page will be retrieved. No additional CSS that is used for other pages will be retrieved. This reduces the size of the CSS that needs to be downloaded.

  • Since the CSS is sent within the HTML file, it won't be cached by the browser. This might sound like a drawback, but can also be a benefit: when you deploy a new version of your application with changed CSS, your users won't see any glitches because the browser still uses an old CSS file and won't have to press F5 to view the page correctly. Pressing F5 might seem trivial to you and me, but a lot of non technical users might not know this.

  • CSS is easy to find. It's right there in front of you when you write your panel, not in some file in some directory elsewhere.

  • It brings CSS closer to web developers. In a lot of companies, CSS is written and maintained by different people than the Java developers, which often leads to a situation where the Java developers don't really know a lot about it. Also, they are often less interested in writing proper CSS and maintain an "If it looks OK, then it is OK" attitude. This will lead to an increasingly complex and buggy CSS codebase. With the approach in this article, the CSS is right in front of the programmer when he's creating Wicket pages. It will increase the sense of ownership and will make writing CSS more fun, since you're only working on your little bit, without having to worry about the rest of the application.

  • CSS gets deleted when a panel gets deleted. This is a major advantage. Old unused CSS often lingers around and since unused code detectors work really well for Java, but not well at all for CSS, an automatic solution to this problem is a nice thing to have.
Drawbacks
As with every architectural approach, this one has its drawbacks too:

  • It does not support SCSS. SCSS is a CSS meta language that allows you to write CSS code in a more advanced way. An SCSS compiler then compiles your SCSS files to CSS files. Since in this architecture, the CSS is inside your HTML files, it cannot be compiled by the SCSS compiler. There are a few silver linings to this though:
    • Adding SCSS compilation to your build process makes it more complex and increases the build time, so not having to do this saves time and effort.
    • It can be difficult to link a CSS rule on your page to an SCSS rule in the original document. This can make it harder to debug errors.
    • The experimental version of Google Chrome supports native SCSS, meaning that you can just send SCSS to the browser directly. Once this becomes mainstream, you can just put SCSS code in your <style> tags. This will make it compatible with this architecture: All the benefits of SCSS, without the aforementioned drawbacks!
  • It is not possible to switch CSS files at runtime. This is sometimes done to let the user choose the look and feel of the page. Since in this architecture, the CSS is embedded in the HTML, this won't be fully possible. It will only be possible with the pattern classes, that are still in separate CSS files. This will still give you plenty of possibilities though, since the pattern classes often contain look-and-feel stuff, whereas the block classes contain more positioning stuff.

  • The HTTP responses will be slightly larger, since the HTML files will be bigger. There will be less HTTP responses though, since there will be less CSS files to retrieve.

  • Internet Explorer 9 and lower are not supported, since they only support a maximum of 31 <style> tags in the head. As mentioned before, Wicket aggregates all <wicket:head> tags of all the panels into the final <head> tag of the page, but the separate <style> tags will remain. so if you have more than 31 panels on a page (which is quite common in Wicket), then any <style> tags after the 31st will be ignored. It is of course possible to write a Filter that puts all the content of all the <style> tags into a single <style> tag, but this will require some effort.
If these drawbacks don't deter you, then I'm sure that the simplicity and the high cohesion of your panels make your frontend development a lot easier. And who knows, it might even transform you from a good Java developer into a CSS master!