Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: How do I learn to write better code?
47 points by momofuku on Sept 22, 2020 | hide | past | favorite | 59 comments
Some context for this question: I'm a mechanical engineer by training and I now work in robotics; developing path planning models in a research setting. I didn't have a traditional education in Computer Science. When I look at the computer engineering posts and comments on HN/Reddit, I feel woefully inadequate. I've never used these technologies like Kubernetes, Docker etc and feel out of place.

So, how do I write better code? How do I plug my CS foundation to better suit the current scenario of engineering?

Probably controversial, but the current scenario of engineering is over engineered. Hacker News is Unicorn-biased, most of the information here isn't practical if you're just trying to solve problems that take your project from point A to point B.

Look into problems, you'll find solutions. Look into solutions, you'll find problems.

Agree. You don't want to do Fashion Driven Development (FDD). You would end up chasing every shiny thing that comes out and not really master anything.

Pick any one stack, build some simple projects and then expand on it. You would also want to be able to read well written code from others on github and learn from those.

by contrast don't not do something just because it's fashionable. It's worth thinking about something fashionable, because many (not all) those things are usually pointing out real pain points that people are experiencing.

If something fashionable looks appealing, I would say, "drill down and understand the core of what pain point it's addressing". If you are convinced, check out "how you would have done it otherwise", and if you are happy with the fashionable thing, add it to your "fashionable thing" budget. Keep that budget tight. Be ready to revert at any time.

"Look into problems, you'll find solutions. Look into solutions, you'll find problems."

God, I love this line.

Yeah, such pithy insight can only come from experience.

Our industry, especially these days, is flooded with "solutions" that promise much - and the best ones do deliver; but what's suitable in an enterprise environment can be a huge mismatch and complexity cost for smaller companies, individuals, or for research purposes.

I heartily agree with the grandparent post, to focus on what the problem domain requires, to use tools and dependencies that specifically support that goal.

Too often we see a framework, library, language or tool used for the sole reason that it's what the big players use - basically driven by popularity and inertia. There are advantages to buying into an ecosystem or particular scalable approaches, but only if it suits and serves your purpose.

As for writing better code - as many comments point out, the best way is to read and write lots of code, study books, follow the best works of people in the field.

It helps to start with the specifics, I think, by having (or creating) a problem to solve, or a project with clear goals. One can start with the simplest, "naive" approach, to solve the immediate needs - often that involves finding off-the-shelf libraries. Then, consider ways of improving the logic, refactoring, maybe dig deeper into the libraries to understand how it's organized.

There's just a really "in" trend right now of prematurely optimizing for scaling up to billions

Could not agree more. A lot of the time the simplest, dumbest solution is the best.

There are some practices that make your app easier to manage, but you need to understand in which circumstances you need to use them.

A lot of the successful companies that are out there, got there from running a simple Django/RoR monolith until they were 60+ engineers.

My mentor was a professor at MIT for a time and then founded his own company. I joined his company as a young hot shot that thought I knew it all, I was a good hacker but not a good developer and I learned that quickly working with him and his team, but that is a story for another time. The point of my post is one thing he said to me stuck with me more than anything else in my career and that was: "Elegant code is not clever code, elegant code is code that is so simple it is clever. Strive for elegance."

I would imagine that the problems encountered by a robot engineer are quite different from those of a web startup, too.

A good way to write better code is to read good code. Go find some open source projects you like and skim read the code!

Personally, I like to go back in the git history to when things were simpler and see the changes to the codebase that solved specific problems they had, e.g; scaling, reusability...

This is often repeated advice, but is less valuable without a sugegsted list of projects known for code quality, or even better a list of projects known for code quality and relatively simple code base.

I often find the best service someone experienced can render to someone unexperienced is the service of curation, i.e. hand pick from the vast amount of available options a few that are likely to help.

When I started down this path I just picked applications that I used a lot.

For example I read the source code to `less`, and the manual. Despite "knowing" less I learned a lot from reading the manpage and reading the code.

Same with GNU Make. I could say I knew it before I started, in the sense that I'd written simple Makefiles and knew how to run `make -n` , `make -j4`, etc. But reading the manual from start to finish, and reading the code meant that my knowledge was more complete.

