DEV Community

Discussion on: A Hooks-vs-Classes Report Card

Collapse
 
sirseanofloxley profile image
Sean Allin Newell

I like what you've written here; I'd like to contest your assertion around the SRP and the 'golden function rule' though - and then I'll agree with your assertion too because I'm double minded like that 😅.

I've written some F# code, specifically with the Suave web framework. In that framework, it's idiomatic to use functions to compose a type called a WebPart to build up functionality of your app. The 'root' webpart would technically be the entire API/Webserver which is certainly 'not a pure function' that does one thing well. However, isn't main 'just' a function too? main (or index) can be written well by delegating and composing the app as it should do since its the conposition root, or
poorly if main triess to do far too much all at the top level.

So at some level, there are higher order functions whose responsibility is to compose smaller, purer functions.

Can't the same be said of react's functional components? Each component delegates to hooks and sub components. This is analgous to the web part type in my mind, and indeed static void main and composition roots.

That being said, your point is still very valid. Without really good names, coding discipline, or true functional programming and coherence (like Elm/PureScript/sub-set of F#), functions in JS can just become big fat classes. Heck, what is the responsibility of those IIFEs we had to write 'back in the day' that our bundlers are writing for us now?

Great food for thought! I'm gonna have to see if I can't name my components better to reflect their reaponsibilities.

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

...and then I'll agree with your assertion too because I'm double minded like that

I also wanted to harp on this (excellent) statement from you, because I believe it highlights a broader point that I'm trying to make in this post. (And indeed, I think this point permeates many of my other posts as well.)

Part of being a programmer is the mindset that a Given Set of Inputs/Logic X should always (or, ideally) result in a Given Output Y. In functional programming terms, we call this a pure function. Taken to a greater extreme, we tend to think that everything can ultimately be coalesced down to a Boolean.

I'm not "angry" about this mindset. I have it. Nearly every solid developer I've met also has it (at least, to some degree). But this mindset also leads to potentially harmful dictates in the development community.

Some "thought leader" comes to believe that a particular programming pattern is "bad" or "harmful" or a "code smell". They start writing think pieces about it. They start proselytizing about all the reasons why Pattern A is "wrong" and Pattern B is "right". Before you know it, people are writing additional libraries with the underlying intent of banishing Pattern A.

But everything in programming (or, in life) isn't always as simple as classes === FALSE or functions === TRUE. You can hold two thoughts. And if you're holding those thoughts, it doesn't necessarily mean that this is a problem to be solved. It's entirely possible that classes might, sometimes, be TRUE. And functions might, sometimes, be FALSE.

So... even though your lighthearted acknowledgment may seem (to some) like a throwaway comment, I think it illustrates the deeper knowledge that experienced devs can bring to the table when we decide to wade into the debates about whether Pattern X is "good" or "bad".

Collapse
 
bytebodger profile image
Adam Nathaniel Davis • Edited

Excellent feedback! And I totally agree with everything you've written.

My point isn't to say, "Functional components don't sound like functions - so you shouldn't use functional components." My point is just to illustrate the contradictions when a Functional Programming Acolyte (and Certified Class-Hater) tries to yell you down because those horrible, nasty, unconscionable class-based components don't comply with their "pure" vision for functional programming in JavaScript.

Even in the best OO codebases, there are some classes that look-and-feel a whole lot like... functions. (static void main is an excellent example of this.) And even in the best FP codebases, there are some functions that look-and-feel a whole lot like... classes.

When we come across those scenarios, I think it's absolutely healthy to run the "coding bromides" through our head and say, "Hmm... Have I really architected this application properly??" But I know full-well that, sometimes, as an experienced developer, you will run that "check" and come to the conclusion that, "Yes... This really is the proper way to go about it."

One of the first steps in learning to program is to learn "the rules" - whatever those "rules" may be for the particular flavor of tech in which you're building solutions. The "rules" are there for a purpose - and generally speaking, they're usually quite helpful.

But the process of becoming a well-experienced programmer also entails learning when it's appropriate to break those "rules". For example, I've written-and-deployed individual functions that contained hundreds of lines of code. Normally, that's a "code smell". But there are absolutely some times when it's 100% appropriate.

This often comes to mind when I'm writing/demonstrating a React class-based component and some kid (sorry if that sounds dismissive - but it's often quite TRUE) says to me, "Dooood... You shouldn't be writing classes in JavaScript." And I gotta admit that, in those scenarios, my inner (snarky-as-hell) "developer voice" is thinking, "Yeah... How bout you just stay in your lane, kid???"