您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

软件工程的迷途与沉思

时间:2020-06-08 10:23:53  来源:  作者:

上世纪60年代爆发的软件危机催生了软件工程,人们寄希望于借助工程化的手段管理、设计、构建和维护软件,自此,聪明绝顶的工程师便在追求更美好软件的漫漫长路上艰苦求索。

开发语言经历了汇编、C、C++、JAVA、Erlang、Python;编程范式涵盖了面向过程(POP)、面向对象(OOP)、泛型(GP)、函数式(FP);软件架构从单机到分布式到云原生,包括巨石,库组件模块服务,分层,微服务,
MVC/ServiceMesh/Serverless等;而软件工程思想和方法论则包括以生命周期管理为核心注重工序的瀑布模型(Waterfall Model),以需求进化为核心注重迭代渐进的敏捷开发(Agile Development),以边界划分和控制为核心注重领域建模的领域驱动设计(DDD:Domain Driven Design)。

世界是缤纷复杂的,要把真实世界映射到虚拟软件注定不会是一件容易的事,软件开发是权衡抉择的艺术,譬如快速交付和安全生产常常背道而驰,开发效率和运行效率总是难以一致。所以在软件发展的历史长河中,人们发明一种方法解决一个问题,而几乎总是会引入另一个问题,软件工程师不得不面对混沌不堪的世界。

面向过程(C)认为一切皆过程,现实世界都可以封装为一个个过程,通过过程串联和编排模拟世界。但随着软件被大规模用于解决复杂的商业问题,这种范式被证明缺乏足够的抽象,虽然函数可视为最小粒度的模块化技术,但依然无法掩盖其模块化能力的不足,过程和被操作数据分离也导致软件偏离高内聚低耦合的方向。

为了解决上述问题,面向对象范式(C+++/Java)被设计为通过对象建模世界,对象把属性和方法封装在一起,通过公开接口与外界交互,为软件设计提供一种逻辑层面的模块化手段;而且,对象与现实世界的事物很容易映射。对象通过组合表征更复杂的概念,通过接口泛化表达更抽象的概念。

泛型的动机则更加简单,需要一种语言机制,为解决跨越数据类型而提供标准容器的障碍,C++通过模板这种语言机制提供了参数化类型的能力,编译期的类型检查和类实例化既保障类型安全又提升执行效率,但也增加编译时间和损害可读性,特别是模板元编程等新玩法的引入则让事情更加复杂。

UML诞生于瀑布模型大行其道的时代,是独立于具体程序设计语言的面向对象建模工具,UML把面向对象开发分解为分析(OOA)、设计(OOD)和编码(OOP)三个阶段,该流程注重分析设计而轻视编码实现。

由于设计和实现被划分成2个相互钳制的阶段,所以开发过程会存在两个模型,即一个显化于UML图纸中的设计模型,一个隐匿于软件源码中的实现模型,两个阶段两个模型必然导致设计和编码的割裂,设计和实施交予不同人实施看似有利于分工协作,实则增加了沟通成本,降低了交付效率。

学院派一度追求依照架构师的UML设计图就能自动生成代码,这看起来很美,而实际上这种目标只在受限的情况下才能被满足;而在日益复杂的商业软件开发中,工程派感受到时间更多被消耗在开发和维护上,最终的交付件只能是源码而非图纸,所以开发人员只能转向设计原则(SOLID)和设计模式(GOF)寻求慰藉,设计人员则头顶“架构师”的美名天马行空。

瀑布模型的过程难以逆转,且只有到项目后期才能看到结果,针对瀑布的缺陷,敏捷开发试图从改善软件开发端到端的沟通方式入手,极限编程(XP)是一种实施敏捷开发的轻量级软件工程方法学,尝试用一种螺旋式的方式演进,极限编程正视软件活动的复杂性,承认需求在起步阶段无法固化下来,主张开发人员应该优先将精力投入到代码中,透过引入基本价值、原则、方法等概念来灵活应对需求变更。

敏捷开发在互联网的蓬勃发展中大放异彩,究其根本是因为互联网应用的需求是动态变化的,难以严格遵照沉重的传统瀑布模型流程。

重原型实现的敏捷方法甚至被曲解为完全不需要设计和文档的开发方式,敏捷的优势同时又成为它的弊端,忽视文档的重要性,在人员流动大的情况下无疑会加大维护的困难,且它在面对领域知识复杂的组织和应用时,敏捷开发也饱受质疑。

随着Web Service的应用井喷,以Java为代表的新兴语言攻城拔地,Controller->Service->Dao或者SOA设计摇身变化成行业的标准解,Service层扮演着上帝类,所有的逻辑都往里塞,充斥getter/setter DAO的贫血模式弥漫着恶臭味,基于数据驱动的开发模式陷入了泥潭,领域驱动设计进入了人们的视野。

