\section{InheritedWidget}
\label{eval:inheritedwidget}

Wie in \autoref{sec:inheritedWidget} beschrieben, stellen InheritedWidgets einen Lösung für das Zustandsverwaltung dar, die ohne externe Bibliotheken auskommt und somit nur Bordmittel des Flutter-Frameworks benutzen.

\subsection{Implementierung}

Für die Implementierung dieses Ansatzes wurden mehrere Stores konstruiert, welche den Anmeldezustand, die geladenen Produkte und die im Warenkorb befindliche Anzahl der Produkte modellieren. Ein Store besteht dabei immer aus einem InheritedWidget und einem StatefulWidget. Das InheritedWidget erhält dabei vom StatefulWidget die Daten und Methoden, welche nach außen abrufbar sein sollen. Zustandsänderungen und Verknüpfungen mit anderen Stores finden ausschließlich im StatefulWidget statt.

Die Benutzeroberfläche greift auf die Stores ausschließlich über die InheritedWidgets zu, wie bereits im \autoref{sec:inheritedWidget} beschrieben wurde.

Der Funktionsumfang konnte dabei ohne Einschränkungen vollständig implementiert werden.

\subsection{Bewertung}

Im folgenden Abschnitt wird die Implementierung mit InheritedWidget \autocite[branch=inheritedwidget]{repo} anhand der definierten Bewertungskriterien bewertet.

\paragraph{\nameref{sec:changeablility}} Bei der Änderbarkeit und Skalierbarkeit wird dieses Zustandsverwaltungssystem mit \textquote{teilweise erfüllt} bewertet. 

Eines der Merkmale von skalierbaren und änderbaren Zustandsverwaltungssystemen ist es, dass sich mehrere Zustände untereinander verknüpfen lassen. Dies ist hier eingeschränkt möglich, da um auf einen anderen Zustand zuzugreifen es erforderlich ist, dass dieser im Widget-Baum oberhalb des zugreifenden Zustandswidgets angeordnet ist. Falls dies der Fall ist, lässt sich der Zustand aber wie bei der Benutzeroberfläche (vgl. \autoref{sec:inheritedWidget}) über einen Methoden-Aufruf abrufen.

Negativ bewertet wird hier aber die Tatsache, dass ein Zustand beziehungsweise Store immer aus mindestens drei Klassen bestehen muss. Dies macht es erforderlich, alle nach außen zugängliche Funktionen oder Variablen per Konstruktoraufruf von dem StatefulWidget zum InheritedWidget zu übergeben. Bei wachsender Größe eines Zustands wird dies unübersichtlich. 

Ein weiter Nachteil ist es, dass es erforderlich ist, im InheritedWidget eine Methode zu implementieren, die feststellt, ob sich der Zustand im Vergleich zu einem anderen Zustand verändert hat. Dies wird bei wachsender Größe oder Datenstrukturkomplexität eines Zustands unübersichtlich und auch komplex.

\paragraph{\nameref{sec:testability}} Zur Bewertung der Testbarkeit wurden mehrere Tests entsprechend der Anforderungen implementiert. 

Das Testen der Geschäftslogik der Stores stellte sich als komplex heraus, da hier keine Unit-Tests sondern Widget-Tests von Nöten waren. Dies hat auch zur Folge, dass man sich während der Tests auch um den Lebenszyklus der Widgets kümmern muss. So muss man im Test die Hilfs-Funktion \texttt{tester.pump()}, wie in \autoref{lst:testabilityInheritedWidget} zu sehen ist, zum richtigen Moment aufrufen, damit das Framework die Zustandsänderungen umsetzt.

\begin{lstlisting}[caption={Aufbau eines einfachen Flutter-Widgets in Dart}, label={lst:testabilityInheritedWidget}]
testWidgets('test cart store', (tester) async {
    final widgetTree = ProductStore(
      products: RemoteResource.finished(demoProducts),
      child: CartStoreImplementation(child: Container()),
    );
    await tester.pumpWidget(widgetTree);
    final cartStoreFinder = find.byType(CartStore);
    expect(cartStoreFinder, findsOneWidget);
    var cartStore = tester.widget<CartStore>(cartStoreFinder);
    cartStore.increaseAmount(demoProducts.first);
    await tester.pump();
    cartStore = tester.widget<CartStore>(cartStoreFinder);
    expect(cartStore.amountOfProduct(demoProducts.first), 1);
});
\end{lstlisting}
\label{par:ihtesting}
Die Tests für Widgets, die den Zustand konsumieren auf der anderen Hand sind einfach umzusetzen, da die Geschäftslogik im besten Fall komplett von der Speicherung der emittierten Daten getrennt wird. So ist es möglich ein InheritedWidget ohne das dazugehörige StatefulWidget zu initialiseren und die benötigten Mock-Daten über den Konstruktor zu übergeben.

