Tag: 清洁架构

iOS上的Cleaner Architecture

今天,我不会教您任何新手或突破性的东西。 相反,我只是想提醒您一些您已经知道的事情:单一责任原则(SRP)。 更具体地说,我想讨论如何在干净的体系结构中正确使用它,并且假定您已经对它有所了解(如果不是,我建议您阅读下面的资源,然后再回来)。 因此,请不要忘记提醒自己在制定决策时明确考虑SRP,并希望这将有助于我们设计更好的软件! 什么是SRP? 这里是一个定义[1]:“单一责任原则是一种计算机编程原则,它指出每个模块或类都应对软件提供的功能的一部分负责,而责任应由类完全封装。 其所有服务应严格地与这一责任保持一致”。 一个班级只有一个改变的理由。 这样做将使更改变得更容易,减少耦合,提高可测试性,加快开发速度等等! SRP也是干净架构的基本思想(但是,它当然也适用于其他方法,例如MVC,MVVM,反应式等)。 为什么不使用MVC? 明显的答案是:因为Massive View Controller。 这当然是个玩笑–但很有趣,因为它是真的。 几乎可以问一个问题:当MVC导致大量问题(例如大规模视图控制器)时,为什么MVC是iOS上的默认体系结构? 答案是,这首先不是问题。 如果控制器很大,那不是体系结构的问题,而是程序员没有正确使用它。 您可以使用MVC编写一个非常干净的应用程序,而大型视图控制器问题可以通过以下方式轻松解决: 在一个场景中不只使用一个控制器, 将工作委托给工人/服务班级。 换句话说,通过应用SRP。 那么,如果不是MVC,那么为什么要使用干净的体系结构呢? 如果在iOS上使用的MVC出现问题,则说明它相当模糊,并且将许多决策留给了程序员。 控制器的责任是什么? 如果您不小心,它将获得太多。 但是,我们将所需的所有其他责任放在哪里? 在模型中? 我们该如何构造? 该架构并没有真正告诉我们任何这些。 我们靠自己,这意味着有很多机会引入错误! 如果您不想考虑所有这些,则可以使用简洁的体系结构。 干净的体系结构明确地在其类之间划分了一些职责:演示者弥合了UI和业务逻辑之间的鸿沟,交互者处理了我们的用例,路由器帮助我们进入了新的场景,等等。职责很明确,我们的代码库更加简洁。 那么,仅通过使用干净的体系结构,我们是否可以解决问题? 现在我们的代码库中有SRP吗? 好吧,不一定。 架构是很有帮助的,但不能解决我们所有的问题。 我们仍然需要思考,做出选择,并付出一些努力使事情变得更加干净。 MIP 干净的架构在Apple平台上已变得非常流行,这是有充分的理由的。 我们甚至可以选择几种方法,例如VIPER [4]和Clean Swift [3]。 让我们看一些使用Clean Swift(或我喜欢称之为CS的真实项目),它与我们在iOS上使用的体系结构的命名约定一致。 我见过带有大型和复杂交互器的代码库,这些代码库显然不遵循SRP。 我称其为巨大的交互器问题(MIP)。 MIP可能不如大型视图控制器那么糟糕,因为交互器并不关心UI,但它们仍然尝试做太多事情。 如果程序员能够编写大规模的视图控制器,那么他当然也会编写出色的大规模交互器。 问题是,即使我们认为我们使用的是干净的体系结构,责任也没有得到适当的分离,因此没有尽其所能。 为避免MVC / MIP问题的根本原因,我们将无情地应用SRP。 交互器包含应用程序业务逻辑,但是每个视图控制器只有一个交互器。 […]

毒蛇的第一个项目

