巨大的整体应用的危险


20

我现在从事的一个大型项目现在是高级设备的控制(及所有)应用程序,它是固件的核心。

该设备相当先进,具有比我在内存中所能说的更多的不同功能,其中98%由该庞大的可执行文件处理。一方面,该程序可维护性强,内部模块化程度高,文档正确,并且按目录和文件等对功能进行了合理隔离。

但是最后,它被全部集中到一个应用程序中,该应用程序执行从远程数据库通信,触摸屏处理,处理十二种各种通信协议,测量,几种控制算法,视频捕获,日出时间和复活节日期(认真地,通常,这是非常紧密相关的内容,通常仅通过一些在一些远模块之间滴加的数据才相关。

它可以通过几个单独的可执行文件相互通信来完成,例如,通过套接字进行通信,具有更特定的目的,可以根据需要加载/卸载等等。没有这种特定方式的原因。

一方面,它有效,而且还可以。该项目更加简单,无需维护多个二进制文件的构建。当您可以仅调用方法或读取变量而不是通过套接字或共享内存进行通信时,内部结构也更容易。

但另一方面,这东西的大小,规模让我感到无所适从,感觉就像是驾驶泰坦尼克号一样。我总是被教导要模块化,将所有内容都聚集到一个庞大的文件中感觉很不对。我知道的一个问题是,一个严重的崩溃(甚至无关紧要的)使所有模块崩溃了,但是代码质量确保在发行版中不会真正发生这种情况。否则,内部隔离和防御性编程可确保即使一半内部模块由于某种原因正常发生故障,该操作仍将大部分正确地运行。

我还忽略了哪些其他危险?为什么这使我感到恐惧?这只是对未知的非理性恐惧吗?这样进行严肃的大型项目是否可以接受?请平息我的担心,或者给我一个很好的理由将2.0版重构为多个较小的二进制文件。


7
如果太阳升得太早,英格兰将漂洋出海。
2011年

1
否则地球核心的压力会略有上升。
StuperUser 2011年

1
@Maxpm我看你做了什么,有... xkcd.com/687
tetO的

3
@Maxpm:幸运的是,我们的应用程序不会驱动日出和日落。我们相信Celestia公主不会在她的工作上失败。
SF。

1
@rwong:1.设备停止升级。尽管它可以随时进行更新,但我们不希望有任何意外的结果,以防万一更新由于任何原因而出错。2.具有嵌入式Linux的单核ARM9。还有第二个监督CPU在没有OS的情况下运行,验证主CPU产生了合理的输出。
SF。

Answers:


5

除了最后的小注释(第二,监督CPU)之外,您可能还描述了我的公司。是的,我们也需要复活节。

好吧,我们还有一段距离。我们确实拆分了大型可执行文件,并尝试将标准组件用于标准位。并非您所希望的大改进。实际上,即使在功能更强大的硬件上,性能也正成为主要的痛苦。既然有大量的代码可以通过狭窄的接口序列化和同步数据,那么维护成本并没有真正降低。

我学到的教训?对于小型系统,拥有一个可执行文件是一种行之有效的解决方案,我们在管理它方面拥有数十年的经验。我们所有的工具都提供本地支持。模块化也可以在单个可执行文件中完成,并且当您出于其他原因需要折衷模块化时,黑客攻击仍然很小。


谢谢-没有“要遵循/牺牲的最佳实践”和“权衡潜在利益与潜在不利因素”的条目,与在篱笆另一侧有第一手经验的人一样,都没有帮助。
SF。

23

该设备相当先进,具有比我在内存中所能说的更多的不同功能,其中98%由该庞大的可执行文件处理。一方面,该程序可维护性强,内部模块化程度高,文档正确,并且按目录和文件等对功能进行了合理隔离。

您自己说过的-它非常易于维护,模块化程度很高...

我认为,并且大多数管理层都会同意我的这一观点,因此永远不要为了改变而进行改变。该程序(您的描述)没有任何问题,除了它没有遵循最新的编程趋势(在其他答案中提到)。

是的,这是一个较大的程序……以前也有很多。它也有据可查,因此您要做的就是研究其内部组织,您将看到其中的逻辑。我怀疑在您撰写本书之前所有的人都是无能的。因此,请对其进行一些探索,学习...之后,将其保持原样,直到出现重写它的可靠原因为止。您的经理将感谢您具有良好的成本/效果比。

我还忽略了哪些其他危险?为什么这使我感到恐惧?这只是对未知的非理性恐惧吗?这样进行严肃的大型项目是否可以接受?请平息我的担心,或者给我一个很好的理由将2.0版重构为多个较小的二进制文件。

因为它很大,它会让您感到毛骨悚然-但是话又说回来,没有人期望您在一周内全心全意地学习它。因此,一点一点地工作,一点一点,直到您掌握了它。最后,您将了解到它可能井井有条,并且井井有条。

如果您重写它,您将完成相同的工作,但是同时对于习惯了代码先前组织的所有人员来说,它都会毁掉它。这样,只有您必须“适应”。


16

如果您说所有内容都包含在单元测试中,我会感觉更好。如果不这样做,则应在考虑重新配置应用程序之前先构建一个测试套件。

拥有测试套件将提高您对应用程序的了解,并会告诉您应用程序中的更改何时会破坏某些功能。


2
但这适用于两种可能的体系结构……
SF。

3
是的,它确实...
罗伯特·哈维

10
...因此,这个答案除了促进单元测试之外,没有增加任何讨论内容。
benzado 2011年

2
@benzado:在OP的场景中,这非常重要。
罗伯特·哈维

2
@ironcode:看一本书,例如“有效使用旧版代码”。他在那本书中说的第一件事是:“如果您还没有一套具有高代码覆盖率的单元测试,请先编写它们,然后再进行其他操作。 ”我要说的是,这里的建议比实际意义更大,鉴于OP明确询问“我还忽略了哪些其他危险”。
罗伯特·哈维,

8

如果代码经过很好的模块化,耦合度低,内聚性高,则可以对代码进行有效分区。一个过程中的通信开销应该比多个过程中的通信开销要低。

对于嵌入式系统,您的一个进程可能不需要实施O / S来运行您将要创建的所有进程。您还需要实现一个系统来检查所有进程是否都在运行,并在可能的情况下重新启动它们。如果不可能的话,您将需要做出相应的反应。

将代码拆分为单独的可执行文件也将增加源代码的整体大小,因为您将需要在模块之间实现所有客户端/服务器代码。您还需要更多的测试用例来处理此代码,以及服务器进程不存在的情况。大型项目很大,因此消除了不必要的复杂性,使它们尽可能地小。

在这里,测试有点像是一团糟,因为无论是否进行测试,问题仍然存在。无论选择哪种设计,都应该进行良好的测试。我希望,使用整体代码可以简化测试。

使用整体可执行文件,在必要时强制崩溃也更容易。


1
+1,工程设计是要权衡的,较小的二进制文件也
要付出代价

+1我全心全意同意。没有给出保证多个可执行文件的特定原因。可执行文件之间的通信和协调有其代价。
埃里克·罗伯逊

+1:如果没有损坏,请不要修复。
鲍勃·墨菲,

1

如果我要在如此大的整体应用程序上工作,那么令我感到震惊的事情是缺少封装,低内聚性,高耦合性以及如何测试所有这些。大的巨石通常会导致放弃适当的建筑并开始陷入泥泞的泥潭

一旦发生这种情况,测试就变成了一场噩梦,而您已经过时了。

但是,如果您的代码结构合理,维护良好,并且遵循高内聚,低耦合和适当封装的原则,那么我几乎没有理由将其重构为较小的单元。

不过,您确实希望有良好的测试。


1

理想情况下,答案是肯定的。具有多个二进制文件可能会使它更加稳定。

...但是,您还提到了整体代码库中的代码编写良好且模块化,这意味着您无需处理庞大的混乱局面,而只需处理庞大的代码库...

总体而言,我会说适用的谚语是:“不要让完美成为商品的敌人”。尽管我认为单片代码库不好是正确的,但我也觉得值得为此付出努力。

通过将新的代码片段放入其自己的二进制文件中来进行前进是合理的,但是返回并进行重构可能不值得您花时间。


1

如果您使用的是单个进程,则很有可能机会来自子模块之一的野指针会破坏关键的内存(并使整个设备崩溃)。

如果使用的进程不同,则至少不会使用相同的堆或调用堆栈,并且重新启动单个子进程也可能会更容易。

当您可以仅调用方法或读取变量而不是通过套接字或共享内存进行通信时,内部结构也更容易。

在多个过程中重新分配所有内容还将迫使您清理设计,并避免每个模块开始使用其他模块的内部方法。

话虽如此,这可能是艰巨的任务。

您可以开始做的是,确定每个新模块都应该是一个独立的过程。


您对运行时的硬件和OS环境有很多了解,尤其是在涉及固件和嵌入式设备时。
Patrick Hughes

0

当我进入一个项目太大而无法一次完成所有内容的领域时,我会建立一张挂在墙上的图表,其中列出了所有主要部分以及它们如何组合在一起。然后,当我工作时,我可以参考我关注的模块,并从视觉上提醒它如何适合整个模块。

对于这样一个庞大而庞大的项目,维护多个断开连接的二进制文件的构建和版本控制系统的复杂性和危险很可能远远超过您的不安。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.