Some programs have terrible source code (e.g. "telnet"), and others good (e.g. "redis"). I think that a list of examples might be useful, but more useful still would be for people to choose things they know, and they use.

Reading all about the design of postgres might be wonderful, but if you're not actively using it then the details aren't going to be so memorable.

Better yet, because I read the source to programs I used I was even able to contribute bugfixes to them. (In the case of less/make at least. Not always.)

also, studying only libraries might encourage people to think that the proper amount of abstraction is higher than it might be for an actual project.

My take is that designing good code has a lot to do with the art of learning what abstraction to construct. Seeing lots people design different abstractions for different use cases is useful.

Going and finding oss project that are similar to the things you’d actually write is hard enough, but then also figuring out if the code is any good when you don’t know what good code looks like is an even greater challenge. Even if you pull that off, you’re not really going to know why parts of it are any good.

Ideally, you’d find a mentor who can review your code and give you pointers on how to improve it, with explanations on why those things would help. Those mentors aren’t easy to find either, but still...

A fun website idea: curated refractors, where commits and design decisions are laid out for readers to skim and enjoy.

> technologies like Kubernetes, Docker etc

These are less about coding, more about ops. I'd only bother reaching for these if you know you need them.

> So, how do I write better code? How do I plug my CS foundation to better suit the current scenario of engineering?

Start with a project. What is a problem you face daily or weekly that you'd like to automate to some extent? What is a problem your friends or family have that you think would be interesting to solve?

Find a project, break it down into its pieces, and start coding. Your code is going to suck. You're going to look at it a month later and cringe. You'll look at it a year later and vomit in your mouth a little. But this is good, it means you're getting better.

As far as learning, I'm not much of a reader. I never learned well by looking at other projects unless I was picking apart a very specific feature. Instead, I learn by doing: trial and error. I found this methodology works great with languages that have a REPL (javascript, python, lisp), but you may want to focus on a language that's more specific to the problems you will want to be solving.

No matter how you learn, once you've been programming for a while you'll start to built a vault of patterns you can use to solve specific or general problems. You'll also find that once you get good at one language, switching to another is much easier than learning the first because a lot of the knowledge transfers.

Hope this helps, good luck!

I’m from Mechanical Engineering background as well.

Software Engineering in essence is about taming complexity so that mere mortal humans can build cost-effective complex software, when you reach to million lines of code, you wouldn’t want complexity get in the way. So I recommend you follow these guidelines:

* Build your software as if it is a house where you can add more rooms as it grows. Ensure that software architecture is modular, each module should be capable of working independently from each other. You will further atomise modules through classes. So basically composition goes like this: Software -> Module -> Classes -> Methods. You absolutely need to get modules right. Mistakes made at class level can be easily corrected but it is harder to separate module level entanglement.

* Variable/function names should be self explanatory. Don’t name them too short or too long, they shouldn’t confuse/waste the time of other people working on the project.

* Code clarity is extremely important. Don’t write hard to understand code unless it is an absolute necessity. Premature optimisation is bad but you can do premature optimisation so long as it doesn’t affect code clarity. Otherwise leave optimising code to last stage.

* DevOp tools like docker incredibly increase the production speeds and overall software quality. So try to keep up with these but don’t go 100% on them as they might also increase the complexity. Gradually add devops tools to your project as it grows. You probably don’t need to implement every single DevOps tools. For example, if you got less than 20 production servers, you probably don’t need kubernetes.

In my opinion the single best way to learn to write better code is to read a lot of it. By reading you'll learn things from those with experience and with good practices. Most importantly, by reading code you'll find that certain practices make code harder to read and as a consequence you will develop a taste for good code while cursing any "bad" code you come across. Ultimately it's all subjective but in the end, I find that reading code in unfamiliar codebases as a powerful self-improvement tool.

Another way to do it is to fix bugs and refactor old not so good code. Force yourself to understand the actual underlying logic and the problems it solve. Use your frustration to figure out a better design that code so it wont punish future programmers.. After doing this for years you will hopefully have built a good habit of simple and clean design.

If you're writing code for robots in a research setting, a lot of good advice around making code easy to deploy, doing continuous integration, logging and monitoring, etc. is just not relevant. Therefore these tools are probably not worth learning about.

