Tag: 仓库模式

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中有许多运算符:创建,转换,过滤,合并……可以使您的生活更轻松。 […]

iOS:Swift中的存储库模式

在上一篇文章中,我们有机会从概念上定义应用程序的体系结构。 这篇文章的目的是深入了解我们正在使用的该体系结构的关键组件的实现。 在这篇文章中,我们将讨论如何实现: 储存库模式 存储库模式是一种软件设计模式,可提供数据抽象,以便您的应用程序可以使用具有接口的简单抽象。 使用此模式可以帮助实现松散耦合,并且可以使域对象的持久性忽略。 它还使代码更具可测试性,因为它允许我们注入实现该定义接口的模拟存储库作为依赖项。 在Tiendeo iOS应用程序中,此模式使我们可以从数据层抽象域层,还可以在数据层内部从其数据源(Web API,Realm,用户默认值等)提取数据存储库。 让我们以一个简单的方案来看它: 在域层中,我们定义了一个RepositoryProtocol ,它允许我们按照依赖关系规则从数据层中抽象出域层(业务逻辑),这是干净架构中建议的。 (+信息) 让我们看一个常见的例子: 但是有很多RxSwift运算符可以在许多情况下为您提供帮助。 如果您对此感兴趣,我们会在其他文章中讨论RxSwift运算符。 希望您发现这篇文章有趣并且对您的项目有用。 任何问题或评论都将受到欢迎! 谢谢,祝你好运! 相关文章 在以下文章中,我们详细介绍了架构中的其他关键组件: Tiendeo应用程序中的MVP清洁架构 依赖注入 RxSwift +干净的架构

iOS:Tiendeo应用程序中的MVP清洁架构

Tiendeo移动部门在2017年面临着巨大挑战:从头开始重新制作该应用程序。 我们的旧版应用程序创建于2013年。它是使用简单的MVC架构,Objective-C(当然)构建的,它使用RestKit,AFNetworking和许多其他Pod …经过多年的开发和一些开发人员,它变得庞大,不可扩展,不稳定,具有大量的视图控制器,大量的AppDelegate,一些新功能都在Swift中进行了编码,还包含一些重构的部分,因此我们很少有Swift-Objective-C桥,……这是一个为孩子们吃早餐的怪物。 考虑到所有这些问题以及业务方向的一些变化,该公司与移动部门一起决定重新制作该应用程序。 ✨ 因此,尽管我们为旧版应用程序提供了少量维护,但我们开始同时为Android和iOS两个平台构建新的应用程序。 这个事实标志着我们将使用的架构。 干净的建筑 我认为,根据我的经验,现代应用程序体系结构必须健壮,稳定,可扩展,可测试,适应更改和可维护。 我认为干净的架构可以提供所有这些功能。 基本上,干净的体系结构使用依赖规则将代码构建在同心层中: 内圈中的任何人都无法完全了解外圈中的任何事物。 特别是,在内圈中的代码不得提及在外圈中声明的名称。 其中包括功能,类。 变量或任何其他命名的软件实体。 只有一条规则! 太酷了! 👌内部层包含业务逻辑,中间层包含控制器和用例,外部层包含UI,框架,DB等。 当系统的任何外部部分(例如数据库或框架)变得过时时,都可以通过这种方式构造代码,您可以用最少的麻烦替换那些过时的元素 。 存档的一些关键技术优势包括: 实现的抽象 单一责任原则 关注点分离 解耦代码 在进行了这一简短介绍之后,让我们回到我们的故事! MVP +清洁架构 我们决定在两个平台上都使用ReactiveX来应用MVP和干净的体系结构。 我们还尝试在两个平台上保持相同的类和函数命名。 以这种方式保持两个平台同步对我们来说真是太棒了,因为当我们计划新功能或讨论错误等时,两个团队都在谈论相同的组件,相同的结构,几乎相同的方法名称,即使一个开发人员想要切换到在另一个平台上,这种方式要容易得多。 构成我们的体系结构的层是: UI层 域层 资料层 这是体系结构的方案: 让我们来研究一下: UI层 我们将MVP用于UI层。 我们使用依赖注入将依赖项注入到Presenter中,例如:用例,自定义对象等。 Presenter在用例和视图控制器之间居于中间。 它处理用户交互,启动适当的业务逻辑并将响应发送到视图控制器。 Presenter不会导入UIKit类以使其更具可测试性。 UI层具有与域实体不同的自己的视图实体。 域层 业务逻辑层。 每个用例都是执行特定业务逻辑的可重用且独立的组件。 域层对其他层一无所知,只是从定义为协议的存储库中获取数据并返回结果。 域层具有其自己的域实体,不同于视图数据实体。 资料层 它使用存储库模式(+ info)。 基本上,存储库模式在数据源上添加了一个抽象层,用例从中获取数据。 使用存储库模式,您只需一个入口即可查询来自不同数据源(核心数据,领域,Web服务器等)的模型对象。 业务逻辑不应该知道数据来自何处。 […]

iOS:Swift中的依赖注入

在上一篇文章中,我们有机会从概念上定义应用程序的体系结构。 这篇文章的目的是深入了解我们正在使用的该体系结构的关键组件的实现。 在这篇文章中,我们将讨论如何实现: 依赖注入 我认为James Shore的这段话定义了依赖注入是什么: 依赖注入意味着给对象一个实例变量。 真。 而已。 依赖注入是一种软件设计模式,可以帮助您使代码更具可测试性,从而减少耦合。 习惯性依赖注入模式面临单例模式。 我认为,根据我作为iOS开发人员的经验,我建议在大多数情况下使用依赖项注入模式,因为除其他外,它在测试期间隔离类非常方便。 尽管这两种模式在每种情况下均有效,但是由于项目的某些组件在某些访问模式下可以更好地工作。 有一些替代方案,例如Swinject,可以在项目中实现依赖项注入,但是在向项目添加新的依赖项之前,我们希望向我们提出一个关键问题:确实有必要吗? 我们可以解决这种需求而无需添加第三方依赖项吗? 在这种情况下,我们认为可以,可以! 我们意识到我们实际上并不需要任何外部库,这就是为什么…… 让我们以应用程序中一个常见情况的示例开始实施: 您有一个带有Presenter的UIViewController。 该Presenter需要一个对象来填充视图,并具有从存储库中获取数据的用例。 我们的建议是定义一个带有一系列方法的协议,这些方法将接收返回准备使用的实例所需的所有实例变量。 我们将此协议命名为Assembler 。 注意,我们需要初始化用例存储库,以将用例注入演示者。 现在,我们可以使用此协议来实例化UIViewController: 结论 使用这些汇编程序来解析程序依赖性的优点是: 没有第三方依赖性。 输入解决依赖性所需的参数,因此开发人员不会犯错误。 要实例化一个组件,您需要解决其依赖性,这可以保证其行为良好。 该应用程序的每个组件都是分离的,可以进行注入模拟测试。 帮助您避免使用共享实例。 (…或至少让​​您考虑是否必要) 希望您发现这篇文章有趣并且对您的项目有用。 任何问题或评论都将受到欢迎! 谢谢,祝你好运! 相关文章 在以下文章中,我们详细介绍了架构中的其他关键组件: Tiendeo应用程序中的MVP清洁架构 RxSwift +干净的架构 储存库模式 这个实现受到了这篇文章的启发。