Hacker News new | ask | show | jobs
by deltasixeight 1777 days ago
Read the 2nd paragraph of my post you replied to. You talk about true modularity and it is addressed in my second paragraph. If you find these problems with your code then the code was Never modular in the first place.

Modular code involves writing code independent of context. One way of doing this is to wrap every expression in a pure functional context. Another way is to make every variable immutable.

> I could take any random 5 lines of a complex function and pull it out into another function in another file, but that doesn't guarantee that this was a smart thing to do in that particular scenario.

Doing this doesn't hurt. There's nothing stupid about it unless you coded everything in a way where it's NOT modular. Procedural programming is usually not modular because the results of a computation depend on the Order of the procedures. Immutable state is isomorphic to an expression so procedural code with immutable state solves the issue.

Let's say I need a function to add 3 numbers. I impliment it like this:

  addThree = func(x, y, z){ return addTwo(x, y) + z}
  addTwo = func(x, y) {return x + y}
You're saying addTwo is unecessary and pointless if it's not reused. I'm saying you can't predict the future, there may be a time where you need addTwo, but if you never need it, it doesn't really matter, you don't lose anything here. Modularity doesn't hurt the structure and organization of the code. It only effects qualitative aspects like how easy is it to interpret understand or read.
2 comments

"it doesn't really matter, you don't lose anything here"

Except you do. It's harder to understand and less readable; and in a real life rather than made up example, addTwo is in some other module entirely and has side effects that are completely invisible (in most languages) when just looking at addThree, making debugging and understanding WTF is going on far harder.

You mention "pure functional context", and yet this whole thread exists under a post about OOP, which is all about state management; it's no good trying to create toy examples that are side effect free to try and dismiss the points being made. Yes, of course pure code is fairly trivial to slice and dice, and the cost of doing so tends to be low (not zero, but low), but that's not really what is being talked about.

Otherwise you're kind of "no true Scotsman"ing this; "if you find these problems with your code than the code was never modular in the first place" - yeah, that's the point. Splitting code doesn't by definition make it more modular.

>Except you do. It's harder to understand and less readable; and in a real life rather than made up example, addTwo is in some other module entirely and has side effects that are completely invisible (in most languages) when just looking at addThree, making debugging and understanding WTF is going on far harder.

You don't lose anything from a hard structural standpoint. Readability and being harder to understand is an opinionated based metric. It can be influenced by how you even name a function. It is a soft metric therefore weaker than the hard one. Additionally I DO mention the qualitative opinionated cost of modularity several times in this thread. So I address it but it is definitively weaker because anyone can have an opposite opinion and say that "in my opinion modular code is more readable"

>You mention "pure functional context", and yet this whole thread exists under a post about OOP,

Did you read the article? The author of the article was not convinced by OOP, he never supported OOP and generally the entire article is critical of OOP. I would say my reply is highly relevant and that you didn't read the article.

>it's no good trying to create toy examples that are side effect free to try and dismiss the points being made.

The examples serve a purpose to illustrate my point not to illustrate a real world example. If you want a real world example look at the react + redux architecture. The gold standard model for all web UIs exactly do what I mention with state management. They completely separate State away from pure functions. The entire web generally follows this model abstracting state management away from even code. Web apps are stateless with the database handling the entire job of state management. Examples of this pattern are EVERYWHERE, the example I gave is a toy example to help you understand not to say "hey this is a real world application." I thought that was obvious, my fault for not being clear on that.

>yeah, that's the point. Splitting code doesn't by definition make it more modular.

Completely and utterly wrong. Splitting code by definition makes it more modular. See: https://en.wikipedia.org/wiki/Modularity

The definition from above says: "Broadly speaking, modularity is the degree to which a system's components may be separated and recombined, often with the benefit of flexibility and variety in use"

If you are "splitting" code then by definition you are separating code which was previously combined. By Definition it is more modular. You really can't argue this point. More likely what's going on here is you have your own personal fuzzy definition of modularity which you are unconciously combining with your opinionated view on what constitutes good code. I am using the english definition not some fuzzy notion of good code so I am definitively right.

