域 嵌入图像显示不出来_如何(以及为什么)将域概念嵌入代码中
域 嵌入圖像顯示不出來
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.
代碼應(yīng)該清楚地反映它正在解決的問題,從而公開暴露該問題的領(lǐng)域。 將領(lǐng)域概念嵌入代碼中需要思想和技巧,并且不會(huì)自動(dòng)從TDD中退出。 但是,這是編寫易于理解的代碼的必經(jīng)之路。
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聚會(huì),在那里我們結(jié)成對(duì),以解決簡(jiǎn)化的Berlin Clock Kata。 柏林時(shí)鐘使用閃爍的行顯示時(shí)間,您可以在下面看到(盡管在kata中,我們只是輸出文本表示,并且行中的所有顏色都是相同的顏色)。
初始測(cè)試驅(qū)動(dòng)解決方案 (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).
大多數(shù)對(duì)在TDD內(nèi)使用,并且有很多解決方案看起來像這樣(完整的代碼可在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:
這種類型的解決方案會(huì)自然而然地從將TDD應(yīng)用于問題之外而退出。 您為秒行編寫了一些測(cè)試,為五小時(shí)行編寫了一些測(cè)試,依此類推,然后將它們放在一起并進(jìn)行一些重構(gòu)。 此解決方案確實(shí)使一些領(lǐng)域概念一目了然:
- There are 5 rows 有5行
- There is one second row, 2 hour rows and 2 minute rows 一秒行,2小時(shí)行和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.
經(jīng)過一些挖掘,還可以使用其他一些概念,但是這些概念并不是立即顯而易見的。 這些行由可以點(diǎn)亮(或可能熄滅)的燈組成,并且點(diǎn)亮的次數(shù)表示時(shí)間。
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.
為了改善這一點(diǎn),我們可以將一些輔助函數(shù)中隱藏的細(xì)節(jié)(例如get_five_hours )放在文件頂部附近。 這帶來了類似以下的內(nèi)容(完整的代碼可在GitHub上找到 ),盡管缺點(diǎn)是它幾乎破壞了所有測(cè)試。 這樣的解決方案在GitHub上很少見,但確實(shí)存在。
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:
這改進(jìn)了現(xiàn)在可以一目了然的概念:
- There are 5 rows 有5行
- The seconds row is a special case 秒行是一種特殊情況
- There are 2 hour rows and 2 minute rows 有2小時(shí)行和2分鐘行
- The rows use different colour lights 行使用不同顏色的燈光
- The rows have a different number of lights 行有不同數(shù)量的燈
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.
這非常好,并且已經(jīng)比大多數(shù)解決方案更好。 但是,各行之間的相互關(guān)系還是有點(diǎn)神秘(有兩行顯示小時(shí)和分鐘,因此大概是鏈接在一起的)。 每個(gè)燈代表多少時(shí)間也并不明顯。
命名隱式概念 (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.
目前,某些概念(例如每盞燈所代表的時(shí)間)已隱含在代碼中。 將它們明確顯示并命名,迫使我們理解它們并將這種理解嵌入代碼中。
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.
為了使每個(gè)時(shí)間指示燈代表明確的量,現(xiàn)在看來似乎是明智的一傳time_per_light值row_lights 。 這意味著我們必須將lights_on的計(jì)算向下推到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).
這樣就可以很明顯地看到兩行:一行與時(shí)間值的商( \\ )有關(guān),另一行與余數(shù)/模數(shù)( % )有關(guān)。 如果看商數(shù)情況,我們會(huì)發(fā)現(xiàn)該操作的第二個(gè)參數(shù)是time_per_light ,在兩種情況下均為5(一種情況下為5小時(shí),另一種情況下為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.
現(xiàn)在,如果我們將注意力轉(zhuǎn)向其余情況,我們將意識(shí)到time_per_light總是單數(shù)(一小時(shí)或一分鐘),因?yàn)樗钛a(bǔ)了商情況中的空白。
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.
例如,五小時(shí)行可以表示0、5、10、15或20小時(shí),但中間沒有任何時(shí)間。 為了表示任何小時(shí),必須有另一行表示+ 1,+ 2,+ 3和+4。 這意味著該行必須正好有4個(gè)燈,并且每個(gè)燈必須代表1個(gè)小時(shí)。
This implies that the remainder case is dependent on the quotient one, which most people would describe as a parent / child relationship.
這意味著剩余的情況取決于商,大多數(shù)人將其描述為父母/子女關(guān)系。
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):
掌握了這些知識(shí)之后,我們現(xiàn)在可以為子余數(shù)行創(chuàng)建一個(gè)函數(shù),解決方案如下所示( 在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
快速瀏覽一下此代碼,現(xiàn)在可以發(fā)現(xiàn)幾乎所有領(lǐng)域的概念
- The first row represents the seconds and is a special case 第一行代表秒,是一種特殊情況
- On the second row each "R" light represents 5 hours 在第二行,每個(gè)“ R”燈代表5個(gè)小時(shí)
- The third row shows the remainder from the second 第三行顯示第二行的其余部分
- On the fourth row each "Y" light represents 5 hours 在第四行,每個(gè)“ Y”燈代表5個(gè)小時(shí)
- 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.
這需要一些思考,這將花費(fèi)我們一些時(shí)間/金錢。 但是,在執(zhí)行問題時(shí),我們加深了對(duì)問題的理解,最重要的是,我們將這些知識(shí)嵌入了代碼中。 這意味著下一個(gè)閱讀代碼的人將不必這樣做,這將節(jié)省一些時(shí)間/金錢。 由于我們花費(fèi)的代碼閱讀時(shí)間比編寫代碼的時(shí)間長(zhǎng)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.
嵌入這種理解也使將來的程序員更難犯錯(cuò)誤。 例如,在先前的示例中不存在父/子行的概念,很容易使它們不匹配。 現(xiàn)在可以清楚地看到該概念,并且大多數(shù)值都是為您確定的。 重構(gòu)以支持新的時(shí)鐘變體也更加容易,例如,第一個(gè)小時(shí)行中的燈表示6個(gè)小時(shí)。
你應(yīng)該走多遠(yuǎn)? (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.
我們可以做一些進(jìn)一步的事情。 例如, parent_time_per_light子行必須匹配time_per_light其父,并沒有什么強(qiáng)制執(zhí)行這一點(diǎn)。 父行的time_per_light和lights_in_row之間也存在關(guān)系,因此也不再?gòu)?qiáng)制執(zhí)行。
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.
但是,目前我們只需要支持一個(gè)時(shí)鐘變體,因此這些可能不值得。 當(dāng)需要對(duì)代碼進(jìn)行更改時(shí),我們應(yīng)該進(jìn)行重構(gòu),以使更改變得容易(這可能很困難),然后進(jìn)行輕松的更改。
結(jié)論 (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.
將領(lǐng)域概念嵌入代碼中需要思想和技巧,而TDD不一定能為您做到。 它比幼稚的解決方案花費(fèi)的時(shí)間更長(zhǎng),但是使代碼更易于理解,并且很可能在中期節(jié)省時(shí)間。 時(shí)間就是金錢,對(duì)于專業(yè)程序員來說,現(xiàn)在要花時(shí)間與以后節(jié)省時(shí)間之間找到合適的平衡也是一項(xiàng)重要技能。
翻譯自: https://www.freecodecamp.org/news/embedding-domain-concepts-in-code/
域 嵌入圖像顯示不出來
總結(jié)
以上是生活随笔為你收集整理的域 嵌入图像显示不出来_如何(以及为什么)将域概念嵌入代码中的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做梦梦到白发老太太怎么回事
- 下一篇: 蛮力写算法_蛮力算法解释