软工+C(2017第7期) 野生程序员

时间:2021-03-12 20:25:43

// 上一篇:最近发展区/脚手架

// 下一篇:提问和回复


怎样做足够好的软件?我们就差一个程序员!

没有什么软件工程的理论的时候,程序员们凭借自己对编程的热爱,凭借着:“这是一个可以自动化的事情,我会写个程序让它自动解决,太酷了!” 的热血,上来就去实现功能,沉浸在创造欲和控制欲被极大满足的过程中。

情景1:

也许只是一个简单的排序算法,只是个冒泡程序,但它能工作!它让你发现了一个神奇的世界,你会接着发现数据结构与算法的世界。你可能会做一些简单的带点算法的事情:

【题目】

已知集合A、B,写一个函数,得到下面三个集合

  1. 在集合A中,不在集合B中的元素
  2. 在集合B中,不在集合A中的元素
  3. 同时在集合A和B中的元素

【要求1】

可使用任何语言,对于集合的具体类型可以任意设定,比如整型数组、泛型、接口类型、文件集合、文件夹集合。

程序员J说,这太简单了,Python轻松搞定:

>>> a = set(range(0, 10))
>>> b = set(range(5, 15))
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
set([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> a-b
set([0, 1, 2, 3, 4])
>>> b-a
set([10, 11, 12, 13, 14])
>>> a.intersection(b)
set([8, 9, 5, 6, 7])

太简单?如果这样呢:

【要求2】

假设两个集合A={ai}、B={bj}的类型信息不一样,必须用一个函数equal(ai,bj)去判断是否「相等」,这个时候该如何实现呢。

程序员W说,我设想的代码没有算法含量,纯暴力枚举:

for each element in a do
for each element in b do
if equal then
remove the element of a
remove the element of b
echo this is intersection
for each element in a do
echo this is unique in a
for each element in b do
echo this is unique in b

程序员L说,我会一些简单的算法分析:

对于一般性的集合AB,如果必须通过某个函数判断ai,bi是否相等,并且ai和bi无法映射到一个公共的X维空间上,那么只能暴力穷举了,O(N^2)的复杂度,因为A集合的每个元素都必须和B集合的大部分元素完成比对才可以获知是否相等。如果可以映射到一个公共的空间上,那么可以在做空间映射时做相应的判断以完成集合交并操作,依然是O(N)的复杂度。

过了一阵,你发现,需要实现一个这样的需求:

【要求3】

有一个区间列表RangeList,里面的元素是一个个左闭右开的区间,例如{[0,1),[5,9),[11,20)},请实现一个Diff算法,传入区间列表pLeft, pRight, 返回这两个区间列表的左差集、交集、右差集:

void Diff(RangeList* pLeft, RangeList* pRight, RangeList* pLeftDifference, RangeList* pIntersection, RangeList* pRightDifference )

然后,你尝试用数组和二叉树分别实现了一次。然后你想,如果我要对比一个代码在修改前后的区别,好像也是对前后代码做Diff,于是你陷入了深深的沉思之中。

情景2

也许只是写了一个自动爬漫画站点上漫画的命令行爬虫,它可以把一个站点上的漫画列表按名字的字母列表从A到Z爬下来,写成Json格式保存在文件里。

过了一阵,你继续实现,可以同时从3个不同的站点上爬下自己想看的漫画,你会发现原来网络上的资源都唾手可得。

甚至你去组队来做GUI,让每个站点的爬虫变成一个插件(可能每个站点一个dll?),把爬下来的数据导入到数据库。

然后,你会去设计界面,重新组织漫画剧集的界面;于是你可能会在内存里构建Comic->Episode->Image的模型去加载Json文件模型。

接着,你觉的GUI不好看,会去寻找一个好的GUI库重新设计和实现交互界面,你可能认识了一位美术功底好的设计师,也可能会认识一位做过产品设计的产品设计师。你们讨论了好几个稿子,这段时间你们都在讨论如何交互,这段时间,你们都叫李UI,张UI。

你还发现手机上需要一个App同步观看,于是你又让队员开发一个Android App。好像IOS也需要一个?找不到人,算了。

为了更方便的搜索漫画,你可能想要用漫画的字母拼音缩写去搜索漫画,于是在内存里建立Tire树结构(啊,算法和数据结构还是需要的啊,虽然消耗了你好久的时间去实现),可是太占内存了,听说有一种叫做后台开发的东西,后台搭建一个mysql数据库,把之前的Json数据导入到mysql里,在后台写一个内存中Tire树,然后对客户端提供一个http服务,接受拼音,返回按序查询的结果。

可是单服务器好像慢慢不够用了,一路狂奔,貌似找到了一个不错的资料,继续?

Learn how to design large-scale systems. Prep for the system design interview..

情景3

也许只是用可视化界面设计器拖了一个简单的GUI程序,看上去很简陋,但是你觉的这样不错,至少感受下了自己写一个GUI程序的感觉。

你可能会去实现一个大家来找不同的GUI程序,设计也简单:

  1. 能显示两张类似图片。
  2. 能监听两张图片上的点击事件。
  3. 如果选中了预定义的找不同区域,就两边高亮,得分!

选个什么开发工具,什么语言来做GUI呢?听说C++做GUI不太方便,你可能会选用C#/Java的GUI工具来做,初步体验了一下。听说桌面GUI如今大不如前了,学了就过时了?可是快速体验一遍也不错。

可是,为什么我做出来的GUI程序都好像不像一个专业的软件。例如,长的不好看?于是,你会去尝试各种控件的美化,「浪费」了大量的时间在做GUI控件的修改上:颜色修改,字体修改,布局修改...;有一天,觉的这些修改都捉襟见肘,总是不令人满意,于是你进一步自己去「研究」,学会了自己绘制GUI界面,处理自己绘制的GUI区域的事件,绘制+交互事件 完成了自己的控件。

你可能会接触到GDI的绘制接口。这些绘制接口是操作系统提供的,它们可能能让你绘制矩形、三角形、圆形。你又会去「浪费」大量时间研究这些系统接口的优缺点,尝试组合这些绘制接口完成自己的一个又一个想法。就像谁谁谁说的,程序员是这个时代的画家,他们涂涂画画实现自己的画家的愿望。有时候,为了画出个花来,又「浪费」了很多时间在搭建各种脚手架上。

系统接口里面到底是做了一些什么事情呢?就像小时候,我们都拆过闹钟一样,闹钟里的零件是怎样组装的呢?额,那些拆了装不回去的印象一一浮现而出。这次,你可能会去「拆」下GDI接口下面,操作系统做了什么?你可能会接触到渲染的概念,于是你可能想,自己来做一个渲染层...,好像,所谓的DirectUI是这么做来着...,怎样自己绘制一个支持10万行数据流畅滚动的List控件?

有一天。你发现有一个叫OPENGL的课程,你可以在一个视图框里绘制3D的正方体、长方体、圆柱、球。太棒了,终于可以绘制一栋房子了,可以绘制一个迷宫了,还可以绘制一只凤凰。想起了什么?对,做一个3D版的找不同,这次,我们可以有丰富的3D模型了。

情景4

[2010/x/x]

xxxxx: 这么早就起来了?

8:45 我: 通宵了 最近非常烦

xxxxx: 不会吧。。在干嘛呢?

: 周一过去,一票需求改变,下午要给

xxxxx: 不是吧。。这么赶。。

8:46 我: 最近2个月这种大改变需求已经有四次了,一次比一次时间紧,他奶奶的,这次是2天完成

[2012/x/x]

yyy: 编码不够严谨啊 请假太多啊什么的,

:嗯,私下说的。

yyy: 所以才问问你作为程序员要怎么成长。。

13:50 我: 追求更好, 周六晚上跟spacenet一起喝酒, 他说我跟他写程序都有个特点

13:51: 就是会不断改进

13:53: 比如我以前学C++,我会去学习STL、学习了STL我会去挖泛型编程、学scheme会去挖lisp的东西,学OOP会去学设计模式;做UI会去做自定义控件、接着做自己的UI框架、接着完全基于绘制去做、再后面做基于xml布局+脚本交互;比如我学一个语言一定会去挖机理。