Please see the disclaimer.
Expect more items to be added to this post over time, especially in the empty sections.
Have you heard of the term “body of knowledge”? I hadn't until recently.
Even more important: did you know there is a body of knowledge for software engineers? It's acronym is SWEBOK.
I am studying the SWEBOK now, and I think it should be more widely known. However, I also think it is missing a lot of knowledge that is essential to the software engineer of today. In this living post, I would like to keep a list of everything else that a software engineer should know.
Structured Programming Theorem
The SWEBOK talks about what structured programming is, but they omit an important detail: the structured programming theorem. This theorem is crucial because it assures software engineers that anything they can do in unstructured programming can be done in structured programming.
The theorem says this (paraphrased):
A program can compute any computable thing if its parts are combined in only three ways:
- In sequence
- By selecting one or the other.
- Or by repeating one.
Software engineers should know how transistors work and how transistors can be combined to implement math. This video is a good place to start.
They should also know how flip-flops work.
Software engineers should know how memory works. They should know about caches and how they work. They should know that memory is orders of magnitude slower than CPU's and how caches and prefetching improve performance. This paper is a good place to start, even if it is a little dated.
They should also understand how virtual memory works. This post is a good place to start.
Obviously, software engineers should be familiar with math. I personally think that they should be familiar with:
- Basic arithmetic
The SWEBOK mentions that software engineers should know how computers store data in binary. That's good, but not good enough.
Software engineers should be intimately familiar with how numerical bases work. They should know how to convert between bases and how to write numbers in any base.
They should also be familiar with these specific bases:
- Binary (base 2)
- Octal (base 8)
- Decimal (base 10)
- Hexadecimal (base 16)
Because unsigned integers in computers are basically using modular arithmetic, software engineers should know modular arithmetic.
Software engineers should know how floating point arithmetic works. They should be intimately familiar with this document.
The important things to know:
- What creates error
- How to calculate error.
- Other analysis.
Operating a Computer
Software engineers should be familiar with a shell and how to use it. They should know the basic utilities available.
Software engineers should know how to administer a basic system with the following features:
- A webserver.
Software engineers need to know the fundamentals of operating systems.
Software engineers need to have a knowledge of the design principles of Unix. They should be familiar with the continuation of those principles in the BSD's, Linux, and in Plan 9.
In addition to being able to quickly learn any programming language, software engineers should know what language to use when. Basically, they should know the strengths and weaknesses of the languages that they know.
Software engineers should be able to program in at least the languages below because each of them will influence the way they can express themselves in other languages:
Assembly, any kind of assembly, is important to know because it helps software engineers understand how computers really work.
C is important because it's the programming language that is everywhere and can do everything. It is also easily translatable to machine code, which can help software engineers understand how such translation might happen.
Java is important because it is the best example of modern-day bastardized object-oriented programming. (Original OOP comes from Smalltalk.)
Lisp is important for two things:
- Functional programming
Haskell is important as the next step in functional programming, and it is also important because of its laziness.
Python is important for prototyping.
Prolog is the best example of declarative programming.
Smalltalk is important for its ideas in the original form of object-oriented programming, as well as a self-contained programming environment.
Software engineers should be familiar with POSIX and how to read the POSIX standards.
Software engineers should be familiar with Windows and how to read the Windows documentation.
Software engineers should know what makes a good bug report.
Software Engineers should be familiar with unit testing.
Software Engineers should be familiar with integration testing.
Random Number Generators
Software engineers should be familiar with the concepts behind random number generators (RNG's), what kinds to use, and when to use them.
Truly Random RNG
Software engineers should understand how to implement a truly random number generator from truly random data.
A truly random RNG can be used to seed the others.
Cryptographically-Secure Pseudo-Random Number Generators
Software engineers should understand how cryptographically-secure pseudo-random number generators work and when they are necessary.
They should also be aware of what sets a cryptographically-secure PRNG apart from other PRNG's.
CSPRNG's are for data that is used in cryptography and in general use when speed is not a problem.
Seeded Pseudo-Random Number Generators
Software engineers should understand how seeded pseudo-random number generators work and when to use them.
Seeded PRNG's are for when the numbers need to be deterministic (for simulations, rendering, Monte Carlo, etc), speed is a concern, there is a need to reproduce results, or some way of sharing or storing the series of random numbers is needed.
Software engineers should understand entropy and its uses in cybersecurity.
They should also know what good password rules are.
Key Derivation Functions
Software engineers should understand key derivation functions.
Software engineers should be intimately familiar with encryption.
Software engineers should understand the strengths and weaknesses of symmetric encryption and the algorithms used to implement it.
Software engineers should understand the strengths and weaknesses of asymmetric encryption and the algorithms used to implement it.
Software engineers should know how to implement encryption without side channels.
Software engineers should understand how hash functions work and the different types.
Cryptographically-Secure Hash Functions
Software engineers should understand how to pick cryptographically-secure hash functions, how to use them, and when to use them.
Non-Cryptographically-Secure Hash Function
Software engineers should understand how to pick non-cryptographically-secure hash functions, how to use them, and when it is safe to use them.
Software engineers should be able to judge the utility and security of cryptographic protocols.
Software engineers should be familiar with formal methods and how to use an interactive theorem prover to prove properties about software.
Software engineers should be familiar with applicable laws for the software they are developing.