在完成我在Viper的第一个项目之后,这篇博客文章只是一些个人经验。 如果您以前从未听说过Viper和干净的体系结构,则应该明确地观看此视频: 最初,一切都进行得很顺利,当我独自从事该项目时,我对自己感到非常高兴。 但是随后另一位开发人员加入了🙂他的第一个反应并不令人鼓舞: 男人,这个毒蛇的东西有点冗长。 我在各处写协议和存根…… 因此,我再次查看了代码。 好吧,他是对的。 如果您遵循这本书,最终会得到很多协议,在大多数情况下只能使用一次。 那时的某个地方,我还观看了有关保持代码可持续性的视频: 类由不同颜色的圆圈表示,您在类中的依存性越高,圆圈越大。 中心的蓝色大圆圈是AppDelegate。 好吧,它保留了对某些顶级视图控制器的引用,处理了一些通知,初始化了一些数据访问对象。 似乎其中没有太多代码,但最终仍然有很多讨厌的依赖项。 如果您考虑一下,这是有道理的。 AppDelegate可以引用RootViewController,而RootViewController可以引用MenuViewController,依此类推。因此,依赖关系的增长。 第二张图是我的第一个Viper项目。 AppDelegate做得少得多。 基本上,它只是创建一个根线框并将控制权传递给它。 每个模块仅知道需要直接调用的模块。 当然,这是您在任何项目中都想拥有的东西,但是在Wireframes中进行所有设置会使依赖项更加公开,并有助于使模块具有针对性和隔离性。 我最喜欢的是: 错误少很多。 它们几乎没有,而潜入其中的那些易于修复。 代码变得更像可互换的乐高积木。 使用现有模块组装新模块,重新组装旧模块,引入接口并为某些类添加不同的实现,所有这些都很容易做到。 我认为,这种方式的主要原因是依赖注入以及线框中所有模块的创建/组装。 再一次,重构非常容易。 想象一下,更改应用程序的整个导航树不会再让您感到恐惧🙂 几个月后,我很想再次查看该项目。 但是到目前为止,它看起来非常有前途!

iOSをMVC,MVP,MVVM,清洁架构で実装してみた

何番煎じだよって感じですが,アーキテクチャに対する考チャに対する方は割と正解がなくて,自分の中に一つ落とし込んでおいて损はないと感じたため,补充という形で记事にさせていただきます。 アーキテクチャとは? 一言でいうと, アプリケーションを绮丽丽装するための设计方法! アーキテクチャを考虑しない设计でコードを书いていると以下のようなスにぶち当たります。 一つのクラスの肥大化(iOSで言うところのFatViewController) ロジックが烦雑になる 同じ处理を使い回せない チーム开発で役割分担しにくい テストがしにくい 属人化が进み,引き継ぎが难しくなる 机能の追加,修正が困难 等等… 正直まだまだあるとは思いますが,とにかく设计はこだわってないと后で地狱を见るということさえ伝わればOKです。 示例应用 アーキテクチャを语る上で叩き台にするアプリがいるなーと思ったので作りました。 阅覧するときは,见たいアーキテクチャのチャランチ(master / mvc / mvp / mvvm / clean-architecture / clearn-architecture + mvvm)に切り変えてください。 https://github.com/rockname/ArchitectureSampleWithFirebase Firebaseでユーザーの登录/登录,投稿のCRUD处理をする,ものすごくシンプルなアプリです。 FatViewController ブアーキテクチャのない世界をみなさんにはお见せしましょう。(ブランチはmasterです) 投稿一覧シーンであるListViewControllerを见てもらうとわかりますが,こんなに単纯なアプリにもかかわらずすでにコードが123行あります。 ViewControllerがすべての役割を担わされていることがわかりますね。 非常に胖な状态です。 役割 ViewController UIのレイアウト UIの更新 ユーザーのアクション通知 データの处理 データの更新通知 ビジネスロジック 评価 いいところ🙆‍ 思考停止でコーディングできる(これはいいところなのか…?) UIKitの恩恵を最大に享受できる 悪いところ🙅‍ それ以外すべて 模型视图控制器(MVC) Webアプリケーションフレームワークでよく闻くやつですね。 Appleの公式ドキュメントでもiOSアプリ开発はMVCが一般的みたいな书き方がされています。 https://developer.apple.com/jp/documentation/CocoaEncyclopedia.pdf しかし,iOSのUIフレームワークであるUIKitはViewとControllerが密接に系がっており(ViewControllerというクラスがあるくらい),iOSのMVCはよくMassiveViewControllerだなんて皮肉を言われています。。 […]

将您的iOS应用程序网络层重构为模块

