经过前面四篇,我们已经具备了最基本的思考编程的能力。我们开始做一个真正的应用吧。
例题
我们现在做一个应用,该应用是一个命令行应用。当程序启动的时候,我们会看到一个命令行的主界面:
1. 添加学生
2. 生成成绩单
3. 退出
请输入你的选择(1~3):
如果我们输入1,那么界面就会变成:
请输入学生信息(格式:姓名, 学号, 民族, 班级, 学科: 成绩, ...),按回车提交:
如果输入格式不正确,就返回:
请按正确的格式输入(格式:姓名, 学号, 学科: 成绩, ...):
如果输入格式正确就会返回
学生xxx的成绩被添加
然后打印
1. 添加学生
2. 生成成绩单
3. 退出
请输入你的选择(1~3):
等于回到了主界面。
如果我们在主界面输入了2,那么界面就会变成:
请输入要打印的学生的学号(格式: 学号, 学号,...),按回车提交:
如果我们输入的不正确,就会打印:
请按正确的格式输入要打印的学生的学号(格式: 学号, 学号,...),按回车提交:
如果输入的格式正确,则会打印成绩单并回到主界面。
成绩单
姓名|数学|语文|英语|编程|平均分|总分
========================
张三|75|95|80|80|82.5|330
李四|85|80|70|90|81.25|325
========================
全班总分平均数:xxx
全班总分中位数:xxx
如果我们输入的学号不存在,该学号在计算时就会被忽略。
讲解
这个题目比之前的复杂一点,我们可以先按照功能简单列一下任务列表。
#1 打印主菜单
#2 添加学生成绩
#3 生成成绩单
#4 退出
然而这个列表是跟我们的程序不等价的。我们还是应该列出跟程序等价的任务列表。为了便于表达,我们就需要画图。我们先不考虑面向对象,直接面向过程的划分,我们画出来的图大概是下面这个样子:
也许你觉得这个做法并不够好,我也这么觉得,那我们可以重构这个图,画出一种更好的解法:
可以看出,这两种做法,在图形上看并没有明显的区别,但是命名上暴露出了思路的不同,后者明显减少了程序对外输入输出的次数。所以不要随便命名。
但如果没有上面那个图,我们是看不出来buildReport这个函数他打印了还是没打印,这就需要我们有一套约定俗成的用语规范,从用语规范中可以看出来我们到底做了什么。
课后练习
- 针对两张图,分别列出所有的任务。
- 在脑中模拟一下,如果测试先行的方式写代码,两种实现的时间花费各会是多少。按照任务列表逐项估出时间,并比较两种实现的时间差异。
题外话 - 1
对于接触本文章的编程初学者,我需要多说几句:我们可以看到,其实一个真正的应用也是由一些简单函数构成的,那就说明编程思想和技巧并不受限于应用的表象。前端、后端、应用、系统之类的名词,往往是从分工的角度来讲的,如果从个人发展的角度来讲,不要拿这些名词限制自己。这也是我们这个系列只讲一些简单应用的缘故,抽象来讲思路是一样的。
题外话 - 2
到这里,你应该能感觉到我们这些题目,其实是一个个思维训练,对于这个思维训练,最重要的事情有三点:
- 语文问题(用词精确,前后一致)
- 接口问题(完全穷尽)
- 每个函数之间互相不知道对方的内在实现(各自独立)
能做好这三点,代码就能完胜行业里的大多数人:)