软件构造 最后的总结

最后只剩下写零零散散的东西了,大杂烩

1.多维度视图

软件构造过程中的多维度视图
源代码,AST:显然属于开发时要关注的,代码层级,瞬时形态
类文件,静态链接库,测试案例:显然属于开发时要关注的,瞬时形态,但是是组件等级
代码扰动量(Code Churn):显然也是开发时,代码层级,不过是一个需要随时间变化进行变化的量
版本,版本控制工具:开发时,组件级,随时间而变化
代码快照图,内存转储: 运行时,代码层级,瞬时形态
执行栈追踪:运行时,代码层级,但是是随时间而变化的形态

2.软件构造工具

作为版本控制工具的git的一些理论知识
软件的构造次序:
programming − > -> >refactoring(代码重构) − > -> >debugging − > -> >testing − > -> >dynamic code analysis/profiling(性能分析) − > -> >code review(代码评审,就是开发者都看一遍,无需执行正在开发的软件) /static code analysis − > -> >build

如何寻找bug?
通过code review 和profiling找出可能的bug,通过testing找出真实的bug,通过debug找出bug的根源

关于git
Git是分布式版本控制系统,而不是集中式版本控制系统

Git中commit节点的数据结构包含一个tree,tree中包含了一组指针,分别指向本次commit中包含的所有文件,而不是很容易理解为所修改的文件,而非仅仅本次修改的文件。即使某文件未被修改,它也有一个对应的指针,只不过指向的就是其parent的对应文件

远程仓库比较“新”的时候,本地仓库不能直接push,会出错,必须先fetch下来,再跟本地的更新merge起来,统一push到远程仓库。
再熟悉一下git创建到连接远程的流程

git init #在本地创建一个git库
git add 文件名或文件夹 ... #将我们想要提交的文件加入缓冲区,准备提交 
git commit -m "信息" #将缓冲区内容提交到本地的git版本库,同时传递一条信息。
本地↑
-----------------------
远程↓
git remote add origin XXX.git #链接我们在git上的远程库 
git push origin master #将本地的git库推送到远程的版本库
#可以把 master 换成你想要推送的任何分支。

git组成部分:

  1. 工作目录(Workspace ):本地文件系统
  2. 暂存区( Staging area ):隔离工作目录和Git仓库 :存放已修改的文件
  3. 本地的CMDB (Local repository ):本地的CMDB ,通常是一个 .git 目录 存放commit的文件
  4. 远程的CMDB (Remote repository ):和本地CMDB对应的远程目录

最恰当的将本地仓库中的master分支的最新提交推送至远程仓库的指令

git fetch origin master;
git merge; 
git push origin master

至于为什么最恰当,应该还是先fetch再merge,比较保险

3.ADT

ADT与OOP的总结 (1)
ADT与OOP的总结 (2)设计规约
ADT与OOP的总结 (3) 抽象数据类型 (ADT)
ADT与OOP的总结 (5) ADT和OOP中的“等价性“
Java中常见的mutable与immutable类
一个immutable的类,一旦其构造方法执行结束并产生了类的实例,该实例的一些成员变量是可以修改的(比如benefit mutation)
行为等价性:

  • 站在客户端的视角看,它们实现相同的功能
  • 它们具有相同的规约(spec)
  • 其实是针对同一个spec来说是等价的。若对这个spec进行更改,这两个方法也许就不等价了

若为某方法设计JUnit test case,在任何test case中对该方法的调用必须遵循其pre-condition(测试健壮性除外)

对于一些Spec的强度,有时候强弱是没有办法比较的,例如前置条件必须等价才能根据后置条件强弱比较,后置相同才能根据前置条件比较

几种方法类型:

  • Creator 构造方法,从0变1
  • Mutator 修改类中的一些属性
  • Producer 从当前的类派生出新的类
  • Observer 观察类中的一些属性

AF→R满射不是单射

AF→R中R是rep的值空间,只能开发者自己了解

ADT的Abstract空间(A)中的某个值,在其Rep空间中可能有多个值与其对应

若ADT的某个方法返回一个mutable的对象,并不一定表明该ADT产生了表示泄露

若ADT的任意costructor所构造出的object都满足RI、每个mutator方法执行结束后都保持RI为真,那么该ADT的RI有可能被违背,如果存在表示泄露,外部client就可以修改内部rep的值,就可能导致RI违反。

一个immutable的ADT,其rep可以是mutable的,只要没有rep exposure就没有问题。

两个ADT有相同的rep和相同的RI,但可能AF不同

两个ADT有相同的rep和相同的AF,但是RI可能不相同

在Mutator,Creator,Producer,Observer 方法之后,最好都调用一下checkRep检查RI

针对mutable的类,由于其rep在变化,直接使用==判断是否相等即可,无需override equals()——观察等价性
例如Java中List和Date等mutable的类,都override了equals()方法,实现观察等价性。

4.可复用性

复用性与各种设计模式(1)结构型模式
复用性与各种设计模式(2)行为类模式
提高可复用性的策略:

  • 泛型/参数化,例如Graph中的
  • 使用interface定义操作,而非用class直接实现op
  • C 设计和实现abstract class
  • 使用override和overload
  • 将ADT的rep设置为private和final,并避免表示泄露
  • 精心撰写符合要求的spec并生成Java Doc

委派 delegates

