提高系统可读性和可维护性
A bit more closer to perfection with MVVM-C in swift
借助MVVM-C更快更接近完美
Many architectural design patterns are introduced since now, amongst those few gained more popularity for developing iOS applications. Earlier, we were using MVC design pattern for developing iOS application, which is quite old now, since many developers have already adapted MVVM design pattern for their iOS applications to focus more on clearly defining responsibility for each layer of architecture.
从现在开始,引入了许多架构设计模式,其中有少数在开发iOS应用程序中获得了越来越多的欢迎。 早些时候,我们使用MVC设计模式来开发iOS应用程序,这已经很老了,因为许多开发人员已经为他们的iOS应用程序改编了MVVM设计模式,以更加专注于明确定义体系结构每一层的职责。
In the following part of the story, we would see, why there was need to enhance MVVM further and how MVVM-C emerged as one of the widely used architectural design pattern.
在故事的以下部分,我们将了解为什么需要进一步增强MVVM,以及MVVM-C如何成为广泛使用的架构设计模式之一。
To answer these questions, let’s have a glimpse of MVC and MVVM.
为了回答这些问题,让我们看一下MVC和MVVM。
MVC中过多的ViewController (Overburdened ViewControllers in MVC)
MVC is having three components Model-View-Controller.
MVC具有三个组件Model-View-Controller。
Model is quite nicely defined and having specific responsibility.
模型定义得很好,并负有具体责任。
View component is somewhat confused with ViewController notion in iPhoneSDK.
View组件与iPhoneSDK中的 ViewController概念有些混淆。
Developers tend to make ViewController responsible for View rendering as well as Controller activity(i.e navigation logic, business logic etc.)
开发人员倾向于让ViewController负责View渲染以及Controller活动( 即导航逻辑,业务逻辑等 )。
Which makes View and Controller tightly coupled to each other and hence they are hard to re-use and of course hard for Unit Testing.
这使得View和Controller彼此紧密耦合,因此很难重用,当然也很难进行单元测试。
调用MVVM进行救援以减少ViewController的责任 (Call MVVM to rescue to reduce responsibility of ViewControllers)
MVVM is quite nice compared to MVC, since it helps to overcome drawback of overburdened ViewController of MVC design pattern.
与MVC相比,MVVM非常不错,因为它有助于克服MVC设计模式的ViewController负担过重的缺点。
MVVM has also three components Model-View-ViewModel.
MVVM还具有三个组件Model-View-ViewModel。
Model is straight forward and having single responsibility like MVC.
模型简单明了,并且像MVC一样具有单一职责。
View is simplified and made more clearer with avoiding confusion of ViewController as Controller in MVC. View is responsible for UI rendering on screen. It can be either UIView or UIViewController subclass.
避免将ViewController作为MVC中的Controller造成混淆,从而简化了视图并使视图更加清晰。 视图负责在屏幕上呈现UI。 它可以是UIView或UIViewController子类。
ViewModel is responsible for implementation of business logic as well as communicator between Model and View. ViewModel can be struct
or class
.
ViewModel负责业务逻辑的实现以及Model和View之间的通信器。 ViewModel可以是struct
或class
。
ViewModel is responsible for containing navigation logic, business logic etc. Since, it’s not UIViewController subclass, it is easier to test business logic which is implemented in ViewModel.
ViewModel负责包含导航逻辑,业务逻辑等 。 由于不是UIViewController子类,因此更容易测试在ViewModel中实现的业务逻辑。
ViewModel also helps to make View component dumb with removing ViewController’s responsibility of containing navigation logic. With a dumb View component, it’s completely re-usable.
ViewModel还有助于消除ViewController包含导航逻辑的责任,从而使View组件变得笨拙。 借助笨拙的View组件,它可以完全重用。
ViewModel承担着许多责任,因此很难重用 (ViewModel is having many responsibilities, making it harder to re-use)
ViewModel helped to make View component re-usable and testable and also it made easier to Unit test business logic.
ViewModel有助于使View组件可重用和可测试,并且使单元测试业务逻辑更加容易。
However, if you have observed, still it has other responsibilities(i.e navigation logic) apart from it’s main responsibility of implementing business logic.
但是,如果您已经观察到,除了实现业务逻辑的主要职责之外,它还有其他职责(即导航逻辑 )。
It’s time now to think of reducing responsibility of ViewModel.
现在是时候考虑减少ViewModel的责任了。
MVVM-C模式的出现,并在MVVM中引入了新的组件`Coordinator`。 (Emergence of MVVM-C pattern with introduction of new component `Coordinator` in MVVM.)
To reduce responsibility of ViewModel
we can add one more component which can take out responsibility to implement navigation logic from ViewModel
为了减少ViewModel
责任,我们可以再添加一个组件,该组件可以承担从ViewModel
实现导航逻辑的责任
We call new component Coordinator
, since it acts as a coordinator between View
and ViewModel
.
我们将其称为新组件Coordinator
,因为它充当View
和ViewModel
之间的协调器。
Coordinator
would help ViewModel to hold single responsibility of implementing business logic, which means it’s more easily testable and re-usable now.
Coordinator
将帮助ViewModel承担实现业务逻辑的单一责任,这意味着它现在更容易测试和重用。
We could achieve separation of concerns with introducing fourth component(Coordinator) to MVVM.
通过在MVVM中引入第四个组件( 协调器 ),可以实现关注点分离。
致电MVVM-C以提高可读性,可伸缩性和可测试性 (Call MVVM-C to improve Readability, Scalability and Testability)
Overview of each component in MVVM-C:
MVVM-C中的每个组件概述:
Model
模型
- Represents data-objects 表示数据对象
Can be
struct
orclass
(Recommended to usestruct
, and confirm toCodable
protocol for easy encoding/decoding operations.)可以是
struct
或class
(建议使用struct
,并确认为Codable
协议以方便进行编码/解码操作。)
View
视图
- Responsible for rendering UI elements on screen 负责在屏幕上呈现UI元素
Make it dumb object, it should follow command of
ViewModel
only使其成为哑对象,仅应遵循
ViewModel
命令Recommended to make
View
dependant onViewModel
withProtocol
instead ofConcrete
types. (i.e DataSource, Loadable, Refreshable, Searchable etc.)建议使
View
依赖于具有Protocol
ViewModel
而不是Concrete
类型。 (即数据源,可加载,可刷新,可搜索等)Make it’s additional behaviour(except data rendering)
Abstract
(i.e LoadingDisplayable)使其成为额外的行为(数据渲染除外)
Abstract
(即LoadingDisplayable)
ViewModel
视图模型
- Responsible for implementing business logic 负责实施业务逻辑
Communicates with
DataLayer
to load data from API/Database与
DataLayer
通信以从API /数据库加载数据Acts as convenient
Datasource
forView
充当
View
方便Datasource
Must notify
View
when it’sstate
is changed(i.e isLoading, isRefreshing)state
更改时必须通知View
(即isLoading , isRefreshing )Must notify
View
when it’s updated(i.e with data from API/Database or any kind of sort/filter of data)更新时必须通知
View
(即使用API /数据库中的数据或任何类型的数据排序/过滤器)Optionally communicates to
Coordinator
forError
handling可以选择与
Coordinator
进行Error
处理
Coordinator
协调员
- Responsible for implementing navigation logic 负责实施导航逻辑
Instantiates and returns
ViewController
viastart()
method通过
start()
方法实例化并返回ViewController
Instantiates
ViewModel
and feeds it toViewController
实例化
ViewModel
并将其提供给ViewController
Optionally acts as
ErrorDelegate
ofViewModel
to handle errors(可选)充当
ViewModel
ErrorDelegate
处理错误Informs to parent cordinator via
finished()
method about it’s job completion通过finish
finished()
方法通知父项Cordinator工作完成情况
Till this point, we just focused on theoretical part. May be you’re not 100% clear about implementing MVVM-C.
至此,我们只关注理论部分。 可能您对实现MVVM-C不太了解100%。
Don’t worry!! In the following section, we would discuss around actual code to give you better understanding. :)
不用担心! 在下一节中,我们将围绕实际代码进行讨论,以使您更好地理解。 :)
We would build one demo application, which consumes remote API and populates list on the screen.
我们将构建一个演示应用程序,该应用程序使用远程API并在屏幕上填充列表。
In this demo, we used https://restcountries.eu APIs to populate countries on the screen, based on search keyword.
在此演示中,我们基于搜索关键字 ,使用https://restcountries.eu API填充了屏幕上的国家/地区。
Let’s start defining one by one entities for our application.
让我们开始为我们的应用程序定义一个实体。
模型 (Model)
As you can see below, I defined my Model as struct
and confirmed my Model to Codable
protocol for easy encoding/decoding.
如下所示,我将Model定义为struct
并确认Model to Codable
协议易于编码/解码。
To know more about Codable
, you can check my story: Essential of “Codable” in Swift
要了解有关Codable
更多信息,可以查看我的故事: Swift中“ Codable”的要点
视图模型 (ViewModel)
As I mentioned above, ViewModel
is responsible to implement business logic and notify View
about its state change.
如上所述, ViewModel
负责实现业务逻辑并通知View
状态更改。
So, I prefer to define ViewModel
protocol, with methods to keep notifying View
about it’s state change and notify View
when it’s updated with data.
所以,我更愿意定义ViewModel
协议 ,与方法,以保持通知View
它的状态变化,并通知View
时,它的数据更新 。
This mechanism to notify view would make communication between
View
andViewModel
pretty easy to implement and understand.这种通知视图的机制将使
View
和ViewModel
之间的通信非常容易实现和理解。It would also make
View
implementation clean and readable to render updated data whenViewModel
is updated.当
ViewModel
更新时,这也将使View
实现变得干净和可读以呈现更新的数据。
Now, we can define our concrete ViewModel
and let’s name it CountryListViewModel
.
现在,我们可以定义具体的ViewModel
并将其命名为CountryListViewModel
。
CountryListViewModel
confirms toCountryListDatasource
protocol, which would make CountryListViewModel
act as datasource for View
.
CountryListViewModel
确认使用CountryListDatasource
协议,这将使CountryListViewModel
充当View
数据源 。
CountryListViewModel
confirms to ViewModel
protocol to notify View
about state change.
CountryListViewModel
向ViewModel
协议确认以通知View
状态更改。
CountryListViewModel
implements “func seachFor(keyword: String)” method to confirm to Searchable
protocol.
CountryListViewModel
实现“ func seachFor(keyword:String) ”方法以对Searchable
协议进行确认。
CountryListViewModel
communicates to DataLayer via RequestManager
.
CountryListViewModel
通过RequestManager
与DataLayer进行通信。
And it communicates with Coordinator
via ErrorDelegate
protocol.
并且它通过ErrorDelegate
协议与Coordinator
进行通信。
CountryListViewModel
implements all required things, which we listed in above section with great Readability.
CountryListViewModel
实现了所有必需的东西,我们在上一节中以很高的可读性列出了这些东西。
We also increased Scalability of CountryListViewModel
, in a sense to easily add new behaviour.
我们还增加了可扩展性 CountryListViewModel
,从某种意义上讲可以轻松添加新的行为。
It can confirm to Refreshable
protocol and implement “func refresh()” method like we implemented “func searchFor(keyword: String)”.
它可以确认为可Refreshable
协议,并可以像我们实现“ func searchFor(keyword:String)”那样实现“ func refresh() ”方法。
Now, let’s have a look, how it helps to improve Testability of our code.
现在,让我们看看它如何帮助提高代码的可测试性。
As you can see above, we can easily test all responsibilities of our ViewModel
. It has code coverage of 100%.
如您在上面看到的,我们可以轻松测试ViewModel
所有职责。 它的代码覆盖率为100%。
And not only code coverage, it would make it easier to achieve 100% functional coverage to test various scenarios for your business logic.
而且不仅是代码覆盖率,还可以更轻松地实现100% 功能覆盖率,以测试各种业务逻辑方案 。
视图 (View)
I prefer to make View
dumb object, to make it easy to re-use.
我更喜欢使View
哑对象,以使其易于重用。
It must communicate to ViewModel
to fetch data to render it on screen. It should observe state change and updating of ViewModel
to refresh data on screen.
它必须与ViewModel
通信以获取数据以将其呈现在屏幕上。 它应该观察状态变化和ViewModel
更新以刷新屏幕上的数据。
CountryListViewController
communicates to Coordinator
via CountryListViewControllerDelegate
protocol.
CountryListViewController
通过CountryListViewControllerDelegate
协议与Coordinator
进行通信。
View
is dependant on protocol types forViewModel
in “func configure(viewModel: CountryListViewModelProtocol)”
View
取决于“ func configure(viewModel:CountryListViewModelProtocol)”中ViewModel
协议类型It would increase Scalability of
View
. For example, if we want to add ability to “refresh” screen, we could easily ask ourViewModel
to beRefreshable
like below.这将增加可扩展性
View
。 例如,如果我们想为“刷新”屏幕添加功能,我们可以轻松地要求ViewModel
如下所示是可Refreshable
。typealis CountryListViewModelProtocol = CountryListDatasource & ViewModel & Searchable & Refreshable
typealis CountryListViewModelProtocol = CountryListDatasource&ViewModel&Searchable& Refreshable
协调员 (Coordinator)
Coordinator
is mainly responsible for implementing navigation logic.
Coordinator
器主要负责实现导航逻辑。
I prefer to define Coordinator
protocol, which defines basic responsibility of Coordinator
.
我宁愿定义Coordinator
协议,它定义的基本责任Coordinator
。
Let’s implement concrete coordinator and name it CountryListCoordinator
.
让我们实现具体的协调器并将其命名为CountryListCoordinator
。
You can see that CountryListCoordinator
implements functionality of Coordinator
protocol.
您可以看到CountryListCoordinator
实现了Coordinator
协议的功能。
CountryListCoordinator
instantiated CountryListViewController
and returned it from start()
method.
CountryListCoordinator
实例化CountryListViewController
并从start()
方法返回它。
CountryListCoordinator
acts as delegate
for View
by confirming to CountryListViewControllerDelegate
protocol.
通过确认CountryListViewControllerDelegate
协议, CountryListCoordinator
充当View
的delegate
。
CountryListCoordinator
also acts as ErrorDelegate
of ViewModel
by confirming to CountryListViewModeLoadingErrorDelegate
protocol.
通过确认CountryListViewModeLoadingErrorDelegate
协议, CountryListCoordinator
还可以充当ViewModel
的ErrorDelegate
。
Implementing Coordinator
makes it easy to separate concern of implementing navigation logic from View
or ViewModel
.
通过实现Coordinator
,可以轻松地将实现导航逻辑的关注点与View
或ViewModel
分开。
We can easily test Coordinator
now.
我们现在可以轻松地测试Coordinator
。
MVVM-C helps to follow SOLID principles by Uncle Bob.
MVVM-C帮助遵循Bob叔叔的 SOLID原则。
SOLID principles helps you improve Readability, Scalability and Testability of your application.
SOLID原则可帮助您提高应用程序的可读性 , 可伸缩性和可测试性。
I hope you enjoyed reading this story and have good understanding of MVVM-C for your swift applications.
我希望您喜欢阅读这个故事,并且对快速应用程序对MVVM-C有很好的了解。
I would be happy to answer your queries.
我很乐意回答您的问题。
Happy Coding!! :)
快乐编码! :)
翻译自: https://medium/swlh/readability-scalability-and-testability-ae0d1d8b08c0
提高系统可读性和可维护性
更多推荐
提高系统可读性和可维护性_可读性,可伸缩性和可测试性
发布评论