Live data from Hacker News

The Most Important Code Isn't Code

zachholman.com

71–80 of 83 posts

Re: The Most Important Code Isn't Code

#71
post #68
post #66

Earlier quoted context omitted.

I was asking about the "non-linear" part.

Perhaps poor choice of phrase. It is my feeling that moving complexity out of methods and possibly having it in the interrelationships between methods results in a net gain in understandability. Perhaps asymmetric would have been a better word?

It codifies the relationships between the parts - but also adds ceremony (the call, the method definition, the arguments). Whether this is a net gain depends. Probably the key is whether it feels like a conceptually distinct component - a theory or abstraction that you can build on. This is probably true even if it isn't reused (but typically coincides with it).

There was some "non-linearity": the interaction between parts increases (roughly) with the square of the number of parts: 4 parts have 16 directed interactions. Combinatorial explosion is a more accurate measure. If you can separate the parts into modules, that interact with only the caller, then the complexity increases linearly (but if many methods need to interact, then it's as if you wrapped all the cables up in one tie, and forced them all to go through the "main" method - not actually an improvement. However, it's rare for everything to interact with everything, and even then, it may be clearer to codify it somehow).

I also wanted to say that while proving correctness is important, the organization that is best for proving is not always the same organization that is best for human clarity (sometimes they are). It depends on what your goal is. Proving absolute correctness is not important for most programs (all software has bugs; bugfixes are common) - to sacrifice human clarity for correctness is usually not the optimal trade-off.

Re: The Most Important Code Isn't Code

#72
post #70
post #65

Earlier quoted context omitted.

With respect to specificity of languages, Uncle Bob in "Clean Code" also advocates for extremely short methods in C#, on the same order as what my friend uses. Different languages do give rise to different ideas, but I think that what matters more is how that language thinks about Objects and Classes, as one example. For example, in Smalltalk, methods are messages. In C++ and other contemporaneous langages, nobody ta…

I like your phrase "how that language thinks". C# doesn't think like Smalltalk, so it's a mistake to write C# code as if it does. "Uncle" Bob is not a reliable source here. It's been a while since I've read any of PG's code, so the following may be off-base, but I don't think he has any heritage in the OO-short-method school. In his books, at least, he's usually looking for functions that work like language construct…

Well, reading between the lines, PG thinks very little of OO.

Uncle Bob's book Clean Code demonstrates very small methods in C#, and it does go in the direction of looking for language constructs. It is just harder to get there in a non-lisp language.

Regarding OO in general, I am a former proponent of OO--in fact taught (delivered might be a more accurate description) the Rational Unified approach several times, brought OO thinking to several business units. Reading PG and getting heavily into Lisp took me away from that.

I think we disagree slightly on "whole program complexity" and the increasing complexity of shifting it around.

Re: The Most Important Code Isn't Code

#74
post #69
post #61

Earlier quoted context omitted.

I think one key thing to keep in mind is that it is better to chose a style that is more likely to obviously have no errors, rather than one that has no obvious errors. (Wirth?) With longer methods, it becomes more strenuous to say that it obviously has no errors. And in It seems that having many small methods trades one complexity for another. is not a fair representation, as the implied relationship is not linear.

