Agile, People & Culture

How to Organize your Code

In this article, Alexander von Zitzewitz teaches you how to organize your code and how to describe this organization using hello2morrow's architecture DSL implemented by their static analysis tool Sonargraph-Architect.

The original post was published on hello2morrow.

In this article I am going to present a realistic example that will show you how to organize your code and how to describe this organization using our architecture DSL (domain specific language) implemented by our static analysis tool Sonargraph-Architect. Let us assume we are building a micro-service that manages customers, products and orders. A high level architecture diagram would look like this:

It is always a good idea to cut your system along functionality, and here we can easily see three subsystems. In Java you would map those subsystems to packages, in other languages you might organize your subsystem into separate folders on your file system and use namespaces if they are available.

Let us assume the system is written in Java and its name is “Order Management”. In that case we would organize the code into those 3 packages:

com.hello2morrow.ordermanagement.order
com.hello2morrow.ordermanagement.customer
com.hello2morrow.ordermanagement.product

This can easily be mapped to our architecture DSL:


artifact Order
{
    include "**/order/**"
    connect to Customer, Product
}
 
artifact Customer
{
    include "**/customer/**"
}
 
artifact Product
{
    include "**/product/**"
}

Internally all three subsystem have a couple of layers and the layering is usually the same for all subsystems. In our example we have four layers:

 

A service would only expose its service and its model layer to the outside. The service layer contains all the service interfaces and talks to the controller and the model layer. The controller layer contains all the business logic and uses the data access layer to retrieve or persist data using JDBC. The model layer defines the entities used by our micro service.

We will use a separate architecture file named “layering.arc” to describe our layering:


// layering.arc
artifact Service
{
    include "**/service/**"
    connect to Controller
}
 
artifact Controller
{
    include "**/controller/**"
    connect to DataAccess
}
 
require "JDBC"
 
artifact DataAccess
{
    include "**/data/**"
    connect to JDBC
}
 
public artifact Model
{
    include "**/model/**"
}
 
interface IService
{
    export Service, Model
}


Please note, that we declared “Model” as a public artifact. That saves us the need to explicitly connect all the other layers to “Model”. Also note the “require” statement. Here refer to a third architecture file, that contains the definition of the artifact JDBC. This way we can ensure that only the data access layer can make JDBC calls. Using “require” will only declare the artifacts contained in the required file, but not define them. This means that the artifacts in “JDBC” have to be defined on another level. The interface is used to define the exposed parts of a subsystem. When connecting to the “IService” interface you have only access to the “Service” and the “Model” layer.

Now we use apply statements to apply the layering to our three subsystems:


artifact Order
{
    include "**/order/**"
    apply "layering"
    // Connect to the IService interface of Customer and Product
    connect to Customer.IService, Product.IService
}
 
artifact Customer
{
    include "**/customer/**"
    apply "layering"
}
 
artifact Product
{
    include "**/product/**"
    apply "layering"
}
 
// By using apply we define the artifacts of "JDBC" in this scope
apply "JDBC"

We also apply “JDBC” in the outermost scope to ensure that the artifacts in there are defined exactly once.

For the sake of completeness, here is the definition of “JDBC.arc”


// JDBC.arc
artifact JDBC
{
    include "**/javax/sql/**"
}

By using smart package naming it becomes easy to map your code to the architecture description. For example the order subsystem would have four packages:


com.hello2morrow.ordermanagement.order.service
com.hello2morrow.ordermanagement.order.controller
com.hello2morrow.ordermanagement.order.data
com.hello2morrow.ordermanagement.order.model

As you can see it required relatively little effort to create a formal and enforceable architecture description for a software system. If you want to learn more about our architecture DSL, I recommend reading a series of blog posts introducing the different concepts of this powerful language.

Top Articles About Agile, People & Culture

STAY TUNED!

JOIN OUR NEWSLETTER

Behind the Tracks

Software Architecture & Design
Software innovation & more
Microservices
Architecture structure & more
Agile & Communication
Methodologies & more
DevOps & Continuous Delivery
Delivery Pipelines, Testing & more
Big Data & Machine Learning
Saving, processing & more

JOIN OUR UPCOMING EVENTS IN LONDON!