I was just looking at some (working) code that i wrote a couple of years ago that's buried deep in my rendering engine. There was quite a few of these "solutions" that i completely forgot about. I found it pretty funny that i wrote before a particular hacky solution: "Dirty hack... fix later".

"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "

I am afraid to type TODO in visual studio find popup.. Since its a hobby project for learning purpose, I only go back when things break.

Im doing an engine and a game, so while the game is running I dont mess with the engine, unless its just to add new stuff that I need and the engine doesnt provide.

Means the TODO comments only grows. Im telling to myself that when the game is over I will go throu all the problems I already identified and redo everything in a better way. I dont do this now cause the game is running fine, and I dont want to take a side quest with the engine and make the game break till the quest is complete.

Whenever necessary. If the "hack" gives the desired results and is just ugly for style reasons or wastes a few cycles, I don't bother with it usually. If it breaks the program, it obviously has to be fixed (with another hack )

It's different if the "hack" has influence on your program and leads to writing more hackish code (like using a global as a shortcut and then start using it throughout the program). Those should be fixed asap.

Ehmm... To be fair, so far in my latest projects, there is only one hack that comes to mind that I haven't fixed (river particle stopping code) because I'm working with the UI now.

I will come to it because the sim needs to be right for everything to look remotely good.

Now, on the UI code? I'm on the point that I'm not sure if I am writing hackish solutions or not. Funnily enough I can find out about that by saying "What if I changed Swing GUI for a SWT based one?" and then all the dependencies/fckups become clear.

If it's a really bad hack, I might fix it that same day or the next day, as soon as I get the hacky version functional (because once it's functional, sometimes I can see a cleaner way of doing it that I couldn't previously).

If it's a minor bit of sloppy code, and I really don't want to work on it today, I'll comment it as hacky, and later if I need to expand that function, then I'll usually rewrite the entire function with the new features and cleaner than before.

On very very rare occasions, the 'hack' is the cleanest way of doing something. I only have one of these in my current code base - a const_cast() of a string used to write to its internal buffer:

Potentially very dangerous, but almost certainly workable in major implementations of the standard library - unless the implementation decides to copy its internal buffer at every call to .data(), or unless it has a duplicate buffer for some reason, .data() should return the internal char* buffer of the std::string.

That's clean code but hacky code. I have messier code in several locations, but I don't have anything hackier than that, iirc.

I put a //TODO: *whatever there is to do* at that place in the code and I periodically Ctrl + f//TODO: to find the places where I have something to fix and as a rule I never commit if a single //TODO exists in the code.That way I'm compelled to fix them as soon as I can.Also I've made it a habit to recognize places where things have a tendency to become "tricky", basically the places that will be responsible for a lack of flexibility and the need to use some not so good method/hack and I spend extra care planning the big picture on these places, so I'm sure that everything will go as planned.I used to use a lot more hacks in the past when I had the habit of thinking as I code, but when I started to actually plan my stuff on paper, the tendency to use hacks reduced greatly.

My code generally starts as a list of 'ToDo:' comments, often before the project even gets a proper name.