One place to start might be learning to write good unit tests. This would require:

1) learning the basics of how to use a modern, nice unit testing framework for whatever language you use.

2) learning the skill of how to come up with good test cases for your code.

3) learning how to write code such that unit testing is easy. this will also make your code higher quality and force you to learn about design and software engineering, but in a way that will actually be useful immediately. Books like highly-recommended "Clean Code" are relevant here.

Wow, great advice in here, good job HN!

I'm an ME but have been mostly doing SW for a very long time. What I remember helping, in addition to the advice here:

1) Start small, don't dive into a complex project right away but instead find the interesting parts of the project where your domain knowledge is useful. Rely on seasoned SW folks to maintain the framework and then slowly learn inside out.

2) Use the debugger! In addition to reading the code and any documentation on the architecture the debugger can help reveal the often crazy runtime behavior. At first just step through your code and watch what happens, then look at the call stack and, if applicable, threads or other concurrent stuff going on.

Watching live-streaming coding sessions can be a real eye-opener. Everything from how to use revision control systems to keyboard shortcuts to labor-saving technologies will be on display. It's extremely hard to figure that kind of stuff out because it's rarely clear there's a problem or concept to search for.

You might try to find some prerecorded sessions in your field.

I agree, there's usually something to be learned when watching someone else work in their environment. Especially if it's radically different than your own. However, I usually learn more about new tools or shortcuts and less often about code unless it's a tutorial of some kind.

Destroy All Software screencasts by Gary Bernhardt has some great content. Besides the typical CS degree, I felt that these videos were most pivotal in writing better code.


These screencasts had such an impact on me that they inspired me to have a go at making my own set of screencasts aimed at non-beginners (a rarity with programming videos)

My guiding principles when recording my (now over 25) videos are:

- prefer timeless technologies (e.g. unix, testing, C) over fad frameworks

— focus on trade-offs — every idea in CS has a cost

— don't be afraid to peel off one layer of the stack

— set everything in real production code rather than in toy examples

- emphasize actual workflows (showcasing vim and bash and all the associated keyboard shortcuts)


For a beginner (and self-starting), I recommend some animations that involve math. There are several javascript libraries like konva.js or paper.js or even d3. They can get you started immediately. You can animate for instance how cycloids are drawn. Or something like a ball bounce.

For the better part of these kind of exercises, you will mostly deal with APIs. (APIs that allow people to draw stuff on html5 canvas). Its APIs all the way. And that should be your expectation moving forward.

When it comes to professional programming, i.e. writing maintainable software - it boils down to a lot of good habits, like organization, commenting, structuring your code, reusability, design patterns, etc. But there is no real roadmap that would lead you here. Perhaps you have to write all kinds of software - servers, daemons, gui apps, etc.

One advice, is that when you write code, and you happen to read it again, say, five years down the line, you must be able to grasp what mess you had originally written. Often, it might not be you doing this; but just think how quickly can someone grasp what you have written. I think that is the nirvana or the higher goal you should try to achieve in professional coding.

Of course, there are many suggestions here. Opensource for e.g. Just try your hand.

Kubernetes, Docker, etc they are technologies that deal with how software is deployed. They influence how we write certain software, but as such not meant to teach you how to code.

Kubernetes and Docker have nothing to do with writing better code.

Those technologies are deployment technologies for large-scale web platforms. If you're working in robotics, you will never need to worry about these technologies, much like SAAS programmers generally won't need to worry about interrupts, device drivers, etc, that might be a part of your daily life.

If you want to get better in programming, you need to get code reviews and listen to what others think about your code. Also, do a side project where you make several iterations on your code. It's easy to write shitty code that works if you write it once and then move on. If you have to make several iterations on the code base, you'll come up against very common problems like "oh shit, if I change this API, it's going to affect all my code!" and if you run into that enough times, you'll remember not to do that in the first place. The only way to become a better programmer is to sit there and code for 10,000+ hours.

If you have a lot of users sharing a small number of servers in the cloud, Kubernetes and Docker can help.

If you have one process hitting one Raspberry Pi, they won't help you.

Part of what you need is a plain English, low jargon, directory that briefly explains each piece of technology, and which problem that piece solves. It would need to be opinionated on when to use and when not to use different pieces of technology.

