如何构建大型应用程序

时间:2009-01-23 17:34:38

标签: architecture distributed

我认为我已经非常擅长编程的基础知识(适用于各种语言)。我可以写一个好的代码行。我可以写一个好的方法。我可以写一个好的类。我可以写一个好的类。我可以编写好的小型或中型应用程序。

但我不知道如何构建一个好的大型应用程序。特别是在涉及多种技术并且更多可能与时间有关的情况下。假设一个带有大型Web前端的项目,一个连接到其他集成后端的大型服务器后端,最后是一个庞大而复杂的数据库。哦,我参与了其中的一些应用程序,我可以构建一个我敢肯定的。然而,我不太确定它是否有资格作为“好”。

因此,我的问题是参考书籍或其他良好的阅读来源,我可以学习如何分发和组织一般大型项目的代码和数据。例如,我想要非常严格地对事物进行分层,还是要将其封装为独立单元?我是否想要尝试将大部分逻辑保留在同一个池中,还是应该只是分配,因为在添加我正在添加的任何功能时它似乎最合乎逻辑?

我已经看到很多关于这些问题的一般原则(例如没有意大利面条代码,肉丸代码......)并阅读了一些讨论此事的优秀文章,但我从来没有遇到过会让我具体化的来源实用知识。我意识到这个问题的难度,所以我很高兴听到其他人发现的帮助他们寻求这些知识的读物。

一如既往,感谢您的回复。

  

****鉴于“良好”代码定义存在争议的本质,在此背景下的“好”一词将不会被定义(它意味着你认为它应该是什么意思)。

12 个答案:

答案 0 :(得分:27)

作为程序员,我们喜欢相信自己是聪明人,所以很难承认某些东西太大而且太复杂甚至无法一次性思考。但对于一个大型软件项目来说,这是真的,你越早认识到有限的大脑容量并开始提出简化问题的方法,你就会越好。

要实现的另一个主要方面是,您将花费大部分时间更改现有代码。构建初始代码库只是蜜月期 - 你需要设计你的代码时考虑到这个想法,6个月后你会坐在它前面尝试解决一些问题而不知道这个特定模块是如何工作的,甚至虽然你是自己写的。

那么,我们能做什么?

最小化代码的不相关部分之间的耦合。代码将随着时间的推移以您无法预料的方式发生变化 - 与不熟悉的产品,需求变化相结合会出现显示问题 - 这些问题将导致波动的变化。如果已建立稳定的接口并对其进行编码,则可以在实现中进行所需的任何更改,而不会影响使用该接口的代码。你需要花费时间和精力开发经得起时间考验的界面 - 如果界面需要改变,你就会回到正方形。

建立可用于回归测试的自动化测试。是的,预先做了很多工作。但是,如果您可以进行更改,运行测试并确定它仍然可以正常工作,那将会获得回报,而不必担心如果您将最新的更改提交到源控制。

解决棘手的问题。偶尔我会看到一些聪明的C ++模板技巧并想一想,“哇!这就是我的代码所需要的!”但事实是,代码变得易读和容易理解的减少往往不值得增加通用性。如果你是像我这样的人,其天生的倾向是尽可能以一般的方式解决每一个问题,你需要学会克制它,直到你真正遇到 need 这个一般的解决方案。如果需要出现,你可能需要重写一些代码 - 这没什么大不了的。

答案 1 :(得分:17)

借用tvanfosson:

  

从一个小应用程序开始说   每次有人想要新的时候都是的   功能已添加。

答案 2 :(得分:11)

这是我们用来指导编码标准和方法的书:

alt text Large-Scale C++ Software Design

自从它首次在众所周知的卫生巾背面绘制以来,我正在开发的程序已经开发了近10年。而且这个项目今天仍然很强劲。它还不完美,并且仍存在循环依赖的问题,并且某些类接口不是很干净,但大多数类都不是这样,程序有效,我们的用户也很满意。

