I spent three years as a wellness and medicine major in college. Through a long and complicated series of events and realizations, I grew interested in computer science and, subsequently, software engineering. So, I decided to transfer schools and enter a Software Engineering undergraduate program.
I spent less than two months in that program.
It wasn’t because I was non-committal. On the contrary, I have a knack for becoming obsessed and consumed by a goal. Consumed by curiosity and obsession, I easily and accidentally forget about social and day-to-day responsibilities as I dive deep into learning a particular subject.
To some people, obsession-with-learning may sound incompatible with the characteristics usually ascribed to a “college drop-out” (a title I wear proudly).
But it actually makes perfect sense. My classes weren’t giving me enough material, nor were they giving me the right kind of material. They were progressing at a snail’s pace and many of my questions were left unanswered (even after I approached professors personally). I was tired of copying programs written on the chalk board. I was tired of hearing about the “object oriented paradigm” without seeing what this “mystical” object-orientation was all about. I was tired of learning at a superficial level.
I remember walking to the library after one of my classes and picking out a Java book. I spent the entire afternoon and evening reading and experimenting. I learned more in that evening than in the entire month and a half I had been enrolled. So, what was I paying for? I was paying for pedigree. I couldn’t allow myself to stay enrolled in this program because I was spending too much time in the classroom and too little time learning.
I don’t think it was a fault of the curriculum, but a fault of classroom based education in general. For multiple reasons, classroom based education does not seem to optimize for competency. All pedagogical qualms aside, though, there was one further issue I often had with classroom-based learning: it was awfully boring. There were times when the pace was too fast and superficial and other times when the pace was so incredibly slow. Even if the course content was deep, the training was not.
In general, I found classroom based education insufficient at pushing students towards that final step: going from knowledge of the material to actionable understanding. By “actionable understanding”, I mean the ability to apply knowledge to new contexts in potentially novel ways. Do you really understand a concept if you can’t recognize its presence in contexts other than the one in which you learned? It’s like claiming to know derivatives because you’re able to take the derivative of a function (which is just a mechanical operation), without being able to recognize when it’s applicable, why it’s important, or what it actually means. Calculators can perform the mechanical operation for us. Calculators (at present) cannot see a problem and use an intuitive understanding to deduce the correct approach. They can only perform the operations they are instructed to perform. Shouldn’t we aim to understand concepts more deeply than an unintellectual calculator “understands” derivatives? I think so. Classroom based education seems to disagree.
When I’m solving problems, learning something new, or forming connections between concepts, I like to pace back and forth, scribble in notebooks, and even explain ideas to myself out loud. I like to poke at my mental model(s) from many different angles until I find a hole that I need to patch. Further, I like to continuously revisit old subjects once they’ve faded, circling back to see the subjects anew, allowing for the opportunity to make connections I previously missed and to re-test my understanding.
So, I dropped out and embarked on a journey of non-traditional education. At first, I was learning in a completely self-directed fashion. During this initial phase, I was dedicating the majority of my energy to the (not so simple) project of coming up with a solid learning plan. I knew I needed to learn from first principles, but sorting through the overwhelming myriad of resources took so much effort and time that my learning was progressing slowly. I knew I was motivated, able to absorb information and synthesize it, and rigorously interrogate my own mental models — all traits of effective self-learners. What I was not as proficient at was sticking to my self-procured learning path because I would always think it was insufficient: I was no expert in the field, so what qualified me to design an effective curriculum for myself? I was not an authoritative source of information about what a software engineer should know. I needed some direction to get me started… Preferably from an expert.
Comparison of Learning Resources
I set out to find non-traditional, external sources of education that could provide more direction than I could on my own.
The first non-traditional resource I identified was the MOOC ecosystem. After sifting through countless options, I realized that MOOCs presented a similar problem to the one I had before: there were MOOCs on just about every subject. Further, they differed in quality, depth, pedagogy, and time constraints, meaning I had a lot of other factors to filter for if I was to rely on MOOCs as a primary source of learning.
Just as before, I needed to sift through many of them and decide on which courses to enroll in, the most sensible order of said courses, and, by virtue of that, which topics were fundamental and which were “elective”. MOOCs were not an ideal source so I abandoned them for the time being and sought elsewhere.
I liked the idea of bootcamps because the idea of intensive study appealed to me. I thrive under pressure and I loved the idea of being pushed to my cognitive limit… and coming out successful. As I explored the myriad of bootcamps, I noticed that they all brought with them two fatal flaws:
- The time constraint seemed too extreme and therefore precluded the ability to iteratively test and review one’s understanding of the subjects. There was no opportunity for circular learning.
- The topics were not taught to depth. Even the best bootcamps out there grossly under-prepare their students’ knowledge of fundamentals.
In other words, I saw bootcamps as a way to produce users rather than developers. Users of what? Of frameworks and high-level development tools. I didn’t want to be confined to a specific toolset, or some parochial set of development principles based on software fads, without being strongly rooted in fundamental/foundational knowledge and training. Of course, there are always exceptions to the rule, and I’ve caught wind of some pretty strong bootcamp graduates (I’ve even met a couple).
Bootcamps seemed to be more successful for students who already had a technical background and merely wanted to get up to speed on a particular specialty, such as web app development or mobile development.
I also came across multiple curricula directed created by- and targeted for- self-learners. Different “Self-designed <CS/Software Engineering/Data Science/AI> Masters Degree” articles and gists were popping up regularly on Reddit and Medium. I looked at many of these. I also looked at the teachyourselfcs curriculum, the content of which was actually pretty solid.
The main problem with these was not the quality of content(there were actually some well-rounded, sensible curricula out there), but that pure self-study, I came to realize, is more effective after one has established themselves as an adept, with a strong foundation of fundamental knowledge and training. This is because self-study lacks a crucial component for newcomers: feedback.
Feedback (from those qualified to provide it) is the most powerful form of self-improvement (assuming you follow it). Newcomers to a particular field do not know how to identify quality work or information. They do not know how to recognize anti-patterns in their own practice. They do not know how to explicate the subtleties in projects (especially larger ones) and they do not know how to hold themselves accountable to certain standards because they don’t know what those standards are (or, if they do know what those standards are in theory, they do not know how to recognize them in practice).
At some point I stumbled upon the enigma that is Launch School. I remember navigating to their “Is this for me?” page, which explained what Launch School was not before saying anything about what Launch School (LS) was. In essence, it was not a place for people who were still exploring their options, nor a place for people who wanted a job quickly. In fact, LS prides themselves on their “slow path” for learning.
They valued depth, mastery, circular learning, and perseverance. They were the opposite of the “quick and easy” path.
Their pedagogy was exactly what I was looking for. They called it “Mastery Based Learning”, which is a learning model that measures progress by competency rather than time. You cannot move onto the next course until you’ve proven that you have mastered the material in the current course.
They measure mastery with a combination of assessments, interviews, and projects. It is typical to encounter a 3–4 hour written assessment filled with questions asking test-takers to explain concepts with linguistic precision. Their study guides explain what they mean by “precision” and the instructors, or TAs, who grade the assessments will make students correct their answers if any language is ambiguous or overcomplicated. There is no way for students to fake their understanding of the material because the level that students are required to explain concepts prevents any hand-wavy or unclear answers.
If students get anything less than a perfect score, they are required to go back and correct their answers. If they get less than a B, they receive a “not-yet” and have to retake the assessment after at least a week of further study. Another “not-yet” means another two weeks of study, and so on.
The written assessment is only the first part of an evaluation of mastery. Assessments tend to have projects and/or interview components as well. During projects, students are given a set of technical specifications and a time limit (usually 24 to 48 hours) to develop an application that meets those specifications. The code quality, structure, and design decisions are rigorously scrutinized and graded by an instructor, at which point the grader provides the student with ample feedback. During interviews, students will solve problems in front of the interviewer, similar to the way coding challenges are performed during job interviews. An interview may also require a student to present on the design decisions they made during development of their application. Launch School’s rigorous assessments test students’ communication skills, planning, precision, and code quality from multiple angles.
Instructors and TAs are available pretty much around the clock to answer questions. They also do a myriad of code reviews for the large number of programming assignments throughout the curriculum (remember: feedback is crucial for mastery).
Making it through the core curriculum took me a few thousand hours of study. I then moved onto their optional, admissions-based capstone program, where I learned optimization, algorithmic analysis and design, and systems design. I also built a project that showcased thoughtfulness, research, the ability to manage complexity, and depth of engineering.
The Capstone Program, in all, took about another thousand hours. I presented my work at multiple events in New York City, which generated enough interest from other engineers looking to make referrals that I actually had to start turning down opportunities for interviews. I had offers, interviews, and the freedom to choose where I wanted to work within two weeks of sending out my first job application. I didn’t pursue any entry-level positions, nor any positions offering less than 100K starting salary.
I loved my experience at LS because I was finally able to embrace my knack for falling down rabbit holes. I could inquire a subject to death in a truly Socratic fashion.
I used other sources for learning as well, supplemental to the LS curriculum. Math was a subject I had virtually no formal training in and it was a subject I valued for its importance and its intellectual pleasure. Here were the primary resources I used:
- How to Prove It
- Discrete Math for Computer Science
- Linear Algebra
- Set Theory (A Book of Abstract Algebra by the same author is also a great read but not necessary)
- Calculus Vol 1 by Apostol
I also studied architecture and design a bit on my own as well, using the following primary resources, among other, less important ones:
- Practical Object Oriented Design in Ruby (applicable to OO languages in general)
- Web Application Architecture
- Designing Data-Intensive Applications (this book is particularly incredible)
- Web Application Security: A Beginner’s Guide
The Importance of Fundamentals
A common complaint about software “engineers” from non traditional backgrounds is that they know how to code but are lacking in the “engineering” aspect. Another way of saying this is: they lack the fundamentals that students tend to be exposed to in more traditional education curricula (such as those seen in universities).
It’s easy for self-taught developers, as well as those who go through non-traditional education programs, to miss out on learning the fundamentals, as well as remain unaware that they were ever lacking a core set of knowledge in the first place. Programs that focus too much on practicality sacrifice producing developers with strong mental models. The problem with this is that a strong mental model built on theoretical understanding is actually a practical asset, as it enables developers to use those mental models to contextualize new information and solve new problems. Mental models are like compasses, assisting the developer in navigating new technological territory.
Traditional education curricula tend to focus more time on theory. Due to this, they sometimes make the mistake of going so in depth on theory that they sacrifice practical training. Non-traditional education curricula tend to do the opposite: they tend to make the mistake of going so in depth on practice that they sacrifice theoretical training. In either case, the student is left ill-prepared: confined by their knowledge rather than empowered by understanding. This is due to the false dichotomy of theory vs practice. Without practice, students have no idea how to apply the theories they’ve encountered. Without theory, students have no idea how to fit new information into their current model of “how it all works”, thereby preventing them from effectively assimilating new knowledge into genuine understanding.
Practice without theory confines the developer to the technology they were initially trained on (the applicable term here is “framework user” as opposed to “software engineer”) and theory without practice produces students who will have no clue where to start when they’re handed their first feature spec.
Strong mental models require the fusion of practice and theory. It is not possible to learn everything you will need to know as a software developer prior to landing your first software developer role. There is always more to learn. Therefore, the best course of action is to establish a strong foundational understanding that will allow you to quickly assimilate new information and adapt to the ever-changing industry.
There are hidden exceptions in both the world of traditional and non-traditional education. Launch School is a non-traditional program but emphasizes the importance of mental models, foundational understanding, and learning “things that don’t change”. Although the software industry rapidly changes, the fundamentals do not. It is common for graduates to be hired for roles that use technology they have never-before encountered.
Western Governor’s University is an exception to the standard education model found at most colleges. I only recently heard about this school and I’m impressed with the fact that they’ve adopted what they call a “competency based education” approach to learning. At WGU, students are required to prove sufficient skill in a particular course prior to progressing to the next topic. There is no time limit on courses: students take as long or short a time as necessary to gain competency in whichever subject they happen to be studying.
The source of a developer’s training is irrelevant. Whether it be traditional, non-traditional, or whether they are entirely self-taught, the most important aspect to consider is: have they mastered the fundamentals?
As an LS Core my present position as a Software Engineer II, I work closely with some really skilled engineers and directors. With a strong grasp of fundamentals and practices, I feel well-prepared to tackle the complex challenges that my career throws at me. What I particularly love about my current position is that some of the challenges we face are not ones that can be searched for on places like StackOverflow because we’re solving them now for the first time in recorded history.
I hope to see a mastery-based learning pedagogy grow more mainstream, as it prevents people from “C” or “D”-ing through courses without a grasp of the core concepts.