Sobes.tech
Middle+

Czy znasz architekturę z cyklem VIP?

sobes.tech AI

Odpowiedź od AI

VIP (Widok, Interaktor, Prezenter) to wzorzec architektoniczny, który stanowi wariant Czystej Architektury, stosowany w rozwoju iOS do rozdzielenia odpowiedzialności i poprawy testowalności kodu. Podstawą jest jednokierunkowy przepływ danych między komponentami.

Komponenty VIP:

  • Widok: Wyświetla dane i wysyła akcje użytkownika (akcje użytkownika) do Interaktora. Widok (UIView, UIViewController lub po prostu protokół) nie zawiera logiki biznesowej.
  • Interaktor: Zawiera logikę biznesową. Odbiera akcje od Widoku, wykonuje niezbędne operacje (np. dostęp do danych, obliczenia) i wysyła wynik do Prezenter.
  • Prezenter: Odbiera dane od Interaktora, formatuje je do wyświetlenia i wysyła do Widoku. Nie zawiera logiki biznesowej, odpowiada tylko za prezentację danych.

Cykl interakcji:

  1. Użytkownik wykonuje akcję w Widoku.
  2. Widok wysyła "żądanie" (request - struct/enum) do Interaktora.
  3. Interaktor przetwarza żądanie, wykonuje logikę biznesową i wysyła "odpowiedź" (response - struct/enum) do Prezenter.
  4. Prezenter otrzymuje odpowiedź, formatuje dane w "ViewModel" (struct/enum) i wysyła do Widoku.
  5. Widok otrzymuje ViewModel i aktualizuje UI.

Dodatkowe komponenty (opcjonalnie):

  • Router: Zarządza nawigacją między modułami VIP (scenami). Zazwyczaj wywoływany przez Interaktora lub Prezenter.
  • Worker: Komponent Interaktora odpowiedzialny za wykonywanie konkretnych zadań (np. zapytania sieciowe, praca z Core Data).

Główne zalety VIP:

  • Rozdzielenie odpowiedzialności: Jasne rozdzielenie między UI, logiką biznesową i logiką prezentacji.
  • Testowalność: Łatwo testować każdy komponent osobno, mockując zależności.
  • Łatwość utrzymania: Zmiany w jednym komponencie mają mniejszy wpływ na inne.

Przykład struktury folderów dla modułu VIP (UserScene):

UserScene/
├── UserViewController.swift
├── UserInteractor.swift
├── UserPresenter.swift
├── UserRouter.swift
├── UserModels.swift // Struktury dla Request, Response, ViewModel
├── UserProtocols.swift // Protokoły do komunikacji między komponentami

Przykład interakcji (ładowanie danych użytkownika):

// W UserViewController
func viewDidLoad() {
    super.viewDidLoad()
    interactor?.fetchUserData(request: UserModels.FetchUser.Request())
}

// W UserInteractor
func fetchUserData(request: UserModels.FetchUser.Request) {
    // ... logika biznesowa ładowania danych ...
    let response = UserModels.FetchUser.Response(userData: fetchedData)
    presenter?.presentUserData(response: response)
}

// W UserPresenter
func presentUserData(response: UserModels.FetchUser.Response) {
    let viewModel = UserModels.FetchUser.ViewModel(
        displayName: response.userData.name,
        displayEmail: response.userData.email
    )
    viewController?.displayUserData(viewModel: viewModel)
}

// W UserViewController (implementacja protokołu UserDisplayLogic)
func displayUserData(viewModel: UserModels.FetchUser.ViewModel) {
    nameLabel.text = viewModel.displayName
    emailLabel.text = viewModel.displayEmail
}