I recently had a discussion with some friends about CS degrees and becoming a software developer. I have strong opinions on what makes a good software engineer, but haven't spent a lot of time thinking about how people get there. This blog post will be an attempt at coming up a cirriculum of sorts to become a good junior software developer.
I think most people agree that the first step to becoming a developer is having an introductory grasp of writing a simple programs and solving simple problems. Basic knowledge of strings, loops, parameters, variables, methods, objects, classes and the understanding that a computer will only do one statement at a time are what I think people need to get out of an introduction to CS.
I'm borrowing heavily from my time at IIT with this course as I think it was one of the courses that shaped me the most. This course should focus on the basic data structures: arrays, singly and doubly linked lists, trees, and hash maps. In it students learn which are better for which sorts of operations (an intro to big O notation), how to write some of the data structures themsleves, and an intro to TDD.
"An intro to TDD," you might ask. "Why an introduction to TDD?" Well for one it's how I learned (ha!), but more importantly it's the most sensible place to start teaching TDD. Each operation on a data structure is easily unit testable and if everyone is working from the same interface you can test your students' code and test your students' unit tests.
I'm still deeply thankful for the way this course was taught to me. Professor Beckman, if by some chance you read this, thanks a lot. Hopefully this bit makes up for how I describe Haskell later on.
Logic aka Discrete Math
I can't remember much of discrete, but what I can remember is a focus on logic and a (poor) introduction to recurrance relations. Looking back over the syllabus it seems like it was treated as an intro to algorithms and logical thinking for computer science.
The big takeaways from this are logic: boolean, induction, recursion, and some basic proofs and recurrance relations: being able to come up with a rough big O for a set of operations. Other bits and bobs like intro to probability, graphs, sets, and trees are also important but might be better covered with algorithms, or when going more in depth with them.
Algorithms is a tricky subject. They are the basis of solving, or providing a best guess to a problem. The course should teach a deeper understanding of big O notation, greedy algorithms, amortization, graph problems, NP and NP-complete, and solved problems like red-black trees and quicksort.
This course should cement understanding that a computer can only do one thing at a time. It sounds like a simple concept, but given someone a deck of cards and ask them to sort it they'll look at all the cards at once to sort them. This class should hammer home the limitations of computers so that students can write efficient software around those limitations.
The title is misleading at first glance, but Funcitonal, Parsers, and Compilation is a bit of a mouthful. Once you have Programming 101 under your belt picking up new similar languages should be fairly straightforward. You might not be able to call yourself an expert for a new language quickly, but you should be able to pick up the basics rapidly.
No matter how much I disliked it, I think having to learn Haskell really opened my eyes to how weird a language can be, and how that weirdness can make it much better at certain things than other languages. Haskell's forced strong type safety and functional style is an eye opener coming from other more common languages.
I think learning lambda calculus isn't required to write good funcitonal code, but it is an interesting subject and maybe a primer on it before introducing a functional language is a good thing.
Low Level Systems
I took a few courses in lower level systems programming and while I think it's an important concept I don't think 3 courses are needed to cover what backend developers need to do their job well.
What developers need is an understanding of basic operating system principles: malloc, syscalls, the kernel, forking, and process reaping, processor pinciples: registers, assembly instructions, and cache hits vs misses, and if not covered yet C style programming with pointer manipulation.
Having a basic understanding of SQL schema design, avoiding data duplication, and a primer on CAP theorem is important for most developers. I don't think going deep in the weeds on the different sorts of normal forms is important, but knowing how to design a database schema with foreign keys, join tables, etc is a skill that's required often enough to be important.
An introduction to NoSQL databases and their pros and cons versus a SQL database would be good to include here as well. There's the old joke of "MongoDB is web scale", and while I have nothing against Mongo, I think there's a kernel of truth in it. Choose the right database for the job. Writing to /dev/null is fast, but you're going to want to read that data at some point. Choose a database that fits not only your data pattern, but also your read, write, and transactional needs.
At IIT this was sort of a blow off or easy work course, and while it was annoying when I was taking it, I think that at least some discussion around ethics in software development is important for developers.
For this I'd suggest talking about current events and past moral quandaries like encryption, copyright, patents and DRM. Reading science fiction, or at least near future fiction that raises questions around AI and other potential future technology is useful for figuring out your personal stance on ethics.
Real World Development
This class is one of the harder ones to pin a syllabus to because it should show students that there are concerns beyond the toy programming of academia: testing, operation, security, debugging, product management, software longevity, dependencies, libraries, etc. Giving students the skills outside of theory is sometimes missed by degree programs.
I think what might be the best way to teach these things is to assign a project and partway through the semester ask for a new slightly orthogonal feature to be added to that project. It's the one way I can think of to reinforce good coding practices.
Another suggestion would be to read Clean Code by (uncle) Bob Martin. Most of his critiques are focused on Java code, but I think it's a very helpful book in encouraging concise, well written code. It's probably the only book from college that I recommend reading.
Apart from all of the basics of development I think it's important to find an area where maybe you don't excel, but that you find interesting and can take a deeper dive into. For me that was information retrieval aka search. I had a great professor for it and was able to do some academic research for him.
I've heard the phrase "T shaped developer" before, meaning someone who has many skills at a basic level and a few skills at a much deeper level. I think coming out of school a student can and should be "T shaped". If you can find something you're passionate in, you'll enjoy your development career that much more.
I've been enjoying trying to put words to concepts and opinions I can't easily describe. I'm not an educator, or even a senior software engineer, but I take pride in my skills and I think (and hope) a lot of the above is applicable to all software developers.
I think a lot of discussion on the internet these days is people shouting past each other, but if you'd like to comment on something you agree or disagree with, my twitter is in the sidebar. Hopefully this made you think about what makes a good software developer and how to get there.