What should people going into “Computer Science” learn in college? I’ve thought about this post for like 10 years, but never wrote it. Might as well get it out of my system.
Mostly I’m impressed with the energy out of new graduates, but observing some things, I think I’m not positive that is directly correlated to what colleges are teaching them. There are also a lot of things in industry that I see people lack experience in, and while it’s not the fault of a college program to teach people things, nor even should it be a requirement that someone have a CS degree, these are things that are most easily fixed if they were addressed at this level.
Well, first off, there is little “Computer Science” in much of anything any of us in the computer industry do. So I think, really, we should just admit that what universities are teaching is “software engineering”. That’s ok. Call it that if it lets you rewrite the curriculum. Even that’s a euphemism though? Should we maybe first admit that too?
Software engineering in the work environment has none of the rigor of an “engineering”, but is a weird mix of an art - where we are not given the time to practice or refine or art (damn you “agile”!!!), and craftsmanship/labor. It’s a skilled trade, much like finished carpentry, plumbing, or dentistry. (Sidenote: I once had a dentist who moonlighted as a plumber). Does this change what we teach also? I think it maybe should.
Often educational programs can be very abstract, or in trying to be less abstract (based on advice from their “industry advisory panel” or whatever), try to unsuccessfully cater to industry in a way that may be worse than not trying at all.
An example of this is software engineering education may emphasize MVP’s and quick prototypes and writing tests over writing maintainable code. This is because velocity and not being a cost center is what some executive cares about, but it’s really the wrong thing for the industry and those companies.
One possible problem is the professors are usually not industry types. Being professors intentionally to escape that corporate grind is valid and I support them for doing it. Yet, all the advisors are probably all out-of-touch big shots, so they are apt to miss the mark in teaching the right lessons for someone about to hop into an industry environment. Would it maybe be better if we tried to not appease industry at all, and did focus only on the Computer Science? Or swing the other action and just teach being a really good at the craft, but don’t split the difference.
I was thinking about marketing things the other day and came to the analogy that many corporate websites are like Potemkin villages — they are based on the idea of what people working for companies think web content should look like.
Now, universities aren’t trying to be fake villages, but when they are so far removed from practice, they can often slide close to this line. They are teaching for something they haven’t really felt. They teach people sometimes misguided things about “MVP” and agile or microservices with lots of fervor and miss the brass tacks and nuance - possibly even contributing to the trend. Software engineering classes can try to teach the project management and maintenance of a large application, but it is going to be a simulation no matter what happens. So my theory is maybe they shouldn’t try. Instead teach how to program so that maintenance isn’t a concern.
Don’t teach agile project management because if you do, you are perpetuating one of the worst parts of the industry that shouldn’t have ever happened.
Many are trying now to expose people to Software Engineering practices like CI/CD systems, and that’s fine, I guess, but I’d prefer they learn to design software first, as the latter tools will change tomorrow. This is something everybody can teach, and it will be a valuable lesson, even if the program is just a made up problem. Yet if we divert from focus, we spend time on breadth and what we may need is an appreciation for depth - being really good at just the basics.
This is the reason I’m writing this - Is Software Engineering as an industry losing an appreciation for good design and architecture? It kind of feels like it. Today’s architecture is often just a bunch of loosely connected services and some architect has a job where he is the architect because he knows where the bodies are buried. This is not design.
Our colleges are our first line of defense because it is where we teach people how to think about software, and indeed, design. But maybe they aren’t teaching the right lessons?
While I’m arguing against teaching all aspects of software development as currently practiced - because they can’t - I do think we need to expose people to software development in context - in user context and in business context.
What if we could teach people the right cross functional business lessons - because, I think, really to work better as companies, we do have to work people in different departments. If there was any successful thing I did, I think it was mostly trying to be a generalist. So maybe we need more of that? Exposure to the whole slice of the software industry, not just development? Encourage people to also be able to fulfill different roles, because this makes people not look at engineers as “code monkeys” but also makes the world better, because we *do* have skills that are useful when applied in other problem domains. And we do want to start businesses sometimes.
What follows is my list of what I think it would be great if people took away from their learning experience - or if colleges emphasized.
For what it’s worth, I do support the idea of much more focused bootcamps as an alternative - and think computer science could work really well as possibly a 2 year technical school program. We just need industry to step up and recognize this - for those that already do, thank you. There’s so much filler in a 4 year B.S. degree and that makes things really expensive.
Maybe that theory is terrible, I don’t know, but here’s my list.
How To Use Even More Programming Languages / Paradigms
Every different paradigm you are exposed to changes you.
Just like there many be many more words for “ice” in certain languages where people live in frozen climates, exposure to different ways of working encourages you will have different ways of thinking.
You may have a language you learn, but learning what you hate makes you a better designer. I personally hate about every programming language for different reasons at this point, but that’s a different post.
Object oriented systems are exceptionally powerful when you build the right abstractions - methods should mostly take objects and return objects, not a slew of random parameters. There’s a really nice Zen spot I’ve found when you can mix functional and object-oriented styles in the same program, things that are *mostly* side effect free, methods that accept first-order functions, and so on. What is a declarative vs imperative API? What is statelessness? These are lessons often learned from functional programming.
Except if you just focus on FP, you’ll be in with a bunch of zealots that hate OO, and that’s the wrong lesson too. Blending martial arts styles is the Bruce Lee-esque way to do it.
A lot of languages people will be exposed to later, but I worry about programs that only expose people to mostly Java, Javascript, and Python and accepting of code by massive addition without belief in aesthetics. These languages don’t really encourage any sort of style by themselves.
In the current state of things, we produce a lot of people pretty good with Java, the language of mediocrity - and while I love Python, it’s possible to write some pretty bad Python, because Python makes it really easy to write lines of code. Some of the code put out by “data science” folks is absolutely terrible, and we need to make sure we are not growing that trend.
My theory is he codeth best who hateth computers the most. And that comes with exposure of seeing all the good things, so you can see when languages are missing the good things, and what you have to do to compensate.
Another fork stuck in the road. What do you learn? Both things?
It's not a question, but a lesson learned in time.
Sorry, that’s a Green Day song. Carry on.
How To Write Maintainable Methods - For Other People
This is just an observation, but I think there was an emphasis in writing really tight code 20 years ago that is possibly gone if I judge this by a lot of programs today.
We believe that because we write a bunch of bad microservices and can therefore avoid code-review that code quality doesn’t matter? Is that what happened to everyone?
Good methods don’t need to be three lines long, they can be 5 or 10 or 15, but good methods require a bare minimum of comments - usually just a single line, and the logic doesn’t take any mental effort to think about. They shouldn’t be indented a whole lot. They should make liberal use of helper functions and the right methods should be in the right classes.
A “util/” namespace is the sign of something that wasn’t designed very well, and it should not keep growing.
I see a lot of people who can’t name variable names decently and don’t handle edge cases, or even follow good error handling practices, which is going to rub off in how they are perceived by their peers.
Good design is an early way you can get ahead, and I believe we should teach people skills that help them stand out in their early years on the job.
How To Design A Good Public Local & Web Service API
A good public API is immediately understandable and evolves in non-breaking ways without losing consistency.
Almost no one builds them well.
Designing a good API is the best way to be perceived as being awesome by an external group, if you aren’t doing a user interface. It’s what people see and use.
How To Design Distributed Software
No software today just runs on one node, but we tend to teach people to develop software for toy implementations and don’t really teach about horizontal scaling and what that requires in building an application, and what that application would look like in production.
Folks think they can use the development web server in production or that “npm” is the way you run a “webserver” to host web content, but you shouldn’t.
Folks should be exposed to patterns for software being run in the real world, but not especially in ways that are teaching particular vendor tools or ecosystems.
How To Make A Good Database Design
A good database design is consistent, not denormalized, and all queries are indexed. It’s not “done” if the queries are not going to scale once you actually get users.
Teach people how to design systems that can handle load.
How To Design A Good Scalable Interface
I see a lot of projects developed that very clearly won’t work when they have 10,000 objects added to them.
We should require even the most basic of prototypes to handle pagination and plan for scale, so it becomes second nature.
Just reminding people to think about this would be a start.
How To Write A Tutorial
So many projects can barely explain how to install themselves and how they are used.
These projects (and sometimes startups) are often doomed to fail.
We often look at communication in that same Potempkin village mode, where we do things because we are copying the look of how something else does something, but we need to develop empathy for the user, how they learn, what questions they need answers to, and what is going to make them understand something.
Ideas without communication are not successful.
I don’t think people understand that communication is something with purpose, not words to fill a page or check off a requirement.
How To Communicate A Design
Basically very few projects today can include a design diagram of what they talk to, what the inputs and outputs are. What does a system require to run, and where can it run?
I feel nobody ever gets taught this, and there are increasingly fewer and fewer examples.
I’m not talking UML, just basic stuff. This should be a habit.
Lots of people need diagrams to learn, and tech is getting harder and harder to understand when our communication skills continue to lag behind.
How To Write
I know my college tech-writing course back in the day was a total joke compared to high school.
While I disagreed with his stylistic preferences, I was lucky enough to have an absolutely draconian English teacher in high school that did teach me to write, and I became better for it. Most people don’t get that opportunity.
(Apologies if you think this blog sucks and isn’t a great example, editing takes 3x longer than writing and I’m not going to spend 4 hours a day on it).
As much as we teach people to chase startups, people are going to have a very rough time if they can’t learn to be persuasive and put themselves in the minds of their reader who is reading about a project.
How To Test And What Not To Test
Everybody learned the wrong lessons from TDD.
Unit tests and mock tests are often useless and can actually impair refactoring by reinforcing and solidifying the wrong parts of the code.
Having a coverage standard of something like 90% is not useful, because it is the error path that you must test the absolute most.
Find ways to get full coverage off of functional real-world tests where you can, and make sure you are at least manually covering all the other areas.
Know that the error path is the path that is most likely to still have errors in it.
If you are short on time, test for all the invalid security conditions and errors rather than what you would normally do when demoing the good parts to make sure they still work.
How To Write A Good Bug Report
This is super minor, but how much time do we waste on things when there’s no steps to reproduce a problem? It would be nice to head this off at the pass.
Product Management
All software would be better if everyone had a better understanding of the needs of a customer and a business. Much software we build and focus on can’t be percieved, we build the wrong things, we waste time with the wrong ideas. We don’t know how to make something polished or compelling.
I know a lot of people want to chase “entrepreurship” because the premise of having their own business at 22 or something is a compelling story (if rare) - but developing engineers into being more well rounded is the place to start.
Frontend and Graphic Design + Art
I see a lot of people building interfaces that look terrible, even coming out of “HCI” programs. Everyone would benefit form a better understanding of aesthethics and probably would appreciate the cross-functional breather.
Also, how to design some wireframes and test them before designing user interfaces that are potentially not great at solving the problem.
Business
Similar to the above, I would have appreciated (but didn’t know I needed it) a better understanding of most business concepts as they relate to software companies.
How is a large business run and structured? How does sales even work? What are the responsibilities of operations and finance personnel?
Again, we don’t want to teach entrepreneurship hustle, we want people to be aware of all the hats they need to know how to wear so they can be prepared for when they are ready.
What Not To Teach
I like the idea of people having room for electives but a lot of mine were a wash - I do like the idea of things that open up worldviews and make you think differently of course.
In terms of required courses? Math. I found every single math course useless except for discrete math - where it was pretty valuable for the idea of critical thinking, so much so that I think it would be the ideal math course for everyone to be forced to take across an entire college campus.
Computer science isn’t about Math. From Calculus I did develop an appreciation for the idea of things being continuous, but my high school Calculus teacher was better than my college ones. Let’s use that time for something else.
Finishing Up
That was kind of long. Those are just some random thoughts about things that I think it would be useful if people learned coming out of school.
Will education change? No idea!
Take them or leave them.