You’ve been commissioned to build a custom application for a particular client. In addition, you or the client wants the option of putting the application up for resale when it’s done.
How should you approach this kind of software project?
Custom software takes a lot of time, and is very expensive for the client. They will sink a lot of money into design and development long before they even see the product, so it isn’t unusual to be asked to design for resale. This is a smart move. Reselling a custom application can help recoup the massive up-front costs, and it might even open up a whole a new market.
If you get asked to write software like this, do yourself a favor… expect that the initial client is the only client you will ever have. Create an amazing product for the current paying client, and ignore any potential mass-market opportunities for now. If you are successful with your fist client, only then should you start seriously worrying about other clients.
Once you have an initial product, you will almost certainly have to redesign and refactor in order to make it ready for the mass-market, so why not just design for the mass-market from the beginning?
Simple… risk and cost.
A mass-market application needs a robust and extensible architecture, more user and developer documentation, a full suite of built-in admin and configuration tools, installers, and support for multiple runtime and database platforms. It may also need localization, theming, and customization features far beyond what your initial client needs. All of this extra stuff takes time and effort, but has little value to the initial client. If you waste their time and money building to support other customers, then you will under-serve the customer you have now. Worse, you don’t even know if the application will be successful, or if it has the mass-appeal you imagine it does.
Getting to version 1.0:
Use an agile process. You don’t have to use a formal methodology, but stick to the agile basics. Code the bare minimum you can get away with, deploy it to your paying customer for testing, get their feedback, then go back and code some more. Repeat until you have all of the 1.0 requirements implemented.
If you are doing this under contract, I suggest that you price your deliverable in iterations too. Embrace your customer’s tendency to introduce feature creep, and shift the requirements as you go. Be eager to change the design, just make sure you have a good understanding (and a contractual agreement) around change management –make sure you are getting paid for scope increases, no matter how small they are at first. Once you start doing extras for free, it will be difficult to charge for bigger change requests later.
Brutally cut everything you can from the client’s initial requirements list. Keep it simple, and implement only the bare essentials. Your client will insist that some fluffy features are “essential”. Ignore them and cut them from your implementation plan. You don’t have to tell the client what you’ve cut, just tell them you have their pet features scheduled for “a later iteration” –even if you don’t. As you deploy iterations towards a 1.0 release, your client will forget about many of those fancy features. Over time you will also get a better feel for what is truly important to the application’s success. Don’t waste time writing a bunch of low-value glitz that isn’t necessary –save that stuff for later versions.
Make absolutely sure that every user-facing feature you implement is amazing. It should be pretty, function smoothly, perform well, and be feature complete. It is better to tell the client that you haven’t implemented the user manager than to show them an ugly or incomplete user manager. Everything they see on screen, ever, should look and act like a finished product. Never demo anything that might disappoint.
Avoid over-architecting. It is tempting to layer and componentize everything, follow all the best practices, use the all the recommended design patterns, and leverage all those fancy OOP techniques you’ve been reading about.
Don’t do it!
Deliver the necessary features to get the job done, and do it as fast as possible. Where an advanced technique or best practice would reduce your own efforts, go for it! But, if you can’t say exactly how a chosen architecture moves the application towards the finish-line, scale it back.
High-coverage unit testing may be super trendy right now, but carefully consider how much testing you should commit to. Unit tests do not meet any of your application’s actual business requirements. Unit tests, collectively, are a complete application in their own right. They have to be designed, coded, maintained, and documented just like code for any other application. If you do heavy testing, you are effectively building a second application alongside the first, but are only being paid for one of them. That doesn’t mean you shouldn’t do unit testing, even high-coverage testing. But you must be as aware of the costs of testing as you are the benefits –especially when considering a test-first methodology like test driven development (TDD) or behavior driven development (BDD).
If you are working in a dynamic language, high-coverage testing is almost always a good idea. These languages tend to have weak design and compile time validation, and their code analysis tools are often quite limited. High-coverage tests compensate for the lack of compile time checking and weak code analysis tools. Also, in dynamic platforms, unit tests are usually easy to write, and have very low maintenance overhead. You won’t have to spend much effort on abstract architectural acrobatics, and you probably won’t need a lot of test-specific infrastructure. So test away!
For static language environments, the benefits vs. costs of high-coverage testing is much more complex. Some testing is a given in any project, but should you go for high-coverage testing, or a full blown test-oriented development methodology like TDD?
Unit tests have more value with larger projects and larger teams. It also has more value if your team has a mix of developers at different experience levels. For experienced developers and smaller projects, you often get better results just using good code-analysis tools in conjunction with compiler validation. In these cases, you can reserve unit tests for code routines that really need them –complex, tricky and critical code segments.
Also consider that high-coverage testing is much harder in static language environments. Often testing necessitates horribly complex architectural designs that wouldn’t be necessary otherwise. For non-trivial applications, you’ll also end up with a lot of test-specific infrastructure, mocking frameworks, and the need to develop deep expertise with the testing tools and technologies. So, commit to high-coverage testing only if you are really sure that the benefits to the development team are really worth the costs.
You should move 1.0 forward without much consideration for the mass-market, one concession you should make is to avoid 3rd party code libraries where you can. This includes 3rd party frameworks as well as packaged UI component suites. If you cannot produce an essential feature with built-in components, or can’t write your own easily, then a 3rd party component may be necessary. Try to stick to open source components if you can. Even though you aren’t worried about the retail market yet, you don’t want to trap yourself into dependencies on 3rd party technologies that you can’t legally redistribute, or that increase the price you will have to charge for your retail product.
Don’t worry about making everything configurable via online admin tools in version 1.0. Sure, it is nice to give your initial client built-in admin tools, but it adds complexity and time. Admin tools are not a frequently used feature-set, so they offer a lower return on investment. To the extend you can, stick to config files or manual database entry. Fancy GUI tools can wait until the core application has proven itself successful enough to justify the additional investment in management tools.
Stick to the simplest data access mechanism that meets your needs, and don’t worry about supporting multiple database platforms. Pick a database platform that the paying client can live with, and don’t look back.
In version 1.0, the most important feature set is likely going to be reporting. If your application has any reporting needs, and most do, you need to be sure you start with reports that dazzle your client from day one. Be sure the reports are pretty, highly interactive (sorting, filtering, paging, etc.), and are highly printable. Reporting is the part of your application that your client’s management will use the most, and they hold the purse strings. Knock them dead with killer reports!
Later, if you get to the retail market, reporting will also be the feature that makes or breaks most new sales.
After version 1.0: getting to the retail market:
I can’t tell you how to find and convince other people to buy your amazing application. What I can tell you is this: if 1.0 makes your initial customer happy, then you have an application that will probably appeal to other clients too.
You can probably make a few minor adjustments to the 1.0 product, and deliver it to other clients as-is. Get it into the hands of as many clients as you can, with as few changes as you can, as soon as you can.
Wait? Didn’t I say earlier that mass-market products required tons of extra stuff? Admin tools, documentation, installers, and all that?
Well, I lied. You will want that stuff for version 2.0 of course, but you can usually take a successful 1.0 product to market, even if it is still rough. Sure, it lacks customization, has crappy documentation, and poor admin tools… but if it works well enough for one client, it probably works well enough for at least a few others. So don’t wait on version 2.0, go ahead and try to get 1.0 out there now!
Why the rush?
You want to recoup the sunk costs of the initial development as soon as possible.
You need as many real clients as you can get so you can gauge if there are additional requirements that need to be addressed in the next version.
You can learn from potential clients that decline to buy your application. Ask them, politely, why they passed on your product. Is it too expensive? Do they have a better competing product already? Does your app lack essential features?
So… what about version 2.0?
If 1.0 was successful with your paying customer, you will likely be heading towards a 2.0 product even if you don’t have a retail market –your initial client will still want improvements. If you can’t reach a larger market soon after 1.0 is done, consider abandoning the larger market. This will keep the costs low for your one paying customer, and will reduce the scope of 2.0 considerably. Concentrate on just enhancing the application around your one customer’s more ambitious needs, and shore up the weaknesses in your initial design.
If there is a retail market buying your product, then keep in mind that developers may be part of your customer base. Developers may need to extend or interoperate with your application, so make sure 2.0 has good developer documentation, consistent APIs, and web service APIs.
Version 2.0 should mostly be about fixing up any sloppy code in 1.0 and improving the design to support those features you cut from the client’s 1.0 wish-list. Re-design, re-architect, and re-code the core framework to support future enhancements going forward. You probably aren’t quite ready for a lot of new user-facing features yet, so save most of those for versions after 2.0.
Version 2.0 is where you start thinking about extensibility, customization, internationalization, and advanced administration. This is also the time to give scalability more serious thought. What about really large customers with lots of data? Are you going to support multi-server or cloud deployments? Should you aim to provide the product as a software service, instead of a packaged product?
This is also the time to consider if the application needs interoperability with other products… perhaps you need to support data imports for customers migrating from a competing product, or using your product in conjunction with a larger suite of products.
This is also the time to reconsider your development team itself. Do you need to contract outside resources, or hire more people? Do you need visual and graphic designers? Do you need code optimization or big-data specialists? What about hiring a marketing firm? How about payment, billing, and sales?
One thing you should consider not doing, in any version, is supporting multiple database or server platforms. Pick the platform that makes the most sense given the development platform. The odds are very good that most clients can deal with your choice, even if they prefer another database or server platform. Is the cost of developing for multiple platforms going to generate enough new sales to pay for itself? Probably not. You’d be better off offering your product as a cloud service, than trying to deal with multi-platform applications. The exception is mobile applications, where you should certainly support multiple platforms right from the start.
And that’s really all I have to offer… once you get to designing version 2.0, you will know better than I do what you should focus on.