I was recently matched to a question on Quora that asked:

“What are the fundamentals of software engineering?”

A short question, to be sure, but one which is so packed with complexity. Are they asking about skills? Engineering? Courses? Concepts that are as immutable as laws? Things which no one can argue against?

Hard to say.

My bent is more naturally towards the philosophical than the purely pragmatic in these discussions, fair warning.

How you approach a problem or opportunity determines how the solution will end up.

One of the key aspects of software engineering is the ability to investigate with curiousity the shape and space of the problem, to understand it’s parts, and be able to assemble them into something useful and valuable.

This applies not only to the actual software, but to the entire system of conception, invention, implementation, deployment, and maintenance. It looks at not only how is this particular feature going to be broken down into objects, functions, procedures, or what-have-you, but how are those parts going to be verified, validated, and assembled, but how the people that are working on these various parts and assemblies going to work together.

So one fundamental of Software Engineering is:

Being able to see the whole as well as the parts, how they come apart and fit back together.

One needs to learn how to do this, of course, as most people aren’t born with this ability. Some people acquire it earlier than others, some may never acquire it, but it is something which can be taught and learned.

But how?

Civil Engineering is arguably the first type of engineering humans developed. Learning to make bridges that spanned rivers, chasms, and generally eased commerce has been a part of human civilization for millennia.

But how did it start? Primarily, because bridges fell down. Tossing a couple of logs across the stream eventually was good enough, but if you wanted something to last longer than the next flood, you needed to figure out ways to keep such things from washing away or falling down and killing people in the process.

So the early engineers learned to study failure, and learn why the things we construct break and fall apart. A software engineer must do the same thing in order to understand how to build better software. It’s not quite enough to just study failure, of course; one also needs to understand successful projects.

In this, we study best when we study together, which is one reason the Open Source movement has been a real benefit to learning software engineering. Even in proprietary development, though, sharing code with colleagues through peer reviews, pairing, and study is very beneficial.

So another fundamental of Software Engineering is:

A deep sense of curiosity about the internals of software and project that work and that fail, and understanding what makes something good and what will cause future problems.

I mentioned the notion of “Laws”, or Fundamental Concepts of Software Engineering.

There are some that approach this sort of immutability but none with such fastness as the Law of Gravity.

I’ll just list some of them off, there’s more than adequate information about these out there, and different people have their favourites.

  • Don’t Repeat Yourself
  • Principle of Least Astonishment
  • Principle of Least Knowledge
  • Make it work, then make it pretty, then make it fast.

Understand principles about what makes a good software architecture.

Shifting a bit, I’m now going to talk more technically and pragmatically, and these will be a bit more directed.

  • Don’t learn a syntax, learn a language or framwork’s idioms, practices, the problem spaces it works best in, those it doesn’t

  • Don’t learn a single language or framework. In Pragmatic Programmer, they urge you to learn a new language every year. The thing is don’t just learn a language of the same kind, learn one that has different ways to solve problems. If you’re using an imperative language such as C, learn Lisp or Smalltalk. If you primarily script in Perl, learn Ruby and Python. Learning is never wasted.

  • Work both with exercises (kata) and with real problems. There is nothing really more satisfying than solving one of your own problems, and these are the ideal vehicles to apply learning to.

  • If you encounter some piece of a project that you don’t know how to implement, or an area that you need more skill in, break out into a small example and practice that until you understand it.

Another principle of Software Engineering is:

Be constantly practicing and learning your craft.

I sure hope other people come up with other thoughts and ideas. Best of luck.