Be more exact and formal with your terminology it will lead to much less misunderstandings.

From the Wikipedia link you provide - "modularity is the degree to which a system's components may be separated and recombined"

Lines of code != system's components.

It's why we don't split a 20 line function into twenty 2 line functions (where the first line is one of the original, and the second is the call to the next function), and no one would say that doing so has made the code more modular.

This is itself backed by the wikipedia link, 'In software design, modularity refers to a logical partitioning of the "software design" that allows complex software to be manageable for the purpose of implementation and maintenance. The logic of partitioning may be based on related functions, implementation considerations, data links, or other criteria'; what we have done by splitting up the code this way has not helped it be more manageable.

So no, by the definitions you yourself cited, splitting up the code does not translate to more modular code.

>Lines of code != system's components.

Did I say this? No. Does this have anything to do with the conversation? No.

>It's why we don't split a 20 line function into twenty 2 line functions (where the first line is one of the original, and the second is the call to the next function), and no one would say that doing so has made the code more modular.

You think of logic as procedural lines of instructions. Procedural lines of instructions are not modular. If you think like this, none of your code is ever truly really modular. All code should be writable in one line. You split into several lines ONLY for readability, but your core logic should easily be isomorphic to one line code.

If your code doesn't share this isomorphism then none of your code is modular.

Inevitably you have to eventually address the procedural nature of the world in your code. When this case arises you have to abstract this all away to the smallest section of your code as possible.

>what we have done by splitting up the code this way has not helped it be more manageable.

Modularity and Manageability ARE TWO different words with two different definitions.

Wikipedia in this case is just being dumb and fuzzy with it's definitions. Right above your cited link it has an alternative definition that is in direct conflict with the one you stated. Modularity in modular programming is different from modularity in software? Come on. This is stupid.

Let's not play pedantic games here. Modularity and Managability are different. We know this. No need to play games. Combining the two into one thing is a lack of coherence. Be coherent.

When you take one thing and split it into two things. The two things are modules and thus more modular than the one thing. That is simple intuitive and clear.

> Doing this doesn't hurt. There's nothing stupid about it unless you coded everything in a way where it's NOT modular.

It does. If I open up an arbitrary Ruby on Rails app for example, it is going to be easier to navigate for example a super fat model file than it is to navigate one that has been divided up into 10s of helpers and companion modules. There are similar scenarios in every other language. Extracting code and moving it somewhere else can truly be a death by a thousand cuts. My rule of thumb is if there aren't at least two places in the code that need to call My Extracted Thing (tm), then it shouldn't be extracted in the first place. If you're being DRY, it's OK to have a long class/file/method/function/module, and it's probably preferable to obfuscating your codebase and making it more difficult to navigate.

>Extracting code and moving it somewhere else can truly be a death by a thousand cuts.

This is not what I mean by modularity. Let me be more specific. The code CAN be seperated and it can be recombined without a structural code rewrite. That is what I mean by modularity. Actually dividing code up and organizing it among different files is an opinionated organization scheme and NOT what I'm talking about.

When you do extract code and move it anywhere it's not exactly "death" it's just harder to read. Structurally the code is still sound. You can meet the requirements without rewriting the code, it's just the code is more complex to understand.

The bad scenario I'm talking about here is when you can't extract code and you can't move it around. When your requirements necessitates logic to be moved around and you can't because code is too coupled with other code. That is more closer to literal death by one cut. You are technically unable to meet requirements with existing code.

The modular primitive that prevents this from happening is the immutable pure function. But it's not a one size fits all solution.

Exactly, and what I'm saying is probably over 50% of the time people modularize code, they aren't actually modularizing it in the good sense you are talking about, but in the bad sense where they are just placating the linter without putting any thought into it and calling it "modularizing".

I'm all for modular code and interfaces, but linting rules like "functions must be a maximum of 15 lines long" are stupid and lead to stupid code. That's what my OP was about.