6 ms·
The problem with the contemporary "clean code" concept is that the narrative that performance and efficiency don't matter has been pushed down the throat of all
by vrnvu 4y ago
The problem with the contemporary "clean code" concept is that the narrative that performance and efficiency don't matter has been pushed down the throat of all programmers.
Re-usability, OOP concepts or pure functional style, design patterns, TDD or XP methodologies are the only things that matter... And if you use them you will write "clean code". Even worse, the more concepts and abstractions you apply to your code the better programmer you are!
If you look at the history of programming and classic texts like "the art of programming", "sicp", "the elements of programming"... The concept of "beautiful code" appears a lot. This is an idea that has always existed in our culture. The main difference with the "clean code" cult is that "beautiful code" also used to mean fast and efficient code, efficient algorithms, low memory footprint... On top of the "clean code" concepts of easy to test and re-usable code, modularity... etc
- lwhi 4y agoIf you have more than one person working on a codebase; clean code matters a lot. A code base that can't be understood and maintained by the whole team, will degrade quickly.
- krona 4y agoNobody is saying maintainable code isn't important but rather that clean vs fast is a false dichotomy.
- lwhi 4y agoOkay, so we should aim for clean AND fast code?
- gjadi 4y agoOne can argue that simple code is both fast and clean. However, you can only measure how fast (or slow) your code is, so make it simple, aim for fast and hope it's clean (:
- Ygg2 4y agoOne can argue that extremes of fast and clean code will both result in something horrific. What Casey is doing is showing how bad a hammer is at removing screws. I mean duh, you're removing screws with a hammer.
- gjadi 4y agoI don't understand what you are saying. My comment was a jest (as suggested by the smiley). What I take from Casey's post is that a simple non-pessimistic representation allows for efficient code. That is, using a table instead of a class hierarchy gives massive performance boost. Compared to a "clever" loop unrolling doesn't give that much of a boost. So we need simpler representation. IMHO the table implementation is not less readable nor less flexible than the class hierarchy. But it is less common in the code I am used to, in other words, it's not a widely used pattern).
- TeMPOraL 4y ago> a simple non-pessimistic representation That's the insight, I think. "Clean Code" tells you to use maximally pessimistic representation for everything, because everything could be extended in some way in every direction. Meanwhile, in the real world, you likely have a good idea what directions of evolution are possible, and which of them are even useful. Casey's example shows you that, if you design your code to make use of those assumptions, you'll get absurd performance benefits for little to none loss in readability (and perhaps even a gain!). Some may ask, "what if you're wrong with your assumptions?". Well, you pay a price then. Worst case, you may need to rip out a module, rethink the theory behind it, and rewrite it from scratch - likely forgoing some of the performance benefits, too. Usually, the price will be much smaller. Either way, it's still better than being maximally pessimistic from the start, and writing software that never had a chance of ever becoming good or fast.
- Ygg2 4y agoThere are competeing in my opinion. Many techniques to make code fast will make it less readable. Techniques like manual code unrolling/inlining, writing branchless code, compressing data to fit into a pointer, etc.
- lwhi 4y agoI agree .. fast doesn't take account of how verbose or understandable code will be. As an extreme example, people choose not to write low level code for a good reason, even if it might be fast. High level / interpreted code will be more understandable, but will automatically have an overhead in most cases.
- Tomis02 4y ago> If you have more than one person working on a codebase; clean code matters a lot. You can have fast and clean code, just not the Uncle Bob style of "clean code". Uncle Bob hijacked the meaning of cleanliness. It doesn't mean that code written like that is actually clean, in fact it's usually the opposite: Uncle Bob's clean code is NOT clean.
- marginalia_nu 4y agoIt's also worth noting that Bob's advice is for Java, which has relatively unusual performance-idiosyncrasies around polymorphism and function calls. Much of the advice becomes very poor in languages that aren't JVM-based.
- mpweiher 4y ago> TDD or XP methodologies > the more concepts and abstractions you apply to your code the better programmer you are! These contradict each other. XP very explicitly opposes introducing (unnecessary) abstractions: YAGNI, DTSTTCPW, etc. And TDD is a good tool for enforcing that, as you only get to write code that you have a failing test case for.
- vrnvu 4y ago> TDD is a good tool for enforcing that, as you only get to write code that you have a failing test case for. TDD encourages the use of mocks and unit testing to increase code coverage. And unit testing is specially dangerous. You write a test, then program, so the test is helping you (the programmer). Selling the idea that the higher the test code coverage is the better and safer your code is. Not true at all. If your code doesn't have integration tests for example, you will never know how it actually runs. If you mock everything, you are not really "testing" anything but your internal logic. Unit testing and code coverage just checks that a code path has been run. But there are other tools like fuzzy testing or mutation testing... Do you randomize the memory at every test run? Do you make sure that the CPU cache is cold or hot depending on the test? Good testing is hard. Most unit tests are written to ease the development. After finishing the development, they are safe to delete. Because they don't add any real value as I understand it. I understand that a test is a business contract of something that MUST work in a certain way. Unless the contract changes, the test must never be removed or changed. TDD and exhaustive unit testing make the maintenance process harder because you don't know if a test is useful or not. If you follow TDD, most unit tests are re-written all the time. Because they were not written to test a business or critical contract, they were originally written to help some programmer write some internal logic.
- pinto_graveyard 4y ago> If you mock everything, you are not really "testing" anything but your internal logic. That's the purpose of unit tests. They do not exclude the need to perform other kinds of test. Integration tests, contract tests, stress tests - all those will focus on different facets of a system. > Most unit tests are written to ease the development. After finishing the development, they are safe to delete. This is especially bad advice, unless no one will never touch that codebase ever again. I saw old unit tests highlight bugs that would have been introduced by new code many times over the years. > TDD and exhaustive unit testing make the maintenance process harder because you don't know if a test is useful or not. Then, as a developer, remove unit tests that became useless. Code coverage is a measurement. If you turn it into a goal, it will become useless. If you have "useless" unit tests, it tells me that some unit tests were written as padding to move code coverage up.
- dvaletin 4y ago> Even worse, the more concepts and abstractions you apply to your code the better programmer you are! I had an Android programmer, who was eager to write clean code following GOF patterns, OP and the rest of the fancy things senior developers usually do. Ended up Android team with 3 devs required 3x time to develop same feature compared to single iOS engineer.
- KyeRussell 4y agoWell they weren’t a good senior developer then. Part of the art is knowing when to use the patterns. An incredibly im protest differentiation as it’s so so easy for someone a bit green behind the ears to see this and think that any sort of architectural thinking is useless.
- dvaletin 4y ago> Well they weren’t a good senior developer then. He wasn't. He was a mid grade dev, but it does not important, because even sr devs can fall in love with overcomplications.
- heisenbit 4y agoReminds me of Go. At the beginning you make only simple moves. As one learns the game more complicated patterns emerge. Watching master games the lines again are simple and clear - in hindsight.
- DaiPlusPlus 4y agoIt's often said that Design Patterns are workarounds for limitations in the expressiveness in a language: for example, the Singleton pattern is only useful in languages where you can't pass a reference to an interface implemented entirely by static methods - or the Visitor Pattern is the workaround for a language not supporting Double-Dispatch - method call chaining is a workaround for not having a pipe operator, and so on. You said you're targeting Android, that implies you were using Java, which has its reputation for both a rigidly inflexible language-design team and its ecosystem having more design-patterns than a set of fabrics swatches - that's not a coincidence. But for iOS, they'd be using Swift, right? Swift's designers clearly decided they didn't want to be like Java: take the best bits of C# and other well-designed languages and don't be afraid to iterate on the design, even if it means introducing breaking-changes - but the result is a highly-expressive language that, as you've demonstrated, allows just 1 Swift person to do the equivalent of 3 Java people. Swift is an actual pleasure to use, but using Java today makes me weary. (To be clear: Java was a fantastic language when it was introduced, but it simply hasn't kept-up with the times to its own detriment, it feels like its falling behind more-and-more at time goes on - but that's going to be the fate of every programming language eventually, imo).
- pinto_graveyard 4y agoAt least in the majority of places I worked at, people cared about readability and maintainability rather than just some abstract notion of "clean code". And perhaps I was lucky, but typically readability and maintainability are orthogonal to performance and efficiency. Sometimes readable will have optimal performance, sometimes not. Then it becomes a matter of tradeoffs.
- Nocturium 4y agoSame here. We had coding guidelines, not rules. The first entry even stated that they were guidelines and if you have a valid reason to deviate: discuss it and you'll get an exception. The discussion thing was mainly for new coders. We had a library part of the code that was used by many programs. Optimizing parts of it for their use case, could make it unusable for the others who used it. Communication is key. If you discuss, before implementing it, why you're making certain design decisions then everything goes a lot smoother. If there are objections, keep in mind that the worst case isn't throwing away your design and starting over. The worst case is implementing it and screwing over your fellow coders.
- tippytippytango 4y agoSounds like clean code used to mean things that were measurable.
- frankreyes 4y ago> the narrative that performance and efficiency don't matter That was the case during the 90s and the first decade of the 2000. Just wait for Moore's Law to kick in and in 18 months your code will get faster by an order of magnitude for free.
- DaiPlusPlus 4y agoMoore's Law concerns IC transistor counts, not actual overall performance, and especially not single-threaded performance: a 40-core CPU isn't going to make Windows twice as fast as a 20-core CPU. Single-threaded performance has long-since effectively plateaued: it's 2023 now and a desktop computer built 10 years ago (2013) can run Windows 11 just fine (ignoring the TPM thing) - but compare that to using a computer from 2003 in 2013 (where it'd run, but poorly), or a computer from 1993 in 2003 (which simply wouldn't work at all). This is not to say that there won't be any significant performance gains to come, such as with rethinks in hardware (e.g. adding actual RAM into a desktop CPU package, non-volatile memory, etc) but I struggle to see how typical x86 MOV,CMP,JMP instructions could be executed sequentially any faster than they are right now.
- frankreyes 4y agoReal-world evidence says otherwise https://stoneridgetechnology.com/company/blog/the-exponential-growth-of-hardware-and-the-linear-growth-of-software/ https://stoneridgetechnology.com/company/blog/the-exponentia...
- DaiPlusPlus 4y agoThat article doesn't contradict my post, in fact it's basically the same thing I'm saying: look at fig2 (the timeline graphic) and the paragraph preceding it: it shows that the gains in "serial" HPC performance gave-way to massively-parallel gains sometime around 2010. The rest of the article is concerned with how software today is still written for those "serial" processors in-mind and fails to take advantage of parallel computing hardware - but this is hardly a new nor controversial statement.
- foul 4y agoStrangely enough, even in this video, everyone notice how you're taken to make tradeoffs between coherence and cleanliness vs performance-oriented code in langs like C++, while the Clean Code book was exemplified in Java (so most of performance is shoved in JVM code) and SICP was in Scheme (which is interpreted, or transpiled to C where you can optimize, or has a VM/JIT underneath). I vaguely smell the language of choice has something to do with that, and C++ would benefit more from data-oriented design than from literate OOP or functional programming patterns took from very very different programming ethoses (the programming language is an interface to something else)
- caeril 4y agoOne of the most insane things I hear repeated constantly is that "servers are cheaper than programmers", implying that runtime efficiency doesn't matter, only developer efficiency. Which is all well and good, until you need to hire all the network engineers, systems administrators, devops people, security staff, datacenter operations managers, database sharding engineers, etc to manage the 10x more hardware and network surface area you have to throw at your slow codebase.
- vntok 4y agoGo full Cloud and you won't need to hire most of these roles ever, except in niche ultra-high performance cases. These roles will be externalized at AWS or Azure, super-paid to work for you 24/7.