Modern applications are extremely rarely created “from scratch.” They are assembled from already existing building blocks – components, libraries, and frameworks, and there are several compelling reasons for this:
- The volume, complexity, and sophistication of applications are increasing, while the time allocated for their creation is decreasing. It is more beneficial to spend the time and intellect of developers on business logic code rather than application infrastructure code. - Widely used components and frameworks have fewer chances of encountering errors compared to those developed independently. - High-quality tools are available for free on the Internet, which reduces development costs and simplifies the search for interested developers with the necessary experience. - The creation and maintenance of software require a significant amount of human labor, so it can be cheaper to buy ready-made products than to create them.
However, the right choice of ingredients for a new application can be a challenging task that requires a thoughtful approach. When making your choice, several factors need to be considered:
- Each tool is designed for use in a specific context, which includes infrastructure, management model, data model, communication protocols, and so on, resulting in a potential mismatch between the tools and the application’s architecture. Such a mismatch leads to the necessity of using “dirty” methods and workarounds to solve problems, which unnecessarily complicates the code. - Each tool has its own release schedule, and updating any of them can become an extremely complex and time-consuming task, as new features, architectural changes, and even bug fixes can sometimes lead to incompatibility with other tools. Each tool has its own release schedule, and updating any of them can become an extremely complex and time-consuming task, as new functionality, architectural changes, and even bug fixes can sometimes lead to incompatibility with other tools. The more tools there are in a project, the more acute this problem can become. - The more tools there are in a project, the sharper this problem can become. - There are tools that require serious configuration, often in the form of one or more XML configuration files, the number and size of which can quickly spiral out of control. There are tools that require serious configuration, often in the form of one or several XML configuration files, the number and size of which can quickly get out of control. As a result, the application looks as if it were written in XML, with just a handful of lines of code in one of the programming languages added on. The complexity of configuration hinders the maintenance and further development of the application. - There may be a strong vendor lock-in, where code that heavily uses their products suddenly becomes constrained by factors such as ease of maintenance, performance, scalability, cost, and others. - A strong vendor lock-in may occur when code that heavily relies on a specific manufacturer’s products suddenly becomes constrained by factors such as maintainability, performance, scalability, cost, and others. If you plan to use free software, it may turn out that in practice it is not so free after all. It may be necessary to pay for commercial support for this software product, and it could turn out to be quite expensive. - It is necessary to consider the terms of license agreements, even if it is free software. For example, in some companies, the use of software with a GNU license is not permitted due to its viral nature, in the sense that such a license allows the distribution of a new product only together with its source code.
My personal strategy for mitigating these issues is to start small – only with the tools that are absolutely necessary. As a rule, at the start, the most important thing is to eliminate the need for low-level infrastructure programming (and the associated problems). For example, in the case of working on a distributed application, this is achieved by using middleware instead of working directly with sockets. Then, if necessary, other tools can be added. Moreover, I try to separate external tools from the objects of my domain using interfaces and layers. This allows for the replacement of any tool with minimal loss if necessary. The positive side effect of this approach is that, as a rule, I end up with a smaller application and fewer external tools than originally planned.