Skip to content

Latest commit

 

History

History
109 lines (80 loc) · 10.3 KB

design.md

File metadata and controls

109 lines (80 loc) · 10.3 KB

GetIt software design

This document outlines the design philosofy for GetIt's source code.

1. Class diagram

The source code for GetIt is made up of four layers

  1. Domain
  2. Service
  3. Data
  4. Presentation

Each of these layers maps to a specific namespace in which contracts, implementations and factories are defined. Besides the presentation layer, each layer must only expose data types that are either defined in the standard C++ library or use data types defined in the domain layer of GetIt itself.

To communicate with classes from a different layer a factory must be used.

Class diagram

1.1 Interfaces

As a general rule, all interfaces are defined in the contracts interface. To imply the layer the

Namespace Interface Description
domain::contracts RequestFactory To create a new Request, the request factory is used. But to inject the factory itself, an interface is defined which used by the dependent classes.
service::contracts RequestService To send a request, the request service is used to send the request object. But to inject the factory that instantiates the service for sending the request, an interface is used by the dependent classes.

1.2 Classes

Namespace Class Description
domain::implementations RawRequest This class is used to represent a raw http request. This implies the use of a raw body. If the body is a string, that string is directly sent to the server without any parsing beforehand.

* This class inherits from the Request model.
domain::implementations FormdataRequest This class is used to represent a formdata http request. This implies the use of the multipart/form-data header. Every element or file that's added to this request is converted to the expected formdata http body, see the IETF RFC 7578 (Adobe, 2015). *This class inherits from the Request model
domain::factories RequestFactory This class is used to instantiate a new Request model implementation based on the parameters. I.e. if the parameters are only applicable to a RawRequest, a RawRequest object is instantiated and returned.
domain::models Request This is an abstract representation of an actual request. The getBody and getContentType methods are override by implementations so these are different for the different implementations of a request.
domain::models Response This is a representation of a response returned by a server after sending a Request.
service::implementations CppRestRequestService Implementation of the RequestService that's using the CppRestRequest library from Microsoft (Microsoft, n.d.). As of right now, this is the only implementation available for sending a request using the RequestService.
service::factories RequestServiceFactory Factory that's used to instantiate a new RequestService. Because the CppRestRequest library from Microsoft is the only supported library for sending a request this class only constructs a CppRestRequestService object. However, in the future this factory could be expanded with other request libraries.

In the following paragraphs each layer will be explained in more detail.

1.3 Layers

GetIt uses the layered pattern, or N-tier pattern, to decouple the different types of partitions most common applications consist of . This pattern groups classes by responsibility and encourages you to place them into the same layer (Price et Al., 2022). Thus meaning that all classes and logic related to data storage or retrieval are put into the data layer.

The table below lists and describes the different layers GetIt acknowledges.

Layer Description
Domain The domain layer consists of classes exclusive to the domain. This includes classes such as Request that are directly sent to a server.

The domain layer can only contain classes that are dependent on other classes inside the domain layer. This is done to prevent knowledge of anything outside of the request domain.
Service The service layer is used to decouple the domain from the actual implementation of sending a request and retrieving a response from a server.

The service layer can be thought of as the layer that can be used to interact with domain objects. Even though it's possible to interact with the domain objects, they can't be used to send an actual request.
Data The data layer is used to decouple the domain layer from storing domain objects. In the data layer it's possible to create multiple implementations of methods for saving a request, or retrieving a request.

With this decoupling, the domain layer can be used to describe the domain without worrying about any details that are required for saving a request.
Presentation The presentation layer consists of QT-libraries and interaction for the GUI. The presentation layer is only allowed to communicate with the service and data layer. However, the objects from the domain layer are used as models in the MVC pattern.

2. Design decisions

This paragraph describes the different decisions that were made during the design of GetIt.

GDD01 Raw- and FormdataRequestBody
Decision Create a different implementation for the RawRequestBody and FormdataRequestBody which implement from the RequestBody interface
Motives When working with a Request you don't need to know the specific body type, therefore an interface RequestBody is used
Alternatives Use different Request implementations for the different body types
GDD02 Abstract factory
Decision Use the abstract factory pattern to inject factories into classes
Motives To make use of the IOC pattern, the factories are injected as interfaces as well.
GDD03 Inversion of Control (IOC)
Decision Use inversion of control to communicate with dependencies
Motives To communicate with dependencies inversion of control is used to abstract the instantation of classes away from constructors/methods that are dependent on the implementations.
GDD04 Constructor injection
Decision Dependency injection is implemented with constructor injection
Motives By using constructor injection the dependencies need to be built in the main.cpp file instead of relaying on the complexity of a dependency injection framework.

However, in the future a DI framework might be implemented without changing the underlying code of GetIt if the DI framework supports constructor injection.
GDD05 Construct classes using a factory
Decision Only construct new objects using a factory
Motives To keep the construction of new classes in a single place, factories are used to construct new instances of objects.

However, some exceptions are expected. But these exceptions only remain in the convert classes or the main method. If objects are instantiated outside of a factory, it must be explicitly expressed in a comment.
GDD06 Use C++ standard 2017
Decision Using the C++ 2017 standard for compiling GetIt
Motives When compiling CppRestSDK with C++ standard 2020 the compilation fails due to implicit capture of ‘this’ via ‘[=]’ is deprecated in C++20 in the pplxtasks.h header.
GDD07 String literals
Decision Only use string literals when there are no line breaks in the string.
Motives To keep the code readable and strings on one line, the use of \r\n line breaks must be used instead of actual line breaks in the string.
GDD08 Separate pipeline to create Github release
Decision Use a different pipeline to create a release based on the latest tag.
Motives To keep the pipelines for packaging GetIt for different platforms independent of each other, the release cannot be created in one of those pipelines. When the pipeline that creates the release fails, the other pipelines subsequently fail as well. Therefore a separate pipeline is the best alternative.