I don't think any directory like that currently exists. If someone built it, I would go to it a lot, and endure lots of ads in order to learn about pieces I don't use yet. If only someone would build this.

I'm in a very similar position: I graduated a couple years ago with a MechE bachelor's but now work as a research engineer in a marine robotics lab, including writing a bunch of code.

There's a few of recommendations I'd make:

1) Use Linux in your day-to-day life, and do as much in the command-line as possible. There's no substitute for bash, especially in robotics when you're working with embedded Linux systems all the time. You'll quickly pick up commands you like, and from that scripting things will really help build some experience and give you a good "sandbox" to play in.

2) Most robotics systems end up either being immensely complex, or simpler than you think. Most of the complex systems aren't the same ones used in the rest of the world, since with the exception of self-driving cars and now the NVIDIA Jetson computers, you don't have enough compute to run the complicated stuff. Raw C++ code will probably run fast enough. As a result, a lot of the stuff-you-use-for-web-apps-that-you-might-have-to-scale-to-millions-of-people won't come into play. Instead, doing things like setting static IP addresses or debugging a serial port connection pop up a lot more.

3) Software has a nasty habit of getting complicated sooner than you'd like. As others have mentioned, testing is really, really important. Whatever your preferred language is, I'd suggest you spend a lot of time figuring out your preference for how to easily and repeatedly ask "does this do what I think it does". Unit tests help a lot, as do. Without trying to shove it down your throat, this is one of the reasons why I do a lot of coding in Rust--the package manager and its unit test tooling is all built in and makes checking my assumptions much easier.

4) Probably avoid a bunch of posts written on either LinkedIn, and to a lesser degree, Medium. I'm sure you've seen it in other areas, but coding in particular seems really prone to have pieces written by people whose main goal is to show that they did something, not teach other people how or explain the nitty-gritty you'll need. On the other hand, some people's personal blogs are gold, and I suggest you figure out a way of saving good content in a way that lets you find it again.

5) And finally, try to find some places where you'll feel comfortable asking questions. Some languages or frameworks have forums, other have sub-reddits, others still have Discord/Zulip/etc. chats. It can save you a huge headache to say "hey, I tried doing this thing, I'm stuck here, here's a well-written explanation of everything and my code in a Github repo, plz help".

I think the fastest way to grow is to have your code reviewed. If you're not in a professional software setting then making a pull request to an active project with patient contributors will probably be your best bet. Find an open issue for k8s, docker(-cli), figure out how to fix it, open a PR and I would try to preface it with a "this is my first PR, I'm very open to critique" type of intro. With any lucky you will find someone who can gently (or maybe not so) nudge you in directions of better quality code.

Best of luck on your journey!

