Comment by hinkley

Comment by hinkley 2 days ago

12 replies

The way to solve this is to split decisions from execution and that’s a notion I got from our old pal Bertrand Meyer.

    if (weShouldDoThis()) {
        doThis();
    }
It complements or is part of functional core imperative shell. All those checks being separate makes them easy to test, and if you care about complexity you can break out a function per clause in the check.
0cf8612b2e1e a day ago

Functions should decide or act, not both.

  • swat535 a day ago

    But if that’s all you have, then how does your system do anything ? You ultimately need to be able to decide and then act based in that decision somewhere..

    • turtleyacht a day ago

      One possibility is a file.py that is called by your framework. The interface could be something like

        def doth_match(*args):
          return True  # the predicate
      
        def doeth_thou(*args):
          # processing things
          return {}  # status object for example
      
      The framework loops and checks the first function; if true, then execute the second function. And then break or continue for other rule files (or objects).

      There could be multiple files rule1.py, rule2.py, etc that check and do different things.

      • gameman144 a day ago

        I think the parent's argument is that wherever in your framework you're calling `doth_match` and then `doeth_thou`, you have a single function that's both deciding and acting. There has to be a function in your program that's responsible for doing both.

        • hinkley 18 hours ago

          A function that asks a question with one function call and calls another based on the answer isn’t doing any work or asking any questions. It’s just glue code. And as long as it stays just glue code, that’s barely any of your code.

          Asking for absolutes is something journeymen developers need to grow out of.

          The principle of the excluded middle applies to Boolean logic and bits of set theory and belongs basically nowhere else in software development. But it’s a one trick pony that many like to ride into the ground.

  • const_cast 21 hours ago

    This just moves decisions from inside of functions to the call site. At which point, there's more that can go wrong, since you're calling a function much more than it's single definition.

btown a day ago

To add to this, a pattern that's really helpful here is: findThingWeShouldDoThisTo can both satisfy a condition and greatly simplify doThis if you can pass it the thing in question. It's read-only, testable, and readable. Highly recommend.

  • efitz a day ago

    This is not obvious to me. The whole point was to separate the conditionals from the actions.

    In your example, it’s not clear if/how much “should we do this” logic is in your function. If none, then great; you’ve implemented a find or lookup function and I agree those can be helpful.

    If there’s some logic, eg you have to iterate through a set or query a database to find all the things that meet the criteria for “should do this”, then that’s different than what the original commenter was saying.

    maybe: doThis( findAllMatchingThings( determineCriteriaForThingsToDoThisTo()))

    would be a good separation of concerns

    • hinkley a day ago

      let list = findHumansToKill();

      //list = [];

      killHumans(list);

      • [removed] a day ago
        [deleted]