Developers are very good when it comes to abstracting things, be this: 1) generating base or generic classes to inherit from or reuse; 2) generic or overloaded functions called with arguments instead of standalone ones; or 3) reusing code under multiple technologies even if it’s difficult to achieve this (e.g. with Xamarin).

While such skills are very important in the programming world, it is also very important that they are not overused in the commercial world!

I learned over the years that very often it’s better to just not abstract things than to do it. (I know this will probably start a big discussion that can never end or at least will turn some of my readers’ minds into generating complex comments like… !@#$%^&*). Here’s why:

Many times we abstract things assuming that the customer(s) will request similar new features in the future, and that in this case we would be able to develop them easier; but we spend a lot of time with the initial setup, while it’s not certain that it will bring any value eventually – customers are unpredictable – and often it turns out that if we wouldn’t have generalized things we could have delivered – at least the first version of the product – sooner (sometimes sooner than our competition!)

Of course, if later we would really need refactoring, we could ask the customer to pay some extra for it, whenever he or she requests a similar feature, explaining him or her about the easier maintainability when not allowing code duplication (money that it would have been difficult to request initially).

Other times there is also a personal value concept involved, such as generated by the feeling of doing things the way we think it’s better: we like to abstract things so much that we want to do it regardless of its commercial benefit.

While from a technical perspective, I observed that having some duplicated code or not sharing code under different technologies comes indeed with some challenges and harder management, but it’s not impossible to live with it: you just need extra care and some good tools during maintenance time.

Moreover, many times the customer(s) will request small changes applying only to one or some of the “duplicated” cases, and if we would have done it with too much abstraction it would have required so many argument chains to be passed along the internal code routes to obtain the intended behavior that we’d say to our customer that it’s not possible to do it – to just keep code readable (and he or she will surely not believe nor understand us!)

Finally, note that sometimes you just can’t share code, such as if you develop apps or components in a multi-platform+native way, e.g. if you develop for Windows using C#/C++ and UWP/WPF, for Android using Java/Kotlin, for iOS using Swift/Objective C, and for the Web using TypeScript/JavaScript and a framework like Angular (and maybe later also for holographic computers using Unity 3D and its C# subset): the contemporary programming languages share – at their core – more or less the same concepts, but they require different syntax and approach, and the maximum you can reuse is often the logical design of the app and a few common looks and supported input types (for UI, at least, you can easily imagine that supporting both 2D and 3D, or mouse, touch, and air gestures together is going to be very, very “expensive”.)

Even if you accept no-nativity for some targets, such as deciding to use C# and Xamarin to get your single codebase app working on UWP, Android, and iOS devices with ease (although this itself would generate other problems, when corner cases would be encountered), you will probably still need a different programming language for the Web and later probably something completely different to support 3D holograms properly.

So do not do your best, and worry less: that’s my advice today, and I’d give it to myself as well, if I could go back in time a decade or two!

This does not mean, though, that you should never abstract or refactor your code. Instead, it means just that you should do it properly: analyze the opportunity of any possible abstraction before you actually apply it!