Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: What helped you get good at programming?
76 points by robalni on May 2, 2022 | hide | past | favorite | 82 comments
What are the most important things that have helped you get as good at programming as you are today?



Dive deeper. A huge amount of programmers bounce out, throw up their hands when something isnt working as expected. Go look at the souce of the libraries you are using. Learn tools like strace or dtrace. For god sake get good at your debugger.

In programming, everything is about mindfulness, perspective, awareness. The willingness & ability to go deeper, to dig for truth is the ultimate superpower. The docs dont help, your mentors dont help: Seymore Papert was correct. You have to mine your own truth, develop your own internal models for what is going on, how things are happening, and you need endless boundless ability to dive further in, to chase real genuine truth yourself. The ability to develop your own mental model of how you think things work, and your ability to probe & validate & make inquisitions into each little step: that scientific minded exploration makes all the magic happen.

Also, get good at promises & async. How things happen over time has gotten more complex in modernity. You need to understand & be able to internalize/visualize the timeline of execution, in a way we didnt used to demand.of programmers. Learn the tools, think about causality.


Came to say basically this.

Whenever something doesn't work the way you believe it should have, whenever you see something that does not make sense, that is your understanding at odds with reality. Something doesn't work the way you think it does! Every time you don't get to the bottom of why it doesn't work the way you think it should work you are continuing to be a little worse than you might have been.

Accumulating moments like this over time adds up to the difference between being a great programmer and being complete crap. It's the difference between someone who overhears two people talking about a problem and says "Did you check that the locale is not set to iso8859?" and blows their minds that you could debug the problem they have spent 2 days working on in 5 seconds and the person who tells people "oh, yea, sometimes our app just crashes, it's something about text encoding but if you just open the file and save it as utf8 then you can manually fix the broken characters after you import it".


Deep dive projects — https://codecrafters.io


This is cool. Thanks for posting.


Similar answer here. Some activities I got most new skills from: reverse engineering feature phone firmware (no previous experience with re, tiny bit of assembly), contributing to all an OS which included an AOT C# compiler (no previous experience), writing a low latency telephony proxy (no previous experience), etc.

Someone learned how to do those things, so you can too. The information is out there, and if not, you can go one layer deeper and figure out how/why things work.


Where did you learn to RE feature phones? Did you need special equipment (e.g. JTAG)?


So the phone was SL45i and at the time firmware was accessible over USB and not signed. (Or maybe the loader bypassed it?) Either way, I started with IDA, got the basic ideas from a forum where people actually knew what they're doing and learned to understand disassembly and hand-patch the code as I got deeper into it. No special equipment, just 3 months of a summer break that... disappeared. I started from patching a jump here and there, then understanding how the menus worked and changing them a little bit, then writing some trivial "games".


> to chase real genuine truth yourself. The ability to develop your own mental model of how you think things work, and your ability to probe & validate & make inquisitions into each little step: that scientific minded exploration makes all the magic happen.

Wonderfully put; this cannot be overstated! And I think you can apply this to most of math, physics, electric engineering, etc too.


- A LOT of practice. One of that parts of becoming a good programmer is learning about potential pitfalls and bad practices; what better way is there of avoiding these than by making these mistakes yourself and learning from it.

- Studying and researching best practices for not just your current language or paradigm, but others as well. If you've got experience with Java, look into other paradigms than OOP such as Haskell / Elm that focus on Functional Programming. This can lead to learning about new ideas of programming in general, which is a good thing as it exposes you to more tools that you can use.

- Making your own things. Find areas in your life that could use some automation, or perhaps use programming as a creative outlet; the more tools you make, the more practice and experience you'll get which leads to the first point I made.

- Cringe at your old code. If it's really that bad, it's likely you've come a long way as a developer, which is good! Reflect from time to time about why you originally wrote code a certain way, and think about how you would approach the same problem now with more experience.


I was able to code much larger projects after watching this Uncle Bob's Live Refactoring video:

https://web.archive.org/web/20150905163826/https://www.youtu...

BTW, I think sometimes is ok to have inline code with a comment of what the extracted function name would have been.

---

Also, by coding using his TPP helped me gain confidence on figuring out complex algorithms. For example, he explains how writing a sort algorithm went from bubble sort to quick sort (I think) by following the TPP. https://en.wikipedia.org/wiki/Transformation_Priority_Premis...

---

Lastly, as I have a few projects that I can't even run dev on them, because their deps are too outdated, I try to keep deps at a minimum. e.g. I have a custom minifyCSS that minifies ~85% compared to other minifiers, but it's super simple in comparison.

