Archive for May, 2008

The Reason Why the Popularity of Unit Testing is Waning

May 23, 2008

Unit Testing is essential in two places: if I’m working on a problem that’s really hard and if I’m working on something that’s going to be refactored *a lot*. Your average developer doesn’t do a lot of the latter and does the former only rarely.

Coders tend to “compile-crap” things into existence and then drop into a fearful sort of maintenance mode after that where they improve code only if they have to. Developers simply do not have a vision for anything beyond that. They fear that unit testing is just more of the same sort of stifling bureaucracy that they’re used to in their suffocating work environment. They have no inkling that they can gain several orders of magnitude in effectiveness and productivity by applying themselves in a concentrated study of programming tools, principles, and concepts.

Their managers understand these things even less: they can’t even identify a good programmer when they see one, much less encourage things that “grow” good programmers over time.

The big fat ERP system my company just bought comes with absolutely no regression testing framework whatsoever– and they’re constantly rolling out patches and updates to clients that have made their own extensive in-house modifications. If ever there was a place where unit testing could offer massive benefits in terms of reducing developer exasperation, this is it. Yet the tribal practice is essentially to rely on the users to do the testing for IT.

If unit testing had gone from being buzzword among the “elite” developers to being something that average managers *insist on* whenever they buy a large system like this, then it wouldn’t be on the wan.  At the moment, though, there just doesn’t appear to be anyone on that scene willing to put up a fight for it.

To Develop a Good Design, You Must Begin by Caring About People

May 22, 2008

“An all-encompassing design culture and strategy in every aspect of your thinking is a more tangible representation of your identity than any clever mission statement or advertisement. And if your design sucks, it simply means you don’t care about people.” — Joshua Blankenship (italics mine)

Josh very succinctly states in his blog what I’ve been gradually discovering over time as a developer. He notes that “it isn’t easy” and quotes Tom Peters as saying it’s “damned hard work,” but he doesn’t go into specifics about how to establish and develop a culture centered on good design.

I think my recent entry on the topic explains in detail how to pull this off– even though I couldn’t put into words what the ultimate objective really was.  However, I think the real payoff will come only if you begin to include the programmers and code maintainers among those that you take time to invest in and care about.  Too many IT managers fail to realize that sacrificing the needs of the coders will have a direct impact on the experience of the end users.  The very fact that most development jobs are mere maintenance work on poorly architected systems is a testament to the fact that we value neither the coder or the user.

How to Deploy Your Skunkworks Application– and Take Over Your IT Department’s Software Development in the Process

May 19, 2008

The first thing you have to realize is that everyone else in the business is scared to death of software development. If you allow your development to be driven entirely by fear, then you’ve got a one-way ticket to maintenance hell. But how do you get control of the development process if your authority and influence is limited? The direct approach will not work. Your arguments for investing in skills, design, and refactoring will fall on deaf ears. Your only hope is to combine an array of guerilla tactics with an understanding of the terms with which those in control view reality.

There’s only three units of time that register in the consciousness of project managers: 5 minutes, two days, and two weeks. For most programmers, there’s been many times that these little “5 minute” changes have exploded into hours of pain, so most developers never let on that it’s possible to get anything done that fast. So really, the smallest unit of development time that a project manager is going to hear is going to be in the two day range– no one’s going to let on that anything faster is possible, and (in the tradition of Mr. Scott) everyone will pad their estimates by at least a factor of four.

“Two weeks” is a code phrase signifying that the people involved in the problem really have no idea how difficult the problem is or how long it should take. If there’s ever something really hard that has to be done, a manager will assume that two weeks is plenty of time to accomplish it. Anything that *you* want to do that will take two weeks or more to accomplish is going to be immediately rejected. The trick is to never ask to take on anything that’s that ambitious in scope, but rather to focus your efforts over time to gradually increase what’s possible in the “5 minute” range. Once you have a framework in place, the general demands of the users will allow you enough leverage to take on more sophisticated tasks that can take up to two days or so to implement. That’s the general idea, anyway. Below are some specific techniques and maxims you can use to work your way up and take control of the development process:

* While no manager will listen to your crazy ideas, they generally don’t care how you accomplish your tasks. This is the leeway you’ll have to leverage to turn things around in your IT department– at the start it’s your only avenue for improvement.

