Computer Science is a branch of Mathematics. Have you ever wondered how Mathematics is a tool that can tackle a great number of different problems, on different fields relying on the very same concepts? Perhaps part of the answer is because, as Poincaré once stated: “Mathematicians do not study objects, but the relations between objects; to them it is a matter of indifference if these objects are replaced by others, provided that the relations do not change. Matter does not engage their attention; they are interested in form alone.”
In 1986 Brooks wrote a highly discussed paper on Software Engineering. Following Aristotle, he divided software construction into “essential” and “accidental” tasks.
Essential tasks are regarded as “the fashioning of the complex conceptual structures that compose the abstract software entity. Accidental tasks are the representation of these abstract entities in programming languages and the mapping of these onto machine languages within space and speed constraints.”
To appreciate that writing code is regarded as an “accidental” task, see we are designing a logical solution. It happens that we are constructing it using available technology. That is, the technology is a means to an end; it is what we got to build the essential.
According to Brooks, the “essence of a software entity is a construct of interlocking concepts: data sets, relationships, algorithms and invocations of functions. The specification, design and testing of this conceptual construct is harder than creating and testing the fidelity of the representation. ”
A pause here: he is saying that thinking and documenting the right thing is harder than building what is documented. That is to say, software properties are hard to model and therefore to predict, and it is a real engineering issue that still remains and makes me wonder.
On Mathematics, definitions of entities and their relations are the core of a theory able to solve problems on different domains; software composed by well-defined entities scales better. Well-defined components narrow down the number of possibilities an essentiality can be represented.
The Abstract Data Type
The word abstraction is everywhere on software engineering. What does it really mean? Normally when creating a solution, we ignore some details either because they are not relevant at all or because they are not relevant for that part of the solution we are proposing. When creating a library that will generalize an entity and its behavior, we are also proposing a set of abstractions. Faulty abstractions lead to faulty representations.
Interfaces and Contracts
When we create an interface, we expect two entities/objects to communicate (relate?) through this interface. A good interface provides just enough generalization to handle all the required transactions between two objects of a certain form.
The point here is that well-defined relations between well-defined objects lays out a contract which these transactions should conform to.
Reusability and Scalability
A scalable and reusable system relies on cohesion of modules. To achieve cohesion, we need to identify and model entities and relationships of a given domain. Eventually this model will translate into data-structures and computations.
As engineers we know that an ideal machine cannot be constructed. The essentials. On our way to build it, we face limitations on the available tools, technologies and techniques. An electrical motor efficiency is limited by the material, assembling and other “accidentalities”.
Software by its turn is a very complex entity. Although it occupies negligible room when compared to others human constructs, the number of discrete states is huge, and therefore the number of ways it can fail is even huger. It is hard to represent since it is intangible. This intangibility brings specific complexities not found on other typical engineering domains.