首页 » 脚本文章 » 我们能做点什么?(软件特性做点什么复杂度是必然)「我们可以做些什么翻译」

我们能做点什么?(软件特性做点什么复杂度是必然)「我们可以做些什么翻译」

南宫静远 2024-07-24 05:03:16 脚本文章 0

扫一扫用手机浏览

文章目录 [+]

Grady Booch 《Object-Oriented Analysis and Design with Applications》

作为程序员,当别人问我们软件复杂吗,我们能说点什么?

Grady Booch 在《Object-Oriented Analysis and Design with Applications》中提出这样一个观念:他认为软件的复杂性是固有的,包括问题域的复杂性、管理开发过程的困难性、通过软件可能实现的灵活性与刻画离散系统行为的问题,这 4 个方面来分析了软件的发展一定伴随着复杂,这是软件工程这本科学所必然伴随的一个特性。

我们能做点什么?(软件特性做点什么复杂度是必然) 我们能做点什么?(软件特性做点什么复杂度是必然) 脚本文章
(图片来自网络侵删)

Brooks认为:一个相互牵制关联的概念结构,是软件实体必不可少的部分,它包括:数据集合、 数据条目之间的关系、 算法、 功能调用等等。
这些要素本身是抽象的, 体现在相同的概念构架中,可以存在不同的表现形式。
尽管如此,它仍然是内容丰富和高度精确的。

软件开发中困难的部分是规格化、设计和测试这些概念上的结构,而不是对概念进行表达和对实现逼真程度进行验证。
当然, 我们还是会犯一些语法错误, 但是和绝大多数系统中的概念错误相比,它们是微不足道的。
如果这是事实,那么软件开发总是非常困难的。
天生就没有银弹。

我们能做点什么?(软件特性做点什么复杂度是必然) 我们能做点什么?(软件特性做点什么复杂度是必然) 脚本文章
(图片来自网络侵删)
软件开发,理解四大内在特性

软件内在特性之复杂性: 软件要解决的问题,通常是一种人为、抽象化的智能活动,没有哪两个软件是一模一样的,复杂是软件的根本特性。

规模上,软件实体可能比任何由人类创造的其他实体要复杂,因为没有任何两个软件部分是相同的(至少是在语句的级别)。
如果有相同的情况, 我们会把它们合并成供调用的子函数。
在这个方面, 软件系统与计算机、 建筑或者汽车大不相同, 后者往往存在着大量重复的部分。

软件系统构建与计算机之上,系统状态非常多。
数字计算机本身就比人类建造的大多数东西复杂,计算机拥有大量的状态,这使得构思、描述和测试都非常困难。
软件系统的状态又比计算机系统状态多若干个数量级。

软件的扩展导致导致复杂度非线性增长,因为软件实体的扩展也不仅仅是相同元素重复添加, 而必须是不同元素实体的添加。
大多数情况下, 这些元素以非线性递增的方式交互, 因此整个软件的复杂度以更大的非线性级数增长。

数学和物理学中用于解决复杂问题的抽象建模方法在软件工程缺行不通了,原因是软件的复杂度是必要属性,不是次要因素。
因此,抽掉复杂度的软件实体描述常常也去掉了一些本质属性。
数学和物理学在过去三个世纪取得了巨大的进步, 数学家和物理学家们建立模型以简化复杂的现象, 从模型中抽取出各种特性, 并通过试验来验证这些特性。
这些方法之所以可行——是因为模型中忽略的复杂度不是被研究现象的必要属性。
当复杂度是本质特性时,这些方法就行不通了

复杂度不仅仅导致技术上的困难,还引发了很多管理上的问题。
它使全面理解问题变得困难, 从而妨碍了概念上的完整性; 它使所有离散出口难以寻找和控制; 它引起了大量学习和理解上的负担,使开发慢慢演变成了一场灾难。

软件内在特性之一致性:大型软件开发中,界面、接口常常会不一致,并且随着时间和环境的推移会变得越来越不一致,要维持这样的一致性通常十分困难。

物理学家坚信必定存在着某种通用原理, 或者在夸克中,或者在统一场论中。
爱因斯坦曾不断地重申自然界一定存在着简化的解释, 因为上帝不是专横武断或反复无常的。
但,软件工程师却无法从类似的信念中获得安慰,他必须控制的很多复杂度是随心所欲、毫无规则可言的, 来自若干必须遵循的人为惯例和系统。
它们随接口的不同而改变, 随时间的推移而变化, 而且, 这些变化不是必需的, 仅仅由于它们是不同的人——而非上帝设计的结果。

软件内在特性之可变性:软件构成的因素随时都在变化。
软件实体经常会遭受到持续的变更压力。
当然,建筑、汽车、计算机也是如此。
不过, 工业制造的产品在出厂之后不会经常地发生修改, 它们会被后续模型所取代, 或者必要更改会被整合到具有相同基本设计的后续产品系列。
汽车的更改十分罕见, 计算机的现场调整时有发生。
然而,它们和软件的现场修改比起来,都要少很多。

这一方面是因为软件可以很容易地进行修改,它是纯粹思维活动的产物,可以无限的扩展。
日常生活中, 建筑有可能发生变化, 但众所周知, 建筑修改的成本很高, 从而打消了那些想提出修改的人的念头。
另外的原因是因为系统中的软件包含了很多功能,而功能是最容易感受变更压力的部分。

