Wednesday, October 27, 2004

Finished. - Tips for Young/New Software Developers

I finished my first project at work today.

After almost two and half years, I locked the SourceSafe database. After three distinct ulcers, after 154,806 lines of C++, I am finally finished.

...and it feels great.

This was my first project right out of college. The project started out with me working on it by myself for about a year and eventually growing into a five developer effort.

I ended up:
  • Designing the majority of the architecture
  • Maintaining the project web pages
  • Serving as the SourceSafe administrator
  • Updating about 2/3 of the user documentation (and directing the updating of the other third)
  • Jointly developing the test strategy
  • Writing over half of the final code
  • Writing the installer
  • Doing the all graphics and a good chunk of the HTML for the help files
  • Writing a few other utilities along the way

Needless to say, I learned a quantity scientists would call "a shitload".

Here are some of the things I have learned:

  • When you think you are being productive by copying and pasting code, you are setting yourself up for ulcers and carpal tunnel. Stop what you are doing, and improve your design.

    Most experienced software engineers will think this is a no-brainer. But as a green optimistic developer, you think, "this code won't change, and I am not sure where a good spot would be for common code". It will change. It will change more than once. You will pay the price.

  • The resource editor in Visual Studio .NET 2002 is buggy and does not integrate well with Visual SourceSafe.

    The applications in our project had large dialog-based user interfaces. The static controls would randomly shrink and truncate the text they were supposed to display. The menu ID's would randomly revert to the the numeric value rather than symbol defined in the resource.h file.

    The other developers and I had multiple instances of making a change to the .rc file only to be prompted to check it out when you went to save it. When you checked it out, you had the two joyous options of either losing your changes or losing every change that occurred between the version in your working directory and the version you were about to check out.

  • The MSI is a hassle to deal with.

    I feel bad for the developers that wrote installers for earlier versions of windows. I was shocked to find out how convoluted the installation process was after taking installers for granted as a user for so many years. I think Microsoft is really getting it right with technologies like ClickOnce and No Touch Deployment.

  • Consistently formatted code is more valuable than you think.

    I read an article on this, and unfortunately I can't remember how I stumbled across it. How I wish I could post a link... Let me summarize, the author talked about an experiment where some psychologist or sociologist abandoned a car on the side of the freeway in a well populated area. The car was not particularly nice, but didn't look like a total clunker either. The car sat untouched for days. They picked the car up, drove it to a comparable area, broke out a window, and watched. The car was stripped within hours. The same kind of thing can happen to your code. We had several relatively simple, but poorly formatted sections of code that seemed to get buggier and buggier every time someone modified it. If your code is poorly formatted, it looks like a careless mess no matter how elegant the semantics of the code are. Psychologically, this will have an effect on your team members, and often times they will not be as careful when working with a piece of code like this.

    In hindsight, I would like to have had a beautifier that could take a coding standard definition and run on any checked out files as a pre-build step. I think it would have saved me and the rest of the team many a headache.

  • If you are planning on putting synchronous I/O in a user interface thread, think again. If it still seems like a good idea, think about several more times.

    The four applications in my team's project were serial I/O intensive. You can often get away with limited file I/O in UI threads, but reconsider doing anything else. In the earlier incarnates of the applications, they did the serial I/O in the UI thread. This brought the UI to a crawl. Like most new computer science graduates, I had done threading in school, found it difficult and intimidating, and the assignments I had been given in school did very little to indicate when a new thread was necessary. As far as not putting I/O in a UI thread, I would think this would be pretty obvious to an experienced developer, but the configuration management tool the organization I contract for uses has major TCP/IP I/O (not to mention our Nazi anti-virus software aggressively scanning all data as it comes in) going on in its UI thread. It starves the message pump for the UI from getting serviced and makes Windows think that the application is not responding. I have heard many of my co-workers complain they can't check in or out multiple files without making the application lock up, when in fact, they just need to wait it out. My other piece of advice would be to prefer asynchronous I/O to spawning a new thread for the I/O unless you can really justify it.

  • If you are in a position were you have any management duties (whether you are paid like it or not), prefer written instructions and guidelines to verbal ones.

    I think this had several benefits. There were certain times when I would give verbal guidelines on particular tasks, and when the tasks were "completed", I often found my instructions were half-followed/not followed. I was in a position where I knew what needed to be done and it seemed obvious to me, but it wasn't to other developers. This brought me much frustration. At times, I remember thinking, these other developers were going home at night and (they all had kids of various ages) it occurred to me that I bet they all had accused their kids at some point of not listening. Initially, I wished I could tell their kids "Well, your dad doesn't listen at work, so it is probably genetic". After the brief moment of internally venting, I realized that continuing to handle the other developers this way was not going to contribute to the success of our project, and ultimately would not reflect well on me. After deciding to give more written instructions, it occurred to me that there were times when I probably overloaded them with information and expected them to just "get it" more often than I should have.

    On the other hand, I am still not convinced every time was my fault (in a way). There were a few times were I thought a developer didn't follow my instructions to the "T" out of laziness. Well, we all get lazy now and then, and after all, Larry Wall said laziness is an important characteristic of a good developer (along with hubris and impatience). Let me get tangental a bit and say I am not criticizing any other developer that I worked with. I am merely stating that they are humans, and must be dealt with as such. I consider myself very enthusiastic about software development, but my motivation is not a constant, although I like to think it consistently high. But giving your developers written instructions allows them to refer back to the instructions, and it gives you traceability if you need to call a developer on not following instructions. The written (or typed, or printed) word carries more weight than the spoken. If your written instructions are in a informal format, add that you are available for clarification. If your instructions are in a formal document, either make it clear that you are available for clarification, or if you have a small enough team, check in with your developers after they have had adequate time to digest the instructions and offer clarification then. After all, we are all human, and we rarely get things right the first time.

  • Prefer to leverage existing tools to "rolling your own".

    If a developer's tool might exist for a task you need to do, for God's sake, search high and low for it. If one does exist, try like Hell to make it work even if it means tweaking the way you work a little bit. Think about it. If a tool has been sold to a fair number of developers and gotten halfway decent reviews, it is going to take you a long time to write a similar tool and get it to the level of stability as the existing tool. In most cases, the time you spend configuring that tool to work in your environment will be miniscule compared to the time it will take you to write a tool that caters to your environment, especially when "scope creep" or changing requirements come into play.

    I had written fairly sizeable serial communication library that was absolutely worthless outside of our applications. Then we found out that several of our users' managers had purchased laptops without serial ports and our code needed to accommodate users with USB to serial adapters. Greenleaf to the rescue! We hadn't really begun testing on other OSes at the time, but things I read later indicated that opening a serial port in an OS-agnostic way is non-trivial. The greenleaf serial communication library made it one line of code. Had we implemented code to deal with USB to serial adapters, it would have been all for naught. Sure, we had to write wrappers around greenleaf to preserve the established interface, but that was not near as time-consuming or discouraging as the alternative would have been.

  • Understand any code your project is dependent upon as much as necessary.

    For this project, we used MFC because we needed to be able to write a native application that targeted everything from Windows 95A to Windows XP SP 2. I have heard Carl Franklin make the statement that he wouldn't use any code wizard/generator that produced code he didn't understand. I dare to disagree, but Carl would be the first to admit that there is no development guideline that doesn't have an appropriate place to be broken. I think it all depends upon the size and scope of your application, and maybe to a certain extent, the age and reputation of the tool in question. Well, to understand the code that MFC generates in your application, you really have to read source for a good portion of the library. We certainly got burned a few times in situations that Carl was talking about--where the generated code acts subtly different than how you think it does. On the other hand, after getting more experience with MFC, we were able to assume more accurately and saved a significant amount of time by not reading MFC source to realize "hey, it does exactly what I thought it did". I know people dis MFC a lot, but that is neither here nor there, and I still think it was the best choice of technologies for the project requirements, even if it did make deployment more complicated.


