What is an acid test for “the same level of abstraction” when writing compound functions / methods?

Context: I need to explain "composed methods" to a group of mixed experience.

I think I first heard about it while reading Beck Multtack's recommendations. I personally did not have too many problems writing such methods, but in the local code desert I saw many cases where the lack of linking methods created illegible Blobs ... and I was in the minority. So I take them through CleanCode where this one reappeared.

The package is pretty simple.

"Functions should be short, do one thing well, and disclosure of intention. Every step in the body of a method should be at the same level of abstraction."

That I am struggling with checking for "the same level of abstraction" ... namely: forgiving a pun is a bit abstract for beginners.

My current explanation will be like SICP wishful thinking . (Imagine the perfect set of steps, and then worry about implementation / do it. ").

Does anyone have a better set of rules / acid test to evaluate your decisions when writing folded methods?

+6
source share
3 answers

The same level of abstraction - examples:

void DailyChores() { Dust(); Hoover(); MopKitchenFloor(); AddDirtyClothesToWashingMachine(); PlaceDetergentInWashingMachine(); CloseWashingMachineDoor(); StartWashingMachine(); Relax(); } 

Hopefully, it should be clear that the washing saga would be better extracted into a separate method permitted by WashDirtyLaundry ();

Perhaps MopKitchenFloor should also be in a separate method called CleanKitchen (), since it is likely that you will want to expand it in the future by including WashPots (), DefrostFridge (), etc.

So the best way is this:

  void DailyChores() { Dust(); Hoover(); CleanKitchen(CleaningLevel.Daily); WashDirtyClothes(); Relax(); } void WashDirtyClothes() { AddDirtyClothesToWashingMachine(); PlaceDetergentInWashingMachine(); CloseWashingMachineDoor(); StartWashingMachine(); } void CleanKitchen(CleaningLevel level) { MopKitchenFloor(); WashPots(); if(level == CleaningLevel.Monthly) { DefrostFridge(); } } enum CleaningLevel { Daily, Weekly, Monthly } 

In terms of “rules”, apply to the code without following this principle:

1) Can you describe what the method does in one sentence without any unions (for example, "and")? If you don’t split it until you can. For example, in the example, I have AddDirtyClothesToWashingMachine () and PlaceDetergentInWashingMachine () as separate methods - this is correct - so that the code for these two separate tasks inside the same method would be incorrect - however, see Rule 2.

2) Can you combine the calls of similar methods together into a higher-level method, which can be described in one sentence. In this example, all methods related to washing clothes are grouped into one WashDirtyClothes () method. Or, subject to rule 1, the AddDirtyClothesToWashingMachine () and PlaceDetergentInWashingMachine () methods can be called from the same AddStuffToWashingMachine () method:

  void AddStuffToWashingMachine() { AddDirthClothesToWashingMachine(); PlaceDetergentInWashingMachine(); } 

3) Do you have loops with more than a simple statement inside the loop? Any loop behavior should be a separate method. The same goes for switch or if, then else statements.

Hope this helps

+12
source

I take the acid test to mean that you need some specific rules that will help bring the abstract concept in question. Like in the section "You may have mixed levels of abstraction, if ..."

You may have mixed levels of abstraction if ...

  • you have a variable in a function that is used only for part of the function.
  • you have several loops in a function.
  • You have several if statements whose conditions are independent of each other.

I hope others add above ...

+5
source

EDIT: Warning - Long answer from self-taught ahead.,.

In my very humble opinion (I am GENERAL TRAINING here) it seems that BonyT and Daniel T. are on the right track. A part that may not be here is part of the design. Although it is safe to say that refactoring / compilation will always be a necessity, can it be just as safe to say that the proper design (ESPECIALLY with beginners!) Would be the first, second and third steps for properly compiled code?

While I get what you ask for (test / test suite for compiling code), I think that BonyT applies the earliest of these tests during the "pseudo-code" part of the design process, isn't it?

Obviously, in the early stages of project planning, strong design and experienced coders will sniff out the obvious places ripe for composition. As the work progresses and the team begins to fill these source code stubs with the body, some slightly dumber outer members inevitably arise. The BonyT example shows these first two steps quite well.

I think there comes a moment when experience comes and a finely tuned "nose" for the smell of code - in other words, a part that you may not be able to learn directly. However, that is where Daniel T's answer comes in — although it is not possible to develop specific “tests” such as ACIDs for the right composition, methods such as Daniel can be used to find potential smelly code. Discover the "clues" if you want, this should at least trigger further investigation.

If someone is not sure that things are made up to the mark, it might make sense to work through a certain function and try to describe in stages what happens in simple single sentences without conjunctions. This is probably the most basic ACID type test that can be performed. Not to mention that by default this process will correctly document the code.,.

In response to BonyT, you mean that its fragments of the pseudocode / method make the next step obvious: I'm sure that if someone goes through the function and describes things step by step, it often turns out that in fact the next step obviously follows at one level of detail or belongs in another place. Although there will obviously be cases (many with complex code) where things are not so neat, I suggest that this only happens with experience (and possibly with genetics!), Again, things that you cannot teach directly . At this point, you need to study the problem area and determine the solution that best matches the domain (and also be prepared to change it along the way). Once again, correctly documenting the “intermediate” cases with short, simple statements (and a narrative describing solutions in gray areas) will help the poor maintenance guy in the future.

I understand that I did not offer anything new here, but what I had to say was longer than the comment would allow!

0
source

Source: https://habr.com/ru/post/890128/


All Articles