0%

代码模块化的目的是让代码组织职责清晰,方便复用。
如果跳出这个场景,放到更广泛的领域会如何呢?比如设计、文档、组织架构 ……

DRY(Don’t Repeat Yourself) 原则在代码层面的理解是,多次遇到同样的问题,应该抽象出一个共同的解决方法,不要重复开发同样的功能避免代码重复。
今天看 《程序员修炼之道 第2版》知道不要复制代码只是 DRY 中很小的一部分。DRY 针对的是 知识意图 复制的约束,强调的是不要重复表达相同的东西,但表达方式有可能完全不同。这样运用 DRY 原则,明显层次更高,运用范围更广了。
看起来太抽象,举些例子:

  1. 验证 IP 有效性在代码中出现了两种实现方式,一种用正则表达式实现,还有一种用 Java 自带的类库 InetAddress 通过异常校验。两种方式代码完全不同,但是意图是一样的,这样也算是违反了 DRY 原则
  2. 业务要求用户名和密码都不能超过16位,且不能出现特殊符号。代码分别实现了 isValidUsernameisValidPassword 两个函数,单函数实现代码完全相同。这里不能说是违反了 DRY 原则,因为两个函数所表达的语意是不同的,后面很有肯能随着业务变化,用户名和密码的约束规则发生不一样。
  3. 校验用户登录的函数 login(String email, String password) 调用了 isValidEmail(email)isUserExisted(email), isUserExisted(email) 在实现时也调用了 isValidEmail(email) ,在代码实现上看没有违反 DRY,但是当执行 login 函数时会执行两遍 isValidEmail ,这种情况也是违反了 DRY 原则。
  4. 实现 isValidEmail(email) 的函数上写了一堆注释,把函数的校验逻辑通过文字的方式又描述了一遍,这也违反了 DRY 原则,属于 知识 的重复。
  5. 一份数据多处保存的重复,也是违反 DRY 原则
  6. 开发人员之间在实现业务功能时,可能出现的相同功能被多次实现,一份数据多处保存的问题,需要建立良好的沟通机制和代码审查机制来尽量避免。

我们在某个领域使用某个技术时候,要习惯跳出当前的上下文,站在更高的层次、不同的角度思考,可能会有更深入的理解、更广泛的运用,还有可能能把一个特定领域的技术通用化。

软件工程师要有优秀的抽象能力才能设计好软件,抽象能够屏蔽细节,让我们关注要点。不同层次的抽象,关注的要点不同,能够帮助我们解决不同层面的问题。拿软件设计来说,一个具体功能,抽象成具体方法,方法帮助我们屏蔽了实现细节,我们只关注方法的功能;我们把一串相关的功能抽象成类(接口),这帮助我们解决类接口的设计问题;如果我们抬高一个抽象层次,把完成整个业务流程的每个步骤抽象成业务模块、业务节点,这能帮助我们解决模块业务领域复用问题、模块之间依赖关系问题等业务架构层面的问题。

在开始阅读本文前请先思考如下几个问题:

  1. 什么是抽象?什么是建模?
  2. 抽象和建模有区别吗?
  3. 如何进行抽象?

抽象(abstracting)

我们把一堆事物集中在一起做比较,寻找他们相同的点,这个过程就是抽象(abstraction),而抽象的结果是概念(concept)。
例如:

牛顿、爱因斯坦,可以抽像出 的概念,
牛顿、爱因斯坦、蜜蜂,可以抽像出 动物 的概念,
牛顿、爱因斯坦、蜜蜂、桌子,可以抽像出 东西 的概念。

有没有发现,当不同的事物在一起对抽象的结果会有影响。这里的例子看出抽象出的概念越来越模糊了。这就需要我们在对事物抽象前进行分类。

分类

分类的目的是为了防止抽象出的概念太模糊,导致价值很低,我们需要把这些想要抽象的东西根据某些共有特性进行分类(classification)。
比方说,我们需要开发招聘网站系统和医院的病人管理系统,他们都需要对人进行管理。张三想求职(应聘人)、李四想看病(病人),我们需要他们相关的信息记录到系统中,但并不是事无巨细,不同的业务关注点不同。
招聘网站对人关注的:姓名、年龄、联系方式、职业经历、学历、语言等等。
病人管理系统对人关注的:姓名、年龄、联系方式、病史、药物过敏史等等。
你会要张三在填写应聘信息把药物过敏史也写上去吗?会不会很奇怪?
所以我们在进行分类的时候,我们必须明确业务目的,排除不关心的、干扰的事物。就像上面的例子,如果只抽象出人的概念明显太模糊,招聘网站应该关注应聘人,排除病人的干扰,同时也应该排除两个眼睛、一张嘴这些一样的信息。

概念

概念是有意义的,概念本身可以单独存在。概念的内容包括所有一个组成该概念的事物的特性和关系。概念是抽象的、普遍的想法,是充当指明实体、事件或关系的范畴或类的实体。
比如铁路运输使用铁路运单,航空运输使用航空运单,多式联合运输则使用联合运输单据。所以 运输单 概念的内容包括所有有关这些单据所有的特性。人们在定义这个概念的时候会挑选出这些特性的关键部分,比如,运输单据通常是指代表运输中的货物或证明货物已经付运的单据,它具体反映了同货物运输有关的当事人(如发货人、承运人、收货人等)的责任与权利,是货物运输业务中最重要的单据文件。
概念在它们的外延中忽略事物的差异,如同它们是一样的去处理它们,所以概念是抽象的。

