• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Waaayoff

How often do you revisit your hacky solutions or "ToFix" comments?


27 posts in this topic

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".

0

Share this post


Link to post
Share on other sites

I have a kind of a todo list in my tiny slowly progressing game project, with a section for things that i should go through when something falls apart for no apparent reason.

0

Share this post


Link to post
Share on other sites

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.

Edited by Icebone1000
0

Share this post


Link to post
Share on other sites

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 tongue.png)

 

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.

0

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

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:

void Serialize(Serializer &serializer, std::string &value)
{
	//Serialize the string size.
	uint16_t size = value.size();
	Serialize(serializer, size);
	value.resize(size);
	
	//Serialize the characters.
	char *cStr = const_cast<char*>(value.data()); //DANGER: Hack. I'm using the .data() function of std::string to write to std::string's internal buffer.
	serializer.Serialize(reinterpret_cast<Byte*>(cStr), size);
} 

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.

0

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

Most programmers abhor unclean code and will naturally fix hacks if given the time (see 20% time).

 

But honestly, it depends on the hack. There are levels of hack from "ugh, slightly dodgy downcast here" to "mondo hackitude o rama" (thanks Microsoft biggrin.png ).

 

It also depends on the program. If it's a library that will be used by millions of users, fix the damn hack. If it's your own little project, well, it's your time... fix it or not at your discretion.

 

But if it's in a program that you are being paid to write, you have a financial responsibility to your employer. Do a cost benefit analysis.

  • How long will it take to fix? 
  • How will the product be better if I fix this?
    • Will it be faster?
    • more stable?
    • will it ease future development?
  • or more importantly, what are the risks of not fixing it?
    • Can the hack cause a crash?
    • or worse still.. data loss? Users will forgive a crash, but losing work (a saved game for instance) will really annoy them.

At the end of the day, you are paid to make sensible decisions about how to use your time.

 

Pragmatism trumps idealism every time. 

Edited by ChaosEngine
0

Share this post


Link to post
Share on other sites

My code generally [i]starts[/i] 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.

0

Share this post


Link to post
Share on other sites

Most programmers abhor unclean code and will naturally fix hacks if given the time (see 20% time).

 

But honestly, it depends on the hack. There are levels of hack from "ugh, slightly dodgy downcast here" to "mondo hackitude o rama" (thanks Microsoft biggrin.png ).

 

Didnt Bill Gates said he prefer lazy ppl because they find ways to do the work faster and easier?

0

Share this post


Link to post
Share on other sites

 

Most programmers abhor unclean code and will naturally fix hacks if given the time (see 20% time).

 

But honestly, it depends on the hack. There are levels of hack from "ugh, slightly dodgy downcast here" to "mondo hackitude o rama" (thanks Microsoft biggrin.png ).

 

Didnt Bill Gates said he prefer lazy ppl because they find ways to do the work faster and easier?

Dunno if Gates said that, but I'd agree with it.

To paraphrase Terry Pratchett "it takes a lot of work to be truly lazy".

0

Share this post


Link to post
Share on other sites

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.

Edited by StubbornDuck
0

Share this post


Link to post
Share on other sites

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'

0

Share this post


Link to post
Share on other sites

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
0

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

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.

 

 

 


void Serialize(Serializer &serializer, std::string &value)
{
	//Serialize the string size.
	uint16_t size = value.size();
	Serialize(serializer, size);
	value.resize(size);
	
	//Serialize the characters.
	char *cStr = const_cast<char*>(value.data()); //DANGER: Hack. I'm using the .data() function of std::string to write to std::string's internal buffer.
	serializer.Serialize(reinterpret_cast<Byte*>(cStr), size);
} 

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.

 

out of curiosity, why didn't you call c_str() instead?

0

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

out of curiosity, why didn't you call c_str() instead?


.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. tongue.png  That's what this thread is for, right? wink.png 
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. rolleyes.gif

Edited by Servant of the Lord
0

Share this post


Link to post
Share on other sites
I alway refactor/fix my shit unless its in code i havent visited in months (thats legacy code then lol)
0

Share this post


Link to post
Share on other sites

Always, although I never use TODO for fixes or for hacks (never even used the HACKED task), in fact all I use TODO for is for future additions to the project that I want but don't have time to implement yet. For fixes / hack checking isn't that best done through unit tests and have full code coverage of the area, at least that way it would always fail until you fix it and you can apply the assertion checks globally too if necessary as a fix in one area could just give birth to a bug in another.

 

Edit: Ofc this isn't always the easiest way to test graphics / sound / scene logic issues but then sticking a TODO flag may not be the most efficient method either, well not for me at least anyway

Edited by Dynamo_Maestro
0

Share this post


Link to post
Share on other sites

Code can pass any and all unit tests you could write, but still be in dire need of fixing/improvement. Performance issues, working well with future expansion, etc. Lots of reasons to still maintain a ToDo list along side other things.

0

Share this post


Link to post
Share on other sites

Code can pass any and all unit tests you could write, but still be in dire need of fixing/improvement. Performance issues, working well with future expansion, etc. Lots of reasons to still maintain a ToDo list along side other things.

 

I agree, I am not saying TODOs are bad I am just saying I never use them for 'fixing' stuff or for anything important for that matter, for extending projects they are great, things typically not part of the project gantt (which is directly connected to my code work items via TFS) but could be a great addition, a wish list I guess. I think my post may have made it look like task lists in general are bad, this isn't the case, im not sure how other version controls work or how others manage but for me it is VERY important for me to ermm analyse, schedule my project work outside code if that makes sense. TFS and ofc VS have some excellent ways to do this, so I cant really use TODO for anything other than a unexpected wish list I guess.

 

I don't think this is an uncommon way of doing things either, as these are all built in features.

0

Share this post


Link to post
Share on other sites

That code looks pretty dodgy to me.


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. rolleyes.gif

 
Hmmm, come to think of it, &str[0] also ensures that compiler implementations doing clever things behind the scenes like copy-on-write strings handle the situation correctly. GCC iirc, still uses COW for relatively recent versions of the compiler. C++11 requires std::string to not be COW, but last I heard GCC hadn't yet changed their std::string implementation. So my const_cast actually could be buggy.

I still think .data() ought to return a non-const pointer. wink.png

Edited by Servant of the Lord
0

Share this post


Link to post
Share on other sites

If you are worried so much about performance you can't read the data into an intermediate buffer, you are probably reading too few bytes of data which is likely inefficient.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0