在每个项目上,总是需要改变核心服务。 这可能是由于不同的原因,对我们使用的库所做的更改,第三方/ Apple库上不推荐使用的方法,或者我们只是想迁移以开始使用新的库或API。 这种“小”变化可能会影响我们的开发速度,可能需要大量时间才能完成和/或可能会引入错误。 我们会做什么 在本文上,我们会将所有与网络相关的文件重构为一个模块。 然后,将网络服务和所有相关类迁移到动态库中,最后将使用URLSession更改为Alamofire 。 你需要知道的 要继续阅读本文,您需要熟悉以下内容: Cocoapods(您可以在此处阅读有关Cocoapods的更多信息) URLSession (很高兴知道) Alamofire ( Alamofire知) 即使您不熟悉最后两个库,您仍然可以利用本文。 初始点 您可以从这里获得本课程的起点材料。 第一 打开.xworkspace (或.xproject ,此时不起作用)并运行( command + R )。 该应用程序非常简单; 它可以让您搜索艺术家并显示其所有专辑,仅此而已。 简单直接。 现在,我们已将应用程序设为初始状态,让我们开始向项目添加动态库。 单击项目导航器顶部的项目。 现在,在“目标”窗口中,单击左下方的加号(+)。 现在一直向下滚动,直到到达“框架和库”,选择“ Cocoa Touch Framework”,然后单击“下一步”。 现在输入名称(我叫我的NetworkService),然后单击“完成”。 创建框架后,您应该在“目标”窗口和“常规”选项卡的“链接的框架和库”上看到它。 第二 现在我们有了框架,让我们将与网络服务相关的所有类移到新创建的名为“网络服务”的文件夹中(或者您将其称为框架) 太好了,现在,如果您运行该应用程序,则会在视图控制器上注意到一些错误。 修复此错误非常简单,只需在视图控制器上import NetworkService 。 再次运行该应用程序,它应该可以正常运行。 太好了,我们只是模块化了我们的网络服务。 第三 现在,该项目正在使用URLSession处理所有网络调用。 随着项目的增加或时间的推移,由于Cocoa Touch API或第三方库的更改,很有可能需要重构,更改或改编代码。 现在,让我们重构网络管理员以使用Alamofire代替URLSession 。 我们需要做的第一件事是更新Podfile […]

另一个干净的架构

你在跟我开玩笑吗? 还没有足够的干净架构模式吗? 是的,有。 像VIPER / Riblets一样,它们都是完全相同的清洁体系结构原理的不同方法,但是它们在细节或处理某些元素的方法上有所不同。 一切始于著名的Bob叔叔的文章,因此请务必查看一下。 我们在这里介绍的是我们在Tooploox成功介绍的一个(感谢出色的Jorge Ortiz研讨会,不要错过他的作品)。 事实证明,这对我们的工作流程和代码质量非常有用,我们希望通过本系列文章分享一些经验。 为什么架构很重要? 在考虑我们的应用程序体系结构时,我们不应该考虑是否使用一种,而是要使用哪种。 有效的体系结构有助于创建结构化,易于理解的代码,从而降低维护成本。 由于每个人都可以独立工作,因此将所有模块模块化可以使团队合作更加轻松和富有成效。 它有助于设计解决方案并减少出错的可能性。 不必担心事物如何协同工作或如何连接某些零件,您可以专注于实际的逻辑。 最后,它将项目管理提升到一个新的水平,即由于在熟悉的环境中使用了经过验证的模板,因此计划和估算更加准确。 它还降低了新团队成员的进入门槛,并使团队更加灵活。 那么,为什么不简单地使用MVC,MVVM呢? 为什么还要另一个复杂的解决方案? 别误会,MVC和MVVM是有效的体系结构。 他们各有优缺点,可以用来创建出色的解决方案,但它们确实有局限性。 通常,MVVM很难扩展。 毕竟,移动应用几乎绝不是仅有的一些功能和几种视图。 随着功能数量的增加,MVVM开始变得难以维护,视图模型变为大规模视图模型,因此很难将所有内容按原样分开。 另外,如果您关心单元测试,那么MVC / MVP / MVVM也不是最佳选择,因为出于测试目的而分离元素和模拟依赖项要困难得多,并且每个组件往往都有多重职责。 如果您曾经使用过MVVM,则可能已经注意到它不是完整的体系结构。 它缺少诸如路由或依赖性管理之类的一些基本层,并且通常通过引入协调器或强制破坏封装并使组件以非结构化方式相互通信来完成。 通过使用干净的架构,您的代码将变得更加模块化,结构更好和高度可扩展。 每个元素都是轻量级的,并且遵循(至少尝试)遵循单一职责规则。 通过控制反转,各层具有良好的分离性,因此组件易于更换。 使用这种结构编写单元测试很简单,可以模拟依赖关系,并且功能简单且易于进行单元测试。 通过松散耦合元素,可以对同一特征进行并行编码。 只需就协议和合同达成协议,然后做好您的工作即可。 使用功能要容易得多,因为您可以一次将精力集中在一个问题上,而不必关心其他任何事情。 硬币的另一面。 但这确实有一些缺点。 它很复杂,一开始有时很难理解,而且入门门槛很高。 它也有点肿。 您将创建很多不同的协议,类,工厂,并且您将必须管理所有文件。 这不是轻而易举的事情(记住缺乏适当的反思并不能帮助迅速进行依赖注入管理)。 这些文件/类中的许多都是简单的传递实体,因此有时感觉像是在浪费时间,但这是有原因的。 它还有点违反框架和官方准则。 Apple API被设计为可与MVC配合使用,因此有时您必须要有一些技巧才能使其与干净的体系结构相处。 最终,我们发现所有的努力都是值得的,缺点并没有真正掩盖我们作为团队所获得的收益。 确实,关于干净架构的资源并不多,可以通过实际示例逐步解释一切。 我们认为这是有时在移动开发中忽略更复杂的体系结构的原因之一。 我们想改变这一点。 让我们开始吧 干净架构的主要重点是将模块分为多个层:连接器,演示者,视图,用例和网关,这些层符合SOLID原则。 […]

