标签:build cto 规则 assert visitor lang complex 难度 obs
模块之间的依赖性。
功能专一性。高聚合度:模块的所有元素作用于同一目标。
SRP The Single Responsibility Principle 单一责任原则
OCP The Open-Closed Principle 开放-封闭原则
LSP The Liskov Substitution Principle Liskov替换原则
DIP The Dependency Inversion Principle 依赖转置原则
ISP The Interface Segregation Principle 接口聚合原则
一个类仅有一个责任;
至多有1个原因使得一个类发生变化。
模块的行为可扩展,从而该模块可表现出新的行为以满足需求的变化。
模块自身原本的代码不应被修改。
扩展模块行为的一般途径是修改模块的内部实现。
如果一个模块不能被修改,那么通常认为其具有固定的行为。
实现方案:抽象:继承、组合
注意:
避免使用 if-else / switch-case 语句。
低层模块依赖于高层模块,具体依赖于抽象(抽象类、接口)。
客户端不应被迫依赖于它们不需要的方法。
客户端不需要实现(接口中)不需要的方法。
实现方案:将"胖"接口分解为若干个小接口,不同的接口向不同客户端提供服务。
Productions 产生式节点,也称nonterminal非终止节点。(中间变量)
Terminal 终止节点。(终止字符)
Root 根节点。(起始字符)
正则语法:简化之后可以表达为一个产生式而不包含任何非终止节点。
Java中:
匹配:
Pattern . matcher ( regex , string)
或 Pattern pattern = Pattern.compile( regex ) ;
Matcher m = pattern.matcher (string) ;
m.matcher().
捕获:
Pattern parse = Pattern . compile (regex) ;
Matcher match = parse.matcher(string) ;
match.find() ;
match.group(index)
当client不知道要创建哪个具体类的实例,或不想在client代码中指明要具体创建的实例时,采用工厂方法。
定义一个用于创建对象的接口,让其子类来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。
有新的子类时,只需添加新的工厂方法。(OCP)
提供接口来创建一组相互关联/相互依赖的对象,但不需要指明其具体类。
抽象工厂接口的每个具体实现类实现一种具体的产品生产搭配。
抽象工厂创建的不是一个完整产品,而是"产品族"(遵循固定搭配规则的多类产品的实例),
得到的结果是:多个不同产品的对象,各产品创建过程对client可见(client或辅助类中调用工厂实现类的相关方法组装具体部件,但每块部件到底选择哪种类型实现,取决于工厂类的搭配规则。),但"搭配"不能改变。
本质上,Abstract Factory 是把多类产品的factory method组合到一起,抽象出配置每块部件的方法。
创建复杂对象,包含多个组成部分。
创建一个完整的产品,有多个部分组成,client不了解各部分如何创建、各部分如何组合,最终得到一个完整产品对象。
通过delegation + inheritance 建立两个具体类之间的关系。(DIP 依赖转置,抽象依赖于抽象)
实例化abstraction时,new RefinedAbstraction(左侧继承树的子类)并将接口实现类传入构造函数(右侧继承树的子类)。
某个对象比较具有高隐私性,不希望client直接访问,设置proxy,在二者间建立防火墙。
隔离对复杂对象的访问,降低难度/代价,定位在"访问/使用"行为。
递归组合,组合对象生成树结构,来体现层级关系(如职位等级图)。
在同类型的对象之间建立起树型层次结构,一个上层对象可包含多个下层对象。
"粉丝"(observer)对"偶像"(subject)感兴趣,希望随时得知偶像的一举一动;
在java中:
Observer 接口,实现该接口,构造"粉丝"。
Observable抽象类,派生子类,构造"偶像。"
对特定类型的object的特定操作(visit),在运行时将二者动态绑定到一起,该操作可以灵活更改,无需更改被visit的类。
本质上:将数据和作用于数据上的某种/某些特定操作分离开来。
类似strategy,不过visitor对ADT本身进行操作。
具体状态实现state接口,根据操作state不同实现之间转换。
记录originator对象的历史状态,并可恢复记录或删除。
健壮性 | 正确性 |
系统在不正常输入或不正常外部环境下仍能够表现正常的程度。 | 程序按照spec加以执行的能力,是最重要的质量指标。 |
出错后:·1、退出(并提示信息) 2、容错(转为正常) | Fail fast |
让用户变得更容易:出错也可以容忍,程序内部已有容错机制。 | 让开发者变得更容易:用户输入错误(不满足precondition的调用),直接结束。 |
对外部接口,开放(倾向于健壮) | 对内部逻辑:保守(倾向于正确) |
可靠性reliability = robustness + correctness
Error --> defeat/fault / bug -->failure
Mistake 程序员犯的错误 缺陷 失效,运行时程序的外部表现
对程序运行结果(Throwable):
程序员无能为力,一旦发生,想办法让程序优雅的结束。
分类:用户输入错误、设备错误、物理限制等
程序导致的问题,可以捕获、可以处理。
异常:程序执行中的非正常事件,程序无法再按预想的流程执行。
程序若找不到异常处理程序,则退出,在控制台打印出statck trace。
Runtime Exception 运行时异常,有程序代码、或I/O等外部原因造成,不需要捕获/处理。
从异常处理机制的角度进行分类:异常被谁check? 编译器/程序员
Unchecked异常:Error + RuntimeException
程序代码产生,编译正常,可以不处理,抛出则程序失败。(类似 dynamic type checking)
Checked 异常:
必须捕获并制定错误处理机制,否则编译无法通过。(类似 static type checking)
如何选择? 对于一个异常:
如果客户端可以通过其他的方法恢复异常,则采用checked exception;
如果客户端对出现的异常无能为力,则采用unchecked exception。
根据LSP:
父类抛出异常与子类协变,或子类不抛出异常;
若父类不抛出异常,则子类不抛出并自行处理异常。
Try-catch-finally :
无论程序是否碰到异常(无论Exception还是Error(包括assertion)),finally均会被执行。
(try 中 return 后,finally中若有return则,则依然执行,若无则在try执行return前执行)
(若 try或catch中强制退出(exit),则finally无法执行)
Try-with-resource:
try-with-resources这种声明方式指定了一个或多个资源,而且这些资源需要在程序结束的时候进行关闭。这种方式可以确保每个指定的资源都可以在声明结束的时候进行关闭(就是在try(){}结束的时候)。但是前提是这些资源必须实现接口java.lang.AutoCloseable(其中包括实现了java.io.Closeable接口的所有对象),原因是java.io.Closeable接口继承了java.lang.AutoCloseable接口。
如上图,BufferedReader 在try结束后自动关闭资源(br.close()).
Assert (布尔值) : (输出字符串) ;
Assert false 则打印输出字符串,并throw AssertionError
断言主要用于开发阶段,为了调试程序、尽快避免错误。
什么时候用断言:
如,验证private Boolean checkRep();
判定不能到达的位置,如switch-case中的default语句
对public方法:使用异常处理(因为是不受控制的外部条件)
对private方法:使用断言(对内严格)
断言 维护正确性,使用断言处理"绝不应该发生"的情况;
错误/异常处理 维护健壮性,处理"预料到可以发生"的不正常情况。
识别错误根源,消除错误
预防:防御式编程、assertion、exception
Debug: test -> debug ->
重现 -> 诊断(假设检验,分治法) -> 修复 -> 反思(是否存在相似的bug等)
Git bisect (诊断方法) 在输入的正确commit和错误commit之间二分查找,定位出错的commit。
常用手段:
Print(到处print)、stack tracing(输出调用栈),memory dump(内存导出分析),logging(记录日志),
断点调试。
探测是否存在错误。
测试的等级:单元测试、集成测试、系统测试、验收测试,回归测试。
白盒测试:对程序内部代码结构的测试。
黑盒测试:对程序外部表现出来的行为的测试。
测试优先编程:先写spec,再写符合spec的测试用例,写代码、执行测试、发现问题并修改、再测试直到通过。
Code coverage 代码覆盖度: 测试效果/测试难度:路径覆盖(所有可能的分支、路径)>分支覆盖>语句覆盖
检查程序是否符合规约。
用尽可能少的测试用例,尽快运行,并尽可能大的发现程序的错误。
将被测函数的输入域划分为等价类,从等价类中导出测试用例。
针对每个输入数据需要满足的约束条件,划分等价类。
每个等价类代表着对输入约束加以满足/违反的有效/无效数据的集合。
在等价类划分时,将边界作为等价类之一加入考虑。不仅考虑边界,还要考虑边界两侧(稍微偏离边界)。
标签:build cto 规则 assert visitor lang complex 难度 obs
原文地址:https://www.cnblogs.com/standingby/p/9219292.html