This is a follow on to part 1 of this series. I'm talking about how to produce software quickly. To be clear, I'm not talking about producing brittle software quickly. Software is too expensive to be built cheaply. This mantra is a good tagline, but it is so true. The software I'm asked to produce is important. It can help make or break the company. The stakes are too high to take shortcuts. I've seen software systems launch with a glory of "congratulations" emails flying around. "The project was a huge success", everyone cries. Then, 2 short years later, developers are threatening to quick if they are forced to attempt one more change to what is now seen as a complete and utter flop. Then management calls for a rewrite. Never mind that there is no introspection about what happened? How could a roaring success turn into a flop in 2 years? No, no time for retrospective, we need a rewrite. And the cycle continues every two years. That is not what I'm talking about. The software needs to be sustainable. It can never become so complicated that newcomers to the team have a hard time figuring it out. It has to glow of simplicity. Anything large and complex can't be simple, can it? I think it can. In this installment, I'm going to talk about a favorite mantra of mine when working on a software product.
Part 2: Dodge as much work as possible
You are laughing at me right this moment, but I'm serious. If I can get away with NOT doing something, I will. There is an infinite amount of work to do on the product, and my team has to produce business value quickly. Logically, we have to maximize business value delivered with each unit of work chosen. Certainly product management needs to prioritize items so that what we work on actually matters, but along with feature stories, technical stories creep in. What other type of work do we find ourselves doing that doesn't translate directly into business value?
First of all, if a high measure of speed is important for the product, the customer will communicate that. Software that flies a fighter jet has to be sufficiently responsive that when the joystick moves, the plane moves with it. 1/2 second delay would be completely unacceptable. Now think about an enterprise business application. Think about Microsoft Outlook. How often is there a 1/2 second delay or more when performing an operation? Is it a show-stopper? Is the application unusable when the progress bar pops up to "check email"? Absolutely not. It is tempting to stroke our technical prowess and ponder ways to save some CPU cycles. After all, I'm iterating over that collection twice. Maybe I could trim it down to just once. . .but those operations are in different classes. . . hmm. . .could I alter my design to save that 2nd iteration? That sounds absurd, especially when your next operation is calling a web service in another state. You might save a few milliseconds, but then you promptly wait 1 second for the web service call to complete. While performance tuning, you have some other high-priority stories assigned. The next stand-up meeting includes your 4 hours of performance tuning, and the customer can't tell a difference in the speed of the application. In other words, developer time was spent on something with no business value. Database access is often another slow area that is optimized. Database access is an "out of process" operation, and is inherently slower in orders of magnitude than any in-process operation. A typical application, when profiled, will find 80%+ of processing time* in data access operations, not in-process object model manipulation or screen drawing.
*Statistics made up on the fly with 95% accuracy.
It makes sense to optimize data access then, doesn't it? I don't know. Does it? If you don't do it, what will happen? Will the customer report that the application is too slow? Will the customer even care? Is it a SQL Server 2000 database with 1,000,000 records total and no more than 10 concurrent users? If so, your database server laughs at the load you place on it every day. It can serve up your requests with one CPU tied behind its back.
It's easy to accept work given by the customer as "#1 priority". It's not so easy when the team comes up with technical stores. Many technical stories have merit, and we, as professionals can see things coming, and we need to be able to responsibly allocate work for ourselves that otherwise would not have been brought by product management. For instance, we must take reasonable measures to secure the application. The basic one is the database connection string. How do we store an secure it. The customer doesn't know about databases or connection strings. The customer may love the application, but it a script kiddy can find the connection string, access our database and call our delete stored procedures, then we have a big risk in the software. Explain that to the customer, and they will understand the time spent on securing the connection string. Judgement comes in to play, though, because we could symmetrically encrypt the connection string, but then a savvy developer could probably hack our software. Judgement: Is the customer paying for protection from ill-meaning savvy developers in the company? This technical story could quickly explode if it's taken too far.
Back to data access. Wouldn't it be great if we could somehow detect which table columns were changed so that when we did an update, we only updated that column? To that, I'd say "that would be terrible. . . if it took more than 10 minutes to implement". If my product were a super-high-traffic site, maybe. If my product is a enterprise app with a maximum of 10 users actively on the system at any given time, then no. 1000 users of a system in any given day might not even translate into 10 database operations happening concurrently (during the same second). In this case, there is absolutely no business value derived with this technical story. If accepted, we are effectively wasting time. We need to eliminate waste.
"To build our application right, we need to build a framework first." Other people have written about this, and I've been there. In fact, I've been a framework writer. Boy, did I crank out a lot of code that nobody uses! If a framework is the deliverable, then ok. If an application is the deliverable, then we'll be building the application, not a framework. Besides the fact that it's hard to know what to build before something exists to use it, a framework is a technical story that the customer doesn't benefit from. I am a big fan of using frameworks to build the application quickly, though.
Build vs. buy
I default to buy and then entertain convincing arguments to build. Think about the extremes and then work your way back. Would you build the .Net Framework? No, buy it (obtain it). Would you build your own web framework or would you use ASP.NET, struts, webwork, rails, etc? Would you build your own ADO.NET provider, or would you use DataReader and DataAdapter? Would you build your own data access plumbing or would you use an O/R Mapper or code generator to build this mechanical, boring code? Would you build your own screens of the application completely or would you buy a UI controls library? All these questions have the same thing in common. Commonality! .Net Framework is used in all .Net applications. Web frameworks abstract away Http plumbing. ADO.NET providers handle the binary communication with a database. O/R Mappers deliver the transition from a rich object model to the relational storage view of the data. UI controls abound to get a nice look and feel by leveraging the UI expertise of the industry. What is left? I'll make an assertion. The only thing that should be left is the code that is unique to your product. This is the code that makes the application important. Everybody does UI. Everybody does data access. Only you deliver application X. Your customer needs application X for a specific purpose, and that purpose is modeled by you. It is the one thing you can't buy. You can't buy the distinct business value you are delivering with your custom software. In fact, that value is the only thing custom about the software. It is what matters, though. By defaulting to buy, I can dodge quite a bit of work. I don't have to spend time on fancy UI controls. I don't have to spend time on boring data access plumbing. I can focus solely on providing unique business value.
Not created here syndrome
This is the fear of tools and libraries. Essentially the fear of the unknown. If it's not from Microsoft and not from us, then we're not using it. I firmly believe that if Microsoft hadn't delivered VSS, many more shops would have never began using source control. There are countless tools and libraries available for use that ignoring them can be irresponsible. It's different in the Java world. The beginning of a project starts with the selection of tools and libraries. Often for web apps, they'll choose Struts, Spring, and Hibernate. This combination gives them the shell of an app, and developers are able to focus on the object model that makes the software valuable. Hibernate is very common for Java apps. Microsoft doesn't have an O/R Mapper. Once they do, no one will ever write data access code again (mark my words) in enterprise apps.
In the .Net world, it can be a struggle because some folks think that Microsoft is the only entity capable of producing a quality library. Not created here syndrome leads to 3 times as much work as necessary.
YAGNI: You ain't gonna need it
If the customer specifically asks for a function build it. If not, don't. Let's say your customer needs a windows app for managing contacts (I know, trivial example). The customer needs to be able to add, edit, and delete contacts. Say you start working on the add feature, and you speculate that you should probably make a screen so that several can be added quickly. It seems like a logical extension to the feature, and it seems that it could provide value. The danger is that while you work on the multi-add screen, the edit screen isn't getting done. A savvy customer will quickly question and correct this type of behavior. It might have been a logical variation of the feature, but it's not the most important thing. Like I've said before, there is an infinite amount of work to do. The art of product delivery is focusing on the small subset of work that will be valued the most. Essentially, if I demo an incremental build to a customer and I have to point out something, then we point in a feature that could have been deferred in exchange for something more important. The customer will come to the demo asking if three things are done: add, edit, and delete. Until those 3 things are done, the product team has no right to insert other work in front of the key stories. With the YAGNI mantra, I assume that if the feature isn't specifically requested, it isn't going to be needed. Maybe it'll be needed later, but that's just speculation. When the priority is to deliver value quickly, I have to be able to defer nonessential work.
It's somewhat of an art to be able to filter that infinite pile of potential work done to a small subset of work that will satisfy the customer. Ratholes and scope creep are very dangerous to the timely delivery of software, and I keep in my mind always: "Can we put this off 'till later"?