Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Here are some comments in no specific order:

* A sample of 9 developers, especially all working for the same company (in similar conditions) isn't much... but this seems to be a sore spot for most research on software development: very small, bordering on unrepresentative samples. Very hard to control for bias. Very hard to establish whether experiment subjects even have the relevant knowledge.

* I would very much prefer if code quality wasn't about people's feelings. There's nothing wrong with people's feelings... except I want a metric. It seems like the authors either don't believe it's possible to capture code quality "impartially" or that we are long way away from being able to do so.

* In the end of the day, the research behind the article doesn't have "action items". Suppose the reader didn't know about the complexities of measuring quality -- then they would've learned how hard it is. But the article doesn't as much as suggest what needs to be done to measure the quality (better). It's hard to fault the authors for not suggesting anything in this regard, and by their own admission, the metrics that they've found so far are kind of a snake oil... But, I really want a metric. That's why others keep pumping that snake oil.

Anyways, I still find the article useful in case anyone needs a brief explanation of the difficulties of assessing software quality.




Well, here's something I could extract from it, and maybe this can even be automated:

Distance between variable declaration and its use. But, oh, distances aren't simple either:

LoCs seem like a reasonable unit to count the distance between use and declaration, but are all LoCs equal? Should the metric penalize less for having long JavaDoc-style comments (which a lot of editors can simply collapse?) What about empty lines? -- seems even more contentious. Penalizing for lines of code regardless of contents of those lines will probably discourage programmers from adding empty lines even when they might make things better. Perhaps a better unit of measurement should be "statements"?

Now, why would using variables deep inside nested blocks be equivalent to using them same distance away but inside the same block? I'd say that probably declaring all your loop variables outside of the outermost loop sounds like a crime to me. Sure, the nesting level should be accounted for.

What do we do with class variables / struct fields though? Someone who wants to game the metric can simply decide that instead of using variables they'd store everything as a struct field. But, if we treat struct fields as variables... ouch, structs are meant to "transfer" bunches of variables from place to place, so, they will definitely score worse than function-local variables... How'd I find good ratio to balance struct fields against the variables? How'd measuring distance in LoCs or instructions coexist with mentions in different files, different directories even? What if it's like a define? Especially a popular one, like "TRUE" in C? -- That variable would pull out such a huge score...

----

I don't think these questions are impossible to answer. But I cannot even imagine the research plan to try to come up with some concrete numbers, ratios, functions to make this thing work...


Wow, that's a good list. I agree with all of those, and am bookmarking this to show to others.

On the subject of deep modules, as also recommended by John Ousterhout, I also enjoy a side effect of this approach: flatter dependency trees (internal dependencies). If you have deeper modules, you stop needing 10, 20 levels of modules to accomplish things. Not needing this makes it easier to debug and understand the big picture. IMO, "big picture code readability" is something of an afterthought. Things like Clean Code only care about the "small picture", individual classes and methods. Things that are rarely a problem in practice IMO.

Flatter hierarchies also reduces the number of things to maintain/understand: in the frontend, for example, a flat component hierarchy removes the need for components far away in the hierarchy to communicate, so no need for Redux (also no prop-drilling). It also makes things like DI containers not strictly necessary, as you can easily do it manually, if you have fewer layers.

Another important thing I realized is flatter hierarchies allow making that dependency graph closer to a tree, rather than a cyclic graph. This reduces cross-cutting concerns and minimizes incidences of "surprise code" that are often super deep into the dependency tree and a common source of bugs.

All IMO and IME, of course. But I'm curious if you also share my experience.


> If you have deeper modules, you stop needing 10, 20 levels of modules to accomplish things.

I'm a big fan of being able to read stack traces without scrolling, so my rules of thumb are to remove layers that pass data around without either providing a substantial abstraction or doing some computation with it (avoid ravioli code), and to collapse layers that were all doing the same sort of thing to the data, each a little bit at a time (avoid salami code).

My bet is that shallow modules originate via Conway's Law, then get cargo culted.


Every layer of indirection needs to earn its keep. I hate working in codebases which are full of indirection without abstraction, you spend so long hunting for the bit of code that actually _does_ something.


> Every layer of indirection needs to earn its keep.

So much this. One of the things I absolutely hate seeing are the use of interfaces with a single concrete implementation.

context matters, it makes sense if you're authoring a library, it can make sense if you're working in something overly dynamic such as Ruby, Python, et al, but in a language like C#, Java, C++, et al, the compiler will assist you if you ever find yourself needing a second concrete implementation and most likely if you DO end up needing that second implementation, the interface is going to change anyway.


Pretty good but regurgitated design patters overall, I'm not impressed. Moreover I personally find the part about "Don’t waste vertical space" too far gone, it would be better to switch to a more terse language like APL or derivative if wasted space is the impediment it's made out to be here.


> Pretty good but regurgitated design patters overall, I'm not impressed.

I wrote "Nothing new of course." in the blog post itself, I am quite aware that it's a regurgitation of old stuff. Still, some of that old stuff is still being controversial, so I quite like giving it some theoretical backing.

> personally find the part about "Don’t waste vertical space" too far gone

Here's code I personally saw on the job, and it was mandatory, and the guy in charge of the silly rule that made it mandatory refused to change the rule, even though he admitted to my face the rule was silly:

  /**
   * Get the foo
   *
   * @return the foo
   */
  int getFoo()

  /**
   * Set the foo
   *
   * @foo: the new foo
   */
  void setFoo(int foo);
For something like 15 or more attributes, and this pattern was repeated across dozens of classes that I could see, and likely dozens that I didn't. Exactly like this, with comments that add zero information. And the rare times that it did, I kept missing it because it was drowned in a see of useless comments.

Sometimes the code is too far gone.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: