iOS开发 (译文)

(翻译) 唯一可行的iOS架构

2019-12-06  本文已影响0人  Grabin
1.png

本文原创作者:Amirzhan Idryshev
原创文章链接:https://medium.com/flawless-app-stories/the-only-viable-ios-architecture-c42f7b4c845d

让我来猜一下你看到这个标题会怎么想。

这是另外一篇指责MVC,并且提供了另外一种“超级欺诈模式(忽悠人)”的架构,实际上只会产生更多问题的烦人的博客吗?这正是我看到另一篇iOS架构的文章的时候我所想的。MVC,VIPER,RIBLET,Clean Swift之类的。关于iOS架构,有几十个文章,但说的却是截然不同的观点和架构。

我们的开发者社区一直不停地在争论哪一个架构才是最好的。但真正的情况却是,它们所有的都是shit。任何认同这些“架构”的观点都是不能完全使人信服的。我们尝试着去使用一些“架构”,然后都陷入了一些没有“正常答案”的问题。最后,我们得到了一些尴尬的解决方案然后有了更多的疑惑。这一切看起来真的很奇怪。说实话,我最开始并不想写这篇文章,但是还是想写出来,毕竟这是iOS社区一个没有解决的问题。

告诉我一个架构“模式”,一个我们应该去用的。或者告诉我一个,一个并不让人感到奇怪的。我们现在有成千上万的架构,但没有一个是真正帮助到我们的,甚至没有一个让我们的代码看起来是一份好代码。为什么?

要想解决这个问题,我们应该从最开始的地方重新思考。我们将会对这些架构有个深刻的认识,并且意识到我们犯下了的错误。

如果我告诉你,iOS可能只有一个架构模式,而且它甚至不是一个架构模式。你会怎么想?

继续看下去,你将会意识到MVC的每一个变化是多么奇怪,在iOS社区里我们对它有深的误解,我们应该怎样去设计我们的app架构。

我们先快速过一下现有的一些架构

MVC



尽管开发者一直在争论要使用那种架构模式,但是apple已经给出了如何构建iOS应用程序的说明。就是 MVC

2.png

view 是用户能在屏幕看到的,model 就是 “数据”,controller是在他们中间的协调者。它从 model 里面拿数据,然后展示到 view 上,还得处理用户操作,并把它们传输给 model

看起来很好对吧。

那为什么不用 MVC呢,既然apple都这么指导了?原因就是,mvc 真的真的很烂。你可能知道,你的 ViewController 有多么庞大,有多难去维护。因为这里面有很多不一样的业务逻辑,数据需要在里面处理,这些都将会放在ViewController里面去实现。

Controllers 的主要职责就是管理它们自己的 view。它们负责对 view 的 loading,appearing,disappearing等等作出响应。它们还得去处理model一些的逻辑和业务逻辑,让 view 更纯粹只负责显示。但这就导致了我们的 Controllers 过于复杂臃肿的问题。

MVVM



我们不喜欢出现这样的问题,所以我们开始寻找能够替代 MVC 的解决方案。我们找到了它们。

3.png

MVVM 新增了一层 ViewModelViewModel 拆分了 Controller 的代码。但事实上它解决不了所有的问题。哪些代码才应该放到 ViewModel 里面呢? 当 ViewModel 的代码跟之前 Controller 那样臃肿的时候,我又该怎么处理呢?开发者社区分成了两派: “喜欢MVVM的” 和 “不喜欢MVVM的”。

MVP

另外一个尝试去解决这些问题的就是 MVP。它开始将 viewController 看成 view,并把所有的逻辑都放到了一个新增的类 Presenter。它并没有受到欢迎,因为它看起来真的很奇怪。实际上,这只是把问题从 viewController 转移到了 Presenter

4.png
VIPER



后来我们认为我们需要更多的分解,并创造出了 VIPER。所有的代码现在都变成了 View, Presenter, Router, Interactor, Entity 其中的一个。

5.png

在很短的时间内,VIPER 变得很受欢迎,但后来我们意识到它有一些不合理。这个架构需要很多的 protocolclass,和层之间的数据传递。但是由于某些原因,所有的额外这些工作都没能使我们的设计,代码可读性变得更好。

其他的一些架构

最后,我们在持续研究能够解决问题的架构的过程中陷入了一个循环回路。所有的这些看起来就像一个笑话。每个新的架构看起来都比之前一个更奇怪,都导致其它的问题。