* If something actually does turn out to take the “five minutes” that you thought it would, use the extra time that you’ve scored to improve the elegance of the code or to learn a better way to accomplish the same task. (How this impacts the project is irrelevant: you’re doing this to invest in *yourself*.)

* When other developers are wasting time playing solitaire, trading stocks, or surfing the web, invest your time in developing tools that help you manage your tasks, problems, code, and data.

* How do you know what tools you should build? Look at where the friction is. Anything that’s tedious, irritating, and boring is something you should look at automating or tooling up for.

* A quick-and-dirty tool can help you get a job done in about the same time as the other fellow that does it the hard way. Tasks that you have to get done weeks or months down the road will give you an excuse to improve your tool(s).

* The thing that’s going to give you an edge is the fact that you’ll have a whole library of tricks, a framework that integrates them, and a “sense” for what fancy-smancy techniques are worth learning and applying on the fly.

* At some point, someone’s going to come in with a task that you’ve pretty much already solved. This is your chance! Basically, you can throw together a simple GUI, code a couple of routines, and suddenly you have pretty sophisticated solution that’s much more robust than what the other guys would have thrashed out as a hand crafted one-off. The trick is that your GUI is just a thin veneer on top of the tools you’ve been using for yourself all along!

* Your solution is not something you could have proposed at the very beginning. You just didn’t know enough back then. So don’t fault your manager for not listening to you back at the start!

* People’s ears will perk up when you say, “I’ve actually got something pretty close to that built already.” The fact that you’ve been the primary user for your stuff for a long while will mean you’ve got a lot of confidence in it. And nobody’s going to take a chance on “vaporware” or “castles in the sky.” “This is practically done,” you say, “I’ve just got to make a couple of quick modifications and we’re there.”

* The fact that you can solve an entire class of problems in 5 minutes that would take your peers two days is what will get people’s attention. Nobody cares what you can do in two weeks time. They don’t even care what you can do in two days time. Five minutes is all anybody’s going to care about at this point.

* Once your solution is deployed, there’s a whole world of forces that your pride and joy will be subjected to. The users are going to be a great resource for new ideas, though. Go watch them work and keep talking to them until they can give you some real constructive feedback. After one minute they’ll assure you that everything’s fine. After five they’ll mention a couple of things that could be better. After ten or so, they’ll be telling you what you really want to know: “Now I don’t know anything about computers, but what I really need is….”

* The worst thing about in-house development is that applications only have to be “good enough.” Once they get that far along, the creativity stops and everything freezes into maintenance mode. You can identify a complete lack of design in an IT department when you see a proliferation of forms, screens, procedures, and programs. You’ve got a lowest common denominator philosophy because nobody’s taking the time to find the common denominator to all of these forms, screens, procedures, and programs.

* If you’re *designing* software, you’re not just adding new screens or modifying existing ones. Real design is going to incorporate subtraction and abstraction as well. A good abstraction is a technique that allows you to synthesize many ideas at once– and once it’s implemented, you’ll be able to subtract away a lot of unnecessary code.

* As your users begin to get the hang of your application, be “jonnie-on-the-spot” when it comes to all of their “5 minute” type requests. If they feel like you’re listening to them and taking care of them, they’ll be more willing to give you a chance to invest in the stuff that will provide the real payoffs.

* Anything that the users ask that’s more in the “two hour” range” should be put on hold until you have at least a dozen such requests. List them all on a whiteboard and kick ideas around with the one person at the company that’s willing to listen to you. Then wait some more and let these ideas percolate a while.

* Code up proof-of-concepts for some of the hard stuff and expose it inside your application with little regard for design. Walk some of your power users through special “previews” of these features so that you can have a chance to soak up as many good ideas as you can from them.

* Now go back and look at the white board. Erase it and reorganize everything into related “buckets” of functionality. In the bottom half of the board, sketch out the GUI for something that could address the bulk of the requirements. Underline the stuff you can address right away with only a minor reorganization of existing code along with new GUI elements. Separate out stuff that appears to be hardest.

* There are undoubtedly areas of the code that have known quantities of suckage in them. There’s areas that really irritate you every time you have to go in to modify them. Avoid wasting time fixing this sort of thing until they’ve had time to fester for a while. As you’re about to go in and fix everything up for your users, be sure to invest some time in cleaning these things up for yourself while you’re making such big changes. If there’s a huge visible leap in the functionality, your users will at least have something they can blame it on. “By the way, when you added this hot feature that I use every day now, this minor thing over here stopped working the way I want it to.” You’ll never have time to work on something just to make it objectively cleaner for “no reason”, though.

