All Projects → KyoheiG3 → Plan

KyoheiG3 / Plan

Licence: MIT License
The Plan.framework helps to keep your iOS application design clean.

Programming Languages

swift
15916 projects
ruby
36898 projects - #4 most used programming language
objective c
16641 projects - #2 most used programming language

Projects that are alternatives of or similar to Plan

Flutter clean architecture
Clean architecture flutter: A Flutter package that makes it easy and intuitive to implement Uncle Bob's Clean Architecture in Flutter. This package provides basic classes that are tuned to work with Flutter and are designed according to the Clean Architecture.
Stars: ✭ 360 (+900%)
Mutual labels:  design-pattern, clean-architecture
Clean React
Sistema em ReactJs usando Hooks, Typescript, TDD, Clean Architecture, Design Patterns e SOLID principles
Stars: ✭ 408 (+1033.33%)
Mutual labels:  design-pattern, clean-architecture
awesome-software-architecture
A curated list of awesome articles, videos, and other resources to learn and practice software architecture, patterns, and principles.
Stars: ✭ 1,594 (+4327.78%)
Mutual labels:  design-pattern, clean-architecture
app-from-scratch
Book about Clean Architecture and Clojure
Stars: ✭ 83 (+130.56%)
Mutual labels:  clean-architecture
Programming-Reference
Open repository of programming topic for reverse engineering purpose.
Stars: ✭ 25 (-30.56%)
Mutual labels:  design-pattern
ApolloRickAndMorty
just a side project to try out GraphQL and Dagger Hilt with Clean architecture and MVVM
Stars: ✭ 28 (-22.22%)
Mutual labels:  clean-architecture
memo sample
No description or website provided.
Stars: ✭ 36 (+0%)
Mutual labels:  clean-architecture
clean-architecture-example
A simple clean architecture example in Kotlin and Spring Boot 2.0
Stars: ✭ 63 (+75%)
Mutual labels:  clean-architecture
design-patterns-for-humans-cn
Design patterns for humans 中文版 - 对设计模式超简单的解释
Stars: ✭ 2,432 (+6655.56%)
Mutual labels:  design-pattern
CleanArchitectureMVVM
Example of Clean Architecture of Android app using MVVM, Koin, Coroutines, Retrofit, Room, Solid Principle, DRY, KISS, OOP
Stars: ✭ 60 (+66.67%)
Mutual labels:  clean-architecture
COVID-19-ANDROID
A simple android application builds for showcase COVID-19.
Stars: ✭ 21 (-41.67%)
Mutual labels:  clean-architecture
GitHubSearch
GitHub iOS client with minimum third-party dependencies.
Stars: ✭ 34 (-5.56%)
Mutual labels:  clean-architecture
MGCleanArchitecture
Clean Architecture with RxSwift & MVVM - Templates and Solutions
Stars: ✭ 156 (+333.33%)
Mutual labels:  clean-architecture
ModernKeePass
KDBX password manager for the Windows Store
Stars: ✭ 29 (-19.44%)
Mutual labels:  clean-architecture
KotlinMvpTemplateGenerator
Android Studio template for Kotlin with MVP + Dagger2 + Retrofit2
Stars: ✭ 65 (+80.56%)
Mutual labels:  clean-architecture
clean-ddd-php-poc-contacts
A simple contact manager API to demonstrate the concepts of Clean Architecture and DDD with PHP 7.4+.
Stars: ✭ 31 (-13.89%)
Mutual labels:  clean-architecture
MVPArchitecture
Android MVP architecture in Kotlin using Dagger2, RxJava2, Retrofit2 and so on
Stars: ✭ 27 (-25%)
Mutual labels:  clean-architecture
RSS-Reader
Simple project with clean architecture
Stars: ✭ 31 (-13.89%)
Mutual labels:  clean-architecture
car-rental
CarRental Project
Stars: ✭ 13 (-63.89%)
Mutual labels:  clean-architecture
paybill-manager
Your personal finance manager
Stars: ✭ 46 (+27.78%)
Mutual labels:  clean-architecture

Plan

Build Carthage compatible codecov Version Platform License

The Plan.framework helps to keep your iOS application design clean. Think of it as a clean architecture. Read about clean architecture here.

