The main idea is to discover patterns, implement them once in adaptable way, then adjust and reuse everywhere. But let’s go step by step.
There is a huge lot of patterns. All software systems, among with their unique features, face a lot of common problems to solve. And the narrower is the kind of the software, the greater is the commonality, related to unique features. In enterprise applications, commonalities can reach as much as 80% of the software, based on my personal experience. The commonalities should be, and many of them already are, captured in patterns.
One value of patterns, is being a catalog of proven solutions to recurring problems – this is what pattern is. There are many catalogs of patterns – GoF, EAA, EAI are just a few to name. Along with that, a pattern is only a recipe. It is still up to us to code the implementation. But hey, we’re in the year 2015… can’t we have a kind of… self-implementing patterns? So that once we capture something in a pattern, we don’t have to code it any more?
Applying a pattern to a problem that recurs multiple times is often a good design decision. Sometimes we can code it as a reusable component. There are many situations though, where we have to go and code that pattern implementation at every place it applies to. Can it be that we are duplicating code?
Most programmers would readily agree that code duplication is bad because it makes software maintenance a hell. Applying a pattern to hundred different places in a program, on the other hand, is rarely thought of as duplication. While it actually is. What if we enhance the pattern? Or decide to switch to a different pattern? We need to go and change every place in the code where the pattern was applied. Let alone the time it took to initially code these; twice with TDD.
Implementing the Self-Implementing Patterns
Good – we want to reuse pattern implementations instead of duplicating them, and this principle applies to every layer and tier in our software. But how can such a thing be achieved? I have implemented one solution in C# language for the .NET platform, which I plan to cover in upcoming posts, and there are probably more different solutions to this. Let’s leave the technical bits for now.
Here I only say that depending on development platform and programming language, self-implementing patterns can be easier or harder to achieve. Dynamically typed languages will often allow for easier implementations, than statically typed ones – the technical approach may vary. In either way, when choosing development platforms and languages for a new software project, one should consider feasibility and easiness of self-implementing patterns as a criterion.
Although pattern catalogs I mentioned before focus a lot on small building blocks, of which larger components and applications are comprised, one should not perceive this as a limitation of what a pattern is. There can be big patterns. An A-to-Z software architecture skeleton, a technology stack of libraries that play well together, or a set of data structures and algorithms for common business domains like e-commerce or CRM – all these are patterns as well.
The bigger is the pattern, the more important is the question, how well will it fit the needs and the requirements of a specific project. A big pattern must be easily adaptable to concrete requirements, otherwise it is useless. Such adaptability requirement stresses the importance of modularity and separation of concerns (aka decoupling) in big patterns design.
For example, consider a project in which a decision was made to use primary keys of type Int64 throughout the database. The project also decides to apply a big pattern of CRM domain, but it turns out that CRM pattern uses primary keys of type GUID. This is unfortunate, because besides violation of uniform design, using GUIDs as database primary keys introduces a new risk to the project of not meeting its throughput SLA, which in my example, is a requirement that cannot be negotiated. Hint: why CRM domain pattern at all cares about data type of primary key?
Orthogonality is the way – more light on this in upcoming posts.
Scope of Reuse
But in what scope can patterns be reused? Well, obviously, this can be done within a specific project. Or maybe, implementations can be shared among several projects by the same software vendor – which sounds even better. Of course, the pieces which contain unique algorithms, or anything considered by the vendor to be its competitive advantage, stop there.
With enterprise applications as an example though, most of the code is dedicated to solving the same recurring problems the majority of software-related companies face. Self-service portals, product licensing, usage tracking, let alone business-invisible infrastructures like connection from REST to ORM with hooks for business logic in between – to name only a few examples; the list is long. If so, why should every project, or every company and vendor, invest in reinventing the wheel? This is not the code which companies drive their competitive advantage from. The resources saved on reinventing 80% of the code can be put into developing the rest 20%, the 20% that really distinguish a software product or service being developed from its competitors.
Single Implementation per Platform
Having said that, how far can we go? Obviously, implementation of self-implementation mechanism, as well as big patterns, will be specific to programming language, and maybe to development platform and runtime environment. Let’s simply name these a platform. Thus, we can have all the various patterns implemented once per platform in the world – most likely and preferably, by open source communities.
Once that happens, every new software project will be equipped with a lot of ready to adapt-and-use building blocks right from the start. By applying the relevant set of small and big patterns, a project will satisfy most of the common base requirements right away. Then all efforts will be put into development of the unique features, which bring the real value and competitive advantage.