* If this takes longer than what folks want, don’t sweat it. Remember, in-house software only has to be “good enough.” You’ve already addressed all of the critical stuff that people absolutely have to have to do their jobs. This reorganization of the code combined with a dozen sorta-optional type features just isn’t as urgent. It’s more important for you to control the growth of the application in a sustainable way. Listen to them as if they’re the first person to suggest whatever feature it is that they’re asking for, but remind them that as long as the code is “good enough” for them to do they’re jobs, they’re just going to have to wait. If you have to respond to these demands immediately, make sure that whatever they’re asking for fits in to your overall scheme for how the application should be structured. Better yet, use some of the time you spend focusing on their needs to flesh out, extend, or improve areas of the code that you can use to nail down your vision further down the road.

* You’ve gotten this far by investing in tools first and foremost for *yourself*. You’ve consolidated your power by training the users to think in terms of tools they can use to solve their problems– as opposed to a screen with buttons on it that they just go in and push.

* You may not always have managerial support for each new order of magnitude increase of functionality in your application. If you’re in doubt of this, build it anyway. Do it on your on time if you have to. Roll the application out on a “Beta” basis to a few of your more savvy users. When your managers find out about the application, they’ll more than likely make you stop everything and load it up on their machines and pester you like crazy for new features.

* Each order of magnitude of increase in application functionality will take more time to develop than the one before– but each one will put more and more features within the “five minute” range of your grasp.

* The final coup de grâce is when you’ve developed your application so much that you’ve gone through several refactorings and paradigm shifts. Your design is so clean and your code so expressive… you’ve rolled with anything the users could throw at you and made something truly beautiful. Then someone comes by and mentions that folks in another department have very similar needs as the ones you’ve been coding for. You listen to their requirements for a while, stroke your chin thoughtfully and say, “I’ve actually got something pretty close to that built already. If I make just a few modifications to the framework I’m using for this other application, I think we’d really only be a day or two away from having something that could work for them.” And so, you get the green light for another project and you are able to justify ever more ambitious features and refactorings because each hour of effort you invest in either can be harnessed to benefit both projects.

* Once you’re this far along, the question will come up as to what the company will do when you “get hit by a bus.” If you get cornered on this, just start talking about how they really have a good point on that. Explain how you’ve had to sacrifice code quality in order address all of those urgent feature requests– and they’re some areas of the code that even you’ve forgotten how they work. Really, the company would benefit greatly if you spent a month or so polishing and cleaning up that stuff. Even better, you should take some time to write articles about the trickier stuff you’ve done in the application. Once published, the articles will generate valuable feedback from more sophisticated developers that simply cannot keep quiet when they see a technical flaw or innefficiency. Those articles can then be folded back into the project documentation for whoever inherits the code. (Cue maniacal laughter….)

* Of course, you and I both know that no matter how great your application is, all it takes is one random IT manager to come in two years down the road and insist that 6 mediocre developers get hired to rewrite everything in the latest Blub IDE or whatever. More than likely, your application will remain “good enough” for quite some time and the average developers that come after you will make only surface changes to it. What will probably happen is that the creative integration of various requirements will cease and the new developers will gradually get bogged down as they create one lame hand crafted form/screen/procedure after another and begin to spend all of their time on maintenance instead of design. But that’s okay. They only needed to make something that was “good enough” for the moment. By the time the company fails because of their negligence, no one will suspect how much they were responsible for so many folks losing their jobs….

Advanced Codemunging: A Report from the Trenches

May 13, 2008

A year ago, I began studying Lisp and Emacs. I would ultimately get through about half of SICP and code up a few small Lisp projects that mainly showed how far I was from grasping the point. Having Emacs skills did come in handy a few times, though. Engaging in such focused deliberate practice was difficult: I rarely came up with anything truly innovative or useful, but instead had to constantly face my weak areas and incompetencies– and doing all of this pretty much in public would ensure those weaknesses would become notorious among the illuminated. I wasted some time blogging about programming practices and things gradually culminated into a manifesto of sorts. While I now had enough technical know-how to address some of the biggest problems I’d faced as a career programmer writing simple database apps and web pages, I also had a minor crisis in choosing which language to implement my new vision. Circumstances at work (and a large decrease in free time to experiment in) would soon narrow my options for me, though. This blog post is about what happened next.