https://github.com/uxtely/js-utils/blob/main/minifyCSS.js


A mentor who wouldn't give me answers.

When I needed to make SunOS give me tty key stroke input 1 character at a time, he refused to tell me what he already knew and just pointed me at some "areas to look into". Knowing about kernel tty drivers and terminals and line buffering didn't make me a better programmer, but it didn't hurt. Knowing my way around a variety of different documentation at many different levels of the systems I was working on helped make me a better programmer, and my mentor refusing to just answer my questions was a major factor in that. It also forced me to understand much more of the systems I was working on, rather than just how to use some piece of convenient API.


I'm curious if you've ultimately found your mentor's behavior to be a net positive, or net negative, in your career.

One of the engineers under me often expresses his discontent that I won't give him answers, either. I think he's more than able to get to those answers on his own, and that the value he'll derive from learning how to learn is vastly greater than the value of being able to complete his work faster. On the other hand, he's given me the feedback that the method is excessively socratic at best, and flat-out frustrating at worst.


I think you have to strike a balance. In reality no one's knowledge came entirely from their own work and asking the right questions. Documentation is just one developer telling another how things work. Should we erase all docs?

You must sometimes give the answer.


It was absolutely a net positive, by a huge margin.

> he's given me the feedback that the method is excessively socratic at best, and flat-out frustrating at worst.

Yep, exactly how I felt in 1987. It was totally worth it, viewed from the present day.


My first boss out of college (a long time ago) was like this. I'd ask him, "how do I do X?" and he'd reply "man <some-command-useful-to-do-X>". I thought it was annoying, but got it a few years later :) I find myself being the same way these days when it comes to mentoring. Others will help a struggling person, but as long as they aren't crazy frustrated it is destroying their motivation too much, and as long as biz needs aren't being too disrupted, I generally have no desire to help. Why would I deprive them of deeper learning by helping them? ;)


The single most important concept separating a good from a bad programmer is the concept of the invariant. Good code maintains (or anyway restores) invariants, bad code doesn't.

It is very easy to miss this because invariants are often not written down, and you have to discover them.

Related are preconditions and postconditions. Function A establishes postconditions that satisfy the following function B's preconditions.

Your goal maximizing merit of code is to ensure invariants, preconditions, and postconditions may be stated as simply as possible; and keep them satisfied.


What do you mean by invariant? Clearly, the word has special meaning for you, but it is defined as never changing. That definition is not consistent with your emphasis.


An invariant is a predicate expression about the state of computation, typically about values in variables affected by code, but may involve control flow.

An invariant is maintained at entry into and exit from a function. What happens inside the function is usually nobody else's business. You can violate it for a reason, there, if you make sure to restore it before returning.

The role of invariants is much like that of conserved quantities in physics. Things can get very complicated, but energy and momentum conservation mean the amount of chaos is strictly limited.

If they are kept as simple as possible, the code can be more easily understood, and has less scope for bugs.


Are you talking about pure functions? Like math, same input -> same output, no side effects / other state affected. Most programmers would recognize that term instead.


Long day, lots of driving, and then a two hour BJJ class, and then a Spanish study session. My brain is exhausted so this is a bit rambling, sorry:

No, they aren't talking about pure functions. Look into design by contract which brings this idea to the forefront. Invariants are properties that you state about a system that should always hold true over some portion of code. They are related to pre- and postconditions (which are more commonly understood and used, sometimes even explicitly, whereas invariants tend to be less explicitly covered by code).

Pre- and postconditions are properties that hold true before or after, respectively, some segment of code (often defined at function boundaries). Like that an input, even though its type may be int, should always be positive. That's a precondition, you can encode it into some languages, or you can cover it with an assert, or you can just "know" it (far more common). Postconditions are similar, at the end of the computation some properties hold about the returned value or the way that the state of the system has changed.

