15 ms·
After years of experience writing code for games, I find that the dumbest code is the best code. It doesn't matter if it's C# or C++, whenever I've used somethi
by PezzaDev 6y ago
After years of experience writing code for games, I find that the dumbest code is the best code. It doesn't matter if it's C# or C++, whenever I've used something like reactive extensions or template metaprogramming, it has been a terrible mistake every single time. Make your code simple, dumb and verbose all the time. Avoid using any complex abstractions or any overcomplicated syntactic sugar and you'll have a codebase that anyone can jump into and quickly be able to add features without introducing bugs (at least less likely). This matters more than anything else.
- CamperBob2 6y agoIt's just so frustrating that they keep adding things that scratch no itch I've ever had as a programmer, while leaving out incredibly obvious things that would make my life easier and my code safer. Named parameters, for instance. It's insane that function parameters still can't be specified in any order with name=value expressions. That would have saved numerous bugs over the years, but apparently I'm the only one who thinks so. When a language such as C++ is harder to use than Verilog, somebody has screwed up badly.
- MaxBarraclough 6y agoNamed arguments are a good example of a simple feature that C++ still lacks, and cannot be effectively 'faked' without it being built into the language.
- BubRoss 6y agoThey can be faked to an extent with structs, but the reality of default arguments is that you have to be aware of them anyway so that you don't get behavior you don't expect. When there are default arguments you are building up assumptions and expectations that can become problems when they aren't right.
- wbradley 6y agoHere's a link to the named parameters spec. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4172.htm http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n417...
- HelloNurse 6y agoC++ fold expressions, the main C++ feature the article covers, are simple and dumb (at least, enough to use them) but not verbose, and definitely harder to get wrong than a much more verbose for loop.
- eska 6y agoI just fixed a segfault the other day because one of our new hires fresh from college is eager on using modern c++ and didn't put parentheses at the correct place in his fold expression.
- HelloNurse 6y agoIt sounds like an interesting bug, can you elaborate? On the surface it sounds like your new hire merely used fold expressions to call functions and operators that were already treacherous on their own.
- eska 6y agoSorry, I can't look it up right now, but trying to reconstruct it in my head it must've been something like y = (f(x1), f(x2), f(x3)) vs y = f(x1, x2, x3) Not entirely sure anymore though. But it was something about causing side effects but throwing away return values with the ,-operator and involved function calls, I think
- MauranKilom 6y agoI love fold expressions, but if you're inside a variadic template, you've long left the realms of "simple and dumb". IMO. I mean, they're only readable to people who have dabbled in variadic templates in their free time. That's how many people on your (future) team?
- hhmc 6y ago> I mean, they're only readable to people who have dabbled in variadic templates in their free time. That's how many people on your (future) team? This line of reasoning is vacously true for any syntax and semantics though. Move semantics and rvalue reference are only readable to people that have taken the time to understand them -- they're undoubtably useful though.
- taneq 6y agoAs I've learned more about programming I've been leaning more and more in this direction too. So very much of the complexity and abstraction we build into software is gratuitous and unnecessary. The real art of writing software is writing simple, obvious code that also happens to be fast and efficient.
- pansa2 6y ago> I find that the dumbest code is the best code. This is the idea behind Golang, isn’t it? That everything should be written out explicitly and not hidden behind abstractions. Some people love that, others hate it.
- PezzaDev 6y agoI'd love to try Golang, but as a game developer, the gc makes it a no go due to perf. I begrudgingly accept C# due to unity. GC is a different topic altogether, but has also always been a pain. You end writing code to avoid allocations, which at that point you ask "Why am I not just writing C++?" I also discovered GC makes bad programmers worse by allowing them not to care about ownership, enabling them to develop systems in an adhoc way. Some programmers need a segfault screaming at them to make them realise they are writing terrible code.
- pansa2 6y agoWhile I’m not suggesting using Go for game development, don’t most games include code written in a language with garbage collection? If not C#, then a scripting language like Lua?
- PezzaDev 6y agoAnd everyone wishes they hadn't :P Even modders that use Lua have to write code that avoids allocations, caching and reusing all the objects they can. I can't stress enough how much time is spent on optimising code to avoid GC pauses. The main goal of my C# coding style is avoiding unnecessary allocations at all costs. I'm not exaggerating.
- yahyaheee 6y agoNot to mention acceleration is an issue with the go/c ffi
- mrmonkeyman 6y ago> the gc makes it a no go due to perf So you use C#..
- lazypenguin 6y agoMatches my experience as well in the hobby gamedev realm. I can give an anecdote, I’m involved in a “private server” dev community for an old niche MMO from 2003. There exists 3 codebases: first the original code written in a windows-style C++ with heavy use of inheritance, custom collections, Hungarian notation, etc. The second is a collaborative open source version that is written in a naive/basic C++ style (e.g. c w/ classes) and the third is a from-scratch reimplementation in modern C++ with all the bells and whistles, cmake, heavy use of templates, etc. Despite the modern c++ version being the highest quality and the original windows-style version being the most fully featured, the vast majority of people use and prefer the rinky-dink basic c++ version. Simply for the reason that you don’t need to be a senior level dev to contribute meaningfully to the code.
- fla 6y agoIs the project you mentioned SWG:ANH by any chance ?
- microtherion 6y agoSo, naive code attracts naive programmers? I'm not sure this is the ringing endorsement you take it to be. I should also add that Hungarian notation is the prototypical example of dumb, verbose code, that wants to make individual lines easier to understand by dragging type information into every single variable name.
- Riverheart 6y agoOr you know, people who respect their time.
- deleted 6y ago[deleted]
- jfkebwjsbx 6y agoThere is no need for Hungarian notation because types are way too complex in C++ for that. On top of that, an IDE tells you right away the type if you want.
- 6y ago
- krapp 6y ago>I find that the dumbest code is the best code Not always, though. See every bug and exploit with C arrays or pointers that exists because C devs think even minimal attempts at safety are too complicated or slow, or old-style PHP code that builds SQL queries out of printf strings directly from POST values, or probably countless other examples in other languages. C++ code that uses raw pointers instead of references or that uses std::vector but never actually bothers to bounds-check anything. It's entirely possible for code to be too dumb for its own good.
- deepaksurti 6y ago> Not always, though. See every bug and exploit with C arrays ... That can also be perceived as a a flaw of the language design in that it does not allow one to write dumb, safe and fast code. Which are such languages in existence today? edit: fixed typos
- gordaco 6y agoI would say Java, which I suspect is bound to be a bit of an unpopular opinion here (I expect more startup people than enterprise denizens in HN); but the more I think about it, the more sure I'm that it fits the bill: - Dumb: you bet. The inclusion of lambdas has shaken things a little, but usually Java code is straightforward with little space for "cleverness". The counterpoint to this, of course, would be the memes about AbstractFactoryFactoryImplementationSubclassDispatcher class names and all that, which IMHO does not represent much actual Java code out there. There are good reasons why big corps prefer Java, and readability is one of them. As a programmer, I've found it easier to jump into a Java codebase I didn't know much about than in any other language. And this has happened even when I had little experience in Java. - Safe: yes. You have to go out of your way to be unsafe in Java. Memory allocation is done for you and the try-with-resources idiom is almost as good as C++ RAII. - Fast: also yes. Usually about 2x or 3x the run time of C/C++ code, some times even less.
- Koshkin 6y agoIndeed, despite all criticisms Java as a technology is one of the best things that has happened to the software industry, next to Linux.
- bullen 6y agoI agree 100%, here you can see the result of an all-nighter getting my dumb engine to finally render models properly with GPU skinning (the problem was vertices with 5 weights, I'm dumb too!): http://talk.binarytask.com/task?id=5959519327505901449 http://talk.binarytask.com/task?id=5959519327505901449
- papito 6y agoIsn't that true for, like, any code? Don't turn your code into an academic exercise. You are not writing it for the compiler - you are writing it for me. It's not that different from the English language either. Laying out your thoughts in a clear and structured way is the real skill. Start using words and expressions that I have to constantly google for, and I will hate you very quickly.
- microtherion 6y ago> Make your code simple, dumb and verbose all the time This is a frequently encountered argument, and sure, if you look at any single line, it looks very obvious what it does. But I would argue that verbosity and lack of abstraction has severe drawbacks for a programmer's ability to understand the overall codebase, and it is disastrous for long term maintainability. You start out with 20 identical pieces of boilerplate code, and a few years later, you have 20 subtly different pieces of code. Good luck guessing whether the differences were intentional, or accidental. Good luck refactoring the code.
- PezzaDev 6y agoNo coding approach will ever solve an issue caused by a lack of discipline.
- klodolph 6y agoI no longer think that saying is helpful. The problem is that every problem is caused by a multitude of causes, and there’s usually no clear way to distinguish issues caused by lack of discipline from issues caused by the wrong coding approach or style. Different styles make different demands on how disciplined a programmer must be in order to write correct code. My experience in well-managed large code base with decent-size teams is that the recommended approaches and coding styles will evolve to address problems that could be solved by asking programmers to be more disciplined. So that’s the problem with saying “no coding approach will ever solve an issue caused by lack of discipline”—it only makes sense if you already have a good idea of which issues are caused by a lack of discipline, and if you already understand that, then the saying doesn’t help you. The key insight here is to understand when changing your coding approach may allow you to write correct code with less effort (and discipline). But this can’t be distilled into an aphorism, so it won’t get quoted. An example is holding a lock to access a certain field. If you’re “disciplined” you can just leave a comment on the field that lock X must be held to access it. But in practice, you want to solve that with code analysis. Another issue is using scoped locks so early returns don’t screw you. You can easily argue that these issues aren’t caused by lack of discipline—but if you travel back in time 20 years or so, “discipline” might be the only tool you have to solve them.
- badsectoracula 6y agoI've worked on a bunch of engines, both big AAA and small indie scaled ones and i agree with you. It is actually from this experience that i have a hard dislike for C++'s "auto" outside of cases where you can't do otherwise - it makes the code you didn't write hard to understand exactly what is going on (and sometimes error prone). Sure IDEs can show you the type if you mouse over (at least some of them), but if the type is explicitly typed you do not need to do that and you can just read instead of pause, move the mouse over the auto, read the type, then move the mouse to the next (if any), etc. And that is assuming you are reading the code inside an IDE - it doesn't work if you are reading the code in a web-based code review tool that at best can show you syntax highlighting (and it is exactly in that environment where you want the code to be at its most understandable). Now not all features are bad, lambdas are OK when used as local functions and can make the code more readable if the alternative is to define some static function outside the current method (e.g. you want to pass some custom filter or comparator). They can certainly be abused though, but it is one of those cases where their usefulness is greater than their abuses (and i can't say the same for "auto"). For the example given... it might be a bad example, but honestly i was looking at that code for a bit and i simply cannot read it - i do not understand what is going on just by reading the code, i'd need to run it in a debugger and go through it step by step (and i've actually written texture atlas packers before). It completely fails to sell me on the "fold expressions" and "parameter packs" and it certainly doesn't look at all "elegant" to me (but note that it might be that the example is awful, not the language feature itself). And it did make me skim through the rest of the article though since after completely failing me on all fronts at the introduction bits, i couldn't get the feel that i have any common grounds with the author.
- KallDrexx 6y agoI wonder how wide spread dislike of "auto" is in c++ (I've seen that a few places) when the equivalent type inference has become fairly standard and preferred in other languages like C#, Rust, Go, etc...
- vbezhenar 6y agoWith Java I've seen coding standards that you can use `var` only when type is obvious from declaration. For example: var person = new Person(); var car = selectCarById(carId); // Car if type is not obvious, it should be explicitly declared.
- vbezhenar 6y agoI agree wholeheartedly. I spent so much time needlessly trying to be smart.
- Koshkin 6y agoYet, it is important not to abandon the hope to become smarter. Learning new tricks never gets old.
- danielscrubs 6y agoI think it's best trying to be smart in areas that will stand the test of time, not the latest lasagna architecture or library hype.
- Koshkin 6y agoThe tool is only as good as the one who uses it.
- meheleventyone 6y agoYup, I think everyone goes through a phase of enjoying creating ‘elegant’ abstractions but you steadily learn nuts and bolts is way more preferable. That’s why I’m way more excited about Zig as a language to write games with than modern C++.
- MacSystem 6y agoThat's why even using C# I wanted to have some of C's simplicity. Keep it simple. As the Da Vinci said, "simplicity is the ultimate sophistication"
- gintery 6y agoIs the code really that complex? Overly verbose, maybe, but its really not that hard to follow even for someone who doesn't know much about C++ templates.
- typon 6y agoI wish this kind of thinking would die. 9 times out of 10 when I'm working on a large code base at (any company I've worked at so far), the main problem I have is with disorganized, messy code with poor abstractions, state everywhere, functions that are too long, functions that are too short, references to objects everywhere with no regard for lifetime and the list goes on and on. The times I have been stumped with clever syntax are few and far between. Almost never have I said "oh man I wish they didn't use a std algorithm/container here, makes the code more obfuscated!". Yes I have seen cases where classes or functions are unnecessarily generic, adding templates when you only needed to support a specific type (YAGNI). But in the end, most bad code I look at, I completely understand it's syntax. It's the semantics of this so called "dumb" code that prevent me from modifying it or fixing a bug in it for days until I actually understand the rats nest of ideas expressed in the code. I think using features like using const as much as possible, preferring return by tuple rather than multiple in out parameters and a bunch of other modern C++ features more often than not make code bases simpler than the other way around.
- PezzaDev 6y agoYou made me realise that term "dumb code" isn't exactly what I mean. I want to advocate writing code that is very easy to statically understand. You should be able to look a piece of code without needing to read too much around it to understand what it is doing. One of the best ways of doing this in my experience is keeping things simple (or "dumb" as I put it earlier). Using simple abstractions, keeping code organised and avoiding global state also help in this regard.
- neutronicus 6y agoIt's the endless copying-and-pasting that gets you. Fix a bug somewhere ... pray to the Nasal Demons you got there before more than two developers duplicated it elsewhere.
- otabdeveloper4 6y agoTemplate metaprogramming is not 'smart'. In fact, it's the dumbest and simplest programming language, not counting esolangs. You just need to know functional programming. Know your tools, people.
- pornel 6y agoNobody thinks "I hate having simple code, I'm going to replace it with a complex one!" It's always "ugh, this code is a copypasta convoluted mess. I'm going to replace it with a simple solution".
- RcouF1uZ4gsC 6y ago> Avoid using any complex abstractions or any overcomplicated syntactic sugar and you'll have a codebase that anyone can jump into and quickly be able to add features without introducing bugs (at least less likely). The thing is what is complex abstraction changes with time. At one time, floating point, especially transcendental functions would have been a complex abstraction. Functions at one time were a complex abstraction. Classes and polymorphism were a complex abstraction. Pointers are a complex abstraction for a lot of people. Linear algebra is a complex abstraction. Transforms are a complex abstraction. Many times “complex abstraction” just means “an abstraction I am not familiar with”. Back in the 80’s most games were written in assembler. I am sure many people thought that C was a complex abstraction. I mean, instead of just doing a jmp to a location, now you had a stack and a calling convention and which registers to save and restore... Since “complex abstraction” is often code for “unfamiliarity”, education, like what the original article is doing is very helpful in moving the state of the art forward. As people become familiar with new abstractions, that becomes the new baseline for “simple” code.
- Bjartr 6y ago> Many times “complex abstraction” just means “an abstraction I am not familiar with”. A lot of times it can also mean "an abstraction that my development environment is unaware of or otherwise has deficient tooling for"
- tonetheman 6y agoThis advice is true across all areas of programming. I always say it as "write code that you could debug at 2:00 am drunk." Be simple, do not be clever and be clear.