Ask HN: What are some rite-of-passage style projects for programmers?
Hi,
I'm trying to compile a list of projects, algorithms and maybe data structures that I feel every well-rounded programmer should have implemented at least once in their career. I'm hoping this list can then function as a guide for programmers to challenge themselves and maybe fill gaps in their knowledge they didn't know they had. So far, I've come up with the following list:
* Data structures - Linked list - Hash map - Several types of trees
* Algorithms - The common sorting algorithms - Dijkstra - Graph-traversal algorithms
* Projects - Ray tracer - Parser/Interpreter - Compiler - Virtual Machine - Small kernel - Neural Network - Web server
The algorithm and data structures section I believe should be covered by any decent computer science education (but may be useful to self-taught programmers). The projects are slightly more advanced and may take up to several weeks to implement completely. I realize this list is far from complete, so that's why I'm turning to you: do you have any projects that you've worked on that turned out to be very educational and made you a better programmer once you completed it?
98 comments
[ 2.8 ms ] story [ 151 ms ] threadSome kind of game.
Edit: Something that uses an API.
I would actively discourage developers from writing their own encryption software, in case they're tempted to use their work in a production app. Encryption is sufficiently complicated that you will get it wrong, and sufficiently important that getting it wrong will be very bad. Leave encryption to cryptographers.
That would be bad, so maybe an obfuscator instead?
For most types of problems, the feedback is clear - if it works and gives you the expected result, then it's (at least mostly) correct. For implementing cryptographic systems, a passing test suite doesn't mean anything, you'd need extensive expert review to tell you where you went totally wrong, and without it you'd just likely learn untrue things.
I prefer this to the more common 'Just don't do it', as you actually state why. The reason is something I knew intuitively but couldn't really (And had actually never devoted any time to) put[ting] it into words. Thank you.
Maybe in the 90s, I might have actually built a linked list in C for whatever reason, and I guess you could define graph traversal to include walking a tree pulled out of a database. But the rest are things that The Universe Provides For You(tm), which one would only ever reproduce in School, a Job Interview, or a Poorly Chosen Hobby.
As to actual rites of passage? Ship Something that real people actually use. Build an entire thing, be it a piece of desktop software, video game, web application, mobile app, etc. from bottom to top and send it out in to the world fully formed. That, in my mind, is what we're here for.
Also, these projects are intended for self-study. Building an entire product from top to bottom is indeed a very valuable skill, but hopefully one you learn on the job.
(I have personally done a toy HTTP server, small compiler, neural network, etc. and will be forever grateful I did so)
You write this, but then you go on to mention job interviews, which are becoming more and more algorithmic each passing year. Software engineers are frequently asked to write these during interviews. If you've missed the experience of being asked to implement a hash table or linked list in an interview, or at the very least asked to write a function somehow manipulating some data structure, you've either been lucky or else stayed in the same job for a long time (not a bad thing, but not typical).
I highly recommend all software developers practice implementing data structures (linked lists, hash tables, trees, graphs) and algorithms (sorting, combinatorics, etc) on a regular basis. If you fail to master these, and to understand their underlying rates of growth (ie, "Big O"), you'll be forever pigeon-holed as a lightweight "webdev" forever, even if you have the programming chops required to build complex, reliable, and useful software.
Plus, they get really interesting the more you study them, and the math behind them.
It's been the opposite experience for me in SF, actually. More startups are realizing that they want people who can build good products quickly, and with more people coming from non-CS backgrounds, they'd rather test for that than see if they can whiteboard a breadth-first search.
I took enough CS coursework to learn the stuff you mentioned, but I've worked with a number of developers who don't know any CS theory. Several of them are stronger engineers than me and have had very successful careers, and I'd rather work with someone who can communicate well and solve hard problems than someone who's read through CLRS.
Most computer science degrees will go way beyond this in the theoretical aspects.
I would add bloom filters, and some math like Fourier transforms and bezier curves.
1. your own MVC framework You should do this to appreciate why developers of other frameworks make the decisions they do. I gained so much wisdom from this.
2. Parsing HTML with regex (see here - http://blog.codinghorror.com/regular-expressions-now-you-hav...)
Seriously, just DONT DO IT(tm) -- but if you do, you will eventually learn why you don't want to do it this way, and you might get pretty good at regex expressions
3. Your first mobile app published to the app store Publishing apps to the Apple app store has given me a deeper appreciation for paying attention to the little details. Also, making native apps is a completely different paradigm than web apps because shipping code with logic errors has such a high cost and delay to fixing them.
4. Port an existing library to a new language I long time ago I ported a recipe parsers from Ruby to Python for a paid gig. It was such a good learning experience because I had a perfectly functioning reference implementation, which allowed me to go deep on getting the details right.
I had to replicate test cases, documentation, scaffolding, and the code itself while being aware of the gotchas of Python.
[1] https://www.youtube.com/watch?v=2Pn1RVZu-24
Yes, you'll learn that this task is literally impossible, as well as why:) I think we've all used regex in a spot where it's impossible to do so correctly at some point.
Someone better versed than I: https://nikic.github.io/2012/06/15/The-true-power-of-regular...
Of course, the money quote is: Just because you can, doesn’t mean that you should.
I thought I knew REs before reading that book -- since I had both been using them for years and did a course on automata theory at Uni -- but that was just Dunning–Kruger.
Edit: Also write a templating system and be done with it, so you won't waste time doing it later. :-) When I first learned programming I did quite a few simple games and routines to find primes.
http://stackoverflow.com/questions/1732348/regex-match-open-...
Great idea, better than mine, but the code was awful, had three global state variables X, XX, and XXX ... plus U, UU, and UUU for the UFOs he'd added to make the game more fun ^_^.
I helped him reduce the complexity by removing the UFOs (it was still quite challenging enough), and getting it to work in general. This prepared me for the many future jobs I took working on the code bases of others (one of which, for example, taught me red-black trees for real), and which soon enough led to the extremes of software archaeology when you can't even ask anyone about the code.
Not that you necessarily want to seek out such work, it's hard and often thankless, but at its best it's also what paying down technical debt is about. And code you've written long ago can also be rather foreign when you come back to it....
However, in terms of projects popularly considered to be commonly implemented by newer programmers that do hold benefit, in network programming, I would say a traceroute implementation. Server-side, I'd say any multi-node cluster system, preferably diskless. Any embedded system. An RDBMS system. A NoSQL system. An open source intelligence system. Any computational linguistic system. Any i18n/l10n heavy project.
[0]: https://en.wikipedia.org/wiki/Rite_of_passage [1]: https://en.wikipedia.org/wiki/Hazing_ritual
If you want to do more parallelism rather than just concurrency, you could have some inputs make the bot start doing some work (like computing the billionth digit of pi) and queue the work up into a threadpool. If you really want to get into parallel programming, you could write a multiproducer-multiconsumer queue to allow the IO threads to communicate with the pi computing worker pool.
Hope this is a good concrete project! I did the first part (multiple connection IRC bot) a few years and it definitely helped me understand concurrency and network programming.
My "hello world" for learning new languages and platforms. Integer based or floating point. 2d or 3d. Sound effects, sprite animation, physics, procedural particle systems, global leaderboards, digital skins and so on ad infinitum. Allows you to experience nuances in packaging and deploying WebGL vs Android vs Steam. Continue polishing it, and you may end up with something fun that others will love!
Can also be refactored into a full Tron Light Cycle style simulation. Which is a great way to learn AI. Good luck!
Seems to me that the best way to test your well-rounded skills as a programmer is to build and launch a product. Even if you don't aim to be an entrepreneur, the holes you find while taking an idea from inception to launch are much bigger holes than you'd find building this tree vs that tree.
It's much more difficult to learn about unit testing when you have the complications of a project stack: databases, front ends, etc. The fundamental data structures are self contained and their behavior down to the last detail (the spec) is fully described. That's an ideal way to learn about writing good unit tests.
Every developer should also implement all the basic data structures and algorithms -- and then never write their own again! The process, however, definitely improves your chops, helps you understand the trade-offs inherent in choosing among data structures and algorithms, and gives you an appreciation for what's going on "under the hood."
(Yep... I'm officially old now. I just played the "kids these days" card.)
1. Build your own CMS
2. Build your own framework
3. Performance tune SOMETHING intensely so that you can observe the bottlenecks and their causes across the stack
Just off the cuff there.
We could totally make career bingo outnof this...
- Attend the same convention twice in a row for different jobs.
- Work with an ivy league MBA.
- Eventually settle on a Java or C# job.
- Build a wonderful product that people won't use. For whatever reason...
- Burnout and dream of working in construction...
why is Java considered "settling"? relatively inexperienced here
I don't have a big problem with Java (it was the first language that I learned object-oriented programming in), and I like C#'s increasingly cross-platform focus. I like the things I've read about C++17 and the features planned for it, and I'd be interested in seeing Rust pick up some steam.
Other people get really excited about various functional languages, new+shiny Javascript frameworks, and Node.js. Anything that's new, related to web technologies, and solves a perceived problem.
Is this a thing? Working in construction is usually my first day dream when I'm feeling fed up with work or a little burned out.
- coding while fighting the scope creep
- coding while trying to figure out the overall project architecture on the fly in endless whiteboard meetings with other devs because the high level architecture Solution Architect put together ain't worth a sh*t.
- stepping out of your comfort zone on the daily basis having to deal with the tech you have 'some' but not 'good' let alone 'expert' knowledge of because you can't possibly hire an expert for every tech
etc etc... but still delivering on time with low defect count :)
1. Writing a professional product, from scratch to completion, by yourself or as a team lead, while doing every aspect of the project: BA, PM, design, architecture, server install, data model (if applicable), code, comments, documentation, QA, deployment, support.
2. Pick up a complete mess that someone else wrote, who is no longer available. Read it, really understand it, and be able to refactor it into something worth while.
As stated, most of the things the OP listed are really just academic and he should have done those in school, as they have been done as nausium. Rarely do you need to do those anymore.
Now, learning people with MS in CS have the same issues is what's really jarring. There were so many weed-out courses in BS CS, I couldn't imagine someone getting as far as a MS CS without knowing the basics.
Having said that, I earned most of my chops on "the street," with a great mentor many years ago. We really challenged each other want wanted to show each other how smart we were. Good times.
Do you know where they got their degree? ITT Tech or something?
In any case, the best developers I've worked with are the ones that practice the fundamentals on their own, regardless of whether they're degreed or not.
Writing a shell in C (you can use Readline if you don't care to learn much about parsing) teaches you lots of stuff about the operating system you're working on.
You won't often see a big project structured this way, but it is very effective for a first hand experience of data driven design.
I'm not saying it can't been done well, but it poses enough problems that are difficult to avoid, like calling an external web service inside a stored procedure, and the general mess of maintaining a bunch of chained stored procedures, functions.
It also guarantees vendor lock-in.
Like Linus said, bed programmers worry about the code, good programmers worry about the data and its relationships (or something to that effect).