MVVM和Clean Archi如何帮助使用BDD方法

我们将尝试演示MVVM和Clean Archi如何帮助以BDD方法进行开发(行为驱动开发)。 该示例源代码可在此GitHub存储库上找到。 本杰西/计算器 计算器–具有BDD,Clean Archi和RxSwift的示例github.com 好的方法是从用户需求和示例映射开始。 我们将使用一个非常简单的示例来描述一个附加项。 通过这个非常简单的示例,我们试图证明MVVM / Clean Archi / RxSwift概念不仅有助于使用BDD,它们也是有教益的。 使用这种严格的方法,我们必须思考:一些输入,一个转换函数和一些输出:有助于我们清楚地识别不同的步骤。 现在我们不再问自己:我可以在哪里使用测试以及必须测试哪些类…… 请享用 ! 😉

iOS:RxSwift +干净的架构

在上一篇文章中,我们有机会从概念上定义应用程序的体系结构。 这篇文章的目的是深入了解我们正在使用的该体系结构的关键组件的实现。 在这篇文章中,我们将讨论如何实现: RxSwift +干净的架构 我们的应用程序使用ReactiveX swift版本:RxSwift。 RxSwift是组合异步操作和事件/数据流的强大工具。 这些流使层之间的通信变得容易。 这就是为什么我们认为它完全适合我们的架构需求。 该方案表示RxSwift流经体系结构不同层的方式: 基本上,Presenter执行返回一个Observable的用例。 此Observable在数据层上创建,并由域层传递。 演示者订阅此Observable来从存储库中获取结果。 但是,什么是可观察的? 如果我们阅读RxSwift的入门文档,我们可以理解什么是Observable: 每个Observable序列只是一个序列。 Observable vs Swift的Sequence的主要优点是它还可以异步接收元素。 这是RxSwift的内核。 让我们逐层介绍实现: 实作 UI层 演示者有一个要执行的用例。 方法execute返回一个Observable。 演示者订阅了此Observable: 请注意,在订阅关闭之后,我们将调用disposed(by: disposeBag) 。 此方法将订阅添加到disposeBag中以取消该订阅。 最后,在闭包内部使用[unowned self]或[weak self]并使用dispose(by:)方法可以避免内存泄漏。 😉 域层 用例具有一个execute方法,该方法调用CatalogRepository协议方法并返回由该存储库创建的Observable: 资料层 数据存储库实现在域层中定义的CatalogRepository协议,并具有数据源和数组。 这些数据源又实现了CatalogDataSource协议。 在数据存储库的每个方法内部,它为包含的每个数据源从CatalogDataSource调用一个函数。 为了连接这些调用,我们使用Observable的操作concat ,如下所示: 远程数据源创建一个Observable并使用Alamofire执行请求。 响应结果将通过Observable onNext() , onCompleted()或onError()方法发送给演示者。 就这样! 通过层连接完成! ✅ 这可能是每个人的应用程序中的常见情况,但是RxSwift是一个功能强大的工具,这只是冰山一角。 让我们深入了解我们在项目中使用更多的东西之一: 经营者 RxSwift中有许多运算符:创建,转换,过滤,合并……可以使您的生活更轻松。 […]

