版本控制
将目录变成git可管理的仓库:git init
添加至暂存区:git add 文件名1 [文件名2 ...]
提交至本地仓库:git commit -m "本次提交的说明"
查看仓库状态:git status
查看文件的修改:git diff 文件名
查看工作区和版本库某文件的区别:git diff HEAD -- readme.txt
显示从最近到最远的提交日志:git log
版本回退:git reset --hard 某个版本
HEAD是指向当前版本的指针,HEAD^表示上一个版本,HEAD^^表示上两个版本
HEAD~n表示表示上n个版本
xxxxx,也可以用版本号前面几位表示某版本,用于版本回退
查看命令历史:git reflog
丢弃工作区的修改:git checkout -- 文件名
--表示命令项的结束,暗示了后面是文件,而不是一个分支(去掉--则为切换分支命令)
若修改后未添加至暂存区,则执行后,文件与版本库中对应的文件一致
过修改后添加到了暂存区,则执行后,文件与暂存区中对应文件一致
使未提交至暂存区的工作区中的文件撤销修改(或删除):git restore 文件名
撤销对暂存区的提交:git restore --staged 文件名
git reset HEAD 文件名
向暂存区添加对某文件的删除:git rm 文件名
远程仓库
创建ssh key:ssh-keygen -t rsa -C "邮箱地址"
关联远程仓库:git remote add origin git@github.com:GitHub用户名/仓库名.git
远程仓库名字定义为origin
查看远程仓库信息:git remote -v
取消与远程仓库的关联:git remote remove origin
简短命令:git remote rm origin
向远程仓库上传本地分支:git push -u origin 本地分支名
加上-u后,可以直接使用短命令,git push、git pull。
删除远程分支:git push --delete origin 分支名
克隆远程仓库到本地:git clone git@github.com:GitHub用户名/仓库名.git
分支管理
显示所有分支:git branch
查看所有分支,包括远程分支:git branch -a
创建新分支:git branch 分支名
切换分支:git checkout 分支名
创建新分支并切换:git checkout -b 分支名
删除分支:git branch -d 分支名
重命名本地分支:git branch -m 旧名字 新名字
-M:即使存在新名字对应的分支,也强制重命名
将当前分支重命名:git branch -M 新名字
通配符
通配符“.”将匹配任意一个字符
通配符“+”用来查找出现一次或多次的字符
通配符“*”匹配零次或多次出现的字符
通配符“?”指定可能存在的元素,前面的字符要么存在要么不存在
指定字符出现次数
要匹配字符串"aaah"中出现 3 到 5 次的 a,你的正则表达式将是a{3,5}h
仅匹配字符串"haaah"与至少出现 3 次的字母 a,正则表达式将是ha{3,}h
为了仅匹配"hah"中出现 3 次的字母 a,你的正则表达式将是ha{3}h
指定匹配字符范围
用方括号[and]中来定义一组你希望匹配的字符
你要匹配"bag","big"和"bug",而不是"bog"。你可以创建正则表达式/b[aiu]g 来执行此操作
字符- 定义要匹配的字符范围
character sets 字符集[0-5]匹配 0 和 5 之间的所有数字,包括 0 和 5
字符“^”定义不想要匹配的字符,[^aeiou]排除元音的所有字符
特定字符表示
快捷方式\w 匹配字母数字[A-Za-z0-9_]
快捷方式\W 搜索\w 的相反方向。需要注意相反的模式使用大写字母。此快捷方式与[^A-Za-z0-9_]相同
快捷方式\d 搜索数字字符集[0-9]。
快捷方式\D查找非数字字符,等于字符集[^0-9]。
模块化的基本原理:关注点的分离,分而治之
衡量软件模块化的程度:耦合度和内聚度
耦合度:无耦合、松散耦合和紧密耦合(我们追求的是松散耦合)
理想的内聚是功能内聚,就是一个模块只完成一个功能
概念
接口就是互相联系的双方共同遵守的一种协议规范,在我们软件系统内部一般的接口方式是通过定义一组API函数来约定软件模块之间的沟通方式。换句话说,接口具体定义了软件模块对系统的其他部分提供了怎样的服务,以及系统的其他部分如何访问所提供的服务。
通用接口定义的基本方法
概念
可以由多于一个任务并发使用,而不必担心数据错误。
基本要求
需求:用户期望软件行为的表述
需求分析:在获取需求的基础上进一步对软件涉及的对象或实体的状态、特征和行为 进行准确描述或建模的行为
原型化方法、建模方法
统一过程(UP,Unified Process)的核心要义是用例驱动(Use case driven)、以架构为中心(Architecture centric)、增量且迭代(Incremental and Iterative)的过程。用例驱动就是我们前文中用例建模得到的用例作为驱动软件开发的目标;以架构为中心的架构是后续软件设计的结果,就是保持软件架构相对稳定,减小软件架构层面的重构造成的混乱。
敏捷统一过程(Agile Unified Process)进一步将软件过程中每一次迭代过程划分为计划阶段和增量阶段。
敏捷统一过程的四个关键步骤:
显然,第一到第三步主要是计划阶段的工作,第四步是接下来要进一步详述的增量阶段的工作。
设计模式的本质是面向对象设计原则的实际运用总结出的经验模型。对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解的基础上才能准确理解设计模式。
单例模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例。
原型模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例,原型模式的应用场景非常多,几乎所有通过复制的方式创建新实例的场景都有原型模式。
建造者模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
代理模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。代理模式是不要和陌生人说话原则的体现,典型的应用如外部接口本地化将外部的输入和输出封装成本地接口,有效降低模块与外部的耦合度。
适配器模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。继承和对象组合都可以实现适配器模式,但由于组合关系或聚合关系比继承关系耦合度低,所以对象组合方式的适配器模式比较常用。
装饰模式:在不改变现有对象结构的情况下,动态地给对象增加一些职责,即增加其额外的功能。装饰模式实质上是用对象组合的方式扩展功能,因为比继承的方式扩展功能耦合度低。
外观模式:为复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
享元模式:运用共享技术来有效地支持大量细粒度对象的复用。比如线程池、固定分配存储空间的消息队列等往往都是该模式的应用场景。
策略模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。策略模式是多态和对象组合的综合应用。
命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
模板方法模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。模版方法是继承和重载机制的应用,属于类模式。
职责链模式:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。通过这种方式将多个请求处理者串联为一个链表,去除请求发送者与它们之间的耦合。
中介者模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。例如,在 MVC 框架中,控制器(C)就是模型(M)和视图(V)的中介者,采用“中介者模式”大大降低了对象之间的耦合性,提高系统的灵活性。
观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为,这样所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。
MVC即为Model-View-Controller(模型-视图-控制器),MVC是一种设计模式,以MVC设计模式为主体结构实现的基础代码框架一般称为MVC框架,如果MVC设计模式决定了整个软件的架构,不管是直接实现了MVC模式还是以某一种MVC框架为基础,只要软件的整体结构主要表现为MVC模式,我们就称为该软件的架构为MVC架构。
分解视图
分解是构建软件架构模型的关键步骤,分解视图也是描述软件架构模型的关键视图,一般分解视图呈现为较为明晰的分解结构(breakdown structure)特点。分解视图用软件模块勾划出系统结构,往往会通过不同抽象层级的软件模块形成层次化的结构。
依赖视图
依赖视图展现了软件模块之间的依赖关系。
比如一个软件模块A调用了另一个软件模块B,那么我们说软件模块A直接依赖软件模块B。如果一个软件模块依赖另一个软件模块产生的数据,那么这两个软件模块也具有一定的依赖关系。
泛化视图
泛化视图展现了软件模块之间的一般化或具体化的关系,典型的例子就是面向对象分析和设计方法中类之间的继承关系。值得注意的是,采用对象组合替代继承关系,并不会改变类之间的泛化特征。因此泛化是指软件模块之间的一般化或具体化的关系,不能局限于继承概念的应用。
执行视图
执行视图展示了系统运行时的时序结构特点,比如流程图、时序图等。执行视图中的每一个执行实体,一般称为组件(Component),都是不同于其他组件的执行实体。如果有相同或相似的执行实体那么就把它们合并成一个。
实现视图
实现视图是描述软件架构与源文件之间的映射关系。比如软件架构的静态结构以包图或设计类图的方式来描述,但是这些包和类都是在哪些目录的哪些源文件中具体实现的呢?一般我们通过目录和源文件的命名来对应软件架构中的包、类等静态结构单元,这样典型的实现视图就可以由软件项目的源文件目录树来呈现。
部署视图
部署视图是将执行实体和计算机资源建立映射关系。这里的执行实体的粒度要与所部署的计算机资源相匹配,比如以进程作为执行实体那么对应的计算机资源就是主机,这时应该描述进程对应主机所组成的网络拓扑结构,这样可以清晰地呈现进程间的网络通信和部署环境的网络结构特点。当然也可以用细粒度的执行实体对应处理器、存储器等。
工作分配视图
工作分配视图将系统分解成可独立完成的工作任务,以便分配给各项目团队和成员。工作分配视图有利于跟踪不同项目团队和成员的工作任务的进度,也有利于在个项目团队和成员之间合理地分配和调整项目资源,甚至在项目计划阶段工作分配视图对于进度规划、项目评估和经费预算都能起到有益的作用。
软件危机的典型表现
开发大型软件过程中的根本问题是难以汇集众多参与人员的设计理念形成完整的、一致的软件复杂概念结构,从而使得大型软件项目往往会进展缓慢、成本暴涨及错误百出。
软件危机的根本问题
软件概念结构(conceptual structure)的复杂性,无法达成软件概念的完整性和一致性,自然无法从根本上解决软件危机带来的困境。
软件的生命周期划分:分析、设计、实现、交付和维护。
瀑布模型(Waterfall Model)是第一个软件过程开发模型,对于能够完全透彻理解的需求且几乎不会发生需求变更的项目瀑布模型是适用的。但是由于瀑布模型能够将软件开发过程按顺序组织过程活动,非常简单和易于理解,因此瀑布模型被广泛应用于解释项目进展情况及所处的阶段。瀑布
模型中的主要阶段通过里程碑(milestones)和交付产出来划分的。
V模型也是在瀑布模型基础上发展出来的,我们发现单元测试、集成测试和系统测试是为了在不同层面验证设计,而交付测试则是确认需求是否得到满足。也就是瀑布模型中前后两端的过程活动具有内在的紧密联系,如果将模块化设计的思想拿到软件开发过程活动的组织中来,可以发现通过将
瀑布模型前后两端的过程活动结合起来,可以提高过程活动的内聚度,从而改善软件开发效率。这就是V模型。
CMM/CMMI:能力成熟度集成模型。
用于评价软件生产能力并帮助其改善软件质量的方法。
CMMI 共有5个级别:初始级、管理级、已定义级、量化管理级、持续优化级。数字越大、成熟度越高,软件综合开发能力越强。
DevOps(Development和Operations的组合)是一组过程、方法与系统的统称,用于促进软件开发、技术运营和质量保障(QA)部门之间的沟通、协作与整合。它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作。
通过对孟宁老师的《高级软件工程》课程的学习以及《代码中的软件工程》书籍的阅读,我学习到了很多知识,这些知识在实际开发有非常具有实用性,对程序员技术面试也有很大的帮助。感谢孟宁老师!同时也向大家推荐孟宁老师的课程以及书籍。