Doku
continuous-integration/drone/push Build is passing Details

This commit is contained in:
qvalentin 2022-05-22 13:50:11 +02:00
parent 1e30d81231
commit b609fac559
Signed by: qvalentin
GPG Key ID: C979FA1EAFCABF1C
10 changed files with 237 additions and 12 deletions

View File

@ -27,7 +27,6 @@ public class CategoryRepository {
return getByName(name) return getByName(name)
.orElseThrow(() -> new CategroyDoesNotExist("A Category with name " + name + " does not exits. You must create it first.")) .orElseThrow(() -> new CategroyDoesNotExist("A Category with name " + name + " does not exits. You must create it first."))
.getId(); .getId();
} }
public Optional<Category> getById(CategoryId id) { public Optional<Category> getById(CategoryId id) {

View File

@ -66,12 +66,34 @@ Allgemeine Anmerkungen:
[Was macht die Applikation? Wie funktioniert sie? Welches Problem löst [Was macht die Applikation? Wie funktioniert sie? Welches Problem löst
sie/welchen Zweck hat sie?] sie/welchen Zweck hat sie?]
Die Anwendung ist zur organisierten Abspeicherung von Links bzw. URLs gedacht.
Diese können durch die Anwendung abgespeichert werden.
Zur besseren Organisation ist es außerdem möglich, Kategorien anzulegen und die Links diesen zuzuordnen, wie beispielsweise 'Libary', 'Selfhostable', 'Dienst' usw.
Zusätzlich kann die Anwendung auch Tags zu Links hinzufügen können, wenn die Implementation Webseite beispielsweise bereits kennt (z.B. 'Github').
Eigene Regeln für Tags können auch angelegt werden, sie werden durch einen Regulären Ausdruck beschrieben.
Der User, welcher einen Eintrag angelegt hat wird auch gespeichert.
TODO: Die Anwendung soll Persistenz enthalten sowie verschiedene Methoden zum Durchsuchen (nach Kategorie, User) und Exportieren der Daten.
*** Wie startet man die Applikation? *** Wie startet man die Applikation?
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: wie-startet-man-die-applikation :CUSTOM_ID: wie-startet-man-die-applikation
:END: :END:
[Wie startet man die Applikation? Welche Voraussetzungen werden [Wie startet man die Applikation? Welche Voraussetzungen werden
benötigt? Schritt-für-Schritt-Anleitung] benötigt? Schritt-für-Schritt-Anleitung]
**** Voraussetzungen:
- Java 17
- Maven
**** Compilieren
#+begin_src shell
mvn clean install
#+end_src
**** Ausführen
#+begin_src
java -jar 0-Plugin/target/0-Plugin-1.0-SNAPSHOT-jar-with-dependencies.jar [PARAMETER]
#+end_src
*** Wie testet man die Applikation? *** Wie testet man die Applikation?
:PROPERTIES: :PROPERTIES:
@ -80,6 +102,9 @@ benötigt? Schritt-für-Schritt-Anleitung]
[Wie testet man die Applikation? Welche Voraussetzungen werden benötigt? [Wie testet man die Applikation? Welche Voraussetzungen werden benötigt?
Schritt-für-Schritt-Anleitung] Schritt-für-Schritt-Anleitung]
#+begin_src
mvn clean test
#+end_src
* Kapitel 2: Clean Architecture * Kapitel 2: Clean Architecture
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: kapitel-2-clean-architecture :CUSTOM_ID: kapitel-2-clean-architecture
@ -90,6 +115,20 @@ Schritt-für-Schritt-Anleitung]
:END: :END:
[allgemeine Beschreibung der Clean Architecture in eigenen Worten] [allgemeine Beschreibung der Clean Architecture in eigenen Worten]
Die Clean Architecture ist eine Software Architektur, die es ermöglichen soll langlebige Systeme zu entwickeln.
Dazu wird der eigentliche Zweck einer Anwendung von möglichst vielen technischen Details getrennt.
Auf diese Weise soll ein Kern der Anwendung entstehen, welcher beispielsweise die Businessregeln enthält und bis auf die Wahl der Programmiersprache (für Langlebigkeit von Sprachen siehe bspw. Java) keine Abhängigkeiten zu technischen Entscheidungen hat.
Konkretere technische Details, wie beispielsweise die Wahl einer Datenbank oder ob für die Benutzerschnittstelle ein CLI oder ein Webserver genutzt wird, werden an den Rand der Anwendung gedrängt und nur durch Zwischenschichten mit dem Kern verbunden.
Die konkreten Schichten sind (von langlebig nach kurzlebig und von wenigen (keinen) nach vielen Abhängigkeiten sortiert):
- Abstraction Code
- Domain Code
- Application Code
- Adapters
- Plugins
Durch die Dependency Rule wird sichergestellt, dass Abhängigkeiten immer von außen nach innen sind, und somit eine äußere Schicht ausgetauscht werden könnte, ohne, dass die inneren Schichten angepasst werden müssten.
*** Analyse der Dependency Rule *** Analyse der Dependency Rule
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: analyse-der-dependency-rule :CUSTOM_ID: analyse-der-dependency-rule
@ -99,14 +138,30 @@ Dependency Rule verletzt); jeweils UML der Klasse und Analyse der
Abhängigkeiten in beide Richtungen (d.h., von wem hängt die Klasse ab Abhängigkeiten in beide Richtungen (d.h., von wem hängt die Klasse ab
und wer hängt von der Klasse ab) in Bezug auf die Dependency Rule] und wer hängt von der Klasse ab) in Bezug auf die Dependency Rule]
Da die Abhängigkeiten zwischen den einzelnen Schichten durch Maven restriktiv kontrolliert werden gibt es kein negativ Beispiel.
**** Positiv-Beispiel: Dependency Rule **** Positiv-Beispiel: Dependency Rule
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: positiv-beispiel-dependency-rule :CUSTOM_ID: positiv-beispiel-dependency-rule
:END: :END:
**** Negativ-Beispiel: Dependency Rule
:PROPERTIES: [[./uml/LinkCliAdapter.png]]
:CUSTOM_ID: negativ-beispiel-dependency-rule
:END: [[./uml/LinkCliAdapterClasses.png]]
Die Klasse LinkCliAdapter ist selbst abhängig von einigen Value Object der Domäne (LinkUrl, UserName, CategoryName) und dem LinkUseCase sowie seinem speziellen Format LinkDto aus der Application Schicht.
Abhängig von der Klasse LinkCliAdapter ist die Klasse LinkCommands aus der Plugin Schicht.
**** 2. Positiv-Beispiel: Dependency Rule
[[./uml/CSVCategoryPersistenceAdapter.png]]
[[./uml/CSVCategoryPersistenceAdapterClasses.png]]
Die Klasse CSVCategoryPersistenceAdapter ist abhängig von dem Domänen Entity Category und Implementiert das Interface der Domäne PersistenceAdapter<Category>. Außerdem ist es abhängig vom Persitenz Entity CategorEntity, das in der Adapter Schicht definiert ist und dem Interface GenericDAO<CategorEntity> aus der Adapter Schicht.
In der Plugin Schicht ist mit dem GenericCSVDAO<T> eine Klasse gegeben, die dieses Interface implementiert.
Das Domänen Repository CategoryRepository ist abhängig von einem PersistenceAdapter (Interface), welche das CSVCategoryPersistenceAdapter implementiert.
Somit ist das Repository der Domäne zur Compile Zeit nicht abhängig von dem CSVCategoryPersistenceAdapter des Adapter sondern nur zur Runtime, da im Adapter eine Implementation des benötigten Interfaces liegt.
*** *Analyse der Schichten* *** *Analyse der Schichten*
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: analyse-der-schichten :CUSTOM_ID: analyse-der-schichten
@ -116,15 +171,27 @@ Clean-Architecture: jeweils UML der Klasse (ggf. auch zusammenspielenden
Klassen), Beschreibung der Aufgabe, Einordnung mit Begründung in die Klassen), Beschreibung der Aufgabe, Einordnung mit Begründung in die
Clean-Architecture] Clean-Architecture]
**** Schicht: [Name] **** Schicht: Domain
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: schicht-name :CUSTOM_ID: schicht-name
:END: :END:
**** Schicht: [Name]
[[./uml/LinkUrl.png]]
Die Klasse LinkUrl ist ein Klasse, welche einen zentralen Bestandteil der zu speichernden Daten repräsentiert: Die URL eines Links.
Damit ist sie Teil der Domäne, da es sich direkt um die Businessregeln der zu verarbeiten Daten handelt.
So stellt sie beispielsweise durch die Verwendung der Java Klasse URL sicher, dass die Url ein valides Format hat und somit die Domänenregeln erfüllt.
**** Schicht: Plugin
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: schicht-name-1 :CUSTOM_ID: schicht-name-1
:END: :END:
[[./uml/GitHubTagMatcher.png]]
Die Klasse GitHubTagMatcher ist eine Implementation der des Interface TagMatcher und dafür verantwortlich festzustellen, ob ein Link auf eine GitHub Url verweist und im positiv Fall zu versuchen über die GitHub Repository-Api zusätzliche Informationen über das verlinkte Repository zu erhalten.
Die Klasse ist Teil der Plugin Schicht, da die Interaktion mit der GitHub Repository-Rest-Api eindeutig eine Abhängigkeiten zu einem fremden Bestandteil darstellt und solche Abhängigkeiten an den Rand der Anwendung gedrängt werden sollten.
* Kapitel 3: SOLID * Kapitel 3: SOLID
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: kapitel-3-solid :CUSTOM_ID: kapitel-3-solid
@ -296,11 +363,11 @@ zusätzlich jeweils UML Diagramm der Klasse]
[4 Beispiele für die Ubiquitous Language; jeweils Bezeichung, Bedeutung [4 Beispiele für die Ubiquitous Language; jeweils Bezeichung, Bedeutung
und kurze Begründung, warum es zur Ubiquitous Language gehört] und kurze Begründung, warum es zur Ubiquitous Language gehört]
| Bezeichung | Bedeutung | Begründung | | Bezeichung | Bedeutung | Begründung |
| Link | Steht für eine eindeutige URL, die von der Anwendung gespeichert werden soll | Gehört zur Ubiquitous-Laguage, weil Link außerhalb der Domäne der Anwendung auch anders verwendet werden kann | | Link | Steht für eine eindeutige URL, die von der Anwendung gespeichert werden soll | Gehört zur Ubiquitous-Laguage, weil Link außerhalb der Domäne der Anwendung auch anders verwendet werden kann |
| Category | Steht für eine Kategorie, die einem Link zugeordnet werden kann | Gehört zur Ubiquitous-Laguage, weil nur im Kontext der Anwendung klar ist, wofür die Kategorien verwendet werden | | Category | Steht für eine Kategorie, die einem Link zugeordnet werden kann | Gehört zur Ubiquitous-Laguage, weil nur im Kontext der Anwendung klar ist, wofür die Kategorien verwendet werden |
| Tag | Steht für einen Tag der automatisch bestimmten Link-Typen zugeordnet wird | Gehört zur Ubiquitous-Laguage, weil nur im Kontext der Anwendung klar ist, was genau getaggt wird und wie dies geschieht | | Tag | Steht für einen Tag der automatisch bestimmten Link-Typen zugeordnet wird | Gehört zur Ubiquitous-Laguage, weil nur im Kontext der Anwendung klar ist, was genau getaggt wird und wie dies geschieht |
| | | | | *TagMatcher | Steht für eine spezielle Implementation des Interfaces TagMatcher (z.B. GitHubTagMatcher), das dafür sorgt, dass einem Link ein Tag zugewiesen werden kann | Gehört zur Ubiquitous-Laguage, weil nur im Kontext der Anwendung klar ist, auf welche Tag sich die Funktion bezieht und was deren Bedeutung ist. |
*** Entities *** Entities
:PROPERTIES: :PROPERTIES:

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<Diagram>
<ID>JAVA</ID>
<OriginalElement>cli.link.LinkCliAdapter</OriginalElement>
<nodes>
<node x="187.6399371069182" y="131.0">category.CategoryName</node>
<node x="202.25" y="315.0">cli.link.LinkCliAdapter</node>
<node x="19.075471698113148" y="0.0">link.LinkUrl</node>
<node x="0.0" y="131.0">link.LinkDto</node>
<node x="57.90880503144646" y="224.0">link.LinkUseCase</node>
<node x="198.75" y="394.0">cli.link.LinkCommands</node>
<node x="139.07547169811312" y="0.0">user.Username</node>
</nodes>
<notes />
<edges>
<edge source="cli.link.LinkCommands" target="cli.link.LinkCliAdapter" relationship="DEPENDENCY">
<point x="-39.5" y="-14.5" />
<point x="238.25" y="369.0" />
<point x="240.0" y="369.0" />
<point x="-37.75" y="14.5" />
</edge>
<edge source="cli.link.LinkCliAdapter" target="link.LinkUseCase" relationship="DEPENDENCY">
<point x="-50.33333333333334" y="-14.5" />
<point x="227.41666666666666" y="294.0" />
<point x="69.78380503144646" y="294.0" />
<point x="69.78380503144646" y="274.0" />
<point x="92.15880503144646" y="274.0" />
<point x="-34.25" y="14.5" />
</edge>
<edge source="link.LinkDto" target="user.Username" relationship="TO_ONE">
<point x="-26.0" y="-14.5" />
<point x="26.0" y="110.0" />
<point x="47.0" y="110.0" />
<point x="47.0" y="60.0" />
<point x="159.2421383647798" y="60.0" />
<point x="-40.33333333333334" y="14.5" />
</edge>
<edge source="cli.link.LinkCliAdapter" target="user.Username" relationship="CREATE">
<point x="50.33333333333334" y="-14.5" />
<point x="328.0833333333333" y="294.0" />
<point x="372.52122641509436" y="294.0" />
<point x="372.52122641509436" y="284.0" />
<point x="377.52122641509436" y="284.0" />
<point x="377.52122641509436" y="60.0" />
<point x="239.9088050314465" y="60.0" />
<point x="40.33333333333337" y="14.5" />
</edge>
<edge source="link.LinkUseCase" target="category.CategoryName" relationship="DEPENDENCY">
<point x="34.25" y="-14.5" />
<point x="160.65880503144646" y="202.0" />
<point x="163.65880503144646" y="202.0" />
<point x="163.65880503144646" y="192.0" />
<point x="264.1399371069182" y="192.0" />
<point x="0.0" y="14.5" />
</edge>
<edge source="link.LinkDto" target="link.LinkUrl" relationship="TO_ONE">
<point x="-26.0" y="-14.5" />
<point x="26.0" y="110.0" />
<point x="47.0" y="110.0" />
<point x="47.0" y="60.0" />
<point x="35.742138364779805" y="60.0" />
<point x="-33.33333333333334" y="14.5" />
</edge>
<edge source="cli.link.LinkCliAdapter" target="link.LinkDto" relationship="DEPENDENCY">
<point x="-50.33333333333334" y="-14.5" />
<point x="227.41666666666666" y="294.0" />
<point x="69.78380503144646" y="294.0" />
<point x="69.78380503144646" y="274.0" />
<point x="18.625" y="274.0" />
<point x="18.625" y="202.0" />
<point x="26.0" y="202.0" />
<point x="-26.0" y="14.5" />
</edge>
<edge source="cli.link.LinkCliAdapter" target="link.LinkUrl" relationship="CREATE">
<point x="50.33333333333334" y="-14.5" />
<point x="328.0833333333333" y="294.0" />
<point x="372.52122641509436" y="294.0" />
<point x="372.52122641509436" y="284.0" />
<point x="351.1399371069182" y="284.0" />
<point x="351.1399371069182" y="70.0" />
<point x="102.40880503144649" y="70.0" />
<point x="33.33333333333334" y="14.5" />
</edge>
<edge source="link.LinkDto" target="link.LinkUrl" relationship="DEPENDENCY">
<point x="26.0" y="-14.5" />
<point x="78.0" y="110.0" />
<point x="75.13128930817612" y="110.0" />
<point x="75.13128930817612" y="90.0" />
<point x="93.38128930817612" y="90.0" />
<point x="93.38128930817612" y="50.0" />
<point x="69.07547169811315" y="50.0" />
<point x="0.0" y="14.5" />
</edge>
<edge source="link.LinkUseCase" target="link.LinkUrl" relationship="DEPENDENCY">
<point x="34.25" y="-14.5" />
<point x="160.65880503144646" y="202.0" />
<point x="163.65880503144646" y="202.0" />
<point x="163.65880503144646" y="182.0" />
<point x="132.63128930817612" y="182.0" />
<point x="132.63128930817612" y="80.0" />
<point x="93.38128930817612" y="80.0" />
<point x="93.38128930817612" y="50.0" />
<point x="69.07547169811315" y="50.0" />
<point x="0.0" y="14.5" />
</edge>
<edge source="link.LinkDto" target="user.Username" relationship="DEPENDENCY">
<point x="26.0" y="-14.5" />
<point x="78.0" y="110.0" />
<point x="75.13128930817612" y="110.0" />
<point x="75.13128930817612" y="100.0" />
<point x="177.1399371069182" y="100.0" />
<point x="177.1399371069182" y="60.0" />
<point x="199.57547169811312" y="60.0" />
<point x="0.0" y="14.5" />
</edge>
<edge source="cli.link.LinkCommands" target="cli.link.LinkCliAdapter" relationship="TO_ONE">
<point x="39.5" y="-14.5" />
<point x="317.25" y="369.0" />
<point x="315.5" y="369.0" />
<point x="37.75" y="14.5" />
</edge>
<edge source="cli.link.LinkCliAdapter" target="category.CategoryName" relationship="DEPENDENCY">
<point x="-50.33333333333334" y="-14.5" />
<point x="227.41666666666666" y="294.0" />
<point x="69.78380503144646" y="294.0" />
<point x="69.78380503144646" y="274.0" />
<point x="264.1399371069182" y="274.0" />
<point x="0.0" y="14.5" />
</edge>
<edge source="link.LinkUseCase" target="user.Username" relationship="DEPENDENCY">
<point x="34.25" y="-14.5" />
<point x="160.65880503144646" y="202.0" />
<point x="163.65880503144646" y="202.0" />
<point x="163.65880503144646" y="182.0" />
<point x="177.1399371069182" y="182.0" />
<point x="177.1399371069182" y="60.0" />
<point x="199.57547169811312" y="60.0" />
<point x="0.0" y="14.5" />
</edge>
<edge source="link.LinkUseCase" target="link.LinkDto" relationship="CREATE">
<point x="-34.25" y="-14.5" />
<point x="92.15880503144646" y="202.0" />
<point x="78.0" y="202.0" />
<point x="26.0" y="14.5" />
</edge>
<edge source="cli.link.LinkCliAdapter" target="link.LinkUseCase" relationship="TO_ONE">
<point x="0.0" y="-14.5" />
<point x="277.75" y="284.0" />
<point x="160.65880503144646" y="284.0" />
<point x="34.25" y="14.5" />
</edge>
</edges>
<settings layout="Hierarchic" zoom="1.0" showDependencies="true" x="189.0" y="215.5" />
<SelectedNodes />
<Categories />
<SCOPE>All</SCOPE>
<VISIBILITY>private</VISIBILITY>
</Diagram>

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB