Skip to content
This repository was archived by the owner on May 22, 2021. It is now read-only.

Commit 055f531

Browse files
committed
Added detailed Contributing Guideline (#191)
1 parent 928dc9e commit 055f531

2 files changed

Lines changed: 310 additions & 9 deletions

File tree

CONTRIBUTING.md

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
# Contributing
2+
3+
Great if you want to contribute to this project!
4+
5+
But we have to maintain this project and to do that easier everyone has to observe the follwing rules.
6+
7+
## Code Style
8+
9+
The code is written like the official [Java Code Conventions](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf).
10+
11+
Important is to give the methods and classes expressive and clear names to easily differentiate between them.
12+
13+
A command should be wrapped in a new line if it has more than 120 characters.
14+
15+
Tab characters have to be used instead of spaces.
16+
17+
All not final fields have to be tagged with `@Autowired`.
18+
19+
Getters and Setters are generated with the annotation `@Data` by the plugin *lombok*.
20+
Constructors with ``@NoArgsConstructor`` and `@AllArgsConstructor`.
21+
22+
### Variable names
23+
24+
In ``ControllerResult`` is Controller just a prefix so exclude it in the variable name.
25+
26+
In any ``Model`` is Model a prefix so exclude it.
27+
28+
Example:
29+
````java
30+
ControllerResult<SolutionModel> solutionResult = this.solutionController.getSolution(taskId);
31+
````
32+
33+
DTOs are named if they are are requestDTO ``dto``, if it is a responseDTO they are called `responseDTO`.
34+
35+
(`ResponseDTOModel` is named `responseDTOModel` )
36+
37+
## Structure
38+
39+
### Package structure
40+
41+
The base package is `de.themorpheus.edu.taskservice`
42+
43+
This package includes:
44+
- controller<br>
45+
└ controller of endpoints
46+
- database<br>
47+
└ repositories of controllers and models of those repositories
48+
- endpoint<br>
49+
└ endpoint classes and response/request DTOs (**D**ata**T**ransfer**O**bject)
50+
- pubsub<br>
51+
└ pubsub classes and subscriber/publisher for the [PubSubSystem](https://github.com/E-Edu/concept/blob/master/documentation/dev/architecture/architecture.md#pubsub-cluster)
52+
- spring<br>
53+
└ custom config files of spring
54+
- util<br>
55+
└ those who don't match to any other package (like Errors, Constants, etc.)
56+
---
57+
### Arrangement of methods
58+
To keep a clean code the methods have to be sorted like the following:
59+
- Create
60+
- Update
61+
- Get
62+
- GetAll
63+
- GetSpecific
64+
- ...
65+
- Check
66+
- Delete
67+
- other methods (e.g. methods in other controllers)
68+
---
69+
### Endpoints
70+
The endpoint classes have to define the route and call the associated method in the controller.
71+
They also have to handle the authentication and authorization of the users and check permissions.
72+
Every endpoint class has to end with the suffix `Endpoint`.
73+
#### DTOs
74+
##### Validation
75+
**D**ata**T**ransfer**O**bjects have to validate the *Requestbodies* with `javax.validation` annotations.
76+
Here is a quick overview:
77+
|Annotation|Function|Applicable to|
78+
|---|---|---|
79+
|@NotNull|Can't be null|-|
80+
|@NotEmpty|Can't be empty or null|String, Collection, Map, Array|
81+
|@NotBlank|Trimmed string can't be empty|Text values|
82+
|@Min|Value can't be lower than parameter|-|
83+
|@Max|Value can't be greater than parameter|-|
84+
|@Size|Size of field has to be within the given parameter|String, Collection, Map, Array|
85+
##### Annotations
86+
Every DTO has to be annotated with `@Data`, `@NoArgsConstructor` and `@AllArgsConstructor`. (Please also in this order)
87+
Example:
88+
```java
89+
@Data
90+
@NoArgsConstructor
91+
@AllArgsConstructor
92+
public class CreateTaskRequestDTO {
93+
```
94+
##### Class name
95+
The DTO class name has to be the action what it does and if it is a
96+
request DTO `Request` suffix or a response dto a `Response` suffix. At least the name has to end with the suffix `DTO`.
97+
Example:
98+
```java
99+
public class GetAllSubjectsResponseDTO {
100+
```
101+
##### Conversions
102+
If you have to convert a DTO you are free to add a method in this class so that the code stays clean
103+
##### DTOModel
104+
Sometimes you have to create a new class because you return e.g. a List. Just create a new Class but add the suffix `Model`.
105+
Example:
106+
```java
107+
public class CheckMultipleChoiceSolutionsResponseDTO {
108+
@NotNull @Size(min = 1)
109+
private List<CheckMultipleChoiceSolutionsResponseDTOModel> solutions;
110+
```
111+
#### Particularities
112+
##### Class annotations
113+
Every endpoint class needs the annotation `@Timed` and `@RestController`.
114+
Example:
115+
```java
116+
@Timed
117+
@RestController
118+
public class TaskEndpoint {
119+
```
120+
##### Mappings
121+
In the endpoint you have use the specific mapping and not ~~`@RequestMapping`~~.
122+
Example:
123+
```java
124+
@PostMapping("/task")
125+
public Object createTask(....
126+
```
127+
##### Returning
128+
If you call a method in a controller it returns a `ControllerResult`.
129+
You have to call the method `.getHttpResponse();` to get a correct *HttpResponse*.
130+
The method has to return `Object`.
131+
Example:
132+
```java
133+
public Object deleteTask(@PathVariable @Min(1) int taskId) {
134+
return this.taskController.deleteTask(taskId).getHttpResponse();
135+
}
136+
```
137+
##### Pathvariables
138+
Pathvariables have to be written in the route with Braces `{}` and
139+
named equal as parameter in the method and have to be annotated with `@PathVariable`.
140+
Example:
141+
```java
142+
@GetMapping("/task/{taskId}")
143+
public Object getTask(@PathVariable int taskId) {
144+
```
145+
##### Requestbodies
146+
Requestbodies have to be tagged with `@RequestBody` and `@Valid` and have to be named `dto`
147+
Example:
148+
```java
149+
public Object createTask(@RequestBody @Valid CreateTaskRequestDTO dto) {
150+
```
151+
---
152+
### Controller
153+
Controllers have to handle the access to the repository.
154+
The controllers have to get the data from the repository, check them and return them.
155+
Controllers have to end with the suffix `Controller`.
156+
**Is is important to access the repository as few as possible, but you should also check if something at all exists!**
157+
158+
#### Particularities
159+
160+
##### Class annotations
161+
162+
Every endpoint class needs the annotation `@Component`.
163+
164+
Example:
165+
```java
166+
@Component
167+
public class TaskController {
168+
```
169+
##### Returning
170+
Every method in Controller has to return an instance of `ControllerResult`.
171+
Example:
172+
```java
173+
public ControllerResult<TaskModel> createTask(CreateTaskRequestDTO dto) {
174+
```
175+
##### Repositories
176+
Most of the Controller need repositories. They have to get annotated with `@Autowired`.
177+
Is is forbidden to access a different repository as what it isn't meant for.
178+
Instead of accessing a different repository you can access the controller of this repository.
179+
#### ControllerResult
180+
Every method in a Controller has to return a `ControllerResult` instance.
181+
On the One Hand you can hand over a Result on the other hand if something went wrong an Error.
182+
`ControllerResult` has several methods to check if there is an Error, Result, etc. to check if e.g. an Error occurred
183+
while accessing another Controller. If this happens you can call `ControllerResult.ret` and insert the previous `ControllerResult`.
184+
Example:
185+
```java
186+
ControllerResult<SolutionModel> solutionResult = this.solutionController.getSolution(taskId);
187+
if (solutionResult.isResultNotPresent()) return ControllerResult.ret(solutionResult);
188+
```
189+
##### NAME_KEY
190+
Every Controller has to `import static` a String `NAME_KEY` in the class `Constants`. It is used to identify where an Error occurred.
191+
Example:
192+
```java
193+
import static de.themorpheus.edu.taskservice.util.Constants.Task.NAME_KEY;
194+
```
195+
##### Errors
196+
If you e.g. check something that returned from a query of a database but theres no Result you have to throw an Error.
197+
To identify the error, as mentioned above, you also have to return as extra of the error the `NAME_KEY` of your Controller.
198+
Example:
199+
```java
200+
Optional<TaskModel> optionalTask = this.taskRepository.getTaskByTaskId(taskId);
201+
if (!optionalTask.isPresent()) return ControllerResult.of(Error.NOT_FOUND, NAME_KEY);
202+
```
203+
### Repositories
204+
Repositories are the imaginary database. Every Repository has to extend `JpaRepository`.
205+
You can write your own methods in this interface and they will be transformed to *SQL-Queries* by *JPA*.
206+
#### Optional
207+
If you just want to access one object you have to use `Optional`, because it is easy to check if your Result is Present.
208+
To access one object the method has to start with `find..`.
209+
Example:
210+
```java
211+
Optional<TaskModel> getTaskByTaskId(int taskId);
212+
```
213+
#### Lists
214+
The Repository can return Lists. You just have to create a method which starts with `findAll..`.
215+
The returning list can't be null, but empty.
216+
Example:
217+
```java
218+
List<TaskModel> findAllByAuthorId(UUID authorId);
219+
```
220+
#### Foreign Keys
221+
If you have to use foreign keys in the Repository if you can. But there's a special if you write a query using the
222+
foreign key. If you use a foreign key you have to use the name like the ID in the foreign key but use the Model.
223+
Example: ``TaskModel``
224+
```java
225+
@Id
226+
@GeneratedValue(strategy = GenerationType.IDENTITY)
227+
private int taskId;
228+
```
229+
Example: ``SolutionRepository``
230+
```java
231+
@Repository
232+
public interface SolutionRepository extends JpaRepository<SolutionModel, Integer> {
233+
Optional<SolutionModel> findSolutionModelBybTaskId(TaskModel taskId);
234+
```
235+
So in the query and the variable is named ``taskId``, but actually there is a `TaskModel` handed over.
236+
#### Particularities
237+
Every Repository needs the ``@Repository`` annotation.
238+
Example:
239+
```java
240+
@Repository
241+
public interface TaskRepository extends JpaRepository<TaskModel, Integer> {
242+
```
243+
### Model
244+
Models are the entries in the associated repository.
245+
#### Foreign Keys
246+
As same as in the repository it is necessary to use foreign keys. You can reference foreign keys by using the
247+
specific *Model* as field declaration.
248+
But if you use foreign keys you have to tag them with `@OneToOne`, `@ManyToOne` or `@ManyToMany`.
249+
These annotations tell hibernate in which relation they are.
250+
Example:
251+
```java
252+
public class TaskModel {
253+
...
254+
@ManyToOne
255+
private LectureModel lectureId;
256+
```
257+
`@ManyToOne` because **many** *Tasks* can have **one** *Lecture* as a foreign key.
258+
Another Example:
259+
````java
260+
public class SolutionModel {
261+
...
262+
@OneToOne
263+
private TaskModel taskId;
264+
````
265+
``@OneToOne`` because **one** *Solution* can have only **one** *Task* as a foreign key.
266+
#### Particularities
267+
##### Annotations
268+
Every Model has to be annotated with a bunch of annotations:
269+
````java
270+
@Data
271+
@NoArgsConstructor
272+
@AllArgsConstructor
273+
@Entity
274+
@Table
275+
````
276+
##### Conversions
277+
If you have to convert a Model in e.g. a [DTO](#dtos) you are free to add a method in the model
278+
class so that the code stays clean. Please place them at the bottom of the file and give the methods a clear name.
279+
280+
Example:
281+
````java
282+
public class SimpleEquationSolutionModel {
283+
...
284+
public CreateSimpleEquationSolutionResponseDTOModel toCreateResponseDTOModel() {
285+
return new CreateSimpleEquationSolutionResponseDTOModel(this.simpleEquationSolutionId, this.step);
286+
}
287+
}
288+
````
289+
## Checkstyle
290+
Checkstyle is a maven plugin which detects any code style violations. You have to fix them because the are necessary
291+
to merge into experimental.
292+
If you execute maven install checkstyle will be triggered automatically. The errors describe pretty good where your
293+
error is thrown and why.
294+
---
295+
#### [Back](./README.md)

README.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
# E-Edu Task Microservice
22

33
This projects contains the source code for the task microservice which
4-
is responsible for everything related to tasks in the E-Edu system.
4+
is responsible for everything related to tasks in the [E-Edu System](https://github.com/E-Edu).
5+
6+
## Contribute
7+
8+
You want to contribute to this project? Great!
9+
10+
[Concept and Documentation](https://github.com/E-Edu/concept)<br>
11+
[Task Ms Conventions](./CONTRIBUTING.md)<br>
12+
[Git Workflow (German)](https://github.com/E-Edu/general/blob/master/guides/conventions.md)<br>
13+
14+
## Issues
15+
16+
##### Any Bugs, Feature Request or Improvements?
17+
18+
[Write us an issue!](https://github.com/E-Edu/task/issues/new/choose)
519

620
## How to build
721
Run:
@@ -14,14 +28,6 @@ Run:
1428
or in detached mode:
1529
```sudo docker-compose up -d```
1630

17-
## Contribute
18-
19-
You want to contribute to this project? Great!
20-
21-
[Drafts & Documentation](https://github.com/E-Edu/draft-documents)<br>
22-
[Git Workflow (German)](https://github.com/E-Edu/general/blob/master/guides/conventions.md)<br>
23-
[Code Style (German)](https://github.com/E-Edu/general/blob/master/guides/conventions.md#code-style)
24-
2531
## Sentry error report
2632

2733
By default this project **won't** send any data to our central Sentry instance!

0 commit comments

Comments
 (0)