After nearly a decade as a professional software developer, I recently found Bob Martin's "Clean Code" videos and I cannot recommend them enough. They're sometimes awkward and weird (he's a bit eccentric) but the content is superb.

I try to watch 2-3 videos each week, usually before work.

O'Reiley has most of them available if you're a member ($50/month) and it's worth it just for those videos, imho.

Do you have anyone who you can work with? When I first started as a SWE I pair programmed every week with a senior engineer on fixing bugs in the application. It was one of the most fun and deep learning experiences I have had.

Besides that, when I come across a technical article - or even comments here on HN - I print it out to take it offline to read later, highlight, mark up. Then months later I circle back to it and usually find that I'm a lot more familiar and knowledgeable about it than the first time - a kind of long term spaced repetition.

Reading other people's code is also really good. Do you have other engineers in your organization that you can read code from? If you don't, try to find open source projects in your field. Again, I like to print things out. It is the best way I digest something. So yes, I print out code to go over later when I'm having dinner with wine.

If you just want to write better code literally, then consider reading Clean Code[0].

If you want to dive deeper in to Computer Science and become a Software Engineer, then there's a lot more to learn. Here's some short tips:

- Learn a few programming language for their paradism: Java (OOP); Python, Hashkell, Scala (Functional Programming), Rust (memory safety). You don't have to actually work on them, just need to be able to write some algorithm and know their key features.

- Read more code, especially those from high quality projects.

- Experiment a lot. Don't just read articles, blog posts. You have to get your hand dirty.

[0]: https://www.amazon.com/Clean-Code-Handbook-Software-Craftsma...

> I've never used these technologies like Kubernetes, Docker etc and feel out of place.

Don't get hung on technologies for technologies sake. Kubernetes, Docket are just tools that are useful in some contexts and are completely irrelevant in others. The fact that a significant portion of HN is engaged in modern web backend development doesn't mean it's the only significant area of engineering.

> So, how do I write better code?

Short answer: be lazy and hate work.

Fixing bugs is work. Instead of just fixing it, find out how you could've used the type system or API design to prevent yourself from making this bug in the first place. Fixing this bug is work. Preventing yourself from making the bug in the first place is saving yourself of doing the work.

Rewriting your old code when you get new requirements is work — learn how to build an app architecture that would make this amount of work minimal.

Writing code is work. Maintaining code is work. If you manage to complete your tasks using less code, you'll have less work.

Manual testing is work. Writing unit tests is saving your time. Learning how to write tests so you won't have to rewrite them when your requirements change reduces the amount of work you have to do even more. And leveraging the type system to maintain some invariants about your code saves you even more work.

Communicating with your colleagues and answering their questions is work. So, learn how to write code that is easy to understand. Writing comments is work too, so if you manage to write a code that is so clear that it doesn't need comments, you'll save yourself from even more work. Writing great documentation will save you time on work chats.

Of course a big difference between being lazy and being irresponsible. We should always thrive to achieve the best possible result for our customers, internal or external. But actively trying spend less effort without compromising on quality is the best driver for innovation and learning, in my experience.

There is basically an entire universe of computer science, computer engineering, software development and software engineering. All up and down from the microprocessor up to the cloud. You can go get lost in javascript as much as you can become lost in the world of cloud databases.

Reading an algorithms and data structure book would probably fit in your path planning model research. I am guessing graphs, trees and A* would be useful. Modern planning probably have some kind of probabilistic component/control system now too e.g. reasoning under uncertainty (graphical models). So that's the theory here is what I am getting at. And probably the most important part!

You probably have a development environment so work in that ecosystem. You can follow test driven development or whatever you want. I would avoid systems tools like docker etc.. unless you need them.

Software design is really breaking down and solving problems at some level of conceptual abstraction. So the canonical example would be a list or an array. It has a data structure, a set of operations. It's easy enough to build a class that models a list of integers, but now extend that to strings and then what about generic objects. I also should be able to have the same algorithms work on a list of any type. Software design is basically that approach but at different levels in the software stack.

For a robot you would want a function for turn left and move right and maybe a module that groups related locomotive functions together. Maybe have a data structure that models state and where in the world the robot is.

Now sometimes you have to come up with the concept of "list" in the first place but for 99% of tasks we just build out of basic data structures and systems and use those to build something bigger. Lists -> arrays -> graphs really are conceptual primitives.

Your algorithm choice will play a role too.

You might also enjoy the screencasts at: https://www.destroyallsoftware.com/

One way is to contribute to a code with others and get into this cycle: 1) Write code that solves problems. Do this a lot. 2) Have other people review the code you write, and offer suggestions, improvements, et cetera. Without a job this is more challenging, but you can still start a project or contribute to an open source project. 3) The next time you write code, anticipate what these reviewers will say, and determine if you should apply the advice.

Also, read other peoples code, and for whatever language you choose, find the aggregators, reddit, twitter and start reading them. Eventually you'll find someone who write very clear code, and start following them.

In my experience the best way is to work with other people who write good code and have them review yours.

If getting a job doing it isn't a viable proposition for your life goals, then alternatively you could study well-written OSS projects.

Writing good code is hard. In general, you should be looking to learn programming practices, principles, and patterns.

The main aspects of coding:

* Make it work (programming paradigms)

* Make it right (code structure/design fundamentals)

* Make it fast (dynamic structure/engineering)

Read other people's code. Write code that will be reviewed by other people. Review other people's code. Do this with many different projects/sets of people. Going for something like GObject to Linux Kernel codebases (both in C) is like going from the Earth to Mars. You will learn something.

Now if you want to strengthen your Computer Science skills, I suggest taking formal Computer Science courses. I think some US universities have classes available on the web. The math part is very important.