但就像我之前说的,这些问题是有解决方法的,我将会告诉你,我们应该使用哪个 “架构模式”。你可能会感到惊讶,但它就是 MVC
我想要做的就是回到一开始的地方,从原始资源中去阅读 MVC,并停止逃离它。如果 MVC 还“活着”,还不断有人使用,证明它也许没有那么糟了吧?

最原始的MVC

很多iOS开发者在抱怨 MVC。但如果我告诉你,之前我们说到的所有问题,都是不存在的?“臃肿的ViewController” “Model是数据”,“ViewController做了太多的业务逻辑” 这些问题都是虚构的。所有这些问题都是出于对真正MVC的误解。

大家觉得它有很多的问题的主要原因是人们对 MVC的过度简化。认真地说,当你听到 MVC 的时候,你认为它是怎么样的?“MVC 里面分成3种类型:Model 就是数据,View 就是视图,Controller 是它们之间的协调者 ”。

拜托,MVC 并没有这么简单

MVC 是一个很巨大工程的产物。它是由 Trygve ReenshaugXerox PARC 开发 Dynabook 项目之后发明的产物。Dynabook是一个给所有年龄段孩子使用的个人电脑。这是一个革命性的项目,它旨在使计算机易于使用,同时使用户能够管理复杂的应用程序。这是图形界面的基础和“提升用户体验”的概念最早被触及的时候。

这个项目持续了接近10年的时间。Reenshaug 把10年来在图形界面应用程序开发的主要的思想和解决方案在 MVC 里面。

但它并意味着说,“嘿,我们这十年创造了一个可以解决任何问题的通用架构”。这是我们犯的一个根本错误。MVC 不是一个架构。它不是一个应用程序模块拆分的方案。没有人能够通过设计一定数量的类,就给你一个完美的解决项目问题方案,因为没人能够完全知道你存在的问题,也不知道你项目的业务逻辑,model的细节,还有你的主要目标。你应该自己去设计自己的应用程序。

以下是Martin Fowler描述 对MVC 误解会导致问题:

它通常被认为是架构模式,但我认为把它看作一种模式并不是那么有意义,因为它包含了很多不同的想法。不同的人在不同的地方阅读关于MVC文章,从中吸取了不同的想法,并将它描述成“MVC”。如果这并没有让你足够混乱的话,那么你就是受到了 MVC 误解的影响,这种误解是通过一个中文的系统传播起来的。

MVC 是一组架构思想和原则。MVC是第一次尝试将使用图形用户界面的应用程序的主要思想正规化。这些思路仍然是相关的,而且不仅仅在iOS平台。

MVC 其中一个重要的理论就是,把所有代码拆分成 “Presentation” 和 “Domain Model”。

Domain Model 是我们应用程序的核心,主要的组成部分。它由多个业务逻辑组成,例如账户、产品、交易等实体。围绕这些对象的逻辑我们称为业务逻辑。例如,“如果用户的账户没有钱,给他打折”。 MVC 中的 Model 是指整个域 Model(Domain Model),而不是单单指某个实体类的一个哑模型。域模型(Domain Model)可以包含一个对象以及整个对象系统。这取决于业务逻辑的复杂度。

Presentation 就是用户能看到和操作的那部分。在 MVCViewControllerPresentation 的组成部分。

** Martin Fowler ** 把这个理论命名为 Separated Presentation (分离表现)

MVC 的核心是对后来架构产生最有影响力的,也就是所说的Separated Presentation (分离表现) 的理论。分离表示背后的思想是在模拟我们对真实世界的感知的域对象(Domain Object)和我们在屏幕上看到的 GUI 元素表示对象之间进行清晰的划分。域对象应该是完全独立的,并且在不参考表示的情况下工作,它们还应该能够支持多个表示,可能同时支持。这种方法也是Unix文化的一个重要组成部分,并且在今天继续允许通过图形界面和命令行界面操作许多程序。

因此,如果我们的展示和域模型很少耦合,Presentation不用知道 “Domain model”的细节,并且域模型完全独立于展示,那么我们的应用程序的设计将是清晰的,可重用和可维护的。

下面这个图片摘自 Reenshaug 的报告。

6.png

