Sign in to follow this  
Nicholas Kong

Is hacky code allowed in industry?

Recommended Posts

Nicholas Kong    1535

I find myself doing something like this alot. Basically setting a condition to false to avoid the if block from running more than once. 

If I do not turn it off, the mushroom will keep appearing.

 

The hacky code is isHit = false;

Given a update method that constantly get executed from the game loop in this pseudo code.
 
[code]
public class Mario{
 
public void collide()
{
        Block.setHit(true)
}
 
}
[/code]
 
[code]
public class Block
{
    public void setHit(boolean hit)
    {
        this.hit = hit;
    }
  
 
   public void update(long milliseconds)
   {
      if(isHit)
      {
                // hacky code
                isHit = false;
                Mushroom mushroom = new Mushroom(50,50);
                Game.getInstance().add(mushroom);
      }
 
    }
}

So my question is: is hacky code allowed in the industry?

Do industry professionals or game developers use hacky code in their game code?

 

I always found hacky code to fix all the bugs in my game and let me progress faster in my game development process.

Edited by warnexus

Share this post


Link to post
Share on other sites
tychon    652

There are kludges in any industry, though with varying degrees of frequency. The question isn't whether or not they exist but why they happen. I've only done games as a hobby, so I can't comment much on patterns for that industry, but my experience with them is that a kludge happens when deadlines loom, developers gloom, and project managers give out ultimatums of doom. In general, a kludge is a sign that either your design isn't working, you don't understand how to work with your design, or you're in a very funky context. The last one being rather uncommon.

 

Given that Mario.collide is calling a method on Block, is there some reason you can't have Block.createMushroom or Block.collide(thingHittingMe)? Does it need to be in update for some reason? An event makes more sense to me than an update loop for a context like this--the collision happens once at one moment and really only needs to fire off, "Hey, I've hit something!" to the interested parties (usually those involved in the collision). It's a lot cheaper than every few milliseconds, "Am I hit? Am I hit? Am I hit? I'm hit! Am I hit? Am I hit?"

Share this post


Link to post
Share on other sites
HappyCoder    5052
I interned at Microsoft and before I could commit my code to the master code repository other people had to review it and they would point out anything I did poorly. They would sometimes suggest alternatives but other times I had to fix it up myself. I realized that many times I would to a hacky solution more because I didn't want to take the time to find a better solution but in the long run you save time by making good design decisions for more elegant solutions. Hacky solutions usually are parts of more bugs later on. If it is allowed will depend on where you work but as I a rule of thumb I think it is good to avoid the hacky solutions, with the possible exception of if you are working on a prototype that you will throw away later.

Share this post


Link to post
Share on other sites
Hodgman    51222

It depends how close you are to a deadline tongue.png

If the game has two months of work left before it's finished, but the publisher wants to see a working/finished version of the game in two-weeks, then all sorts of horrible looking "duct tape" code starts appearing, which may work for now, but is barely managing to hold itself together!

Share this post


Link to post
Share on other sites
Buster2000    4310

Hacky code is frowned on and there are code reviews and code style guidelines to try and prevent it.  However hacky code still gets through.  In the games industry you are likely to find a lot more hacky code than anywhere else though because most games code is throwaway code.

Share this post


Link to post
Share on other sites
StubbornDuck    602

Depends on where you work entirely, and the general stress level. Good programmers would rather fix stuff like that properly, but management and/or reality may disagree about that priority.

 

 

 


IMHO hacky code is OK if it's used as a stepping stone. Actually, many times I've found that adding a lot of hacky dependencies allows you to use the resulting code smells as a guide to find the architecture.

 

Agree on this one, if I can't immediately see a clean solution I may start out with a hacky one and then refactor it later once it becomes clear exactly how the related code meshes together. (Or I don't even start implementing it until analyzing it further. Starting to code when you don't know what you're doing is a major time waster.)

Edited by Petter Hansson

Share this post


Link to post
Share on other sites
Adyrhan    216

 Hacky code is not allowed, but when there are deadlines is tolerated. I think that sums it pretty much.

 