4.1 复用性性的设计模式

  1. Adapter模式 :客户端对接口编程,无需了解Adapter类
  2. Decorator设计模式:装饰
  3. Façade设计模式:针对一个或多个已有的类,client需要调用它们的多个方法,故该模式将这些调用统一封装为一个方法对外提供,减少了client与已有类之间的耦合度
  4. Strategy模式:将职责委派给了Strategy接口,实际执行的是其某个实现类的对应方法,若要扩展新的策略,只需为Strategy接口增加新的实现类
  5. Template模式:模板方法,包含了对一系列操作的调用,几个客户端共享相同的算法,但在细节上有所不同。比如比如算法可由可定制部分和不变部分组成。
  6. Iterator模式:Java里Iterable接口只有一个方法iterator(),它返回一个迭代器对象 ,Iterator接口有三个方法hasNext(), next(), remove(),返回一个具体实现类

5. 维护性

https://blog.csdn.net/Franklins_Fan/article/details/107039003
复习一些提高可维护性的原则:

  • 可维护性的基本原则:高内聚(一个好的内聚模块应当恰好做一件事)、低耦合(模块间接口的复杂程度应该低)
  • 信息隐藏原则 :避免类产生“表示泄露”

OO(面向对象(Object Oriented))设计五大原则:

  • 单一责任原则”SRP:每个类的责任应尽可能单一

  • LSP原则:参数逆变,返回值和抛出异常协变 LSP里氏原则与软件设计

  • OCP原则:开放/封闭原则 ,软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

  • 依赖转置原则(DIP) :抽象的模块不应该依赖于具体的模块,具体应该依赖于抽象,抽象出共同点,然后让实现细节依赖于抽象,客户端也使用抽象。

  • 接口隔离原则(ISP):客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。其实通俗来理解就是,不要在一个接口里面放很多的方法,这样会显得这个类很臃肿不堪

为了迎合OCP开放-封闭原则,客户端不应该直接使用具体的类,而应尽可能使用接口,能够通过在已有类结构上增加新的类来进行扩展,不应或应尽可能少的变化已写好的代码

尽可能降低委派,类之间的委派越多,耦合度可能就越大

5.1可维护性的设计模式

面向可维护性的设计模式

  1. 工厂模式 Factory Method,适用于无法预知要构造一个什么样的对象的时候

  2. 抽象工厂 Abstract Factory :多类产品的工厂方法组合在一起,提供接口以创建一组相关/相互依赖的对象(工厂模式只生成一类产品(比如不同厂家的鼠标),而抽象工厂可以生成多类产品(比如鼠标和键盘))

  3. 构造器模式:生成一个产品族,一个完整的对象(由若干小的objects组成),客户端不需了解各部分怎么创建、怎么组合,这些细节完全隐藏在Director类当中,比如生产电脑需要 鼠标,键盘,显示器,主机等,构造器模式分别生产并组装,客户只需买电脑即可

  4. Bridge模式:通过委派+继承建立两个具体类之间的关系,两个ADT对象之间的关系是永久保存,同时建立两棵继承树,两棵树中的不同子类之间的关系根据client的具体需求在client代码中动态确定,避免具体类之间的直接“接触”

  5. proxy模式:某个对象比较“敏感”/“私密”/“贵重”,不希望被客户端直接访问 到,故设置proxy,在二者之间建立防火墙,在客户端代码和具体被访问的类代码之间建立隔离,客户端实际请求的Proxy类和实际执行任务的类,二者实现同一个接口或具有相同的父类,通过委派到原来的类来完成具体的业务逻辑

  6. Observer模式:该模式在1个subject对象和一组observer对象之间建立1对多的委派关系,Observer对象调用subject对象的attach()方法,将自己加入到subject对象的“粉丝”队列中,当subject对象的状态变化时,它回调各个observer对象的update()方法。可以形象的比喻为“粉丝”对“偶像”感兴趣,希望随时得知偶像的一举一动,粉丝到偶像那里注册,偶像一旦有新闻发生,就推送给已注册的粉丝 (回调callback粉丝的特定功能)。

  7. visitor模式:给原ADT传递进不同的visitor实现类的实例,即可对ADT对象实例做不同的操作,但无需改变原ADT的代码,被visit的ADT,需要提供accept(Visitor v)这样的方法,便于将一个外部visitor实例传递进来,即可支持对ADT做两个外部操作的组合

关于Java中的-able和-ator的,-able一般是接口,而-ator一般是一个具体类/抽象类

可维护性构造技术

  1. State设计模式:类似自动机,使用有限状态机来定义 程序的行为、使用状态来控制程序的执行 ;根据当前状态,决定下一步要执行什么操作、执行操作之后要转移到什么新的状态,使用委派,将状态转换的行为委派到独立的state对象去完成,state再根据读入选择要跳转的状态;各具体State类分别代表对象能达到的某种状态,并负责完成在该状态下所能进行的状态转换,向客户端返回某个新状态的实例。
  2. Memento模式:分为:Originator是需要备忘的类;Memento ——备忘录,一个Memento对象代表“备份”的一次历史状态;Caretaker ——添加originator的备忘记录和恢复 ,负责掌控全部的状态备份,客户端通过它来操纵ADT的 状态备份与恢复;备忘和恢复的动作由客户端代码发起,而非由Originator类和Memento类发起
  3. 面向语法的构造模式,就是正则

正则:
Java中的正则

注意:
小写符号表示特殊符号对应的范围,而大写符号则是取反,例如\d:[0-9] \w:[a-zA-Z_0-9] \D: [ ^0-9] \W: ^ [a-zA-Z_0-9]

6.健壮性和正确性

健壮性与正确性

6.1 软件测试

关于软件测试

7.线程

7.1 线程

并发——线程

7.2 线程安全

线程安全

7.3 锁与同步

锁与同步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值