Abschließend erfolgt hier die Bewertung mit \textquote{vollständig erfüllt}, da besonders die einfache Testbarkeit von konsumierenden Widgets die Nachteile bei dem Test für die Geschäftslogik ausgleicht. 

\paragraph{\nameref{sec:efficiency}} Nach der Ausführung der Teststrecke, ergaben die Zähler folgendes Ergebnis: 
\lstinputlisting[caption={Anzahl der Render-Vorgänge bei InheritedWidget}]{results/inheritedwidget/benchmarks.txt}

\paragraph{\nameref{sec:complexity}} Die Auswertung der Metriken (vgl. \autoref{metrics:inheritedwidget}) ergab eine \ac{mi} von 83 für das gesamte Projekt.

\paragraph{\nameref{sec:readability}} Bei der Bewertung der Lesbarkeit sind mehrere Faktoren wichtig.

Der erste Faktor ist die Frage, ob neue Konzepte eingeführt werden. Diese Frage kann mit nein beantwortet werden, da hier ausschließlich Komponenten aus dem Flutter-Framework in Form verschiedener Widgetes zum Einsatz kommen.

Der zweite Faktor hierbei ist die Frage, inwiefern die Struktur klar nachvollziehbar und verständlich ist. Dies ist bei InheritedWidgets nicht der Fall, da besonders die Konstruktion aus mehreren Widgets und Widget-Typen schwer nachvollziehbar ist. So gibt es keinen zentralen Ort, welcher die Geschäftslogik übersichtlich zusammenfasst. Im Gegenteil ist es hier notwendig, die Geschäftslogik als Teil eines StatefulWidgets zu implementieren, was die Lesbarkeit definitiv erschwert. Hinzu kommt der große Umfang an Boilerplate-Quelltext, da selbst für einfache Zustände wie das Speichern des Anmeldezustands drei Klassen benötigt werden.

Der letzte Faktor befasst sich mit der tiefen Verschachtlung von Widgets (engl. Nesting). Nesting wirkt sich negativ auf die Lesbarkeit von Widgets aus. Auf Nesting kann allerdings bei diesem Ansatz nicht verzichtet werden, da InheritedWidgets in die Baumstruktur eingebaut werden, wie in \autoref{lst:nestingInheritedWidget} zu sehen ist, und somit immer ein Child-Widget übergeben bekommen. 

\begin{lstlisting}[caption={Nesting bei InheritedWidgets in app.dart \cite{repo}}, label={lst:nestingInheritedWidget}]
return UserStoreImplementation(
    child: ProductStoreImplementation(
      productService: productService,
      child: CartStoreImplementation(
        child: child,
      ),
    ),
);
\end{lstlisting}

Zusammengefasst wird die Verständlichkeit/Lesbarkeit mit \textquote{nicht erfüllt} bewertet.

\paragraph{\nameref{sec:documentation}} Die Dokumentation gibt ein zwiegespaltenes Bild ab, da zum einen die einzelnen Widget-Typen an sich ausführlich beschrieben werden, allerdings das Zusammenspiel als Zustandsverwaltungssystem als Ganzes in der offiziellen Entwicklerdokumentation gar nicht beleuchtet wird. Dieses Zusammenspiel wird lediglich in Resourcen, außerhalb der Dokumentation beschrieben. Somit fehlen auch umfangreiche Beispiele, wie das Zustandsverwaltungssystem implementiert oder genutzt werden kann.

Aufgrund der großen Bandbreite an Dritt-Resourcen zu InheritedWidgets erfolgt hier noch eine Bewertung mit \textquote{teilweise erfüllt}. 

\paragraph{\nameref{sec:structure}}

Das Konzept mit InheritedWidgets stellt keine starren Strukturvorgaben an die Anwendung. Lediglich das Zusammenspiel zwischen InheritedWidget und StatefulWidget wird dadurch forciert, dass InheritedWidgets von sich aus ihren Zustand nicht ändern können. Dies hat allerdings keinen Einfluss auf die Gesamtarchitektur der Anwendung, das InheritedWidget und StatefulWidget als gemeinsame Komponente betrachtet werden können. 

Somit wird hier eine Bewertung mit \textquote{nicht erfüllt} vorgenommen.