overview

The purpose of this design is to clear the processing flow and dependencies.

The ideal processing flow is as follows.

If it is difficult to accept processing in Controller, you may prepare Adapter instead of Controller and Adapter may interact with Controller. However, the Adapter should not do more than necessary.

Details

Plan offers five main types, but in many cases a framework that allows reactive programming is helpful.

Interactor

Input from Controller is processed. Data I/O and API calls are also performed here. When the processing is completed, execute the action of Dispatcher. It is included in the Domain Layer.

enum LoginUseCaseAction {
    case loading
    case login(Result<User, Error>)
}

protocol LoginUseCase {
    func login(userName: String, password: String)
}

class LoginInteractor: Interactor<LoginUseCaseAction>, LoginUseCase {
    let disposeBag = DisposeBag()

    func login(userName: String, password: String) {
        dispatcher.dispatch(.loading)
        userRepository.login(userName: userName, password: password)
            .subscribe(onNext: { [weak self] user in
                self?.dispatcher.dispatch(.login(.success(user)))
            }, onError: { [weak self] error in
                self?.dispatcher.dispatch(.login(.failure(error)))
            })
            .disposed(by: disposeBag)
    }
}

Dispatcher

Pass the Output by Interactor to Translator.

Store

Store the state of View. The status is changed by the Translator. It is included in the Presentation Layer.

class LoginStore: Store {
    let viewModel = BehaviorRelay(value: LoginViewModel())
}

Translator

The data received from the Interactor is converted into the data for configuring the View and the state of the Store is updated. It is included in the Presentation Layer.

struct LoginTranslator: Translator {
    func translate(action: LoginUseCaseAction, store: LoginStore) {
        switch action {
        case .loading:
            store.viewModel.modefy { viewModel in
                viewModel.loginProgress = .loading
            }

        case .login(.success(let user)):
            store.viewModel.modefy { viewModel in
                viewModel.user = user
                viewModel.loginProgress = .loadSucceeded
            }

        case .login(.failure(let error)):
            print("login failed \(error)")
            store.viewModel.modefy { viewModel in
                viewModel.loginProgress = .loadFailed
            }
        }
    }
}

Presenter

Convert the stored state to the optimal form for View to use. It is included in the Presentation Layer.

class LoginPresenter: Presenter<LoginTranslator>, LoginPresenterProtocol {
    var viewModel: Observable<LoginViewModel> {
        store.viewModel.asObservable()
    }
}

When initializing the Interactor, pass the Presenter instance as the Dispatcher.

let presenter = LoginPresenter(store: LoginStore(), translator: LoginTranslator())
let interactor = LoginInteractor(dispatcher: presenter.asDispatcher())

Normally, the Action that can be dispatched to the Presenter is limited to the one defined in the Translator, but if there are multiple UseCase, by overloading the asDispatcher() method, It is possible to dispatch to multiple Interactor.

class LoginPresenter: Presenter<LoginTranslator>, LoginPresenterProtocol {
    var viewModel: Observable<LoginViewModel> {
        store.viewModel.asObservable()
    }

    func asDispatcher() -> AnyDispatcher<UserInfoUseCaseAction> {
        AnyDispatcher(self)
            .map { (action: UserInfoUseCaseAction) in
                // Convert UserInfoUseCaseAction to LoginTranslator.Action
        }
    }
}

let presenter = LoginPresenter(store: LoginStore(), translator: LoginTranslator())

// Can dispatch to one Presenter from multiple Interactors.
let loginInteractor = LoginInteractor(dispatcher: presenter.asDispatcher())
let userInfoInteractor = UserInfoInteractor(dispatcher: presenter.asDispatcher())

More details

See Examples.

Requirements

  • Swift 5.0
  • iOS 10.0 or later
  • macOS 10.12 or later
  • tvOS 10.0 or later
  • watchOS 3.0 or later

Installation

CocoaPods

Add the following to your Podfile:

pod "Plan"

Carthage

Add the following to your Cartfile:

github "KyoheiG3/Plan"

Acknowledgements

I've always used VueFlux inside the architecture, but I've created a Plan in an attempt to make it simpler and easier for module testing.

LICENSE

Under the MIT license. See LICENSE file for details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].