Or you could start by reading something like Introduction to Algorithms from Thomas H. Cormen. Or the book from Sedgewick.

Something simple you can start with is naming. practice choosing better variable names, argument names, and function names.

Take a look at the Clean Code book. The chapters on functions and naming are some of the best.

This might be different to consensus, but write a lot of code.

Each time you end a project look back on how it worked and what could be improved.

I am believer in learning by mistakes. That way you get to appreciate how you failed and how you improved your understanding of the problem(s).

At higher level you don't think how func_a() needs to be implemented (thats easy and well defined) but you focus on modularisation and proper layering of data and responsibilities.

Its also good to have some work buddies/mentors that you can talk about writing code/design.

Nothing will ever beat finding a skilled engineer at your workplace and asking them “can you help me become better?”

That relationship can be something simple. You can bounce design ideas by them, ask them to glance over your PR before you open it to the team, or ask them general workplace questions.

You’d be surprised at how willing people are to take you under their wing. It’s ingrained in us, and I find that the better engineers are more likely to accept these requests than the bad ones.

Write code. It'll likely be bad initially. Don't just write throwaway code, write code that you massage for a while (either rewrite it over and over, or maintain it longer term.). It's when you start to change it on a large scale you notice if it's good or bad. Did you break it when you changed it? Why? Did the changes fall into place easily or was it a pain? Why?

I think our area and especially the enterprise side/web has become obsessed with code and developer convenience. Focus on solving problems and delivering good quality solutions! Stop focusing so much on the code.

How do you focus on the product? Testing, especially testing of the end product behavior and performance. Alternatively and if applicable, learn formal methods such as TLA+.

1. write more code 2. read more code 3. learn more theory

If you want to learn to code better, then do that but what you describe is a stack of technology. So the same rules apply, theory and practical. Install docker, use docker, read about docker etc. There is no magic solution other than gaining experience.

Don't get too overloaded with tools, learn the basics, remember the 80/20 rule.

1. Try a completely functional language like Haskell once to learn about side-effects.

2. If you do multi threading: Look into Immutability and communicating sequential processes

3. Use static analysis / linters / code checkers for every language you use. They provide a lot of tips. There are linters for bash and Dockerfiles as well.

1. Write code for production.

Set up CI/CD, build tests, deploy to a package repository if it makes sense, etc. If you're building and maintaining an actual product, you get feedback that forces you to identify and solve problems. Writing real tests forces you to think about testing your code, solve problems in tests, make tests run quickly, etc.

Ideally, you're working on a team, so you're also looking at the work that others do and critiquing it and they're critiquing you. You're looking for actionable critiques, "if you change X, you get Y," which should help you learn the idioms your peers use and an intuition for why one way of doing it is better.

2. Learn from your standard libraries.

Generally your standard libraries are the best code you'll see. Popular open source libraries, especially ones that are de facto standard libraries, are a close second. Even when they aren't how you'd like to write your code, there's a lot of wisdom in the compromises they made. Read their decision making process, JCPs, PEPs, Go proposals, to find insights as to why the language does things one way or another.

3. Math > Docs >> Stack Overflow >>>> Tutorials

You won't do math every day to implement things, but you're already comfortable with it, so practice expressing the math as cleanly as your language allows. The math of CS is way simpler until you get into AI or compiler theory, so it shouldn't be hard to find resources that explain it.

The next stop that should address 95% of things you need is your language's documentation.

Stack Overflow is okay for solving obscure problems, but rather than copypastaing a SO solution in your code, figure out what it does and why it works. And SO answers are routinely badly wrong or out of date.

Most tutorials and blog posts out there are hot garbage.

4. Why is this better?

That's the question you want in the back of your mind. As you're maintaining your old code (recall point 1) you should be looking at it and thinking, "I don't like how I did this." Then redo it, make it better, and think about what's better.

How you structure code, how you name things, how you manage compatibility, all these are hard to quantify and explain. But the subtle pros and cons of different choices become really obvious (to you, at least) when you're refactoring and fixing your old code.

Check out this talk from Bill Sourour https://www.youtube.com/watch?v=0czUk0j6zLg

To learn to write better code, iterate over your code. Attempt to make it better over every iteration.

It's a good question, but has multiple components.

