What every engineer needs to know
You might have seen the article Computer Science Education: Where are the Software Engineers of Tomorrow? written by two professors emeritus of computer science at New York University in which they cast dispersions at their own university and others for various atrocities such as removing mathematic prerequisites and not teaching languages such as C, C++, Lisp, and ADA. Their abstract states:
It is our view that Computer Science (CS) education is neglecting basic skills, in particular in the areas of programming and formal methods. We consider that the general adoption of Java as a first programming language is in part responsible for this decline.
Jeff Atwood from Coding Horror recently posted a similar blog about how we should teach CS. Now we love a good lambasting of the younger generation who’ve had it so easy and blah, blah, blah…but what we find more interesting is the question of what basic skills a solid software engineer should have, regardless of when they matriculated into the venerated halls of our fine universities? So here is our list of topics (and the reasons for them) with which an engineer should have some level of proficiency.
1. Algorithms – Engineers should know the concept of asymptotic notation (Big-O) and that it is used to describe upper, lower, and tight bounds for algorithms and how their growth can be constant, linear, logarithmic, etc. The reason is clearest in the needs of Software as a Service (SaaS) businesses on the internet. Much of our practice is dedicated to helping companies understand how to scale their product and technology. Often one of the first things we find is that no one is paying attention to the way in which work is being performed by the system and no one has first looked at whether there are more efficient ways of performing this work.
2. Object Oriented Programming – Engineers should know the fundamentals of inheritance, encapsulation, abstraction, and polymorphism and how these are implemented or not in their particular language of choice. While procedural programming is still useful and in use, in order to be a good engineer you need to understand the different programming paradigms and theories in order to weigh the tradeoffs of each and understand how decisions impact performance, scalability, and security.
3. Language – It’s not enough that an engineer knows the language they use every day. A language is a tool, and just as a carpenter would not consider sawing a board with a hammer, neither should an engineer assume that one language is appropriate for each possible need. With respect to the language they use most often, they should know they following:
a. Syntax – They should be able to write a simple method without syntax errors. The more correctly that an engineer can do this the first time; the faster, and more efficiently he/she will produce code.
b. Data Structures – Engineers need to understand the common data structures such as arrays, vectors, linked lists, hashtables, map, etc. An understanding of data structures also means understanding the performance implications of each of them and knowing when one is better to use over another, etc. To the extent that you are using data structures that are already implemented within your language, be careful that you understand the performance implications of the implementation.
c. Types – They should know if the language is strong/weak and static/dynamic typed.
4. Design Patterns – Engineers should know about these and at least a couple of the more common ones such as factory and bridge. Extra points for knowledge of anti-patterns. The reason should be obvious, don’t reinvent the wheel and don’t invent the square wheel either.
5. Software Development Life Cycle – Engineers should at least know the difference between Waterfall and Iterative lifecycles and be able to argue for the appropriate uses of each. Be careful of engineers (or be careful of yourself!) if you think that there is one lifecycle that best fits the need of every company and/or every project. Lifecycles, like languages, are tools with specific purposes.
6. Source Code Control – Engineers should believe in the concept and practice it with knowledge of at least one platform. All too often this topic is skipped in college and learned “on the job”. But more and more often companies are struggling with how to perform massive parallel development and a basic understanding of the tools that enable this activity is key to being successful as an engineer.
7. Compiler and/or Interpreter Understanding – In saying this we are also implying that an engineer should have an understanding of the debugger and that they be able to read and step through the compiler output (assembly equivalent) in the debugger. What separates an engineer from a technician in most disciplines is an understanding of “why things work” rather than just “how things work”. It’s why engineers have bachelors and/or graduate degrees while technicians typically attend 2 year (or less) colleges. Understanding how something gets changed from code into something easily understood by a computer is very useful in understanding how to debug what you’ve written when you have a problem. Understand how the compiler and/or interpreter works and you will likely produce better, more efficient code.
Let us know what you think every engineer should know.