75

编程到底难在哪里? - 知乎

 6 years ago
source link: https://www.zhihu.com/question/22508677/answer/141334678?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

编程到底难在哪里?

各种语言就好比文字,编程的过程就是用文笔书写诗篇,假设对于语言的应用已经十分透彻了,那么编程的难点在哪里? 在使用的思路,还是各种算法,还是以人脑却用…
26,575
9,329,919
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

我今天要买一斤苹果。

我今天要买一斤苹果。

因为我只喜欢红富士苹果,所以我只买红富士苹果。

我能接受的最高价格是10元/斤。

正常情况下一斤苹果用一个袋子能装下,但是为防万一,我会带两个袋子。

我知道附近的3家水果店,所以我会依次访问这3家水果店。

根据上述条件,我设计出以下的买苹果的流程:

买苹果流程开始
    对水果店0、水果店1、水果店2依次执行:
    拜访一家水果店流程开始
        走到此水果店
        如果此水果店没有开门,则结束当前的“拜访一家水果店流程”
        如果此水果店没有苹果,则结束当前的“拜访一家水果店流程”
        如果此水果店的苹果当中没有红富士苹果,则结束当前的“拜访一家水果店流程”
        如果此水果店的红富士苹果剩余不到一斤,则结束当前的“拜访一家水果店流程”
        如果此水果店的红富士苹果的价格高于10元/斤,则执行3次:
        讲价流程开始
            询问店主是否愿意将价格降到10元/斤或更低
            如果店主愿意,则跳过剩余的“讲价流程”
        讲价流程结束
        如果此水果店的红富士苹果的价格仍然高于10元/斤,则结束当前的“拜访一家水果店流程”
        打开一个袋子,将其作为当前的袋子
        重复执行以下流程,直到总重量大于一斤:
        装袋一个苹果流程开始
            从所有的不在袋子中的红富士苹果中选出最好的一个
            如果此苹果能装入当前的袋子,则将此苹果装入当前的袋子,否则执行:
            换袋子流程开始
                如果我有剩余的袋子,则从中任意选出一个并作为当前的袋子,否则执行:
                向店主要袋子流程开始
                    向店主索要一个袋子
                    如果店主拒绝给我袋子,则将我的所有袋子里的所有苹果取出,然后结束当前的“拜访一家水果店流程”
                    将店主给我的袋子作为当前的袋子
                向店主要袋子流程结束
            换袋子流程结束
            测量我的所有袋子里的所有苹果的总重量
        装袋一个苹果流程结束
        根据我的所有袋子里的所有苹果的总重量和店主给出的价格,计算我应付的价格
        向店主询问我应付的价格
        如果我不接受店主索要的价格,则执行3次:
        校对流程开始
            向店主解释我计算出的价格,并询问其是否同意
            如果店主同意,则跳过剩余的“校对流程”
        校对流程结束
        如果我仍然不接受店主索要的价格,则将我的所有袋子里的所有苹果取出,然后结束当前的“拜访一家水果店流程”
        如果我没带钱,则将我的所有袋子里的所有苹果取出,然后结束当前的“拜访一家水果店流程”
        付钱拿走苹果
        跳过剩余的“拜访一家水果店流程”
    拜访一家水果店流程结束
买苹果流程结束

这个流程怎么样?我来设计一些测试样例,测试一下这个流程。

测试发现一个问题:如果水果店0和水果店1都有红富士苹果并且价格都低于10元/斤,而且水果店1的价格比水果店0更低,那么我希望买水果店1的苹果,但我设计的流程会让我买水果店0的苹果。

为了解决这个问题,我应该先询问所有水果店的价格,然后去价格最低的那一家买苹果。

经过修改,我重新设计出以下的买苹果的流程:

买苹果流程开始
    对水果店0、水果店1、水果店2依次执行:
    询问一家水果店的红富士价格流程开始
        走到此水果店
        如果此水果店没有开门,则视此水果店的红富士价格为无穷大元/斤,并结束当前的“询问一家水果店的红富士价格流程”
        如果此水果店没有苹果,则视此水果店的红富士价格为无穷大元/斤,并结束当前的“询问一家水果店的红富士价格流程”
        如果此水果店的苹果当中没有红富士苹果,则视此水果店的红富士价格为无穷大元/斤,并结束当前的“询问一家水果店的红富士价格流程”
        如果此水果店的红富士苹果剩余不到一斤,则视此水果店的红富士价格为无穷大元/斤,并结束当前的“询问一家水果店的红富士价格流程”
        向店主询问此水果店的红富士苹果价格并记录
    询问一家水果店的红富士价格流程结束
    从3家水果店中选出红富士价格最低的一家(如果有并列则随机选择),将其作为目标水果店
    如果目标水果店的红富士苹果价格为无穷大元/斤,则结束当前的“买苹果流程”
    走到目标水果店
    如果此水果店的红富士苹果的价格高于10元/斤,则执行3次:
    讲价流程开始
        询问店主是否愿意将价格降到10元/斤或更低
        如果店主愿意,则跳过剩余的“讲价流程”
    讲价流程结束
    如果此水果店的红富士苹果的价格仍然高于10元/斤,则结束当前的“买苹果流程”
    打开一个袋子,将其作为当前的袋子
    重复执行以下流程,直到总重量大于一斤:
    装袋一个苹果流程开始
        从所有的不在袋子中的红富士苹果中选出最好的一个
        如果此苹果能装入当前的袋子,则将此苹果装入当前的袋子,否则执行:
        换袋子流程开始
            如果我有剩余的袋子,则从中任意选出一个并作为当前的袋子,否则执行:
            向店主要袋子流程开始
                向店主索要一个袋子
                如果店主拒绝给我袋子,则将我的所有袋子里的所有苹果取出,然后结束当前的“买苹果流程”
                将店主给我的袋子作为当前的袋子
            向店主要袋子流程结束
        换袋子流程结束
        测量我的所有袋子里的所有苹果的总重量
    装袋一个苹果流程结束
    根据我的所有袋子里的所有苹果的总重量和店主给出的价格,计算我应付的价格
    向店主询问我应付的价格
    如果我不接受店主索要的价格,则执行3次:
    校对流程开始
        向店主解释我计算出的价格,并询问其是否同意
        如果店主同意,则跳过剩余的“校对流程”
    校对流程结束
    如果我仍然不接受店主索要的价格,则将我的所有袋子里的所有苹果取出,然后结束当前的“买苹果流程”
    如果我没带钱,则将我的所有袋子里的所有苹果取出,然后结束当前的“买苹果流程”
    付钱拿走苹果
买苹果流程结束

现在这个流程是不是完美了呢?不是,我还能发现很多问题。
如果3家水果店都有红富士苹果但都不到一斤,但是三家店加起来能达到一斤,那么我不应该结束流程回家,而是应该把三家店的红富士苹果都买下来。
如果我向水果店询问价格的时候这家店还有红富士苹果,但我询问完所有水果店的价格后这家店的红富士苹果卖完了,那么我的流程会让我试图处理不存在的红富士苹果。
我走路的过程中可能会遇到突发事件,比如发现了新的水果店,比如袋子破掉了苹果掉一地,对于这些情况我的流程都无法进行处理。

啊问题太多了我懒得再改流程了。我还是去X宝买吧。
那么接下来我要设计一个在X宝买红富士苹果的流程……

==========================================================

这篇沉寂了5天只得到1个赞的回答竟然一夜之间收获2000+赞,一举成为个人最多赞的回答。感谢大家的支持,以及精彩的评论。

这篇回答并不是讲述在生活中程序员如何买苹果,而是以买苹果为例说明程序员如何解决问题。程序员需要对问题进行透彻的分析,理清其涉及的所有细节,预测可能发生的所有意外与非意外的情况,列出解决方案的所有步骤,以及对解决方案进行尽量全面的测试。

而这些正是我认为编程难的地方。任何一点遗漏都会成为bug,轻则导致挨骂,重则导致经济损失甚至危害安全。

注意这些难点全部和语言无关。和编程所需要的绝对严密的逻辑相比,语言实在是太简单了。(某些自带代码混淆效果的语言除外)

==========================================================

我勒个去4000+赞了!妈妈!我火了!

好多评论说这代码像python。然而我根本不会讲python。

==========================================================

本回答可以随意转载,只需附带原文链接即可。

==========================================================

好不容易写了篇高赞回答,不打个广告是不是有点浪费?

求偶。本人男,爱好女,27(划掉)28岁,Google员工,现居湾区。要求对方同样现居湾区并有稳定身份(不符合者抱歉勿扰)。有意者请私信。(注:已失效

更新(5/30/2021):

这篇4年前的老回答竟然又火了一波,我已经不理解互联网是如何运作的了。

上述广告仍然有效。我是一名会及时更新文档的程序员,如果哪天脱团了会回来更新这条广告的。湾区是指美国加州的湾区;稳定身份是指可以在美国长期生活(例如持有绿卡或者在申请绿卡)。

广告是2020年加上的,所以并不是说我4年一来一直单身,不过现在确实是。

==========================================================

更新(2/15/2022):

上述广告已失效!我脱单了!

加一套免费推广:Coffee Meets Bagel,为寻找serious relationship的人而设计的约会平台。

这回答隔了数年被

小姐姐点赞之后又引来了大量看热闹的观众和评论; (相比之下费劲精力写的专栏技术文章基本没人看真是惨)

想在这里统一回复一个关于认为做“最新东西”写的乱点没问题,反正最后会重构的问题;

这个理论对么?当然对,但是有一个前提,就是做的东西简单, 更确切的讲, 好测, 能很容易验证基本逻辑或者系统的normal path;

对于不好测,且出一个bug就影响重大, 可能会导致黄掉整个项目,那么程序复杂度就不能过于给系统添麻烦,程序复杂度和业务复杂度不成基本线性关系,说明这个程序员写程序没有scalability,做点简单东西还行,做复杂东西就原地爆炸;

程序员产出的code能不能在复杂度这个维度上scale,是我想指出的东西;

————————原文分割线————————

记得之前组里来了一个美国实习生小伙子,很geek的那种,干活快,一天能给你写2000行代码(我code review的速度跟不上他写的速度),让做什么东西,上午告诉做个这个功能,下午就能在测试环境跑起来演示了。跟他单独开会的时候,他说觉的普通的编程没什么意思,太简单了,写程序这方面已经没什么追求了,他比较想跟我研究大数据的框架,数据库,或者机器学习之类的工作,做设计,早日脱离代码这种无脑工作。

我足足花了1周时间,每天review他的代码到凌晨。给他写的comments反馈快赶上我在知乎写的答案文章之和了。。。期间几小时几小时的开会论战,孩子狂,语速快,脑力灵,辩论角度刁钻。他天天要与我论战,看我的评语,速度还算慢下来了。

没来得及讨论完,隔周我要休假了,2周。交代了些他要做的工作。

2周回来,让他改的那个java包爆炸了,本来我们一个支持了7个功能的框架包,总代码量也就5k把,等我回来这包代码量1w5+。也就是说他为了一个小功能加了1w行代码。

这没法review,只能跟他坐一块,先让他给我讲讲这代码都干什么的,然后他说:

(沉思+100)这块我现在也看不太懂当时为什么这么写了。。。

(沉思)这边写的比较复杂是因为当初那边是那样写的,所以这边没办法才只能这么写。

(沉思)把当初那边改好很麻烦,影响也很大,不如就这样吧。

(沉思)这里这么写是因为你看着里是这样的, 然后这里有这个逻辑,然后这里。。。(来回来去翻n个类之后)。。。 所以你看我这里虽然写的比较诡异,但是完全没问题的!(得意ing)

(沉思)这边做的这么奇怪是因为有个bug,通过这么写,这个就bug没了,我也不知道怎么回事。。。所以你看我在这边注释,这行不能删了。。。

(沉思)我觉得这个功能很酷,你们虽然现在不需要,不过有总比没有好吧,将来如果……%¥……&%&……%*7&%……*%…(我没听懂)的话,这个就很有用!!

...

一次一次被我打回去重写,后来总算简化成大概5k行了;临走时候跟我说:你这样编程也太难了。。。

再后来由于一些额外复杂的代码造成我们实现新东西会很复杂,我又重写了一遍,总共大概不到1k行代码。

这里边有几件事情我想说:

  1. 做出来容易, 做正确难,这里做出来指没bug且完成需要的功能,这是最基本要求,不多加讨论。这里正确,不是指功能正确,而是指程序可以很容易推理理解,理解意图, 理解如何做到的,理解为什么系统不会出错。理解为什么要这么做。正确是现在怎么写不会挖坑害将来的人,现在怎么写能让别人1年后看你代码时候不可能理解错你现在的意图,现在怎么写能在别人将来犯错的时候提示他你错了。
  2. 编程是给未来的未知人讲故事,你无法知道将来这个人是谁,他都懂什么,他经历过什么,这个系统将来已经是什么样子了。我们需要在这种无知,缺乏信息的情况下做决定,从千万种把这件事做出来的方法里,选出你觉得最能把这个故事给讲好的那种方式,把故事写下来。编程是一种沟通,沟通是一种艺术,用程序跨越时空之沟通则是一门属于程序员的特有的艺术(就好比数学家用数学公式来沟通) coding is all about the art of communication(引用)。
  3. 坏的决定会导致坏的决定,甚至导致人们去扭曲一个好的决定去迎合坏的决定。垃圾会制造垃圾,一个放在系统里不经清理的额外复杂度,会导致更多的额外复杂度的生成。
  4. 每个人甚至同一个人的不同时刻都有自己的不同的制造额外复杂度的缺陷,比如我每年去看去年自己写的代码,觉得都是垃圾。

然后我又想问几个问题:

我们所在的部门,所在的组,公司,它们的文化,到底是关心作出了一个东西,还是关心做好了一个东西。一个总是给系统添加垃圾,留坑给后人,但是能很快做出能跑起来的系统的程序员,我们到底认为他是做了好事还是做了坏事?我们到底认为他很强,还是他很弱?用超过必要而为了突显技术实力(或者练手)的复杂工具,技术框架搭建系统,做完跑路,在一个组,一个部门,一个公司,那里的文化,到底应该是鼓励还是抑制这种行为?我们又应该如何在一个环境中,去倡导推崇什么样的文化,相遇什么样的人?

人与文化,决定了什么人留在这里,什么人离开,什么人吸引什么人,什么人成长成什么样子。而设计/技术这些枝末细节则必顺应此中的人与文化而自然变化,或自愈,或走向毁灭;哪怕在恶劣的环境中,向下引导,向上规谏,潜移默化,最终改天换日,此为编程之大道也!

下边是定理证明(雾) ( ̄∇ ̄)

最小垃圾存在定律:定义垃圾为系统的总复杂度减去系统的本质复杂度;那么得到:如存在多种方法可以设计与实现一个系统或功能,存在且只存在一种实现会引入最少的垃圾;

垃圾与复杂度正比定律:根据定义可得,系统存在的垃圾越多,系统越复杂;

垃圾倍增定律:基于已有垃圾量a的现状来演化,进化此系统,增加的新垃圾量与已有垃圾量a成正比;

系统腐败定律:当基于垃圾量a来实现新功能的cost大于新功能本身的价值时,系统腐败,需要重构;

战斗人员负战力定律:如果程序员a引入的垃圾,在n次迭代中经过倍增所造成的成本,大于其所清扫的垃圾经过倍增所获得的机会成本,和其实现的新功能价值之和。此时,我们称此程序员战力为负值,其战力绝对值与其引入垃圾的能力和其清扫垃圾的能力的差值成正比

以一敌百存在定律:由负战力定律可知,对所有的自然数n,一个正战力的战斗人员的战力 > (负战力战斗员1+负战力战斗员2+ … 负战力战斗员n)的战力和

系统本质复杂度不可知定律系统表征复杂度无限接近本质定律:取决于战斗人员的知识量,经验,天赋等,对于任何战斗人员n,都必定存在一个战斗人员m(考虑历史长河)使得战斗人员n观察系中的纯净无垃圾系统(复杂度总为1)是战斗人员m观察系中的含垃圾系统(复杂度为1+x),这使得在所有观察系中(包含外星生物),系统的表征复杂度(或者说观察复杂度)无限趋近与本质复杂度。然而我们只能通过观察来感知事物的本质复杂度,却永远无法得知我们离本质复杂度还有多远。(感谢评论区

提出表征复杂度这个概念来纠正此定律)

以有限的生命去追求可以无限的提升的净化方法与视野,我们称之程序艺术家,也就是SDA(Software Development Artist)

… it's extraordinarily important that we in computer science keep fun in computing…

——— Alan J. Perlis (April 1, 1922-February 7, 1990) 《SICP》

打星际… 哦,不, 错了重来… 写程序,你快乐嘛?

写在最后,看到大家最关心的是他拿到正式录取资格了么?还有也许通过我的描述关于他的这个侧面,你会觉得他很不称职。其实不是的,他代码写的绝对是平均值往上的水平,他的问题在于:

  1. 是他根本没有想过去简化业务逻辑,所以很多符合最初需求的代码在简单优化业务逻辑之后完全不需要,
  2. 是自己加了很多功能,
  3. 是自己加了很多自以为是的优化,比如用一个算法估算某个函数的输入数组的最大可能值,然后用那个值来初始化一个数组,因为这样就不会重新分配内存了(他原话)。
  4. 抽象能力有限,这个毕竟经验少, 年轻。
  5. 滥用设计模式(关于设计模式,最多程序员被绊住的一关:设计模式是面向对象编程模型中,应对经典问题的经典解决方案。这里就有两个问题,第一,设计模式的场景用对了么第二,为什么要用面向对象范式,选择编程语言范式时,要从表达力最弱最简单的语言范式开始选择。这叫做最弱表达力原则,而面向对象范式作为最复杂,表达力最强的语言范式,在大多数时候都可以避免使用。关于第二点的论述证明,你可以看concept techniques and models of computer programming这本书。注意,这里说的是语言范式,而不是语言。即使你用java,如果你从来不使用mutable(专业词汇)的功能,和继承。那么你就没有使用面向对象范式)

他其实有非常强的解决问题的能力,想法天马行空,通过自己设计算法来猜函数可能需要的数组大小就可见一斑,还有一个从s3(专业词汇)读数据的需求,他不是简单调api完了,而是写了一个环状buffer(专业词汇),使得网络,硬盘,app可以在理论上最大效率的适应程序当时的场景(为了协调异步,他自己发明了一个很笨拙的promise(专业词汇)),这非常厉害,一般的实习生哪怕sde1可能都写不出来(可惜的是场景会随业务逻辑激烈变化,今天的优化可以是明日的累赘,这就叫做过度优化,过度优化是一种强耦合,会把你的系统死死的钉死在当前版本)。他只是不明白简单是美这件事情而已。如果能有人帮他斧正,日后必成大器。

他最终拿到了正式录取资格,这其中还有个小波折,终审的bar raiser(amazon内部的一个可以一票否决招聘结果的角色)看到他在代码复查系统里跟我的各种激辩,觉得这人不能留。好说歹说才给了正式录取资格。不过最后人家没接,去读博啦。

最最后:在一个相对干净的环境写程序,不断找出新的本来以为不是垃圾的垃圾,对我来说,是一件非常愉快的事情。然而帮别人打扫他本就不该制造的垃圾则是非常痛苦的一件事。

写程序,本应是多么快乐的一件事啊!

====== 小尾巴 =====

用谁都能看懂的方法解释分布式系统

一个书魔程序员的读书简评

编程到底难在哪里?www.zhihu.com

在做程序员的道路上,你掌握了什么概念或技术使你感觉自我提升突飞猛进?www.zhihu.com

请问分布式事务一致性与raft或paxos协议解决的一致性问题是同一回事吗?www.zhihu.com

翰者学堂,https://www.hanzhe.com

关于这个问题,这个人已经回答的很好了:

v2-802d17b02a415ede10494ee00edaeb52_720w.webp?source=1940ef5c

他在1986年的一次茶话会上发了一篇受邀论文(论文的开头就是“谢邀”),题目就是《没有银弹-软件工程中的根本和次要问题》。 这个人就是IBM大型机之父,Frederick Brooks. 整个论文不太长,有兴趣的同学可以找来读读。在他的经典书《人月神话》中也有收录。 在30多年后的今天,我们在知乎上讨论这个问题,他却早就回答了。他的答案,至今看来,都没有一丝一毫需要修改的地方,毫无瑕疵。

布鲁克斯把软件开发中的困难分为两类: essence,可以译为本质困难或者主要问题,指的是软件开发中不可规避的问题,就是软件本身在概念建构上存先天的困难,也就是如何从问题领域,发展出具体的解决方案。 Accident,可以译为次要因素或次要问题,指的是把解决方案实施到电脑上,所遇到的困难。

他认为软件开发中无法规避的四个特性是: 复杂度; 一致性; 可变性; 不可见性。

他还归纳了在次要问题上我们取得的进步: 高级语言; 分时系统; 统一开发环境。

次要问题我们就不展开了,相信大家都可以理解。 下面所有就都是摘录了,分别描述了4个主要问题。

复杂度。 规模上,软件实体可能比任何由人类创造的其他实体要复杂,因为没有任何两个软件部分是相同的(至少是在语句的级别)。如果有相同的情况,我们会把它们合并成供调用的子函数。在这个方面,软件系统与计算机、建筑或者汽车大不相同,后者往往存在着大量重复的部分。 数字计算机本身就比人类建造的大多数东西复杂。计算机拥有大量的状态,这使得构思、描述和测试都非常困难。软件系统的状态又比计算机系统状态多若干个数量级。 同样,软件实体的扩展也不仅仅是相同元素重复添加,而必须是不同元素实体的添加。大多数情况下,这些元素以非线性递增的方式交互,因此整个软件的复杂度以更大的非线性级数增长。 软件的复杂度是必要属性,不是次要因素。因此,抽掉复杂度的软件实体描述常常也去掉了一些本质属性。数学和物理学在过去三个世纪取得了巨大的进步,数学家和物理学家们建立模型以简化复杂的现象,从模型中抽取出各种特性,并通过试验来验证这些特性。这些方法之所以可行——是因为模型中忽略的复杂度不是被研究现象的必要属性。当复杂度是本质特性时,这些方法就行不通了。 上述软件特有的复杂度问题造成了很多经典的软件产品开发问题。由于复杂度,团队成员之间的沟通非常困难,导致了产品瑕疵、成本超支和进度延迟;由于复杂度,列举和理解所有可能的状态十分困难,影响了产品的可靠性;由于函数的复杂度,函数调用变得困难,导致程序难以使用;由于结构性复杂度,程序难以在不产生副作用的情况下用新函数扩充;由于结构性复杂度,造成很多安全机制状态上的不可见性。 复杂度不仅仅导致技术上的困难,还引发了很多管理上的问题。它使全面理解问题变得困难,从而妨碍了概念上的完整性;它使所有离散出口难以寻找和控制;它引起了大量学习和理解上的负担,使开发慢慢演变成了一场灾难。

一致性。

并不是只有软件工程师才面对复杂问题。物理学家甚至在非常“基础”的级别上,面对异常复杂的事物。不过,物理学家坚信必定存在着某种通用原理,或者在夸克中,或者在统一场论中。爱因斯坦曾不断地重申自然界一定存在着简化的解释,因为上帝不是专横武断或反复无常的。 软件工程师却无法从类似的信念中获得安慰,他必须控制的很多复杂度是随心所欲、毫无规则可言的,来自若干必须遵循的人为惯例和系统。它们随接口的不同而改变,随时间的推移而变化,而且,这些变化不是必需的,仅仅由于它们是不同的人——而非上帝——设计的结果。 某些情况下,因为是开发最新的软件,所以它必须遵循各种接口。另一些情况下,软件的开发目标就是兼容性。在上述的所有情况中,很多复杂性来自保持与其他接口的一致,对软件的任何再设计,都无法简化这些复杂特性。

可变性。

软件实体经常会遭受到持续的变更压力。当然,建筑、汽车、计算机也是如此。不过,工业制造的产品在出厂之后不会经常地发生修改,它们会被后续模型所取代,或者必要更改会被整合到具有相同基本设计的后续产品系列。汽车的更改十分罕见,计算机的现场调整时有发生。然而,它们和软件的现场修改比起来,都要少很多。 其中部分的原因是因为系统中的软件包含了很多功能,而功能是最容易感受变更压力的部分。另外的原因是因为软件可以很容易地进行修改——它是纯粹思维活动的产物,可以无限扩展。日常生活中,建筑有可能发生变化,但众所周知,建筑修改的成本很高,从而打消了那些想提出修改的人的念头。 所有成功的软件都会发生变更。现实工作中,经常发生两种情况。当人们发现软件很有用时,会在原有应用范围的边界,或者在超越边界的情况下使用软件。功能扩展的压力主要来自那些喜欢基本功能,又对软件提出了很多新用法的用户们。 其次,软件一定是在某种计算机硬件平台上开发,成功软件的生命期通常比当初的计算机硬件平台要长。即使不是更换计算机,则有可能是换新型号的磁盘、显示器或者打印机。软件必须与各种新生事物保持一致。 简言之,软件产品扎根于文化的母体中,如各种应用、用户、自然及社会规律、计算机硬件等等。后者持续不断地变化着,这些变化无情地强迫着软件随之变化。

不可见性。

软件是不可见的和无法可视化的。例如,几何抽象是强大的工具。建筑平面图能帮助建筑师和客户一起评估空间布局、进出的运输流量和各个角度的视觉效果。这样,矛盾变得突出,忽略的地方变得明显。同样,机械制图、化学分子模型尽管是抽象模型,但都起了相同的作用。总之,都可以通过几何抽象来捕获物理存在的几何特性。 软件的客观存在不具有空间的形体特征。因此,没有已有的表达方式,就像陆地海洋有地图、硅片有膜片图、计算机有电路图一样。当我们试图用图形来描述软件结构时,我们发现它不仅仅包含一个,而是很多相互关联、重叠在一起的图形。这些图形可能描绘控制流程、数据流、依赖关系、时间序列、名字空间的相互关系等等。它们通常不是有较少层次的扁平结构。实际上,在上述结构上建立概念控制的一种方法是强制将关联分割,直到可以层次化一个或多个图形2。 除去软件结构上的限制和简化方面的进展,软件仍然保持着无法可视化的固有特性,从而剥夺了一些具有强大功能的概念工具的构造思路。这种缺憾不仅限制了个人的设计过程,也严重地阻碍了相互之间的交流。

我的公众号dingshukai666,教编程,欢迎关注~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK