Contents
  1. 1. Swagger
  2. 2. Relation SQL VS NoSQL
  3. 3. Redis 构建缓存
  4. 4. 消息队列
  5. 5. 设计模式
    1. 5.1. UML 图与时序图
    2. 5.2. 时序图
    3. 5.3. 创建型
    4. 5.4. 结构型
    5. 5.5. 行为型
  6. 6. 单元测试
  7. 7. 基本概念
  8. 8. 桩对象 VS 模拟对象
  9. 9. 看过的书

Swagger

作用:是一个常用的开源框架,具有一个包含大量工具的生态系统,可帮助我们设计、构建、记录和调用RESTful API。
Swagger的核心是Swagger规范,它是JSON或YAML文件中的API描述元数据。该规范可为API创建RESTful 契约,以人机可读的格式详细描述所有资源和操作,以便于开发、发现和集成。
为什么使用 Swagger:

  • 其他产品能够自动调用和集成 API。
  • 能够自动生成 API 文档。
    借助Swagger获得必要文档以及稳定的API资源管理器,是API成功实现和降低开发者使用难度的关键。
  • 使用 Swashbuckle NuGet 软件包在 ASP.NET Core 上构建
    除了Swagger元数据生成器引擎外,Swashbuckle还包含swagger-ui的嵌入式版本,安装后可自动运行。

Relation SQL VS NoSQL

SQL No SQL
类型 关系型数据库 非关系型数据库
语言 数据库的定义与操作都基于结构化查询语言,适用于非常复杂的查询。在使用之前,需要预定义的架构来确定数据的结构,并且要求所有数据都遵循这个结构。结构的更改,对整个个系统来说是复杂和具有破坏性的。 对于非结构化数据,其架构是动态的。数据可以通过多种方式保存,这就意味着它可以是面向文档,面向列,基于图形或组织为Key、Value存储。这种灵活性表明,文档可以不需要先定义结构就能创建。每个文档也可以有自己独特的结构。语法因数据库而异,您可以随时添加字段。
可扩展性 几乎应对扩展的所有的解决方案都是垂直扩展,这意味着通过在一个服务器上增加配置来提高负载。 可以进行水平扩展,这意味着,可以通过分片或在NoSQL数据库中添加更多服务器来处理更多流量。因此NoSQL最终可以变得规模更大,更强,使的这些数据库成为大型或不断变化的数据集的首选。
结构 基于表的。适用于:需要多行事务的应用程序(如会计系统)、使用关系结构构建的遗留系统。 键值对、基于文档的、图形数据库或宽列存储
遵守的属性 ACID(Atomicity, Consistency, Isolation and Durability) 原子性、一致性、隔离性、持久性 CAP theorem (Consistency, Availability and Partition tolerance). 一致性、可用性、分区容错性
可用数据库 PostgreSQL, MySQL, Oracle and Microsoft SQL Server Redis, RavenDB Cassandra, MongoDB, BigTable, HBase, Neo4j and CouchDB

Redis 构建缓存

消息队列

设计模式

UML 图与时序图

以下参考至
类之间的关系:

  • 泛化关系
    类的继承结构表现在 UML 中为:泛化(generalize)和实现(realize)
    继承关系是 is-a 的关系;两个对象之间如果可以用 is-a 表示,就是继承关系。如,自行车是车。

  • 实现关系

  • 聚合关系
    用于表示实体对象之间的关系,表示整体由部分构成的语义。如,部门由多个员工组成。
    与组合关系不同的是,整体和部分不是强依赖的,即整体不存在了,部分依然存在。如,部门撤销了,人员不会消失,他们依然存在。

  • 组合关系
    与聚合一样,组合关系同样表示整体由部分构成的语义。如公司由多个部门构成。
    组合关系是一种强依赖的特殊聚合关系,如果整体不在了,那么部分也不存在了。如,公司不存在了,部门也将不存在了。

  • 关联关系
    描述不同类的对象之间的结构关系;是一种静态关系。通常与运行状态无关,一般由常识等因素决定的。它一般用来定义对象之间静态的、天然的结构。关联关系是一种“强关联”的关系。关联关系默认不强调方向,表示对象间相互知道。

  • 依赖关系
    表示一个对象在运行期间会用到另一个对象的关系。
    与关联关系不同,它是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化,依赖关系也可能发生变化。
    依赖也有方向。在最终代码中,依赖关系体现为类构造方法及类方法的传入参数,箭头的指向为调用关系。