我还建议,像许多其他人一样,史蒂夫麦康奈尔Code CompleteSoftware Estimation。我特别喜欢他用“增长”软件而不是构建或构建软件的比喻。这种查看软件的方式更适合于具有较长生命周期的东西。

答案 3 :(得分:5)

正如我在其他地方提到的,大型应用程序不仅更大,而且不同。这么多,我们说的是编程 in-the-small in the the large 。当您进行大规模编程时,问题的性质及其解决方案会发生重大的质的转变。这条线非常模糊,有很多具体问题可能会迫使你越过那条线。

其中一些问题包括:

  • 大小(例如数据库根本不适合单个硬盘驱动器)
  • 复杂性(从一体化应用程序到多个子系统)
  • 并发(从0到数千/数百万同时用户)
  • 可用性(从9%的正常运行时间到99.999%的正常运行时间)
  • 可靠性(从每日故障到MTBF几年)
  • 速度(响应时间从小时到毫秒)
  • 产品化(从您的宠物项目到可销售的商品)

如何应对这一切?学习并使用所有有价值的技术,并学习评估哪些是有价值的 - 这需要一段时间,而且没有快速的答案。

然而,有一种技巧是简单,明显和一刀切:分而治之。隔离每个主要功能,每个子系统,每个外部依赖,以便您的主系统仅在其外边缘接触它们。当你可以通过在很短的时间内调整一个瘦接口来改变每一个,那么你已经完成了一些事情。这将带你走很长的路。

祝福。

答案 4 :(得分:4)

  1. 决定哪些功能最重要;忘了其余的
  2. 决定哪些那些功能最重要,而忘记其余功能
  3. 实施它们(应该花费几周时间,否则重复步骤1和2)
  4. 启动
  5. 查看哪些功能有效,哪些无效,哪些功能缺失
  6. 返回第1步

答案 5 :(得分:4)

大型应用程序不会在一个晚上创建。企业应用程序从小块开始,然后将它们组合在一起。如果您设计的应用程序是一种可以扩展的方式,那么它将更容易与所有周围因素集成,如数据库,第三方工具等。如果你进入infoq.com,你会发现很多很棒的关于缩放和体系结构的研究和材料的案例,如Myspace,亚马逊和许多其他。除了体验之外,您将无法开发出色的大型应用程序。

答案 6 :(得分:4)

增量,使用Test Driven Design

答案 7 :(得分:3)

使用设计模式使其可扩展,这意味着您不必更改所有内容以楔入新功能。

决定构建和构建它所需的内容。

将其分解为分别执行任务的模块。

计划计划计划,在开始之前了解您正在构建的内容,并构建该计划,而不是其他内容。

只编写你需要的功能,不要添加你认为可能有用的东西,但是......保持足够的灵活性,以便能够添加你可能需要添加的anthing。

答案 8 :(得分:3)

值得注意的是,有多少评论认为盲目迭代是唯一的方法。

迭代是至关重要的(我是一个巨大的粉丝),但有些人可以计划大型项目 - 这只是我们中很少有人见过的。

想想看,我们所有人都在车道上打篮球。我们非常好,我们可以获得大多数篮子,并且在公园里玩得很开心。

但是,仅仅因为我们从未见过职业球员,并不意味着他们不存在,并且不能整天在场上上下踢我们每一个人。

唯一的问题就是没有专业的编程游戏 - 也许如果有我们会看到它们更多。

答案 9 :(得分:0)

那么,你可以看看理性的统一过程。检查基本部件,选择一些您认为需要的工件。 列出您想要的所有功能,并将它们组织在需求列表中。 还要仔细规划您的软件架构,这样您就不必在以后更改它。 通过其中的一些提示,开发大型应用程序会相对容易。

答案 10 :(得分:0)

