6 ms·
It strikes me that your argument taken to the extreme is that everybody should program in assembly language because you can do anything, anytime, anywhere. Wel
by georgeorwell 14y ago
It strikes me that your argument taken to the extreme is that everybody should program in assembly language because you can do anything, anytime, anywhere. Well, at least as far as control flow structures are concerned. Certainly C is preferable to C++ if you want simple and malleable code.
Do you also prefer if-else to switch statements? (I'm not sure.)
Do you like to use goto? (I doubt it.)
Do you eschew the use of classes and inheritance? (I doubt it.)
Do you keep all your code in one file? (I'd be very surprised.)
My point with these semi-facetious questions is that structure is important and regularity in a codebase does wonders for comprehensibility and maintainability. I agree with you for the case in which you do actually have something where the underlying structure is likely to change, in that then it does make sense to write it with malleability in mind.
Consider something like command line options processing. You have 50 options. You might want a 51st option. It makes sense to use the most regular structures you can so that people don't start special-casing stuff in the middle of it all. That, or to use an options library that defines the allowable formats for you.
Part of me thinks you're just having an allergic reaction to ?: simply because it is pretty unusual the first time you see it used seriously. But it can simplify so much:
Compare:
if (a)
{
return b;
}
return c;
to:
return a ? b : c;
- npsimons 14y agoNot to mention that it's essential for initializing some constant variables; I have yet to find a better way to do: const int count = argc > 1 ? atoi(argv[1]) : 1000000; For quick test programs where I might want to change some number of iterations without having to recompile, but I also don't want to have to provide an argument every time I run it.
- johnbellone 14y agoYou're assuming that the first argument here is an integer value. For a single, one off, testing haress application I wouldn't worry too much about applying a full-blown semantic code style. Is there anything wrong with keeping the default value as a separate constant? const int kDefaultValue = 1000000; int value = kDefaultValue; if (argc > 1) { value = std::atoi(argv[1]); } const int count = value; Personally I much prefer using [program options][1] from the boost project (since we are talking about C++ here). Most projects already have this as a dependency, and its quite easy to setup. It also properly handles your types. [1]: http://www.boost.org/doc/libs/1_52_0/doc/html/program_options.html http://www.boost.org/doc/libs/1_52_0/doc/html/program_option...
- npsimons 14y agoPerhaps I should have clarified: when I said quick test program, I was referring to something I would write to convince myself of some minor detail (sometimes just checking compiler warts or algorithm performance) and that piece of code would never be seen or run by anyone but me. I know that the first argument will always be an integer, because I'm the only one who will pass it arguments! I'm also (kind of unreasonably) a const nazi. So given the option, where I can take a shortcut (I know, bad, bad programmer), but still do "proper" programming (consting everything by default is my SOP), I'll do it. And I'll never release that code (I'm starting to regret posting that snippet here . . .). I will agree, though, option parsing libraries are a definite must for released software. I like Boost, but using even small parts of it tends to pull everything in, and at least for my current project, we are trying to minimize dependencies (it's a library). I had to fight for Boost::regex, and only got it as a fallback for compiler versions that don't have regex.
- johnbellone 14y agoI wasn't lambasting you, and I wouldn't ever regret posting a snippet. It helps drive the conversation. I understand and agree with Boost injecting a whole lot of dependencies, and for a small testing library or executable I would probably got the same route that you did. I'm also a pedantic const nazi at times, and merely replied back as it makes me feel that, in some else's code, they may find this useful. If you take a look at the Doom3 code there are even places where they stray from the code style guide when it makes sense. I'm more of a proponent of "in the moment" styling to make sure that it matches the rest of the project, or at the very least, component that I am working on.
- jblow 14y agoNo, you clearly didn't understand my point. I am talking about maximizing the rate of successful features implemented. Programming things in assembly language is obviously not going to do that. I don't know, man. I have 31 years of programming experience. I am not detecting from your argument that you have anywhere near this level of experience, so I am inclined not to get into this discussion. But I will say that your code example at the end of your comment is exactly what I am talking about. It happens all the time that I want to put something in front of 'return b' (or, in fact, I just want to put a breakpoint on that line in the debugger! Not going to happen in your second example...)
- Cushman 14y agoNot to repeat myself, but: if (a) printf("returning b"); return a ? b : c; ...makes it easy to modify the side effects of the return without muddying the semantics.
- to3m 14y agoNow, let us suppose that expression a has side-effects... "But that's just stupid!" Yes. Now, given that a has side-effects...
- Cushman 14y agoSuppose I want to `printf("Returning. A: %i", a)`. Same answer.
- georgeorwell 14y agoAssuming a has type int: int a_val = a; if (a_val) printf ("returning b"); return a_val ? b : c; Anyway, it's not useful for complicated code that needs to do lots of stuff. It's useful for simple code that ends up being more verbose with if-else. It's also useful for enforcing behaviour.
- georgeorwell 14y agoI'm not even clear that it's clear I didn't understand your point. I guess I have trouble communicating effectively. I thought your point was that flexible control flow structures like if-else allow you to change code quickly and more easily in the future. Wasn't that the point? Assuming I have understood your preference for flexible code, I am simply stating my belief that it is useful to balance this with rigid code. Sometimes the flexible code is simpler, easier to read and write, and more maintainable, sometimes the rigid code is simpler, easier to read and write, and more maintainable. It depends on what you are trying to do. In this particular case I prefer the ?:. The assembly argument was based on a notion I had that any time you use something more complicated than test and branch for control flow you are introducing rigidity into your code. Often this lets you be productive too; switch statements are a good example. And lastly, let's assume I am 14 years old. Is that really the way a wise teacher talks to the young and inexperienced? My favorite teachers ask questions to check and help deepen my understanding, and sometimes it's revealed that they're learning something too.
- to3m 14y agoWell, I might be unusual, but I don't object to goto, I don't uses classes and inheritance much - and I like code that's all in one file, too. (Means I can keep an eye on it.) So it might not surprise you to hear that I'd vote for the code that uses the if statement :) - in fact, I don't really understand why the second would ever be preferable, outside some unlikely case specially engineered to prove me wrong. I can pretty much promise you that at some point, you will find yourself wanting to debug one case, but not the other. If not this specific code, then some other code very much like it. If not you, then somebody else! But if the code is all on one line, how will you stop on one case and not the other? In every native debugger I've ever used, you can't. You need to split it into separate statements, so you can breakpoint each case separately. So in the long run, the code is very likely to be changed, so it'll probably end up the first way eventually. So why not just write it that way to start with? ("Ah, ah, but but, but have you heard of this thing called a conditional breakpoint?" - yes, I have, thank you.) It's just not even funny to think about how much of my time this specific issue has wasted over the years :(
- georgeorwell 14y agoAll you need to do is hoist the conditionals out of the ?: if you have a bug and you want to inspect them, either with printf or a debugger. Everything else is available before the statement. Personally I don't use debuggers except to get a backtrace from a core dump once in a while. I use various forms of automated testing and logging to stderr/stdout. They just aren't very useful with concurrency bugs.
- to3m 14y agoThe "all you need to do" bit is exactly the way this has wasted my time. I'm not saying that doing it is particularly complicated, nor that any individual occurrence is especially onerous, and in fact it usually isn't (though you do lose your state, and that's annoying) - but the time taken mounts up! Ah well. I've said my piece. If your experience hasn't convinced you, like mine convinced me, then I imagine yours was a lot more fun ;)