Design principles - SE-TINF22B6/CookHub GitHub Wiki
The MVC pattern is used achieve a seperation of concerns by dividing information representation into 3 parts:
- the Models, which contain and manage data,
- the Views, which define how the data is shown to the user, and
- the Controllers, which manage user interaction and pass the data from the model to the view
In our case, we defined our MVC pattern as followed:
-
Models: Classes that represent our database entities, e.g.
User
,Recipe
,Ingredient
-
Views: React components that define our different web pages, e.g.
LandingPage
,LoginPage
,RecipePage
-
Controllers: Backend API endpoints, which take requests by the frontend and change/transfer the requested data, e.g.
UserController
,RecipeController
,IngredientController
The dependency inversion principle states that high-level modules should not depend on low level modules. Instead, both should depend on abstractions.
To achieve this, we decouple our classes using dependency injection:
Instead of our classes creating their dependencies themselves, they only define what type their dependencies should have. The concrete instances will get passed through the constructor. This can be done by using the built-in IoC container of ASP.NET, which automatically resolves the dependencies (after a little bit of configuration).
E.g. The UserController
class depends on the UserService
class, which handles all the logic when managing user data. Therefore, we define that the constructor of UserController
takes a UserService
as a parameter. To automatically resolve the dependency, we then configure the IoC container with the following instruction: services.AddTransient<UserService>();
. This will have the effect that everytime a user request comes in and a new UserController
instance gets created, a new instance of UserService
will automatically be passed through the constructor.
The decoupling of classed achieved by this principle makes the replacement of whole modules very simple. And when testing code, we can just pass a different object through the constructor, which makes the mocking of dependencies a lot easier.