本文档收集了这些年来我们使用Katana定义的最佳实践和准则。
目标
指导方针
1.使用管理器封装逻辑
2.事件观察者
3.避免复杂的副作用
4.利用封装,模块化和可见性修改器
5.文件
6.项目文件结构
项目中定义和共享准则和最佳实践的优点:
1. 当做一件事有多种相同的方法时,选择一种方法并保持一致可以让每个人立即了解事情是如何工作的,以及如何向应用程序或库引入更改,即使他们并不熟悉代码库。
2. 通过遵循共享的模式,我们可以在假设某些事情是以特定的方式完成的情况下实现工具。
3. 在审查Pull请求时,可以利用指导方针来提供有效的反馈。
4.指南所保留的统一的书面知识,新手们可以领先一步。
Guidelines
使用管理器来封装逻辑
为了实现代码的尽可能高的模块化和可重用性,我们定义了对象,我们称之为Manager。Manager负责处理业务逻辑的特定部分。例如,健身应用可能需要一个登录管理器、一个计划生成器,甚至需要更通用的逻辑来执行API调用或跟踪用户指标。
依赖容器负责启动这些管理器,并将它们暴露给Katana的Side Effects。以下是创建管理器时需要遵循的一些指导方针:
1.管理者是“被动的”,他们被Katana的 Side Effects所调用,他们不应该以任何方式与武士刀交互(也就是说,他们不能分派)
2.管理器既不能访问存储getState,也不能访问分派
3.管理器不应该包含状态。函数执行计算所需的所有信息都作为参数传递。
4.管理者可能需要使用其他管理者来实现他们的部分逻辑。我们称这些下属管理者为依赖关系。在初始化管理器时,依赖项应该作为参数传递。
在命名约定方面,作为管理器的类应该使用Manager后缀命名。举个具体的例子,Login不是一个有效的管理器名,而LoginManager是。
Event Observers
Katana 提供了一个拦截器,可以用来观察以下事件:
1.状态变化,
2.一个状态更新器或一个副作用已经被发送,
3.通知是否已经被发布
有时这是不够的,我们需要观察外部世界,并把我们从这个观察中得到的信息带回Katana的世界。正如指南(1)中所讨论的,管理器是应用程序的被动成员,因此它们不能分派。为了解决这个特定的用例,我们引入了event observers。这些类是由依赖容器创建和拥有的,它们唯一且唯一的职责是监听来自外部世界(例如,Firebase、Websockets等等)的事件,并在这个事件之后在Katana世界中分派一些东西。
虽然分开管理者(Manager)和Observers 可能看起来很奇怪,但这实际上有助于保持每个部分的简单和一致。对于简单的情况使用管理器,对于更复杂的情况使用event observer。
在命名约定方面,作为eventtobservers的类应该使用Observer后缀命名。举个具体的例子,HealthKit不是一个有效的观察者名,而HealthKitObserver是。
Avoid complex Side Effects(避免复杂的Side Effects)
在编写应用程序的逻辑时,可能会创建一些高度灵活的Side Effects,这些Side Effects需要多个输入(即,实现Side Effects的结构有几个参数),并根据这些输入实现不同的东西。
逻辑被封装在分组的、可重用的函数中。这意味着您应该尽量使Side Effects简单,并尽可能接近管理器功能和分派的简单链接。
关于在另一个Side Effects中发送一个Side Effects,应该尽可能避免,因为这会使整个逻辑更加难以遵循。如果您最终处于这种情况,请尝试查看您的代码,并考虑更多地利用管理员。
Leverage encapsulation, modularisation and visibility modifiers(利用封装、模块化和可见性修饰符)
应用程序是由相互协作的独立逻辑部分组成的。在编写应用程序逻辑时,应该创建名称空间(模块),反映这些名称空间中的划分和组状态更新器以及Side Effects。
Documentation
文档是应用程序中非常重要的部分。拥有出色的文档,其他开发人员可以轻松进入您的代码库,并更快地提高生产力。
上面一条准则定义了逻辑模块的公共接口的概念。在将该准则应用于代码时,还应确保正确记录了“公共接口”。好的文档应包括:
1.功能/副作用/状态更新程序的功能说明
2.参数说明
3.前提条件(如果有)
4.在编写代码时所做的假设
5.代码无法轻易推断出的任何其他信息,这些信息在使用代码或需要更改代码时都非常有用
Project files structure (项目文件结构)
ProjectName
|-- Logic
|-- AppDependenciesContainer.swift
|-- Home
|-- HomeDispatchable.swift // side effects and state updaters
|-- Login
|-- LoginDispatchable.swift // side effects and state updaters
|-- LoginManager.swift
|-- PlanGenerator
|-- PlanGeneratorDispatchable.swift // side effects and state updaters
|-- PlanGeneratorModels.swift
|-- PlanGeneratorManager.swift
|-- UI
|-- Login
|-- LoginVC.swift
|-- LoginView.swift
|-- Home
|-- HomeVC.swift
|-- HomeView.swift
|-- HomeVM.swift
|-- State
|-- AppState.swift
如您所见,主文件夹包含3个主文件夹:逻辑,UI和状态。
逻辑文件夹包含应用程序的所有逻辑(状态更新程序,副作用和管理器)以及依赖项容器。
即使所有逻辑都在一个文件中(例如Home.swift,它具有与Home视图控制器严格相关的副作用),也应该将该文件包含在文件夹中以方便搜索,而不必猜测它是文件夹还是文件夹。一份文件。总体逻辑应包含副作用,状态更新程序,管理器和与逻辑相关的模型。
State文件夹包含该状态一部分的所有结构。请注意,遵循 准则(4),您可能希望将状态与逻辑共同定位,以对代码实施某种信息隐藏技术(即,将某些变量设为私有或文件私有)。这是唯一允许的例外。