代码基础
由功能偏向质量,由具体偏向抽象,由编程偏向工程,由手工偏向工具
- Design Goals 编程的视野
- Design Principles 编程的标尺
- Design Patterns 编程的经验
三维度八视图阶段
构造时build-time / 运行时视图run-time动态性
时刻moment / 阶段视图period构造对象
代码code / 构件视图component
Build-time 构建阶段 idea->
requirement->
design->
code->
installable/executable package
$$ 代码的逻辑组织\left{
\begin{array}{lcl}
functions\
classes\
methods\
interfaces
\end{array} \right.$$
- Software = Program(codes)
- Software = Algorithm+Data Structure
- Software = Program+Data+Documents
- Software = Modules(Components)+Data/Control Flows
静态链接
库被copy进代码形成整体,执行的时候无需提供库文件动态链接
仅仅做出标记,运行时根据标记加载库文件至内存
SCI Software Connfiguration Item
软件配置项
Evolution Graph 演化图
versioning版本号的一般命名
major.minor.patch
几种代码运行方式
full program interpretation 由runtime system完全载入并interpret
native machine code 完全转换为CPU的可执行程序
Interpreted byte codes 被编译成字节码的形式(如java的class文件)再以前两种方式运行
Perl or Python 在运行时编译成字节码解释执行
snapshot diagram 描述程序运行时,某时刻内存里变量层面的状态
memory dump 内存信息转储,储存程序间断错误或信号
execution tracing 用日志方法记录程序执行的调用次序
event logging (系统层次)抽象的行为和错误日志
- Correctness 按照预先定义的”规约”执行
- Testing and Debugging
- Defensive programming
- Formal approach(高级)
- Robustness 针对异常情况的处理(Exception handling)
合称reliability
- Extendibility 对规约修改的容易程度(高内聚,低耦合,如下)
- Design simplicity简约主义
- Decentralization分离主义
- Reusability 一次开发,多次使用
合称modularity
- Compatibility 不同软件间的相互可容易的集成
- 关键是in homogeneity of design, standardization; 尤其是standard protocols
- Efficiency 在硬件资源上放尽可能少的demands(processor time, space, bandwidth)
- Portability 软件在不同的软硬件环境间移植
- Ease of use 容易use, installation, operation, monitoring
- Structural Simplicity
- Know the user
- Functionality
- Timeliness 按时release
Liskov Substitution PrincipleLSP原则
如果S是T的子类型subtype
,那么程序中使用T类型的对象的地方,也可以用S类型的对象替换,而不会产生任何错误或异常。
委托delegation
是一种设计模式,用于将某个对象的功能委托给另一个对象来处理。它通过在对象之间建立一种关系,使得一个对象能够调用另一个对象的方法,并将任务的执行委托给该对象。
协变Covariance
:
协变是指在类型转换或继承关系中,保持类型关系的方向不变。简而言之,如果类型 A 可以被隐式转换为类型 B,那么 A 是 B 的协变类型。
Composite Reuse Principle (CRP) 更倾向于使用委派而不是继承来实现复用。
SOLID是OO设计原则 5 classes design principles
▪ (SRP) The Single Responsibility Principle 单一责任原则:There should never be more than one reason for a class to change
▪ (OCP) The Open-Closed Principle 开放-封闭原则:行为是可拓展的,自身代码是不可修改的
▪ (LSP) The Liskov Substitution Principle Liskov替换原则:子类型可替换父类型
▪ (DIP) The Dependency Inversion Principle 依赖转置原则:具体应该依赖于抽象
▪ (ISP) The Interface Segregation Principle 接口聚合原则:只提供必须的接口
测试
- LOC
代码行数
- Cyclomatic complexity
循环层次
- coupling and cohesion
耦合度和内聚性
- readability
可读性
Test first programming 先写测试,再写代码
residual defect rates per kloc 每千行代码残留缺陷率Unit Testing
单元测试Integration testing
集成测试System testing
系统测试
黑盒测试 从spec导出测试区间的等价类划分
白盒测试 考虑内部实现细节,对所有执行路径进行等价类划分找出代表性的简单路径
code coverage 代码覆盖度
- Function Coverage
- Statement Coverage
- Branch Coverage
- Condition Coverage
- Path Coverage
构造过程
$$ \textcolor{red}{basic\ types} \left{
\begin{array}{lcl}
Linear\
Iterative\
\end{array} \right.$$
$$ \textcolor{red}{existing\ models}\left{
\begin{array}{lcl}
Waterfall\ 瀑布\
Incremental\ 增量\
V-Model\ V字\
Prototyping\ 原型\
Spiral\ 螺旋
\end{array} \right.$$
Waterfall 线性推进,阶段划分清楚
Increment 多个Waterfall的串行
V-Model Waterfall变型,强调测试的重要性
W-Model 由两个V组成,增加了Verification和Validation,
Prototyping 首先做出合适的基础模型,接着不断根据需求迭代 抛弃式和演化式
Spiral 风险驱动,多轮迭代基本遵循Waterfall
Agile development 敏捷开发 rapid delivery,eXtreme Programming
Pair Programming 一个人写,一个人看
Scrum 核心是 Sprint(迭代)和 Scrum Team(团队)
Fagan inspection 核心思想是通过系统性的检查和评审来提高软件质量。
Team Version Control
Software Configuration Item 软件中发生变化的基本单元
OOP的基本概念
public
,protected
,default
,private
四种对象访问权限类型
抽象类 包含至少一个抽象方法
1 |
|
- Ad-hoc polymorphism
重载多态 / 运算符多态
函数重载或运算符重载 - Parametric polymorphism
泛型多态 / 参数化多态
泛型 - subtyping(subytpe polymorphism or inclusion polymorphism)
对象多态/继承多态
继承和方法重写
Specifacations
Spec规约
充当过程的实现者与其客户之间的重要防火墙。它使单独开发成为可能:客户可以自由编写使用该过程的代码而无需查看其源代码,而实现者可以自由编写实现该过程的代码而不知道它将如何使用。
Null
值是 Java 类型系统中的一个不幸漏洞。当程序试图在null上调用方法或访问其成员时,会触发NullPointerException(空指针异常)
precondition前提条件
说明参数的限制等,postcondition后置条件
说明返回类型等
java异常
$$ \left{
\begin{array}{lcl}
checked\ exception\
unchecked\ exception (RuntimeException)
\end{array}
\right.$$try,catch,finally
Error表示严重的错误,一般是由于虚拟机出现问题或系统资源耗尽等无法恢复的情况引起的。通常情况下,程序不会捕获和处理Error类型的异常,而是由虚拟机来处理。
Exception表示非致命的异常,可以通过程序的处理来恢复或终止程序的执行。
Designing Specifications
$$ \left{\begin{array}{lcl}
deterministic和undetdetermined(不是nondeterministic)\
declarative和operational\
strong(precondition弱,postcondition强)和weak
\end{array}\right.$$
要求:coherentmeaning that it does one thing and does it well
,
results informative,
strong enough,
weak enouph,
use abstract types when possiblestatic
vs. instance
static
static关键字用于声明静态成员(变量或方法),即类级别的成员,不依赖于类的实例而存在。
静态成员属于类本身,只会在内存中存在一份副本,被所有类的实例共享。
可以通过类名直接访问静态成员,无需创建类的实例。
静态变量在程序启动时被初始化,可以在任何时候访问。
instance
实例成员是与类的实例相关联的成员,每个类实例都有自己的一组实例成员。
实例成员包括实例变量和实例方法,它们依赖于类的实例的创建和存在。
实例成员在每个类的实例中都有自己的副本,它们独立于其他实例。
实例成员需要通过创建类的实例来访问和使用。
Avoiding Debugging
利用assert
检查先决条件是防御性编程
的一个例子。
不要使用断言来测试程序外部的条件,而是使用异常。
由于断言可能被禁用,您的程序的正确性不应该依赖于断言表达式是否被执行。
1 |
|
当x是-1时,将输出x is -1
默认情况断言语句不执行,必须通过将-ea(代表启用断言)传递给 Java 虚拟机来显式启用断言。
Mutability&Immutability
mutabale objects会使对其大量操作时所需空间复杂度大大降低
passing mutable objects和returning mutable objects一样有latent bug,需要defensive copying
Sharing a mutable object complicates a contract. 因为要用时合同不清楚的话不知道是否已经被人修改
contract: a form of agreement or protocol that establishes the rules of engagement between different parts of a system
Recursion
base case + recursive step
Debugging
reproduce the bug ->
find the bug ->
fix the bug
Abstract Data Type
operation分类:
- creator: create new objects of the type.
t* → T
- producer: create new objects from old objects of the type.
T+, t* → T
- observer: take objects of the abstract type and return objects of a different type.
T+, t* → t
- mutator: change objects.
T+, t* → void | t | T
Each T is the abstract type itself; each t is some other type. The + marker indicates that the type may occur one or more times in that part of the signature, and the * marker indicates that it occurs zero or more times. | indicates or.
抽象(高层思维)、模块化、封装、细节隐藏、单元化(separation of concerns)
representation independent表示独立性
核心思想是将数据的表示方式与其处理方法相分离.
override覆盖
,可把基类中标记为abstract
的函数覆盖重写
overload重载
,构造函数名相同但参数列表不同的方法,以实现静态多态性
Design Patterns
▪ Creational patterns
创建型模式
– Concern the process of object creation
▪ Structural patterns
结构型模式
– Deal with the composition of classes or objects
▪ Behavioral patterns
行为类模式
– Characterize the ways in which classes or objects interact and distribute responsibility.
factory methodVirtual Constructor/工厂模型
A creator implemented as a static method
Adapter适配器模式
Decorator装饰器模式
对每一个特性构造子类,通过委派机制增加到对象上
Strategy策略模式
有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里
Template Method模板模式
共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现
Iterator A strategy pattern for iteration
visitor 为ADT预留一个将来可扩展功能的“接入点”,外部实现的功能代码可以在不改变ADT本身的情况下通过delegation接入ADT
Abstract Functions & Representation Invariants(AF &RI)
抽象函数
定义了系统的功能接口,使得模块之间可以进行交互和协作;而表示不变量
则确保数据结构的有效性和一致性,提供了正确和可靠的操作。
Interfaces
Java 的接口
是一种用于表达抽象数据类型的有用语言机制Language mechanism
。subtypes
子类型 “B is a subtype of A” means “every B is an A.” In terms of specifications: “every B satisfies the specification for A.”
Equality
The ==
operator compares references. More precisely, it tests referential equality
. Two references are == if they point to the same storage in memory.
The equals()
operation compares object contents – in other words, object equality
, in the sense that we’ve been talking about in this reading.
The instanceof
operator tests whether an object is an instance of a particular type.
Always override hashCode
when you override equals
.
immutable types must override both equals() and hashCode().
Recursive Data Types
递归数据类型
Regular Expression & Grammars
形式语言和自动机
讲过原理,java实现的语法没讲过级联
x ::= y z
an x is a y followed by a z
重复
x ::= y*
an x is zero or more y
联合(也称为交替)
x ::= y | z
an x is a y or a z
Parser Generators
解析器生成器(Parser Generator)是一种工具,用于根据给定的文法规则和语法描述生成解析器代码。解析器的作用是将输入的文本按照语法规则进行分析,将其转换为抽象语法树或执行特定的操作。
Concurrency
即并发
,多个计算同时运行,共享内存和消息传递范例进程
就像一台虚拟计算机;线程
就像一个虚拟处理器
Thread Safety
- 限制:不共享数据。
- 不变性:共享,但保持数据不可变。
- 线程安全数据类型:将共享可变数据存储在单个线程安全数据类型中。
Socket & Networking
Socket(套接字)
是计算机网络编程中用于实现网络通信的一种编程接口。它提供了一种机制,使得不同计算机之间的进程能够通过网络进行数据交换和通信。
Socket在网络通信中的作用类似于电话中的插座。
TCP套接字(Transmission Control Protocol)
:TCP套接字提供可靠的、面向连接的通信。它使用TCP协议来确保数据的可靠传输,通过三次握手建立连接,并提供流式的、双向的通信。TCP套接字适用于需要可靠传输和顺序传输的应用,如文件传输、网页浏览等。UDP套接字(User Datagram Protocol)
:UDP套接字提供无连接的、不可靠的通信。它使用UDP协议来发送和接收数据,不保证数据的可靠性和顺序,但具有较低的延迟。UDP套接字适用于实时通信和广播等应用,如视频传输、游戏、DNS等。
Queues & Message-Passing
使用队列来实现消息传递
Locks & Synchronization
Locks(锁)
和Synchronization(同步)
是在并发编程中用于管理共享资源和保护临界区的重要概念和技术。锁
是一种机制,用于控制对共享资源的访问。它提供了对临界区的互斥访问,确保在同一时间只有一个线程可以进入临界区并执行操作,从而避免多个线程同时访问共享资源而导致的数据不一致或竞态条件问题。常见的锁包括互斥锁(Mutex Lock)
和读写锁(Read-Write Lock)
等。同步
是一种机制,用于协调多个线程的执行顺序,以确保数据的一致性和正确性。它通过使用锁和其他同步原语(如条件变量
、信号量
等)来控制线程的执行顺序和访问共享资源的方式。同步机制可以防止多个线程之间的竞争条件和数据竞争问题,并确保线程之间的操作按照预期的顺序执行。
Graphical User Interfaces
窗口(Window)
:窗口是 GUI 的基本容器,用于承载其他组件。每个窗口都有自己的标题栏、边框和控制按钮,可以最大化、最小化、关闭等。控件(Widget)
:控件是 GUI 中的可视化元素,用于展示信息、接受用户输入和执行操作。常见的控件包括按钮、文本框、标签、复选框、滚动条等。布局管理器(Layout Manager)
:布局管理器用于控制和安排窗口中的控件的位置和大小。它可以确保控件在窗口中正确布局,并根据窗口的大小进行自适应调整。事件处理(Event Handling)
:GUI 界面可以响应用户的输入事件,如点击按钮、拖动滚动条等。事件处理机制用于捕获和处理这些事件,并触发相应的操作和逻辑。
Map,Filter,Reduce
映射(Mapping)
:
映射操作是将集合或序列中的每个元素都应用一个函数,生成一个新的集合或序列,其中每个元素都是原始元素经过函数处理后得到的结果。简单来说,就是对集合中的每个元素进行转换或映射。常见的应用场景包括对列表中的每个元素进行加工、提取元素的某个属性等。过滤(Filtering)
:
过滤操作是基于某个条件,从集合或序列中选择满足条件的元素,生成一个新的集合或序列。过滤操作通过提供一个判定条件函数来决定哪些元素应该被保留下来,而哪些应该被过滤掉。常见的应用场景包括从列表中筛选出符合特定条件的元素。归约(Reducing)
:
归约操作是将一个集合或序列中的所有元素通过某个操作进行组合,生成一个单一的结果。这个操作通常是将集合中的元素逐个进行累积或聚合,以产生一个最终结果。常见的归约操作有求和、求最大值、求平均值等。
Little Languages
小语言
通常用于描述和处理特定领域的数据和操作。它们可以用于数据转换
、配置文件解析
、模板生成
、领域特定的查询
和规则引擎
等任务。
一些常见的小语言包括正则表达式语言
、SQL(结构化查询语言用于数据库查询)
、HTML(超文本标记语言)