Part of my day job as an architect is to suggest/cajole/enforce "best practices" within the organization I work in. This runs the gamut from a repeatable and measurable software development process, to establishing solid principles for large scale architectural design, right down to "design in the small" at the implementation level. In a large corporate environment, at least a nod towards some or all of these issues will serve you well in the long term. Big money, large distributed project teams, aggressive deadlines, and a substantial legacy application base mean that techniques, practices and technologies that seemed to be firmly rooted in academic circles, or just "wouldnt it be nice if we did it this way" flights of fancy are seen as emergent ideas, or are now gaining traction in the main stream. You know the sort of things : iterative development/delivery cycles, eXtreme Programming (XP) and agile development are shunting aside traditional no-design/waterfall approaches, slowly but surely... Design and development technologies, patterns, frameworks, components provide "out of the box" guidance on how to do something, or just do it for you with minimal effort on your part. Requirements, or at least aspirations at the enterprise level have grown exponentially since the days that computers had names like "MultiVac" and "GorgoTron", and required the resources of a decent sized principality to build and maintain :) Many of these techniques, practices and tools simply enable us to deal with the heinous complexity of our requirements and environments, they dont make software development easier per se, but enable you to manage, partition and organize the complexity of your current uber project ... oh and make sure that the next slob who is paid to add to it can actually understand what it does!
Jump to the other end of the spectrum. The adventure and romance of a single, lone developer building and supporting a small set of applications in a micro-isv. In building my first product I wanted to apply at least some the best principles and practices of my day job, but only where they made sense. After all we are dealing with a huge difference in scale here. The temptation was of course, to just go for it, take my idea(s) and rapidly realize it as an evolutionary prototype that would grow into a fully-functional product... of course such an app had every chance of looking like a mutant spaghetti-like shambling mound of horror... But then, I remembered that the timescale and effort would be both extended and inconsistent in terms of effort. When I add in a hack, I usually quickly forget why I did it in the first place, comments in code help of course, but there is usually a "relearning curve" as I piece together the circumstances that lead me to perform such a heinous act in the first place. So I decided that I would at least try to engineer my code in such a way that it conformed to best development practices .. at least as I understand them ;-) Hopefully it would make it simpler to understand, and re-understand when real life kept me away from product development for an extended period of time. There are other benefits: extendibility - my customers will expect new features as my product grows - I wanted to think how to build upon my product in a consistent fashion. Maintainability : hey I know we all write bug free code, but sometimes I fall asleep at the keyboard and bad stuff happens :) In fact anything ending in "-ility" is probably a good outcome of such a move! The trade-off? Well its gonna push out my delivery date, but in the long term I think it'll be worth it.
But to get back to the main gist of this post. What best practices could I beg, borrow or steal to help me out? The main thing for me : it has to be lightweight .. and to be honest I think this applies to any scale of development effort. Onerous heavyweight tasks beyond the actual production of code (e.g. heinous "non-productive" deliverables) bog down the development effort with very little return... if they are not completely ignored that is! For an enterprise scale effort a heavyweight approach to such documentation/deliverables (which *are* important for accountability, scope, checkpointing, budgeting etc!) can be a crippling burden, at the individual level its just plain dumb.
Ok, lets start with process. Iterative releases of the product seemed to be an attractive proposition. This also falls in line with good advice I have read elsewhere: "get it out there warts and all, as quickly as possible". Each iteration of the product will add new features, as part of my long term plan of world domination through rich application functionality, and of course, responding to feature requests from the adoring millions who will buy my offerings. In order to actually get to my 1.0 release, there will, and have been, a number of internal "iterations", enough to establish a baseline and infrastructure that the first public release will have to have in place. With each iteration comes a degree of lightweight planning. I have been doing this as a simple list of detailed features I want to include in each iteration cycle, nothing more fancy than that.
Within a given iteration, I'll make sure that I understand "what" I want to build before I go ahead and commit to anything else. Again, short notes describing a feature, diagrams for screens and general doodling that helps me get a grasp on the problem, and tease out all those little "gotchas" that inevitably lurk within is a good exercise. Practically speaking I do all my note taking on a Tablet PC with stylus ... I'm expert at losing pieces of paper so at least I know where my notes are. I just have to hope that I don't lose my tablet.... That really covers the requirements piece. It's a world away from use cases, requirements documents and screen prototypes, but in this case its more than enough to get my ideas from my head and onto paper for future reference.
Design... thats quick too, but I do put some thought into how I'm going to do something before I start writing it. A few scrawled UML diagrams are worthy enough to do the job here - maybe a simple class diagram showing the major dependencies, and a sequence diagram to show the flow of control if its gonna be complicated. But thats it - again MS Journal on my tablet is the favored basis of representation.
The development itself... thats where the low-level design work gets done, oh as well as building the stuff that actually executes :-) I'll try and consistently add to my burgeoning code base on a feature-by-feature basis, but sometimes the need to go ahead and write another piece of infrastructure sometimes gets in the way. Also, I have to admit, if the feature muse bites me in the butt I'll often go do something else in the application just for the heady spice of variety.
Testing... not the most exciting aspect of software development, but to release a quality "bit of kit" it's essential. My unit testing (bless the JUnit gods) is fairly thorough, and on a larger scale I have a set of test plans that are designed to send my application into horrid spasms of death if I havent done something right :) However, never fear gentle reader, my application will have a cast of millions involved in its testing, a closed, or maybe even open (!) beta process made up of individuals who wont be shy in coming forward if something is quirkly, nasty, broken or just plain evil.
So to end this ramble, "lightweight semi-formality" is the order of the day. There *is* a process, there *are* requirements, a clear purpose in design, and thought that goes into the production of code - shaped (I hope) a little by what I have learned in the "real world". I even test what I've written :)! That may be too much for some... or too little by far for others, but hey, at the end of the day its just me dude.