类型

什么是类型:在概念的基础上扩充对某些关键信息的要求就是类型。也就是说,某个事物想要属于某种类型,就必须满足这个类型的概念,同时提供这个类型要求的关键讯息。
比方说,我们在对铁路运单和航空运单进行抽象时候,已经抽象出运输单的概念。现在我们要区分不同运输方式的运输单据,是铁路运单还是航空运输,所以我们扩充了运输方式这个关键信息。
铁路运单是一个概念(有自身的意义),也可以是一个类型(除了运输单这个概念的意义,还必须要有运输方式的信息)

建模(modeling)

建模是过程,模型是产物,模型是用来描述事物的。

模型的价值

  • 作为沟通的工具,传递想法(就像地球仪、建筑蓝图)
    • 因为实际的事物,或者你脑海中的想法,通常都非常复杂或模糊,难以让其他人理解
    • 对于软件来说包括系统设计和架构设计
    • 对于企业组织包括组织架构和流程设计
  • 是事物进行迭代设计的工具,有助于改进设计、研究事物演进过程
    • 由于实物的变化,成本高,而对模型的改变,更容易、经济
    • 通过对模型的调整,可以推演出适合的迭代轨迹
    • 对于软件来说就是重新工程化的设计
    • 对于企业组织就是企业架构和业务调整过程的设计

建模的要点

  • 时刻明确目的,记录和目的相关的要点(profiling)。例如为人建模,如果目的是为了就业,那么技能、兴趣等信息很重要;但是如果目的是健康,体重、血压很重要。
  • 只记录有差异的点,才能精简。例如为人建模时,要把两个眼睛、一张嘴这些一样的信息排除。这就是抽象的问题了,人是抽象的结果。

总结

  1. 分类的目的是为了更好地抽象,抽象的目的是更好地建模,良好建模的第一个重点在于记录业务目标的相关要点。
  2. 抽象的产物是归纳出概念(属性),并为了突出关键信息,将概念扩充为类型。
  3. 对事物进行建模的过程是,一堆事务先分类,不同分类的事物分别建模。分类后的事物再抽象得到事物的概念,在将概念扩充为类型,最后将事物概念里需要的信息,结合实际物体信息填充,得到具体事物的模型。
  4. 建模(modeling)和抽象(abstracting)是不一样的。建模是对某一个(或某一类)事物描绘要点(profiling),重点在找出特殊的属性值;抽象是对某些事物找出共性的概念,重点在找出共有的属性,而非属性值。所以说现要抽象,才能建模。
  5. 建模是过程,模型是产物,模型是用来描述事物的。
  6. 建模前需要明确目的,只记录有差异的属性值。差异的寻找是是通过对一类事物进行抽象,归纳出属性列表,对照属性列表记录有差异的属性值。
  7. 反过来想,当我们学习新知识的时候,可能先知道了某个概念名词,我们需要思考这个概念是对什么事物(问题)的抽象,这样有利于我们对新知识的学习。比方说 CAP 这个概念是对,是对分布式系统特性的抽象;ACID 是对事务特性的抽象。

扩展阅读

《建模的重要性》《抽象和类型》

起源

David Gelernter 在1991年出版的 《Mirror Worlds》 中提到数字孪生。后来 Michael Grieves 首次将数字孪生概念应用于制造业,并在工业和学术出版物中都得到广泛认可。随后在 2002 年提出将数字孪生作为产品生命周期管理(PLM)的概念模型。
数字孪生概念由三个部分组成:物理实体,数字实体以及他们之间的连接。连接就是物理实体和数字实体之间的信息交互和数据同步。
数字孪生中包含的特定信息由实际场景驱动。
数字孪生是逻辑结构,这意味着实际的数据和信息可能包含在其他应用程序中。
数字孪生的最终愿景是在虚拟环境中构建和测试我们的设备。

从技术角度理解数字孪生

数字孪生这个概念是在物联网领域中,对现实世界里资产或设备所有的属性和功能的抽象。这就像真实世界的实体,在信息化平台中映射出的孪生兄弟。这样我们就可以借助信息化平台中的数字孪生,来了解物理实体的真实状态,甚至可以通过对物理实体中预定义的接口进行控制。

  • 数字孪生的特性:

    • 是物理实体的镜像
    • 在信息平台中,充当物理实体唯一事实来源
    • 围绕设备提供各种方面的服务
    • 保证真实世界和数字世界的信息同步
    • 可以应用于工业和消费者领域的物联网场景
  • 数字孪生框架:

    • 提供与数字孪生交互的 API
    • 能够对数字孪生操作进行鉴权
    • 支持对数字孪生的批量操作
    • 能够集成到其他后端基础架构(例如消息系统,代理)

为什么需要数字孪生

可以通过数字孪生实时查看实际物理设备的状况,方便设备监控和维护定位,甚至可以通过接口解决产品缺陷,从而可以从根本上减轻维护成本。与此同时,我们需要注意安全性、隐私性等问题。

在物联网中的应用

Kaa IoT Platform
Eclipse Ditto