Editor 就是 Presentation 的前身。在这个方案中,我们可以清楚地看到 MVC 并不是3个类。它更多的是按照层级划分,而不是根据类。最重要的点是,Presentation 应该跟 Domain Model 解耦。理想情况下,它应该只是依赖于所需要的接口,以便于任何 Domian Model 都可以实现此接口。门面设计模式(Facade pattern)表明,域模型中有一个类通过调用所需要的对象来实现此接口,这样表示就不需要知道域模型中任何具体对象。接口和Facade帮助我们对域模型Domain ModelPresentation进行解耦。

Domain Model应该怎么和Presentation进行通信呢?如果有这么一个例子,Domain Model 中有一些数据发生改变,它该怎么让Presentation知道呢?这是 MVC 的另外一个理论。Domain Model 不应该依赖于 Presentation,即使是通过接口。Domain Model 所能做的就是发送有关某个事件的通知,而不知道谁将会处理此事件。它可以通过观察者模式来实现。它将使我们完全独立Domain Model

另外一个图片摘自 Reenskaug 描述 MVC 的第三个理论。

7.png

它是关于把 Presentation 拆分成 “Input” 和 “Output”的。最初,将Presentation拆分成 负责向用户显示信息的层 和 负责从用户获取信息的层 是个非常好的主意。稍后你会看到,这个原则不适用于iOS环境,但是你应该知道,在最初的MVC中,Controller 和 View 都有图形表示。

总之,最初的 MVC 应该是这样:

8.png

它适用于iOS吗?

当然可以了!如果我们把 MVC 看作一套编程思想,而不仅仅是一个“三个类的模式”,我们永远不会知道 “臃肿的Controller”的问题,让我们来看看这些原则是如何适用于iOS的。

就如我们前面所说的,** MVC 的核心是 PresentationDomain Model 的强烈分离 **。实际上,这一原则已经成为可视化应用程序设计的主要原则之一。其它架构像 MVVM或MVP,也基于这种分离。不管你是为哪个平台编写代码,使用哪种架构,你始终都要进行这种分离。所以,这意味着这个原则对 iOS 也很重要。

如何在 View 和 Controller 上划分 Presentation?一般来说,它也适用于iOS,我们甚至在iOS的SDK里面有这些类:UIView 和 UIViewController。但是我们应该知道,这种分离与原来的MVC有一些不同。这一点也不奇怪,因为已经有一段时间来,很多东西都变了,用户界面也变了。现在,我们不需要在输入和输出上划分图形元素。特别在iOS上,每个UIView元素都能够显示信息并接收用户操作。因此,UIView是一个类,它有一个图形表示,负责在两个方向上与用户一起工作。而UIViewController是UIView的拥有者。它“控制”view及其生命周期,在view上处理用户操作,并在view上显示来自model的数据。

9.png

原始 MVC 的这种变体有一个不同的名称,我们稍后会看到它,但无论怎样,我们将称它为 MVC,因为主要原则还是被保存下来的,它只是MVC的变体。此外,苹果自己称之为 MVC。

实际上,我们怎么称呼它并不重要。最重要的是去理解它是怎么实现的。更准确地说,要意识到 MVC 已经实现了。UIView 和 UIViewController 是类,已经在iOS SDK中实现了。我是说,有些人拒绝 MVC,但仍然在使用 UIView 和 UIViewController。虽然,这是主要的,这也使得 apple的 MVC不同于其它架构。这是一种方式,我们处理用户交互的方式,像 “Interactior” 或 “Presenter” 这样额外的类不会改变这种方式。相反,根据实际问题的需要,MVC涉及额外的实体。尽管“Interactior” 和 “Presenter”是不好的类的例子,但是我们应该记住 MVC 不是一种模式,而且我们可以根据需要去创建很多的类来解决问题。所以,如果你在用户前面使用 UIView 和 UIViewController,不要介意创建其它的类,你使用 Apple 的 MVC。

那我们能不用 UIViewUIViewController 吗?肯定不行!很多工作都是在幕后完成的,因此我们可以轻松地处理用户与我们应用程序的所有通信。除了这两个类之外,还有很多东西:响应链、UIEvent、UIView层次结构、UIView 生命周期、点击测试、UIControls、UIGestureRecognizers等等。所有这些都是Apple MVC。这意味着MVC不是我们的选择。如果你说你不用MVC,实际上,你还是在使用!我们使用MVC,在iOS中我们不能找到其它能够替代的方案。

