Articles

Was ist VIPER?

Dies ist der erste Beitrag in einer Reihe von Beiträgen zur iOS-Projektarchitektur. In diesen Beiträgen beabsichtige ich nicht, auf die Vor- und Nachteile der Architekturmuster einzugehen, sondern den Fokus auf die Darstellung verschiedener architektonischer Strukturen zu legen, die in einem iOS-Projekt angewendet werden können. Ich beabsichtige jedoch, ein meinungsstärkeres Stück als Zusammenfassung / Schlussfolgerung für die verschiedenen Konzepte zu schreiben, die später in dieser Serie vorgestellt werden.

In diesem Beitrag werde ich das VIPER-Architekturmuster vorstellen. In diesem Beitrag werde ich mich auf die Verwendung von VIPER in einem iOS-Projekt konzentrieren.

VIPER steht für die verschiedenen Komponenten des Architekturmusters; View, Interactor, Presenter, Entity und Routing. Das Kernprinzip von VIPER besteht darin, die Funktionalität der App in diese verschiedenen Komponenten zu unterteilen, um eine geringe Kopplung zwischen den verschiedenen Komponenten der App zu erreichen und dem Single Responsibility-Prinzip zu folgen.

Abgesehen von den oben erwähnten Komponenten in VIPER verwendet das VIPER-Muster auch Helfer, die die Logik zwischen externen Quellen wie einer Datenbank und der iOS-Anwendung verwalten.

Die verschiedenen Komponenten von VIPER

Zu Beginn werde ich die verschiedenen Komponenten in VIPER und ihre Verantwortlichkeiten durchgehen. Während ich die verschiedenen Komponenten von VIPER beschreibe, werde ich Beispiele dafür geben, wo die verschiedenen Komponenten in einem traditionell eingerichteten MVC iOS-Projekt zu finden sind (falls zutreffend).

Sobald die Komponenten eingeführt sind, werde ich mich darauf konzentrieren, wie die verschiedenen Komponenten in einem Projekt zusammenkommen und wie die Komponenten miteinander in Beziehung stehen.

Ansicht

Die Ansicht ist für die Anzeige von Informationen für den Benutzer der App verantwortlich. Da die Ansicht das ist, was der Benutzer sieht, ist dies eine wichtige Komponente, die dem Benutzer eine direkte Schnittstelle zur Anwendung bietet – in einem herkömmlichen iOS-Projekt kann dies eine Ansicht in einem Storyboard oder in einem Storyboard sein.xib-Datei. Die Ansicht ist daher auch dafür verantwortlich, der App die Möglichkeit zu geben, Informationen einzugeben.

Interactor

Der Interactor enthält die Geschäftslogik der App für den Umgang mit Daten. Der Interactor ist nicht direkt für das Abrufen von Daten von einem Server verantwortlich, diese werden häufig einem oder mehreren Netzwerkmanagern zugewiesen. Der Interactor ist jedoch für die Interaktion mit diesen Netzwerkmanagern verantwortlich. Da für eine bestimmte App möglicherweise Daten aus mehreren verschiedenen Datenquellen abgerufen werden müssen, kann der Interactor Netzwerkanforderungen über mehrere verschiedene Netzwerkmanager initialisieren. Es liegt am Interactor, die erforderlichen Daten für den spezifischen Anwendungsfall der App aus den verschiedenen Datenpunkten gemäß der Geschäftslogik der App abzurufen. Sobald die Daten von allen externen Servern über die Netzwerkmanager abgerufen wurden, übernimmt der Interactor alle erforderlichen Datenmanipulationen.

Hinweis: Wenn Sie mit einer modernen MVVM-Architektur vertraut sind, kann die Verantwortung eines Interactors mit der Verantwortung des ViewModels von MVVM verglichen werden.

Moderator

Der Moderator ist dafür verantwortlich, die Logik anzuwenden, wie Inhalte angezeigt werden sollen. Der Präsentator verwendet die vom Interactor bereitgestellten Daten und wendet dann die erforderliche Logik an, wie diese Daten in einer Ansicht dargestellt werden sollen. Der Moderator ist auch für die Logik verantwortlich, wie die Anwendung auf Benutzereingaben und Benutzerinteraktionen reagieren soll. Diese Verantwortung wird häufig einem ViewController im Kontext eines iOS-Projekts übertragen.

Entität

Eine Entität ist ein Datenspeichermodell. Dies kann entweder ein persistentes Speichermodell sein, z. B. ein Core Data-Objekt, oder ein temporäreres Speichermodell, z. B. eine Struktur, eine Klasse oder eine Enumeration. Die Entität sollte keine Logik enthalten, die sich auf die Formatierung von Daten vor der Anzeige bezieht, und sie sollte auch keine Logik zum Abrufen der Daten enthalten (z. B. Netzwerkanforderung). Eine Entität enthält einfach Variablen, die für das Modell spezifisch sind, das sie darstellt. Die Verantwortung für die Anzeige der Daten einer Entität wird stattdessen dem Präsentator übertragen, und ein Netzwerkmanager ist dafür verantwortlich, wie Daten abgerufen werden.

Routing