I certainly admit this post is a bit scattered, and I am probably not saying anything new. But if it helps one other developer, its existence is justified. As far as being scattered, a young developer with such diverse responsibilities on his or her first project is going to learn important things on a wide variety of aspects of software development. I am glad this post is that way. It is not all about the code, people.

Looking at all this stuff I learned from I screwed up, I feel like I need to have a post outlining what I did right on the project.

Furthermore, I am not an expert on anything, so any comments offering valid counter-arguments are appreciated.

In closing, as Chris Sells would say, think deeply, code well.


At 11:50 AM, Blogger gus away from the metroplaza said...

you may have done all that stuff, but did you arrive having eaten?

Rod Torfleson's Armada featuring Herman Menderchuck rocks the house!

At 3:28 PM, Blogger Jim B said...

Everytime I feel sort of good about myself, someone has to remind me that Kevin McDonald is way better than I will ever be.

Sometimes I arrived having eaten, but not always. I mean, I could have eaten at home and been healthy and whatnot, but that would cut into my sleeping time. Plus, with the fine cuisine that can be obtained from our break room vending machine, who could blame me? I mean c'mon, Cheez-its and a Diet Coke for breakfast? That is livin' large and in charge, or bling-bling on the triple beam or something. Maybe I should have mentioned that I have gain thirty pounds since I started this project...

At 1:53 PM, Blogger gus away from the metroplaza said...

I was a little short on time when I posted the previous comment because I was working up in canada, eh. But I meant to congratulate you on completing the project. I know how awesome it feels to have the first one out the door. But also, expect in a couple weeks to feel a bit depressed about the whole thing. I haven't seen anything written about this subject in any of the trade mags, but I've definitely noticed that I and the developers around me start to like we've stagnated a bit in the weeks after a big project is released.


Post a Comment

<< Home