域 嵌入图像显示不出来

Code should clearly reflect the problem it’s solving, and thus openly expose that problem’s domain. Embedding domain concepts in code requires thought and skill, and doesn't drop out automatically from TDD. However, it is a necessary step on the road to writing easily understandable code.

代码应该清楚地反映它正在解决的问题,从而公开暴露该问题的领域。 将领域概念嵌入代码中需要思想和技巧,并且不会自动从TDD中退出。 但是,这是编写易于理解的代码的必经之路。

I was at a software craftsmanship meetup recently, where we formed pairs to solve a simplified Berlin Clock Kata. A Berlin Clock displays the time using rows of flashing lights, which you can see below (although in the kata we just output a text representation, and the lights in a row are all the same colour).

我最近参加了一次软件手Craft.io聚会,在那里我们结成对,以解决简化的Berlin Clock Kata。 柏林时钟使用闪烁的行显示时间,您可以在下面看到(尽管在kata中,我们只是输出文本表示,并且行中的所有颜色都是相同的颜色)。

初始测试驱动解决方案 (Initial Test Driven solution)

Most pairs used inside out TDD, and there were a lot of solutions that looked something like this (complete code available on GitHub).

大多数对在TDD内使用,并且有很多解决方案看起来像这样(完整的代码可在GitHub上找到 )。

def berlin_clock_time(julian_time):hours, minutes, seconds = list(map(int, julian_time.split(":")))return [seconds_row_lights(seconds % 2), five_hours_row_lights(hours), single_hours_row_lights(hours % 5), five_minutes_row_lights(minutes), single_minutes_row_lights(minutes % 5)]def five_hours_row_lights(hours):lights_on = hours // 5lights_in_row = 4return lights_for_row("R", lights_on, lights_in_row)# ...

This type of solution drops out naturally from applying inside out TDD to the problem. You write some tests for the seconds row, then some tests for the five hours row, and so on, and then you put it all together and do some refactoring. This solution does expose some of the domain concepts at a glance:

这种类型的解决方案会自然而然地从将TDD应用于问题之外而退出。 您为秒行编写了一些测试,为五小时行编写了一些测试,依此类推,然后将它们放在一起并进行一些重构。 此解决方案确实使一些领域概念一目了然:

  • There are 5 rows
    有5行
  • There is one second row, 2 hour rows and 2 minute rows
    一秒行,2小时行和2分钟行

Some more concepts are available after a bit of digging, but aren't immediately obvious. The rows are made up of lights that can be on (or presumably off), and that the number of lights on is an indication of the time.

经过一些挖掘,还可以使用其他一些概念,但是这些概念并不是立即显而易见的。 这些行由可以点亮(或可能熄灭)的灯组成,并且点亮的次数表示时间。

However there are some big parts of the problem that are not exposed. And since I haven't yet explained it, you probably don't know exactly how the Berlin Clock works yet.

但是,有很多问题尚未解决。 而且由于我尚未解释,您可能还不知道确切的柏林钟如何工作。

提升概念 (Elevate the concepts)

To improve this we can bring some of the details that are buried in the helper functions (such as get_five_hours) closer to the top of the file. This brings you to something like the following (complete code available on GitHub), although the downside is that it breaks nearly all of the tests. Solutions like this are rarer on GitHub, but do exist.

为了改善这一点,我们可以将一些辅助函数中隐藏的细节(例如get_five_hours )放在文件顶部附近。 这带来了类似以下的内容(完整的代码可在GitHub上找到 ),尽管缺点是它几乎破坏了所有测试。 这样的解决方案在GitHub上很少见,但确实存在。

def berlin_clock_time(julian_time):hours, minutes, seconds = list(map(int, julian_time.split(":")))single_seconds = seconds_row_lights(seconds % 2)five_hours = row_lights(light_colour="R",lights_on=hours // 5,lights_in_row=4)single_hours = row_lights(light_colour="R",lights_on=hours % 5,lights_in_row=4)five_minutes = row_lights(light_colour="Y",lights_on=minutes // 5,lights_in_row=11)single_minutes = row_lights(light_colour="Y",lights_on=minutes % 5,lights_in_row=4)return [single_seconds,five_hours,single_hours,five_minutes,single_minutes]# ...

This improves the concepts that are now exposed at a glance:

这改进了现在可以一目了然的概念:

  • There are 5 rows
    有5行
  • The seconds row is a special case
    秒行是一种特殊情况
  • There are 2 hour rows and 2 minute rows
    有2小时行和2分钟行
  • The rows use different colour lights
    行使用不同颜色的灯光
  • The rows have a different number of lights
    行有不同数量的灯

This is pretty good, and is already better that most of the solutions out there. However, it's still a bit mysterious how the rows are related to each other (there are 2 rows to display the hours and the minutes, so presumably these are linked). It's also not obvious what amount of time each light represents.

这非常好,并且已经比大多数解决方案更好。 但是,各行之间的相互关系还是有点神秘(有两行显示小时和分钟,因此大概是链接在一起的)。 每个灯代表多少时间也并不明显。

命名隐式概念 (Name implicit concepts)

At the moment some of the concepts (such as the amount of time each light represents) are implicit in the code. Making these explicit, and naming them, forces us to understand them and to embed that understanding in the code.

目前,某些概念(例如每盏灯所代表的时间)已隐含在代码中。 将它们明确显示并命名,迫使我们理解它们并将这种理解嵌入代码中。

In order to make the amount of time each light represents explicit, it seems like it would be sensible to pass a time_per_light value to row_lights. This means we have to push the calculation of lights_on down into row_lights.

为了使每个时间指示灯代表明确的量,现在看来似乎是明智的一传time_per_lightrow_lights 。 这意味着我们必须将lights_on的计算向下推到row_lights

This in turn makes it obvious that there are two kinds of rows: one related to the quotient (\\) of the time value, and one related to the remainder / modulus (%). If we look at the quotient case, we see that the 2nd parameter to the operation is the time_per_light, which is 5 in both cases (5 hours in one case and 5 minutes in the other).

这样就可以很明显地看到两行:一行与时间值的商( \\ )有关,另一行与余数/模数( % )有关。 如果看商数情况,我们会发现该操作的第二个参数是time_per_light ,在两种情况下均为5(一种情况下为5小时,另一种情况下为5分钟)。

This allows us to write these rows like this:

这使我们可以像下面这样写这些行:

five_hour_row = row_lights(time_per_light=5,value=hours, light_colour="R",lights_in_row=4)

If we now turn our attention to the remainder case, we realise that time_per_light is always singular (one hour or one minute), as it is filling in the gaps in the quotient case.

现在,如果我们将注意力转向其余情况,我们将意识到time_per_light总是单数(一小时或一分钟),因为它填补了商情况中的空白。

For example, the five hours row can represent 0, 5, 10, 15, or 20 hours, but nothing in between. In order to represent any hour, there must be another row to represent +1, +2, +3 and +4. This means that this row must have exactly 4 lights, and that each light must represent 1 hour.

例如,五小时行可以表示0、5、10、15或20小时,但中间没有任何时间。 为了表示任何小时,必须有另一行表示+ 1,+ 2,+ 3和+4。 这意味着该行必须正好有4个灯,并且每个灯必须代表1个小时。

This implies that the remainder case is dependent on the quotient one, which most people would describe as a parent / child relationship.

这意味着剩余的情况取决于商,大多数人将其描述为父母/子女关系。

With this knowledge in hand, we can now create a function for the child remainder rows, and the solution now looks like this (complete code on GitHub):

掌握了这些知识之后,我们现在可以为子余数行创建一个函数,解决方案如下所示( 在GitHub上完整的代码 ):

def berlin_clock_time(julian_time):hours, minutes, seconds = list(map(int, julian_time.split(":")))return [seconds_row_lights(seconds % 2),parent_row_lights(time_per_light=5,value=hours, light_colour="R",lights_in_row=4),child_remainder_row_lights(parent_time_per_light=5,value=hours,light_colour="R"),parent_row_lights(time_per_light=5,value=minutes, light_colour="Y",lights_in_row=11),child_remainder_row_lights(parent_time_per_light=5,light_colour="Y",value=minutes)]# ...

A quick glance at this code now reveals nearly all the domain concepts

快速浏览一下此代码,现在可以发现几乎所有领域的概念

  • The first row represents the seconds and is a special case
    第一行代表秒,是一种特殊情况
  • On the second row each "R" light represents 5 hours
    在第二行,每个“ R”灯代表5个小时
  • The third row shows the remainder from the second
    第三行显示第二行的其余部分
  • On the fourth row each "Y" light represents 5 hours
    在第四行,每个“ Y”灯代表5个小时
  • The fifth row shows the remainder from the fourth
    第五行显示了第四行的其余部分

This took something thinking about, which will have cost us some time / money. But we increased our understanding of the problem while we did it, and most importantly we embedded that knowledge in to the code. This means that the next person to read the code will not have to do this, which will save some time / money. Since we spend about 10 times longer reading code than we do writing it, this is probably a worthwhile endeavour.

这需要一些思考,这将花费我们一些时间/金钱。 但是,在执行问题时,我们加深了对问题的理解,最重要的是,我们将这些知识嵌入了代码中。 这意味着下一个阅读代码的人将不必这样做,这将节省一些时间/金钱。 由于我们花费的代码阅读时间比编写代码的时间长10倍左右,因此这可能是值得的。

Embedding this understanding has also made it harder for future programmers to make mistakes. For example, the concept of parent / child rows didn't exist in earlier examples, and it would be easy to mismatch them. Now the concept is plain to see, and the values are mostly worked out for you. It is also easier to refactor to support new clock variants, for example where lights in the first hours row represent 6 hours.

嵌入这种理解也使将来的程序员更难犯错误。 例如,在先前的示例中不存在父/子行的概念,很容易使它们不匹配。 现在可以清楚地看到该概念,并且大多数值都是为您确定的。 重构以支持新的时钟变体也更加容易,例如,第一个小时行中的灯表示6个小时。

你应该走多远? (How far should you take it?)

There are things we can do to take this further. For example the parent_time_per_light of a child row must match the time_per_light of its parent, and there is nothing enforcing this. There is also a relationship between time_per_light and lights_in_row for the parent rows, and again it is not enforced.

我们可以做一些进一步的事情。 例如, parent_time_per_light子行必须匹配time_per_light其父,并没有什么强制执行这一点。 父行的time_per_lightlights_in_row之间也存在关系,因此也不再强制执行。

However, at the moment we are only required to support one clock variant, so these probably aren't worth doing. When a change is required for the code, we should refactor so that the change is easy (which might be hard) and then make the easy change.

但是,目前我们只需要支持一个时钟变体,因此这些可能不值得。 当需要对代码进行更改时,我们应该进行重构,以使更改变得容易(这可能很困难),然后进行轻松的更改。

结论 (Conclusions)

Embedding domain concepts in code requires thought and skill, and TDD won't necessarily do it for you. It takes longer than a naive solution, but makes the code easier to understand, and will very likely save time in the medium term. Time is money, and finding the right balance of spending time now versus saving time later is also an important skill for a professional programmer to have.

将领域概念嵌入代码中需要思想和技巧,而TDD不一定能为您做到。 它比幼稚的解决方案花费的时间更长,但是使代码更易于理解,并且很可能在中期节省时间。 时间就是金钱,对于专业程序员来说,现在要花时间与以后节省时间之间找到合适的平衡也是一项重要技能。

翻译自: https://www.freecodecamp.org/news/embedding-domain-concepts-in-code/

域 嵌入图像显示不出来

域 嵌入图像显示不出来_如何(以及为什么)将域概念嵌入代码中相关推荐

  1. word嵌入对象依损坏_出错提示“Word 未能写某些嵌入对象,因为内容或磁盘空间不足”...

    出错提示"Word 未能写某些嵌入对象,因为内容或磁盘空间不足",感开始怀疑是转换软件,经过诊断,一切完好.问题主要出在word上,文档里插入了比较多的公式和图片,而且这些嵌入对象 ...

  2. 作业优先调度java代码_如何在触发它时在java代码中为hadoop作业设置优先级?

    这是我的工作人员的外表.如何在触发这项工作时设定低优先级? public int run(String[] args) throws Exception { this.initJob(); Path ...

  3. vscode中怎样格式化js代码_[VSCode插件推荐] Bracket Pair Colorizer: 为代码中的括号添上一抹亮色...

    在代码编写过程中,各种括号 {[()]} 必不可少.然而,随着代码量的增加,你有没有因为括号的嵌套太多,而导致代码难以阅读? 我们来看看下面的代码,在第三行代码的最后部分,连续出现了5个右括号! 这还 ...

  4. 命令不识别_互助问答138期:GMM命令代码中如何识别年份国家及异方差检验问题...

    老师您好,有两个关于系统GMM的问题想请教一下:(1)在所学的教程里,系统GMM没有引入时间,我目前是分行业分国家的时间为T年的面板数据,请问时间应该放入xtdpdsys的命令中的哪个位置?代码是写作 ...

  5. python四分位数_分位函数(四分位数)概念与pandas中的quantile函数

    函数原型 DataFrame.quantile(q=0.5, axis=0, numeric_only=True, interpolation='linear') 参数 - q : float or ...

  6. vscode括号颜色插件_[VSCode插件推荐] Bracket Pair Colorizer: 为代码中的括号添上一抹亮色...

    在代码编写过程中,各种括号 {[()]} 必不可少.然而,随着代码量的增加,你有没有因为括号的嵌套太多,而导致代码难以阅读? 我们来看看下面的代码,在第三行代码的最后部分,连续出现了5个右括号! 这还 ...

  7. mysql求分位数_分位函数(四分位数)概念与pandas中的quantile函数

    函数原型 DataFrame.quantile(q=0.5, axis=0, numeric_only=True, interpolation='linear') 参数 - q : float or ...

  8. JavaScript跨域问题分析与总结_直来直往_百度空间

    JavaScript跨域问题分析与总结_直来直往_百度空间 JavaScript跨域问题分析与总结 2009-11-15 16:44 一.为什么需要JS跨域 假设我们构建了一个网上商城www.xxx. ...

  9. bat 域 本机管理员密码_域渗透——Local Administrator Password Solution

    0x00 前言 在域渗透中,有关域内主机的本地管理员的安全介绍还很少,对于LAPS大都比较陌生,所以这次就和我一起学习一下吧. 0x01 简介 在实际的域环境中,域内主机的本地管理员账户往往被忽视,再 ...

最新文章

  1. 从零开始PyTorch项目:YOLO v3目标检测实现
  2. Python 面试中可能会被问到的30个问题
  3. C、C++和C#区别概述
  4. python图片马赛克_Python实现PS滤镜中马赛克效果示例
  5. 奚江华的几篇Silverlight文章
  6. Java中的数据结构之常见的五种数据结构
  7. PDF目录的自动生成
  8. Flash CS3无法导出测试影片问题解决
  9. VS2012 MFC 入门
  10. 2022年信息安全工程师考试知识点:信息系统安全产品的配置与使用
  11. 渺小的个体不能体会之孤独
  12. 利用sqlmap注入获取网址管理员账号密码
  13. 股票移动平均线matlab,移动平均线(MA)
  14. 2108 JAVASE每日复习总结 链接汇总
  15. 新华三笔试题(助力面试)
  16. 智能手表APP方案开发公司那个好
  17. 【迭代式开发】v1架构设计文档——大数据开发实战项目(三)
  18. Linux 磁盘自动分区脚本
  19. 第七章 数据类型、平面直角坐标系和复数
  20. CodeForces 652C Foe Pairs

热门文章

  1. Java面试题2021,文末有福利
  2. 漫谈MySQL权限安全,威力加强版
  3. [New Portal]Windows Azure Web Site (4) Web Site Gallery
  4. 无法获取 vmci 驱动程序版本: 句柄无效
  5. hadoop2.x HDFS快照介绍
  6. AngularJs 相应回车事件
  7. 分享网页设计当中使用进度条打造精美界面最佳例子
  8. 安卓开发1-初步了解使用
  9. happens-before规则和as-if-serial语义
  10. python一步将npy数据保存成mat