Merge branch '110-entwicklungsumgebung-chapter' into 'master'

Resolve "Entwicklungsumgebung Chapter"

Closes #110

See merge request marcel.schwarz/2020ss-qbc-geofence-timetracking!105
This commit is contained in:
Marcel Schwarz 2020-06-09 13:58:42 +00:00
commit 1d24f210f1
2 changed files with 96 additions and 1 deletions

View File

@ -24,6 +24,63 @@
\usepackage{wrapfig}
\newcommand*{\source}[1]{\par\raggedleft\footnotesize Quelle:~#1} %source command fuer bildunterschriften
% Code
\usepackage{listings}
\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{gray}{rgb}{0.5,0.5,0.5}
\definecolor{mauve}{rgb}{0.58,0,0.82}
\lstset{literate=%
{Ö}{{\"O}}1
{Ä}{{\"A}}1
{Ü}{{\"U}}1
{ß}{{\ss}}1
{ü}{{\"u}}1
{ä}{{\"a}}1
{ö}{{\"o}}1
}
\lstset{
frame=tblr,
frameround=tttt,
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle={\small\ttfamily},
numbers=none,
numberstyle=\tiny\color{gray},
keywordstyle=\color{blue},
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
breaklines=true,
breakatwhitespace=true,
tabsize=3,
xleftmargin=1.0ex,
xrightmargin=1.0ex
}
\lstdefinelanguage{docker}{
keywords={FROM, RUN, COPY, ADD, ENTRYPOINT, CMD, ENV, ARG, WORKDIR, EXPOSE, LABEL, USER, VOLUME, STOPSIGNAL, ONBUILD, MAINTAINER},
keywordstyle=\color{blue}\bfseries,
identifierstyle=\color{black},
sensitive=false,
comment=[l]{\#},
commentstyle=\color{purple}\ttfamily,
stringstyle=\color{red}\ttfamily,
morestring=[b]',
morestring=[b]",
}
\lstdefinelanguage{docker-compose}{
keywords={VERSION, SERVICES, CONTAINER\_NAME, BUILD, CONTEXT, PORTS, DEPENDS\_ON, RESTART, VOLUMES, ENVIRONMENT},
keywordstyle=\color{blue}\bfseries,
identifierstyle=\color{black},
sensitive=false,
comment=[l]{\#},
commentstyle=\color{purple}\ttfamily,
stringstyle=\color{red}\ttfamily,
morestring=[b]',
morestring=[b]",
}
\usepackage{setspace}
\setstretch{1.2} %Zeilenabstand
\setlength\parindent{0pt} %keine Paragrapheneinrueckung

View File

@ -1,9 +1,47 @@
\chapter{Entwicklungsumgebung}
Da wir uns für eine Full-Stack Application entschieden haben, war es wichtig, gleich zu Beginn die Entwicklungsumgebung so robust wie möglich zu gestalten. Weiter sollte das ganze Setup einfach unter Versionskontrolle gestellt werden können, um überall reproduzierbar zu sein.
\section{Versionsverwaltung}
Für die Versionsverwaltung haben wir das aktuell am weitesten verbreitete Tool Git benutzt. Dies war notwendig, damit wir unabhängig voneinander arbeiten können. Das Repository ist öffentlich auf der Plattform GitLab einsehbar. Die Adresse lautet \url{https://gitlab.com/marcel.schwarz/2020ss-qbc-geofence-timetracking}
\subsection{GitLab}
Die Entscheidung für GitLab fiel aber nicht ohne Grund. GitLab bietet auch sehr ausgeprägte Projektplanungsmöglichkeiten, die die Kollaboration sehr vereinfachen. Dazu zählen:
\begin{itemize}
\item Issues. In den Issues werden alle Aufgaben für das Projekt abgelegt, die noch erledigt werden müssen oder eine weitere Betrachtung benötigen. Auch Bugfixes werden dort angelegt.
\item Issues werden in Merge Requests bearbeitet. Diese Merge Requests können genutzt werden, um über Code zu diskutieren und gegebenenfalls zu verbessern.
\item Code Ownership. Da wir die Teile der Anwendung nach Personen aufgeteilt haben, gibt es für jeden Teil der Anwendung mindestens ein Teammitglied, welches sich besonders gut mit diesen Themen auskennt. Diese Teammitglieder haben dadurch auch die Codeownership für diesen Teil des Codes.
\item Merge Request Approval. Wenn ein Issue mehrere Teile der Anwendung ändert, muss der jeweilige Codeowner dieses Teils dem Merge Request ebenfalls zustimmen. Ein Beispiel wäre hier die Implementation: "ein Datum im Frontend ändern", was aber zusätzlich die Anpassung des Datumsformates im Backend erfordert. Bei diesem Merge Request muss dann sowohl ein Codeowner des Frontends als auch des Backends zustimmen. Diese zusätzliche Sicherheitsschicht dient der Stabilität des Master Branches und der allgemeinen Codequalität.
\end{itemize}
\subsection{Umgang mit Issues}
Die Issues sind die komplette Dokumentation der erledigten Aufgaben während des Projekts. In ihnen können alle Informationen abgelegt werden, die relevant sind. Beispiele sind hier Bugfixes, Features aber auch Definitionen von Design und Farbschema, die die Zustimmung mehrerer Gruppenmitglieder benötigen. Auch API Definitionen und Alignment-Meetings gehören bei uns dazu.
Der Lebenszyklus eines Issues sieht wie folgt aus:
\begin{enumerate}
\item Issue wird angelegt. Entweder während eines anderen Sprints aus einer Idee heraus, oder bei der Sprintplanung.
\item Zuweisung und Schätzung. Das Issue wird spätestens beim nächsten Planning einem Sprint zugewiesen und erhält Labels die zeigen, welche Teile der Anwendung von diesem Issue betroffen sind. Zuletzt wird dem Issue noch ein Gewicht zugewiesen, welches die geschätzte Dauer in Stunden darstellt.
\item Assignment. Das Issue wird der Person zugewiesen, die es erledigen wird.
\item Merge Request. Es wird ein Merge Request zum Issue angelegt, welcher, wenn er akzeptiert wird, das Issue automatisch schließt.
\item Coding.
\item Review und Ausführung der Continuous Integration Pipeline.
\item Merge des Merge Requests und Schließen des Issues.
\end{enumerate}
\subsection{GitLab Wiki}
Das GitLab Wiki ist eine, auf der Markdown Sprache basierende, Möglichkeit, genauere Dokumentationen zu erstellen. Sollten beispielsweise Entscheidungen getroffen werden, die das ganze Team betreffen, werden diese hier abgelegt.
\subsection{Continuous Integration}
GitLab bietet die Möglichkeit Pipelines für Continuous Integration anzulegen. Diese Pipelines werden dann auf geteilten Maschinen (sog. Runners) der GitLab eigenen Infrastruktur ausgeführt. Die Pipeline baut im Kontext eines Merge Requests die Codeteile, in denen Änderungen erfolgt sind, und validiert damit die Funktionalität auf einem sauberen System. Auch Unit- oder Integrationtests sowie Deployments könnten an dieser Stelle ausgeführt werden.
\section{Docker}
Um die Umgebung unserer Anwendung so homogen wie möglich zu halten, wurde schon von Anfang an auf Docker als Runntime gesetzt. Jeder Teil der Anwendung besitzt eine Dockerfile, die den Code zu einem Executable zusammenbaut. Alle Teile außer Android besitzen zusätzlich noch eine Runtime-Umgebung in Docker. Die Dockerfiles sehen wie folgt aus:
\lstinputlisting[language=docker, caption=Dockerfile Backend]{../backend/Dockerfile}
\lstinputlisting[language=docker, caption=Dockerfile Frontend]{../frontend/Dockerfile}
\lstinputlisting[language=docker, caption=Dockerfile Android]{../android/Dockerfile}
Zu erwähnen sind noch einige Besonderheiten. Da wir ein Programm entwickeln, was sich mit Zeiterfassung beschäftigt, ist es wichtig im Backend die Zeitzone des Images zu setzen, da sonst immer die UTC Zeitzone als Standard angenommen wird. Selbiges gilt auch für die SQL Datenbank, welche mit MariaDB umgesetzt ist.
\section{Docker-Compose}
Um nun die ganze Applikation auszuführen, kommt ein Docker-Compose Setup zum Einsatz.
\lstinputlisting[language=docker-compose,caption=Docker-Compose]{../docker-compose.yml}
Es werden drei Services definiert: frontend, backend und db. Diese Dienste arbeiten zusammen und warten auf ihre jeweiligen Abhängigkeiten. Zudem wird das Frontend auf dem Port 8080 an die lokale Maschine gebunden und das Backend an Port 5000. Android ist hier nicht vertreten, da dies eine alleinstehende Anwendung ist. Dieses Setup funktioniert sowohl zu Entwicklungszwecken, als auch in unserem kleinen production deployment. Um den Stack bereitzustellen, muss nur der Konsolenbefehl
\begin{lstlisting}[language=bash]
docker-compose up --build -d
\end{lstlisting}
im Rootverzeichnis der Anwendung ausgeführt werden. Es sei noch zu erwähnen, dass beim allerersten Start die Datenbankinitialisierung etwas länger brauchen kann und deshalb das backend mehrere Versuche braucht, bis die Verbindung aufgebaut werden kann.
\section{Infrastruktur}
Die Infrastruktur, auf dem die Anwendung zur Zeit bereitgestellt ist, ist ein kleiner Linux Server bei Strato. Dieser Server hat ebenfalls eine Docker-Compose Installation und läuft auf Ubuntu 20.04 LTS. Gestartet wird es dann exakt gleich, wie im obigen Abschnitt erklärt. Natürlich ist Docker-Compose kein Deployment, welches in Produktion verwendet werden sollte, aber es reicht aktuell für unsere Zwecke aus. Nichts desto trotz ist die Anwendung aber auf eine sehr viel größere Skalierung bestens vorbereitet. Durch die Containerisierung ist unsere Anwendung komplett entkoppelt und könnte somit unabhängig skalieren. Einzig die SQL Datenbank müsste als Container entfernt werden und in ein eigenes Deployment verschoben werden.