MVVM et Clean Archi peuvent cadrer l’approche BDD

MVVM和Clean Archivent faciliter和cadrer la mise场所的简单示例说明BDD(行为驱动的开发)。 Github上的所有消息来源: 本杰西/计算器 计算器– BDD和带有Cucumberish和RxSwift的Clean Archi github.com 倒入开胃菜,不添加任何示例性的调味品即可。 例举者,蒙特维尔评论MVVM / Clean Archi / RxSwift peuvent faire plus ques’intégrerparfaitement dans unedémarcheBDD: il sontmêmedidactiques。 结构化教学方法,实体入门方法,转换等方法,基本原理以及可识别的标记。 Il n’y a donc plus 吹捧审讯: oùdois-je places mes测试,quelles sont les长沙发que je dois traverser… 请享用 ! 😉 原则上对地方和地方的保护的原则: AXA Banque Dans L’App Store 咨询与比较,实用工具的注释,视觉捕捉德克兰与德古弗雷斯的AXA Banque… itunes.apple.com

Swift中的UI测试

一,为什么要使用UI测试? 1.自动化手动测试🤖 测试应用程序时,我们总是重复相同的过程以测试我们没有破坏任何东西。 我们可以通过一系列与手动测试相同的测试来实现这一目标。 2.表示层中的逻辑丰富🌅 我们拥有的UI逻辑越多,我们测试的内容就越多 3.节省时间⌚️ 有了一系列的ui测试,我们可以在更少的时间内每次都重复相同的手动测试。 二。 我们可以测试什么? 纽扣 刷新表格 输入文字 滑杆 检查导航栏标题 推拉视图控制器 重新排列细胞 等等.. 您可以查看此UI测试备忘单以获取更多信息。 三, 我们如何正确测试? 1.有助于将逻辑与表示法separate分开的架构。 当我们谈论MVC时,我们都知道它不是非常可测试的,因为视图和控制器之间的交互非常紧密。 我们可以使用MVVM或VIPER架构,通过更好的分布来实现更好的可测试性。 您可以查看这篇很棒的文章,以获得更多信息iOS体系结构模式。 2.依赖注入💉 这种软件设计模式允许在运行时而不是在编译时选择组件,目的是用Test Doubles代替生产代码。 依赖注入的示例将类似于以下ServiceLocator: CharactersViewController :是主视图控制器,并显示GOT字符列表。 CharacterDetailVC :显示CharacterDetailVC的详细信息。 字符VC测试 辅助方法 我们将在测试中使用一些辅助方法。 我们将不再需要手动重复此过程this。 五,从这里去哪里 在github上检查整个项目,查看所有使用的配置和框架。 尝试自己编写一些UI测试。 创建您自己的项目,并按照此结构做一些事情! VI。 归因 GOT Challenge Swift应用程序基于Idealista GOT Challenge Android。

SRP:单一责任原则

单一责任原则(SRP)规定,每个软件模块或类都应该有一个且只有一个更改理由。 除佛陀本人外,任何人都不承担透露神秘秘密的责任。 。 。 将因相同原因而发生变化的事物聚集在一起。 分开那些由于不同原因而改变的事物。 鲍勃·马丁 难以理解,因此难以维护。 重用困难。 由于职责在同一个类别中紧密联系在一起,因此很难在不损害其他职责的情况下更改其中一项职责(刚性),并且最终可能破坏软件的其他部分(脆弱性)。 高耦合,即该类具有过多的依赖性,因此,由于其他类的更改(同样是脆弱性),因此更容易发生更改。 让我们考虑一些可能需要分开的职责: HTTP API调用 -如果需要修改标头或基本URL,则只能将其修改为HTTPClient 。 无需为此其他文件做任何更改。 创建视图状态-创建视图状态应该由工厂或转换器负责。 验证 — 所有验证逻辑都应封装到单独的Validation类中,以便将来只有一个人负责修改验证逻辑或添加新行为。 坚持不懈 通知 错误处理 记录中 格式化 解析中 制图 导航 商业逻辑 创建视图 https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html https://www.scaledrone.com/blog/solid-principles-for-becoming-a-better-ios-swift-developer/ 单一责任原则@清洁代码联盟聚会,来自Eyal Golan 感谢您阅读文章。 您可以在以下位置找到我: Linkedin: Aaina Jain 推特: __aainajain