所有成功的软件都会发生变更。
现实工作中,经常发生两种情况。

当人们发现软件很有用时, 会在原有应用范围的边界, 或者在超越边界的情况下使用软件。
功能扩展的压力主要来自那些喜欢基本功能,又对软件提出了很多新用法的用户们。

其次,软件一定是在某种计算机硬件平台上开发,成功软件的生命期通常比当初的计算机硬件平台要长。
即使不是更换计算机, 则有可能是换新型号的磁盘、 显示器或者打印机。
软件必须与各种新生事物保持一致。

简言之,软件产品扎根于文化的母体中,如各种应用、用户、自然及社会规律、计算机硬件等等。
后者持续不断地变化着,这些变化无情地强迫着软件随之变化。

软件内在特性之不可见性: 尚未完成的软件是看不见的,即使利用图表说明,也常无法充分呈现其结构,使得人们在沟通上面临极大的困难。

软件是不可见的和无法可视化的。
例如,几何抽象是强大的工具。
建筑平面图能帮助建筑师和客户一起评估空间布局、 进出的运输流量和各个角度的视觉效果。
这样,矛盾变得突出, 忽略的地方变得明显。
同样, 机械制图、 化学分子模型尽管是抽象模型, 但都起了相同的作用。
总之,都可以通过几何抽象来捕获物理存在的几何特性。

软件的客观存在不具有空间的形体特征。
因此,没有已有的表达方式,就像陆地海洋有地图、 硅片有膜片图、 计算机有电路图一样。
当我们试图用图形来描述软件结构时, 我们发现它不仅仅包含一个, 而是很多相互关联、 重叠在一起的图形。
这些图形可能描绘控制流程、 数据流、 依赖关系、 时间序列、 名字空间的相互关系等等。
它们通常不是有较少层次的扁平结构。
实际上, 在上述结构上建立概念控制的一种方法是强制将关联分割, 直到可以层次化一个或多个图形。

除去软件结构上的限制和简化方面的进展,软件仍然保持着无法可视化的固有特性,从而剥夺了一些具有强大功能的概念工具的构造思路。
这种缺憾不仅限制了个人的设计过程,也严重地阻碍了相互之间的交流。

一点务虚,思考框架顶层之道

软件开发是偏纯粹思维活动的产物,要想很好的理解,控制和优化,只能用改变思维从源头进行做起。

应对任何大规模复杂的问题的解法,简单归为几点:抽象,分解,隔离。

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

抽象牛只有几根线条,不过这几根线条是做了高度抽象之后的线条,过滤了水牛的绝大部分细节,保留了牛最本质特征,比如牛角,牛头,牛鞭、牛尾巴等等。

这种对细节的舍弃使得“抽象牛”具有更好的泛化(Generalization)能力。
可以说,抽象更接近问题的本质。
也就是说所有的牛都逃不过这几根线条。

思考下面向对象编程本质是什么?很多人会不假思索说,通过“封装”、“继承”、“多态”三个特性的有机组合实现对真实世界的建模,真是这样吗,C语言大家都一致认为他是面向过程的对吧,用C语言的面向过程和面向对比?

通过封装特性,我们把一组相关联的数据+函数打包起来,封装成一个整体,使圈外的代码只能看见函数,数据则完全不可见,比如实际应用中的类中的公共函数和私有成员变量就是这样。
但是这个特性并不是面向对象所特有的,比如C语言也支持完整的封装,来看看一个C语言的常见例子,都文件和实现完全分离的两个文件

进一步看c++,java和c#,他们则彻底抛弃了头文件与实现的分离的的编程方式,这其实是进一步削弱了封装性,因为在这些语言中我们是无法区分一个类的定义和声明的。

再来看继承,继承的主要作用是让我们可以在某个作用域内对外部定义的某一组变量与函数进行覆盖,这也在C语言时代也用的非常多,在C语言结构体中,字段顺序相同的是可以被隐式覆盖的,达到继承的目的

再来看多态,C语言中函数指针本身就是面向对象语言中多态的基础,面向对象只是让多态使用变得更容易了而已。

面向对象编程编程本质是什么?业界在这个问题上存在着很多不同的说法和意见。
然而对一个软件架构师来说,其含义应该是非常明确的:面向对象编程就是以多态为手段来对源代码中的依赖关系进行控制的能力,这种能力让软件架构师可以构建出某种插件式架构,让高层策略性组件与底层实现性组件相分离,底层组件可以被编译成插件,实现独立于高层组件的开发和部署。

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

隔离,即分离关注点,是为了解耦,建立松耦合的系统一直是工程师们孜孜以求的目标,分层是实现隔离的有效手段,每层专注于自己的功能实现,上层使用下层的能力,下层为上层提供服务,上下层之间通过约定的接口交互,不紧邻的层之间完全透明。
前面在隔离关注点小节也讨论过,这里不再赘述。

一个的能力不是只是因为他在某个领域非常资深,而是他可以基于这个领域总结自己思考问题框架,让当前领域能力可迁移可复用,以不变应万变。

一些务实,提升也能快的飞起

一直学习,练习沉淀积极分享

两周后的平均留存

人啊,吸收率低,留存还短,整体效果差;主动学习,积极讨论和实践才能更好的留存。

了解历史已经够难了,我们对现实的认知也不够可靠,预言未来就更难了。

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

标签:

相关文章