5 ms·
Casey makes the point that you don't have to hand-tune assembly code, but instead just write the simpler code. It's easier to write, easier to read, and runs fa
by jiggawatts 4y ago
Casey makes the point that you don't have to hand-tune assembly code, but instead just write the simpler code. It's easier to write, easier to read, and runs faster too!
If there's something wrong with that advice, I can't imagine what it is...
- Aeolun 4y ago> If there's something wrong with that advice, I can't imagine what it is... It will start getting really annoying when you try to add shape ‘hexagon’ and need to figure out all the places where a shape can potentially be used, just so you can update the switch statements.
- andyferris 4y agoMany languages provide unions or sum types along with exhaustiveness checking to make this very easy (frequently not OO-inheretence based languages though).
- Ygg2 4y agoWhat happens if library user wants to extend functionality? They can't inject their code into the library.
- deleted 4y ago[deleted]
- piaste 4y agoYeah, it's very awkward. Your best option is to leave a 'hole' case where someone may provide a 'data type' set of functions satisfying an interface, and the library author simply calls them. Effectively you're adding an OO escape clause, but it's ugly and will break user code when you add more functions and grow the interface. Conversely, in a codebase organized by objects it's not clean to add an extra method to the base class and each subclass. You have to write an external function and switch over every known subclass inside it, which is also very ugly and will also break when you add more subclasses. The two designs are actually the duals of each other. Someone compared it to rows vs columns and it's a great comparison. In OO, the methods are columns and each new row is a new subclass implementing them. In FP, the types are the columns and each new row is a function that switches over the possible types.
- sarchertech 4y agoBob Nystrom has a good article on this (the expression problems it’s called) https://journal.stuffwithstuff.com/2010/10/01/solving-the-expression-problem/ https://journal.stuffwithstuff.com/2010/10/01/solving-the-ex... He also discusses it in his book Crafting Interpreters.
- Olreich 4y agoIf this is going to be a library where that’s a desirable feature, architect it for that feature. In the example, one easy way would have the coefficient table be expandable/replaceable. If you really need to run arbitrary user code, then write an interface that the user will conform to and call their code. You don’t even need OOP support to do that easily, just typed function pointers.
- crabbone 4y agoWhy would you go with "many languages" into a thread showcasing how C++ sucks? I'm pretty sure that had the author of the video done all the same manipulations in Python, the speed difference would've been negligible. The author of the video discovered that C++ compiler is dumb when it comes to optimizing virtual method calls (that instead of bare virtual method calls he had to help the compiler to guess the right conditions where these virtual calls could be replaced with guessed static calls). Essentially, all that his video is saying is: "virtual calls bad if-else good". Which is like what every C++ game-dev thinks after few years on the job. Which is amusing in how short-sighted it is, and sometimes even more amusing to discover the "solutions" created by such C++ game-devs that are aimed at replacing C++ objects, but do it in a way that's even worse than C++ original design (who would've thought that to be possible!?)
- GrumpySloth 4y agoEven in C compiler will emit warnings for unhandled cases in switch statements as long as you don’t provide a default case (as you shouldn’t).
- e28eta 4y agoDepends on the type of code you’re writing. If your `switch` is tightly coupled to the code that defines the cases and they’ll definitely be changed in lockstep, a default is more likely to be harmful. If your cases are defined externally, and you need to be forwards compatible, omitting a default is wrong. The Swift language specifically added `@unknown default` for switching over enums.
- Aeolun 4y agoDepends on your language I suppose. I haven’t worked with a ton of compiled languages. But we can just re-up the problem by adding 100 different shapes instead of the one. Now you have switch statements with 104 cases each spread through your codebase.
- yakubin 4y agoI prefer to have those 104 cases all in one place (as is the case, when it is a switch statement) rather than each in a separate file, that I need to jump around between now (as is the case with polymorphism). This situation is a bit analogous to organising things column-wise vs row-wise. And in practice I find that I need to jump around a lot less with code that uses switches than with code that uses polymorphism. Tangentially, the latter is also more prone to turning into spaghetti, as the whole is obscured by indirection levels between the parts, but you don't see the spaghetti until you try to step through the code, when debugging an issue or just trying to familiarise yourself with a new codebase.
- jbverschoor 4y agoswitch isn't 'invented' for enums. switch is a low-level construct which mimics several goto's / jumps. It's just as bad, except for the case where you have either: a) multiple behaviors for the same value, b) need to pass through (not break). b) is the nr 1 reason I hate switches, and my nr 2 reason is that most languages don't support proper enums, and will fail when you don't handle all possible values
- EVa5I7bHFq9mnYK 4y agoSwitch was invented because it allows to replace several ifs and gotos with a precomputed static jump table, an optimization trick.
- radiator 4y agoSwitch is not bad, far less is there any reason to hate it.
- smnplk 4y agoAgree. It's the same as saying don't use for loops or any other basic language constructs. Switch is very useful, please leave switch alone! You will not take switch away from me :)
- jbverschoor 4y agoWhen do you actually pass through? Only some state machines do that. But even I. That case, ifs are more clear and less error prone due to missing breaks, braces/scoping issues, etc
- camgunz 4y agoConversely it's really annoying to add a new method to each shape--you've got to open them all up and add shape-specific code for them with a bunch of boilerplate. With switch statements you just add one more function. This is the "expression problem": https://en.m.wikipedia.org/wiki/Expression_problem https://en.m.wikipedia.org/wiki/Expression_problem
- kyralis 4y ago"Easier to write, easier to read" is the part that's wrong with that advice. It absolutely is, on toy problems like the one described in the article. It very frequently is not when embedded in much larger domains as part of large projects maintained over years by teams.
- jrumbut 4y agoAnd when you combine inadequate abstractions with programmers who aren't the kind of geniuses brought in to optimize game engines you get very difficult to fix performance problems. One of the nice things about some of the clean code concepts he uses is that (as he shows) you can tactically step back from them in key, performance critical areas and reap these wins. If you stay too low level you get lots of tangled spaghetti code with major performance problems and no obvious way forward besides "make it better."
- dsego 4y agoIt could in fact sometimes be easier to refactor low level code, than to dig yourself out of bad leaky abstractions. https://caseymuratori.com/blog_0015 https://caseymuratori.com/blog_0015
- whstl 4y agoI find it a bit disingenuous to call what Casey Muratori is doing "staying in the low level". Using procedures/functions is not exactly "low level". Using switch is not low level. Lookup tables are something you have to do in high level code all the time. Sure he could have used much better variable naming (CTable?) and probably documentation, but code-wise there's nothing that screams low level there.
- jrumbut 4y agoI'm not sure how it's disingenuous, I sincerely believe what I said and I'm not trying to fool anyone. I would consider most of his replacements lower level than typical the clean code practices he critiques (especially the ones like iterators that he mentions but avoids in order to steel man the clean code side a little bit), not the lowest level possible. They take into account how the machine actually works and avoid additional indirection which is why they perform better.
- saagarjha 4y agoThe problem is that Casey has a very particular definition of simple which is problematic to apply in many cases.
- whstl 4y agoDoes he? If anything, it is the definition of "Clean Code" that is somewhat special compared to previous usage of OOP and other paradigms. Casey's definition of simple actually reminds me of the cliché by Rich Hickley. It's simple, but it's not necessarily easy.
- moremetadata 4y ago> It's easier to write, easier to read, and runs faster too! ITs still possible to get a bottleneck in assembler. Whatever language is used, executable code still needs to be profiled using tools as described here. https://en.wikipedia.org/wiki/Profiling_(computer_programming) https://en.wikipedia.org/wiki/Profiling_(computer_programmin...