2003年,Eric Evans提倡的领域驱动设计(DDD)视“领域内核”为企业最重要资产,主张通过通用语言(Ubiquitous Language)消除表达的不准确性,领域驱动设计继承并发展了敏捷开发。DDD把领域和设计归为软件设计的核心,让业务人员和开发人员得到同样的重视,建议合力捕捉充血的领域模型。DDD战略设计从宏观上确定限界上下文,而战术设计在实现层面给出一些最佳实践。

传统模式秉持以数据(库)为中心的理念,而领域驱动设计则转向以领域模型为中心,这是根本性的设计转变。DDD通过四重边界划分问题空间和解空间,确定核心、通用、支撑三类子领域,在界限上下文内部,通过分层(基础层-领域层-应用层-展现层)实现内外隔离,应用层形成了一种保护层,有效地隔离了业务复杂度与技术复杂度。将领域层作为整个系统稳定而内聚的核心,是领域驱动设计的关键特征。

回顾软件工程发展过程中涌现的各种主义,每一个流行的思潮都有一套自圆其说的理论,都声称完美解决了某些问题,但又无一例外的陷入另一个框架陷阱,但又都无一能够终结软件工程的无序设计。我们无法跳出自娱自乐般无休止重构循环的怪圈,我们依然置身于充满各种技术债的困境,所以,跳出各种框架模式的精神枷锁,回过头来,我们不妨重新审视设计的本质,我们不妨想一想应对软件复杂性的根本原则。

可将解决大规模复杂软件问题的方法,简单归为几点:抽象,分解,隔离。

抽象就是归类,归类是为了复用。抽象的意义是通过表现找到事物背后的本质,抽象的目的是为了减轻认知负担,避免重复思考和劳动,精简问题空间,让人关注更高层次的事物,建模是提炼心智模型的过程,本质就是一种抽象。

分解是把一个复杂问题分割为更小的易于解决的小问题,拆分问题的过程即是简化问题的过程,问题分解之后,还需要协作,这其实就是分治的理念,库、组件化、微服务无不闪烁着分治理念的智慧的光芒。拆分有两种方式:技术维度和业务维度,微服务和DDD就是从业务维度做问题拆分。拆分可以遵循AKF原则和康威定律,高内聚低耦合是评价拆分好坏的标准,让上帝的归上帝,让凯撒的归凯撒。

隔离是为了解耦,建立松耦合的系统一直是工程师们孜孜以求的目标,分层是实现隔离的有效手段,每层专注于自己的功能实现,上层使用下层的能力,下层为上层提供服务,上下层之间通过约定的接口交互,不紧邻的层之间完全透明。外部世界的规则是契约、通信以及系统级别的架构风格和模式,而内部世界的规则是分层、协作以及类级别的设计分格和模式。

在软件变革的滚滚洪流中,软件工程的先驱和贤哲们,提出了各种各样的编程思想和方法论,但无一从根本上彻底解决问题,《人月神话》第16章提出,因为软件工程是超级复杂的系统,所以断言没有银弹,不仅没有包治百病的灵药,更指出在未来十年不可能有提升十倍效率的方法。

回顾历史,每一种完美方案都从怼已有的方案和宣称解决所有问题开始,然后传播布道,把大众带入自己精心设计的逻辑闭环,然后追随者以一种宗教般的虔诚,将理论生搬硬套到项目中去,最后交付的代码依然充斥各种模糊不清、污浊不堪,任何演进都可能便引起偶然不变性的瞬间坍塌,剩下一地鸡毛,而那些新颖的理论,最终都会像袅烟一样,飘散在历史的浩瀚天空中。

古人云:人生而无知,却并不愚蠢,是教育使人愚蠢。古人又云:学而不思则怠。所以,我们应该意识到思辨的重要性,对于知识,我们学习它研究它,但不盲从它。那对待软件工程,我们应该秉持怎样的原则呢?

首先,人是关键,软件开发没有终极解,因为软件就是人思想的外化,而人本身充满缺陷。我们必须认可人这种生物在抽象过程中的一些必然缺陷,以及人抽象能力的差异,这将意味着,相比于规则和流程,人其实才是软件实施过程中的灵魂,思想和法则可以给人提供指引,但它们无法神奇的解决软件工程中的所有问题,影响软件开发质量的关键因素是人,而不是设计方法。注重形式而不是内容,注重文档而非交付的代码,都是本末倒置的。