跟 iOS SDK 抗争是不可能的,任何尝试都会使系统复杂化。但如果我们能理解这一点也不会很糟。一旦我们停止与iOS SDK的斗争,所有这些东西都会变得有用。SDK开始帮助我们,让我们从中收益。每个UIViewController拥有一个根UIView。我们只要在界面生成器中绘制视图而无需任何代码,并将所有用户操作链接到 UIViewController。UIViewController通过 viewDidLoad() viewWillAppear() 等方法处理view的状态,我们应该使用所有这些特性。

iOS SDK 提供了很多的特性。很多开发者抱怨 UIViewController变臃肿了,但只有一小部分人谈到UIViewController的分离特性。这就是为什么很多开发者都会感到惊讶。但是我们可以为一个屏幕创建多个UIViewControllers。是的,如果一个屏幕上有多个逻辑独立的组件,我们可以将其划分为多个小的UIViewController。

你还认为使用 MVC会导致“ViewController臃肿”的问题吗?让我们再回顾一遍反驳它的主要内容。

  1. UIViewController 是视图显示(Presentation)层级的一部分。如果你在里面写了业务逻辑,网络请求或者其它无关用户界面的代码,那它就不是MVC。

  2. 如果需要的话,在视图显示(Presentation)层级创建其它的类。UIViewController的存在并不是强制让你在那里写所有的代码。如果你有很多的表示逻辑,请将其从ViewController中抽取出来,但得确保新的实体是必要的。

  3. 不要和 iOS SDK对着干。它为我们提供了很多的功能,如果我们开始使用这些功能,会给我带来很多的好处。

那我们需要 MVC 的替代方案吗?

答案是显而易见的。我们不需要它们。你已经了解了什么是真正的MVC,以及如何在iOS中使用它。此外,使用自己的架构,几乎不可能与iOS SDK 对着干。让我们重新考虑一下每一个架构,我们一开始就已经描述过了,你会发现它们在iOS环境中是多么的奇怪。

MVP

MVP 是里面最奇怪的一个了。 列举下它的一小部分历史来说明这一点。MVP是由 Mike Potel 在 1996年引入的,是对MVC的一种改进。在他关于MVP的工作中,Mike Potel 建议不需要将小部件划分为视图和控制器。现代操作系统用户界面以及在视图类中提供了大部分的控制器功能,因此控制器看起来有点多余。因此,控制器被移除,一个新的类 Presenter被创建为视图和模型之间的黏合剂。

等等,这看起来跟apple的MVC很像?还是它可能就是apple的MVC?难道apple用的是MVP,跟我们说MVC?我不知道,因为这些术语之间有太多的混淆。让我们看看 Martin Flower 在其关于可视化应用程序架构的文章中是怎么区分 MVC 和 MVP 的。

MVP使用一个监控控制器(Supervising Controller)来操作模型。小部件将手势传递给监控控制器。小部件并没有被分成视图和控制器。你可以将 Presenter 看作控制器,但不需要对用户的手势进行处理。不过,还需要注意的是,Presenter 通常是在表单级别,而不是小部件级别 ---- 这可能是一个更大的区别。

10.png

现在,看看MVC 和 MVP的这些方案。并将它们与我们以前看到的Apple MVC 进行比较。哪一个更像 Apple MVC?是的,
Apple MVC看起来更像MVP,但不是原来的MVC。但再说一遍,我们怎么称呼它并不重要。此外,Apple MVC无论如何都不同于两者。

最重要的是要了解我们已经有了作为 UIView 持有者的 UIViewController。这意味着我们不需要任何具有 Presenter 或者 Controller 角色的附加类

因此,尝试创建一个新的 Presenter 类并将 UIViewController设为View是毫无意义的。尽管我说过,除了UIView和UIViewController之外,表示层还有其他的类,但Presenter是一个不好的例子。这是一个与iOS SDK对抗的例子。无论我们希望将UIViewController看作View,它仍然是一个Controller(或者你可以称之为Presenter)。而在iOS中,MVP的方案实际上是这样的:

11.png

我们真的需要这个新的类吗?它看起来很奇怪,因为我们只是完全用相同的角色创建了一个UIViewController的副本一样。为什么我们要将所有的用户操作、所有的视图状态从Controller改到Presenter(如果它没有带来任何好处)?它只会给我们带来额外的代码复杂性。很难将每个动作委托给Presenter。再说一次,不要和iOS SDK对着干,我们不能把UIViewController变成View,即使我们可以,我们也没必要这么做。

VIPER

记得我刚说 MVP是最奇怪的一个吗?不,VIPER才是。因为,除了MVP的所有问题(它重复了MVP在表示层中的所有错误,包括复制Presenter和试图将UIViewController转换成View的失败尝试)之外,VIPER还试图将我们的域模型划分为interactor、service和entity类。

VIPER 是如何产生的?它像MVC或者MVP一样有自己的历史吗?是的,但是历史没那么辉煌。VIPER创建于2013年,旨在解决apple MVC 问题。

由于许多应用程序逻辑不属于Model或者View,因此通常在Controller中结束。这导致了一个称为“臃肿Controller”的问题,Controller最终做了太多的工作。

上面的引述是从最初关于 VIPER的帖子。这意味着VIPER被创建来解决不存在的“臃肿Controller”问题。它是基于“MVC 是一个有3个大类的庞大的UIViewController的模式”的错误思想而创造的。为了解决这个“问题”,VIPER用5个类进行了更多的拆分。但实际上,你的“架构”有多少个字母并不重要。如果你认为你的应用程序只是一个“模式”,有确切的类,你无论如何都会失败。类的数量是有限的,但是每次逻辑都可能更多,这样我们的 "interactor" 或者另一个类也就成了另外一个“臃肿Controller”。

而且,逻辑是可以不同的。但在VIPER中,我们总是创建5个类,即使逻辑很少或者非常特殊。问题就会变得不一样,没有一个方案适合解决所有的问题。我们应该根据这个特定的逻辑,单独分解。在OOP中,理解我们应该创建哪些实体,它们应该如何关联以及如何命名它们 让代码更清晰是一项很常见的任务。

Chris Eidhof 在 《应用程序架构》一书中对VIPER问题和分解有一些很好的想法。

虽然接口分解是管理代码大小的有效方法,但我们认为它应该根据需要执行,而不是按系统和按视图控制器执行。分解应该于所涉及的数据和任务的知识一起执行,这样就可以实现最好的抽象,从而减少复杂性。

“interactor” 是一个很好的抽象吗?interactor的定义是否定的,“interactor是一个包含业务逻辑的类”。拜托,这有助于我们理解代码吗?它包含哪些业务逻辑?如果我们有很多的业务逻辑呢?我们应该创建和命名我们的实体,使其清晰和具体,而不仅仅是一般的“interactor”。

为所有的问题创建相同的类,每次都只向这些类添加代码都不是一个很好的设计。它甚至不是面向对象的,我把它看作是5个文件的过程式编程。

在我看来,VIPER是我们可耻的错误。VIPER证明我们还不够理解MVC。在阅读原始材料之前,我们已经开始抱怨MVC,并想出了这样一件奇怪的方案。我的建议是,忘掉VIPER,再也不要讨论VIPER了。

MVVM

如果我们不把业务逻辑代码放在UIViewController里面,而是将业务逻辑分解成一个屏幕多个UIViewControllers,那么我们的UIViewController永远不会变得臃肿吗?好吧,这取决于它具有多少表达逻辑。

让我们来思考一个例子

// Domain Model Object
struct Person {
    let name: String
    let gender: Gender
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // presentation logic 
        if person.gender == .male {
            nameLabel.text = "Mr." + person.name
        } else {
            nameLabel.text = "Mrs. " + person.name
        }
    }
}

在上面的例子中,我们有一个关于根据用户性别显示不同person name的逻辑。这个逻辑代码应该放在UIViewController吗?如果存在很多复杂的表示逻辑怎么办?除了复杂性之外,还存在测试问题。测试UIViewController类并不容易。这是有的开发者为什么把UIViewController的逻辑转到Presenter中,或者使用它的子类。但是我们已经看到了这种方法的问题。

我们可以把这部分逻辑放到 Person 类里面吗?在这个例子里面,它根据MVC原理将表示和业务逻辑混合在一个不好的类中。很难理解为什么有此代码。我们看不到该代码是针对哪个具体视图编写的。最后,很难在不同的屏幕上重用此模型。如果在其他屏幕上以不同方式显示此信息(例如表情符号)怎么办?

