启动软件项目的九个步骤

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 54w+ 字,讲解图 2476+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 1900+ 小伙伴加入学习 ,欢迎点击围观

不管敏捷与否,软件项目都是从需求分析和定义开始的。我们基本上定义了需要以某种方式完成的事情,无论是在一张餐巾纸上还是在 100 页的 word 文档上。下一步是尽可能快地把它变成一个可用的软件,并花费尽可能少的钱。理想情况下,这个原型制作需要一周时间,并且由 独立 工作的建筑师完成。一旦“骨架”准备就绪,我们就开始在其上放置软件“肉”。我们为此招募了一个程序员团队或将其外包。我在骨骼创建部分看到了九个重要步骤;让我一一给你看。

英雄 (2002) 作者:张艺谋

让我们用一些例子来说明这一点。假设我是一名软件架构师,而该项目是“谷歌杀手”。我们受雇创建一个新的搜索引擎,我的工作是将需求转化为原型,也就是骨架或概念证明。这就是我的输入(假设它是一张餐巾纸......对于谷歌杀手来说还有什么,对吧?):


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

对我来说似乎是一个可行的项目,需求文档也很清楚。它没有说任何关于性能的事情,但我可以假设它必须和谷歌一样快。可伸缩性、压力恢复能力等也是如此。

我不打算讨论软件是如何在特定的技术堆栈中创建的。这对本文并不重要。现在重要的是如何“包装”我的编程工作。换句话说,经过一周的努力工作后,我将向程序员团队交付什么——我的产品是什么,或者更正式地说,我的 可交付成果是什么

因此,让我们假设我设法创建了一个软件并且它可以工作。

决定和备选方案

首先,我必须记录我的关键技术决策及其备选方案。 我们 平时在github上工作,最好的文档媒体就是repo根目录下的 readme.md 文件。我只是把我的文字以普通的降价格式放在那里。对于一份好的技术文档来说,这就足够了——它必须简短;这很重要。

对于我做出的每一个决定,都必须至少有一个我考虑并拒绝的备选方案。我的列表顶部有两项:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

这些决定是非常高层的,但我仍然需要将它们记录下来。如您所见,我没有详细解释为什么替代方案被拒绝,这是我的选择。如果将来有人质疑我的决定,他们可能会说备选方案分析不当。很明显这是谁的错——我的错。所以我对我做出的这两个选择负全部责任:lucene 和 java 8。

列表中的另一个项目:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

然后,我附上一张简单的图表来说明我的决定:









如您所见,在这种情况下,我完全忽略了所有替代方案。我什至没有提到他们。再次,我对此负全部责任;我说,“我看不到任何替代方案。”如果以后发现了更好的替代方案,那么我们为什么会忽视它以及这是谁的错就会一目了然。这不仅关乎惩罚,还关乎纪律和决策的可追溯性。每个决定都必须追溯到做出决定的人。这有助于我们避免在未来做出错误的决定,并使整个项目更易于维护和透明。

让我们在列表中再添加一个决定:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

在这种情况下,我记录了备选方案并给出了它们对我们不利的原因。如您所见,原因非常有偏见;我对这三个框架基本上表达了我个人的看法,并且肯定会优先考虑我自己开源的 Takes 框架。好吗?不,这不对。但我是,我会做我认为适合该项目的事情。

我试图表明,这份文档的目的是为了我,架构师,解释我的思维方式——不管它有多糟糕、有偏见或不合理。我必须把我的决定写下来,让项目知道所有这些。

我建议您将记录在案的决定的数量保持在 4 到 12 之间。如果少于四个,我可能忘记记录一些重要的东西。超过 12 个——我记录了太多不重要的决定。我应该为此使用其他媒体,例如 javadoc 块或响应类。

顾虑

readme.md 文件的下一章必须解释我是如何设法解决初始要求中表达的所有问题的。我在上面提到,不用说我们的系统必须像谷歌一样快速和可扩展。因此,假设有两个“问题”——性能和可伸缩性。

作为一名软件架构师,我必须解决这两个问题。换句话说,我必须证明我的解决方案是快速且可扩展的。也许不是,但如果我相信是,我必须解释为什么我这么认为。我不能对这些担忧保持沉默。关于性能,我要说的是:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

这是关于可扩展性的:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

如您所见,我正努力诚实并说实话。稍后我们将能够审查这些陈述并决定我是对还是错。但我们需要得到我对要求中表达的所有担忧的答复。

假设

下一部分是关于我在使用原型时所做的假设。当我们没有足够的事实信息时,我们通常会做出假设,我们基本上会填补空白。它没有任何问题,但我们必须记录填补了哪些空白以及为什么。

这两个假设如何:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

我在没有对情况进行适当分析的情况下做出这些假设。我不知道 Twitter 是否会乐于看到每小时来自我们服务器的数百万个请求。也许它会禁止我们;我不知道。我不必对此进行评估并找到确切的答案。我只是做了一个假设并记录了下来。

