跳到主要内容

28 篇博文 含有标签「architecture」

查看所有标签

再窥iOS架构模式

· 阅读需 3 分钟

我们为什么要在架构上费心思?

答案是:为了减少在每做一个功能的时候所耗费的人力资源

移动开发人员会在以下三个层面上评估一个架构的好坏:

  1. 各个功能分区的职责分配是否均衡
  2. 是否具有易测试性
  3. 是否易于使用和维护
职责分配的均衡性易测试性易用性
紧耦合MVC
Cocoa MVC❌ V和C是耦合的✅⭐
MVP✅ 独立的视图生命周期一般:代码较多
MVVM一般:视图(View)存在对UIKit的依赖一般
VIPER✅⭐️✅⭐️

紧耦合MVC

传统 MVC

举一个例子,在一个多页面的网页Web应用程序中,当你点击一个链接导航至其他页面的时候,该页面就会被全部重新加载。该架构的问题在于视图(View)与控制器(Controller)和模型(Model)是紧密耦合的。

Cocoa MVC

Cocoa MVC 是苹果公司建议iOS开发者使用的架构。理论上来说,该架构可以通过控制器(Controller)将模型(Model)与视图(View)剥离开。

Cocoa MVC

然而,在实际操作过程中,Cocoa MVC 鼓励大规模视图控制器的使用,最终使得视图控制器完成所有操作。

实际的 Cocoa MVC

尽管测试这样的耦合大规模视图控制器是十分困难的,然而在开发速度方面,Cocoa MVC是现有的这些选择里面表现最好的。

MVP

在MVP中,Presenter与视图控制器(view controller)的生命周期没有任何关系,视图可以很轻易地被取代。我们可以认为UIViewController实际上就是视图(View)。

MVC 的变体

还有另外一种类型的MVP:带有数据绑定的MVP。如下图所示,视图(View)与模型(Model)和控制器(Controller)是紧密耦合的。

MVP

MVVM

MVVM与MVP相似不过MVVM绑定的是视图(View)与视图模型(View Model)。

MVVM

VIPER

不同于MV(X)的三层结构,VIPER具有五层结构(VIPER View, Interactor, Presenter, Entity, 和 Routing)。这样的结构可以很好地进行职责分配但是其维护性较差。

VIPER

相较于MV(X),VIPER有下列不同点:

  1. Model 的逻辑处理转移到了 Interactor 上,这样一来,Entities 没有逻辑,只是纯粹的保存数据的结构。
  2. ==UI相关的业务逻辑分在Presenter中,数据修改功能分在Interactor中==。
  3. VIPER为实现模块间的跳转功能引入了路由模块 Router 。

Lambda 架构

· 阅读需 2 分钟

为什么要使用lambda架构?

为了解决大数据所带来的三个问题

  1. 准确性(好)
  2. 延迟(快)
  3. 吞吐量(多)

例如:以传统方式扩展网页浏览数据记录的问题

  1. 首先使用传统的关系数据库
  2. 然后添加一个“发布/订阅”模式队列
  3. 然后通过横向分区或者分片的方式来扩展规模
  4. 容错性问题开始出现
  5. 数据损坏(data corruption)的现象开始出现

关键问题在于AKF扩展立方体中,==仅有X轴的水平分割一个维度是不够的,我们还需要引入Y轴的功能分解。而 lambda 架构可以指导我们如何为一个数据系统实现扩展==。

什么是lambda架构

如果我们将一个数据系统定义为以下形式:

Query=function(all data)

那么一个lamda架构就是

Lambda Architecture

batch view = function(all data at the batching job's execution time)
realtime view = function(realtime view, new data)

query = function(batch view. realtime view)

==lambda架构 = 读写分离(批处理层 + 服务层) + 实时处理层==

Lambda Architecture for big data systems

将软件架构视为物理建筑

· 阅读需 1 分钟

什么是架构?

架构是软件系统的形状。将其视为物理建筑的全景。

  • 范式是砖块。
  • 设计原则是房间。
  • 组件是建筑。

它们共同服务于特定的目的,比如医院是为治愈病人而设,学校是为教育学生而设。

我们为什么需要架构?

行为与结构

每个软件系统为利益相关者提供两种不同的价值:行为和结构。软件开发人员负责确保这两种价值保持高水平。

::软件架构师由于其职位描述,更加关注系统的结构,而非其特性和功能。::

最终目标 - ==降低每个特性的人工资源成本==

架构服务于软件系统的整个生命周期,使其易于理解、开发、测试、部署和操作。 目标是最小化每个业务用例的人力资源成本。

设计非常大的(JavaScript)应用程序

· 阅读需 3 分钟

非常大的 JS 应用 = 很多开发者 + 大型代码库

如何处理很多开发者?

同理心

什么是 ==高级工程师==?没有初级工程师的高级工程师团队就是工程师团队

  1. 成为高级工程师意味着我能够解决几乎所有别人可能抛给我的问题。
  2. 让初级工程师最终成为高级工程师。

高级工程师的下一步是什么?

  1. 高级: “我知道我会如何解决这个问题”,因为我知道我会如何解决它,我也可以教别人怎么做。
  2. 下一个层次: “我知道别人会如何解决这个问题”

良好的编程模型

人们如何编写软件,例如 react/redux, npm。这里有一个影响所有大型 JS 应用的模型 - 代码分割。

  1. 人们必须考虑打包什么以及何时加载
  2. ==基于路由的代码分割==
  3. 但是,如果这还不够呢?
    1. 懒加载我们网站的每一个组件
    2. Google 是怎么做的?通过渲染逻辑和应用逻辑进行分割。==简单地在服务器端渲染一个页面,然后实际渲染的内容触发下载相关的应用程序包。== Google 不做同构渲染 - 没有双重渲染

如何处理大型代码库?

==代码可移除性/可删除性==

例如,CSS 在代码可移除性方面表现不佳

  1. 一个大的 CSS 文件。里面有这个选择器。谁真的知道它是否仍然与你的应用程序中的任何内容匹配?所以,你最终只是把它留在那里。
  2. 因此,人们创建了 CSS-in-JS

==不惜一切代价避免应用程序的中央配置==

  1. 坏例子
    1. 中央路由配置
    2. 中央 webpack.config.js
  2. 好例子
    1. 去中心化的 package.json

避免中央导入问题:路由器导入组件 A、B 和 C

  1. 为了解决这个问题,做 ==“增强”而不是“导入”==
  2. 然而,开发者仍然必须决定何时增强,何时导入。由于这可能导致非常糟糕的情况,我们使“增强”成为非法,没人可以使用它——只有一个例外:生成的代码。

避免基础包的垃圾堆

  1. 例如,基础包绝不应包含 UI 代码
  2. 通过禁止依赖测试解决此问题
  3. ==最直接的方法必须是正确的方法;否则添加一个测试以确保正确的方法。==

小心抽象

我们必须变得善于找到正确的抽象:同理心和经验 -> 正确的抽象