Some languages (SPARK/Ada, for instance) even let you prove that if some properties are true (basically preconditions become assumptions about the system) then your code will result in the postcondition being true (but not for everything you may want, they're working on pushing the boundaries of what can be proved). And if the system can't prove it, but you believe it to be true, you add other properties about the system or tell it to assume certain things that you may be able to prove by hand (or whatever) but not programatically. Or perhaps the systems proof reveals a problem where the computations will violate one of the conditions. Languages like Idris permit encoding many (most?) of these ideas into the type system which has its own accompanying proof system.

  int foo (int n) {
    // pre: 1 <= n && n <= 10
    // post: 1 <= result && result <= 10
    return n * 10;
  }
A prover (or anyone with common sense, short example, use your imagination for how this could be more usefully extended) can show that given the assumption of the precondition and the action of the code, the post condition cannot hold. In some languages, without the ability to prove it or even with, you may use asserts (often people disable these for "release" builds because they can be a performance hit, so hope your testing and code reviews are good):

  int foo(int n) {
    assert(1 <= n && n <= 10); // pre
    int result = 10 * n;
    assert(1 <= result && result <= 10); // post
    return result;
  }
Invariants are related to that, they are properties that should hold over some period (perhaps the entire program, perhaps just parts). A common application is the idea of a loop invariant. This is something that is expected to be true about the state of execution of a loop across all iterations. As a trivial example you may have a sorting algorithm (let's not worry about the efficiency of this, brain tired) and you have two indexes (quadratic time worst case). Your outer loop determines the lower bound of the next inner loop:

  for i from 1 to size
    min = i
    for j from i+1 to size
      if a[j] < a[min] then min = j // not a good sort, don't do this at home kids
    swap a[i] and a[min]
Then you have two invariants: The first portion of the sequence (from 1 to i) is sorted (it may not be the final elements in it, but it is sorted). This holds both before and after the swap. And min is always the index of the smallest value in the subsequence from i to size when we hit the swap. Like I said, this one is trivial, but it's about all my brain can handle right now.

You can also see invariants in the way abstract data types may be used. For instance, to use a simple example, suppose you had (for reasons) a structure called unitary_complex with these two fields:

  unitary_complex { real, imaginary }
We can establish an invariant: The length of this complex number will always be 1 (making it unitary). A reason OO languages often encourage the use of getters and setters (setters, in particular) is precisely to ensure that invariants like this are enforced. Raw access to the struct means that the responsibility to maintain the invariant is scattered across the codebase, everywhere that real is modified, imaginary may or may not need to be modified as well. So everywhere you use this you have to be aware of the invariant and maintain it, that's a great deal of complexity that gets introduced. And if somewhere you do:

  ui.real = 10; ui.imaginary = 20;
There is no stopping you. But if you have to go through a method (in OO languages) to modify it (for instance, you can only rotate the pair, math happens behind the scenes) or if the type is "opaque" (meaning outside its primary module and perhaps a few limited "friend" modules the internals cannot be seen or modified, like can be done in C and most languages, really) then you can contain the enforcement of the invariant in one (or at least fewer) place(s). Again, tired brain, use your imagination to consider any type that you may want to constrain by some property you want to always hold. Many data structures that you use in your everyday programming language have these kind of invariants (a set never has more than 1 of an item; a dictionary never has more than 1 of a key; a sorted collection is, well, sorted).

Invariants are sometimes "relaxed", that is there may be a portion of the program where it doesn't quite hold true. In a more complex example where you cannot guarantee a sequence of statements are executed atomically, you may only be able to declare something invariant at a point before or after the sequence (which makes it similar to preconditions and postconditions in some sense):

  total_cost = 0 
  bag = {}
  // invariant: total cost is always the sum of the cost of items in the bag
  // adding an item:
  bag.add(tv)
  total_cost += 1000 // only after this is the invariant true again
The invariant is not actually true at the moment between those two statements, which is helpful to recognize. In a concurrent system this suggests that we need some kind of control to ensure those two statements are treated atomically (they both complete together). In fact, this is the sort of "trivial" thing that TLA+ and similar systems can help you discover. For a real world case, I used TLA+ to show that the communication model between two processors using shared memory (it was the system architecture we had, not something we could alter) could permit, basically, a section to be marked "ready" (for reading) when it wasn't actually ready, which meant the reader could end up with garbage data. Nothing to do with pure functions, just defining invariants, preconditions, and postconditions and observing what the available actions could do (and in that case did) that would violate them.

https://en.wikipedia.org/wiki/Design_by_contract


PSA: The above DbC wikipedia page contains a link to the paper Applying Design by Contract by Bertrand Meyer which is THE paper to read to learn usage.


If you don't recognize the term as having a specific meaning in programming, it may be worth reading up. This[1] blog post has a great walkthrough of invariants.

https://reprog.wordpress.com/2010/04/25/writing-correct-code...


This is from formal methods, and while it is one way to specify your code, and contain unexpected behaviour, I wouldn't say it's the main thing in being a good programmer. Managing complexity in general is perhaps the main thing, so that you can do more complex things without getting completely overwhelmed by details.


I think outside of the formal logic space the concept of invariants still are core to programming. Many different strategies such as pure functions, unit tests, type systems, isolation of global state, all key really key around the concept that their are logical truths that always hold for a given program. This is a key way to build large complex programs. it’s impossible to hold every detail of what the code does, so having certain things be known truths goes a long way to enabling one to reason about code.


Invariants are among the most powerful ways to manage complexity, although of course not the only ones.

A type may be seen as a convenient packaging and naming of a collection of invariants.


[flagged]


What?


[flagged]


[flagged]


[flagged]


We've banned this account for breaking the site guidelines. Please don't create accounts to do that with.

If you don't want to be banned, you're welcome to email hn@ycombinator.com and give us reason to believe that you'll follow the rules in the future. They're here: https://news.ycombinator.com/newsguidelines.html.


I am not sure that I am good at programming. I am certainly not as good as the HN-type second generation SV kids who started programming at four.

Given that, I do work at a lucrative position doing cutting-edge work.

What made me get programming was- _getting hired_. I was so-so before.

When I got hired, the work was so challenging and the situation was so unforogiving, I had to grow. I had no other way. I learned new stuff, wrote code that inspired me, and was really "impossible" by me a few months ago. Sometimes, a few weeks ago.

What made me and and keep making me better than before is Hacker News and peers.

I want to get as good (from the first paragraph); grow as a programmer, grow as an overall problem-solver and thinker.

I keep learning new paradigms, new applications, gaining new knowledge, and growing as a person.

So the most important thing would be community. Before HN, Reddit. Now, Twitter and Discord, too.

I get to know so many new perspective, so many new resources to follow, books to read, stuff to generally know. I barely have time to breathe.

I also made some genuine, long-term friends through this process.

So, community would be the utmost important things.

I was born in a middle-of-nowhere small town, and community and internet are the ones that made me who I am today.

I am not much, but definitely levels above what I was a decade ago.

Edit: It would be incomplete if I did not mention high-quality teachers teaching for free through MOOCs, YT playlists, etc. And internet pirates, too. Having quick access to any book you might want is very important. (I do spend a lot on books, but piracy is what makes me spend that money so that authors get what they deserve).


I wouldn't say I'm a top notch programmer by any means, but one thing ironically that made be better is to take a step back for a while and stop programming and try to learn, read and understand things better. This doesn't work unless you've been programming for a bit and have some hands on the basics, but it does help to break bad habits.

Stick with standards and conventions, even if they seem stupid. Just do them. Four spaces in python, that sort of thing. Pretend they're rules of the language, pretend that not following them will break your program.

Try to understand data types and structures, they're vastly more important than programming. Knowing how to write code, syntax, libraries only helps you if you understand the data you're manipulating, what you want to do with it, and how it is best structured for your purpose. You're better off knowing about data structures and not knowing a single programming language than the opposite.

Finally, build things, solve problems. If you want to do something, do it. Don't worry about if you're good enough.


I don't believe I can prioritize these between more or less important things, but this is the set of things that I usually credit:

* Programming competitions. The main utility I got out of this wasn't learning obscure data structures or algorithms (which tend to often not be very relevant), but rather the experience in coming up with corner cases that might break my own code, and how to write and debug code without sitting in front of the computer. I guess in short it's the ability to separate the algorithm from the implementation and track down failures to one or the other.

* Going to school and getting a CS degree. Learning in general is useful, but I believe that the structure of a full CS degree is generally better than picking things up ad-hoc, especially in guiding you towards areas you wouldn't otherwise think to learn about (e.g., I wouldn't have picked up information visualization on my own).

* Seek out and learn as much as you can in general. You never know when randomly learning some topic in some distaff field might come in useful; one time, I happened to discover (while looking up information on ptrace in a debugger-like side-project I was working on at the time) that Linux supported hardware watchpoints via perf... and a few days later, we had to resort to that to track down a bug that wouldn't reproduce in gdb.

* Peruse other projects for how they do stuff. Part of the above, but you'll pick up on "huh, that's an interesting thing to do" as you learn about how they work. If you're curious about how something works, just open up the source code to see how it works. At the very least, doing so frequently will give you a good sense of how to quickly find stuff in large, unfamiliar projects, which is apparently not as common a skill as I take it to be.


1. Having a passion project that made it easy for me to sustain lots of hours of coding as I strove to complete the project.

2. Reading widely in the coding literature, from personal blogs to engineering blogs to O'Reilly (etc.) books, to "philosophy" stuff like Bentley's Programming Pearls

3. Regular LeetCode. Not grinding exactly, but disciplined practice of solving specific, short challenges.

4. Browsing OOP (other people's programs) on github and such.

I'm curious to see what others post!


My first real experience programming was when I was 19, before ever having a class, teaching myself PHP/JS on the job to write custom wordpress themes. I started writing inefficient spaghetti code and progressed into writing object-oriented, then started looking at performance. The performance aspect was definitely the deepest rabbit hole.

I would say that I learned more doing that than I have getting a CS degree at my state school (aside from writing performant code, which classes have helped with). But it is mostly because I viewed getting good as a way to escape from some bad circumstances at the time - every word I didn't know was a low-hanging fruit waiting to be picked. I did a lot of reading, and I practiced at home in my spare time as well.

I got really good at front-end stuff and learned how to use the terminal so that I could host and manage our company's websites on a digital ocean droplet (running centos). I learned a lot on the linux terminal - writing bash / shell scripts, managing configurations, etc. Improved speed a lot by configuring apache... then again by redoing things in Nginx on the next site, which I've preferred since.

Since I've gone back to school, going overboard on programming labs has also helped a lot.


- A lot of practice, which stemmed from a lot of fooling around and abandoned side-projects. I would deliberately start projects which were way over my head, with no intention of even getting something working, just to see how far I could get before getting bored.

- Learning new languages which had vastly different paradigms than the ones I was used to. Java to Perl to Javascript to PHP to Erlang to Clojure to Go to... Over time you learn patterns from one place you can bring to another, and learn patterns which exist in most places which you'd rather didn't.

- Lots of experience in the actual workforce, building things people (supposedly) wanted. There are aspects of programming which people spin their wheels on which really don't matter in the long run, and conversely there are aspects which go ignored but are very important. Working on real, rubber-to-the-road projects gives you perspective on what actually matters.

- Being a daily archlinux user (I don't use any non-archlinux OS on any machine I own). Yes, it's hard. Yes, it's an incredibly good use of your time to figure out. Once you're comfortable in arch, every other Unix-like OS (ie, most of them that you'll ever probably work with) will feel familiar.


I've been at it for a bit over 20 years and I haven't figured out how to get good at it. I do OK, though, because I learned it's often more important to ship than perfect[0], and rewriting isn't so bad because the second time is usually better than the first.

0: I choose not to work anywhere that sells critical infrastructure, medicine, or anything else where imperfections could jeopardize someone's life.


18 yrs doing this and I feel exactly the same way. I just love building things on my free time even if i know some of them won't make it out of my dev environment simply because i work too slow. I guess to me, the discovery process (in building something new) is so much fun than say, playing video games.


I have no clue who you are but from reading your answer, I bet your coworkers love working with you and I bet you write nice maintainable code. You are probably better than you think.


That's very kind of you to say.


Make something from nothing. Trying skipping out on a project starter-template. Try compiling it without your IDE. Try writing the SQL. Not with the intent of saying "this way is better" but with the intent of feeling what is done for you, so that you might control it when the time comes.


I presume, a large number of problems to solve through coding and a passion to solve them...


Not sure I am good at programming, but I would list the following:

Programming, a lot. And I would add, staying on the same project for long enough to get the pain from your mistakes.

Working alone, because it prevents "easy help" and forced me to dig hard on some problem that needed solving.

At the opposite side of the spectrum, having super rigorous colleagues that did not mince their words and explained and asked me to redo work multiple time if needed (I only had that for a few months but I think it was a turning point).

Practicing multiple languages and shipping something with them.

Building a mental model, I consider that software engineering is 90% a communication exercise towards colleagues or your future self.


I had a really good mentor for many years. He was my manager starting back when I was in high school, and he was always working with us to improve our code. He recommended good books and articles, put in place systems of formal code reviews that emphasized egoless programming, so we could review, learn about, and improve our code without feeling threatened. He helped me think about the code development process and how to be constantly improving it.

He helped me establish many good habits that helped me to grow throughout the years. More than 3 decades later we are still good friends.


Access to a programming environment with good discoverability, and reasonable examples of working code that I could tweak. Back when I learned, examples abounded in print material, and print documentation tended towards complete. (Especially Turbo Pascal's manual)

This made it possible to experiment, and get started. Since then it's a matter of repetition, deliberate practice, and raw experience over time.

Everything has scaled towards good thanks to Moore's law, the Internet, and GIT. You can't overstate how much better git makes things.


* I read a lot of technical books. Designing Data-Intensive Applications was a favourite. I dove deeply into technical books on the language I was using at the time - C/C++. That knowledge carried over to other languages I later learnt.

* I read a lot of non-technical books. Don't underestimate how beneficial it is to expand your general knowledge. Be open to new ideas. Engage in discussions with people, but don't be arrogant. It can be tempting to think you know everything, especially when you read a lot. Books can teach you a lot about the human condition, helping you connect and collaborate better with others. Ultimately to be a good programmer you need to be able to work with others.

* I was genuinely curious and played around with Linux a lot at home. I got pretty good at writing bash scripts. When shit hits the fan, being able to bang out a bash script to quickly fix some data issue can literally save the day. Also knowing where things live on Linux can be super helpful when debugging services, or just getting your dev environment set up.

* My first graduate role was doing mostly C, as well as C++ on fairly barebones Linux devices. Knowing C, understanding memory allocation, concurrency (mutexes, semaphores), man I can't overestimate how useful that has been. Having this understanding means you're just way ahead when you need to learn another language. It all carries over.

* Don't neglect the human/social aspect. Be the kind of developer people love having on their team. Be generous, be kind, be humble. A smile can go a long way in this world. You'll be paid back many times over.


The top one for me has been to try working with as many technologies as possible. Do something in every environment you can – write some C, some Ruby, Python, Java, Swift, Typescript, C++, Haskell, Rust, Objective C… whatever you can get your hands on. Every language and framework you use—even if just for a minor project—will expose you to a set of new ideas, idioms, and APIs. After a while you start to recognise all of the different patterns, and understand how and why they work in the way they do. I think this is effective if you're the sort of person who learns more effectively from practice than from research.

The other one is to always be thinking about that well-known Torvalds quote:

"Bad programmers worry about the code. Good programmers worry about data structures and their relationships."

We often think of "programming" as "writing code" - but that's really just a tool to an end, and the best code is the code you didn't have to write. Approaching problems by thinking about the shape of the data you have, what you want it to look like, and the relationship between these things sometimes feels like a superpower. The code is just the annoying bit in the middle that helps you do all that stuff.


Probably starting with my Atari 400 back in the 80s. There was no internet and any low-level documentation was hard to come by and readily shared with the few others with the same system and interest. All this is to say that I learned to dig, learn, and figure out stuff on my own, trying, failing, and keep going until I got something I was satisfied with. The other interesting thing is that the computer was over my budget so my parents only bought me the BASIC cart and Asteroids, but no storage of any kind. That meant that I would code for a couple days, never turning the computer off and when my program was done and I'd played with it long enough, I'd get bored and want to play Asteroids. That taught me not to get too attached to versions of programs I wrote. The next version was of course better, and I got faster writing them.

After going through this process, anything after like school courses, university, co-op terms, learning C, using compilers, doing low-level firmware development all seemed like natural continuations. I'm also always seeking novelty and new ways of doing old things.


A little late to the party here, but here's my list:

- Leetcode, my DS & A courses in college weren't particularly rigorous. Only by doing 300 LC problems to prep for interviews did I begin to feel competent with DS & A, and I still have a lot more niche stuff to learn like Red Black trees and KD trees.

- Pay attention in college classes! Certain classes I took in college are core parts of my computer mental model that I think about every day. Especially operating systems, hardware + systems fundamentals, programming languages, and obviously DS & A.

- Generally most of the work that is done these days is in web dev, so be sure to do a bunch of web dev personal projects, ideally substantial apps. If going into another area then be sure to get good at that, like do some RPi stuff if you're trying to get into embedded.

But above all else, the number one thing that made getting good at programming easier was being genuinely interested in the subject matter. My classes and projects never really felt like work to me. If you hate computers then you're gonna have a bad time.


* reading other people's code

* studying algorithms

* experimenting with different solutions

* learning paradigms, methodologies and best practices

* striving for simplicity

* being curious about how things work

* systems thinking


Writing lots and lots and lots of code.

Being really interested and motivated to write my own projects.

Learning everything I possibly could about every topic I found interesting relating to computing ans software.

Focusing my effort on a small selection of technologies.

Making the decision to be able to build an end to end application on my own.


Avoiding taking sides in religious wars and understanding there are no solutions, only tradeoffs.


Umm how do you define "good" at programming?

1. Is it the fast promotion cadence in a non-faang job? 2. Fast promotion cadence in a faang job? 3. Confident that you can learn a new langauge/stack/tool/algorithm easily? 4. Confident that you can implement a language/stack/tool/algorithm (with enough time)? 5. Passion to actually do #3 and/or #4?

I have always sucked at #1 and #2 but have constantly been deep on #5 (id even say i "waste" enough time doing this that I neglected coding at work so ended up switching to management). I really envy the folks who can only code for a living and not be bothered about wanting to do side projects.


1. Taking a CS course so that I was incentivized to cross the threshold into "real" algorithmic problems. Once you have a few basic CS concepts in your tool belt, you can tackle the majority of programming tasks; it's just a matter of grinding through the specific system you're working on to spot where the concepts apply.

2. Reading, debugging, modifying source code. Reading is harder than writing, which means that it's good practice: "why is this hard to read? Is it necessarily hard, or is it something about the implementation?"

3. Taking less advice from random blog posts. When I started getting good in the 2000's, it was quite a thing for developers to self-promote by making cookie-cutter blogs about OO pattern du jour or "code katas" or something. Today YT content probably does the same kind of thing with new fads. When you cut through it, it mostly isn't technical knowledge, it's sophistry. You don't want to restrict yourself to "never view this stuff", especially not at the beginning where you're looking for a branch to cling to, but you do want to locate it in a place of pop culture and fashion relative to the actual problem-solving work.

4. Doing things two or three times in different ways. This is a way of testing whether advice is good. In work you may not get the chance to, but as a side project, you can try doing things with different styles of coding and seeing if one way is harder, substantially reduces your error rate or SLOC, etc.

5. Applying logic and philosophical thinking to coding. To do task 4 properly you have come up with success metrics. What makes code successful, and what makes it fail, and can you encode those things as a rule for yourself? If you can encode it as a rule for yourself, can you then automate that rule so that it is enforced by definition? The better your critical thinking is, the more you can work through these entanglements. Both math and philosophy can spark some ideas towards this end, as well as plain old life experience.

Programming can be both satisfying and frustrating: when you're able to apply the basic concepts well to solve something it almost always feels great. When you have to deal with things other people built, it's almost always frustrating.


Which cs course(Point 1)?


In order of impact:

1. Programming. Lots and lots and lots and lots of programming.

2. Having my code reviewed by people with strong opinions, some of which I agreed with and some I didn't.

3. Reading, and practising what I read (number 1 above).


A lot of reading. I started programming when I was in high school, but procrastinated hard on making project. So I read a lot of books about C, assembler, network, security, operating systems, algorithms. When I started doing projects in university, everything I did made sense conceptually. To this day, when I'm doing project, I can go left and right on the slider [Abstraction----Implementation], very easily, from the architecture of the whole systems, and the gritty details of the particular language and algorithms.


its gonna sound crazy but... practice.

i made toy apps and widgets. chrome extensions. took on a bit of client work.

read some books.

stay up all night and hack on projects for a few years while people are sleeping and youll get some where.

never had a sideporject or 'startup' that actually made money, but thye taught me the skills i have now that are paying the bills, and i pretty much have my pick of jobs at this point.

but also suffer from extreme impostor syndrome and try and use that to fill my (perceived) gaps


Use an IDE that lets you follow stack traces into library source code easily. You learn a lot from going down the rabbit hole... ... when you have time to do it.


Practice, lots of practice. Doesn't really matter what kind of program you write as long as you write code. Can be assignments from your university, can be online puzzles like advent of code, can be a program that sends you reminders to kiss your wife, can be the 984397594th minecraft clone, or whatever else you want. Basically if you have a problem that can be solved by coding, do that.


* read all of the docs if possible, but know that they are never complete

* read the source /framework code, if available

* tests and examples are not optional documentation. They will always tell you things that were forgotten in the docs

* reading docs without actually writing code won’t help until you’ve spent a long time with the code. You have to write your own examples while you were learning



I've just been programming a lot since I was about 10 years old. Persist in doing anything for 25 years of your life and odds are you'll get decent at it.

I've never deliberately practiced or anything like that, just built stuff that I wanted to build.


Finding a side project. When I was 16 I wanted to make a bot for a 2D multiplayer Flash game. I learnt so much on so many concepts: network libs, packet parsing, some design patterns, reverse engineering… you can’t beat first hand experience.


Reading other people's code (both good and bad), realising how it affected my use of that code, and reflecting on what I should learn or do in order to master or avoid those patterns respectively in my own code.


Reading the manual.

Taking time to read docs and "learning" to read docs (awkward output of various auto-docs tools) has helped me crack programming right from my early days of PIC microchip data sheets


Consistency and strong goals that align with your needs.

Getting constant exposure to cutting edge tech so you have a delta between what is possible and what you can build.

Shrink the delta by building such a thing


what helped me get good?

well I wouldn't say that I'm good. I'm better than I was, sure but "good", man, I dunno. I've been told I'm good but those people were being nice to me so I can't trust what they say.

to get better: do more of it. come to your own conclusions about what works. read other's opinions, and ignore them mostly, because what sounds good when described is rarely actually good when implemented (see: object orientation).

put the hours in. there is no shortcut.


Anything you persist in doing you will get better at. So, I got better at programming by programming. So what if your code sucks today. Keep programming and it will get better.


Find a project you want to build and stop at nothing until it works. Repeat. Caveat: pick things that are just beyond your current level of knowledge.


When you begin programming, all of your problems will be of the form "how do I get my program to do X?" and all of your answers will come from stack overflow or similar. You will build things by example, and that's fine: in fact it's great for your motivation because you'll be able to achieve some impressive things, so definitely don't try to skip this step!

But at some point you won't be satisfied with just doing things that other people have already done before, or you'll want more control, or be unhappy with some aspect of the approach people before you have taken. Or maybe you'll just be curious: "I know this code let's me draw a circle... but how exactly does it do that?".

At first, this will be hard because the "how" is often quite complicated. You'll have to force yourself to understand a lot of things that previously you didn't, but you'll also see why certain things you've tried in the past didn't work. This is where you learn the difference between what is easy and what is hard. You'll start to properly plan a project out before just diving in.

Later, you'll get used to processing the complexity of "how" things actually work behind the scenes, and then a strange thing will happen. Instead of seeing complexity and thinking "that person must have been a genius to come up with that", you'll see something and think "wait a minute... what idiot wrote that".

You'll suddenly find that every codebase you dig into is a steaming pile of garbage under the surfacce, and you can't bear to build anything on top of it. Congratulations, you now have NIH syndrome! You'll try lots of different languages, technologies, etc. and although they'll all be a disappointment in one way or another, you'll learn a ton in the process.

After that, there are fewer dramatic step-changes. It will just be several gradual changes:

- Some (although definitely not all...) of those things you thought were garbage turn out to actually be well motivated.

- Your focus will shift from the code itself, to more abstract engineering ideas. The coding part will just be automatic at this point, but you'll be thinking about things like backwards compatibility, ease of use, scale, performance, etc. more and more.

- Motiviation will be a bigger problem. You'll have the mathematicians problem of knowing in so much detail how to do something that actually doing it is just... uninteresting.

The only way to progress through all of this is to keep programming, keep reading other people's code, and keep learning.


Test Driven Development. It forces you to write simpler, cleaner code in order to better test it.


Getting paid to do so.

Being able to be choosy where I do so.

Follow your instinct, build things, read, write, repeat.


Getting an internship at a company with solid engineering culture.


Supporting & evolving my own code/projects for years.


Still trying to figure out how to get good at programming.


SICP has timeless advice that I follow: Write programs.


getting a job where I couldn't shirk programming duties and being forced to program every day for at least a year to meet deadlines


I was never good at practicing for practice sake but I also know of the value of "doing the work" to get better at a skill.

So, I become a better programmer when I'm actively working on something. I no longer contribute code on a regular basis at my day job so to stay sharp I've started creating little utility programs for personal use.

I've also started finding hobbies that incorporate some programming, generative art, robotics, etc.

tldr; find ways to incorporate programming into everyday life, practice by building things that are actually useful to you.


Time and self awareness.


Coding and more coding


starting my own company and doing everything by myself


programming a lot


programming


I’m not sure that I’m “good” at programming yet, but I am growing. I think it’s important to know that there are always new things to learn, even if you think you’re pretty good at something.

I love the community. There are so many people who are willing to help others learn, which is really inspiring. I think it’s because we get that everyone starts somewhere, and we all want to grow our skills and help others do the same. There are also tons of resources online for learning new things—a quick Google search is all you need to find a tutorial or a YouTube video that can give you the information you need to move forward.

Last but not least, my mentor has been an invaluable resource for me as I started learning about programming and software development. He has a lot of experience in the field and he’s been able to answer any questions I have about what it’s like working as a developer in the real world. He also gave me some great advice when I was starting out, like making sure to keep up with current events in tech and reading blogs written by developers with more experience than me.




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

Search: