Live data from Hacker News

Solid Relevance

blog.cleancoder.com

51–55 of 55 posts

Re: Solid Relevance

#51

Earlier quoted context omitted.

"It is useless to have a conversation with those who will not listen." Neither of us are listening, because we're both sure we're right. So I'm out. You get the last word, if you want.

Don't be stupid. I'm listening to you. I'm actually responding to you. You say theory is different from the real world so I present you with a real world solution and examples of how it works with embedded specifically. Your job should you choose to continue is to use other real world examples to counter my arguments. That's all, if you convince me it's done, If i convince you it's also done. Until then leaving the d…

Fine.

  void handleEvent1() {
    if (currentState == state1) {
      currentState = state2;
      setHardwareState2();
    } else {
      currentState = state3();
      setHardwareState3();
    }
  }
You can move state to the boundary, and IO to the boundary, and then... what's left? It was all boundary.

A bit more realistically, here's an automobile cruise control that uses the same button for "reduce set speed" and "set the speed". (Don't blame me, I've had more than one car with that exact setup).

  void buttonXEvent() {
    if (cruiseControlEnabled) {
      if (cruiseSpeedSet) {
        cruiseSpeed--;
      } else {
         cruiseSpeed = currentSpeed;
         cruiseSpeedSet = true;
      }
      writeSpeedToEngineComputer(currentCruiseSpeed);
    }  // else do nothing
  }
How would you write this in your approach?

Re: Solid Relevance

#52

Earlier quoted context omitted.

Don't be stupid. I'm listening to you. I'm actually responding to you. You say theory is different from the real world so I present you with a real world solution and examples of how it works with embedded specifically. Your job should you choose to continue is to use other real world examples to counter my arguments. That's all, if you convince me it's done, If i convince you it's also done. Until then leaving the d…

Fine. void handleEvent1() { if (currentState == state1) { currentState = state2; setHardwareState2(); } else { currentState = state3(); setHardwareState3(); } } You can move state to the boundary, and IO to the boundary, and then... what's left? It was all boundary. A bit more realistically, here's an automobile cruise control that uses the same button for "reduce set speed" and "set the speed". (Don't blame me, I've…

  //combinators
  CruiseSpeed = int

  CruiseSpeed getNextCruiseSpeed(bool cruiseControl, bool cruiseSpeedSet, int cruiseSpeed, int currentSpeed) {
      if cruiseControl && cruiseSpeedSet
         return cruiseSpeed - 1
      elif cruisControl && !cruiseSpeedSet
         return currentSpeed
      else
         return cruiseSpeed
  }

  bool getNextCruiseSpeedSet(bool cruiseControl, bool cruiseSpeedSet){
      return cruiseControl && !cruiseSpeedSet ? true : cruiseSpeedSet
  }

  //IO functions
  void getCurrentSpeed()
  bool isCruiseSpeedSet()
  void setCruisSpeedSet(bool cruiseSpeedSet)
  void writeSpeedToEngineComputer(CruiseSpeed x)
  void handleButtonPress(bool cruiseControl, bool cruiseSpeedSet, int cruiseSpeed, int currentSpeed){
     speed = getNextCruiseSpeed(cruiseControl, cruiseSpeedSet, cruiseSpeed, currentSpeed)
     cruiseSpeedSet = getNextCruiseSpeedSet(cruiseControl, cruiseSpeedSet)
     writeSpeedToEngineComputer(speed)
     setCruiseSpeedSet(cruiseSpeedSet)
  }
Your example uses free variables extensively. It means that all your logic cannot move outside of the context of the free variable which means they cannot be reused. Even IO functions should not use external context.

Combinators can be reused everywhere.

Re: Solid Relevance

#53

Earlier quoted context omitted.

Fine. void handleEvent1() { if (currentState == state1) { currentState = state2; setHardwareState2(); } else { currentState = state3(); setHardwareState3(); } } You can move state to the boundary, and IO to the boundary, and then... what's left? It was all boundary. A bit more realistically, here's an automobile cruise control that uses the same button for "reduce set speed" and "set the speed". (Don't blame me, I've…

//combinators CruiseSpeed = int CruiseSpeed getNextCruiseSpeed(bool cruiseControl, bool cruiseSpeedSet, int cruiseSpeed, int currentSpeed) { if cruiseControl && cruiseSpeedSet return cruiseSpeed - 1 elif cruisControl && !cruiseSpeedSet return currentSpeed else return cruiseSpeed } bool getNextCruiseSpeedSet(bool cruiseControl, bool cruiseSpeedSet){ return cruiseControl && !cruiseSpeedSet ? true : cruiseSpeedSet } //I…

I see no respect in which your solution is superior.

By the time you implement getCurrentSpeed(), etc., you're going to have a fair amount more code than me. (writeSpeedToEngineComputer() doesn't count, because I need to implement that also.)

Your reason for doing so is, I think, in your last two paragraphs. But this isn't particularly reusable code - I'm not going to use getNextCruiseSpeed() or handleButtonPress() in the windshield wiper controller. It's pretty much tied to the specific use. (There may be a handleButtonPress() in the windshield wiper controller, but I can't reuse this one.)

