第一——四章作业
第一章
1.编写四则运算生成器(python)
答:
__author__ = \’Doris\’
from random import *
def createAnExpression():
beginNum = 0
endNum = 100
a = randint(beginNum, endNum)
b = randint(beginNum, endNum)
c = randint(beginNum, endNum)
d = randint(beginNum, endNum)
opChoice = (” + “, ” – “, ” * “, ” / “)
op1 = choice(opChoice)
op2 = choice(opChoice)
op3 = choice(opChoice)
exp = str(a) + op1 + str(b) + op2 + str(c) + op3 + str(d)
return exp
if __name__ == “__main__”:
num = 50
for i in range(0, 50):
print createAnExpression()
2.列举你在使用软件的时候观察到的“特殊”现象,它们能说明软件的某些本质特性么?
答:软件的“特殊”现象:
a. 闪退现象:在使用一些游戏软件时,因为内存不足会出现闪退现象,在没有提醒的情况下用户体验较差。
b. 卡机现象:在部分软件发布新版本时,会出现机器卡死现象,如百度浏览器等,被大家所诟病。出现原因可能为新版本功能紊乱,没有做到很好的测试。
c. 濒死现象:软件只有最初一个版本,反馈Bug也没有下一步修复,可能原因是开发者不再进行维护,常出现在学校项目中。
3.上网调查一下目前流行的源程序版本管理软件和项目管理软件都有哪些, 各有什么优缺点?
答:目前流行的源程序版本管理软件有 Microsoft TFS, GitHub, SVN, Hg/Mercurial
TFS:由微软提供的团队协作开发工具,集中式
Git:开源的版本控制工具,分散式控制
SVN:集中式控制
Hg:分布式控制
|
优点 |
缺点 |
TFS |
|
|
Git |
|
|
SVN |
|
|
Hg/Mercurial |
|
项目管理软件:
Trac:开源的应用平台,包含wiki和问题跟踪。以面向进度模型为项目管理模型,以里程碑方式进行项目管理。使用python开发,需要环境支持。
Bugzilla:为Unix定制的追踪系统的软件,可以管理软件开发中缺陷的提交、修复、关闭等整个生命周期。
Apple XCode:苹果公司向开发人员提供的集成开发环境,用于建立iOS X和iOS应用。拥有统一的用户界面设计、编码、测试、调试都在一个简单的窗口内完成,编译速度极快。
4.软件工程是不是教那些不怎么会写程序的人开发软件? 你怎么看?
答:软件工程并不是教不会写程序的人开发软件,而是提供一种科学的、有效的开发思想、开发理念、开发模式和开发流程,使得开发团队更有效地工作,提供更可靠的、更优秀的产品。
5.你所在的学校有计算机科学专业和软件工程专业么?相关专业的教学计划和毕业出路有什么不同?
答:天津大学开设有软件工程和计算机科学两个专业:
计算机科学专业侧重于科学,也就是学术,侧重于数学和计算机的具体方向,如图论、图形图像、并行计算等,也有硬件开发等。
软件工程专业侧重于软件开发,如语言类课程、设计模式、操作系统、需求分析、软件体系结构、UML建模语言、软件项目管理等。
两者的主要区别在于软件工程是涉及人类活动的,考虑这个软件做什么,怎么组织团队,怎么完成软件,怎么更好地开发等;而计算机科学则更多地从理论的角度出发,并不直接考虑工程方面的问题。
一句玩笑话是“软工出来的,都是码农;计科出来的,90%码农,10%电工”。
6.有学生提到,在大学选课的时候,可以写一个“刷课机”的程序,利用学校选课系统的弱点或漏洞,帮助某些人选到某些课程。或者帮助用户刷购票网站,先买到火车票。这些软件合法么?符合道德规范么?是在“软件工程”的研究范围么? 请大家讨论。
答:这种做法是不合适的,并不符合道德规范,不在“软件工程”的研究范围内。
软件工程是有着明确的职业道德要求的,只有当软件在安全、符合规范、通过测试、不降低生活质量、不侵犯隐私、不对环境造成伤害时,我们才认可这个软件,不能以牺牲他人利益来谋求自身利益。程序或者软件本身是没有伦理和道德约束的,但是企业或者程序员是要有自身职业道德要求与素养的,无规矩不成方圆,程序员不能无所控制。
7.有人认为,“中文编程”, 是解决中国程序员编程效率一个秘密武器,请问它是一个 “银弹” 么?
答:“中文编程”并不是提升编程效率的武器。首先目前并没有成熟的编译环境;第二、反复切换中英文输入容易引起不易察觉的Bug;第三,英语作为目前编程的公认语言,被大家广泛使用,使用中文编程后,大量的开源项目都难以维持,造成交流上的障碍;第四,中文语言歧义较多,需要定制一系列的规定才能真正应用起来。
8.创建个人技术博客 (建议是 cnblogs.com)
答:已经创建。
9.快速看完整部教材,列出你不懂的 5 – 10 个问题,发布在你的个人博客上。
答:问题:两人结对编程在时间操作中的可行性
敏捷流程相比于增量开发,对于成员个人能力要求太高,是否是主流的开发方法
在目前开发中,尽量避免过多的文档,TFS功能是否太过复杂
目前编程人员频繁跳槽的处理方法
在公司实际开发过程中,使用完整的软件工程思想开发,时间、经济上能否承受
10.现代软件工程这门课已经上了好几年了,以前有很多学生做过团队项目(说不定包括本校的学生),请你们找一个以前的团队采访一下:当时的项目有多少用户,给用户多少价值? 现在还有人用吗?这个项目能否给我们团队继续开发,源代码/文档还有么?项目开发有什么经验和教训对学好软件工程有什么建议?
答:“移动物联系统”:项目使用手机等移动设备控制家用电器,作为竞赛项目,成果较好,但是没有推向市场。在竞赛结束后没有进行后期的开发和维护。项目源代码和文档仍有存档,但是由于代码没有备注、文档过于简单,所以再次开发成本较高。
经验和教训:对于较好的软件要进行市场推广;在开发过程中留有较为详细的文档说明和必要的备注,以便于移交给其他人进行继续开发。
对于学好软件工程的建议是:多关注业界信息,了解新的软件工程思想;理论结合实践,在实际开发中,尽量使用软件工程的观念进行开发。
11.请问 “软件” 和 “软件工程” 这些词汇是如何出现的 – 何时、何地、何人
答:“software”:1958年,Tukey的论文”The Teaching of Concrete Mathematics”中首次使用software的概念。1953年Richard R.Carhart在备忘录中使用software一词
“software engineering”:1968年在第一个软件工程大会上,NATO首次提出software engineering的概念。
第二章
1.(1)全部用命令行工具和notepad编辑器,不用Visual Studio 等集成编辑环境,每人手工创建并编译一个C的命令行程序:“Hello World”。
(1)答:
(2)练习数值计算。找出一个整数数组中子数组之和的最大值,例如:数组[1, -2, 3, 5, -1],返回8(因为符合要求的子数组是 [3, 5]);数组[1, -2, 3, -8, 5, 1],返回6(因为符合要求的子数组是 [5, 1]); 数组[1, -2, 3,-2, 5, 1],返回7(因为符合要求的子数组是 [3, -2, 5, 1])。
答:MaxSum:
#include <iostream>
using namespace std;
intarrayMaxSum(int* arr, int n)
{
int sum = arr[0];
inttmp = 0;
for(inti=0; i<n; i++)
{
if(tmp< 0)
tmp = arr[i];
else
tmp += arr[i];
if (sum <tmp)
sum = tmp;
}
return sum;
}
int main()
{
intmyArr[100] = {1, -2, 3, 5, -1};
intnum = 5;
intrlt = arrayMaxSum(myArr, num);
cout<<rlt;
return 0;
}
1.(3)字符串操作。把一个英语句子中单词的次序颠倒后输出。例如程序的输入是“how are you”,则返回“you are how”。
答:Reverse Word:
#include <iostream>
#include <cstring>
using namespace std;
voidswapChar(char &a, char &b)
{
chartmp = b;
b = a;
a = tmp;
}
voidsentenceSwap(char* str, intsBegin, intsEnd)
{
int low = sBegin;
int high = sEnd;
while (low < high)
{
swapChar(str[low], str[high]);
low++;
high–;
}
}
voidreverseWord(char str[])
{
intlen = strlen(str);
sentenceSwap(str, 0, len-1);
int s = 0;
int e = 0;
for (inti=0; i<len; i++)
{
e = i;
if (str[e] == \’ \’)
{
sentenceSwap(str, s, e-1);
s = e + 1;
}
if (e == len-1)
{
sentenceSwap(str, s, e);
}
}
}
int main()
{
charstr[] = “hosw are you”;
reverseWord(str);
cout<<str<<endl;
return 0;
}
1.(4)使用工具Visual Studio,创建一个C++或C# Windows程序,在主窗口中显示“Hello World”,用户可以用鼠标拖动“Hello World”在主窗口中移动。
答:鼠标拖动hello world:
Form1.cs:
using System;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Windows.Forms;
namespaceDragLabel
{
publicpartialclassForm1 : Form
{
public Form1()
{
InitializeComponent();
}
privatePointmouseOffset;
privatevoid label1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
PointmousePos = Control.MousePosition;
mousePos.Offset(mouseOffset.X, mouseOffset.Y);
((Control)sender).Location = ((Control)sender).Parent.PointToClient(mousePos);
}
}
privatevoid label1_MouseDown(object sender, MouseEventArgs e)
{
mouseOffset = newPoint(-e.X, -e.Y);
}
}
}
namespaceDragLabel
{
partialclassForm1
{
///<summary>
///必需的设计器变量。
///</summary>
privateSystem.ComponentModel.IContainer components = null;
///<summary>
///清理所有正在使用的资源。
///</summary>
///<param name=”disposing”>如果应释放托管资源,为 true;否则为 false。</param>
protectedoverridevoid Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
///<summary>
///设计器支持所需的方法 – 不要
///使用代码编辑器修改此方法的内容。
///</summary>
privatevoidInitializeComponent()
{
this.label1 = newSystem.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = newSystem.Drawing.Point(12, 26);
this.label1.Name = “label1”;
this.label1.Size = newSystem.Drawing.Size(77, 12);
this.label1.TabIndex = 0;
this.label1.Text = “Hello World!”;
this.label1.MouseDown += newSystem.Windows.Forms.MouseEventHandler(label1_MouseDown);
this.label1.MouseUp += newSystem.Windows.Forms.MouseEventHandler(label1_MouseUp);
//
// Form1
//
this.AutoScaleDimensions = newSystem.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = newSystem.Drawing.Size(284, 261);
this.Controls.Add(this.label1);
this.Name = “Form1”;
this.Text = “Form1”;
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
privateSystem.Windows.Forms.Label label1;
}
}
1.(5)很多同学自己会写不少程序,但是往往看不懂别人写的程序,这也需要练习。不借助电脑的帮助,回答下面的问题(如代码清单2-8所示)。
答:. 解读成成
(1) 程序要找的数为:寻找不能被数组中rg[k]和rg[k+1] 整除,但是可以被其他所有数整除的数。
(2) 首先分析rg的特征:
当n <=15时,n *2 也在数组中,所以n>15.
剩下的数字可以分解为16=2*8, 18 = 2*9, 20 = 4*5, 22 = 2*11, 24 = 3*8, 26 = 2*13, 28 = 4*7, 30 = 2*15, 但是因为16=2*8中2是8的因子,所以16去除。
这样可以筛选出rg[ k ] 和rg[ k+1]为16和17。
接下来就是求不能被16 和17 整除,但是能整除其余所有数的数字。
2到31中去除16和17的所有素数为:2 3 5 7 11 13 19 23 29 31
非素数可由素数作为因子相乘得到,其中8=2*2*2, 25=5*5, 27=3*3*3, 为例外情况。
所以,最小的数为 2^3 * 3^3 * 5^2 * 7 * 11 * 13 *19 * 23 * 29 * 31 =
2123581660200
(3) 估计时间:
该程序主要包括一个取模和一个判断,如果进入if语句的话,还包括1次加法操作,1~2次判断和一次赋值操作。
加法、判断等操作在几个时钟周期内,除法、取模操作在几十个时钟周期,另外,对64位整数的除法要慢于32位整数。
我们可以假设一次操作需要100个时钟周期。因此4GHz的CPU在1秒内能跑4*10^9 / 100 = 4*10^7 即6.4亿次原子操作,大约是0.03s。
接下来操作的次数:外层循环跑了2123581660200次,内层循环取决于i的情况,当i为奇数的时候,内层最多跑5次即可结束;当i为偶数的时候,大约平均在10次,总的操作执行了2*10^13次。
所以需要 2*10^13 / (4*10^7)* 0.03 = 6000秒,约为100min。
(4) 可以使用CUDA进行GPU加速,将对数组的每个元素的除法分开计算。
2. 请同学们做一个调查,到相关的软件学院或计算机学院采访学长或学弟学妹,调查一下程序设计大作业的完成情况:程序花多少时间完成?程序量是多少(多少行代码)?开发过程中使用了源代码管理等工具么? 完全独立完成的同学有多少个?程序解决实际问题么?在一些学校里,全班50 个同学,交上来的作业只有 4 到 5 种版本。这说明了什么?
答:程序设计大作业大概是3周时间,每天4小时,15* 4 = 60小时。
程序量为1000 ~ 1500 LOC.
本科大作业多为个人项目,所以使用源代码管理的同学较少,一些习惯较好的同学会使用Git管理代码。
完全独立的学生在3-5人左右。
说明了同学们在遇到困难的时候更倾向于”拿来主义”,而不是请求帮助,自己完成;其次,在时间规划上并不好,经常是前面很长时间没有好好写,到了DDL,时间紧迫也就”心安理得”地用他人的作业。
3.效能分析的讨论
答:使用List替代ArrayList, 因为ArrayListz在存储或检索值类型时通常发生装箱和取消装箱操作,带来很大的性能耗损。
可以使用性能分析工具Performance analysis tool来观察程序中每一句的时间开销,从而优化程序。
第三章
软件工程师的成长 练习与讨论
1.选哪一种医生?
(1)答:A是新手型,当产品有新的功能需求时,由于经验有限,这一类的程序员并不完全知道要如何实现这个功能,需要通过学习、寻找资料等方式来解决问题。
B是创新型,这一类型的程序员喜欢以新的方法解决现有问题,同样喜欢发明方法解决尚未解决的问题。有时会发明出新东西,有时也会创新失败。
C是经验型,这类程序员在行内具有多年丰富的经验,技术熟练,手法纯熟,但面对新的挑战时还是要和其他人站在同一起跑线上的;
D是折腾型,擅长“折腾”,行为也许与业内规范不靠边,但是不排除有时也会折腾出东西。
(2)你要选哪种类型的医生?
答:如果我可以选择, 我要选C那样的医生。
(3)医生、药剂师、律师和很多行业都有职业考试和职业证书,软件工程师需要有正式的职业证书才能上岗么?
答:个人认为如果作为软件工程师仅仅是为了找一份工作,并且自身技术过硬,那么没有正式的职业证书也可以上岗,当然有证书再好不过。但是如果是为了全身心投入这个行业来进行发展、研究,那么取得一份正式的职业证书是很有必要的。
2.工程还是艺术
(1)软件开发是一门工程(Engineering), 是一门艺术(Art),还是一门手艺(Craftmanship)? 你如何衡量艺术家? 如何衡量创造能力?
答:个人认为软件开发是一门工程,然后是一门艺术。不论在哪个领域,优秀的作品就是艺术,创造它的就是艺术家。衡量创造能力从艺术家的作品看起。
(2)软件设计工程师们在做代码复审的时候,是看“重复字”的多少, 还是程序的艺术性?
答:不同作品评审的要求不同,“重复字”不能作为所有作品的衡量标准。在一个程序中,代码不重复使用是不现实的事情,而在编程过程中,有些代码合理重复,对整个程序有积极作用,那它就是具有艺术性的。所以,代发复审的标准不能仅仅用这几个方面来衡量规定。
(3)这个问题的另一个侧面是,在中国,一个成名的歌唱家往往出现在各种场合,演唱她当年成名的作品,观众们往往显得百听不厌。一个软件工程师就不能这样,在舞台上展现他当年写的“hello world” 程序,或者是1.0 的产品。为啥有这样的区别呢?
答:一个软件工程师不能在舞台上展现他当年写的“hello world” 程序,或者是1.0 的产品的原因,个人认为是因为,软件开发虽然是一门艺术,但是它却不仅仅是一门艺术。虽然经典永远是经典,但是软件开发它自身会有一个更新迭代的过程。
3.绞刑架和职业发展
请同学们思考这个故事对个人及软件业发展的启示。
答:这个寓言故事对于个人,是鼓励个人要不怕困难勇敢进取。有了困难,才能拦阻与淘汰掉一切不如我们的同行竞争者。有时候,阻碍对于个人而言不是仇敌,而是恩人。
对于软件业的发展来说,首先这个故事中的绞刑架到底是指什么,是代表软件工程理论规范,还是软件开发过程中的困难。有了软件开发理论规范的约束,会使软件开发的标准语流程变得正规,规范的程序员可以得到更好的发展,软件的质量达到一个更好的提升,对于同行的竞争力变大。同样,有了困难,才能促进我们的发展。
4.案例
答:个人认为小飞应该更改设计,向老板、同事解释、承认自己的错误,主动承担责任。因为一个项目的开发首先是团队合作,然后才是个人技术的展示。要将团队利益放在首位,从大局出发来考虑事情。
5.成长和代码量的关系
软件工程师的工作就是写代码,相关专业的练习也是以阅读代码,写代码为主,那么代码量和工程师的水平是线性的关系么?
答:程序员Norris发现了一个基本常数,提出了程序员瓶颈这样的概念。通过阅读这段文字,我个人的体会为程序员的水平与代码量之间并不是一个线性的关系。可以说,代码量的积累对工程师的水平的提高一定有关系,并且工程师的水平的提高一定有代码量积累的参与。就好比量变是质变的必要准备,质变是量变的必然结果,质变不仅可以完成量变,而且为新的量变开辟道路,并且总的量变中有部分质变,质变中有量变的特征。
所以工程师的水平与代码量的关系应该与质变和量变一样,是一种阶梯式的前进与螺旋式的上升的关系。
6.成长和公司的关系
软件工程师在企业中是劳动密集型的工人么,还是有独创性的专业人士? 他们对软件企业的成败负多大的责任?
答:软件工程师在企业中应该是有独创性的专业人士。他们对软件企业的成败所负的责任大小应该取决于他们在企业决策中所能起到的影响力的大小。如果软件工程师所做的工作与公司方向的决策与改变没有什么影响,那么不应由他对企业的成败负责,反之亦然。
第四章
结对编程 练习与讨论
4.7.1 结对项目的案例与论文,请阅读至少两篇相关论文或论文。
答:论文已阅读。
4.7.2请看网上关于MBTI的文章,测试并分享各自的MBTI类型,讨论不同性格类型对合作有多大的影响, 在合作的各个阶段应该如何应对。
答:性格对合作的影响
MBTI倾向显示了人与人之间的差异,而这些差异产生于:
– 他们把注意力集中在何处,从哪里获得动力(外向、内向)
– 他们获取信息的方式(实感、直觉)
– 他们做决定的方法(思维、情感)
– 他们对外在世界如何取向;通过认知的过程或判断的过程(判断、知觉)
用字母代表如下:
精力支配:外向 E — 内向 I
认识世界:实感 S — 直觉 N
判断事物:思维 T — 情感 F
生活态度:判断 J — 知觉 P
其中两两组合,可以组合成16种人格类型。
团队成员的性格分别是:包扬ENTJ(外倾直觉思维判断),高晓妮ENTJ(外倾直觉思维判断),吴熙ESTJ(外倾感觉思维判断),郭小星ISFJ(内倾感觉情感判断)
在团队合作中,外倾型的人一般会较为热情对工作积极性比较大,内倾型比较安静,外倾型依靠思维做出选择判断较多,内倾型依靠清感做出选择判断较普遍。从作决策的方式来看,两类人都有理性思考的成分,但作决定或下结论的主要依据不一样。情感型的人常从自我的价值观念出发,变通地贯彻规章制度,做出一些自己认定是对的决策,比较关注决策可能给他人带来的情绪体验,人情味较浓。思维型的人则比较注重依据客观事实的分析,一以贯之、一视同仁地贯彻规章制度,不太习惯根据人情因素变通,哪怕做出的决定并不令人舒服。所以在团队合作时,团队里应包容统一,协调合作。
4.7.3 是否需要有代码规范
对于是否需要有代码规范[vi],请考虑下列论点并反驳/支持:
-
这些规范都是官僚制度下产生的浪费大家的编程时间、影响人们开发效率, 浪费时间的东西。
-
我是个艺术家,手艺人,我有自己的规范和原则。
-
规范不能强求一律,应该允许很多例外。
-
我擅长制定编码规范,你们听我的就好了。
答:1. 这些规范都是官僚制度下产生的浪费大家的编程时间、影响人们开发效率, 浪费时间的东西。(反驳)
统一是有价值的,一个程序员永远不可能独自工作,在软件团队工作时代码规范是一定要强调的,这是团队积攒下来的经验。在整个软件团队的工作环境中,它能够大幅度节约团队编程所需要的时间,提高团队的工作效率。也许代码规范会让刚接触的使用者感到束手束脚,但是熟悉之后,在程序的可理解性上得到的好处会大大的补偿之前的损失。
2.我是个艺术家,手艺人,我有自己的规范和原则。(反驳)
特立独行对于开发者来说也许很合适,但是在软件团队的工作中,艺术家的行业道德并不合适。一个人的规范不叫规范,没有哪个人的个人规范和原则可以凌驾于团队规范与团队原则之上。如果因为一个人的个人规范和原则导致团队工作受到了严重的影响,那么这样的规范和原则不如没有。
3.规范不能强求一律,应该允许很多例外。(反驳)
规范应该尽量一致,即使有例外,也只能是少数情况,而不能是很多例外。我个人认为例外多了,就不能叫做例外了。
4.我擅长制定编码规范,你们听我的就好了。(反驳)
在团队工作中,完全遵守代码规范的收益是 降低阅读代码时候的沟通成本,但是在一个团队适用的规范和原则在另一个团队不一定同样适用。如果对现有的代码规范和原则有意见,可以通过一定方法修订并发布新的规范。但是在新的规范发布之前,遵守旧的规范,维护团队利益。
4.7.4 代码复审的讨论
答:代码复审的讨论
4.7.5 阅读别人的代码有多难?我们经常抱怨阅读别人的代码很难, 我们自己在写代码的时候,是否考虑到如何让代码更易于阅读和维护呢?
答:关于自己编写代码时,如何让代码更易于阅读与维护。
归纳:
1.
使代码遵从工具
2.
坚持使用一种命名模式
3. 使用断言来记录先决条件和后置条件
4. 不要随意缩写英文单词
5.
C语言标准运行时库的设计不是很优秀。不要去效仿它
6.
不要写“聪明”的代码
7. 理解编程语言特性的设计初衷,使用这些特性去做它们适合完成的工作,而不是它们能做到的工作
8. 按功能单元划分源码树,而不是按组织结构