10 ms·
The Shapes of Code
- l0b0 7y agoHandy patterns, which could probably fairly easily be implemented as a high-level linter.
- luckycharms810 7y agoWhile the patterns themselves are interesting, the idea that all code must be rearranged in to smaller functions to be “refactored” seems a little juvenile.
- CoolGuySteve 7y agoIt seems antithetical to the intent of "Goto considered harmful": > My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible. While Dijkstra later talks about using procedures to index into the call stack, needlessly adding to the depth of the callstack for single use functions seems excessive. With this logic, I actually think "The paragraphs with headers" is the way to go since as TFA states: "You know that the algorithm operates in steps, and you know where the steps are located in code." http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html http://www.u.arizona.edu/~rubinson/copyright_violations/Go_T...
- makapuf 7y agoFunctions can be inlined by the compiler if it thinks it's an issue. I think it's rather a question of readability : sometimes if a process involves a long series of step I like to be able to read them linearly rather than jumping back and forth to sub steps. I can read just the headers if they're cleanly organized by cleanly separated paragraphs (with braces if needed to indicate separate scopes and no leaking variables between paragraphs).
- hinkley 7y agoThere’s an exercise for creative writing that my lit major friend told me about. You take everything you’ve written and cut it up into sentences. You just push the sentences around until something clicks and you figure out how to write your way out of the “stuckness”. Refactoring has rediscovered this trick, among others.
- 0x445442 7y agoAnother similarity to creative writing is this; you're not done when there's nothing left to add, you're done when there's nothing left to remove.
- rgoulter 7y agoI can agree "code should be in small functions" by itself is a bad guideline. I think it's suggested due to other principles around making code easier to read / use. It'd be better to ask if the code is more complex than it needs to be. I liked the terms John Ousterhout uses. For some module of a program (e.g. a method, class, package, etc.), it has an interface and an implementation. The interface is "what you need to know to use the module", the implementation is "how it's done". Complexity comes from dependencies (e.g. more interfaces you need to know about), and from obscurity (e.g. things you need to know about, which aren't obvious from the interfaces given). In some cases, many small methods would be an increase in complexity overall. In some cases, one big method may be an increase in complexity.
- hinkley 7y agoIn most cases one big method is an increase of complexity (and others will add to it over time). Large methods are usually a failure of imagination, like bad and rambling prose. Code is a set of instructions for the computer, and for the next person who has to maintain it (“ Programs are meant to be read by humans and only incidentally for computers to execute.”) Cooking instructions are split into steps. Assembly instructions are split into steps. LEGO instructions are split into steps. When drawing instructions aren’t split into steps the Internet turns them into a cultural phenomenon (Step 2: draw the rest of the fucking owl). Only programmers think they are immune to this ridicule, smash all the steps together, and then get salty when others complain, ignoring a series of luminaries who beg in every format of media available, and for decades, to do otherwise. Seriously, organize your code, separate the steps. You’re killing us.
- mason55 7y agoNo one disagrees that code needs to work in steps. The conversation is around how much and the answer is going to depend on what you're doing. Why have a function that prints a whole line? Isn't that just smashing together a bunch of small steps to print one character at a time?
- taspeotis 7y agohttps://news.ycombinator.com/item?id=8374345 https://news.ycombinator.com/item?id=8374345
- DavidVoid 7y agoSince that blog seems to be down at the moment here's a cached version of the article/email. https://webcache.googleusercontent.com/search?q=cache:http://number-none.com/blow/john_carmack_on_inlined_code.html https://webcache.googleusercontent.com/search?q=cache:http:/...
- ipnon 7y agoThe code that is easiest to revisit is decomposed into separate functions that are each trivial to understand. They are used to compose similarly trivial functions, and so on. Ideally every point of your program from input to output can be understood clearly and immediately.
- 0x445442 7y agoMakes the test a hell of a lot easier and more robust as well.
- reuben_scratton 7y agoAbsolutely this. More functions => More complexity => Bad. Also: decreased legibility, less opportunity for compiler optimisation.
- saltyfamiliar 7y agoI'm glad I'm not the only one who pays attention to this. This is completely unsubstantiated and coming from a relatively inexperienced programmer, but it's been my experience that better code tends to produce nicer shapes. An obvious example not mentioned in the article arises when code is nested too deeply and too thinly, creating jarring and disproportionate peaks.
- Thorrez 7y agoMicrosoft's docs have an interesting idea of what good nesting looks like: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb776913(v=vs.85)?redirectedfrom=MSDN#basic-usage https://docs.microsoft.com/en-us/previous-versions/windows/d... Apparently 13 different indentation levels is good.
- reilly3000 7y agowow.
- jpz 7y agoI actually find that surprisingly readable, probably because of the indent size which clearly allows the eye to see the blocks - and the size of my very large monitor - but this code seems to indicate a religious dogma about avoiding early returns, which would otherwise straighten it up.
- a_t48 7y agoRefactoring it effectively needs some sort of scope guard, too, to run `pfd->Release();` and the like. It's just as much dogma to write C++ like C, avoiding RAII.
- DonHopkins 7y agoGood code should be tightly wrapped around the problem, and reflect the shape of the problem itself. But sometimes, the shape can be deceptive: https://www.youtube.com/watch?v=CAUxhXIeSc8 https://www.youtube.com/watch?v=CAUxhXIeSc8
- sinuhe69 7y agoFunctional code would be totally different, I guess.
- pmontra 7y agoProbably. This is my experience with the case of the unbalanced if. When it happens to me in Python or Ruby, I return immediately from the smaller branch and move the other branch out of the if, to the main level. When it happens in Elixir... It doesn't happen because I don't use ifs there. I write two versions of the same function. One matches the condition for the then branch, the other the condition for the else one.
- mariojv 7y agoI hadn’t thought about the shape of code much as a refactoring heuristic, but it’s neat to see a post about the concept of code shape. I found examining code shape to be an effective method for assisting in algorithm recall in some college courses. Now working with larger codebases in industry, I find it really useful for navigating around large files or remembering where to go for particular snippets of code. I wonder if this phenomenon has anything to do with different spatial tricks people use for memorization and recall (the “memory palace” technique). I’ve never thought of myself as having good spatial reasoning at all, but this kind of thing makes me question the boundary between “spatial” and symbolic / verbal thinking.
- zdragnar 7y agoMy favorite name for a shape of code I've heard is the "pyramid of doom" caused by excessive nesting- think lots of ifs or callback hell in something like node.js It's easy to recognize, and the importance of recognizing it is right in the name.
- quickthrower2 7y agoLuckily we have async await to save us!
- DarkCrusader2 7y agoThis post very nicely summarizes what I now realize I have been doing subconsciously all the time. Writing in paragraphs with headings, turning short else branches in guards, refactoring "sharp saw teeth" etc. Good to know that others also use these heuristics.
- hinkley 7y agoI used to push hard for my favorite indentation style, and at one point I figured out that a big reason I could find bugs so fast was that, given reasonable formatting, I could see code smells just from the shape. If the bug wasn’t in the ugliest part of the code, then that code likely had two bugs in it.
- foxes 7y agoFor me I would think of the "shape of code" as an abstract measure of complexity [0]. More text might correlate with more complex logic. This is a measure in a language which manipulates state / control flow. I'm not sure what happens in a functional language. Maybe you could just think about numbers of functions. In Haskell sometimes it helps to write things in a pointfree way and you can spot some more general function to replace some noise. [0] https://en.wikipedia.org/wiki/Cyclomatic_complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity
- gitgud 7y agoHigh indentation has always been a good heuristic for high complexity. More indentation equals more mental context required. But although these shorter, less-indented functions are inherently easier to understand, they're not necessarily freer of bugs...
- classified 7y ago> ... not so good code: if it was, we wouldn’t need a comment... How much longer will this rumor persist that "good code" doesn't need commenting? Good comments explain things that aren't immediately obvious from the code.
- CraigJPerry 7y agoLike what? It can’t be the “how” - the code should be able to express that clearly. It can’t be the “what”, again that should be apparent from some combination of code and configuration / metadata. So that leaves the “why”. To my mind, code comments are the worst place to record why a particular implementation exists. The why often needs collaboration with non-coders.
- artsyca 7y agoIt's definitely the why for any particular unorthodox bits like shims hacks workarounds and the like The worst is finding some snippet from stack overflow or GitHub without a reference to the issue to back up why this thing is here or perhaps a TODO: with an improvement
- minaa-chan 7y agoI disagree. The code is the best place to comment the why. Regardless of what is documented or what is written up on jira or w/e, the code is what is true. Commenting the purpose of the code and maybe a link to some documentation allows a future reader to see if the code still fulfills the requirements.
- CraigJPerry 7y agoThe comments are very often not true, that's why there's so much push back
- minaa-chan 7y agoSo they should be updated the same as any other documentation. They're there to help. They don't need to be 100% infallible to be useful.
- lincpa 7y agoThe data flow programming of pure pipeline structure, It systematically simulates integrated circuit systems and large industrial production lines. In the computer field, for the first time, it was realized that the unification of hardware engineering and software engineering on the logical model. It has been extended from Lisp language-level code and data unification to system engineering-level software and hardware unification. and it brings large industrial production theory and methods to software engineering. It incorporates IT industry into modern large industrial production systems, This is an epoch-making innovative theory and method. This is the [Pure Function Pipeline Data Flow v3.0 with Warehouse/Workshop Model](https://github.com/linpengcheng/PurefunctionPipelineDataflow https://github.com/linpengcheng/PurefunctionPipelineDataflow).
- RickJWagner 7y agoI'm a software maintenance engineer. I make my living reading other people's code and trying to internalize it so I can make repairs where they are needed. This is an interesting article, and I intend to go listen to the podcast, too. In the past I've made efforts to try to speed up the process of learning a codebase. I'd do things like copy the code into a text processor, then shrink the font so I could see which files (classes) were biggest, and look for repeating shapes like the author mentions. I'd also use code cleaners to point out troublesome classes and UML full-trip tools to try to get a good sequence diagram out of a piece of code. It was all cumbersome, unfortunately. Most days I just use 'grep' to help me figure things out. I'm still looking for helpers, though. I'm hoping the podcast helps.
- Huggernaut 7y agoSandi Metz talked about a thing she does in her 2014 All the Little Things talk that she calls the "Squint Test". The idea being that you can tell a lot about the code from only its shape and colours by squinting at it. Someone made an Atom plugin: https://atom.io/packages/squint-test https://atom.io/packages/squint-test
- hackinthebochs 7y agoThis is exactly why I hate the trend in reducing structural characters in new languages, or having it be almost all words (e.g. python). There is much to understand about code by its shape, but blocks of words tend to have much less obvious at-a-glance shape than similar code with structural characters thrown in.
- 0x445442 7y ago> ...understand legacy code, refactor long functions... Wouldn't this invite consternation during code reviews because it doesn't have anything to do with the current feature? Or are you one of the lucky few who gets to exercise professional judgment when working?
- crimsonalucard 7y agoFunctional code tends to extend horizontally a lot.
- crimsonalucard 7y agoThis is the surface shape of code. There is an intrinsic and deeper geometry that textual programming hides.