Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: The Required Fundamentals for Self-Taught Programming
55 points by LunarVB 55 days ago | hide | past | favorite | 49 comments
I have been wondering which programming fundamentals are needed for using in real projects and the fundamentals in computer science needed. I already can read code, but don´t know how to apply that effectively. Any suggestions? Like books and resources?

If you really want to learn programming.

1. Buy SICP and put it on your book shelf.

2. Don't read it, instead read random StackOverflow posts talking about the content.

3. Spend the next 10-50 years trying to understand what people are talking about on various related forums.

4. Add more legendary books to your shelf over these 10 years, like The Art of Computer Programming. Fawn over their greatness. DON'T READ THEM.

5. Go on long walks, take spirit journeys to harsh natural locations, put your life in danger while you meditate on the concepts.

6. Blog profusely about your experiences.

7. Optional: actually write code.

Feeling slightly called out right now

Data structures and algorithms. I don't have a formal education either but after 25 years of programming, IMO everything boils down to data structures and algorithms - the former more so than the latter. I think everything else comes from experience gained from on the job training because you need to train the pattern matching part of your brain. A good foundation in data structures and algorithms simplifies that process a lot.

Data structures are how programmers describe reality in the Wittgenstein/Sapir-Whorf sense and they shape our understanding as much as we use them to encode it. The right data structures drastically simplify problems and the wrong data structures turn them into nightmares of bugs and spaghetti code. Database schemas are the natural extension of this at the application, rather than module, level.

I don't have a specific recommendation because data structures is such a broad field, but an MIT OCW data structures and algorithms course is a good place to start. Oh and the book Designing Data Intensive Applications for a higher level overview of how data structures and algorithms are used in the field.

> ... IMO everything boils down to data structures and algorithms - the former more so than the latter. ...

And from Fred Brooks...

> Representation Is the Essence of Programming

> Beyond craftsmanship lies invention, and it is here that lean, spare, fast programs are born. Almost always these are the result of strategic breakthrough rather than tactical cleverness. Sometimes the strategic breakthrough will be a new algorithm, such as the Cooley-Tukey Fast Fourier Transform or the substitution of an n log n sort for an n2 set of comparisons.

> Much more often, strategic breakthrough will come from redoing the representation of the data or tables. This is where the heart of a program lies. Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious.

Brooks Jr., Frederick P.. Mythical Man-Month, The: Essays on Software Engineering, Anniversary Edition

Replace "flowcharts" with "code" and "tables" with "data structures" (or leave it with "tables" for a database centric view) for more modern terminology.


I would also reminded of Algorithms + Data Structures = Programs by Wirth... which in turn brought me to his quotes.

> "Good enough software" is rarely good enough. It is a sad manifestation of the spirit of modern times, in which an individual's pride in his or her work has become rare.

Craftsmanship is something that is lost. It's written and it's someone else's problem once it is deployed. Be that a "its operations problem now" or "this contract is done, the next contractor will need to deal with it."