The first, and IMHO most important component of your question, is how to improve your actual written code. A few ideas:

~ Pair programming with an experienced programmer, if possible. If not, try to work on a project (even an open source one) with someone who is an experienced software developer and who does comprehensive code reviews. Code reviews from articulate, experienced developers are an excellent way to learn.

~ Write lots of code. Write code in new areas unrelated to your job. Try to find some small project or projects to do. Once you're done, reflect on what you've done and what you could do better next time.

~ Read books like Clean Code. It might also be wise to pick up a book on design patterns, particularly if you'll be working much in object-oriented languages like Java, C#, or C++.

~ Always read source code when possible. Using a new tool at work? If it's open source, go check out the code. Starting a new project? Go find similar projects on Github and browse the code. You could also find some well-known open source projects and read through their code. A good book for ideas on which open source projects to focus on is called The Architecure of Open Source Projects (there are two volumes, shown at the bottom of this page: http://aosabook.org/en/index.html)

~ Learn other programming paradigms, such as functional programming (maybe learn Haskell, or Scheme) or logic programming (learn Prolog). You may never use such languages in your work, but languages in other paradigms will provide you with both a better understanding of computation, and a bag full of useful techniques and ideas for your working language(s).

The next component is how to improve your understanding of data structures, algorithms, and other topics rooted in theoretical computer science.

~ Consider doing problems from sites like leetcode.com and hackerrank.com.

