This post is intended to be the first of a series. I want to be clear about what it entails and its intended audience.
For the past several years I’ve been an architect in enterprise-level RIAs. This is a fancy way of saying I oversee the design and construction of apps that are web-based but have a lot of the same characteristics as desktop applications. Some of the applications I work on are in fact desktop applications but heavily communicate with the web. The line becomes very blurry, but the main point is — I deal with applications which in my world are quite different than what is often considered a “website” even though they both live within a browser.
You might think this is a broad effort, but my goal is not to simply regurgitate everything I’ve learned but to help boil things down to what’s important to get you on your way. We’ll discuss core principles that are common in dynamic apps regardless of the languages or libraries used. However, to illustrate them and hopefully give you enough of a concrete example to help you hit the ground running, I’ll be using specific, hand-picked libraries for this series. In your own research you may find other libraries are more appropriate for your particular project. That’s fine; the principles in this series are still valuable and applicable.
For an architect, specifically in an enterprise setting, these decisions will be very important and can ultimately determine the fate of your product. If I were farting around on a side-project, I’d probably feel comfortable picking the most awesome-sounding libraries and running with them. In the corporate world though, we have to answer some important questions: Is our product part of a larger suite? If so, what is the rest of the suite using? If the rest of the suite were to standardize on a particular library, how hard would it be for us to refactor? What if we chose a “full-stack” library and a portion of it is or becomes inferior to other options? What’s the chance that a different library may overtake my library in community and technical progression? What’s the community like around those libraries? Which libraries are gaining steam or fizzling out? What’s their learning curve? How easy is it to hire developers for these libraries? It’s a very different ballgame so take care in your decisions. In my case, I found the best option was to pick a handful of high-quality tools with healthy communities that worked well together but were decoupled in their implementations. Grooveshark provides a very interesting related case study.
Rolling your own
There comes a time in every developer’s life where we get caught up in rolling our own libraries. Maybe we think our work is superior, maybe we don’t do enough research on what’s already available, or maybe there’s just one small thing that isn’t quite right in a library so we rewrite it from scratch. I’ve done it and you likely have too. When determining what your team will use, it’s very important to keep in mind some of the significant benefits of going with a wisely-chosen 3rd-party/open-source library:
- Free development resources
- Free documentation
- Free bug fixes
- Free testing by automated tests and other community members
- Collaboration amongst generally intelligent industry leaders
- A place to learn more and ask questions
Far too often I’ve seen very intelligent architects roll their own libraries because they feel their skills are superior or are OCD that the libraries work exactly like they want and carries no extra baggage. Very often, if that architect were to stay on the project forever, this would probably work out quite well and the product would be successful. In reality, the architect leaves. Almost always they were time-crunched and didn’t fully document the library, set up testing, or cross-train their co-workers. They developed the library for the purpose of fulfilling the specific needs of a project and even though the library may have been a fantastic work of art, the engineers left with that work of art don’t understand its intended usage or how to make modifications. From there, the engineers begin using it incorrectly and if they have questions they have nobody to ask and nowhere to look except for undocumented, increasingly morbid code. Inevitably, the product starts its death-spin, the engineers blame the architect that left, and technical debt grows until the product declares bankruptcy. At this point it’s time to rebuild or sink.
Truthfully, most of the fault really does fall on the architect. The role of the architect is not only to code awesomeness, but also to understand the software circle of life and make wise decisions.
Don’t get me wrong — there is a time and place for rolling our own libraries. If you come across this time and place, make sure you have the necessary resources behind it. Do it right. Where possible, create the libraries as though other companies might also use them. Document them — not only in code but in API documents, examples, and tutorials. Open-source them on GitHub and make it a home for external resources to congregate around and contribute. Pay attention to others’ contributions and incorporate their ideas and code where possible. Many if not most of the great libraries available today originated from this concerted effort.
One last note about open-source libraries. The historical perception is that these libraries are siloed away in some remote part of the web and their developers are anonymous and unapproachable. This usually isn’t the case anymore — especially with GitHub. Oftentimes if you have a legitimate concern the community is very approachable and will respond quickly and respectfully. A great example of this is when I recently found that underscore.js lacked a function for finding the symmetric difference between multiple arrays. I provided the underscore.js community an example of where it would be beneficial and five days later it was added to the trunk with a unit test and documentation. Good libraries have good communities. Choose wisely.
We don’t need no stinkin’ frameworks!
A long-standing debate among some in the community is whether formal frameworks are needed at all. The argument against frameworks usually goes something like, “We’re all smart engineers — we can architect an app well without having to resort to a formal framework.” That may be true, but it’s usually a fallacy. If it’s not a fallacy, it’s very difficult to do with most teams. If you are able to successfully execute on that concept, you very likely unconsciously re-wrote large portions of a framework you could have used in the first place.
When working in a team, a framework provides an important benefit of consistency and a game plan. Good frameworks generally prescribe examples of best-practice usage but provide some flexibility in implementation. No doubt engineers can abuse the best of frameworks, but having a blueprint of how architecture and implementation should, in general, be performed goes a long way in getting everyone on the team to have a consistent vision and understanding.
Have comments or questions? Post them below!