如果没有任何额外的数据持久层,只使用 lucene 就足够了吗?我不知道,但我 希望 如此。我没有时间详细分析我们的整个数据模型及其潜在的未来需求。我只是做一个假设,然后就到此为止。

如果稍后在移交过程中,项目发起人说这个假设给项目带来了太多风险,我们将进行更好的分析。现在,我的工作是记录我所看到的并继续前进。记住,我只有一个星期的时间。

风险

现在我列出我预见的所有潜在问题并估计它们的可能性和影响。让我先给你看一个例子:


 each page is ranked by the number of mentions in
social networks like twitter, linkedin, facebook, etc.
the more mentions it has, the higher the rank and the
higher its position in the search results page.

方括号中的第一个数字是概率,第二个数字是影响,从 0 到 9 分。如果两个数字都是九,则不再有风险;这是事实。如果两个数字都为零,我们可以简单地忽略这种风险。

我只列出了两个,但在实际系统中应该有 4 到 12 个风险。太多的风险是原型不够专注的标志,而太少是由于缺乏关注。

持续集成

现在我必须确保产品在持续集成中被“包装”,这是任何软件包的关键组成部分。我必须配置它,最好是在云端,并确保构建是干净的。

确保持续集成管道涵盖所有关键领域也很重要,包括:

  • 在多个平台上构建,例如 linux、windows 和 mac。
  • 运行集成测试和单元测试。
  • 静态分析。
  • 收集测试覆盖率。
  • 生成文档。

管道越严格,项目越好。在这个阶段,作为一名架构师,我的工作是在产品周围建造一道“防护墙”,以保护它免受未来 混乱 的影响。混乱将来自程序员通过拉取请求进行更改。他们会比我更不关心产品的整体质量,这就是为什么我必须采用工具来控制情况。

我的目标是使持续集成管道尽可能 脆弱 。任何小错误都会导致构建失败。当然,我说的是可重现的失败。构建应该以可预测的方式失败,而不是偶尔失败。

静态分析

这是任何软件项目的另一个关键组成部分。您必须静态分析代码的质量。在最原始的方法中,静态分析将检查源代码的格式,并在格式损坏时构建失败。然而,在更高级的变体中,静态分析将捕获许多重要的错误。

之所以称为“静态”,是因为它不需要运行软件。相反,单元测试通过运行应用程序来验证运行时的软件质量。

有许多静态分析工具,几乎适用于每种语言和格式。我强烈建议您使用它们。此外,我建议您尽可能严格地配置它们,以使构建尽可能脆弱。构建的脆弱性是软件开发的关键成功因素。

测试覆盖率

必须在每次构建时收集测试覆盖率,并且至少要报告。在理想情况下,低测试覆盖率一定会导致构建失败。假设我将所需的覆盖百分比设置为 75%(这实际上是一个更复杂的指标,但在原始方法中,只需一个数字就足够了)。如果有人在没有单元测试的情况下引入了一个新类,覆盖率就会下降,构建就会中断。

作为一名创建原型的架构师,我的工作是确保在每次构建时计算覆盖率并在控制之下——它不能低于我设置的阈值。

不管门槛有多低,关键是能不能控制。

持续交付

这是交接前的最后一步。我必须配置一个持续交付管道,以确保一次单击即可打包和部署产品。这是非常重要——极其重要的——一步。没有它,之前所做的一切和软件本身都只是一个文件集合。当一个软件可以通过单击进行打包和部署时,它就是一个产品。

“流水线”意味着有许多元素顺序链接起来;对于 java 应用程序,例如:

  • 运行自动构建(与持续集成相同)
  • 打包jar文件
  • 上传jar文件到仓库
  • 建立javadoc网站
  • 将 javadoc 站点上传到 amazon s3

我正在使用 rultor 来自动化整个管道并简化其启动、停止和日志记录。我只是将“请立即发布”消息发布到 github 票证,产品在几分钟内打包和部署。

验收

最后一步是交接——我必须向项目经理、项目发起人和团队展示我的解决方案。每个人都必须接受它。这并不意味着他们会喜欢它,这不是目标。目标是交付一个完整的解决方案,记录风险、假设、决策、配置持续集成、强制执行静态分析等。如果我的解决方案不能满足他们的标准,他们将更换架构师并重试。

我的目标 不是 满足他们,而是根据要求和我对问题和业务领域的专业理解尽我所能。我前段时间写过这篇文章:一个快乐的老板是一个错误的目标。同样,我的目标不是让他们开心。相反,我的目标是制作一个完美的原型,就像我对 完美 这个词的理解一样。如果我失败了,我就失败了。该项目将请另一位建筑师再试一次。

就是这样。骨架准备好了,我的工作完成了。