The first stages are always the most fun. Usually, you get to pick if you're going to work on a project or not. If you're stuck on a single project, well that's life. On occasion, especially if it's a personal project, you get to decide what to work on. So it should be something you really like. Whether the requirements come from the outside or from you personally, it's usually a good feeling. Everything is new and fresh. There's no old code to maintain or get in the way. You have a blank slate and are free to be creative. Some even have brainstorming sessions. It's relaxing, fun and all ideas are welcome, especially the crazy ones at which I excel.
The next stage is putting those ideas together. What direction do you want to take? How are these ideas going to help with the requirements? What's the best option? In short, you decide what the heck it is you're going to build. Is it going to be web based? Is it an application? Is it some combination of both? You don't need to go into that much detail, but you need to weed out what you're definitively NOT going to do.
The above two stages usually go by quick. Probably too quick. Some programmers aren't even involved. Many usually come in during the implementation phase or at the current stage. This stage is about the foundation. What are you going to use to build it? What's going to be the platform? And I'm not talking Java or C++. I'm talking about the initial code structure that all other code must follow. How are different parts going to work? What systems are going to be put in place? This is my second favourite stage. It's a programmer's dream. You get to decide how you're going to fill the now-blank canvas. Oddly enough, it's not the toughest stage, but the most important. It's the most important because everything else depends on this. It needs to support code that will be implemented maybe months or even years down the road. But it's not the toughest stage. No, there are two other stages more difficult. Or should I say tedious.
The next stage is support building. It's before you actually get to implementing features. I don't really like this part. We usually get through it because it's the first coding stage. So everything is still new. But here's the deal. The better programmer you are, the better designer you should be. And the better designer you are then the less creative you have to be during implementation. So the better programmer you are, the more boring this stage is going to be. You don't need to think. You just have to sit there and code. If you're being creative at this stage, you should rethink your design.
I want to talk more about this support building stage. There's a LOT of code in this stage that does absolutely nothing. Remember, it's the support building stage, so no features have yet to go in. You're basically constructing your classes and how external data will be handled. Maybe the socket engine and DB interface. The user still doesn't see anything, but you have to build how everything is going to interact. So you're laying down objects and defining constructors and possibly destructors (or at least some kind of resource management). All this has to be handled so that when you implement the high level features, you don't need to deal with all this low level crap. And the really annoying thing is that you can't see results until the entire support structure is completed. You can't test the socket system if the user system isn't completed. And you can't test the user system before the DB interface is completed. You can also have other things like event queues. So there's all this code and you have nothing to show for it.
It gets even worse. There's not only writing countless constructors and error checking routines, but sometimes you sit there trying to figure out what values certain variables should have. This can also happen in the next stage, so let's take an example of that. Let's say you're designing a web site, but you need some code to handle the resizing of certain elements on the page. So you figure out that the left navigation panel is 120 pixels wide and the total page width should be 750 pixels, so that leaves uh... And for some reason, it's so simple that you just can't figure it out. So you bring up the calculator tool and you still think it's wrong. Finally, you write some code that will fetch the size, but it doesn't fit. Then you get caught up in minute details and you're whole day is gone. You should know better, but every now and then, you get sidetracked. And it's not just the above example. It's anytime you get to a constructor and you have to decide where the values will come from and how they will calculated. Who builds this object? How long do I keep it for? Where should I store them? Bad design. You have to go back and figure out how all this will be handled. They're specific details, so they don't always find themselves into the specs.
Now we get to actually implementing features. Often, there's a GUI. So you have a list of things that need to be done. This button does X. That menu does Y. This is both rewarding and annoying. Rewarding in that you finally get to see your code do something. Frustrating because every new feature runs the risk of breaking prior features. So you have to go back, check them and fix them if necessary. I don't so much mind this part. Every new feature is just that, new. So you have the next feature to keep you going. It's like dangling carrots in front of programmers. Staying on the same feature for too long is cruel and unusual punishment.
Implementing features has other downsides though. We must decide who dictates the action. In most projects I've seen, this decision was not made. It was left up to the programmer. What I mean is when a system needs to know information about another system on a timely basis. There are two ways to do this. You can have a main loop where you wait or poll for the information. This is usually the simplest, but most tedious to write. It's simple because the logic is continuous. Everything must be controlled from this location, but at the same time, you must handle dispatching and how other systems communicate. For example, if you have a DB system and a user system, you must decide the hierarchy. They can be both on the same level or one can be higher than the other. So if the user system is higher level then it can use DB functionality, but not the other way around. This would lead to recursive behaviour and cause havoc on updates. However, a proper method must be established for how the DB system notifies other systems of events. A simple solution is to have the user and DB system at the same level and they each take turns. Inter-system events are queued. The other way to handle events is to register listeners. The problem with this is that any operation that involves more than one event will have its code spread all over the place. Logic will no longer be continuous. Not even for a single operation. Drag and drop is one such feature. Mouse down, mouse move and mouse up events must all be coordinated for the drag and drop operation. Also, wherever you registered your listener must now have control of execution. There can no longer be a main loop unless you allow it to update at every iteration. If you have threading, you must also take care that registered listeners are in the correct thread or are synchronised.
Feedback is a very real problem and I encounter it in every single piece of software I write using any language. I always encounter a situation where I update some element deep in the hierarchy, but it changes something that requires an update higher up. How should this be handled? There are different ways and I've mentioned a few of them. In any case, this is what slows me down the most. That's why games almost always have a central game loop. Anything else is just a pain. Sure, you can use events. But they must be controlled by the main loop. You need "someone" in control. It can't be a free for all otherwise you end up with too much coupling.
And that was the fun stage for programming. Now we get into a stage that programmers dread. Finishing up loose ends. Everything that came before pales in comparison to this stage. This stage is not for the weak. It is what separates the real programmers from the wannabes. This is the last 10% that takes 90% of the time. Programmers just don't volunteer for this. They get paid or are sucked into a contract before they knew what they'd be getting into. This part is when the product goes alpha. For those who don't know, alpha is when a product is working, but hasn't been tested yet. At least, not beyond what programmers and the QA department have tested. Now you have to get some real users. You need a few test cases. This stage has the property that it can go on forever. Someone must eventually say, "Ok, that's it. All other features must wait for the next release." If someone isn't ready to say this, then be prepared to walk away. Don't expect this product to ever be completed. So find out who that person is and if they are prepared to do so. Some companies, especially small ones outright refuse to do this. I've actually gotten weird looks as if I was talking some alien language. If you get this, run away. You can be 100% guaranteed that disaster will ensue.
This stage can be easily completed though. It doesn't have to be tough. You need a list. And you need a global list. EVERYONE needs to see it. You must also leave OLD items on the board when they are completed. DO NOT ERASE THEM! Once they're erased, people forget how long you've been at it. Just put a mark through it. Don't put an X or a checkmark beside it. Put a big black line through it. It feels pretty good too. And make sure you write down every single little detail on the board no matter how insignificant. If you have to put them on your own personal board, that's fine. Just make sure they are written somewhere in big. Every little detail that you go in to fix will bring up more details to fix. Mark these down. The other most important thing to do is to write down how much time it will take each and every item right from the beginning. If you want to get good at timing things, this is it. By the end of it, you will be a pro. Even if you go overboard, you will be impressed at how close you were. They are YOUR estimates, so you'll be inclined to keep them. DON'T let others specify the time it takes. If they time it, they buy it. NEVER complete an item timed by someone else. NEVER!
I still remember one of the first projects I worked on. I was just helping out to get something on my resume, so it wasn't a big deal to me. But I was asked to help out. We worked and worked and worked and nothing seemed to advance. We were getting stuff done, but there was always more. Finally, most people went their separate ways. But this outstanding project remained. It was a government grant of sorts, but they'd be liable if it wasn't completed. So I sat with the owner and said I wanted to start from scratch. He said he didn't want to do that. I said there's no way the current project will ever get completed. We've been at it for nine months. Do you think another nine is going to change anything? He was sceptical. Why would one guy be able to finish something from scratch what four (to six on occasions, artists and such) was not able to do in nine months? I said give me three months and I guarantee it. I told him I'd put up a chart with every single day laid out what I need to do. At every stage, if I fall behind, you will know it and you'll be able to decide what you want to do. Not having much other alternative, we went ahead and were able to get the ok for the extension from the government.
You may wonder how I could mark down every day for three months. Well, I was already working on it before with the failed project. So I knew every detail that needed to be done. I was basically in the last stage I talked about for the entire three months. Every detail was on the board and I did them. At every stage, I had a few people test it out. In the middle, I was three days late. I thought at this rate, I was going never going to recover. I needed something new. The thing is that I knew exactly by how much I was late. If I didn't mark down every little detail, I wouldn't know. Here, I knew I had to make it up and I didn't have much time to do so. Only 5 weeks left. So I talked to my "boss" and we worked something out. There were some features we didn't absolutely need. It would have been great to have them, but we decided to take them out. And you know what? We ended up with something far superior because it made all the other features work that much better. If something causes problems, usually it will make everything else work badly too. That was a good lesson. And this wasn't just any feature. It was something we all thought was the core of the project. I did take a day to put in something new and simple that while it did not do the same thing, made for a better experience than the original design. I worked a couple weekends and got back on track. The "feature" we took out had future unexpected benefits that made later features easier to implement. I ended up finishing two weeks ahead of time. Of all the companies that got a grant, we were the only one who had a working product. In case you're wondering what the project was about, it was about an educational software drive that the government was sponsoring. Try writing educational software that is also entertaining. It's tougher than you think.
And this brings me to the very last stage. Shipping. Sending it out the door. I have to say that I was lucky to have been part of a failed project so early in my career. Not because it failed, but because I was given the opportunity to do it right. I saw what didn't work. And what's really weird is that I didn't have any software cycle knowledge or any of that. It was basically out of fear. My boss wanted assurances, so I made up the timeline. But I still can't say for sure if I would have done that if I wasn't asked for assurances. I was young and never worked on a project of any significant size before. That project remained my largest project for quite some time afterwards. It used graphic techniques that I think only ID software was using at the time. And there was an editor too for the levels. Even today, I wonder how I ever finished it.
I look around for proper software development and I cannot find anything in them that comes close to what I did back then. What I do know is that finishing a product feels like nothing else. This is what got me hooked. Right from the beginning, I had done something that most other programmers never get to do so early in their careers. Produce a real product. OK, so the company was done anyways and the product went nowhere, but I had gained experience. But what did I learn? Why did it succeed in three months when we couldn't get it done before? What's the secret recipe?
Another project I finished is my multiplayer backgammon client and server. That was a project from hell because, again no one wanted to end the final stage before shipping. When I took control of it, it was again done in three or four months. This time, I had past libraries to help out which oddly date from that very first project I worked on. I keep upgrading my libraries over time. So although all the critical parts were rewritten, I didn't have to rewrite everything. So I don't think it's the fact that I rewrote it that made things better. I think it was the foundation. I rewrote the foundation so that it worked well with what I knew would come later. Normally, we don't have that hindsight. So that may be the biggest hurdle. This may be a crazy idea, and it'll never be approved, but what if software development needed to provide a test application that would be scrapped. Engineers do it all the time. Take three months and implement whatever you can. Find out where the problems are and what doesn't work. Then start over for real. All the most successful projects I've seen have done this in some form or another. Maybe there's something to this.
The other thing that I noticed was time charts. You can't possibly know what's down the road in five months time. If I did, I wouldn't be a programmer, I'd be on wall street. Sure, I make predictions from time to time. But will I be right 100%? So we have to revise every now and then. Not only that, but we have to be as detailed as possible. Every day should have a list of things to do. If you do them all, you're free for the rest of the day. If you don't, you need to make up the time. It may seem odd to take the day off. But it's critical. I've seen people burn out all the time. Programmers need breaks. So just because you have two to four hours left, don't jump into tomorrow's list. Go home. If you keep working, it will slow you down weeks or months from now. In short, if you do tomorrow's tasks right away, you are effectively killing the project or at the very least, your part of the software. I found this out the hard way. And if you have to make up time, make sure you don't work both days of the weekend. And don't work late every night. That's suicide. Plan out and modify the list so that you can catch up without killing yourself. What's really insidious is that working an extra hour doesn't seem like much. It won't matter for one day or two. But over time, it will destroy you. You will burn out.
What else could make a project succeed? Well, admitting when things aren't working. That's why a time chart is so important. There's no denying it when it's written down. The most important thing I found was that you need everyone writing code with the same design in mind. You don't want one person who likes auto-notifications and another that likes requests. This won't work.
On the positive side, what should we do for sure? I don't really know. I always think about the foundation (from the early stages). If this works well, everything else will work well. But sometimes people fight the foundation either because they disagree how it's done or because they're using a library that does things differently. I'm also reminded of something that happens all too often with beginning game developers. Let's say you're writing a game and you want left on your controller to make your avatar go left. Same thing for the other directions. The buttons could shoot. Standard stuff like that. Here's what always happens if they try to make the game available for two players or playable over the Internet. The beginner game programmer would likely write an event for each direction. So when the left button is pressed, he would write an event that moves the avatar left. But now he wants those commands to come from the Internet. He's duplicating code. You may think this is obvious, but it isn't. You may be thinking he should have put the commands in with the avatar object. That may not be the best way. This is about feedback. If the avatar is on a grid, then the grid must be updated too. This is outside of the avatar's object. So something must update the grid. You could ask the grid to update itself, but this would require two calls, one for the avatar and one for the grid. There may be reasons why the grid cannot update the avatar. So it's not that clear cut.
What I'm saying is that sometime what is the best interface for objects in the programming world is not the best when it comes to human interfaces. I see this all the time. An advanced game programmer would likely have a separate area for human interface. From there, you can update all your data structures. This way, you have two separate systems. You have the human interface layer and the game engine. So if you later decide to implement keyboard events, you can relay them to the same human interface commands without changing any existing code. This is an example where you can easily see what is happening. But sometimes, the same thing happens within code itself. Some systems should be built as if they can be replaced. But we all know this isn't how most code is written. Since it's all code and no physical separation is seen, it's a little more difficult to really see what's going on. Can you replace your socket engine? Can you replace your GUI? Can you replace the web from your application? You think the web as is will last forever do you?
Are there ways to avoid rewriting the foundation? Sure there are. Make sure that the interface for your external input and output is different than the one for other systems. Don't say things like "System A needs access to this functionality, so I'll write function X in system B." That spells disaster. You want to separate systems so that they don't interact directly. A controller will handle this. All systems should have access to another global system so that it queues requests or updates. Now you can just give each system its turn without them messing each other up. Over time, this is what I've found to work the best. So I'm done fighting it. One thing I like is that you can implement this same idea over and over at any level of granularity within the same software.
Not sure if all this coincides with other people experiences. The reason being we don't hear many stories about the development process. We don't hear personal accounts. Why is that? Are they all bad? Are they all under NDA? We all had success stories and we all had some kind of failures. Or is it taboo to talk about it? The most recent experience I've heard of is the MS Vista account by a developer. You can Google it. I don't want to link it. But other than bad stories, we don't really hear about the good ones. How were difficulties overcome? That kind of thing.
Anyways, I find the lack of discussion on foundation design a little disturbing. If you really want my opinion, it all comes down to this. If you want to get it right the first time, research foundations. There are different ones that work well for different things. But a decision must be made. In a way, this is what I'm attempting to resolve with my current project. Not within the project, but as a tool that will provide a foundation for future software. Maybe we'll get a little Christmas present after all. I'm hoping to release something in a few weeks. Or maybe after New Year's. It won't be much, but this is what's been lacking in my personal project. A definitive timeline. So either the 22nd of December or the 6th of January. The first release will be quite bad. I don't care that others say that I shouldn't release something until it's completely finished. I'm doing this so that I can implement the ideas described here. I'm going to plan out a daily list of things I have to do and see how it goes. If I just get 1+1=2 I'll be happy. I've just laid down a new foundation. Now I have to implement all the features. One a day will give about 15 features. Not bad. The second release in January will hopefully have more components available. Remember, I'm not being paid for this, so I'm not in a rush. I just want to see what will happen. I only have a few hours a day too. I'll keep you all updated on how it goes. We'll find out once and for all if I'm all talk.
I expect delays especially during the Holidays, but if I don't release anything by the end of January, I'm shutting this blog down.