I got really lucky in the way things panned out in my career. You’ve probably read where Joel Spolsky was talking about how awful it is to get stuck being an in-house developer. More recently, Paul Graham has gone off on how we’re all supposed to be like the start-up coders that he funds. Really, most of us aren’t *that* talented to begin with… or at least, we’re not willing to live the start-up lifestyle or take on the associated risks. But there is another option that can be almost as satisfying as working in a Graham/Spolsky type setting: be the *only* developer in a company that’s large enough to have interesting problems and that’s looking to cut the cord with as much of their legacy software as they can as they move to a new system.

If you can land that sort of job, you’re probably savvy enough to avoid most of the stupidity that comes with dealing with corporate type development. Because you’ll be they only developer on staff, you won’t have to waste time building consensus with fearful managers and mediocre “day coders”– and face it, they would never have gone along with your insane ideas to begin with. Also, you have a huge business value bearing down on the side of good design: you’re essentially getting paid to eliminate and refactor away all of the crappy development projects that have accrued over the years. The scope of such a change is so big (and everyone else is so busy), you’ll have to come up with big architectural ideas on your own and you probably won’t even have to pitch them to anybody except the other techy type people that are in your (small) IT department. You’ll just have to make the right decisions on your own.

Looking back on the most painful moments of my career, I think I have pinpointed the cause of most of the disasters. Because I needed the experience, I allowed myself to get into positions where I had to maintain code that I had no authority over. Whether out of my own fear or by decree of my immediate manager, I was isolated from the problems I was supposed to solve. I would continually get requirements that were just enough wrong to be useless and would often spend as much time removing them as I did implementing them. The common denominator in most successful projects/modifications were in situations where I rewrote entire sections of code (with or without permission) and where I also took the time (with or without permission) to hash things out with some smart folks lower down on the totem pole– people that actually did the work and people that would end up using the application. Talking to people like that would often uncover the real problem– but then I’d have to “sell” a new solution to managers at one or more companies. I’d often spend more time talking about the issues with management than I did writing code. And its those sorts of interactions that become the fodder for an unlimited number of Dilbert strips. And because of all of the bad requirements, IT departments start to withdraw from their users and create buffers of bureaucracy to protect themselves from getting “burned.” You can let this insanity grind you down… but you can also take advantage of it if you play your cards right.

You’ve got to realize that while management types generally can tell you what to do (and sign your paycheck and stuff), they can’t really help you with the bulk of your development work. Too many of them are going to just tell what kind of buttons to put in the application. “I just need one that has ANSWERS written on it.” Right. If you can just get your foot in the door, you won’t be so dependent on them. Any sort of application that you can roll out is your ticket to finding our how things really should work. Talk to your users at all levels. “Joe Six Pack” knows a heck of a lot about the company and will not waste your time with stupid requirements. Generally speaking, no one asks his opinion: he’ll be grateful for giving him a voice and making his work easier.

Growing up as a geek, you probably played off-beat rpg’s and war games in your basement. In order to run them, you had to have the bulk of the system “in your head”. This type of thing is very similar to a company’s overall business process– and your contacts with people on the ground and your familiarity with the back end data structures will allow you get large portions of a company’s business processes “in your head” as well. (As long as there’s some room left up there what with all the AD&D stuff junking it up.) The trick is to address the process issues in a coherent way: what’s convenient for one person may not be efficient for the whole. It’s this kind of knowledge and savvy that separates you from the code-monkies. People that have a slightly smaller interest in programming will often use the position they gain from this to become de facto controllers of the company. But you’re a geek, so you’ll probably just be glad to have the chance to deal with management as an equal instead of as a flunky. That way, you can get a chance to implement the code designs of your dreams! Party!

So, once you’ve got a decent job where you have the authority to develop code effectively, how do EMACS, Lisp, and SICP impact your day to day work? The main area is in your attitude. Even if you’ve never truly mastered those tools, you end up cultivating a conviction that your program should be dynamic and malleable at all levels. Your abhorrence of repetition and bloat will be cranked up to “11” and you’ll just have this default expectation that your code should magically respond to you no matter what you’re trying to achieve. You’ll also be exposed to enough unusual ideas that you’ll see things you can do back in “blub” that you never would have imagined. You’ll have a wider range of programming styles at your disposal, and your ability to discern various “code smells” will be much sharper.

