4 ms·
Abstractions are different to metaphors. You can have an abstraction with a name 'x' that you can use to send messages over an SMTP server. The metaphor could b
by crdoconnor 10y ago
Abstractions are different to metaphors. You can have an abstraction with a name 'x' that you can use to send messages over an SMTP server. The metaphor could be "mailer", "mailbox", "email sender", "postman" or many other different things with subtly different implications.
Moreover, the "basic library" creation step that you allude to the point where you decide where the borders between different modules of code lie. Creating those borders at the appropriate point - deciding the coupling - is arguably the most important part of refactoring and the part (I) have found hardest to clean up in legacy code. I am currently rewriting a library which in retrospect I now realize should have been two libraries.
"You cannot write a terse function with high coupling"
Oh, you absolutely can. In fact, after a certain point terseness tends to correlate with higher coupling. There is often a trade off to be made between coupling one block of code to another (e.g. introducing a dependency) and sacrificing terseness.
- js8 10y ago> Abstractions are different to metaphors. You can have an abstraction with a name 'x' that you can use to send messages over an SMTP server. How is that different from a function (or set of functions) that abstract the technicalities of sending messages over SMTP? I am not sure why specific metaphor is so helpful here. I don't think it helps in understanding the function, on the contrary. > Moreover, the "basic library" creation step that you allude to the point where you decide where the borders between different modules of code lie. Not quite. The important thing to understand is that I am not optimizing for size of a single program, but large set of different programs. The same thing that humans do. > There is often a trade off to be made between coupling one block of code to another (e.g. introducing a dependency) and sacrificing terseness. Well, I understand "high coupling" differently than you, then. For me, it means things like doing different unrelated things in a single function (so the result is that it's harder to reuse it). It doesn't mean that you cannot call other functions. I don't consider a function that avoids a library call, instead inlining the functionality, to be well-written. (If that's what you mean by the trade-off - maybe some example would help.)
- crdoconnor 10y ago>How is that different from a function (or set of functions) that abstract the technicalities of sending messages over SMTP? > >I am not sure why specific metaphor is so helpful here. I don't think it helps in understanding the function, on the contrary. It isn't a different function, but "send_email" is better than "send_message" which is in turn better than a function just called "x" which is shorter. In each case a different metaphor is used. x is a shorter method but code that uses names like that everywhere is NOT cleaner. It's horrible. >Not quite. The important thing to understand is that I am not optimizing for size of a single program, but large set of different programs. Optimizing purely for size will end up increasing coupling to an insane degree. I've seen this done by people who get religious about DRY. >Well, I understand "high coupling" differently than you, then. For me, it means things like doing different unrelated things in a single function (so the result is that it's harder to reuse it). It doesn't mean that you cannot call other functions. If you're using one function to call another you have coupled them. Coupling is not about what you can or cannot do it's about what is. Coherence (or rather, a lack thereof) is about doing different things in the same function (or class, file, project, etc.).
- js8 10y agoWell, I agree that naming is a problem, but let's put that aside for this discussion. However, I should have explained that I consider all identifiers to have the same length for the purpose of trying to make the representation of program "compact". So what matters is number of functions being called inside a function (in FP, even constants are considered a function). OK, I get your point about coupling. But I am not sure why you consider high coupling to be a bad thing, especially in case where you have an automated refactoring system. It seems to me that to "decrease coupling" you have to add nodes to dependency graph, and this increases overall complexity. Perhaps you could provide some example where high coupling (calling different functions from a single function) is bad, and how would you like to have it resolved. Update: Actually, with automated refactoring, you wouldn't have to modify any existing functions (except maybe to call your new functions). You would just write new functions that would incorporate the new functionality using perhaps the existing building blocks. Then the refactorer would sort out things in DRY manner, as needed. So you don't need to care if the code is easy to refactor, it just needs to be easy to read.