博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
无事实的事实表_事实在代码中
阅读量:2522 次
发布时间:2019-05-11

本文共 16242 字,大约阅读时间需要 54 分钟。

无事实的事实表

Sooner or later, every software developer will hear something like this:

迟早每个软件开发人员都会听到这样的消息:

“Truth can only be found in one place: the code.”
“真理只能在一个地方找到:代码。”

– Robert C. Martin,

–罗伯特·马丁(

But what does that mean?

但是,这是什么意思?

The values “working software over comprehensive documentation.”

重视“工作软件胜于全面文档”。

Developers write comprehensive documentation of the software’s behavior all the time, though. The code.

但是,开发人员始终会编写有关软件行为的全面文档。 代码。

Code comments, and external specifications, document the software’s behavior as well. But they may not get updated when the code changes. Then they stop reflecting the software’s behavior soon.

代码注释和外部规范也记录了软件的行为。 但是,当代码更改时,它们可能不会更新。 然后它们很快就会停止反映软件的行为。

In contrast, code always reflects the software’s behavior. It defines it.

相反,代码始终反映软件的行为。 它定义了它。

That’s why the truth is in the code.

这就是为什么真理在代码中。

为读者写作 (Writing for your readers)

Code is documentation. Any kind of documentation should be understandable by its readers.

代码是文档。 读者应该可以理解任何类型的文档。

The readers of code are a compiler or interpreter, and other developers.

代码的读者是编译器或解释器,以及其他开发人员。

So it is not enough if your code compiles. Other developers need to understand it as well. They need to work on your code in the future, change it and extend it.

因此,仅编译代码是不够的。 其他开发人员也需要了解它。 他们将来需要处理您的代码,进行更改和扩展。

A common suggestion to make code understandable is that you write clean code. Code that uses understandable language for variable and method names. That also makes a lot of code comments unnecessary.

使代码易于理解的常见建议是编写干净的代码。 使用易于理解的语言作为变量和方法名称的代码。 这也使很多代码注释不必要。

Clean code should express the intent: what somebody can achieve by calling a method. Not how the method achieves it.

干净的代码应该表达的意图: 哪些人可以通过调用的方法实现。 不是该方法如何实现。

Guess what this method does:

猜猜此方法的作用:

BigDecimal addUp(List
ns){..}

How about rather writing this:

宁愿这样写:

BigDecimal calculateTotal(List
individualPrice){..}

Clean code is a good idea. But I don’t think it is sufficient.

干净的代码是一个好主意。 但是我认为这还不够。

达成共识的重要性 (The importance of shared understanding)

When there’s a new requirement, you need to understand how implementing it affects the existing code.

当有新要求时,您需要了解实现它如何影响现有代码。

That can be a challenge if your software has been around for some time. Quite often, I have heard a dialogue like this:

如果您的软件已经存在了一段时间,那将是一个挑战。 我经常听到这样的对话:

X: We can’t go on with feature foo.

X :我们不能继续使用foo功能。

Y: Why?

Y :为什么?

X: Cause Z is the only one who knows about the code. He has implemented the code that we need to change now.

X :原因Z是唯一知道该代码的人。 他已经实现了我们现在需要更改的代码。

Y: Well, why don’t we ask him?

Y:恩,我们为什么不问他?

X: Because he is sick / on vacation / at a conference / no longer at the company.

X :因为他病了/休假/在会议上/不再在公司里。

Y: Oh…

Y :哦...

Here’s the thing. To find out if your code is understandable, somebody else should try to understand it.

这是东西 为了弄清楚您的代码是否可以理解,其他人应该尝试理解它。

There are techniques for that. is a good one. Or you sit down with other developers. You walk them through the code you have written.

有一些技巧。 是一个不错的选择。 或者您与其他开发人员坐下来。 您将引导他们完成您编写的代码。

Still, what if many developers are involved with a product? What if the development teams change their members? That makes it harder to write code that enough other people understand.

但是,如果有许多开发人员参与该产品怎么办? 如果开发团队更改其成员该怎么办? 这使得编写其他人足够理解的代码变得更加困难。

故事 (The story)

Clean code gives you the right words.

干净的代码可以为您提供正确的

The question is: what story will you tell with them in your code?

问题是:您将在代码中与他们讲述什么故事

I have no idea.

我不知道。

But for a typical business application, I am pretty sure what story I want to read in the code.

但是对于一个典型的业务应用程序,我很确定我想在代码中读什么故事。

After introducing you to a brief example, I will outline that story.

在向您介绍了一个简单的示例之后,我将概述该故事。

手套店的例子 (The glove shop example)

As a user of software, I want to . For example, I want to own a new pair of gloves to keep my fingers warm in winter.

作为软件的用户,我希望 。 例如,我想拥有一副新手套以在冬天保持手指温暖。

So I go online and see there is a new online shop specialized in gloves. The shop’s website lets me buy gloves. The “basic flow” (also called “happy day scenario”) of the use case could look like this one:

因此,我上网查看有一家专门从事手套的新网上商店。 我在商店的网站上可以买到手套。 用例的“基本流程”(也称为“欢乐时光场景”)如下所示:

  • The system starts with an empty shopping cart.

    系统从一个空的购物车开始。
  • The system displays a list of gloves.

    系统显示手套列表。
  • I add the gloves I like to the shopping cart. The system adds the gloves to my order.

    我将喜欢的手套添加到购物车中。 系统将手套添加到我的订单中。
  • I check out.

    我退房。
  • I enter shipping information and payment details. The system saves this information.

    我输入运送信息和付款明细。 系统保存此信息。
  • The system displays a summary of the order.

    系统显示订单摘要。
  • I confirm. The system initiates shipping of my order.

    我确定。 系统启动我的订单的运送。

After a few days, I get my gloves.

几天后,我拿到了手套。

这是我想用代码阅读的故事。 (Here’s the story I want to read in code.)

第1章:用例 (Chapter 1: Use cases)

The first chapter of the story is about use cases. When I read code, I want to follow a use case in the code step by step to the desired outcome.

故事的第一章是关于用例的。 当我阅读代码时,我想逐步遵循代码中的用例,以达到所需的结果。

I want to understand how the system reacts when something goes wrong. From a user’s perspective.

我想了解出现问题时系统的React。 从用户的角度来看。

I also want to understand the possible turns along the way. The user tries to go back from the payment details to the shipping information, for example. What happens? Is that even possible?

我也想了解整个过程中可能发生的转折。 例如,用户尝试从付款详细信息返回到运输信息。 怎么了? 那有可能吗?

I want to understand what code to look at for each part of a use case.

我想了解用例的每个部分要看什么代码。

那么用例的组成部分是什么? (So what are the parts of a use case?)

The fundamental part of a use case is a step that brings a user closer to a desired outcome. For example: “The system displays a list of gloves.”

一个用例的基本组成部分是,带来了用户更接近期望的结果的步骤 。 例如:“系统显示手套列表。”

Not all users may be able to run a step, but only members of certain user groups (the “actors”). End customers buy gloves. Marketing people enter new glove offers into the system.

并非所有用户都可以运行某个步骤,只有某些用户组的成员(“ 参与者” )可以运行。 最终客户购买手套。 营销人员将新的手套报价输入系统。

The system runs some of the steps on its own. Like when it displays the gloves. No user interaction necessary there.

系统自行运行某些步骤。 就像当它显示手套时一样。 那里不需要用户交互。

Or a step is an interaction with the user. The system reacts to some user event. For example: The user enters shipping information. The system saves the information.

或者一个步骤就是与用户的互动。 系统对某些用户事件 做出React 。 例如:用户输入运输信息。 系统保存信息。

I want to understand which data to expect with the event. Shipping information includes the user’s name, address etc.

我想了解该事件需要哪些数据 。 送货信息包括用户的姓名,地址等。

The user can run only a subset of steps at any given time. The user can enter payment details only after shipping information. So there is a flow that defines the order of the steps in a use case. And a condition that defines if the system can react, depending on the system’s state.

用户在任何给定时间只能运行一部分步骤。 用户只能在运送信息后输入付款明细。 因此,有一个流程定义了用例中步骤的顺序。 以及一个条件 ,该条件取决于系统的状态来定义系统是否可以做出React。

要理解代码,您需要一种简单的方法来了解几件事。 (To understand the code, you need an easy way to know several things.)

For a use case (like “buy gloves”):

对于用例(例如“购买手套”):

  • The flow(s) of steps

    步骤 流程

For each step:

对于每个步骤:

  • Which actors have access to it (that is, which user groups)

    哪些参与者可以访问它(即,哪些用户组)

  • Under which condition the system reacts

    在这种情况下 ,系统会做出React

  • If the step is autonomous, or based on a user interaction

    如果步骤是自主的 ,或基于用户交互

  • The system reaction

    系统 React

For each step that is a user interaction:

对于用户交互的每个步骤:

  • The user event (like “user entered shipping information”)

    用户事件 (例如“用户输入的运送信息”)

  • The data that comes with the event

    事件随附的数据

Once I know where to find a use case and its parts in the code, I can drill deeper.

一旦知道了在代码中哪里找到用例及其部分,便可以进行更深入的研究。

第2章:通过组件将事情分解为若干步骤 (Chapter 2: Breaking things down into steps through components)

Let’s call an encapsulated, replaceable building block of your software a component. A component’s responsibilities are available to the world outside the component.

让我们将软件的封装的,可替换的构建块称为组件。 组件的职责对组件外部的世界都是可用的。

A component could be:

组件可以是:

  • a technical component like a database repository,

    技术组件,例如数据库存储库,
  • a service like “shopping cart service”,

    诸如“购物车服务”之类的服务,
  • an entity in your domain model.

    域模型中的实体。

That depends on your software design. But no matter what your components are: you usually need several of them to realize one step of a use case.

这取决于您的软件设计。 但是,无论您的组件是什么:通常都需要几个组件来实现用例的第一步。

Let’s look at the system reaction of the step “The system displays a list of gloves”. You probably need to develop at least two responsibilities. One finds the gloves in the database, and one turns the list of gloves into a webpage.

让我们看一下“系统显示手套列表”步骤的系统React 。 您可能需要承担至少两项职责 。 一个人在数据库中找到手套,另一个人将手套列表变成一个网页。

When reading code I want to understand the following things:

阅读代码时,我想了解以下内容:

  • What are a component’s responsibilities. For example: “find gloves” for the database repository.

    组件的职责是什么 例如:数据库存储库的“手套”。

  • What are the inputs / outputs of each responsibility. Example input: criteria for which gloves to find. Example output: list of gloves.

    每个职责的输入 / 输出是什么。 输入示例:查找手套的标准。 输出示例:手套清单。

  • Who coordinates the responsibilities. For example: find gloves first. Turn result into a webpage second.

    谁来协调责任。 例如:首先找到手套。 将结果转换为网页。

第三章:什么组件起作用 (Chapter 3: What components do)

A component’s code fulfills responsibilities.

组件的代码履行职责。

That often happens in a domain model. The domain model uses terms relevant in the business domain.

这通常发生在领域模型中 。 域模型使用与业务领域相关的术语。

For the example, a term could be Glove. Another term could be Order.

例如,术语可以是手套。 另一个术语可以是订单。

The domain model describes the data for each term. Each Glove has a color, a brand, a size, a price and so on.

域模型描述每个术语的数据 。 每个手套都有颜色,品牌,尺寸,价格等。

The domain model also describes computations on the data. The total price of an Order is the sum of the prices of each Glove bought by the user.

领域模型还描述了对数据的计算。 订单的总价格是用户购买的每个手套的价格之和。

A component can also be a technical component like a database repository. The code needs to answer: How does the repository create, find, update and delete elements in the database?

组件也可以是技术组件,例如数据库存储库。 代码需要回答:存储库如何在数据库中创建,查找,更新和删除元素?

讲你的故事 (Telling your story)

Maybe your story looks similar to the one above. Maybe it’s different. Whatever your story is, programming languages give you great freedom to express yourself and tell that story.

也许您的故事与上述故事相似。 也许不一样。 无论您的故事是什么,编程语言都给您很大的自由来表达自己并讲故事。

That’s a good thing because it allows developers to adapt to different contexts and requirements.

这是一件好事,因为它允许开发人员适应不同的上下文和要求。

It also bears the risk that developers tell too many different stories. Even for the same product. That makes it harder than necessary to understand code that somebody else has written.

它还冒着开发人员讲述太多不同故事的风险。 即使对于相同的产品。 这使得理解别人编写的代码变得非常困难。

One way to address this is the use of design patterns. They allow you to structure your code. You can agree on that common structure in your team or even across teams.

解决此问题的一种方法是使用设计模式。 它们允许您构造代码。 您可以在团队中甚至跨团队达成共识。

For example, the Rails framework is based on the well-known Model View Controller pattern.

例如,Rails框架基于著名的“模型视图控制器”模式。

The model is the place for domain data.

该模型是 数据的存放地

The view is the client side user interface, like HTML pages. It is the origin of user events.

该视图是客户端用户界面,例如HTML页面。 它是用户 事件的起源

The controller receives the user events on server side. It is responsible for flow.

控制器在服务器端接收用户事件。 它负责流量。

So if several developers use Rails, they know which part of the code to look at for certain parts of their story.

因此,如果几个开发人员使用Rails,他们就会知道在故事的某些部分要看代码的哪一部分。

They could find out what is missing when sharing their understanding. Then, they could agree on further conventions on where to put which part of their story.

在分享他们的理解时,他们可以找出缺少的东西。 然后,他们可以就将故事的哪一部分放在哪里的进一步约定达成共识。

If that works for you, that is just fine. But I want to go further than that.

如果这对您有效,那很好。 但我想走得更远。

要求作为代码 (Requirements as Code)

Many of my clients ask me how to deal with long term software documentation.

我的许多客户都问我如何处理长期软件文档。

When working in an agile context, how do you create documentation for software maintenance?

在敏捷环境中工作时,如何创建软件维护文档?

What requirements have been implemented so far?

到目前为止已经执行了哪些要求?

Where do you find their realization in the code?

您在代码中的哪里找到它们的实现?

For a long time I had no satisfying answer. Except, of course: the importance of well written, automated tests. Clean production code. Shared understanding.

很长一段时间我都没有令人满意的答案。 当然,除了:编写良好的自动化测试的重要性。 清洁生产代码。 共同的理解。

But a few years ago, I started thinking:

但是几年前,我开始思考:

If the truth is in the code, the code should be able to speak the truth.
如果代码中包含真相,则代码应能够说出真相。

In other words: if you took great care of telling your story in the code, why would you want to tell it again?

换句话说:如果您非常注意在代码中讲故事,为什么还要再次讲?

There needs to be a better way. It must be possible to extract the story, and generate documentation from it. Documentation that non-technical stakeholders understand as well.

需要有更好的方法。 必须有可能提取故事并从中生成文档。 非技术涉众也可以理解的文档。

Documentation that is always up-to-date, because it comes from the same source that defines the software’s behavior.

文档始终是最新的,因为它来自定义软件行为的相同来源。

The only reliable source: the code itself.

唯一可靠的来源:代码本身。

After a lot of experiments, I had some results. I made them public in a Github project called .

经过大量的实验,我得到了一些结果。 我在Github项目( 公开了它们。

这个怎么运作 (How it works)

  • A Model instance defines the actors, use cases, their flows and steps. It tells chapter 1 of the story. You find an example of such a model at the start of this article.

    一个Model实例定义了参与者用例 ,它们的流程步骤 。 它讲述了故事的第一章。 您可以在本文开头找到此类模型的示例。

  • A model configures ModelRunner instances. Every user has her own runner, because every user may take a different path through the use cases in the model.

    模型配置ModelRunner实例。 每个用户都有自己的跑步者,因为每个用户在模型中的用例中可能采取不同的路径。
  • The runner reacts to a user event from the frontend by calling the system reaction in the backend. The frontend communicates to the backend only through the runner.

    运行程序通过在后端调用系统响应来响应来自前端的用户事件 前端仅通过运行器与后端通信。

  • But the runner only reacts if the user is at the right position of the flow and the step’s condition is fulfilled. For example, the runner only reacts to the “EnterPaymentDetails“ event if the user has entered the shipping information right before.

    但是,只有在用户位于流程的正确位置并且满足步骤条件时 ,跑步者才会做出React。 例如,仅当用户之前输入了运送信息时,跑步者才对“ EnterPaymentDetails”事件做出React。

  • The system reaction is a single method. The method’s body is responsible for coordinating the components to realize the step, as described in chapter 2.

    系统 React是单一方法。 方法的主体负责协调组件以实现该步骤,如第2章所述。

  • Chapter 3 is out of scope of requirements as code. It is left up to the application. That makes requirements as code compatible with arbitrary software designs.

    第3章超出了代码要求的范围。 它由应用程序决定。 这使得要求的代码与任意软件设计兼容。

So the ModelRunner controls the user visible behavior of the software. Based on a Model.

因此,ModelRunner可以控制用户可见的软件行为。 基于模型。

With , you can generate documentation from the same model that configures the runner. That way, the documentation always reflects how the software works.

通过将 ,您可以从配置运行器的同一模型生成文档。 这样,文档始终可以反映软件的工作方式。

Requirements as code extract uses the FreeMarker template engine. That allows you to generate any plain text documentation you like. For example HTML pages. Further processing could turn it into other documentation formats, like PDF.

代码提取中的要求使用FreeMarker模板引擎。 这样就可以生成所需的任何纯文本文档。 例如HTML页面。 进一步处理可能会将其转换为其他文档格式,例如PDF。

您的反馈将帮助我改善这个项目 (Your feedback will help me improve this project)

I started working on requirements as code several years ago. It has gone through significant improvement since the beginning.

几年前,我开始研究需求作为代码。 从一开始,它就经历了重大改进。

To learn whether the approach scales, I tried it on an application with several thousand lines of code. It worked. I tried it on smaller applications as well.

为了了解这种方法是否可以扩展,我在具有数千行代码的应用程序上进行了尝试。 有效。 我也在较小的应用程序上尝试过。

Still, so far, requirements as code has been my hobby project.

到目前为止,代码需求一直是我的爱好项目。

That’s why I need your help. Please give me feedback.

这就是为什么我需要您的帮助。 请给我反馈。

What do you think of the idea? Can you imagine that it works in the context of the software you develop? Any other feedback?

您如何看待这个主意? 您能想象它可以在您开发的软件的上下文中起作用吗? 还有别的反馈吗?

You can drop me a note in the comments or contact me on or .

您可以在评论中给我留言,或通过或与我联系。

You can the project and try it out yourself.

您可以项目并自己尝试。

Or you can to documenting the truth in the code.

或者你也可以到记录真相的代码。

Edited October 16, 2018: adapted to the version v1.0.0 of requirements as code

编辑于2018年10月16日:适应v1.0.0版本的要求作为代码

翻译自:

无事实的事实表

转载地址:http://lnwzd.baihongyu.com/

你可能感兴趣的文章
第五天站立会议内容
查看>>
ATMEGA16 IOport相关汇总
查看>>
面试题5:字符串替换空格
查看>>
[Codevs] 线段树练习5
查看>>
Amazon
查看>>
hMailServer搭建简单邮件系统
查看>>
从零开始学习jQuery
查看>>
opacity半透明兼容ie8。。。。ie8半透明
查看>>
CDOJ_24 八球胜负
查看>>
Alpha 冲刺 (7/10)
查看>>
一款jQuery打造的具有多功能切换的幻灯片特效
查看>>
SNMP从入门到开发:进阶篇
查看>>
@ServletComponentScan ,@ComponentScan,@Configuration 解析
查看>>
unity3d 射弹基础案例代码分析
查看>>
thinksns 分页数据
查看>>
os模块
查看>>
最短路径(SP)问题相关算法与模板
查看>>
js算法之最常用的排序
查看>>
Python——交互式图形编程
查看>>
经典排序——希尔排序
查看>>