~ The book _Algorithms_ by Robert Sedgewick and Kevin Wayne is very good, as is their free two-part course algorithms and data structures offered on Coursera (https://www.coursera.org/learn/algorithms-part1).

~ Work all the way through the online book Structure and Interpretation of Computer Programs (https://mitpress.mit.edu/sites/default/files/sicp/full-text/...). It will not only touch on a number of important theoretical computer science topics, but you'll also get some good exposure to functional programming.

Finally, to learn commonly used technologies you see on HN, such as Docker or Kubernetes, you'll just need to get your hands dirty:

~ Rent a $5 server on Digital Ocean, or set up a home server, running a Linux distro like Debian or Ubuntu (which often makes installation easier), and start experimenting with them.

~ Continue following HN and reading about new technologies and programming languages.

~ Realize that it's critical for software developers to constantly learn new technologies. Otherwise, they very often become unemployable after a decade or two. HOWEVER, it's also critical that devs exercise restraint and good judgment when selecting technologies for important projects. For such projects, it's usually better to choose languages and technologies that have a proven record and that you personally have a good understanding of, over some new technology that's getting a lot of attention on HN.

With respect to all three of these components, it's a very good idea to maintain a blog and write about your experiences and projects. A blog will serve to not only consolidate your new knowledge, but also to improve your writing and help your career (a good technical blog will be a strong positive signal toward potential employers).

Don't worry about not having a traditional education in computer science. Lots of excellent senior devs I've worked with have no formal training in computer science. As long as you're motivated to constantly learn new languages, technologies, and techniques, and master the ones you already know, then few people will care (or even know) whether or not you have a CS degree.

“Better” depends on who and what you work for. But on average write code that is more easily readable and can easily add/subtract features will cover the basics. Those basically get you to point A to point B faster but without burning bridges.

100% depends on what kind of work you want to do. There's some principles like cleanliness and comments. But outside of that it starts to get domain specific pretty quickly.

I learned by putting shitty code infront of users. The program might run well in your test bed, the real learning starts when your code runs in robots doing real work.

Use the code you write

Write bad code, and you will learn.


There is a large gap between the quality of code that shows up in textbooks/online programming courses and the code that’s usually deployed in production.

Most of that gap has to do with the complexities of deploying, maintaining and scaling a system in production. This recent blog post does a fantastic job at providing a taste of these complexities:


It’s these complications that make up most of the gap between what’s in the textbooks and what’s in the real world.

Kubernetes and Docket don’t make your code more efficient, more readable, more terrible, more correct or more stable. They solve specific problems that teams encounter in one part of the software industry. Engineers writing device drivers at Apple will have a different set of tools, practices and coding standards for example - if they optimize for running tests in the factory and reducing the drain on the battery, it will be a different set of complications that will create the gap between textbook code and what’s deployed. Apple’s production quality code will look extremely different from Facebook’s because the complexities are different.

There is a small part of the gap between textbook and real world code that is not caused by domain specific nuances. It’s pretty easy to pick up those skills:

1. Use a code formatter like clang-format and/or a linter. Pick a coding style and stay consistent with it.

2. Write code to communicate intent. Name your variables and your methods so that the resulting code reads as close to prose as possible. Write your code in a way that someone you’ve never spoken to can easily figure out what’s going on and modify your code.

3. Design your APIs first. Think long and hard about your API, how it will be used, how it can be tested against, how it can be extended in the future. Read “The design of every day things” by Don Norman and pick up on what is good design.

4. Related to 3, design your API (and implement) them in a way that’ll allow as much of your code to be unit tested as possible. Have an algorithm that will run when your robot hits a wall? Pull your algorithm into a separate file, with its own API in such a way that you can compile that algorithm into a second “test” program that’ll feed it some inputs and check if it produced the expected output. Use a code coverage tool (google gcov) to see how much of your code is covered by unit tests. Aim for 98% or higher. The “should I move these lines of code to a new function” is then easily answered with “will a new function (in maybe a new file) help me increase my code coverage in unit tests?”

5. Write your code so that tiny errors blow up into catastrophic failures as quickly and as loudly as possible. Add error messages everywhere. Add asserts and static_assets everywhere. You are going to spend a lot of time tweaking and testing your code - if any change triggers a failure anywhere else - you want it to fail with a really really loud bang so that you are more likely to notice (and debug) it.

6. Avoid creating skews/variants in your code. don’t have a debug version and a release version - write code that you can test, deploy code that you have tested (exactly the same code, with no changes)

This will get you over that gap between text books and real world. The rest you will figure out as you go deeper into your domain.

Specifics: Kubernetes and Docker are tools you'll use when you need them.

You can find yourself a tutorial on these, go though it, and have a sense on what you can use them for.

For example, we use Docker images to spin up Jupyter notebook servers with the most common dependencies for our users, plus other components that add features like notebook scheduling, and live collaboration.

It would be hard for users to set that up thelselves. Think of it as a way to package and deliver value without the fuss.

How to write better code:

- Read good code: clone repositories of proven software that you use, and read from it from time to time.

- Curiosity: when you use software, you may encounter functionality and wonder about it. If you have the code for that software, you can look how it was implemented and architected. Doing a git blame and finding the first commit where something was introduced is educational. You can then advance commit by commit to see how it played out.

- Vocabulary: sometimes you don't know something and you can't even look it up because you don't know the word for it. For example, there are concepts like 'message passing' or 'multiple dispatch' that I have pondered on for quite some time before knowing what they were called. I was trying to formulate a search query to find what that way of coding was. The same thing happened to me when I wanted to learn how to think better and improve my cognition. I had tormented myself thinking 'is there a field from which I can learn to think about my own thinking. Cognition on my cognition'. I felt stupid when I stumbled upon it and found it was simply called 'metacognition'. Sometimes I was luckier. For instance, after observing how some software can add new functionality from pieces created by third parties, I knew I wanted to learn how to do that. When I was a child, I found it really cool that you could make a Winamp skin, and Winamp would transform to that skin even though the Winamp folks ignore everything about your existence. They didn't need to integrate your skin. I found that to be really powerful. I had the docs for win32api, and found it amazing I could use it to access system functionality, etc. When I wanted to transform a Doc to PDF, I installed an extension and Microsoft Word knew where to display it and what to do with it. Same with applications. The underlying themes are APIs, extensibility. The materializations are plugins, extensions and applications. The supporting principles are good abstractions, and open/closed principle, dynamic loading, and interfaces.

It helps to structure the thought into 'themes'. Extensibility theme, for example. And then categories, like a plugin architecture. Keep those and link new things you learn to those themes. These compound and find their way in your new software.

- Write the documentation or the use guide first. A description of how your yet to exist software is used. You write 'X does this, here is how you use it'. If everything were possible, what would the usage be ? How would a user interact with it. Write it, then code the simplest version that does the job.

- Don't be unproductively hard on yourself. Pick any amazingly successful software and do a 'git log --reverse' to see the first commits on top. Ad augusta per angusta.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact