- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Wouldn't happen to be one without a filesystem, would it?
Admin
Snip-snip-snip...
Thanks.
This is because you haven't given any. You've made a whole lot of blanket assumptions about the context of the code, and stated that a switch (or if-elseif) statement is wrong, and that polymorphism is the "right" solution. For all you know this is part of the function or method that is always used to set these particular variables. There is no particular reason to assume that a polymorphic approach would be superior, nevertheless you're sure it is...
Yes I did. That's where I learned functional, procedural, modular and OO programming techniques (various styles), and a little about machine-code programming. My minor was Logic. After that I worked commercially for 13 years, 10 in a senior position. I enjoy kayaking, target shooting and long walks on the beach. But enough of the resume.
The approach you're suggesting is more complicated than a dozen-line switch statement. You're writing at least 2 more class definitions, probably more than that from your remarks. From a maintenance perspective (that's what the guy who comes after the designer does, and the situation we find ourselves in looking at a piece of pre-existing code), less is more. A mature project will have many thousands of class definitions (hopefully in a well organised framework) which need to be sifted through in order to make modifications or add new features. Object instantiation also means (implicit) memory allocation, which can be a problem if you're replacing simple program structures with objects (I was fixing just such a problem last week, out of memory errors, but I digress). How do you justify this additional layer of complexity?
Bear in mind that simplicity is one of those higher criteria that should always come before rigid adherence to a single programming style or paradigm.
Indeed. This is why I find your so amusing.
Admin
If you want to optimize for the fewest total number of operations (including conditional branches) without using a lookup table, and limiting division to that which can be optimized into bit shifts, how about this:
I believe it beats RandomNameOfHiding's solution, which takes a similar approach...
Admin
tl;dr: A shotgun might fix this. Assuming anyone not frozen in terror by meh code and stylistic choice is still capable of making a design decision and/or maintenance assumption about what type of Apocalypse we're really facing, here... (is it Zombie? Possibly Swamped.)
gtfo||stfu pls; kthxbai.
Admin
Admin
Admin
Getting rid of the unnecessary conditional... FTW
Admin
Admin
Admin
No no no. Base class? Inheritance? No. You need interfaces! That way you can dependency-inject the strategy class from your XML file.
Wow! That was so easy. And maintainable. No one will ever be confused as to why I wrote so much code instead of an if-else block! Adding a new class in the future will be sooo much easier than adding an extra else-if line.
But seriously, patterns are good.... just not here.
Admin
class MainType { bool operator== (int x) { return true ; } } mainType;
Welcome to the alternate universe ;-)
Admin
Sorry, but all these mathematical operations are conceptually wrong. Both variables (mainType and subType) contain the value of a "type", they do not contain a quantity; so it is conceptually wrong to perform mathematical operations on them.
The requirements are to set a certain value to subType according to certain rule based on the values of mainType. You are abusing the fact that the current values of those codes match your needs to perform an unneeded 'optimization' that also obscures the code.
A simple switch statements seems much wiser to me.
Admin
Ok, in this particular case a switch/case would have been clearly preferable. But generally a construct like
for example is a valid construct and imo more readable than several nested if clauses or "goto out;". And once you are used to this pattern it is not that far fetched to use it the way it is used in the article. At least I think my code is a valid example for using a while loop without the intention to run it more than once.
Admin
Admin
Yeah we all know you can use switch and should probably use enums or defined constants instead of magic numbers.
The question here is what are mainType and subType and whether a switch / if-else block should be used at all.
That would depend a lot on the rest of the code and where else this variable is checked, but the fact it is called "type" suggests it defines a type of some description and should probably use polymorphism, with possibly something along the lines of...
and of course the subtype itself might also be a polymorphic class.
You might want each class to have a unique identifying numeric code if you are going to serialize it or persist it in some way and then will have to construct it back again. In that case you should register a factory against the enumeration to construct the appropriate class.
Once again too many comments on here pick on the "obvious" and fail to see the overall picture.
Admin
@Deadcode: The switch statement is still not maintainable. Obviously the code avoid magic numbers to improve readability.
Admin
Obvious troll is obvious.
I will now commit harakiri for having propagated the meme....
Admin
enum is better than #define, but either way it is not extensible. If you add another case you must edit the code.
Using polymorphism you can add new implementations without modifying the existing code.
It is likely also that this number is used in more than one place, in which case if you add in another case you have to modify the code in several places.
switch has its purpose: where an object changes its state during its lifetime. Also commonly where there are two special cases, 0 and 1, and everything else follows the "default" path (and it is not related to the type of an object but something like the size of a returned data-set).
Admin
Short and beautiful.
s = ((m == 7) ? 4 : (m == 9) ? 6 : (m == 11) ? 9 : 0);
Admin
I've always used that in all my programs: (hello world) void main(){ while(true){ cout << "Hello World!" << endl; break; } }
The advantage is that your code only executes in dimension where "true" is true. You wont believe the things your algorithms can get up to when logic no longer works like here.
Admin
In C++ main must return int not void
Admin
@Cbuttius Ok, obviously my proposal with the defines was just fooling around (the deliberately bad choice of names for the define might give a clue...).
If I wanted a clean and well readable C implementation, I'd probalbly do it this way:
or shorter, easier maintainable (separate code from data), more runtime efficient and maybe even more secure (duplicate mainType entries are discovered as compile time) but probably makes the toenails of most OO developers curl:
source.c:
map.m:
Cheers, Throsten
Admin
If I were doing it in C (rather than C++), and the main types were close enough to 0, I would not do it your way but would use an array something like:
If it is C++ you can improve it by having an object with a constructor that constructs the table for you, thus you don't need to remember to call the initialisation function (although with C++ you would probably use polymorphism because it's clean enough, while with C passing function pointers about is very messy).
The big advantage though is that you get constant time lookup.
Admin
@Cbuttius
Why use an enum here? How would you name the mambers? map_type_0, map_type_1, ... ? If they are close to zero I'd use a table rightaway:
No explicit initialization required, just check
(sizeof is executed at compile time.) But the example looks like the tale is not that populated, so it is a waste of memory. On embedded system (especially those whithout a file system :-)) this might be not acceptable.
Admin
The real wtf here is 'WTF do those magic numbers mean???' =D
Admin
you could eliminate the unconditional break with a tail-controlled loop as in
do { ... ... ... } while (false)
;-)
Admin
I think this is a useful pattern that might come in handy. Unusual, but not wtf.
Admin
That's not what I meant at all. Nor am I talking about any particular pattern per se. But I suspect you know that.
Admin
STILL not semantically equivalent to the original code!
Admin
Except that we have no idea whether subType's type's operator=() has the side effect of altering the value of mainType. So you'd HAVE to break after each assignment...!
Admin
Maybe the "mainType" class has an overloaded "==" operator. If that is the case, then using a switch on "mainType" wouldn't be straighfoward. However, you could come up with something muy elegante like this .
Admin
In this case, each if is tested. With an else-if or switch structure, it only continues to test up to the first true if statement.
Admin
Oh noes, but what will we do when we need to call MainTypeEightStrategy!?, obviously, you need to have a dynamic code generation system that parses XML thats retrieved via SOAP tunnelled over an encrypted SMTP relay, which generates new methods dynamically as they are called/needed, causing failproof code!
CAPTCHA: causa , like cause, but the dude to made it happen, "I'm the causa u playa' "
Admin
I just hate long blocks of flow control.
I can't tell if thats winning the fail contest or failing the win contest.
CAPTCHA: Saepius, I guess like chimp royalty?
Admin
Captcha: quis. Quissiness? Queasiness?
Admin
Admin
Wimps, all of you
subType = (int)Math.Round(1.25 * mainType - 4.9167);
Admin
I don't understand how this is C++ code at all. By all rights, this should have something similar to:
And again, if this is embedded or something, then they are mostly just writing C code with a C++ compiler. C++ is, afterall, a lot like several languages mushed into one. But that code snipped isn't "C++ish" at all, it looks like pain-jane C.
Admin
Admin
Admin
Admin
But where is multiple inheritance?
You just can't get true C++ elegance without it!
Admin
Admin
That is not possible unless the values are regularly spaced. If the values are 1, 2, 3, 4, 100, 59087, then an indexed Goto would not work.
Admin
Admin
(i lol'ed :D)
Admin
Admin
Why just procedural? I've seen ugly crap like that in OO code. Knowledge of fundamental control structures (or lack thereof) are independent of the programming paradigm.... just saying.
Other than, that is one ugly code snippet.
Admin
[BANG! Thump.]
Admin
Just procedural?