Schließlich ist die Routing-Komponente für die erforderliche Logik und die Navigation zwischen den verschiedenen Ansichten der App verantwortlich. Diese Komponente beschreibt, was erforderlich ist, um die einzelnen Ansichten der App anzuzeigen. Sobald alle für eine bestimmte Ansicht erforderlichen Abhängigkeiten bereitgestellt / erstellt wurden, initialisiert Routing die Ansicht, stellt diese Abhängigkeiten bereit (dies wird als Abhängigkeitsinjektion bezeichnet) und präsentiert dann die Ansicht.Dies ist eine Verantwortung, die traditionell zwischen einem Storyboard-Segment und einem ViewController (in einer prepareForSegue-Funktion) aufgeteilt wird. Eine App, die die VIPER-Architektur verwendet, enthält daher normalerweise keine Übergänge zwischen den verschiedenen Ansichten eines Storyboards.

Bemerkenswert

Gemäß der VIPER-Architektur sollte keine andere Klasse als ein Datenmanager Kenntnis von Kerndaten oder Kerndatenobjekten haben. Stattdessen konvertiert eine Datenmanagerklasse das Kerndatenobjekt in ein PONSO (einfaches altes NSObject), bevor es an eine andere Klasse wie eine Interaktorklasse übergeben wird.

Module mit VIPER verwenden

Einem Modul kann ein Bildschirm oder eine Reihe von Bildschirmen hinzugefügt werden. Ein Modul kann einfach ein Ordner im Projekt sein, der die für einen bestimmten Bildschirm erforderliche Funktionalität enthält. Das Modulmuster kann nützlich sein, um spezifisches Verhalten für verschiedene Plattformen zu ersetzen oder wiederzuverwenden. Wenn beispielsweise eine bestimmte Funktionalität nur für eine iPad-App vorhanden ist, kann sie leicht durch ein anderes Modul für eine iPhone-Anwendung ersetzt werden.

Wie wird diese Struktur in einem iOS-Projekt aussehen?

Bisher habe ich in diesem Artikel die verschiedenen Komponenten von VIPER sowie die unterschiedlichen Verantwortlichkeiten dieser Komponenten identifiziert. Lassen Sie uns genauer durchgehen, wie diese Komponenten miteinander interagieren und wie sie in einem Projekt zusammenpassen.

Die Tatsache, dass jede der Komponenten im VIPER-Modell einer bestimmten Aufgabe gewidmet ist, macht es uns leicht, die Komponenten zu kombinieren, um eine Aufgabe zu erfüllen, die für die Funktion der App erforderlich ist, sowie die Komponenten in verschiedenen Teilen der App wiederzuverwenden. Wie das obige Diagramm zeigt, interagieren die verschiedenen Komponenten miteinander, um ein bestimmtes Ziel zu erreichen.

Während die Ansicht einem Benutzer einen bestimmten Bildschirm der App zur Verfügung stellt, spielt der Präsentator eine wichtige Rolle bei der Entscheidungsfindung, wie Daten in einer Ansicht angezeigt werden sollen und was mit Daten zu tun ist, die ein Benutzer in eine Ansicht eingibt. Der Präsentator ruft Daten ab, die in einer bestimmten Ansicht vom Interactor angezeigt werden sollen, und formatiert die Daten, bevor sie in der Ansicht angezeigt werden. Wenn der Benutzer unserer App mit der Ansicht interagiert, liegt es in der Verantwortung des Moderators zu entscheiden, wie sich die Ansicht ändern soll, um dem Benutzer das erforderliche Feedback zu geben.

Wenn die Benutzereingaben für einen späteren Abruf gespeichert werden sollen, leitet der Presenter die Daten an einen Interactor weiter. Der Interactor entscheidet, wie die Daten formatiert werden sollen, indem er die entsprechende Geschäftslogik anwendet, bevor er sie entweder an einen Netzwerkmanager (zur externen Speicherung der Informationen) oder an eine Entität übergibt.

Eine App enthält oft mehrere Bildschirme mit unterschiedlichen Funktionen, die einem bestimmten Anwendungsfall gewidmet sind. Jeder dieser Bildschirme (oder ein Satz verwandter Bildschirme) besteht jeweils aus einer Ansicht, einem Interactor, einem Presenter, einer Entität und einer Routing-Komponente, die zusammen als Modul bezeichnet werden können. Da einige Bildschirme möglicherweise dieselben Entitäten oder denselben Interaktor wie ein anderer Bildschirm erfordern, kann eine VIPER-Komponente in verschiedenen Modulen wiederverwendet werden.

Routing kann auf verschiedenen Ebenen innerhalb der Anwendung existieren. Es kann einen Router geben, der für ein Modul spezifisch ist und die Navigation zwischen einer Sammlung von Bildschirmen ermöglicht. Ein Router kann auch auf höherer, übergeordneter App-Ebene vorhanden sein und die Navigationsfunktionalität zwischen den höheren Hauptansichten der Apps bereitstellen (z. B. die Erstellung von Ansichten und das Routing zu diesen Ansichten über eine Registerkartenleiste).

Nützliche Links:

  • Architektur von iOS-Apps mit VIPER – by objc.io
  • iOS-Architekturmuster – von Bohdan Orlov
  • iOS-App mit VIPER-Architektur erstellen – von Amit Shekhar

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.