I'm actually working in a product for a client and from time to time he asks for some more functionalities. It happens that if I would go the safe route and take my time to design proper and clean code, my clients go hunting me constantly asking for progress and they go with a bad feeling about my services. If i do hacky code, I deliver much faster and they say ohh you are very productive, but its obviously a trap not only for them but for myself. What happens is that after two or three updates, code gets messy and difficult to modify and even understand after some time since its writing, you already know the story. What I do now is to clean an even rewrite those hacky lines of code only after delivering even when they dont expect a second release. Its more work for me but with this I get saved from the chaos, they get a free update and the code is ready for being upgraded with more functionality if the client requests it.

Edited by Adyrhan

Share this post


Link to post
Share on other sites
Nicholas Kong    1535


If you’d taken all those times you ran away from proper design via hacks and instead took the time to do it right, the easy solution to the problem you suggested would be obvious to you by now. Every time you use hacky code you miss out on a chance to learn. Remember that.

 

I will bear in mind. Wow! Thanks for the truth about hacks.

Share this post


Link to post
Share on other sites
I have seen something similar to what you are referring to as a "hack" many times in the software development industry. I am not sure if this is the official name for it, but at my job we refer to it as a "latch". It is usually used to stop normal functionality when the form "IsLoading" or something of the sort.

Share this post


Link to post
Share on other sites
Nypyren    12061

Where I work, hacky code appears:

 

- When the programmer is not experienced enough and/or does not care enough to write good code.

 

- When the system has already been implemented (with nice, clean code) and the product managers decide to drastically change it close to a deadline.

 

- When a programmer leaves the company without documenting his systems and another programmer is told to make changes to the system close to a deadline.

Share this post


Link to post
Share on other sites
kalle_h    2464

Sometimes you need hacky solutions for bugs that are out  of your control. Yesterday I fixed bug where new Apple A7 chip renderered pure black if there were shadow receivers but no casters with horrible kludge where I render small sub pixel size triangle to center of shadow map. This fixed nasty bug just before deadline.

Share this post


Link to post
Share on other sites
rpiller    839

Your collision callbacks should be more robust. You should have OnCollideEnter, OnCollide, OnCollideExit. Enter and Exit will only ever be called once per collision with a given object. OnCollide would fire each frame. This way you can put your mushroom creation in the OnCollideEnter so it's only called once per collision.

 

Who cares if the industry allows hacky code. You should try to not make it hacky if possible. If you don't have control over your collision library and it doesn't support the enter/exit thing then you have to do what you have to do to make it work. It just so happens that you picked a path that is a little wasteful.

 


I always found hacky code to fix all the bugs in my game and let me progress faster in my game development process.

 

This is another way of saying you get lazy. It's not the end of the world. We all get lazy in different aspects of our lives (even football players who get paid millions sometimes "take plays off"), but it's important to know that's what you are doing (if it's a hobby project). Don't deny that fact or try to justify it in any way.

Share this post


Link to post
Share on other sites
Nicholas Kong    1535


When the programmer is not experienced enough and/or does not care enough to write good code.

 

No! I do not want to be that guy. Okay. I am def going to have to find a better way soon enough. This is the toughest part.

Share this post


Link to post
Share on other sites
cardinal    908

The amount of hacky code in professional game code depends entirely on how strict the team's leaders are. I've been on teams where every bug I fix seemed to be the result of some hack, and I've been on teams that are very strict with code reviews and would not allow hacks at all. Generally the latter teams had better products commercially and critically than the others.

 

Deadlines and laziness generally are the main causes for hacks. On my current team, the only acceptable time for a hack is right before going into certification, and only if it's a localized targetted fix where the proper solution (which we also have prepared) would require extensive testing since the fix touches many game components. Generally the process there would be to send the hack (after testing) through certification and testing the proper fix extensively while waiting to hear back from first parties (Sony/Microsoft). If there are bugs preventing certification we would evaluate our testing on the proper fix and include it in the next submission. If the games are certified with the hack, then so be it.

Share this post


Link to post
Share on other sites
Nicholas Kong    1535


