2017年秋,第三次使用邹欣老师的《构建之法:现代软件工程》作为教材,授课对象是计算机系研究生一年级学生。班级在这里[https://edu.cnblogs.com/campus/nenu/SWE2017FALL]。
在本轮授课中,有以下几方面印象较为深刻。
1. 工具
工欲善其事,必先利其器。
在课程中我们要求学生使用特定的工具,不仅希望这些工具能减少重复工作,更重要的是约束学生的操作,通过操作传授软件工程概念的组织结构和流程,好工具同时也是好的过程的示范。这些工具包括 GUI原型工具 墨刀、进度管理中看板和燃尽图工具 leangoo、版本控制工具git、tortoisegit。PSP中也应该包括时间记录工具atimelogger(toggl也不错,最近被墙了)。
1.0 原则
在软件工程的教学中,教师和助教也应该注意工具使用。
原则一 DRY[https://en.wikipedia.org/wiki/Don%27t_repeat_yourself]。
这是我们经常在课程中灌输给学生的,教师本身也应该以身作责,不然是件很人格分裂的事情。凡是通过profile发现占用大块时间的,特别是其中有重复工作的,应该优化这一部分。
原则二 过早优化是万恶之源。不熟悉的工作不应该写脚本或者做系统,妄图提高工作效率。在重复若干次以前,不应该盲目尝试创新。需要多次尝试,总结规律,然后写脚本。如果能熟悉大家的工作习惯,还应该写出软件来供大家用。
在本学期中,我完善和使用了一些半成品的脚本工具自用,用以提高工作效率。
目前仍需改进的是,手写的这些脚本仍然只是工具而不是工程,更不是产品,有不少硬编码和对环境的要求,不易为他人所用。好的工具还应该约束用户的行为,向用户指出设计者的意图(组织结构、流程),并且避免反复操作中的失误甚至避免反复操作本身。
1.1 投票统计-邮件AHK脚本
在课程中有同学们投票的活动,如在选题、alpha发布、beta发布、final发布中,有全体同学对作品投票排名次的要求。
为减少同学们投票的顾虑,采用匿名制。以往的学期中,曾经对投票人匿名,但是类似于唱票,公布过所有投票内容。但是教师低估了人性的聪明,同学们居然能猜出哪个票是谁投的。大致的原理是利益相关,会如何投票。这一原理导致不能公布所有投票,只能假设同学们可以信任教师可以保护匿名,由教师统计和发布。
要求投票的内容与一般问卷系统不同,是作品的名次(并且不得有并列),以确保分值差异化,或者人名,用于投票领跑黄衫获得者,既非多选,也非单选。所以目前没有找到适合的软件系统,由同学用电子邮件投票,发送给教师。没有用微信私聊,是因为不应假设所有同学都希望加教师为好友。
邮件有格式要求,比如下面这个。
本作业截止前每位同学向教师 ([email protected]) 发送1封邮件投票, 作为投票者的一次成绩5分。不投票或投票不符合要求 (包括不限于标题错误、 正文格式不符、小组名字写错) 的,视为未提交,倒扣分数。 投票 1名 你最感谢的同学。 收到感谢最多的同学将获颁“感谢多”黄色领跑衫。如果王超同学收到感谢最多,则由收到感谢第二多的同学获得。 -------邮件样例开始------------------ 邮件标题为: 我最感谢的同学 邮件正文为: 姓名:杨贵福 邹欣 -------邮件样例结束------------------
这次投票结果
收到投票34份,废票1张,重复投票1张,有效票共32票。
教师收到的邮件,比如下面这张截图。“姓名”之后是投票者的姓名,教师要用来登记完成投票这一作业的分数并避免重复投票,“排序”之后是这位投票者给出的各团队名次。
我对了件主题过滤,运行AHK写的脚本,遍历所有投票邮件,把每封邮件的正文复制添加到excel里。在excel中统一字体格式然后统计。
因为投票这一作业规定了截止期限,所以,AHK脚本在截止期限后运行。此后收到的邮件不必手工处理,而是丢弃。
邮件的正文在作业中有格式要求,凡是不符合格式要求的,作业不计分,投票视为废票。在实际操作中,有拼写错误、大小写错误、冒号半角全角错误的,一概按不符合格式要求处理,即使教师手动发现了这张投票。所以不需要处理更多的容错,同时这也是对同学们训练合规的一个机会。
不少地方非常粗糙,使得脚本仍然只是小工具,而不是适合更多人使用的软件。这本身有违软件工程的精神,不过符合重复次数不够多的情况下暂勿抽象的原则。比如,遍历邮件的个数是硬编码的;每封邮件打开以后停留一下,以保证正文载入完成。没有用中断/回调之类的机制,就只是等待;点击“下一封”按钮的位置与屏幕分辨率有关,也是硬编码的。
脚本如下。
; precodition:
; web邮箱录,搜索""选题 视频展示投票""结果页,打开第一封邮件,AHK脚本会循环开始下一封
; excel打开,光标置于左上
MsgBox, 4,, "Press Yes to go on if you have setup the env." (press Yes or No)
IfMsgBox Yes
dump()
else
return
dump()
{
SplashTextOn,,, "Working, please standby.".
sleep 2000
SplashTextOff
Loop, 31
{
; 复制邮件正文
MouseClick, left, 299, 421
Send ^{a}
Send ^{c}
; 切换到excel
IfWinExist, ahk_class XLMAIN
WinActivate ; use the window found above
else
MsgBox Please run Excel.
; 右移一列
Send {Right}
; 粘贴邮件正文
Send ^{v}
; 切换到firefox
IfWinExist, ahk_class MozillaWindowClass
WinActivate ; use the window found above
else
MsgBox Firefox lost.
; 下一封
;MouseClick, left, 1839, 226 ; home
MouseClick, left, 1833, 212 ; xxhb
sleep 2000 ; 等网页载入完毕
}
}
Escape::
ExitApp
Return
上学期一共统计投票200余次,每次30余张票,节省了不少时间。
统计得票时,分别统计某一团队名次第1、名次第2、名次第3、名次第4的票数,然后求得平均名次。最下一行的27,是用于交叉检验的。
1.2 pull脚本
单人任务和结对编程两个项目,需要把同学的代码成批从 coding.net中获取到教师机编译运行检查结果。这也是检验同学们是否能够正确使用版本控制工具的时机。
我写了shell脚本为每位同学分别建立目录和pull代码。还有脚本用于批量执行和对比,效果不佳,因为同学们普遍地没有按作业的spec要求放置文件。此处略。
以下是pull脚本。第一次作业时有相当数量的同学git不符合要求,执行扣分,以后的作业有所好转。
#mkdir 翟宇豪
#cd 翟宇豪
#git init
#git pull https://git.coding.net/Rio56/wf.git master
declare -A map=(["冉华"]="https://git.coding.net/Dawnfox/wf4_2.git"
["刘淑霞"]="https://git.coding.net/liusx0303/CountWords__standardinput.git"
["胡佑蓉"]="https://coding.net/u/huyr000/p/countWords/git"
["王超"]="https://git.coding.net/SuperCodingChao/wfProject.git"
["高远博"]="https://coding.net/u/Rainbows/p/wc/git" #old
["陈建宇"]=" https://coding.net/u/MR__Chen/p/Demo/git" #old
["代秋彤"]="https://git.coding.net/a284617374/soft.git"
["方铭"]="https://coding.net/u/MingZi-/p/cipingtongji/git"
["葛美义"]="https://coding.net/u/gmyznb/p/wordcount1/git"
["黄泽宇"]="https://coding.net/u/huangzy_95/p/wf/git"
["贾男男"]="git://git.coding.net/lynlynyess/wf.git"
["贾雅杰"]="https://git.coding.net/jyj5951/wf.git"
["姜珊"]="https://git.coding.net/js2017102865/wf_c.git"
["阚博文"]="https://git.coding.net/zbwd666/zbwd.git" # old
["李传康"]="https://git.coding.net/lick468/wf.git"
["李圆圆"]="https://git.coding.net/lyy181/count.git" #old
["蔺依铭"]="https://git.coding.net/Hitagi123/word-count.git"
["刘成志"]="https://git.coding.net/liuchengzhi0944/wf.git"
# ["刘耀泽"]="https://coding.net/u/liuyz349/p/word_count/git" # 未交作业
["米赫"]="https://git.coding.net/immixiaomi/wf.git" #old
["苗威"]="https://git.coding.net/Vrocker/wf.git"
["任思佳"]="https://coding.net/u/rensijia/p/count-words/git"
["邵朔"]="https://git.coding.net/ss505072461/wf.git"
["宋雨"]="https://git.coding.net/songyuu/wf.git"
["田继平"]="https://git.coding.net/tianjiping/11111.git" #old
["王航"]="https://git.coding.net/wangh013/wf.git"
["王磊"]="https://git.coding.net/137911934/SE20170914.git"
["王伟东"]="https://git.coding.net/wangwd/SecondAssignment.git"
["王玉玲"]="https://coding.net/u/tutu123/p/tutu1234/git" #old
["吴雨丹"]="https://git.coding.net/clairewyd/wf.git"
["徐劭斌"]="https://git.coding.net/xushaobin/xushaobin_gongneng_4_2.git"
["杨梓瑞"]="https://git.coding.net/Vector121/homework.git" #old
["袁玥"]="https://coding.net/u/yuanyue2017102885/p/wf-part420170926/git"
["翟宇豪"]="https://git.coding.net/Rio56/wf.git" #old
["张恩聚"]="https://git.coding.net/ZhangEJ/wf.git"
["邹双黛"]="https://git.coding.net/szjzsd/123.git" #old
)
for key in ${!map[@]} ; do
mkdir $key
cd $key
git init
git pull ${map[$key]} master
cd ..
done
#echo ${!map[@]}
#
#echo ${map[@]}
#
# for key in ${!map[@]} ; do
# # echo ${map[$key]}
# echo $key;
# done
# 语法学习自 [https://coding.net/u/ZhangEJ/p/wf/git/tree/master/wf11]
1.3 excel
我用excel计算每周的作业成绩。函数lookup和vlookup在作业计算中起了重要作用,用于查 某作品被投票的分数、某同学的团队归属(以便累加团队得分)、某团队的单项作业得分等。
例如,在冉华同学的团队一列中,“王者荣耀交流协会”的取值,来自另一个名为“归属”的工作表。不hardcode有利于alpha阶段后换人。
又如冉华同学的视频展示得分,来自所在团队的“final视频”单项得分,查找自另一工作表“scrum+todolist+burndown”第14列匹配团队名“王者荣耀交流协会”。
除vlookup以外,在统计得票时countif、sum等也常用,match也有用到。
1.4 excel导出成markdown格式
构建之法课程群统一在cnblogs.com上发布成绩,该网站支持markdown格式。幻飞龙博士开发有exceltk[http://www.cnblogs.com/math/p/exceltk.html]可以完成excel导出成markdown格式,大大方便了这一工作。极其方便,强烈推荐,非常感谢。
1.5 仍存在的困难
在算分时常犯错误,被同学们纠正过几次。1.本周成绩没有累积到总成绩,2.修正学生得分时担心错,3.使用错误的sheet,因此排序错误(数据没错)。这些都应可以通过数据检验或交叉检验完成,不过仍未找到可行的方法。
------------------------------------------------------
博客会手工同步到以下地址:
[http://zhuanlan.zhihu.com/younggift]
[https://younggift.net/]
//[http://blog.csdn.net/younggift]
//[http://giftdotyoung.blogspot.com]



