Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Organize Your Code

DZone's Guide to

How to Organize Your Code

Code organization is more an art than a science. See how the folks over at Hello2morrow do it here.

Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

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:

System Architecture

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: 

Layering

A service would only expose its service ad 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 microservice.

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”

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.

Download Modern Java EE Design Patterns: Building Scalable Architecture for Sustainable Enterprise Development.  Brought to you in partnership with Red Hat

Topics:
packages ,dsl

Published at DZone with permission of Alexander Von Zitzewitz, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}