DEV Community

loading...
Cover image for Keep your code well organized. How I structure my web project

Keep your code well organized. How I structure my web project

pazvanti
Originally published at petrepopescu.tech ・3 min read

Article originally posted on my personal website at How to organize your web project

It is easy to get carried away and just write code. The code may even work as intended but trust me that, in 6 months time, you won’t know anymore what it does and where to find a specific functionality. Unless you have a clean and clear structure. I am not necessarily talking about the classes itself, but the way to properly organize functionalities in packages so that, when a change is needed 6 or 12 month later, you know exactly where to look.

I will be using a web server application as an example and will explain pitfalls and how to avoid them. Some may seem obvious, nevertheless I feel obligated to point them out. Many times you will see wrongly placed functionality, especially in legacy code. Furthermore, it is not always a clear and clean line between two places and both may seem right, so consistency is key in these situations.

Main parts of a web application

Web applications usually have a few key main components that interact with each other. These are the controllers that handle the requests, the services that processes the data and the data access layer responsible for persisting and retrieving stored data. Let’s take a look over each component.

Controller

This is the main entry point of the application and it is usually mapped to one or more endpoints that are accessible via the web browser. The controller receives the HTTP request and it will return an HTTP response back to the client. It does not matter if you are using Spring, Play or any other framework, the controller should be the one to handle the request and only the request.

One frequently encountered mistake is doing business logic inside the controller. I strongly believe that this not the right way of doing thigs and that only validating the request should be done here, the actual business logic being the services responsibility. Furthermore, the request should not be submitted to the services unless it is absolutely necessary. Instead use a mapper to transform the request into one or more data objects and those should be passed down to the service.

The main responsibilities of the controller should only be:

  • Receiving the request
  • Validating it
  • Mapping the request to an internal data object (here it should delegate the request to a mapper)
  • Calling the service
  • Mapping the result object to the HTTP response
  • Returning the response

Service

The service is the component that is responsible for doing the business logic. Any calculations, business validations, and business operations should be handled here. A service can call and delegate part of the functionality to other services, with the exception of data persistence, something that should be done buy the DAO.

Here it can be easy to have God classes which do many (unrelated) things. It is normal to have many services that interact with one another. Try to split up your classes based on what they do and not over extend a service’s responsibility. Do you manage users? Have a ‘Users’ service. Does your site allow posting of articles, have an ‘Articles’ service. What about comments? You guessed it, a ‘Comments’ service. Yes, you need a logged in user to post an articles, so the ‘Article’ and ‘Users’ services can interact with one another, but don’t do the ‘submitNewArticle(User user, String articleText)’ method inside the Users service just because you use a User object.

Data

This is the part of the application that handles the persisted and transmitted data. This is where we should keep Domain Objects (DO), Transfer Objects (DTO), Access Layer (DAO), and, at least in my case, filters needed. Keep in mind that these should be properly arranged into packages. Don’t keep classes that have different responsibilities in the same packages.

Others

This is the basic structure, however each application has its own needs. That is why other top-level packages should be created when needed. Furthermore, the main three parts presented here can be further divided into other parts in order to make things clear and to make the code easier to maintain.

Article originally posted on my personal website at How to organize your web project

Discussion (3)

Collapse
icatalina profile image
Ignacio Catalina • Edited

I find it way more intuitive to split your application by domain.

Within each domain folder you can then have controllers or services related to that domain.

Collapse
pazvanti profile image
pazvanti Author

In some cases it may be true, however, for bigger projects the services usually work with multiple Domain Objects and DAOs. Where will the service reside in this case? It is completely acceptable to further categorize services based on common working grounds, but I still believe the general structure should be similar to the one I presented.

Collapse
icatalina profile image
Ignacio Catalina

I wasn't referring to domain objects but rather domain from Domain-Driven-Design:

Domain
A sphere of knowledge (ontology), influence, or activity. The subject area to which the user applies a program is the domain of the software;

Services will live within the domain they deal with. It might be just me, but when I browse code I don't think: am I looking for a service or a controller but rather what part of my app is responsible for this. For instance, if I see a problem within the shipping endpoint I'd expect the code that I need to fix to be within the shipping folder.

The DAOs and domain objects of one service should be contained within that service's domain. The representation of what a customer is will likely vary between domains, having a single representation can cause pain in the long run.

Forem Open with the Forem app