With longer methods, it becomes more strenuous to say that it obviously has no errors. I disagree. The proper comparison is not between one long function and one short one (that's a no-brainer), it's between a long function and a corresponding set of short functions plus all their interactions . Posing the comparison correctly makes the complexity tradeoff look very different. I'm not saying it's obvious, but the pri…

I like how you qualify program length as a fallible measure (they're more guidelines). Similar to your story of overdoing tiny classes and short methods, due to a belief from programmers you admired, I once dogmatically followed this as a rule, always extracting code than was used more than once, and only doing so then. I think that's a standard learning stage, where you learn something, over-apply it, then learn distinctions for when it is appropriate and when not.

Optimizing for length is only one criteria - optimizing for clarity is more important (strange observation: in writing, redundancy enhances communication); optimizing for flexibility/change is another. I like the idea of just expressing your current understanding, very simply - not weighed with suspect prophecies. Change it as your understanding improves; as you reuse it. Brooks observed that having a spec and different implementations leads to a more robust spec; and there's an idea of not generalizing code until after you're implemented it three times, for different purposes. This is the opposite of architecture astronautics - being grounded in actual instances of concrete experience.

So, I give up a simple, single theory of how to code, and I'm lost - which is perhaps an accurate appraisal of our current understanding of programming. Only the actual details of a problem guide you.

From what you said elsewhere, I think the simple key is to keep focusing on the problem, not the program. My old supervisor said I was over-concerned with theory. "Look at the data!" he admonished me.

Re: The Most Important Code Isn't Code

#76
post #5

The documentation example for the multiplex() function seems like massive overkill to me. The most informative part of the documentation comment is the line that starts with "Duplicate some text..." So why not just name the function duplicate_text() and be done with it? The arguments could be documented similarly, by naming them "text" and "num_duplications". I don't think I'd need an 11 line comment to tell me what…

That was pulled from the TomDoc spec- it was designed to demonstrate TomDoc, not the code. Having an overly complicated implementation makes explaining the documentation side of things a bit more difficult. :)

But "TomDoc is a mentality". What the heck is "TomDoc" anyway? The author says it's a mentality, but since when do mentalities come with specs? As far as I can tell, it's an example of a function spec that's so badly written that it needs a huge comment to explain it. Lousy name, lousy parameter names, no statement of what it returns, no actual return, etc. Maybe the author just needs a language that declares returns and some practice at naming variables/functions?

Re: The Most Important Code Isn't Code

#77
post #58
post #50

Earlier quoted context omitted.

What do you think of short methods?

For fun, I'm going to write my thoughts before reading what you said about it elsewhere in the thread. What do you think of short methods? I'm skeptical of them. I think it's a mistake to try to make functions short for the sake of making them short. It's a mistake because adding a new function also adds complexity (i.e. more code, plus opacity between the calling and called) - not a lot, but greater than zero - so i…

The empirical studies you're mentioning were of FORTRAN functions, I think from a linear algebra library. They may not generalize.

My thought is that short methods make your code more flexible — that is, you can compose the pieces of it in more ways, so the next bit of code you write without modifying the existing code can be shorter — at the cost of comprehensibility and verifiability. It's no surprise that this value came out of the Smalltalk camp, because Smalltalk (and OO in general, but especially Smalltalk) is optimized for flexibility at the expense of verifiability.

When you factor out a method, you're making the code you pulled it out of easier to read — except when the reader needed to know the details of what you pulled out. But you're making the code you pulled out harder to read, because the reader no longer knows that it's called in only one place, what the state of the system is when it's called, what the values of its arguments are, and what its results are used for.

There was once a school of thought that it's easier to read a piece of code if it's laid out to visually show the tree structure of its loops and conditionals, and if it uses loops and conditionals instead of gotos. I think this is not the only virtue that code can possess that helps its readability, but it is a real virtue. Factoring out more methods reduces this virtue, so it needs to be repaid by some other virtue, which I think is what you're saying.

I have several different heuristics for when it's good to factor out methods or functions, but I think they aren't good enough, because I always end up with some functions that are kind of a mess.

Re: The Most Important Code Isn't Code

#78
post #63
post #58

Earlier quoted context omitted.

For fun, I'm going to write my thoughts before reading what you said about it elsewhere in the thread. What do you think of short methods? I'm skeptical of them. I think it's a mistake to try to make functions short for the sake of making them short. It's a mistake because adding a new function also adds complexity (i.e. more code, plus opacity between the calling and called) - not a lot, but greater than zero - so i…

> After you do that for a while, your program stops evolving as an expression of the problem being solved, because you've built it out of primitives that refer only to the internals of the program rather than to concepts drawn from the problem space. Wow, nicely said. You also remind me of the problem of removing "accidental duplication", or overfitting: this is when you factor out common code, but it turns out later…

http://lists.canonical.org/pipermail/kragen-hacks/2011-June/... has an example of this "eliminating accidental duplication", I think. The first version of the program treats "note handlers", the end-users of the "notes" it distributes, as simply one kind of peer. But the later versions have a more complicated protocol between peers, and so they reify "note handlers" as a separate kind of thing. Similarly, the first two versions invoke the user-visible .publish() method when they receive a note from a peer, but the third version has factored out a new .got_note() method to factor out the duplication between the two code paths.

As I was writing this code, I was thinking about Uncle Bob's extremist viewpoint on short methods in Clean Code, and I tried it out. In the end, I inlined all the methods that had only a single caller, except for the handle_message family. I think the code came out exceptionally clear and simple, but Uncle Bob would not be happy with it.

Re: The Most Important Code Isn't Code

#79
post #65
post #60

Earlier quoted context omitted.

Hell, this reminds me of another thing I want to say. The word that leaps out here is "smalltalk". The short-method school of OO came from the Smalltalk world. It has since been extrapolated to other languages. I am skeptical of this extrapolation. It's fashionable to say language choice doesn't matter that much, but I think language choice has a powerful effect in conditioning how one thinks about one's program. Dif…

With respect to specificity of languages, Uncle Bob in "Clean Code" also advocates for extremely short methods in C#, on the same order as what my friend uses. Different languages do give rise to different ideas, but I think that what matters more is how that language thinks about Objects and Classes, as one example. For example, in Smalltalk, methods are messages. In C++ and other contemporaneous langages, nobody ta…

You may be interested in my comment above about my experience: http://news.ycombinator.com/item?id=2648279

Re: The Most Important Code Isn't Code

#80

Earlier quoted context omitted.

You mean to say that a test like the following wouldn't be better than the comment for multiplex()? unless multiplex('Tom', 4) == 'TomTomTomTom' raise TestError( 'multiplex() failed' ) end Not only does that test communicate the exact same thing as the documentation comment, it is guaranteed to be correct and not out-of-date (assuming it's run as part of a test suite), whereas the comment can easily be wrong.

It doesn't communicate the same thing. It communicates one example, leaving the reader to guess how to generalize it. Examples are good, testing is good; and specs are good too. It's currently popular to valorize the first two at the expense of the third, but I think this was an overreaction to the older dogma.

Even the Agile Manifesto itself explicitly says that its signatories value comprehensive documentation. They just value working software even more.
Post reply on HN