《构建之法》邹欣pdf:https://pan.baidu.com/s/1Z7cTtVBqxbVcU3vsyynysQ 提取码:dusr

章1.概论

软件=程序+软件工程

写程序练习数据结构/算法,用新的语言尝试以下“hello world”->用JavaScrip、ASP.NET、Ruby写写网站->钻研新技术,应用新技术在软件行业创新->银行软件系统,互联网搜索行业,淘宝、Windows操作系统

软件工程是什么

软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上 的过程

软件的特殊性

软件的各种形式:

  • 系统软件:操作系统、设备驱动程序、工具软件等
  • 应用软件:用户使用它们来完成工作,从管理核电厂到写文章,或者是通信、 游、浏览网页、播放视频等
  • 恶意软件:软件病毒等软件

软件开发过程中有什么特别的难题?

  • 复杂性(Complexity):软件的各个模块之间有各种显性或隐性的依赖关系,随着系统的成长和 模块的增多,这些关系的数量往往以几何级数的速度增长
  • 不可见性(Invisibility):工程师是“看”不到自己的源代码如 何具体地在用户的机器上被执行的。商用软件出现了错误,工程师可以看到程序 在出错的一瞬间留下的一些痕迹(错误代号、大致的目标代码位置、错误信 息),但是几乎无法完整重现到底程序出现了什么问题
  • 易变性(Changeability):正确地修改软件是一件很困难的事情。
  • 服从性(Conformity):软件总是要运行在硬件上面,它要服从系统中其他组成部分的 要求,它还要服从用户的要求、行业系统的要求
  • 非连续性(Discontinuity):有时输入上很小的变化,会引起输出上极大的变化

软件的这些本质特性让“做一个好软件”变得很难,同时也让软件工程有它独特的挑战和魅力

软件工程与计算机科学的关系

工程:创造性地运用科学原理,设计和实现建筑、机器、装置或生产过程;或者是在实践中使用一个或多个上述实体;或者是实现这些实体的过

托尼·霍尔(Tony Hoare)比较计算机科学和软件工程不同的侧重点

计算机科学 软件工程
发现和研究长期的、客观的真理 短期的实际结果(具体的软件会过时)
理想化的 对各种因素的折衷
确定性,完美,通用性 对不确定性和风险的管理,足够好,具体的应用
各个学科独立深入研究,做出成果 关注和应用各个相关学科的知识,解决问题
理论的统一 百花齐放的实践方法
强调原创性 最好的、成熟的实践方法
形式化,追求简明的公示 在实践中建立起来的灵感和直觉
正确性 可靠性

软件工程的目标–创造“足够好”的软件

好软件–没有缺陷(Bug) | 软件工程–把软件中的Bug都消灭掉的过程

  • 用户满意度:用户使用时发现了很多Bug,影响了用户使用软件的效率。

  • 可靠性:某个软件经常会崩溃,某个操作系统会时不时死机。

  • 软件流程的质量:软件团队和开发流程的问题太多,导致团队成员无法互相协 作,按时交付软件。这也可以说是软件团队的Bug。

  • 可维护性:某个软件太难维护了,按下葫芦起了瓢,修复了一个问题,另一个问 题又出来了。也没有足够的文档,维护人员表示需要更多的资金和时间来维护这 个软件

章2.个人技术和流程

单元测试

  • 如何能让自己负 责的模块功能定义尽量明确,模块内部的改变不会影响其他模块,而且模块的质 量能得到稳定的、量化的保证?单元测试就是一个很有效的解决方案。

  • 因为可将程序的功能分为可作为单个单元 测试的独立可测试行为,所以它叫做单元测试

  • 只要你编写了一个函数或其他应用程序代码块,就可以创建单元测试用于验证对应于输入数据的标准、边界和不正确情况的代码的行为,而且用于检查代码所做的任何显式或隐式假设

VSTS (Visual Studio Team System) 写单元测试

简单例子

新建一个控制台程序ConsoleApp2,在Program.cs添加如下类:

public class CheckingAccount
    {
        public double m_balance;
        string name;

       public CheckingAccount(string name,double balance)
        {
            this.name = name;
            m_balance = balance;
        }

        public void Withdraw(double amount)
        {
            if (m_balance >= amount)
            {
                m_balance -= amount;
            }
            else
            {
                throw new ArgumentException(nameof(amount), "Withdrawal exceeds balance!");
            }
        }
    }

右击Withdraw方法点击创建单元测试

创建单元测试

在生成的CheckingAccountTests.cs中添加测试方法

		[TestMethod()]
        public void Withdraw_ValidAmount_ChangesBalance()
        {
            double currentBalance = 10.0;
            double withdrawal = 1.0;
            double expected = 9.0;
            var account = new CheckingAccount("hhq", currentBalance);

            account.Withdraw(withdrawal);

            Assert.AreEqual(expected, account.m_balance);
        }

image-20200209233637945

打开测试资源管理器,选择相应方法进行测试

打开测试资源管理器

更多内容

Visual Studio文档\单元测试https://docs.microsoft.com/zh-cn/visualstudio/test/getting-started-with-unit-testing?view=vs-2019

好的单元测试的标准

单元测试应该准确、快速地保证程序基本模块的正确性,单元测试应该在最基本的功能/参 数上验证程序的正确性。单元测试应该测试程序中最基本的单元—如在 C++/C#/Java中的类,在此基础上,可以测试一些系统中最基本的功能点(这些 功能点由几个基本类组成)

回归测试

在单元测试的基础上,我们就能够建立关于这一模块的回归测试(Regression Test)

在软件项目中,如果一个模块或功能以前是正常工作 的,但是在一个新的构建中出了问题,那么这个模块就出现了一个“退步”(Regression),从正常工作的稳定状态退化到不正常工作的不稳定状态。在 一个模块的功能逐步完成的同时,与此功能有关的测试用例也同样在完善中。一 旦有关的测试用例通过,我们就得到了此模块的功能基准线(Baseline),一个模块的所有单元测试就是这个模块最初的Baseline,一个 模块的所有单元测试就是这个模块最初的Baseline。工程师们应该在新版本上运行所有 已通过的测试用例,以验证有没有“退化”情况发生,这个过程就是一 个“Regression Test”。

效能分析工具

个人开发流程

PSP(Personal Software Process)

PSP有如下特点

  • 不局限于某一种软件技术(如编程语言),而是着眼于软件开发的流程,这 样,开发不同应用的软件工程师可以互相比较。
  • 不依赖于考试,而主要靠工程师自己收集数据,然后分析,提高
  • 在小型、初创的团队中,很难找到高质量的项目需求,这意味着给程序员的输 入质量不高。在这种情况下,程序员的输出(程序/软件)往往质量也不高, 然而这并不能全部由程序员负责
  • PSP依赖于数据
  • 需要工程师输入数据,记录工程师的各项活动,这本身就需要不小的时间代价
  • 如果数据不准确或有遗失,怎么办?让工程师编造一些?
  • 如果一些数据不利于工程师本人(例如:花很多时间修改缺陷),我们怎么能 保证工程师愿意如实地记录这些数据呢?
  • PSP的目的是记录工程师如何实现需求的效率,而不是记录顾客对产品的满意度

软件工程师的任务清单

PSP2.1
计划

  • 估计这个任务需要多少时间

开发

  • 分析需求
  • 生成设计文档
  • 设计复审(和同事审核设计文档)
  • 代码规范(为目前的开发制定合适的规范)
  • 具体设计
  • 具体编码
  • 代码复审
  • 测试(包括自测,修改代码,提交修改)

记录用时
测试报告
计算工作量
事后总结
提出过程改进计划

章3.软件工程师的成长

个人能力的衡量与发展

