The other day a customer asked me to give them some advice on building or acquiring a development framework. As it turns out, I've spent most of the last seven years either building or using reusable code assets of various kinds, so I happily agreed. And since I've still looking for directions to take my blog since leaving p&p, I thought I'd share some of this with you too!
First, a quick comment on terminology. I generally avoid the work framework since it tends to mean many different things to different people. Still it isn't necessary to get hung up on what is and isn't a framework, as this discussion is really about reusable code assets in general. But while we're on the topic, here's the taxonomy I normally use when thinking about reusable code:
Code reuse is of course a very good thing - provided it is managed well. A good reuse strategy will lower development time and cost and result in applications that are more consistent, of higher quality and easier to maintain. Unfortunately implementing a good reuse strategy is easier said than done. Over the course of the last ten or so years I've seen a number of different strategies in use at customers, including:
All of these strategies are in use by some customers today, and all can make sense under some circumstances. However the general trend has been to move through this list in order, and more and more people are gravitating towards number 4.
But whether you are building your own framework, evaluating one that already exists, or extending one, there are a number of common pitfalls I've seen people fall into. Here are the main offenders:
Of course this is just my opinion based on my own set of experiences. Do you agree with my list of deadly sins? Do you have anything else to add to the list? What do you think is the key to a successful code reuse strategy?
Some of your assertions I agree with.
One you didn't mention was that a great deal of solutions aim to solve non-standard requirements. i.e. there are way too many types of customer requirements - hence way too many frameworks and solutions that can't be re-used with high effect (and bloat the solution domain). They are also way to context specific and hard to learn another customers requirements which they fit well.
A lot of this would be easier if requirements were standardised, with standard solutions if you get my drift. Then framework applicability and reuse would increase dramatically, becuase there would be a common understanding of common requirements and appropriate solutions.
The other point is that any given framework (or other high level abstraction i.e. a DSL) is typically not suitable for adaptation to another slightly different use (unless that use in on teh same axis as orginal DSL, i.e. a specialisation or generalisation of it), and adapting or hacking to fit that different use becomes more trouble to maintain than its worth. Again, this is a side-effect of non-standard custom requirements.
One of the biggest problems customers face in the real world is assessing any given framework will apply to them. In order to do this, many feel like they have to own a deep understanding of it, and they need an exact match between their unique customer requirements and those covered by the framework. Doing this easily is the largest challenge with selecting a framework, and to be fair, most organisations don't have the time or budget to invest in that exercise (not that it wouldn't pay off, but more becuase it's easier to take a 'not built here' position so they can tackle the intellectual challenge themselves). Resulting in of course rolling their own one-off solution or half-baked attempt at a reusable framework - which suffers the problems you point out in the first point.
This will be printed and posted on my cube with all the other good advice on it that nobody follows. Well said Tom, keep it coming!
You've been kicked (a good thing) - Trackback from DotNetKicks.com
This feels very much like a list of sins for Big Design Up Front frameworks. I think if this list were written from an Agile perspective, it might look completely different.. Thoughts?
Jezz - it almost sounds like you're suggesting we use something like a Software Factory! :-) Of course I agree that these are valuable and can simplify many aspects as reuse by packaging related resuable assets together and being explicit about what requirements they do and don't address. However I still believe that the potential pitfalls listed here can apply to almost any resuable asset type, including software factories (which are really a context-specific combination of all of the asset types mentioned in my post).
Evan - I'm not sure I agree. If you set out to build a business application using agile techniques, then any frameworks or other reusable assets would need to fall out of the user stories, and as such many of the risks I've listed shoudn't occur. However if you set out to specifically build a resuable asset, even if using agile techniques for planning and developing, I believe it's possible to fall into these traps. Ultimately most of these issues are a function of the requirements and priorities, and if these aren't thought through well it doesn't really matter what process is followed to actually build the thing.
I don't think software development methodology makes any more of a difference than the language when it comes to good/bad - success/failure.
Projects/frameworks written with Agile/RUP/ERUP/Scrum/Waterfall have all had successful outcomes and complete failures. Just as projects/frameworks written in VB/C#/Fortran/C++/Java/COBOL/RPG have all had successful outcomes and complete failures.
If our community focused more on doing things right, and being pragmatic about it, rather than trying to find the golden methodology/language that will solve all there problems or be the solution to 90% of there problems, maybe we would have so many pointless debates about which is better and why and so many shops that have the horse blinders on and won't even consider other options. All methodologies, all languages have there pros and cons. Use the right tools for the right jobs.
Making sure that eveyone in the team / organisation knows what is available can be a major hurdle. You can spend forever creating the perfect comms layer but if no-one else knows youve done it, youve wasted your time. I sometimes find myself creating code to perform a particular task only to find out later that theres already a method in the .net framework that would have done the same thing for me. The same applies.
I think number 7 is a big hurdle for a lot of people too...especially when it comes to naming your classes; things like CarImpl? WTF? It's either a Car or it's not a Car. If you want to talk about it generically call it a Car (abstract or root) or ICar (interface); if you want to talk about it specifically, call it a Saturn, or a Ford - but these stupid Impl classes I see floating around in some frameworks is just asinine. Oh wait, I probably shouldn't use the word 'asinine' - sorry Tom; let me just hit my KeyImpl a few times on my InputDeviceImpl and remove those...
Anyway, unnecessary declarative programing... why have all your objects config file driven and all this extra fat in your config file if there's not a chance in a heck that you're ever going to need that type of flexibility. It's hard to maintain, much harder to debug, and harder to develop new features against. It's like the UIP or WF - great/outstanding framework - if you need that level of flexibility and scalability - but if you don't need it why are you adding extra complexity? Martin Fowler has a few words for those of you answering with 'we might need it someday' - 'Speculative Generalities'. But then unfortunately a lot of developers just add it because it's there, it's considered trendy, and 'they can' - that's even worse than speculative generalities - that's outright amateur.