Back on the job, I did choose a ubiquitous “blub” as the primary language. The lesson of Lisp is that it takes very little to engineer a custom programming language: just a few axioms will get you something reasonably complete in short order as long as you’re able to combine the pieces into more complex concepts. I realized that if I stole somebody else’s evaluator, I had 90% of what it took to make a dynamic language. I embedded the evaluator into an “environment” that could manage the overall state. I then wrote a small deck of crappy string functions that I used to “compile” lines of text into “code objects”. From there it was a piece of cake to write code to “execute” the objects by running a series of operations on the environment variables based on what’s specified in a list of those “code objects”. This was all done with the crappiest of quick-and-dirty programming techniques. Just awful. It didn’t take long, though. And it doesn’t have to be great. It just needs to be “good enough” for now.

Once the core of this (albeit awful) custom language is done, you’re (generally) only about two hours away from being able to implement any given language feature that you want to do. And thanks to a small familiarity with Lisp, I realized that there was a lot of slick ideas that are opened up once a programmer has gains control over what gets evaluated and *when*. Macro-like functionality became possible, among other things…. In practice though, coding a new language feature take me maybe ten times as long as it would to write a comparable function to do the same thing. There are things that can be done to cut the time off of that, and it’ll be fun to someday compare and contrast my ideas with what can already be done with List “out of the box.”

What I ended up using my roll-your-own language for was to build a scripting language for customizing my main application. When the application is run, it reads a script to set up the environment. All of the GUI is bound to the environment. Advanced users can customize 90% of the application’s functionality without recompiling– and as a bonus, I have a way to test and experiment with malfunctioning desktops without having to use the old “it works on my machine” excuse. Not quite as good as a REPL prompt, but good enough. (For now.)

Because I’m a database app developer, 80% of my code is about connecting to database X, prompting the user for some stuff, getting a deck of rows, and maybe doing something for each row in the deck. (I get so sick of seeing the same crappy DAO, ADO.Net, and stored procedure call code over and over. Blech!) It sure would be nice to have a language designed completely around doing exactly that. And the thing is… I do! My custom language has all kinds of features for manipulating blobs of text. My “environment” stores the blobs in a prominent place, and the GUI automatically picks them up, displays them, and knows how to operate them. This may sound crazy at first, but I’ve been able to come up some powerful front end features because of this approach. Features that I never would have thought up emerge naturally and give my users an unprecedented amount of functionality. Dozens of minor problems routinely get addressed all at once with relatively simple abstractions.

For the first time, I am coding against the problem at both ends. The blobs of text that represent the fundamental unit of work in my system are abstractions that I once referred to as being “hairy at both ends” after trying describe something Peter Norvig was doing in an code sample. These abstractions allow the functionality of the program to be extended gracefully– and I’m generally only a “very short time” away from being able to extend those functions for either myself on the code side or my users on the GUI side. No… for the first time, I have an architecture that acknowledges myself as being the primary “user”. Refactoring is now easier than any other alternative– and the business case for it can be made convincingly at every stage of the project. I can code features that make it easier to manage growing collections of business object blobs in my heavily syntactic sugared scripting language. New blobs are automatically picked up by the GUI… and serendipitous GUI features emerge naturally because of the consistency inherent in the abstractions. Each layer of the architecture builds on and magnifies the efforts of the underlying layers. And every line of code I write is impacted by my (admittedly mediocre) understanding of recursion and the closure property.

You see a lot out there about those supposedly super-duper type programmers that are worth ten times as much as their lesser colleagues. While I will not claim to be one of those guys, I do feel at least ten times as effective of a programmer as I was a year ago. At any rate, I love my code base, I enjoy improving it continuously, and I enjoy seeing my users immediately benefit from the wacky ideas I come up with back at my desk. For the first time in a long while, I wake up excited every morning and I actually look forward to going to work. Life is good.

Thanks John, Harold, Jay, Peter and Paul. You guys have given me answers to the core problems I face every day– even as a lowly database app developer. I may not have the privilege of being able to code in a lisp dialect professionally, but at least I can now begin to “Greenspun” with the best of them….