When working on a project, there are hundreds of possibilities for reuse of existing components. On first sight, some of them seem to do all we need or to do it partially. However, we rarely know the details. Without looking at the code, there is no way to know how it does things or what the priorities were. In the best cases, good documentation with usage samples will be available (API documentation is useless in this case). We don’t know how flexible it is or what the limitations are. There is also the whole question of quality. There is nothing more annoying that reusing code only to realize it’s full of bugs, then go through the code and realize the documentation was wrong.
The question really is to reuse or to rewrite. Writing it ourself is a very safe route without too many surprises, but it’s a long one. When you write it yourself, you know the details. The implementation is usually light an tailored to your needs. It’s easy to extend in the future, because you know the details and the vision. Choosing the reuse route is accepting a packaged deal. The implementation does what it does. Evaluation will tell you it does what you need. It will also come with a whole lot of elements you don’t really need. It may end up being good, because you may need them in the future, but on the short term, it clutters your vision. Reusable code weights a lot more than custom-built code. It contains more validations and verifications to deal with all sorts of environments and to produce better errors for the implementor (if you produce a reusable library that is “lightweight” and does not contain all of this stuff, what you produced is a custom piece of code you decided to give out). All this code has a value. When reusing code, you have a peace of mind. If you migrate to a different platform, or browser technology evolves, you won’t have to deal with the problems yourself. A simple update will do (never considered reusing an unmaintained component).
However, when you develop your software and need something that does not quite fit with what it does, you’re in trouble. You can work around the problem, which is likely to be innefficient, or you can fork the library and deal with the trouble of updating (only works with Open Source, but you want to use Open Source to have this option). The latter is completely undesirable. The ideal solution would be to contact the authors and see if you can get your modifications, or at least the required hooks, to be part of the core. Good solution, but they might refuse, and you still need to go through their code and understand it.
Reuse works great as long as you don’t push the limits. Low initial cost, high cost to maintain if you go beyond what it does.
- Writing a quick solution can be faster than reusing an existing component
- The quick solution will be easier to extend
- The quick solution will have a lot of maintenance to do if the environment changes
- Reuse makes migration easy
- Reuse will require more effort if you need to push the limits
The worst thing you can do is to decide to write it, publish it and maintain it. Down the road, you will have a clone of the solution you discarded for being “too heavy”.
So, if you want to reuse a component, the one thing you want to avoid is having to go beyond it’s limits, or expect those limits to be moved further away by the time you need it. It basically means you know the library is maintained, will be in the future, and has a good vision of where it’s going. This is a lot of trust required. Why do I prefer Zend Framework over CakePHP or CodeIgniter? Mostly because I met with the project leaders early on in the project. I discussed with them and figured out the project could be trusted. I put my trust in the people behind it. Problem is, not everyone gets to travel around and meet project leaders (not that it’s hard, just that most don’t think they can). So if you can’t have a face to face discussion with project leaders (which may give a positive bias anyway), what can be relied on? You want to make sure there is a community of people invested in the component and that the project will survive. One man shows working on hobby projects don’t really qualify.
Reusing a component adds weight to your project managment. Dependencies have to be maintained. You need to monitor releases and security advisory. It may call for an update that will require a few minutes or a few hours of work, and that call may not fit in your project’s schedule. You need to trust the project to be responsible about this too. If they reuse components themselves, do they follow the security advisory, or will you have to do that too?
One thing for sure, when you decide to reuse a component, you need to abstract it away. There are two reasons to this. One is self defense, so you can change to something else without too much effort if required, the other is more subtle and often forgotten: to preserve the aesthetics of your project. Each program is developed with a certain style. In a good program, you can guess how functions will be named and how objects need to be interacted with. The high quality components you reuse are probably like that too, but it’s not the sample style. Reusing without abstracting will create something that looks like patchwork, even when done by talented people.
These are the rational aspects of code reuse. There are also the irrational ones, which mainly cause to reject reuse.
- Wrong expectations
- Focus on other aspects
I’ve seen people discard solutions for having high hopes, and I probably did it in the past. The laziness that makes great programmers can turn bad. When looking for a reusable solution to their problem, they hope that it will do everything they need. A bit like the VB expectation of RunTheProgramINeedForAssignmentNumber6(). Sometimes, you need to accept that the library won’t do everything and making a feature request for it is ridiculous. If you want to reuse a data storage layer, it may not do the remote synchronization you need, and it’s right not to do it, but you should not discard the storage layer because it does not do everything you need.