bla
This commit is contained in:
@@ -3,22 +3,31 @@
|
||||
|
||||
|
||||
\chapter{Sicherheit gewinnen, ohne den Code zu verstehen}
|
||||
Wenn Änderungen an einer Software durchgeführt werden, ist es von hoher Bedeutung, die Sicherheit zu haben, dass danach weiterhin alles funktioniert.
|
||||
Auch die erfahrensten Entwickler machen hin und wieder Fehler. Fehler sind menschlich.\\
|
||||
Im folgenden werden einige Maßnahmen vorgestellt, die die Funktionstüchtigkeit von Softwareprojekten gewährleisten können. Insbesondere im Kontext von Refactoring spielt dies eine wichtige Rolle, da dort oft umfassende Änderungen vorgenommen werden. vgl. \citep[S. 323]{fiveLines.2023}
|
||||
\section{Sicherheit durch Tests}
|
||||
Die wohl einfachste Möglichkeit die Korrektheit von Software zu überprüfen, ist das Testen. In der Softwareentwicklung gibt es verschiedene Arten, wie richtiges Verhalten, einzelne Codeabschnitte oder ganze Produkte getestet werden können. Einige dieser Arten werden im folgenden aufgelistet.
|
||||
Die einfachste und verbreitetste Möglichkeit, die Korrektheit von etwas zu überprüfen, ist das Testen. Auch in der Softwareentwicklung ist dies der Fall. Allerdings ist es hier nicht so einfach, wie es sich anhört: Rund die Hälfte der Entwicklungszeit wird in das Testen investiert \citep[Introduction]{artoftesting.2011}.\\
|
||||
Es gibt viele verschiedene Arten, um Software zu testen, wobei diese sich auf unterschiedlichen Ebenen bewegen. Die folgende Auflistung soll einen Überblick darüber geben.
|
||||
\begin{itemize}
|
||||
\item \textbf{Unit Tests:} Testen von bla
|
||||
\item \textbf{Whiteboxtests:} Testen von bla
|
||||
\item \textbf{Unit-Tests} (oder Modultests) sind ein Prozess, bei dem die einzelnen Unterprogramme, Unterroutinen, Klassen oder Prozeduren in einem Programm getestet werden. Genauer gesagt wird der Test nicht zunächst auf das gesamte Programm konzentriert, sondern zuerst auf die kleineren Bausteine des Programms \citep[S. 85]{artoftesting.2011}.
|
||||
\item \textbf{Integrations Tests} sollen das Zusammenspiel von einzelnen Modulen, aus dem vorherigen Schritt, testen. Oft ist es der Fall, dass Integrations Tests nicht seperat durchgeführt werden, sondern die Stellen durch umfangreichere Unit-Tests beretis abgedeckt werden \citep[S. 117 f.]{artoftesting.2011}.
|
||||
\item \textbf{Funktionale Tests} sind ein Prozess, um Abweichungen zwischen dem Programm und der externen Spezifikation zu finden. Eine externe Spezifikation beschreibt das Verhalten des Programms aus der Sicht des Endbenutzers. Diese Tests werden normalerweise als Black-Box-Test durchgeführt, da das interne Verhalten des Codes in den vorherigen Schritten überprüft wurde. \citep[S. 119]{artoftesting.2011}
|
||||
\end{itemize}
|
||||
\section{Sicherheit durch Handwerkskunst}
|
||||
Diese Liste ist unvollständig, da nur Test-Arten gelistet sind, die den Code direkt betreffen. Es gibt zusätlich noch \textbf{System Tests}, \textbf{Akzeptantz Tests} und \textbf{Installations Tests}. Diese zielen eine höhere Ebene an und sollen die Software als ganzes Testen um festzustellen, ob die angeforderten Problemstellungen des Kunden richtig erfüllt werden und somit z.B.: Missverständnisse bei den Anforderungen ausgeschlossen werden können.
|
||||
Es ist wichtig zu verstehen, dass diese Ebenen unabhänig voneinander laufen müssen. Funktionieren alle Unit-Tests ordnugnsgemäß, heißt das nicht, dass die Software insgesamt funktioniert, da z.B.: Klassen falsch verwendet werden können.
|
||||
\textit{„[Außerdem bleibt immer] das Risko, dass unsere Tests genau die Stelle, an der ein Fehler auftritt, nicht abdecken oder dass sie etwas anderes testen, als wir glauben.“} \citep[S. 323]{fiveLines.2023}
|
||||
\par
|
||||
Um den Zeitaufwand des Testens auf lange Sicht geringer zu halten, gibt es wie in \citep[S. 323]{fiveLines.2023} die Möglichkeit einige dieser Tests zu automatisieren.
|
||||
\par
|
||||
In der modernen Softwareentwicklung sind automatiserte Tests oft Teil einer „Continous Integration“. Dabei muss jeder Commit oder jeder Pull Request vorher definierte Aufgaben erfolgreich absolvieren. Dabei können Unit-Tests, Buildvorgänge \cite{CIMeyer.2014}
|
||||
\section{Sicherheit durch Werkzeuge}
|
||||
\lipsum[1] % Dummy text
|
||||
|
||||
\begin{wrapfigure}{r}{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=0.35\textwidth]{Bilder/screenshotWebstorm} % Replace with your image file
|
||||
\caption{Screenshot WebStorm Refactoring-Tools \cite{webstorm.2024}}
|
||||
\label{webstormRefactor}
|
||||
\end{wrapfigure}
|
||||
|
||||
\lipsum[2-4] % More dummy text
|
||||
Gerade für Refactorings bieten die meisten modernen Entwicklungsumgebungen verschiedenste Werkzeuge, die den Entwickler unterstützen sollen. In der nebenliegenden Abbildung \ref{webstormRefactor} ist ein Auszug aus den Refactoring-Tools
|
||||
\section{Sicherheit durch formale Verifikation}
|
||||
\section{Sicherheit durch Fehlertoleranz}
|
||||
153
Bestandteile/ungenutzteStruktur.tex
Normal file
153
Bestandteile/ungenutzteStruktur.tex
Normal file
@@ -0,0 +1,153 @@
|
||||
\chapter{Ungenutzte Strukturen im Code}
|
||||
Im letzten Kapitel sollen einige Spezialfälle untersucht werden, bei denen oft aus verschiedenen Gründen auf ein Refactoring Verzichtet wird.
|
||||
Gründe dafür können unter anderem Zeitmangel, fehlende Erfahrung oder gar Faulheit der Entwickler sein.
|
||||
|
||||
\section{Leerzeilen nutzen}
|
||||
Wenn im Code Leerzeilen verwendet werden, hat dies zumeist einen Grund.
|
||||
Programmierende grenzen dadurch Gruppierungen von Aufrufen, Variablen oder generell zusammengehörigen Codeteilen voneinander ab.
|
||||
Da Leerzeilen in kürzester Zeit eingefügt werden können und einen großen Effekt zur Lesbarkeit des Codes beitragen, werden diese fast immer benutzt.
|
||||
Dies ist auch ein Grund dafür, dass viele kleinere Refactorings nicht durchgeführt werden, da diese mehr Zeit in anspruch nehmen würden. \citep[S. 325]{fiveLines.2023}
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minted}{typescript}
|
||||
function login(username: string, password: string) {
|
||||
if (username !== "admin" || password !== "123") {
|
||||
throw new Error("Invalid credentials");
|
||||
}
|
||||
const loginUser = getUser(username)
|
||||
|
||||
userHistroy.push(loginUser);
|
||||
currentUser = loginUser;
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Loginmethode mit einer Leerzeile}
|
||||
\label{fig:LoginLeerzeile}
|
||||
\end{figure}\\
|
||||
Das Codebeispiel \ref{fig:LoginLeerzeile} zeigt eine stark vereinfachte Methode, um einen Login durchzuführen.
|
||||
In Zeile Nr. 6 wird die Überprüfung der Anmeldedaten und die annschließende Anfrage des Nutzers, von den weiteren Bestandteilen des Logins räumlich voneinander getrennt.
|
||||
Das durchzuführende Refactoring wirkt in diesem Fall fast trivial.
|
||||
Die beiden Bestandteile vor und nach der Leerzeile können nach \citep[S. 325]{fiveLines.2023} in eigene Methoden gezogen werden.
|
||||
Jediglich passende Funktions Namen müssen gewählt werden.
|
||||
Das folgende Ergebnis \ref{fig:LoginErgebnis} entsteht dadurch.
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minted}{typescript}
|
||||
function updateCurrentUser(loginUser: String) {
|
||||
userHistory.push(loginUser)
|
||||
currentUser = loginUser;
|
||||
}
|
||||
|
||||
function authenticateUser(username: String, password: string) {
|
||||
if (username !== "admin" || password !== "123") {
|
||||
throw new Error("Invalid credentials");
|
||||
}
|
||||
return getUser(username);
|
||||
}
|
||||
|
||||
function login(username: string, password: string) {
|
||||
const loginUser = authenticateUser(username, password);
|
||||
updateCurrentUser(loginUser);
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Loginmethode mit extrahierten Untermethoden}
|
||||
\label{fig:LoginErgebnis}
|
||||
\end{figure}
|
||||
\newpage
|
||||
Eine weiterer Punkt, an dem oft auf Leerzeilen zurückgegriffen wird, ist das Erstellen von Klassen.
|
||||
Dort werden oft zusammengehörende Felder gruppiert.
|
||||
Das folgende Codebeispiel \ref{fig:LeerzeileFelder} zeigt den Anfang einer Klasse für eine Nutzer Authentifizierung.
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minted}{typescript}
|
||||
class Authentication{
|
||||
private username: string;
|
||||
private password: string;
|
||||
|
||||
private timestamp: Date;
|
||||
//..
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Authentication Klasse mit einer Leerzeile}
|
||||
\label{fig:LeerzeileFelder}
|
||||
\end{figure}\\
|
||||
Hier kann an der 4. Zeile eine klare Einteilung zwischen den tatsächlichen Nutzerinformationen und weiteren zur Authentifizierung gehörenden Metadaten erkannt werden.
|
||||
Auch in diesem Fall ist das nach \citep[S. 326]{fiveLines.2023} durchzuführende Refactoring selbsterklärend.
|
||||
Der folgende Codeausschnitt \ref{fig:LeerzeileFelderErgebnis} zeigt ein mögliches Ergebnis.
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minted}{typescript}
|
||||
class UserCredentials{
|
||||
private username: string;
|
||||
private password: string;
|
||||
}
|
||||
|
||||
class Authentication{
|
||||
private timestamp: Date;
|
||||
//..
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Loginmethode mit einer Leerzeile}
|
||||
\label{fig:LeerzeileFelderErgebnis}
|
||||
\end{figure}\\
|
||||
\newpage
|
||||
\section{Doppelten Code zusammenführen}
|
||||
Es gibt immer wieder Situationen, in den zwei Methoden oder Klassen nahezu identisch sind, es aber trotzdem einen kleinen Unterschied gibt.
|
||||
In solchen Fällen wird oft auf das Refactoring verzichtet, da der Aufwand zu groß erscheint oder die Entwickler im Programmierfluss keine einfache Lösung finden den Code zusammenzuführen.\citep[S. 326 f.]{fiveLines.2023}\\
|
||||
Das folgende Beispiel zeigt zwei Klassen, die jeweils einen Fromatierer umsetzen.
|
||||
\begin{figure}[ht]
|
||||
\begin{subfigure}[t]{0.48\textwidth}
|
||||
\centering
|
||||
\begin{minipage}[t]{\linewidth}
|
||||
\begin{minted}[linenos=false]{typescript}
|
||||
class XMLFormatter {
|
||||
format(vals: string[]) {
|
||||
let result = "";
|
||||
for (let i = 0;
|
||||
i < vals.length; i++) {
|
||||
result +=
|
||||
`<value>${vals[i]}</value>`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
\end{minted}
|
||||
\end{minipage}
|
||||
\caption{Klasse eines XML-Formattierers}
|
||||
\label{fig:XmlAnfang}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[t]{0.48\textwidth}
|
||||
\centering
|
||||
\begin{minipage}[t]{\linewidth}
|
||||
\begin{minted}[linenos=false]{typescript}
|
||||
class JSONFormatter {
|
||||
format(vals: string[]) {
|
||||
let result = "";
|
||||
for (let i = 0;
|
||||
i < vals.length; i++) {
|
||||
if (i > 0) result += ",";
|
||||
result +=
|
||||
`{ value: "${vals[i]}" }`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
\end{minted}
|
||||
\end{minipage}
|
||||
\caption{Klasse eines JSON-Formattierers}
|
||||
\label{fig:JsonAnfang}
|
||||
\end{subfigure}
|
||||
\caption{Ähnliche Formattierer Klassen \citep[S. 327]{fiveLines.2023}}
|
||||
\label{fig:FormatterAnfang}
|
||||
\end{figure}\\
|
||||
Vergleicht man die beiden Klassen \ref{fig:XmlAnfang} und \ref{fig:JsonAnfang}, fällt auf dass diese nahezu identisch sind.
|
||||
Ein Unterschied ist zum Einen die abweichende Formatierung jedes einzelnen Wertes.
|
||||
Bei XML wird der Wert in ein Tag eingebettet, bei JSON wird ein Objekt mit einem Schlüssel-Wert-Paar in geschweiften Klammern erstellt.
|
||||
Dieser Unterschied liese sich einfach vereinen lassen, da dort nur unterschiedliche Zeichenketten eingefügt werden müssen.
|
||||
Die ausschlaggebende Problematik stellt, in diesem Beispiel, das trennende Komma zwischen einzelnen Werten im JSON Format dar.
|
||||
Dies verhindert eine einfache Zusammenführung der beiden Klassen.
|
||||
Im folgenden wird ein möglicher Lösungsansatz gezeigt, solche Probleme trotzdem zu lösen.
|
||||
blabla
|
||||
|
||||
\section{Gemeinsame Affixe nutzen}
|
||||
\section{Den Laufzeittyp bearbeiten}
|
||||
@@ -40,4 +40,14 @@
|
||||
edition={3},
|
||||
year={2012},
|
||||
publisher={John Wiley \& Sons, Inc.}
|
||||
}
|
||||
}
|
||||
@ARTICLE{CIMeyer.2014,
|
||||
author={Meyer, Mathias},
|
||||
journal={IEEE Software},
|
||||
title={Continuous Integration and Its Tools},
|
||||
year={2014},
|
||||
volume={31},
|
||||
number={3},
|
||||
pages={14-16},
|
||||
keywords={Production;Servers;Monitoring;Software;Green products;Marine vehicles;Multimedia communication;continuous integration;continuous delivery;testing},
|
||||
doi={10.1109/MS.2014.58}}
|
||||
Binary file not shown.
@@ -78,7 +78,7 @@
|
||||
\frontmatter
|
||||
\include{./Bestandteile/titel} % Titelblatt
|
||||
% \include{./Bestandteile/sperrvermerk} % Sperrvermerk (nur falls von Firma verlangt)
|
||||
\include{./Bestandteile/kurzzusammenfassung} % Abstract
|
||||
% \include{./Bestandteile/kurzzusammenfassung} % Abstract
|
||||
\tableofcontents % Inhaltsverzeichnis
|
||||
\clearpage
|
||||
\listoffigures % Abbildungsverzeichnis
|
||||
@@ -92,6 +92,7 @@
|
||||
\input{./Bestandteile/strukturImCode}
|
||||
\input{./Bestandteile/verhaltenImCode}
|
||||
\input{./Bestandteile/sicherheit}
|
||||
\input{./Bestandteile/ungenutzteStruktur}
|
||||
% ----------------------------------------------
|
||||
\backmatter
|
||||
|
||||
|
||||
Reference in New Issue
Block a user