When we develop software, it's important not only to use design patterns, but also to use architectural patterns. There are many different architectural patterns in software engineering. In mobile software development, the most widely used standards are MVVM, Clean Architecture, and Redux.
In this article, we point out awork sample projectas architectural patternsMVVMmiclean architecturecan be applied in an iOS app.
If you are also interested in learning more about Redux, please read this book:Advanced iOS app architecture.
More information aboutclean architecture.
how can we see in itclean architecturegraphic we have different levels in the app. The main rule ishas no dependencies from inner layers to outer layers๐ง๐ท The arrows pointing from the outside in are thedependency rule๐ง๐ท There can only be internal dependencies of the external layer.
After grouping all the layers, we have:Presentation, domain and data layers.
Domain layer (business logic)it is the innermost part of the onion (it does not depend on other layers, it is completely isolated). containsEntities (business models), use cases, and repository interfaces.This layer can potentially be reused in different projects. Such separation makes it possible not to use the host application within the scope of the test becauseNo dependencies required (even from third parties)โ As a result, domain use case testing takes just seconds.Observation:domain layershould not be includedeverything from other layers (p.Presentation - UIKit or SwiftUIthe data layer mapcodificable)
The reason why good architecture takes center stageuse casesSo that architects can confidently describe the structures that support themuse caseswithout compromising frameworks, tools, and environments. is calledscreaming architecture.
slidecontainsUser interface (UIViewControllers or SwiftUI Views). Points of vieware coordinated byViewModels (presenters) that execute one or more use cases.slideit just dependsnodomain layer.
data layercontainsRepository implementations and one or more data sources.Repositories are responsible for coordinating data from different data sources. The data source can be remote or local (for example, a persistent database). data layerit just dependsadomain layer๐ง๐ท In this layer we can also add the JSON network data mapping (eg.decodificableaccordance) for domain models.
In the graphic below, each component in each layer is shown along withdependency addressand also himdata flow(request response). we can see themdependency reversalPoint where we use the repository interfaces (protocols). The explanation of each level is based on thesample projectquoted at the beginning of the article.
data flow
1.panorama(UI) calls the method ofsee model(Moderator).
2.see modelruncase of use.
3.case of usecombine dataof the usermilocations.
4. AllRepositoryreturns data from aremote data(The net),persistent databaseStorage source or data in memory (purged or cached).
5. Information flows back topanorama(UI) where we show the list of elements.
dependency address
Presentation Layer -> Domain Layer <- Data Storage Layer
Presentation layer (MVVM)= ViewModels (moderators) + Views (UI)
domain layer= entities + use cases + repository interfaces
Data repository layer= Repository Deployments + API (Network) + Persistence Database
domain layer
Withinsample projectYou can finddomain layer๐ง๐ท containsentities, Search Moviescase of usesearch the movies and save the latest successful queries. In addition, it containsdata storage interfaceswhat is needed for thisdependency inversion.
To use: Another way to create use cases is to usecase of usestart withBeginning()The feature and all use case implementations will conform to this protocol. One of the use cases in the example project follows this approach:BuscaRecentMovieQueriesUseCase๐ง๐ท Use cases are also mentioned.from Interaktor
To use: Acase of usemay depend on othersuse cases
slide
slidecontains List of moviessee modelwith elements watched by MoviesListpanorama๐ง๐ท movie listsee modelit doesn't matter UIKit. Because keeping the ViewModel clean of any UI framework like UIKit, SwiftUI or WatchKit allows for easy reuse and refactoring. In the future, for examplePoints of viewRefactoring from UIKit to SwiftUI will be much easier because thesee modelyou won't have to change.
Observation:We use a MoviesList interfaceViewModelEntryand movie listViewModelExitto make MoviesListpanoramaController verifiable, via teasingsee modeleasy(example๐ง๐ท Also, we have MoviesListViewModelBehaviourclosures that sayMoviesSearchflow coordinator presenting different points of view. When the completion of the action is requested, the coordinator displays the movie details screen. We'll use a framework for grouping actions because we can easily add more actions later if needed.
slidealso includes List of moviespanoramacontroller what islinked data(elements) from MoviesListsee model.
The UI cannot access business logic or application logic (business models and use cases), only ViewModels can. this is itseparation of interests๐ง๐ท We cannot pass business models directly to the View (UI). For this reason, we assign business models to ViewModel inside ViewModel and pass them to the view.
We've also added a View search event call to the ViewModel to start searching for movies:
Observation:We watch the elements and reload the view when they change. We use a simple one hereobservable, which is discussed in the MVVM section below.
We also assign functionmostrarMovieDetails(Movie:)by actions ofmovie listsee modelinside sideMoviesSearchflow coordinatorTo view movie detail screens in the scheduler:
Observation:we useflow coordinatorfor presentation logic, to reduce the size of view controllers, andresponsibility๐ง๐ท We havedifficultreferring toCaudal(with action closures, own functions).Caudalnot released as needed.
With this approach, we can easily use different views with the same ViewModel without changing it. We could check if iOS 13.0 is available and then create a SwiftUI view instead of UIKit and bind it to the same ViewModel; otherwise, we would create a UIKit view. In whichsample projectAlso added a SwiftUI example for MoviesQueriesSuggestionsList. AAt least Xcode 11 Beta is required.
data layer
data layercontains standard moviesRepository.Corresponds to the interfaces defined within the domain layer (dependency reversal๐ง๐ท We have also added JSON data mapping here (decodable compliance) miCoreData Entitiesto domain models.
Observation:Data Transfer Objects DTO is used as an intermediate object to map the JSON response to the domain. Even if we want to cache the response from the terminal, we will store the data transfer objects in persistent storage by assigning them to persistent objects (eg DTO -> NSManagedObject).
In general, data stores can be injected with API Data Service and with Persistent Data Storage. The data repository works on these two dependencies to return data. The rule is to first request persistent storage for output cached data (NSManagedObject are allocated via the domain DTO object and retrieved inclose cached data๐ง๐ท Then call the API data service, which returns the latest updated data. The persistent store is then updated with this latest data (DTOs are mapped to persistent objects and stored). And then the DTO is assigned to the domain and retrievedUpdated/Completed Dates๐ง๐ท That way, users see the data immediately. Even when there is no internet connection, users still see the latest data from persistent storage.example
The storage and API can be replaced with completely different implementations (for example, from CoreData to Realm). While all other application layers are not affected by this change, this is because the database is a detail.
infrastructure (network) layer
It is a wrapper around the network structure, it can bepoplar fire(or other structure). It can be configured with network parameters (for example, base URL). It also supports the definition of endpoints and includes data mapping methods (using Decodable).
To use: You can read more here:https://github.com/kudoleh/SENetworking
it isModel-View-ViewModelStandard (MVVM) provides a clear separation of concerns between the user interface and the domain.
When used in conjunction with Clean Architecture, it can help separate concerns between the presentation and UI layers.
Different view implementations can be used with the same ViewModel. For example you can use CarsAroundListpanoramae CarsAroundMapapanoramaI use CarsAroundsee modelfor both. You can also implement a View UIKit and another View using SwiftUI. It's important to remember not to import UIKit, WatchKit and SwiftUI in your ViewModel. This way it can be easily reused on other platforms if needed.
data linkin betweenpanoramamisee modelit can be done eg with closures, delegates or observables (eg RxSwift). Combine and SwiftUI can also be used, but only if your minimum supported iOS system is 13panoramais directly related tosee modeland notifies you when an event occurs in View. From the ViewModel there is no direct reference to the View (only data binding)
In this example, we use a simple combination of Closure and didSet to avoid third-party dependencies:
To use: This is a very simplified version of Observable, to see the full implementation with multiple observers and removal of observers:observable.For the sake of simplicity, call the observer lockmain threatbecause it is used by the presentation layer that contains the user interface.
An example of a ViewController data binding:
To use: The viewModel is not allowed to be accessed from a nearby viewer, this causes a hold cycle (memory leak). You can only access viewModel with self: self?.viewModel .
An example of data binding in TableViewCell (reusable cell):
To use: We need to unbind if the view is reusable (eg UITableViewCell)
MVVM modelsIt can be foundhere
Delegation
The ViewModel (screen) of one MVVM communicates with the ViewModel (screen) of another MVVM using a delegation pattern:
For example, we have ItemsListsee modeland editing elementssee model๐ง๐ท Next, we create an ItemEdit recordViewDelegateModelwith the ItemEditViewModelDidEditItem(item) method. And we made it compatible with this protocol: ListItemsViewModel Extension: ItemEditViewModelDelegate
Observation:We can also refer to delegates as responders in this case: ItemEditViewModelrespondedor
locks
Another form of communication is through closures assigned or inserted by the FlowCoordinator. In the example project, we can see howMoviesListViewModeluse actionfence showMovieConsultasSugerenciasto watch the MoviesQuestionsSuggestionspanorama๐ง๐ท Also passes parameters(_didSelect: MovieQuery) -> Voidthen you can remember therepanorama๐ง๐ท Communication is connected insideMoviesSearchflow coordinator:
Now each layer (domain, presentation, user interface, data, network infrastructure) of the sample application can be easily separated into separate frames.
New Project -> Create Projectโฆ -> Cocoa Touch Framework
You can then integrate these frameworks into your main application using CocoaPods. can you see thatworking example here.Observation:you have to deleteExampleMVVM.xcworkspaceand runInstalar podto generate a new one due to a permissions issue.
addiction injectionis a technique in which one object provides the dependencies of another object.DIContenedorin your application it is the central unit of all injections.
Using dependency factory registers
One option is to declare a dependency protocol to delegate the creation of dependencies toDIContenedor๐ง๐ท To do this we need to define MoviesSearchFlowCoordinatordependenciesRegister and create your MoviesSceneDIContenedorto fulfill this record and then paste it into MoviesSearchflow coordinatoryou need this injection to create and present MoviesListpanoramacontroller. Here are the steps:
wear bras
Another option is to use staples. To do this, we must declare the closure inside the class that needs an injection, and then inject that closure. For example:
kudoleh/iOS-Clean-Architecture-MVVM
iOS project implemented with Clean Layered Architecture and MVVM. (Can be used as a template design by replacing the element...
github.com
Clean architecture + MVVMit issuccessfully used by fintech companiesRevolutionwith more than 70 iOS engineers.
more usedarchitectural patternin mobile development are Clean Architecture (Layered), MVVM and Redux.
Of course, MVVM and Clean Architecture can be used separately, but MVVM provides separation of concerns only within the presentation layer, while Clean Architecture breaks your code into modular layers, which can be simple.tested, reused, miit is understood.
It is important not to skip creating a use case, even if the use case does nothing more than call the repository. That way, when a new developer sees your use cases, your architecture is self-explanatory.
While this should be useful as a starting point,there is no silver bullet๐ง๐ท You choose the architecture that meets the requirements of your project.
Clean Architecture works very well with (Test Driven Development) TDD. This architecture makes the project testable and the layers can be easily interchanged (user interface and data).
domain-directed design(DDD) also works great withclean architecture(CALIFORNIA).
In software development, there are other different architectures that are interesting to know:The 5 standards you should know
Other software development best practices:
- Don't write code without testing (try TDD)
- Do continuous refactoring
- Don't exaggerate and be pragmatic
- Avoid using third party framework dependencies in your project as much as possible
modular architecture
How can you improve your project by splitting your application into completely isolated modules (eg.NetworkingService, TrackingService, ChatFeature, PaymentFeatureโฆ๐ง๐ท And how can all teams work quickly and independently with these modules ๐ค?
Check out the white paper on modular architecture:Application Modularization
FAQs
What is Clean Architecture in iOS? โบ
Clean architecture is a software design philosophy that separates the concerns of an app into distinct layers, each with a specific responsibility. It is called โcleanโ because it promotes code that is easy to read, test, and maintain, and is not tied to a specific framework or technology.
Does iOS use MVVM? โบModel-View-ViewModel (MVVM) is a design pattern that's gained traction in the iOS development community in recent years. It involves a new concept called a view model. In iOS apps, a view model is a companion object to a view controller.
What is MVVM Clean Architecture? โบMVVM with Clean Architecture is pretty good in such cases. It goes one step further in separating the responsibilities of your code base. It clearly abstracts the logic of the actions that can be performed in your app. Note: You can combine Clean Architecture with the model-view-presenter (MVP) architecture as well.
What are the advantages of MVVM architecture in iOS? โบBenefits of MVVM
By moving data manipulation to the ViewModel, MVVM makes the testing much easier. Unit testing of ViewModel is easy now, as it doesn't have any reference to the object it's maintained by. Similarly, testing of ViewController also becomes easy since it no longer depends on the Model.
Model-View-Controller(MVC)
This architecture is the most standard one in the development world since it's used in many languages like Java, Swift, and Python. It's also the default pattern used in Apple projects since we have already some native classes relying on its layers.
Clean architecture allows us to create architectural boundaries between dependencies which allows components to be intrinsically testable. What's to follow is our attempt to build an iOS application using clean architecture with TDD. The app will be used to manage contacts.