This is another way of saying you get lazy. It's not the end of the world. We all get lazy in different aspects of our lives (even football players who get paid millions sometimes "take plays off"), but it's important to know that's what you are doing (if it's a hobby project). Don't deny that fact or try to justify it in any way.

 

Interesting statement. I will come up with a better design to avoid hacky code or latch. Thanks.

Share this post


Link to post
Share on other sites
EarthBanana    1794

I wrote some hacky code back when I was prototyping the rendering part of my engine out - just trying to get stuff together and render some meshes on the screen..

 

well I forgot to go back and fix it..

 

3 months later certain types of meshes would scale and rotate what seemed in a random fashion - took 1 week to find my problem - took about 30 mins to rewrite the bad code...

 

so - I think most of the time it pays to take the 30 mins rather than the week

Share this post


Link to post
Share on other sites
Orymus3    18821


Given that Mario.collide is calling a method on Block, is there some reason you can't have Block.createMushroom or Block.collide(thingHittingMe)? Does it need to be in update for some reason? An event makes more sense to me than an update loop for a context like this--the collision happens once at one moment and really only needs to fire off, "Hey, I've hit something!" to the interested parties (usually those involved in the collision). It's a lot cheaper than every few milliseconds, "Am I hit? Am I hit? Am I hit? I'm hit! Am I hit? Am I hit?"

 

I'm faulty of going that road too, very often. I have a post-it on my left screen (coding screen) that says exactly 'use events!' and it helps.

 

As for, is it acceptable in the industry: not really.

Does it happen?: All the time!

 

The thing is, no client (whether it be internal or external) will flat-out say that it's acceptable to code cheaply. They all want quality for cheap, but only some of them actually have realistic budgetary estimates.

Then you need to account for the quantity of change of direction during production, how late it happens, etc.

These tend to lead to hacky code appearing in the codebase. The technical debt increases, and through escalation of commitment, it gets more and more ignored (and not refactored).

 

As an 'indie developer', I give myself a guideline that goes as follows:

Code 5 days.

Refactor 1 day.

Take 1 day off.

 

During the 5 days I develop, I try to make things as 'fast' as possible.

During the refactor day, I take all the things I've done and consider how to make it more efficient, cleaner, etc. I break longer functions into smaller ones, fix my encapsulation usage of local vars, etc.

No later than yesterday, I've fixed a problem exactly like yours (occurring in an onEnterFrame loop and using a hacky Boolean to make sure it happens only once). It was taxing my loop unnecessarily and I switched that to an actual Event.

 

Whether it ends up being acceptable or not, I think you should aim at being able to avoid it, so that when given the time, you are able to code cleanly. The idea is that, if you're not rushed early in dev, you'll be able to do a clean codebase and keep relatively the same velocity over time.

Share this post


Link to post
Share on other sites
cr88192    1570

I recently was faced with a bug which was pretty annoying:

periodically, all the point-light sources would momentarily fail, causing the scene to periodically go into full darkness.

 

long story short, eventually figured out that it occurred whenever the shadow maps were being redrawn (basically redrawing the scene via FBOs and a cube-map), but would fix itself whenever the scene-visibility was re-evaluated (via occlusion queries).

 

spent a while trying to figure out just where/how the OpenGL state was getting messed up here, but couldn't locate the issue.

 

eventually, I just hacked it, so that the shadow-maps would always be redrawn prior to re-evaluating visibility (rather than afterwards), which fixed the issue (even if the actual cause of the bug was not determined).

 

better still would have been to try to properly hunt down and eliminate the bug though.

Share this post


Link to post
Share on other sites
Snovi    142

What's "hacky" about your code?   You seem to have a requirement that collisions with a block should power up a mushroom only once, and have implemented it as such.    

Edited by Snovi

Share this post


Link to post
Share on other sites
rpiller    839

The "hacky" part is that it's wasting cycles by checking an if statement on every update or a block. The more block objects he has in his level the more wasteful his code becomes. This situation in itself isn't the worse but if he does things like this all over the place it could add up. The better approach would be to have an OnCollisionEnter() for Mario which gets called once and only once per collision. Then inside this event create the mushroom. It's more efficient.

