Low Level vs. High Level
tl;dr; Contrast between low and high level thinking in software engineering.
Many years ago I was an editor of a small magazine called “Eiffel Outlook”, which was dedicated to the Eiffel programming language. I wrote a number of editorial opinions, some are out of date today, but others are still relevant.
This editorial from September of 1995 contrasted the low and high levels in software engineering. I think it still is applies today.
Eiffel Outlook Editorial: September 1995
Recently a message was posted on COMP.LANG.EIFFEL that criticized Bertrand Meyer's advice to project managers: "when hiring, beware of C hackers". As one would expect a spirited discussion followed. Although parts of the debate went off in strange directions, it seemed to me that the main argument was driven by the age-old tension between the low and high levels of software. It was a fight between the "bubble-and-arrow" crowd and the "bit-twiddlers" - design vs. code.
I am sure that you are familiar with the extreme positions of both camps. The disciples of the "design-is-king" school say, design is what software is all about. Once the design is complete the implementation is just a trivial conversion into some programming language. A good Object Oriented (OO) design will translate into a wonderful OO system, even if it is implemented in a non-OO language, like let's say ...(gasp!)... COBOL.
On the other hand, the "bit-twiddlers" and compulsive coders reply - you can't make "bubble-and-arrow" pictures execute on the computer. The only thing that is important is the code, therefore there is no point wasting time drawing pretty charts, as that time could be better spent coding.
Clearly, both of these extreme positions are flawed. To start with I have two objections to the "design-is-king" view. First, I strongly object to the idea that the implementation language is unimportant. If the gap between the design concepts and the programming language is large, then the programmer must work harder to translate between the two. Moreover, such translation is a tedious, boring and error prone process full of, what Fred Brooks calls, "incidental complexities". In a word, it's a process best left to computers.
My second objection is to some designer's reckless disregard for the implementer's task. I have yet to see a design for any sizable system that was easily translated into code and ran perfectly the first time. There are just too many issues that are not considered by the designers but must be faced by the implementers - machine limitations in memory and CPU speed can render the most beautiful design unimplementable, unexpected dependencies between subsystems can make debugging hellish, and sluggish response time can make the system useless.
At the other extreme, "bit-twiddlers" position is not without serious problems either. The low-level gods often spent too much time so close to the machine, that they miss the forest for the trees - they never see the big picture. What good is there in optimizing a routine that only gets called once, or in coding bubble sort in assembler? Low-level code may be faster and it may use less memory, but it does no good if it solves the wrong problem. Also, we should not forget the poor soul who will have to fix the bits of low-level brilliance left by some wizard who has moved on to greener pastures.
The process of developing and maintaining software, that is software engineering, has many levels. Sometimes we have to work at a high level, as during analysis and design, and at other times at a lower level, as during coding and debugging. A true software engineer must be familiar with all these levels, as ignoring one at the expense of another only leads to problems.
Moreover, note that the longest part of a successful project is the unglamorous "maintenance" phase. Many programs remain in use long after the paper on which their design was written has been shredded and recycled. To survive and flourish in the maintenance mainstream the software engineers must be prepared to work at any level of the software process: they must be able to extract the design from the source code and extend it to add new features, and must be able to find and correct problems when the program crashes.
The analysis of failures is perhaps the most difficult task, to which the engineer needs to bring as much knowledge, understanding and as many tools as possible. This is not only true of software engineering, but also it is at the heart of other engineering disciplines. By analyzing failures we can discover its causes and then we can re-design our software to avoid the same failure in the future. As Henry Pietrowski says in his book To Engineer is Human - 'Success is foreseeing failure'.
And now back to Eiffel. Eiffel is a high-level language that closes the gap between design and code. Translating an OO design into Eiffel is easy, especially if you used Eiffel as the design language. Surprisingly, Eiffel also provides some relief for the low-level concerns. Automatic garbage collection frees the programmer from tedious and tricky memory management, assertions provide a neat way to catch errors close to the source before they cause serious damage and strict type-checking eliminates an entire class of possible runtime errors. But don't think that with Eiffel you will break free of the low-level problems - garbage collectors can get overworked by a program that creates too many objects, and debugging at the interface of Eiffel and C can at times be a hair-raising experience.
So how are we to interpret Betrand Meyer's comment about C hackers? I think his advice is to beware of individuals who focus on a single phase of the software process and ignore all others. After all, in the same book he also said not to hire any consultants who "leave after analysis and design are complete."
Take care and see you on the net.