时序图

时序图是显示对象之间交互的图,这些对象是按时间顺序排列的。时序图中显示的是参与交互的对象及其对象之间消息交互的顺序。
时序图包含的建模元素主要有:对象(Actor),生命线(Lifeline)、控制焦点(Focus of control)、消息(Message)等待。

创建型

创建型模式对类的实例化过程进行抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责。
创建者模式在创建什么(What)、有谁创建(Who)、何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起,达到使整个系统独立的目的。

  • 简单工厂模式
    工厂类内部通过流程判断语句来选择使用哪个产品。

  • 工厂方法模式
    定义抽象工厂类,不同的产品类型由具体的工厂类负责创建。这种模式可以做到,在不修改具体工厂类的情况下,引入新的产品(通过添加新的子类工厂实现),做到对扩展开发,对修改关闭。工厂父类负责创建产品的公共接口,子类工厂负责实现。

  • 抽象工厂模式
    与工厂方法相比,一个工厂不仅仅只生产一种产品,它可以生产多个产品对象。工厂方法创建的是一个产品等级结构(即,同一种商品,多个品牌的创建),而抽象工厂创建的是一个产品族(即,同一个品牌,多种不同商品类型的创建)
  • 构造者模式
    构造者就像是加工车间(Builder,抽象构造者),你(Director,指挥者,也就是需要产品对象的人)使用不同的加工车间(ConcreteBuilder,具体的构造者),就能加工出不同的产品(Product,产品角色)出来。既然是加工车间,那么加工需要的原料必须自己提供(当然还是由产品自己公开自己有那些部件可用)。这样作为使用者的你就不需要关系加工车间是以什么样的工序进行加工的,整个产品的生产过程都外包给了加工车间。而且每个加工车间都有自己的一套工序标准。
    构造者适合所创建的产品有较多的共同点,其组成部分相似。差异性很大不适合使用这种模式。(例如游戏中有不同的地图和人物,而地图或人物的构造过程类似。这种情况就可以使用该模式)
    可以省略掉抽象构造者角色和指挥者角色。

代码示例

  • 单例模式
结构型

结构型模式描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能强大的结构。
结构型模式可以分为类结构型模式和对象结构型模式;

  • 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系

  • 对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联(组合)关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。

  • 适配器模式
    适配器模式使用的场景,就像我们希望使用三孔插座,但实际环境中只有两孔插座,但我们可以通过一个插座适配器来将两孔插座转换为三孔插座。
    适配器模式就是将现有接口转换为客户类期望的接口。这样保证了对现有类的重用。适配器类的实现就是将客户端类的请求转化为对适配者相应接口的的调用。

示例代码

  • 桥接模式
    在一个跨平台的视频播放器上播放多种格式的视频文件。有两种方式。
    • 针对每一个平台都提供每种格式的实现。
    • 根据现实的需要对操作系统和视频格式实现进行组合。

对于两个个变化维度(两个变化原因)的系统,采用交接模式,可以减少系统中类的个数。将抽象化和实现化分离,使它们都可以独立地变化。抽象化就是忽略一些信息,把不同的实体当作同样的实体对待。将对象的共同性质抽取出来形成类的过程即为抽象化。实现化,针对抽象化给出的具体实现,就是实现化。实现化产生的对象比抽象化更具体。

示例代码

  • 装饰者模式
    装饰者以对客户透明的方式,动态地给对象附加更多的功能。换言之,客户端并不会觉得对象在装饰前和装饰后又什么不同。装饰者模式可以在不需要更多子类的情况下,将对象的功能加以扩展(通过继承也可以获得父类的功能)。也采用包装的方式,在这方面与适配器一样,但适用场景不同。
    Decorator 继承 抽象Componet 是为了达到类型一致。

代码示例

  • 外观模式
    外部与一个子系统必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这个子系统更加容易使用。在不引入抽象外观类的情况下,将会违背开闭原则。

