**Please see the disclaimer.**

Expect more items to be added to this post over time, especially in the empty sections.

## Introduction

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.

## Fundamentals

### 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.

### Computer Architecture

Software engineers should be familiar with the differences between the Harvard Architecture and the von Neumann Architecture.

They should also know the difference between RISC and CISC.

#### CPU's

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.

#### Memory

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.

## Math

Obviously, software engineers should be familiar with math. I personally think that they should be familiar with:

- Basic arithmetic
- Algebra
- Geometry
- Statistics
- Calculus

### Numerical Bases

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)

### Modular Arithmetic

Because unsigned integers in computers are basically using modular arithmetic, software engineers should know modular arithmetic.

### Floating Point

Software engineers should know how floating point arithmetic works. They should be intimately familiar with this document.

The important things to know:

- Gotchas
- What creates error
- How to calculate error.
- Comparisons
- Other analysis.

## Operating a Computer

### Shell

Software engineers should be familiar with a shell and how to use it. They should know the basic utilities available.

### System Administration

Software engineers should know how to administer a basic system with the following features:

- A webserver.
- A
`ssh`

daemon.

## Operating Systems

Software engineers need to know the fundamentals of operating systems.

### Unix

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.

## Platforms

### Programming Languages

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

Assembly, any kind of assembly, is important to know because it helps software
engineers understand how computers *really* work.

#### C

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

Java is important because it is the best example of modern-day bastardized object-oriented programming. (Original OOP comes from Smalltalk.)

#### Lisp

Lisp is important for two things:

- Functional programming
- Macros

#### Haskell

Haskell is important as the next step in functional programming, and it is also important because of its laziness.

#### Python

Python is important for prototyping.

#### Prolog

Prolog is the best example of declarative programming.

#### Smalltalk

Smalltalk is important for its ideas in the original form of object-oriented programming, as well as a self-contained programming environment.

### Operating Systems

#### POSIX

Software engineers should be familiar with POSIX and how to read the POSIX standards.

#### Windows

Software engineers should be familiar with Windows and how to read the Windows documentation.

## Development

### Bug Reports

Software engineers should know what makes a good bug report.

### Testing

#### Unit Testing

Software Engineers should be familiar with unit testing.

#### Integration 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.

## Cybersecurity

### Entropy

Software engineers should understand entropy and its uses in cybersecurity.

### Passwords

Software engineers should understand how to manage passwords safely and how not to.

They should also know what good password rules are.

### Key Derivation Functions

Software engineers should understand key derivation functions.

### Encryption

Software engineers should be intimately familiar with encryption.

#### Symmetric Encrytion

Software engineers should understand the strengths and weaknesses of symmetric encryption and the algorithms used to implement it.

#### Assymetric Encryption

Software engineers should understand the strengths and weaknesses of asymmetric encryption and the algorithms used to implement it.

#### Side Channels

Software engineers should know how to implement encryption without side channels.

### Hash Functions

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.

### Cryptographic Protocols

Software engineers should be able to judge the utility and security of cryptographic protocols.

## Formal Methods

Software engineers should be familiar with formal methods and how to use an interactive theorem prover to prove properties about software.

## Laws

Software engineers should be familiar with applicable laws for the software they are developing.