This series of articles is a compilation of the notes I gathered during my programming bootcamp at Green Fox Academy, last year.
You can read the other articles here:
If think about the responsibilities of a web application, we notice that a web application has the following concerns:
- It needs to process the user’s input and return the correct response back to the user
- It needs an exception handling mechanism that provides reasonable error messages to the user
- It needs a transaction management strategy
- It needs to handle both authentication and authorization
- It needs to implement the business logic of the application
- It needs to communicate with the used data storage and other external resources
We can fulfil all these concerns by using only three layers. These layers are:
- The web layer is the uppermost layer of a web application. It is responsible of processing user’s input and returning the correct response back to the user. The web layer must also handle the exceptions thrown by the other layers. Because the web layer is the entry point of our application, it must take care of authentication and act as a first line of defense against unauthorized users.
- The service layer resides below the web layer. It acts as a transaction boundary and contains both application and infrastructure services. The application services provides the public API of the service layer. They also act as a transaction boundary and are responsible of authorization. The infrastructure services contain the “plumbing code” that communicates with external resources such as file systems, databases, or email servers. Often these methods are used by more than a one application service.
- The repository layer is the lowest layer of a web application. It is responsible for communicating with the used data storage.
The components that belong to a specific layer can use the components that belong to the same layer or to the layer below it.
- Controller: responsible for displaying views
- Service: responsible for business logic
- Repository: responsible for data storage and retrieval
@Component — generic stereotype for any Spring-managed component. We can use @Component across the application to mark the beans as Spring’s managed components
@Service, @Controller / RestController, @Repository and @Entity — all “just” specializations of @Component for more specific use cases (@Component could be used instead, but these make the code more readable)
@(Rest)Controller (stereotype for consumer/web layer) — responsible for triggering the creation of a (REST API) controller
@Service (stereotype for service layer) — beans marked by ~ hold the business logic; responsible for triggering the creation of a service
@Repository (stereotype for persistence layer) — responsible for triggering the creation of DAOs in our application. Also to catch persistence-specific exceptions and rethrow them as one of Spring’s unified unchecked exceptions.
@Entity (stereotype for persistence layer) — responsible for triggering the creation of an entity in the database
Stands for Model — View — Controller. It is an architectural pattern commonly used for developing user interfaces that divides an application into three interconnected parts.
The Model-View-Controller (MVC) pattern is a web application architectural pattern that focuses on one thing — separation of concerns. The goal is to separate data handling from display logic and separate the presentation of the data from its underlying representation and tied-in application logic.
The model layer is the lowest level of the back end of your application. It sits on top of the data store and handles manipulating the data at a database level. Furthermore, current design idioms implement most of your application’s logic at the model layer, meaning that not only do models manage their own attributes, they are also responsible for handling all side-effects in your application’s back end when a change occurs.
Controllers are the glue that tie an MVC application together. At their most basic level, they handle three tasks: data marshaling, routing, and model updating. Data marshaling consists of communicating with the model layer and obtaining all of the objects necessary to present a particular view to the user. Routing, on the other hand, handles control flow for the application, directing the next view to be rendered by a page flow, or guiding the view layer in its data presentation as the user moves through — and interacts with — your application.
Inversion of Control & Dependency Injection
Inversion of Control (IoC)
Inversion of Control is a principle in software engineering by which the control of objects or portions of a program is transferred to a container or framework. It’s most often used in the context of object-oriented programming.
By contrast with traditional programming, in which our custom code makes calls to a library, IoC enables a framework to take control of the flow of a program and make calls to our custom code. To enable this, frameworks use abstractions with additional behaviour built in.
The advantages of this architecture are:
– decoupling the execution of a task from its implementation
– making it easier to switch between different implementations
– greater modularity of a program
– greater ease in testing a program by isolating a component or mocking its dependencies and allowing components to communicate through contracts
Dependency injection is a pattern through which to implement IoC, where the control being inverted is the setting of object’s dependencies. The act of connecting objects with other objects, or “injecting” objects into other objects, is done by an assembler rather than by the objects themselves.
What is a dependency? Whenever Class A relies on (=uses) methods, and thus instances, of another Class B, this relationship represents a dependency.
What is dependency injection? It’s the technique used to decouple the creation and the usage of the dependency. That is, the instance of Class B used by Class A will NOT be created in/by Class A — but it will be injected therein. DI is a middleman — takes Class A’s order for an instance of Class B, makes sure it’s created and provides it to Class A.
There are basically 3 types of DI:
1) Constructor injection — the dependencies are provided through a class constructor
2) Setter injection — the client exposes a setter method that the injector uses to inject the dependency
3) Interface injection — the dependency provides an injector method that will inject the dependency into any client passed to it
What is DI good for, why do we need DI? It helps you to follow SOLID’s dependency inversion and single responsibility principles. The goal of SOLID design principles is to improve the reusability of your code. They also aim to reduce the frequency with which you need to change a class. Dependency injection supports these goals by decoupling the creation of the usage of an object. That enables you to replace dependencies without changing the class that uses them. It also reduces the risk that you have to change a class just because one of its dependencies changed.
📝 Read this story later in Journal.
👩💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.