其二,实事求是,具体问题具体分析,软件涵盖的范围实在太广的,这就意味着每一种具体实施细则都有它的局限性,不能用僵化的标准困住手脚,不可拘泥于规则而使之成为教条,不可用倚天剑剪指甲,不要用屠龙刀剃胡子。比如最简单的业务CRUD模型可能就够了,而有些可能适用CQRS、六边形架构,有些贫血领域对象也可以,有些可能事件风暴模式更好,有时候数据和操作应该分离,甚至读写也应该分离,而有时候数据和操作封装在一起更好,脱离实际的牛刀杀鸡只会徒增笑耳。

第三,几乎任何语言和技术都有好坏的两面,都有适用性,比如C,它虽然欠缺抽象能力,但是它的核心语法集非常简单,简单意味着聚焦和可靠,意味着对程序员的要求更低,你只需要掌握几十年不变的少数几十个STD C API便能构建所有应用,但你必须认识到它在抽象能力和开发效率上的不足。而C++虽然有良好的抽象能力,但它的语法集太庞大,而且似乎很难约束大家都在最小的公共知识面行事,但如果能够达成共识,又或者大家水平都比较高,它编写的程序确实有更好的可维护性。

第四,纪律!对,纪律才是关键,一套方法体系不管有多么的完美,如果团队不能严格地执行方法体系规定的纪律,都是空谈。无论是整洁编码还是架构设计还是敏捷开发还是领域建模,只有持之以恒的一致性的遵守纪律,用纪律施加约束,才能持续改进质量。

最后,虽然没有银弹,但我们不应该过于悲观,软件工程一直在迂回中前进,每进一步,就能够解决一大片问题,同时引入一些可控的副作用,但宏观上来看,软件工程还是伴随人类社会在不断进步。

所以,何不尝试接受不完美?



Tags:软件工程   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
软件工程专业有Web开发、移动终端开发、大数据开发、计算机系统工程师、视频开发工程师、计算机软件应用工程师等就业方向。第一,Web开发。Web开发包括前端开发和后端开发。...【详细内容】
2021-10-19  Tags: 软件工程  点击:(80)  评论:(0)  加入收藏
有一种说法,硅谷程序员是不是收入动则就是年入百万呢?事实上,确实是这样,硅谷程序员和我们国内程序员一样,在美国也属于高收入群体,年入百万属于大概率的事件。大概率到一个什么...【详细内容】
2021-08-11  Tags: 软件工程  点击:(388)  评论:(0)  加入收藏
存在任何解决实际人类问题的业务。它可能是提高速度,降低成本,提高便利性,增加生活乐趣或使知识触手可及。通常用于解决这些业务问题的技术。但是,为什么设计模式很重要?IT系统的典型挑战是可用性,可伸缩性,弹性,数据管理,性能...【详细内容】
2021-01-14  Tags: 软件工程  点击:(176)  评论:(0)  加入收藏
推荐这五本书。1、代码整洁之道 本书提出一种观念:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。作为编程领域的佼佼者,本书作...【详细内容】
2020-11-26  Tags: 软件工程  点击:(119)  评论:(0)  加入收藏
谷歌软件工程文化的主要元素之一就是通过设计文档定义软件设计。在开始项目编码工作之前,软件系统或应用程序的作者会创建这些相对非正式的文档。设计文档记录了高级实现策略...【详细内容】
2020-08-26  Tags: 软件工程  点击:(100)  评论:(0)  加入收藏
您刚刚从大学获得计算机科学或软件工程学位,并且正在寻找职业。您还记得自己喜欢单身汉编写代码,并与好友一起做过一些很棒的项目,然后决定要成为一名开发人员。您开始准备工作...【详细内容】
2020-07-21  Tags: 软件工程  点击:(78)  评论:(0)  加入收藏
说明:本篇文章题库来源于网络,目的在于共同学习,共同进步,知识分享可以通过网络平台不断提高自己海康威视嵌入式驱动工程师的题目只包含选择题和简答题,没有编程题。毫无疑问,C语...【详细内容】
2020-06-21  Tags: 软件工程  点击:(687)  评论:(0)  加入收藏
上世纪60年代爆发的软件危机催生了软件工程,人们寄希望于借助工程化的手段管理、设计、构建和维护软件,自此,聪明绝顶的工程师便在追求更美好软件的漫漫长路上艰苦求索。开发语...【详细内容】
2020-06-08  Tags: 软件工程  点击:(42)  评论:(0)  加入收藏
▌简易百科推荐
本文分为三个等级自顶向下地分析了glibc中内存分配与回收的过程。本文不过度关注细节,因此只是分别从arena层次、bin层次、chunk层次进行图解,而不涉及有关指针的具体操作。前...【详细内容】
2021-12-28  linux技术栈    Tags:glibc   点击:(3)  评论:(0)  加入收藏
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(2)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(10)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(20)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(25)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(25)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条