Software engineering importance

[Versión en castellano]This link opens in a popup window

Introduction

In former posts I have written about the importance of adaptability and maintainability. In this post I’d like to focus on the engineering aspects. I mean to say, how these issues could be addressed from a software engineering point of view.

9378193_339189378193_33918

First and foremost, I like to think on software as a set of interrelated systems and components, each one could be actually implemented as a function or an object, to name but a few. In fact, these implementations details are not so important, the critical point of view is that all of them should behave as a unit of functionality. Both the concept of unit of functionality and systems are thoroughly discussed in software engineering literature. But I like to highlight this approach, instead of using concepts as API or service, because, on the one hand, it allows me to reflect on how each single software component should behave and, on the other hand, the idea of a system, its dependencies, its ability to be simulated is pretty aligned with my education in another engineering field.

Be that as it may, this concept or unit is utterly important. Let’s imagine a complex machine comprised of several components or even systems. For the sake of example, we could talk about several gear systems, an engine or even the individual gears. Obviously, not only should the full system work smoothly but also each individual component. Furthermore, the gears could be used in another complex machine. So then, they should work properly and according to certain specifications. Hence, when we talk about software we are talking about similar concepts and ideas, following system design principles and proper system or component reusability.

Explaining concepts

Further to this, problems arrive when we try to explain how software systems should be built, how components should be isolated or how can reusability could be achieved. It is, indeed, not an easy task since acquiring a proper comprehension requires that the teacher has the knowledge and the learner is actually ready to apprehend it.

11107581_463006211107581_4630062

Certainly, we have developed patterns, SOLID principles, and tools like TDD, but I wonder if an unmature developer is able to understand how these tools could allow him to develop a proper engineered system or component. From my point of view it is hard without a proper mentorship and teaching-by-example.

A sample use case

In order to clarify my point of view, I would like to showcase an actual example of a subsystem we are currently working on, a whatsapp/telegram bot application, a directed question based one. As a matter of fact, this is not a complex application. Its difficulty comes from system’s decomposition and proper testing of each component. Let’s try to make the exercise that you are junior developers and you have to build this solution, what could be your approach? If your team leader is kind enough, he could suggest you to start developing the Telegram Bot and when it works properly, to build the Whatsapp one. Unfortunately, this is a recipe for disaster from the point of view of system design. If you wonder why, take into account that I stated that you were junior so, probably, you would build your bot following an approach similar to the following one:

  • You would look for Telegram API Library in your preferred programming language.
  • After finding the library, you would develop the bot acting as a humongous switch-case, request-response system. Pretty tightly coupled to the Telegram API library.
  • Since you were requested to write tests, you would try to test the system almost to its full extent.

If you are senior enough you will have certainly expressed your discomfort at the idea of such a piece of shit, since, among other problems, that strategy drives to implement Whatsapp Bot from scratch. Actually, the problem is not only placed on the junior side, but also on how the senior, the team leader or the project manager has given instructions or has followed project development. A better instruction set, from the point-of-view of system’s architecture should have included the following blocks:

Imagen2Imagen2

In depth,

  • The conversation subsystem is the subsystem responsible for both receiving questions and emitting answers in a Bot independent manner. This system should be comprised of different elements as state - perhaps a stack based one -, or the set of different supported actions.
  • The network layer which is used to exchange information with the actual Bot Provider (Whatsapp or Telegram). This network layer could be a third-party-provided library.
  • The integration layer, used to intercommunicate the conversation subsystem and the network layer, translating specific network messages to the expected inputs and the conversation layer outputs to proper network messages.
  • Obviously, testing should be done in each layer, and if we talk about unit testing, we should write them to test only specific layer codebase.

In conclusion

It could be considered that a software system written this way is complex. Well, in fact, it is. Even more, if we take into account that each individual software component should be written taking into account similar ideas such as isolation or behavioral design. Advantages are subtle, but important:

  • System will be adaptable, since we can improve one of the layers without affecting the rest of them. Provided you have a new kind of message you will only have to modify the proper conversation subsystem’s component.
  • System will be maintainable since its decomposition in components, make it easier to modify the codebase, to understand its aim.

On the other hand, any system has a certain degree of complexity. Recovering the analogy of the gear system, knowing what a gear does not mean that you know how to create an automatic watch. Ignoring the complexity of this kind of work, the actual engineering behind it, only drives to unmaintainable products and more costs than the initially expected.