When planning ahead or deciding what to do next, how do you choose?
Work stack
By work stack I mean that when you think of something new, start working on it; when you're done, go back to what you were working on. If you've ever worked with someone who bursts into the room and shouts with joy, "I just got a great idea! Drop everything and work on this now!" then you'll be familiar with the result: you end up going nowhere. These constant interruptions are highly disruptive and cause unfocused thrashing and churning. The product owner doesn't get what they want because their next idea interrupts any progress on the current idea and they don't get what they need because the focus is always on something else. Most of the time is wasted on incomplete, buggy, useless features. I have nothing positive to say about doing things this way because in my experience, it's by far the most wasteful. This is like trying to swim across a river by jumping in and moving your arms and legs in every direction as fast as you can: you might make it across but you'll probably just suffer and die.
There's also a more subtle and personal work stack too. This is where you see something near what you're working on and you decide to take a short detour to fix it or clean it up. If you're especially prone to this then you can end up wandering from one little detour to another and not accomplishing what you set out to do. I've found that I've gotten much better at avoiding this by focusing on finishing one feature before starting on another and setting aside time specifically to refactor and payoff technical debt.
Work queue
A work queue is the opposite: new ideas are added to the end of the list and you'll get to it after you finish everything before it. This sounds a lot like Big Design Up Front and suffers the main drawback too: solutions you come up with probably will be bad since you know the least at the beginning of the project. If you have a long list then when you learn something new, it will be a long time until you can benefit from it. I think human nature and our eagerness to implement new ideas makes it just about impossible to stick to this method - which is for the best.
Horizontal slice: Front end first
You could try the tiered architecture approach and do the outside first. This gives early visible progress but there's a lack of functional progress. Unfortunately, non technical people often don't see the difference between "gui is done" and "app is done". Having such a large disconnect between the customer and team is a recipe for disaster.
Horizontal slice: Back end first
You could try the tiered architecture approach and do the outside first. This gives early functional progress but there's a lack of visible progress. Very few users understand the difference between "non existent app" and "98% of the use cases have passing automated tests". If the person paying your bills doesn't think they're getting anything for their money then it doesn't matter how close you are to really being done because you won't get a chance to finish.
Minimum cost
How about doing the smallest and easiest things first? This has a lot of good things going for it: you make quick and early progress, you're always doing the easiest work available, and you'll probably spend most of your time on things you enjoy and are good at. But as you go you'll find that everything becomes more difficult and risky since you've been putting it off. You may not have a usable product for a long time and what you do have will probably be missing important functionality. Or you can spend a lot of time and only too late discover that the hard parts will be too expensive and the whole thing was a waste of time. Unfortunately for those who prefer the easy way, the hard parts are often what solve the real problem and make software worth it.
Maximum cost
How about doing the most difficult or risky things first? This also has a lot of good things going for it: solving hard problems (or even working on them) can boost morale, you reduce risk over time, the pieces you work on will become easier over time, and if it's too difficult, risky, or expensive you cut your losses before making a huge investment. But there are downsides. Just like when working the minimum cost first, you may not have a usable product for a long time and what you do have will probably be missing important functionality. You'll also be making a lot of long term solutions to hard problems that may be bad since you know the least at the beginning of the project. And possibly the biggest drawback is that difficult problems require skilled teams with skilled people who work well together, which you may not have at the beginning.
Important and urgent first
It seems like thinking about things first works best so far. Hopefully that's not too surprising. Maybe we should try using two variables to categorize things instead of putting things on a high-to-low, inside-to-outside, or newest-to-oldest spectrum? You could use an importance and urgency matrix with 4 quadrants: high importance and high urgency, high importance and low urgency, low importance and high urgency, and low importance and low urgency. Everything that needs to be done is placed in one of those quadrants and you come up with some rules about working the important before the non-important and the urgent before the non-urgent. Sounds good in theory but from what I've seen, it really devolves into two categories: "get to it when we can" and "ignore". Eventually someone will say "this is very high importance!" and someone else will say their task is "critical importance" and another becomes "ultra critical importance" and before you know it, you get importance inflation where the only way to get something worked on is to say we're all going to die unless it gets done by tomorrow. Unfortunately, the difference between Important and Urgent (and sometimes even Nice To Have, or Just Putting Words Together With No Clear Thoughts) seems impossible for some people to understand.
Maximum value
Take your to do list, order it by how much value you'll get from each thing, and call it a backlog. By focusing on the most valuable things first you'll get usable software sooner and as we know, "working software is the primary measure of progress." One of the best things about the list as a developer is that the opportunity cost is clear and can't really be argued. Lets say someone tells me that a certain issue needs to be handled asap. Since two things can't be at the top of the list at the same time, I can ask them what items I should move down the list to make room for it. Should I delay the bugfix that's costing us thousands of dollars a day? How about the feature that the CIO himself asks be about each morning and evening? Or maybe the feature that will prevent our largest client from leaving in a month? Suddenly their request isn't as important as they thought is was. The biggest downsides are that deciding the relative value of things takes discipline and knowledge and that some clients have an all or nothing mentality. The idea that even the tiniest feature might be left out or is less valuable is unacceptable to them.
I've found that I'm most productive and happy when I change it up to maintain flow. I'm almost always trying to focus on maximum value but sometimes visible progress, easy wins, or tackling tough problems soon is important. After all, working software is the primary measure of progress but not the only.
Wednesday, October 31, 2012
Saturday, October 20, 2012
October 2012 challenge, Day 20
Well, I failed.
I got the core mechanics and everything done in just a couple days but I only had a few hours a week to work on music, sounds, graphics, and extra content. That just didn't happen. So, as tough as it is for me, I've admitted that I should cut my losses and stop worrying about it.
Retrospective time!
I should start learning the language, tool chain, graphics, music, and sound before committing to a project. I hadn't used haxe before (but I'm somewhat familiar with Actionscript) so the language, libraries, and compilation process and quirks took some time to get. Despite 6 or so years of piano lessons, I don't know anything about making good computer music either. Pixel graphics wouldn't fit the theme and good looking graphics are beyond what I can do. I had some good luck with procedurally generated plant graphics, but couldn't quite integrate it with my game code due to how the rendering code worked.
I should stop planning on spending all of my time working on a project with so many unknowns . I have less time than I expected and it's not sustainable. After a week of nothing but work, sleep, and this project, my place was a mess and it was hard to stay focused. If I picked a smaller project - like a platformer or turn based strategy - then I think I would have had a better chance of finishing. I can do old-school graphics and sound effects so that's what I should stick to.
I should continue writing well factored code and trying short term projects like this. Breaking it down into pieces that I could prioritize and implement in a couple hours helped me get started and make early progress. The simple and clean code meant that I could change my mind, try something different, and generally make progress much faster than some of the messier code bases I've crapped out.
If I follow these simple plans, then I'll be much better equipped for the next ludum dare.
I got the core mechanics and everything done in just a couple days but I only had a few hours a week to work on music, sounds, graphics, and extra content. That just didn't happen. So, as tough as it is for me, I've admitted that I should cut my losses and stop worrying about it.
Retrospective time!
I should start learning the language, tool chain, graphics, music, and sound before committing to a project. I hadn't used haxe before (but I'm somewhat familiar with Actionscript) so the language, libraries, and compilation process and quirks took some time to get. Despite 6 or so years of piano lessons, I don't know anything about making good computer music either. Pixel graphics wouldn't fit the theme and good looking graphics are beyond what I can do. I had some good luck with procedurally generated plant graphics, but couldn't quite integrate it with my game code due to how the rendering code worked.
I should stop planning on spending all of my time working on a project with so many unknowns . I have less time than I expected and it's not sustainable. After a week of nothing but work, sleep, and this project, my place was a mess and it was hard to stay focused. If I picked a smaller project - like a platformer or turn based strategy - then I think I would have had a better chance of finishing. I can do old-school graphics and sound effects so that's what I should stick to.
I should continue writing well factored code and trying short term projects like this. Breaking it down into pieces that I could prioritize and implement in a couple hours helped me get started and make early progress. The simple and clean code meant that I could change my mind, try something different, and generally make progress much faster than some of the messier code bases I've crapped out.
If I follow these simple plans, then I'll be much better equipped for the next ludum dare.
Wednesday, October 10, 2012
October 2012 challenge, Day 10
I only had a few hours to program over the weekend but I managed to get saving and continuing to work - which took much longer than I expected. If you're looking for advice on how to save objects to the SharedObject with Flash or haxe and nme, I ended up relying on the Memento Pattern.
Here's the relevant part of the Fruit class:
One place where this was tricky was with the creatures' needs. Each creature has a list of needs that implement the Need interface. Since I don't know the real class at design time, it has to be handled differently. When creating the memento for needs, the class name is included and when converting the memento to the real object, a separate class takes the memento, looks at the need field, and has a switch statement that tells the appropriate class to create an instance from the memento. Here's the relevant part of the NeedToEatFruit class:
Apart from that, I made some simple placeholder graphics for the plants and got the basic plant lifecycle to work. There's twelve species of plants. Some float to the surface, some are buoyant enough to float around, and others are planted in place. The simple ones are just a sprite but the more complex ones grow separate leaves. They can reproduce by budding, spores, seeds, or fruit. When a fruit-eating animal eats a fruit, it will wait 5 seconds or so then drop a seed of that plant. And that's why the Creature class has a pooCountdown field.
Next up is animal graphics, lifecycle, and more needs as well as changing the world structure. It's currently Perlin noise but when targeting the mac, it runs out of memory trying to make it. Really odd.
Here's the relevant part of the Fruit class:
public function toMemento():Dynamic { return { x:x, y:y, vx:velocity.x, vy:velocity.y, maxSpeed: maxSpeed, maxAge: maxAge, type: type, plantType: plantType, age: age, }; } public static function fromMemento(o:Dynamic):Fruit { var c = new Fruit(o.x, o.y, o.type); c.velocity.x = o.vx; c.velocity.y = o.vy; c.maxSpeed = o.maxSpeed; c.maxAge = o.maxAge; c.age = o.age; c.plantType = o.plantType; return c; }
One place where this was tricky was with the creatures' needs. Each creature has a list of needs that implement the Need interface. Since I don't know the real class at design time, it has to be handled differently. When creating the memento for needs, the class name is included and when converting the memento to the real object, a separate class takes the memento, looks at the need field, and has a switch statement that tells the appropriate class to create an instance from the memento. Here's the relevant part of the NeedToEatFruit class:
public function toMemento():Dynamic { return { need: "NeedToEatFruit", target: target == null ? null : target.toMemento(), } } public static function fromMemento(o:Dynamic):Need { var n = new NeedToEatFruit(); n.target = o.target == null ? null : Fruit.fromMemento(o.target); return n; }
Apart from that, I made some simple placeholder graphics for the plants and got the basic plant lifecycle to work. There's twelve species of plants. Some float to the surface, some are buoyant enough to float around, and others are planted in place. The simple ones are just a sprite but the more complex ones grow separate leaves. They can reproduce by budding, spores, seeds, or fruit. When a fruit-eating animal eats a fruit, it will wait 5 seconds or so then drop a seed of that plant. And that's why the Creature class has a pooCountdown field.
Next up is animal graphics, lifecycle, and more needs as well as changing the world structure. It's currently Perlin noise but when targeting the mac, it runs out of memory trying to make it. Really odd.
Friday, October 5, 2012
October 2012 challenge, Day 5
If you look at it a certain way, then I'm almost done. If you look at it the real way, then all that's left is the stuff I'm not good at.
After some late night work, pre-work work, and lunchtime work, I've got the core ideas working so now it's mostly a matter of adding content (graphics, sound, music, more game objects, etc) and fine tuning it. I'm sure there will be a round of performance optimizations, a round of cross-platform hacks, a round of feedback from beta testers, a round of panicked hacking, and a round of October 30th surprises. But not today. Today is good.
I don't want to give away too much of what the game is about (October is only 17% done after all) but here's the AI for other creatures:
And here's a screenshot:
After some late night work, pre-work work, and lunchtime work, I've got the core ideas working so now it's mostly a matter of adding content (graphics, sound, music, more game objects, etc) and fine tuning it. I'm sure there will be a round of performance optimizations, a round of cross-platform hacks, a round of feedback from beta testers, a round of panicked hacking, and a round of October 30th surprises. But not today. Today is good.
I don't want to give away too much of what the game is about (October is only 17% done after all) but here's the AI for other creatures:
package; class CreatureController { public function new() { } public function update(creature:Creature):Void { var lowestScore = 1.0; var lowestNeed = creature.needs[0]; for (i in 0 ... creature.needs.length) { if (creature.needScores[i] > lowestScore) continue; lowestScore = creature.needScores[i]; lowestNeed = creature.needs[i]; } lowestNeed.update(creature); } }
And here's a screenshot:
It's hard to see but there's two different background colors. The large squares are plants, the medium squares are animals, and the tiny squares are fruits. The green bar is your happiness. Later the squares will be things that look like what they are.
Thursday, October 4, 2012
October Ludum Dare challenge accepted
"Make a game — Take it to Market — Earn $1"
I'm in. I just got haxe setup on my computer and I'm ready to start working on an idea I've had for some time.
Things I still need to do:
I'm in. I just got haxe setup on my computer and I'm ready to start working on an idea I've had for some time.
Things I still need to do:
- Make the game.
- Make it not suck.
- Make it look good.
- Make it sound good.
- Make an attractive website for it.
- Make sure it works on iPhone, iPad, and Android.
- Submit to the Apple App Store.
- Submit to the Android Market.
- Submit to some flash game site.
That's only nine things. I can do nine things in one month.
Subscribe to:
Posts (Atom)