The third virtue ( http://wiki.c2.com/?LazinessImpatienceHubris https://news.ycombinator.com/item?id=39385228 ) of programming is often forgotten and lost.

> Hubris: Excessive pride, the sort of thing Zeus zaps you for. Also the quality that makes you write (and maintain) programs that other people won't want to say bad things about. Hence, the third great virtue of a programmer. See also laziness and impatience. (p.607)

+1 for learning datastructures + algorithms in a structured way.

Other posters are saying "just build stuff and you will learn", which isn't wrong, but there's a reason every CS student learns data structures and algorithms first. They are literally the building blocks for everything else. Then, once you've got that foundation, the "just build stuff" advice is sound but if you skip that step you will always be at a disadvantage.

DDIA is a great book but definitely not for a beginner and is only applicable to backend web engineering at a certain scale.

Do you know of a more beginner friendly book?

For algorithms, I would recommend "Grokking Algorithms" by Aditya Y. Bhargava. The reason is that the book contains hand drawn visualization. I believe this will make the beginner easier to learn the concept.

One more thing, if you learn programming. Don't forget to practice, practice, and practice. The book has exercise sections. Please, don't skip it.


The traditional reply is complete either of these books and you'll be further than even an average Comp Sci BA:

  - Structure and Interpretation of Computer Programs
  - How to Design Programs (easier)
In reality, it strong depends on your specific domain and how old your company is. Doing embedded projects at home vs. quickly prototyping systems in Ruby vs. modifying an API for a large SaaS vs. lowering latency for trading vs. ensuring compliance at a bank... The demands are all very different, yet generally we don't write algorithms or implement data structures too often. Our languages and libraries typically offer optimized versions, we just have to know when and why to use them. And after it's built, adding extra features won't change that model.

The way everyone actually learns is by doing many projects, like an apprentice of old. Such a book could interest you (after) though: https://aosabook.org/en/index.html#500lines

I will see that book, thank you!

You need problems to solve, but most importantly, problems that are highly relevant to you and your interests so you won't give up easily if they become unexpectedly difficult.

You'll be forced to learn new approaches, new tools, perhaps even new languages to solve these problems if they're challenging enough, and don't worry, you'll almost always assume something is easy when it turns out to be a lot harder than you could ever imagine.

Get exceedingly good at breaking down difficult problems into smaller steps you can actually achieve. Try and estimate how much time these steps will take so over time you can get better at estimating how much work is involved in something, which can inform which approach to take or which tool to use.

Above all else, when you learn something and want to know more, learn both in terms of deeper fundamentals, but also in a more strategic sense, like how it is applied, and what are the ramifications of this knowledge, how it fits into the bigger picture.

Remember, it's abstractions all the way down, but also all the way up!

> ... so you won't give up easily if they become unexpectedly difficult.

Find the Hard Work You're Willing To Do http://www.cs.uni.edu/%7Ewallingf/blog/archives/monthly/2018... ( https://news.ycombinator.com/item?id=26209541 )

The final two paragraphs of the essay (from a university undergrad advisor in a CS department):

> Maybe this is what people mean when they tell us to "find our passion", but that phrase seems pretty abstract to me. Maybe instead we should encourage people to find the hard problems they like to work on. Which problems do you want to keep working on, even when they turn out to be harder than you expected? Which kinds of frustration do you enjoy, or at least are willing to endure while you figure things out? Answers to these very practical questions might help you find a place where you can build an interesting and rewarding life.

> I realize that "Find your passion" makes for a more compelling motivational poster than "What hard problems do you enjoy working on?" (and even that's a lot better than "What kind of pain are you willing to endure?"), but it might give some people a more realistic way to approach finding their life's work.

Got it! Thank you!

I’ll add to the comments: Whatever you decide to do, don’t be too picky. Choose something and get started. In the begginig avoid lengthy courses or books; start with something small but read it to the end. Be patient and consistent, and don’t rush. Also I would recommend to watch a youtube video: Harvard CS50 (2023) – Full Computer Science University Course

Build projects and ship them. There's no better way to learn.

That could mean web applications deployed online, or CLI tools that people can install, or data science projects that result in a report you can show people, or mobile apps shipped to an App Store.

The key thing is to build actual working software, and ideally to get that to a place where other people can try it out. This will help you learn SO much, and will make it a whole lot easier to attract the attention of hiring managers as well.

Agree 100%.

I’ll add: build whatever interests you

The project you’ll work on will teach you more than the one you abandon.

Some of the most random things I’ve done purely out of curiosity, which were objectively not valuable at the time, have paid dividends decades later.

Like writing AOL chat room bots in the late 90’s and accidentally learning a lot about the Windows API.

Looking for fundamentals to get you ready as a self taught programmer is going about it in the wrong direction. Pick something you want to do and go do it. When you run into roadblocks try to figure out how to solve them and when you get too stuck then ask the question "what are the required fundamentals I'm missing in order to solve this problem".

You'll find you will rarely need to ask that question, just keep solving problems and learning what you need to know for that problem. You'll build good experience and though that experience you'll learn a lot.

Im self taught and worked with CS majors as well as other self taught ppl. Maybe stating the obvious but its interesting that CS majors begin with fundamentals and work up to abstractions while self-taught people begin with beginner-friendly tools like nodejs then spend the next decade peeling back layers to learn all the inner workings of tools they used since day 1. Lots of prototypes kept me interested and built a habit of working on personal projects daily.

SICP was helpful in peeling back abstraction layers but I lost interest a quarter of the way through. I found The Rust Programming Book[0] really approachable coming from a nodejs background. Rust's compiler is so helpful I learned more about CS just working through the exercises and making mistakes. Rust really holds your hand but the book describes all of the "why" behind Rust's memory safety. Completely changed how I structure programs. After the Rust book I dove right into personal projects in Swift and fundamentals I learned in Rust translated very well.

[0] https://nostarch.com/rust-programming-language-2nd-edition

An entire CS curriculum from the beginning starting with fundamentals is particularly hard to follow by yourself and not particularly rewarding. Some people could do that but most would lose interest in the theory and never end up anywhere. It's the kind of thing that needs structure which not many people are going to create for themselves.

Interesting, thanks for the tip!

I would describe the minimal stack for self learning programming as the following:

1. Genuine interest

2. Ability to focus/concentrate and overcome frustration (there will be plenty)

3. Understanding of the basics: conditionals, iteration, functions and function calls, variables, basic input/output in any form. I would add on memory/pointers here, as understanding it will greatly improve your comprehension of what's going on even if you use a language that attempts to abstract that away.

It's worth finding a tutorial on these and do as many exercises as necessary. I'm not going to recommend any specific language as I think they all are bad for beginners in their own ways. You need not concern yourself with practicality or popularity of the language you pick though as your focus is on the basics. These skills are transferable, important and yet a tiny kernel of all your future progression. Then you'll be able to combine these basics to build some simple programs. Print a string backwards, guess the number, guide a cursor on a canvas by keyboard or similar.

From that point you can branch out to explore and comprehend actual CS concepts, and start with writing small practical applications.

Just write code.

I started writing minecraft plugins[0] and now I can write software as low as ioctl firmware and as high as web development. The more you write the more patterns you will start to notice and the better you will become.

Do not seek answers, do not seek solutions[1]. Stack overflow and guides are your enemy (documentation is fine[2]).

Want to learn x86 assembly? Throw a random exe (notepad.exe) into x86dbg (or CheatEngine) and start debugging[3] from the beginning. See what each instruction does and how it affects the hardware registers. Look at it long enough and you will start to understand assembly and be able to write it.

Programming is special for me - I was the dumbest person you could find as I even struggled with basic multiplication at school, but with years of programming I've also noticed how I've started doing much better at school without putting in the extra effort usually required.

So in the end - just write code, see where it takes you. Follow your interest and see where you end up.

[0] With no education, no knowledge and a slow computer with a free eclipse IDE. The only guides I ended up using the most were on how to setup bukkit plugins in eclipse.

[1] For specialized software, otherwise try to figure out what the library does that you want to use yourself by looking at what it does and how it does it. Finding out how to use any kind of particular software is typically fine, but it's better to play around with it and figure it out yourself.

[2] Unless you're reinventing a wheel (don't invent a sorting algorithm).

[3] Single-step program entry-point until the application is running and you notice a repeating loop.

If you can already read code... just start a small project of your own, I would say. Pick the language you are most familiar with and create something. Be patient, learn as you go. Learning to code requires a lot of time and dedication, but it is a good experience!

What is your language? Maybe people here could give you ideas of a good first project to try :-).

I hope the OP is okay with me getting in on this.

I just picked up _Learning Go: An Idiomatic Approach to Real-World Programming_, 2nd ed, based on its positive reviews. I'd like to read it and create a small project (for example, a simple backend for a personal website).

Any other suggestions for a good Go project?

When you get started, make sure that the project interests you. The language doesn’t matter much because if you keep going, the code will embarrass you in six months anyways. The project itself doesn’t even matter much as long as it interests you.

If it interests you, you will want to work on it and the initial (extremely frustrating) steps will be more joyful and fun. You will still get frustrated and likely be embarrassed by the project within six months, but that only means two things:

1.) You kept going (which is most important).

2.) You got much better (which is great news).

Otherwise, be gentle on yourself.

Alex Edwards' Let's Go and then Let's Go Further are already sufficient, honestly. You'll built a simple backend and go way further quickly with them.

My first language that i was taught is C, i tried once making something with Arduino but i didn´t went too far with it.

There are so many books on learning a programming language, that I'll ignore that topic.

Someone else mentioned data structures and algorithms. Algorithmic complexity is particularly important. The Algorithm Design Manual is a great book in this space.

As a low level developer, I've also found the following topics way more useful than I expected:

- Finite State Machines (These are the basis for everything from inter-device communication protocols to simple video game AIs.)

- Binary arithmetic and boolean logic (Rarely relevant, but absolutely essential for diagnosing certain types of parsing errors, buffer overflows, etc.)

- The Halting Problem and P = NP (Useful when a manager tries to get you to do something that is actually impossible.)

I learned these from intro to Computer Science classes in university, but honestly Wikipedia is probably a good place to start. I think the (middle grade) book Lorem Ipsum also covers most of these concepts.

The absolutely most fundamental thing to master is to read books about the concepts, practices, histories and philosophies of the craft.

It's become very popular to learn how to assemble code by following step-by-step tutorials and watching YouTube demonstrations. It does get the job done for a lot of people, but it usually doesn't develop very strong or deep foundational knowledge. As a result, people who don't make a point to leave that world generally end up stuck under a low skill ceiling.

So whatever suggestions you find in other replies here, favor books (and perhaps deep courses) over anything more shallow. And among those books, favor those that are heavy on prose and explain things over those that just guide you through doing things. And then when you get the books, sit down with them and really work through them.

How to be a Programmer by Robert L. Read (and expanded by the community) https://github.com/braydie/HowToBeAProgrammer

It is a collection of short essays on particular skills that are applicable to programmers of different levels.

The introduction starts with:

> To be a good programmer is difficult and noble. The hardest part of making real a collective vision of a software project is dealing with one's coworkers and customers. Writing computer programs is important and takes great intelligence and skill. But it is really child's play compared to everything else that a good programmer must do to make a software system that succeeds for both the customer and myriad colleagues for whom he or she is partially responsible. In this essay I attempt to summarize as concisely as possible those things that I wish someone had explained to me when I was twenty-one.

I will also point out that "How to debug" is the first thing in the list. It starts out with:

> Debugging is the cornerstone of being a programmer. The first meaning of the verb "debug" is to remove errors, but the meaning that really matters is to see into the execution of a program by examining it. A programmer that cannot debug effectively is blind.

> Idealists, those who think design, analysis, complexity theory, and the like are more fundamental than debugging, are not working programmers. The working programmer does not live in an ideal world. Even if you are perfect, you are surrounded by and must interact with code written by major software companies, organizations like GNU, and your colleagues. Most of this code is imperfect and imperfectly documented. Without the ability to gain visibility into the execution of this code, the slightest bump will throw you permanently. Often this visibility can be gained only by experimentation: that is, debugging.

My first programming language was assembler. From the outset that completely removed the shroud of mystery concerning “what happens under the hood.” To this day I am convinced that it was an important step in and of itself, and I also believe that knowing how data structures are represented in computer memory helped me a lot. The rest (C, then C++) were a breeze. I know, “computer science has as much to do with computers as astronomy has to do with telescopes,” but there’s a good reason for Knuth’s choice of the language for the analysis of algorithms, and I have a suspicion that had I started with something like SICP I’d be scarred for life instead of enjoying what I do.

I echo others: follow your nose. Build things. Find an open source project that interests you, pick a low hanging bug, fix it. Do it again. Work on harder issues. Try implementing a requested feature.

Start a greenfield project. Something that isn’t huge in scope. A basic text editor, a mini redis clone, an asteroids game. Try something harder for your next project.

Theory-wise I think type theory is a good start. Along with with Software Abstractions; a great book on the design of software systems using formal methods. And a book or two on data structures and algorithms. Discrete maths essentially and combinatorics. That will get you far.

My suggestion would be to experiment with languages until you find one that you like more than the others and replicate the functionality of someone else’s software. Free yourself of the need to come up with a good idea.

If you choose a language that’s not widely used or no one is hiring for, don’t worry about it. You’ll find that the concepts you learn in any language are portable to all languages. Once you learn those, it will be easy to pick up new languages when you need to.

Bonus advice: when you find a language you’re good at, stick with it and get really good at it.

If you can get access to ChatGPT, use it as a learning resource.

Ask it to act as a mentor that is teaching you how to program, ask it to give you an problem to solve, and give it a shot.

Then paste back your code you wrote (keep it simple) and ask it to explain your approach, provide advice, describe patterns, and explain tradeoffs between different techniques.

Initially, learning how to talk about code is important, then identifying patterns and approaches.

Coding isn't about memorizing things, it's about understanding the advantages and disadvantages of different approaches.

Have fun!

I see, thanks!

The fundamentals are a voracious appetite for trivia, and a temperament suited to debugging.

Plus a certain amount of raw intelligence, but less than many people think. If you're asking, you've got that one covered.

The temperament, though. Can you spend hours to weeks trying to find the stupid and obvious thing you did wrong, and feel good about it afterward? If so, welcome to programming. Enjoy your stay.

Start by just learning Python. It's how I started 15 years ago. It's how my wife started, with https://programming-24.mooc.fi/ , and how she got into computer science as her current college major. It's still the best general purpose thing out there.