作为负责大型应用程序的人,我会说

  • 使用非侵入性框架,例如Spring
  • 减少耦合
  • 尽可能创建不可变对象 - 它们是线程友好的
  • 接受您的应用程序可能需要拆分为单独的流程,以便更好地扩展并为此做好计划。
  • 构建可靠的工具集并学习工具。

请勿恐慌

答案 11 :(得分:-2)

关于产品和供应商锁定的一些想法:

  • 尝试尽可能独立于供应商和平台。这将使您无需使用新产品/平台/框架等从头开始重新实现所有内容。
  • 这实际上意味着使用Java SE + Java EE +和开源RDBMS,如Java EE封装的JPA封装的PostgreSQL。不要使用额外的库,框架(spring,hibernate,...)等。这样你就可以随时切换产品和供应商。
  • 我认为您只能通过Java获得此级别的产品和平台独立性。即使您使用OSS库和框架,如果您发现实现不符合您的需求并且您必须重做所有内容,您将后悔使用它们。
  • 您可以使用Java Application Verification Kit
  • 检查代码的产品独立性
  • 事先花一些时间在架构上,但也要在整个实施过程中重新设计架构。一本好书(不幸的是只有德语)是Adam Bien的“Java EE 5 Architekturen”。

@j_random_hacker:实际上,没有 - 我仍然认为我的第一点是在大型应用程序中使用java而不是反对它的论据。每种语言都是一种语言。因此,当然,你总是必须对语言做出承诺。

  • 但Java SE& EE包括语言,编译器,虚拟机以及所有必需的库/框架。但是整个Java SE / EE平台有不同的实现:来自Sun,Apache,IBM,HP,Oracle,BEA的Java SE(JDK)。来自Sun,Apache,Red Hat,IBM,Oracle等的Java EE(Application Server)。 .Net与C#只有一个实现(来自Microsoft和一个名为Mono的类似语言/平台的实现)。
  • 我认为PHP也只有一个实现。有很多不同的C ++编译器。但它们都实现了略有不同的C ++语言,并且它们不与所有共享相同API的库捆绑在一起。选择Java,我知道我可以选择六个Java SE实现和六个Java EE应用服务器来运行该软件,该软件又可以在Linux,Solaris,FreeBSD,HP-UX,IBM z / OS,Windows上运行,Mac OS X以及各种各样的硬件平台。所以我不必担心,如果我在开发后期甚至在生产中发现一个非常糟糕的实现问题 - 我会离开Sun而永远不会回头。 (这就是我推荐Java应用程序验证工具包的原因。通过检查您的源代码,您可以确定,Sun,IBM,Oracle或任何其他邪恶的公司没有将他们的任何专有内容作为依赖项潜入您的源代码,这可能会绑定你到那家公司。你像鸟一样自由。)
  • 你不能用PHP或Ruby做到这一点。使用这些语言,如果没有其他人这样做,您将不得不自己修补实现问题,因为花费数月的错误修补时间到PHP或Ruby仍然比重写整个应用程序要少。
  • Sun开源了:Java SE(完整的JDK)和Java EE(Glassfish应用服务器)。唯一不是“开源”的是有一种绑定语言规范,它由sun领导,并得到其他人的大量贡献。这就是为什么你可以从sun获取Java实现,修改Java语言并重新分发源和二进制文件,但如果不符合语言规范,则不能再调用“Java”(Sun仅保护Java商标)实际应用于事物java)。这听起来可能听起来很“邪恶”,但实际上确保存在“Java”这样的东西:你可以编写一个java应用程序并在任何java实现上运行它。你不能用C ++做到这一点,因为没有C ++规范,这是每个c ++实现都同意的(源代码可以用英特尔C ++编译器编译,但不能用GNU编译器编译),更重要的是 - 没有公共库:如果我用QT库编写C ++程序,它将无法使用GTK库进行编译,因为它们具有完全不同的API。
  • 如果你无法忍受任何Sun微系统,但想要一个开源Java,那么你可以使用Apache Harmony(Java SE)和Apache Geronimo(Java EE)。