软件系统的绝大部分模块都是由个人开发或维护的。在 软件工程的术语中,我们把这些单个的成员叫做Individ-ual Contributor(IC)。 IC在团队中的流程是怎么样的呢?以开发人员为例,流程如下:

  • 通过交流、实验、快速原型等方法,理解问题、需求或任务
  • 提出多种解决办法并估计工作量
  • 其中包括寻找以前的解决方案,因为很多工作是重复性的
  • 与相关角色交流解决问题的提案,决定一个可行的方案
  • 执行,把想法变成实际中能工作的代码,同时验证方案的可行性和其他特性 (例如程序的效能等)
  • 和团队的其他角色合作,在测试环境中测试实现方案,修复缺陷(Bug)。如 果此方案有严重的问题,那么就考虑其他方案
  • 在解决方案发布出去之后,对结果负责每个人的工作质量直接影响最终软件的 质量

什么样的数据能说明一个软件工程师的技术和能力呢?衡量能力有哪 些参数?没有量化的指标,就谈不上衡量和比较。我们还是看看搬砖的伙计们, 关于工作量,他们:

  • 有多少块砖?
  • 要搬多远?他们也有简单的指标衡量工作质量。
  • 多快搬完?
  • 搬的过程中损坏了多少块砖?

初级软件工程师如何成长?

  • 积累软件开发相关的知识,提升技术技能(如对具体技术的掌握,动手能 力)。例如:对Java、C/C++、C#的掌握,诊断/提高效能的技术,对设备驱动程序(Device Driver)、内核调试器(Kernel Debugger)的掌握;对于某一开发平台的掌握
  • 积累问题领域的知识和经验(例如:对医疗或金融行业的了解)。第一点和第二点都可以在很多简历上都可以看到,也可以比较容易地检测出来。随着经验的 增长,一个工程师可以掌握更广泛、更深入的技术和问题领域的知识。
  • 对通用的软件设计思想和软件工程思想的理解。这一方面就比较虚,什么是好的软件设计思想?什么是好的软件工程思想?一个工程师开了博客,转发了很多别人的文章,这算有思想么?另一个工程师坚持做任何设计都要画UML图,这算有思想么?
  • 提升职业技能(区别于技术技能)。职业技能包括:自我管理的能力,表达和交流的能力,与人合作的能力,按质按量完成任务的执行力,这些能力在IT行业和其他行业都很重要
  • 实际成果。绝大部分软件工程师的工作成果都是可以公开的,你参与的产品用 户评价如何,市场占有率如何,对用户有多大价值?你在其中起了什么作用?

软件工程师的职业发展

就软件工程师这个职业而言,有很多证明 个人能力的办法和模型,下面简单介绍几种

职业发展—-考级之路

在中国,软件工程师的职业资格考试有:

  • 计算机等级考试和全国计算机技术与软件专业技术资格考试

此类考级的好处:国家认证,有一定的权威性和通用性;任何人都可以参与

局限性:以答题/评分为主要考试形式,没有面对面的口试;考试中每个人单独行动,不能考量团队合作能力;要考虑到通用性和稳定性,考题内容相对滞后于工业界的发展,部分内容相当滞后

很多公司也提供了针对自己产品的职业认证项目,如:

  • 微软公司有微软认证专家(Microsoft Certi-fied Professional,MCP)
  • 甲骨文公司有Oracle认证项目(Oracle Certi-fication Program,OCP)

国内也有机构和学校探索各种能力和认证考试服务,如:

职业成长—-Steve McConnell

一个软件工程师需要具备一定的知识和能力:

知识:迈克康奈尔把相关的软件知识分为十大知识领域

能力:一个工程师对这些知识的掌握分为如下四个阶段

  • 入门(Introductory);

  • 熟练(Competency);

  • 带头人(Leadership);

  • 大师(Mastery)

迈克康奈 尔把工程师分为8个级别(8—15),一个工程师要从一个级别升到另一个级别, 需要在各方面达到一定的要求。例如,要达到12级,工程师必须在三个知识领域 达到“带头人”水平。例如要到达“工程管理(知识领域)的熟练(能力)”水平,工 程师必须要做到以下几点:

  • 阅读:4—6个经典文献的深入分析和阅读
  • 工作经验:要参与并完成6个具体的项目
  • 课程:要参加3个专门的课程有些级别