Share this post


Link to post
Share on other sites
DrEvil    1148

I tend to think about implementation details in terms of the mechanics of the game. Your example suggests a mario clone sort of block triggering powerups. From that perspective, you need to first think about what the mechanism for triggering the blocks is going to be. Simply colliding with the blocks is too low level of a mechanism with which to trigger the spawning of the powerup. You want mario to trigger the powerup when he jumps upward into the block and collides, and also if the game has the power drop thing that allows you to smash down from a jump with it. Because the triggering of the blocks should be dependent on the type of action that is being performed, it would make more sense to generalize these activities within the state inside the Mario object class, such that when you jump up into something, or smash down onto something, you are calling functions that provide that context, and the objects being hit can respond accordingly.

 

Some example pseudocode

enum HitFeedback
{
    FEEDBACK_NOHIT,
    FEEDBACK_HIT,
};

class Mario : public GameObject
{
    void collide( collisionevent )
    {
        HitFeedback hit = FEEDBACK_HIT;

        // assuming -z is down
        if ( collisionevent.normal.z < 0.5 ) // did we jump up into the object?
            hit = collisionevent.otherObject.HeadSmashed( this );
        else if ( collisionevent.normal.z > 0.5  && IsSmashingDown()  ) // did we fall down into the object in the smash down state?
            hit = collisionevent.otherObject.SmashDown( this );

        if ( hit == FEEDBACK_HIT )
        // handle landing on slopes or ground to change state to walking, etc
        if ( hit == FEEDBACK_NOHIT )
        // allow the character to continue its current physics state, if flying, keep flying, if smashing, keep smashing
    }
}

// Then your various other game objects can easily implement responses to the game mechanics available by your player

class BreakableBlock : public GameObject
{
    void HeadSmashed( Mario & player )
    {
        Break();
        return FEEDBACK_HIT;
    }
    void SmashDown( Mario & player )
    {
        return FEEDBACK_NOHIT; // so that mario can continue smashing down a column of breakable blocks
    }
}

class PowerupBlock : public GameObject
{
    void HeadSmashed( Mario & player )
    {
        // implemented via a state as it likely involves playing an animation and isnt just an immediate spawning of the powerup
        ChangeState( SPAWN_POWERUP );
        return FEEDBACK_HIT;
    }
    void SmashDown( Mario & player )
    {
        ChangeState( SPAWN_POWERUP );
        return FEEDBACK_HIT;
    }
}
class CoinBlock : public GameObject
{
    void HeadSmashed( Mario & player )
    {
        if ( mCoinsRemaining > 0 )
        {
            player.AddEvent( AddCoin( 1 );
            --mCoinsRemaining;
            if ( mCoinsRemaining <= 0 )
                ChangeState( DEACTIVATED ); // animate, disable callbacks, etc
        }
        return FEEDBACK_HIT;
    }
    void SmashDown( Mario & player )
    {
        // same action as HeadSmashed
        return HeadSmashed( player );
    }
}

class Turtle : public GameObject
{
    void HeadSmashed( Mario & player )
    {
        // hitting a turle from below is damaging, and should probably be treated as solid
        player.AddEvent( Damage( 1 ) );
        return FEEDBACK_HIT;
    }
    void SmashDown( Mario & player )
    {
        ChangeState( FLIPPED_OVER );
        // add some small velocity so the turle gets knocked to the side a bit from where mario smashed down
        return FEEDBACK_NOHIT; // so that mario can continue smashing down to the ground
    }
}

Implement things with respect to game mechanics, and not so much the low level functionality of collision, physics, sound. Those low level systems will often be intricately tied to the function of certain mechanics. In marios case there will be some degree of complexity in interpreting the physics and collision information into a way that gets the actual game mechanics working as you want, but most of those details would ideally be encapsulated into the objects where it matters, such as your Mario class in a simple implementation. The game objects can provide some amount of hit information back from its callbacks such as in this case, so that the type of object can propagate back and effect

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