Sunday, October 13, 2013

Iterations Rules

As I've mentioned previously, I've been working lately on a side project called Iterations. At the moment, I'm the only back-end developer which means I get to make the rules, something that I don't often get to do. :) And my rules have been formed based on pains that I've experienced first-hand on work-related projects, pains born from mistakes made by both myself and others; pains that I want to avoid this time around.

In general, Iterations is a web app that will allow Agile projects to be tracked...basically to provide functionality that vendors usually charge a pretty penny for, for free, and hosted on your own server pointing to your own database, instead of someone else's.

So what's the technology stack being used? Well, it's a Maven project that uses RESTEasy to allow the front-end to make calls to the back-end, Guice is used for dependency injection, while MyBatis takes care of the database side of things. On the UI side, we're using CoffeeScript and Sass to make things look pretty, which is all being taken care of by the rather talented UI guru Mike Munsie.

Architecturally, there are three main layers to the app; a resource layer which acts as the entry point to the back-end, a service layer where the main logic lies, and a data-access layer that provides all database related functionality. There are other layers that provide things like security and exception handling, but for the main part, it's these three layers that provide the majority of the grunt work. So with that, here are my four simple rules that I apply in order to keep the design as clean as possible:

The resource layer can only talk to the service layer
Each resource is allowed to talk to one or more services only. It seems pretty reasonable that resources cannot talk to DAOs, but let's tighten things up a bit and say that resources cannot talk to other resources either. The reason being that talking to other resources, to me, implies that there is common functionality that should be abstracted out instead.

Resources must not pass HTTP specific information to the services
As requests come in, each resource should extract the information from the HTTP request, and provide that to the services. This way, a service may be reused by some future layer that isn't HTTP based. For example, let's imagine that we're going to start using a scheduler like Quartz to send out emails each night; it would be pretty much hosed if a service that it depends on requires an HttpServletRequest to be passed to it. In order to be reusable, a service must be unaware of who is calling it.

The service layer can only talk to the data-access layer
This is similar to the first rule, and for the same reason; services cannot talk to other services as that implies common functionality that we can abstract out. Services also cannot talk to resources (and if we follow the previous rule, they probably can't anyway). This helps to avoid any entanglement of code, which is a good thing (the avoidance that is, not the entanglement ;).

The data-access layer cannot talk to any other layer
Each DAO is tasked with simply making calls to the database, that's all, so as to keep things simple. A DAO cannot talk to another DAO.

And that's it. Following these four simple rules has so far kept the design pretty simple, as it should be. They've helped prevent the beginnings of spaghetti code from happening, and helped avoid broken windows from appearing in the first place.

I like rules. Especially when they're my rules. :)

No comments:

Post a Comment