职业成长—-大公司版本

微软公司的软件工程师职业等级:

等级 要求
SDE(初级软件开发工程师) 入门。在学校里学到了一些技能
SEE II(中级软件开发工程师) 独立。可以写别人交给你的任何东西,不明白时知道去问谁
Senior SDE(高级软件开发工程师) 小组领导。影响着3~12名工程师,或者是它们的行政领导;或者是它们的技术带头人
Principal SDE(首席软件开发工程师) 团队领导。影响着10人以上的一个大团队,成为影响团队成败的关键人物
更高的职位有:
Partner SDE
Distinguished Engineer
Technical Fellow
影响力扩大到整个机构,甚至工业界

职业成长—-自我评估

并不是每个软件工程师都有强烈的愿望或机遇去做最先进、最创新、最有风险的项目。绝大部分软件工程师都不是技术天才,但即使是一般的工程师,做一般的信息系统,就是业界说的“CRUD”(Cre-ate/Retrieve/Update/Delete,增删改查)数据库系统,也需要一些核心技术和许多扩展的知识:

基本需求 基本技术 扩展技术 进一步的扩展技术
把数据放到数据库中满足增删改查的需求 数据库技术(关系数据库的基本原理和操作) 大容量的数据库操作、并行、备份等技术 关系数据库模型,数据挖掘,商业智能
有网页满足一般用户的查询需求 网页服务技术(ASP.NET、PHP等),数据绑定及控件 用户界面的设计,对不同浏览器的支持 用户心理,用户交互的原则在不同设备和不同场景下的应用
能不断实现新的功能 编程语言和开发工具(Java、C#、Python) 程序的效能分析,软件的重用,面向对象的理论等 能改进软件工具,或构建新的语言提高解决问题的效率
软件团队能按时高质量完成任务 每日构建,版本管理,单元测试,项目管理 需求分析,敏捷开发等高级软件工程的技术 软件团队的绩效评估,团队的发展
要有一定的安全性 数据安全、网站的安全 计算机网络与数据通讯,操作系统的知识,数据加密解密 密码学,各种病毒工作原理
能满足业务的需求 对业务领域有基本的了解 进一步了解业务领域知识 对业务领域有深入了解,能洞察行业发展的趋势

很少有人能在学校里掌握这么多知识后才毕业找工作,随后把技术运用在实践中。工程师应该在实际工作中不断学习和不断成长,根据自己的情况选择在哪个方面追求“专和精”,在哪几个方面达到“知道就好”的水平

技能的反面

巴克斯顿说技能的反面是“Problem Solving”—“解决问题“

一个例子:

一个IT专业的大学生来面试,简历上写“技 能:精通Visual Studio C#编程”。于是面试官请他用Visual Studio IDE写一段程 序。一个“不精通”的面试者的编程过程实际上就是一个“解决问题”的过程。例如:
嗯,怎么开始一个C#的命令行程序呢? 定义数组是怎么弄的?是“int [] arr”还是“int arr[]”,还是ArrayList, 还是Array。哦,我平时都是上网查的。哦,我不知道还有MSDN网站。 嗯,为什么编译没过呢,哦,这里少一个分号。 嗯,怎么设断点?怎么定义命令行参数?额,
我要查一查……你发现他把时间都花在“解决(低层次)问题”上了,你想考察的“算法技能”、“C#程序设计技能”都无暇顾及。注意,这是在他认为非常精通的编程工具和编程语言中出现这样的问题。你要这样的员工么?那怎么提高技能呢?答案很简单,通过不断的练习,把那些低层次的问题都解决了,变成不用经过大脑的自动操作,然后才有时间和脑力来解决较高层次的问题

版权声明:本文为hhhqqq原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/hhhqqq/p/12287911.html