So you offer me something that is more verbose, based on a benefit that I can't actually benefit from.

(I presume that getCurrentSpeed() returning void was just because of quick typing.)

Re: Solid Relevance

#54

Earlier quoted context omitted.

//combinators CruiseSpeed = int CruiseSpeed getNextCruiseSpeed(bool cruiseControl, bool cruiseSpeedSet, int cruiseSpeed, int currentSpeed) { if cruiseControl && cruiseSpeedSet return cruiseSpeed - 1 elif cruisControl && !cruiseSpeedSet return currentSpeed else return cruiseSpeed } bool getNextCruiseSpeedSet(bool cruiseControl, bool cruiseSpeedSet){ return cruiseControl && !cruiseSpeedSet ? true : cruiseSpeedSet } //I…

I see no respect in which your solution is superior. By the time you implement getCurrentSpeed(), etc., you're going to have a fair amount more code than me. (writeSpeedToEngineComputer() doesn't count, because I need to implement that also.) Your reason for doing so is, I think, in your last two paragraphs. But this isn't particularly reusable code - I'm not going to use getNextCruiseSpeed() or handleButtonPress() i…

The point was to prove that I can pull the combinator out of your unsegregated code and moularize IO away from logic.

The other point of this was to improve code modularity in every corner of your code. Why is this good? If all your logic can be shifted around then that means that you can reuse code to anticipate future changes.

The most insidious form of technical debt is unanticipated technical debt. You encounter it when a new requirement makes you realize that you can't reuse segments of your code. You realize that you grouped things together incorrectly. You failed to have the foresight to make your code more modular.

It's a problem people think they can solve in hindsight but they can't in reality because they cannot predict the future so they will inevitably group code incorrectly. And therein lies the problem: grouping. Don't group your code. Make all your logic modular and just organize your code with superficial schemes like namespaces.

The problem with OOP is that the very nature of an object is a grouping. OOP is all about grouping the code around shared mutable variables within a context. You are forced to assume a grouping and you may be right in some cases (like cruisecontrol) but you will inevitably be mistaken in many other cases. This "mistake" is the origin of the most insidious form of technical debt.

The other problem with OOP is that they think that this style of programming is modular. They have no idea how un-modular it is. So they use it extensively with patterns thinking they're improving modularity.

The most modular primitive is the combinator. That is why to prevent technical debt as much as possible, the key is to move as much code as possible into the combinators.

Re: Solid Relevance

#55
post #2

There's 2 approaches to programming: - make it easy to extend (lets's call it SOLID in this context) - make it easy to rewrite (let's call it KISS) OO developers think that the first approach is The Only Way but both can be right, especially with high-level declarative languages and with tasks small enough (relative to the language expressive power). SOLID makes it easier to modify programs (in predetermined directio…

> There's 2 approaches to programming

Written like a programmer! And therein lies the bug. Unless SOLID is the negation of KISS, the world tends to have more than two options. How about DRY, for instance? Off by at least one.

Post reply on HN