So, 'most' of my ToDo comments get followed up on, and I can easily reach a 90+% 'finished' on the ToDo list for any given project, even if less than 20% functionality has been implemented. (Some of those ToDo entries are to create other ToDo entries that are needed to flesh out the feature's requirements.)

It might not be right, but it looks impressive if you put it all into a nice big chart.

Old Username: Talroth
If your signature on a web forum takes up more space than your average post, then you are doing things wrong.

I usually put down //TODO: and //POSSIBLE TODO: in my code. The former is generally something I will revisit as it's part of developing the functionality I've been assigned to do - I just need my brain to focus somewhere else for a moment. The //POSSIBLE TODO: category (that I might sometimes abbreviate to //TODO: stupidly enough) are things that at some undefined point in the future might become relevant to change. I rarely end up revisiting these.

Also have //HACK: and //NOTE: tags to warn for and explain WTF-code. Not using these nearly as often, for obvious reasons.

The only time I commit hacks is when we're up against a deadline, the fix is localized and the proper fix requires tons of testing to a bunch of systems. I generally have a proper fixed shelved in perforce for when the game is safe to commit these changes to again.

I often find myself fixing a lot of other engineers' TODO's. Often when tracking down bugs I'll debug down to the problem only to find a comment stating: "TODO: you need to do blah or it will break when blah happens"

I do sometimes leave TODO comments when I want to revisit an existing implementation later on when I have more time, but these aren't usually hacks, just not extensible in the way I'

When the number of "todo" comments crosses some arbitrary threshold - which varies in space-time, aka the "I gotta fix this mess" effect - I focus on getting them down to a sane level before continuing to add more features, if I have time (e.g. no imminent deadline or priority feature to implement). I eventually get around to it for projects I really care about. Eventually.

Well, it depends, of course. If it's things like "todo: improve this later on to support XXX" then I would probably implement it immediately after implementing said XXX out of necessity, unless I found a better alternative in the meantime. If it's a "todo: this could be better", that can wait (possibly indefinitely). If it's a "todo: [insert pseudocode]" then it's obviously just a placeholder to give high-level structure to my code until I actually get around to writing it. I try only to submit working and elegant code to the world, with as little todo's, missing bits and warnings (and free of as many bugs as possible) but sometimes nothing else will do in the time given, and you just gotta put that hack in to make the thing work like you want it to..

Edited by Bacterius, 18 October 2013 - 06:46 AM.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

I wind up doing this with most pieces of code I write that require more than a little bit of thought. My first pass I code with the sole goal of getting whatever I'm trying to do working. Usually by the time it does work the eloquent, or at least not awful, solution presents itself.

it depends, does the "hack" save me several days worth of re-writing code? Then i can live with it. however, if i forsee re-doing things to be structured in a better format, and it would save me future work, i'll go back and redesign things if i need to.

Potentially very dangerous, but almost certainly workable in major implementations of the standard library - unless the implementation decides to copy its internal buffer at every call to .data(), or unless it has a duplicate buffer for some reason, .data() should return the internal char* buffer of the std::string.

That's clean code but hacky code. I have messier code in several locations, but I don't have anything hackier than that, iirc.

c_str is probably more likely to copy the data to put a null terminator on it? He's writing to the string not reading it. That code isn't going to null terminate the string which may violate an assumption the class makes (unless the null terminator is included in the size count). That code looks pretty dodgy to me.

If you read the whole data file into memory beforehand it's probably better to just construct the string from the raw bytes in the file buffer.

I'd just overload Serializer::Serialize to take a string argument though I think. Presumably it knows how to read bytes from the file so I'd read however many is needed then construct the string from the buffer.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

.data() gets a char* string that is equivalent to the data the std::string holds. (pre-C++11)
.c_str() gets a null-terminated char* that is equivalent to the data the std::string holds.

This means that an implementation is more likely to create a copy of the string data for a call to c_str()... in theory. In practice, they almost certainly return the same string pointer.

In C++11, .data() is also required to be null-terminated. So they are even more almost-certainly going to be the same string pointer. Because of this, I chose the one the more closely documented my intent: I wanted to access the internal buffer (the 'data').

c_str is probably more likely to copy the data to put a null terminator on it? He's writing to the string not reading it. That code isn't going to null terminate the string which may violate an assumption the class makes (unless the null terminator is included in the size count).

.data() in C++11 is guaranteed to be null-terminated, just like c_str(). Since it's already null-terminated when I get the buffer (".........\0"), and I'm not writing over the terminator, the end result is still null-terminated..

That code looks pretty dodgy to me.

Absolutely. That's what this thread is for, right?
It's pretty much the only true "hack" I have in my code - I have a few messy functions, but no other 'hacks'.

If you read the whole data file into memory beforehand it's probably better to just construct the string from the raw bytes in the file buffer.

I'd just overload Serializer::Serialize to take a string argument though I think. Presumably it knows how to read bytes from the file so I'd read however many is needed then construct the string from the buffer.

Yea, that would be ideal. I wish I could just hand std::string a null-terminated char* buffer for it to take ownership of, and that I could take() ownership of it's own null-terminated char* buffer (with the std::string then becoming an empty string, similar to move-semantics).

The problem with overloading Serializer::Serialize() for a string argument, is the std::string still won't take ownership of the char* buffer you'd read the data into - a completely unnecessary copy of every string read will always take place for no reason, unless you write directly to the string's buffer.

I should actually use &str[0] to get a non-const pointer to the internal data... oops. That'll let me avoid the const_cast, but it'll do the same thing anyway. Really, they ought to just make .data() return a non-const pointer.