In the software world we constantly use abstractions to make our work easier, as they abstract us from other domains and significantly reduce the complexity we have to deal with. An example of abstraction is ORMs. An ORM allows us to abstract the application from the database being used. Instead of having to write queries (specific to the database engine) to access the data, the ORM allows us to use the programming language we are using to code the application, also to access the data. Anyone who has used ORMs knows that in many cases the abstraction works well and brings a lot of value, but when the application requires us to get multiple related entities, among other examples, is when we start to see the limitations. In these cases, it is common that ORMs do not always generate the optimal queries, or that they require us to write excessively complex code, so that sometimes we end up writing queries directly in the language of the underlying DB. This means setting aside abstraction for such cases.
It is at these moments when abstractions begin to “take on water” that an understanding of the abstracted domains or layers becomes necessary. However, developers often become mere users of abstractions and fail to take an interest in what lies underneath. Sometimes we do this because of lack of time, but in many other cases it is because of a lack of basis or interest.
Nowadays there is a proliferation of schools that teach you to program from 0 in a matter of months, in general these schools focus on teaching you the languages and frameworks at user level. Everything is very hands-on and almost from the beginning you are programming. But anyone who has gone down the path of learning to program knows that it takes years, not months. And that it takes a lot more knowledge than just knowing how to use a framework. It is only a matter of time before students in these schools encounter the limitations of abstractions. In these cases they will have two options: to try to avoid the problem, with a workaround of more or less severe effects; or to recognise that they have to go deeper into the abstracted domain and work on it. And only one of these paths will bring them closer to becoming programmers.
However, this is not just a problem that affects programming students, all developers who program applications with a minimum degree of complexity will sooner or later run into this problem. And I think programmers often accept abstractions as perfect, we “fall in love” with abstractions. And we forget that they are tools to make our lives easier, and like all tools they have limitations.
Today we are faced with what is probably one of the greatest abstractions in history, namely AI language models, which allow source code to be generated from natural language. This abstraction is so powerful that many believe it will no longer be necessary to know how to program in order to create software. However, those of us who have used this technology to generate code know that it still has significant limitations that require solid programming skills to overcome. While abstraction is likely to be refined over time, I think it may be a mistake to think that we can train a new generation of developers without programming skills, just as ORMs have not eliminated the need for database skills.
While the value of abstractions is indisputable, as they allow us to soar and to undertake greater goals with less effort and complexity. I see it as very important to be aware that they are not all virtues, and they also have limitations that cannot be overlooked. From all this I draw two conclusions: on the one hand, the choice of an abstraction has to be made by analysing both its virtues and its drawbacks, being ready to discard them if this analysis is unfavourable, and on the other hand, we have to bear in mind that when we come up against the limitations of abstractions we will have to have a good knowledge of the underlying domain in order to give a solid answer. If we or our team only have user-level knowledge of them, it is only a matter of time before we run into problems that we cannot solve satisfactorily.