代码示例

  • 享元模式
    运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。享元模式要求能够共享的对象必须是细粒度对象。由一个工厂负责缓存对象,客户端对对象的访问和指向默写操作,都从工厂的缓存中获取,从而实现对象的复用。

代码示例

  • 代理模式
    给某一个对象提供一个代 理,并由代理对象控制对原对象的引用。一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现 间接引用。Proxy 类继承抽象 Subject 是为了使 Proxy 与 Subject 具有同样的接口。可以在代理中设置在实际操作之前或之后指向一些其他操作。
行为型

行为型模式使对不同的对象之间划分责任和算法的抽象化。
行为型模式不仅关注类和对象的结构,而且重点关注它们之间的相互作用。
通过行为型模式可以,更加清晰地划分类和对象的职责,并研究系统在运行时实例对象之间的交互。在系统运行时,对象并不是孤立的,它们可以通过相互通信与协作完成某些复杂功能,一个对象在运行时,也将影响到其他对象的运行。
行为型模式分为类行为型模式和对象行为型模式。

  • 类行为型模式:类行为型模式使用继承关系在几个类之间分配行为,类行为型模式主要通过多态来分配父类与子类的职责。
  • 对象行为型模式:对象行为型模式则使用对象的聚合关联关系分配行为,对象行为型模式主要是通过对象关联等方式来分配两个或多个类的职责。根据“合成复用原则”,在系统中尽量使用关联(组合)关系来替代继承关系,因此大部分行为型设计模式都属于对象行为型设计模式。

单元测试

基本概念

测试的方法名由三部分构成:

  • 被测试的方法名
  • 测试场景(能产生预期行为的条件)
  • 预期行为(在给定条件下,期望被测试方法产生什么结果)

编写一个单元测试,通常包含三个主要的部分:

  • 配置对象,根据需要新建和设置它们
  • 操纵对象
  • 通过断言判断结果是否符合预期

使用桩对象解决依赖
桩对象定义:对系统中现有依赖项的一个替代品,可认为控制,通过桩对象,无需涉及依赖项,就可以直接对代码进行测试。
热河面向对象的问题都可以通过添加一个间接层来解决,除非由太多层。消除依赖项的模式:

  1. 找到被测对象所对应的接口或者 API。
  2. 如果接口和测试的方法直接相关,则添加一个间接访问层来调用接口(泛指一起协同工作的方法或者类),以便能够测试代码。(即为代码添加一个中间层,被测试代码的依赖转变为整个中间层)
  3. 将接口的底层实现替换为你能控制的东西。

用模拟对象做交互测试和状态测试
模拟对象用于测试对象之间的调用。被调用的对象可能不返回结果,也不保存状态,但它的复杂逻辑需要基于其他对象的调用。
交互测试定义:测试一个对象如何向另一个对象传递消息,如如何从其他对象接收消息,即测试对象如何和其他对象进行交互。
可以把交互测试,看作“动作驱动测试”,把基于状态的测试看作“结果驱动测试”。

模拟对象定义:系统中的一个伪对象,用来决定一个单元测试是通过还是失败。它通过验证被测对象和伪对象之间是否进行预期的交互来判断。通常每个测试只有一个伪对象。

桩对象 VS 模拟对象

基本区别:桩对象不会使测试失败,但模拟对象可以。
使用桩对象,断言是针对被测试类执行的。借助桩对象,能够确保测试顺利进行。
利用模拟对象来验证测试是否失败。断言是针对模拟对象的。被测试类与模拟对象通信,模拟对象记录所有的消息。测试使用模拟对象来验证测试是否通过。
伪对象是桩对象或者模拟对象的概称,因为它们看起来都像真对象。一个伪对象是桩对象还是模拟对象,取决于它在当前测试中的用法。如果是用来检测交互(断言所针对的),那么它就是模拟对象,否则它就是桩对象。

模拟对象框架:Moq,Moq是针对Net开发的模拟库。他的目标是让模拟以一种自然的方式与现有的单元测试进行集成,使他更加直观。模拟的类不能为密封类。不能直接模拟静态方法。Moq只能创建模拟对象的实例。
压力测试工具

看过的书

《Dot.NET单元测试艺术》Nunit