现在,我们再次强调MVC不是模式。是的,我们在Presentation层中有一些逻辑,MVC不会强制让你把逻辑代码放在现有的类中。Martin Fowler谈到了这个问题。他说,如果与域模型对象不同,我们可以在Presentation层中创建其他模型。他称这个对象为Presentation Model

struct PersonPresentation {
    let name: String
    init(person: Person) {
        if person.gender == .male {
            name = “Mr.” + person.name
        } else {
            name = “Mrs. “ + person.name
        }
    }
}

现在,在UIViewController中,我们仅需要将name显示在label上。

你可能会说它是MVVM,但实际上并不是。尽管我们将其称为MVVM,但事实并非如此。因为实际上,MVVM于2005年创建,是对MVC和MVP的修改。添加了ViewModel而不是Controller和Presenter,它可以处理View操作。但是在iOS中,我们仍然没有摆脱Controller。UIViewController处理我们与用户交互的方式。我们要做的就是在Presentation层中创建一个额外的模型,这在MVC中是隐含的。我们只是使用了一个Presentation Model。

但还是得再说一下,命名并不是一个大问题。当然,我们不会将所有ViewModels重命名为PresentationModels。但是,我们应该了解ViewModel的真正含义(为避免混淆,现在将其称为PresentationModel)。

PresentationModel不是包含所有业务逻辑的类,很多开发人员都这么说。 PresentationModel不是将网络请求,数据库请求,缓存等组合在一起的接口(门面模式)。它只是Presentation层中的模型。使用PresentationModel并不意味着我们使用另一种架构。我们仍然使用MVC,因为我们不会更改与用户合作的方式。

通常,PresentationModel只是一种模式。是的,与MVC原始MVVM不同,PresentationModel是一种在真正需要时使用的模式。无需进行标准化,也无需无故在每个模块上创建PresentationModel。

总结

MVC不是表示根据类名划分成3个类的方案那么简单。 MVC不是模式,而是一组架构思想和原则。

这些原则的核心是表示层(Presentation)和域模型(Domain Model)之间的强烈分离。 MVC中的模型表示整个域模型。 UIViewController是Presentation的一部分。这意味着MVC不允许我们创建一个哑Model并将所有业务逻辑移入UIViewController。

这种分离已成为图形界面应用程序设计中的主要分离之一,它们对iOS也很有用。但是表示层(Presentation)分离通常是特定于平台的。iOS SDK已经完成了很多工作,因此我们可以轻松地通过我们的应用程序处理用户的所有交流。因此,MVC不是我们的选择,我们无法更改与用户交互的工作方式。我们不应该和iOS SDK对着干,这样会使我们的设计变得很复杂。但是,一旦我们顺着iOS SDK的设计来,所有这些sdk就会变得有用。

除了根据业务逻辑设计域模型(Domain Model)外,我们还可以根据表示(Presentation)的逻辑来设计它。 MVC不会强迫我们在UIViewController中编写所有代码。如果需要,我们可以在Presentation层中创建其他类。但是,如果你添加ViewModel或Coordinator或其他名称,请不要将其称为新架构。

最后,请勿尝试将架构标准化为模式。根据特定的场景特定的逻辑进行分解,才能更清楚地描述代码。

别再抱怨 MVC 了。

附言:让我们停止这些吧!

这篇文章的主要目的是想说明现在的情况有多奇怪。我们没有去反省一下我们在MVC的认知上犯下的一个很大的错误。我们没有去正确认识原始的MVC,反而相信了一些有误导性的内容,例如 “臃肿的View Controller”,“ VIPER架构”,“架构模式”等等。

我们现在正确认识错误了,就必须停止它!我们应该停止认为应用程序设计如此简单,可以使用某种模式来完成,我们应该停止寻找解决所有问题的灵丹妙药,我们应该停止责怪MVC并停止讨论MVC替代品,这些对于iOS来说是不常见的。听到说“ MVC很糟糕”,“ ViewController做很多业务逻辑”,“模型就是数据”的人,阻止他们,并向他们解释大家对MVC的误解。

如果我们能停下来抱怨,对我们的社区将是巨大的进步。我们应该理解,架构设计不仅仅是模板或模式,而是一个复杂的过程。这是经验带来的技能。如果我们不是随波逐流地遵循一些时髦的“模式”,而是根据问题的具体情况,平台的功能以及对通用设计原则的了解,针对性地解决每个问题,我们的技能将开始提高。

上一篇 下一篇

猜你喜欢

热点阅读