I'm also a self taught programmer, my first book about programming was "Automate the Boring Stuff with Python", then I tried to learn C and I didn't understand anything of what I read until I find "Introduction to Computing Systems" by Yale Patt and Sanjay Patel, great book.

Edit: also did 200 Codewars katas to practice, then started to build things.

If you can read the code next step would be to start writing the code. Write a code of the program that you are interested in and it does not really matter which kind of program you will develop. If you are interested in learning more about fundamentals (which is really good) you can do that in parallel to writing the code.

Use python to build things. Make sure you can deploy them to AWS and actually use them.

Use c to build some very minor things, so you can get a better feel for how memory works.

Don't build any mobile apps, you'll go down a rabbit hole. Don't worry about algorithms or any theoretical books for at least a year.

teachyourselfcs.com has a neat collection of textbooks for CS fundamentals.

Though, these fundamentals are more theoretical (though worthwhile). You may want to just build a couple of things first to get some muscle memory.

No need to finish them, as long as you make it over a few hurdles before you move on.

I will give a try, thanks!

To answer your question we would need to know more about what you want to do. What is a real project? A web application? A website? A desktop application? Mobile?

I recommend picking an area of interest and diving in head first.

Depends on domain: generally learn by building, try different langs, profile your code and gradually understand the relationship between data, memory, cache, latency, etc.

Learn some C, and dabble in assembly, because that's what the computer is actually doing under the hood. Every operating system you probably use is written mostly in C. It exposes you to the gory details of computation: memory management, function calls, fiddling with the stack, etc. The fundamentals are simply what the computer is doing that usually gets abstracted away from you. Learn how your computer actually works, not the Pollyanna version presented by high-level languages. Sure, use Python for playing with trees and graphs, but spend time down in the dirt with the language that still underpins a large amount of software.

Gang of Four book on code patterns

I hope that you forgot the /s on that line.

Learning Patterns is one of the worst things to do without the experience in the problems that they solve since it results in coders who think that you write programs by hooking up some objects built with a Factory via xml (well, that was the thing when I wrote the post... its yaml now) and you've got a program - and that every program should be built of Factories and Observers and Facades and such and the dev goes about and builds the Patterns without actually solving the problem.

I have ranted on this before and that rant is at http://the-whiteboard.github.io/2016/09/02/patterns.html

I would also encourage reading https://www.artima.com/articles/how-to-use-design-patterns

> Bill Venners: Is the value of patterns, then, that in the real world when I feel a particular kind of pain I'll be able to reach for a known solution?

> Erich Gamma: This is definitely the way I'd recommend that people use patterns. Do not start immediately throwing patterns into a design, but use them as you go and understand more of the problem. Because of this I really like to use patterns after the fact, refactoring to patterns. One comment I saw in a news group just after patterns started to become more popular was someone claiming that in a particular program they tried to use all 23 GoF patterns. They said they had failed, because they were only able to use 20. They hoped the client would call them again to come back again so maybe they could squeeze in the other 3.

> Trying to use all the patterns is a bad thing, because you will end up with synthetic designs—speculative designs that have flexibility that no one needs. These days software is too complex. We can't afford to speculate what else it should do. We need to really focus on what it needs. That's why I like refactoring to patterns. People should learn that when they have a particular kind of problem or code smell, as people call it these days, they can go to their patterns toolbox to find a solution.

> Trying to use all the patterns is a bad thing, because you will end up with synthetic designs

That's how you learn. We don't become seniors overnight.

One certainly doesn't become a senior overnight. However, the GoF book is not a book for fundamentals for a self taught developer.

I will also point out that the quote that I have and that you've quoted again is from Erich Gamma... of Design Patterns: Elements of Reusable Object-Oriented Software by by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.

The GoF book on design patterns is a book for how to solve a common set of problems using these common solutions. What it is not is a "use these solutions in every well designed program".

My read on the OP's question is one of "how to become a junior programmer" - they can read code but don't write it well. The GoF is not the next book on that path. It is a book to read after you've been designing and understand the pains of writing and designing larger pieces of software... but if you're still working on "write something that solves a problem in 200 lines" the GoF will not provide any solutions for those problems. ... And if you do try to apply the GoF to the 200 line long problems you'll have contrived solutions that are a synthetic design that, in the words of Erich Gamma "speculative designs that have flexibility that no one needs. These days software is too complex."

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