5

I've just read the book called Clean Code. The author (Robert C. Martin) talks about a single responsibility that a function should have in a program. It should only do one thing.

Now, I would like to understand how is it now possible to reuse a code that does multiple things. Let's say I have a method called runTrafficAndCheckIfItPassed and it calls two methods inside of it: runTraffic and checkIfTrafficPassed.

Now let's say that in my software I need to run traffic and to check it's result in a lot of places in my software. sometimes I need to check that traffic has failed, and sometimes I need to check if it passed.

Why wouldn't it be right to call the runTrafficAndCheckIfItPassed function and why is it way better to call the functions inside separately?

As far as I see, if there will be a change in the runTraffic function, for example to receive another parameter, the change will be implemented in one place, only in runTrafficAndCheckIfItPassed, which we see will be easy to maintain. But if I will use the functions separately I will need to change it in any place. But the author says it's wrong. So do you have any examples or tips why it is considered wrong?

Here's how I used it:

runTrafficAndCheckIfItPassed(TCPTraffic):
   trafficResults=runTraffic(TCPTraffic)
   hasAllTrafficPassed=checkIfTrafficPassed(trafficResults)
   return hasAllTrafficPassed
Glorfindel
  • 3,137
  • 6
  • 25
  • 33
Azuk
  • 59
  • 3
  • It is very difficult to answer this question without some example method calls so we can see how these fictional methods are being used. – Greg Burghardt Feb 15 '19 at 12:37
  • well, its in theory. and it's in Perl and i don't want to scare everybody. i will at some pseudo code – Azuk Feb 15 '19 at 12:39
  • I don't think Perl will scare anyone here. – Greg Burghardt Feb 15 '19 at 12:42
  • added in python :) – Azuk Feb 15 '19 at 12:45
  • 2
    I would argue that there is no need to have a function which simply calls another two public functions with no added value or efficiency. A function can be called in multiple places in your code and *still* do one thing. If you need to create a runTrafficAndCheckIfItFailed function, you've defeated the purpose of trying to simplify and merge functions. – Neil Feb 15 '19 at 13:00
  • what do you mean by defeated the purpose of trying to simplify and merge functions? – Azuk Feb 15 '19 at 13:49
  • @GregBurghardt I've seen some pretty scary Perl – DaveG Feb 15 '19 at 14:00
  • In natural language terms, you code answers the question 'Did the Traffic Run Pass?' That is a single concept / responsibility. It is pretty normal for non-trivial processes to have multiple possible endstates (success, fail, blocked, pending, yada) and thus require some sort evaluation step. The question is whether it make sense to combine the run with the eval, and, again, that is pretty common. Super common in implementation (e.g., if (auditFaileded()) { raise exception(); } and similar constructions ) – Kristian H Feb 15 '19 at 16:12

2 Answers2

15

Though the name gives a different impression, the function runTrafficAndCheckIfItPassed does only "one thing" in the "clean code sense": it coordinates the calls to two other functions.

The operational code for those two actions included, however, is in runTraffic and checkIfTrafficPassed, which are two functions for which we can assume they "do one thing" as well, but on a lower level of abstraction.

To apply the "do one thing" metapher correctly, one needs to take different levels of abstraction into account. Things which may be seen as one operation on a higher level usually consist of lots of single commands, actions and steps on a lower level.

To make the different levels of abstraction more transparent, it is often a good a idea to give a function like runTrafficAndCheckIfItPassed a different name, one which summarizes the combined actions under one concise term. If you cannot come up with such a name, then alas, let the name as it is now, naming things is one of the toughest tasks in software development ;-)

You find a good example in this older SE post.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
  • so your saying that it is ok to use a `runTrafficAndCheckIfItPassed ` function and to add another one runTrafficAndCheckIfItFailed`? – Azuk Feb 15 '19 at 13:49
  • @Azuk: sure, why should that case be different? (It is actually hard to reason about artificial, contrived examples). – Doc Brown Feb 15 '19 at 14:11
  • it isn't its the same just with a validation, im just making sure :) – Azuk Feb 15 '19 at 14:16
  • @Azuk wouldn't failure be the logical inverse of passing? Why not `!runTrafficAndCheckIfItPassed()`? – cbojar Feb 16 '19 at 01:05
  • The ckeck if traffic fails also reports the ui about each traffic component, and returns the summery. #spaggethy – Azuk Feb 16 '19 at 09:12
4

Generally, anything with "and" in the name leaves a suspicion that it's violating the SRP. However, that sort of function could be renamed to something like "tryRunTraffic", with little change in meaning.

Functions named "try..." are often used to indicate that they will return a success or failure code, rather than throwing an exception if they fail. This is useful if failure is not an error.

Simon B
  • 9,167
  • 4
  • 26
  • 33