1. There is no substitute for the hours spent coding. Sure, you can waste a lot of time, but there's a high correlation between hours spent and skill attained.
2. You can do almost anything with almost any tool. The energy spent debating tools would probably be better spent building something.
3. One of the biggest differentiators between a good coder and a poser is the willingness and ability to go several levels down. Deep understanding comes from deep diving.
4. One of the best ways to deep dive is to benchmark. The milliseconds gained will be a byproduct. The real benefit is your understanding of what goes on under the hood.
5. Write a framework. You may never use it, but you'll never be the same programmer either.
6. Almost everything you do will take longer than you expect, no matter how experienced you get or how good you get at estimating. If it doesn't, then you're not taking on challenging enough work.
7. Once you regularly deliver great value to others, you will often feel like an imposter. The compliments will exceed what you think you deserve based upon how hard it was for you to build. That's OK. Accept it and enjoy it. It's payback for all those hours you slaved away and no one knew what you were doing.
8. If you maintain a sense of wonder and delight every time you get something new working, you will probably never get burnt out. Don't let anyone tell you otherwise.
9. When you look at your old code, most of it will suck. That means you're always getting better. But some of it will still amaze you. Embrace and harness that energy. Try to recreate the conditions under which you wrote it.
10. Name your variables properly. That will always be half the battle.
> 1. There is no substitute for the hours spent coding. Sure, you can waste a lot of time, but there's a high correlation between hours spent and skill attained.
Even the time wasted is valuable, and not just for racking up hours. Wasted time includes making mistakes, and once you've made a mistake then you've seen that mistake. This means that when you later see the results of that mistake, made by you or a colleague, you can quickly consider if it's that same mistake; often it is.
We've all asked someone for help about something weird, and that someone gives us an immediate suggestion. Chances are it's because they've made and seen that mistake in the past.
> 7. Once you regularly deliver great value to others, you will often feel like an imposter. The compliments will exceed what you think you deserve based upon how hard it was for you to build. That's OK. Accept it and enjoy it. It's payback for all those hours you slaved away and no one knew what you were doing.
That's a byproduct of learning any craft. It is not the act of writing 20 lines of a script in 10 minutes to process that file that makes you amazing. It is the fact that you know what 20 lines to write.
11. Learn to read, navigate and understand code! Unless you are working alone (but even then) you will spend a lot of time "uploading" code to your brain. Code is read more than written.
12. Algorithms are not nearly as important as some people make it look like. I can't really remember if I ever wrote a sorting routine that is used in production and I am still waiting for the moment A* will be useful. And when that moment comes, I will just need to _read_ it on wikipedia.
Re 12: It happens (sometimes? eventually?). It took me 15 years though until that point came. And the answer was just looking at Wikipedia and other code samples in other languages to get some understanding of it. I also implemented it wrong and it kind of worked (not as well, but well enough) and only realized my mistake months later.
Re: #7, there's sort of a catch-22 with that, and not just with software, with any creative endeavor.
If you struggle, bash your head against the problem, put in a lot of hours, and eventually produce something that works you may feel like you don't really understand what you're doing, that you only managed to produce something by brute force and luck (which may sometimes actually be true).
On the other hand, if you breeze through something and knock out a solution with little effort it may seem like you're not actually doing anything at all.
It's easy to undervalue knowledge and the difficulty of acquiring it. Just as it's easy to undervalue merely putting in the time and effort even when skills are underdeveloped. What ultimately matters is whether or not you were able to build something worthwhile that wouldn't have existed without your effort.
Re: #10, also use good commit messages. I find this harder with smaller commit increments such as with using git. Lately I've tried to avoid using "change" or "fix" as the first words in my commit messages.
I find that it goes away with experience. Over time we learn that the true value in our output isn't to ourselves, it's to the users.
I see users of a simple file parsing utility that took me an hour to write gushing over the amount of time it saves them every day and it just makes me feel good to be able to help someone with such little effort.
Not everyone is the same, for some it doesn't go away as easily. I've heard plenty of stories from talented artists, makers, and devs of falling into that mentality. It can be difficult to kick for the reasons I laid out. When it's hard it feels like you're a fraud, when it's easy it feels like you're cheating. It's not true, but people should be aware that these sorts of feelings are pretty common.
I'm reminded of the scene in Office Space where people are brought in an asked to describe what they do. That sort of thing is harder than one may think, it can be difficult to fully sum up how one works and in what ways one's skillset and expertise is valuable. For several years I had a job that was very difficult for me to describe to others succinctly. Mostly because it was hard to explain what I did if you didn't know many other details of the development process within the organization, some of them highly technical.
To use an analogy, it's a bit like asking why Beethoven is good music (without falling back on popularity). To express such things succinctly can be quite difficult, more so if you're put on the spot. Most people don't spend hours and hours thinking about how to justify the value of their own work, because that sort of thing can seem egotistical, more so if they already suffer from imposter syndrome. And without doing that when they put themselves on the spot they'll fall into the same trap of not having a good answer.
Number 5 is right where I'm at right now. I'm still really new and have spent my time learning Ruby and Ruby on Rails. I've recently embarked down the Erlang path. The frameworks aren't nearly as developed as Rails and I've realized I have no idea what the hell REALLY happens on the server side. My current goal is to write a server and my own framework. I have no illusion that either will ever be used for production. But I know I'll never get to where I want to be as a programmer if I don't understand what's going on back there.
By the way, nice to see a post from you. It seems like it's been awhile.
I'm a little bit further on that point and I think you should slow down a bit.
(All that follows is my humble opinion, apply grain of salt and critique as needed)
Writing a framework for the first time is hard. You said you don't really know what happens server-side and this may get in your way. A framework is often designed to address specific problems/needs in a specific context.
These problems/needs don't have to be shared by anyone else, it could just be you thinking "It's hard to build RESTful urls, I should build something to do it for me" and have a CLI util or a script handler that would register them for you in your app server. And some can be everyday problems: "F*ckin' databases, how do they work?".
However, you need to know these problems to address them. Which is a part of my long-term feud with frameworks: "If you always use a framework, you will never have (too much) problems and will never learn how to solve them" (writing my own active-record-like ORM for node.js is a lot of fun actually).
Which is why my advice to you is: Don't write a framework.
Instead, write an app, get stuck a lot of times and find a way. Identify your problems. Then write a different app. This time, look at what you are doing the same way, what problems you are solving another way and what you'd like your framework to automate. There, for this second app, you can start writing your framework because you'll have a better idea of what you need to address.
You don't really need to make a framework that caters to everyone's needs, but one that caters to your needs and expand from there.
Next (optional) step is rewriting the first app with the second app's framework and iterate new functionalities.
I solved this problem by using Sinatra rather than Rails. For most things you will build as a novice coder, Sinatra will do what you need and get out of your way.
When you start building bigger stuff, and your routes and controllers start looking crufty and ugly, and you start wishing you had more tools to keep everything organized, then pick up Rails.
I suppose you could try to hack together your own framework to give you a sense of what's involved. In Ruby this is done with Rack, it handles the HTTP requests and you can focus on the mid-level framework-y stuff. But seriously, Sinatra's what you'd eventually come up with, and it's already out there, so why not use it?
Excellent list. I would add to #3 to read the source. Many frameworks are open source so they are easy to link in the editor and follow all the way down. Even though something like iOS isn't open source, the headers are all available and have tons of information.
#8 is why I've been coding for years. There is always something new and interesting to do.
Biggest lesson after my 29 years of programming is the difference between the best solution, and a successful solution. I.e. getting familiar with system patterns (architecture) that work for your chosen stack/area of interest.
There are a million resources for specifics, like doing a server redirect or creating a jump list for Windows Phone, but precious little on the end-to-end implementation semantics of, say, a smartphone app that syncs content to a server that scales out and up. Also, adding security, monitoring hooks, and exception and configuration management. The realisation that open standards are far, far more important than open source.
Similarly, the web is full of people telling you to use Mongo, but again hardly anything about being able to reference indexes in a document, or that partition tolerance and availability come at the expense of consistency.
Get these things right and suddenly even using GOTOs, or the differences between closed and open source, become non-issues because if your solution works, and is successful, any ciritics of such semantics can go to hell.
a smartphone app that syncs content to a server that scales out and up
This made me chuckle. I recently designed an entirely new way of doing just that (to me, at least), and it's probably the 20th or more end-to-end approach I've developed over the last seven years on that specific problem.
I don't know why scalable sync interests me, but it does. :)
A key for learning anything is being curious and exposed, in combination. A great way to get that as a beginner (in coding or in a new environment) is to take on bug fixes and CRs. While not always everyone's favourite it forces you to dig into others code, see things you like/dislike, grok new concepts, and challenge the inner-you with doing what's right vs. what is faster. Perfection vs pragmatism - knowing what to side with and when is a key to a long career.
"Braces should go on the next line. Braces should go on the same line. Use tabs to indent. But tabs are evil. You should use stored procedures, but actually you shouldn’t use them. You should always comment your code. But good code doesn’t need comments."
In contrast to what she is saying, there is a true path. The true path is: use whatever the coding standard for that particular company or project says. There is nothing more annoying than people having different formatting settings and having each commit/diff being 80% formatting changes and 20% actual changes.
Work on an over-commented code base and come back and tell me commenting everything is good.
Work on a large crud app where it's 'SPs only' and come back and tell me SPs are good. Worse still that particular debate is dead. The parametrized queries not only won, they blew SPs out of the park with ORMs. Hence the articles linked are 7-8 years old. And yet I still come across the occasional programmer who uses SPs (who will generally think ORMs are evil rather than massive time savers).
As for commenting, new coders need to comment because they forget what they did. New programmers can't read code properly, they need help from comments. So it's good general advice to tell newbies to comment while they're learning. But not in production code.
New coders also tend to get a revelation when they go back to some of the first code they wrote and can't understand it. The revelation is 'I should have commented it all!'. But the revelation is false, there are two reasons they can't understand it. Firstly, it's crap code because it's their first code. Secondly, they can't read code properly. But they can't admit it to themselves because they think that now they're good coders.
I've seen this time and time again, programmers with less than 2 or 3 years experience often won't try to read the code and figure out the logic when something goes wrong. Be it their own code or a bug in someone else's they've been asked to fix. They start changing random variables or commenting out lines. And yet they honestly think they are good coders.
Many time I have sat down with them to help, read the code and then pointed at a line and said 'Hmmm, that looks wrong'. And that will be the bug. 5 min fix, if you can read code. It's just part of the learning process and now I'm older I can see the Dunning–Kruger effect as stupefyingly obvious in programmers. I don't begrudge it, I don't think they're stupid or unskilled, it's just a stage every programmer seems to need to go through. The stage where they still haven't realized they can actually read the code to figure out what it does.
What's funny is that I can see I suffered from it constantly in my early years and was a right arrogant idiot.
I disagree with some of your points, and I have experienced what you pointed out should be needed to bring that conclusion. This stuff isn't cut and dried, so i just go with whatever the project is already using. Seems easier that way :)
> Before you learn to code, think about what you want to code
This is and always has been my problem. I like to look at what other people do, and I like coding in theory. But the little I need for myself isn't enough to keep pushing myself. I don't work anywhere near programming, and I don't particularly want to, either. Because of that, though, I haven't progressed very far into SICP, my finished Scheme programs can be counted on one hand, and most of my shell scripts are simple <1h (including looking things up) hack jobs.
I only really script for personal use, and my personal usage patterns are either not terribly demanding or too complex for me to satisfy.
Try automating some of your work. Pick one simple thing that you do a lot, and write a small script or program to automate it: getting a handful of files from somewhere; putting a handful of files somewhere; opening one or a handful of files; creating the skeleton of a file that you will later flesh out.
I'm guessing you probably work in Windows because most people do at work; their shells are either too simplistic and awkward (cmd) or nuclear-capable (psh). Install cygwin and use the bash shell. Or do everything in Scheme/Racket and don't worry about a shell.
Automate something today, something almost too simple to automate. Repeat.
openSUSE & zsh all the way! ;) In all seriousness, though, my setup is a wee bit unusual for somebody who isn't a programmer, since I work exclusively in emacs via LaTeX & org-mode, stuffing all of it into git, on a openSUSE system, zsh as my standard shell, i3 as my window manager etc.
The thing is, I do have a script for example to push the current git project to various remote repositories or to create a new empty remote repository on those servers, set it up locally etc. But there are few other things that need to be scripted. I'm sure some of my things violate all kinds of sensible programming standards, but they do work (e.g. looping through shell arguments and then using case "$1" instead of using getopts, because it only allows long arguments in a hackish way).
The problem, essentially, is that of the plateau. If I wanted to do something that pushes things further, I'd need a real project, not the odd, occasional shell script. But for that, I lack the motivation, since, after all, it's not really what I should be doing. It's a bit of a circular problem.
Mh, I don't really. There are few things that need to be changed all at once. The only recent time I needed regex on a wider scale was when I botched org-mode radio targets after a recent syntax change, which was a simple case of replacing >> with >>> and << with <<< respectively, as well as extracting some text from within square parenteses and put it on its own instead. But 1 to 2 lines of sed -i are not thaaat challenging! ;)
That poster probably meant things such as quantitative text analyis, comparing language patterns used in literature, etc - which is mostly a question of interpretation, but requires some skills in scripting for the initial data gathering.
I agree with all of the points of the author. I'm currently in the process of teaching myself iOS development (nathanmorgan1.wordpress.com - for anyone who's interested) and have experienced some of the issues the author addresses first hand. I'd like to say little on 'teach yourself to code' programs.
When I came to start learning iOS development, I had a range of transferable skills and knowledge that I could call upon, for example I was comfortable with loops, declaring variables and manipulating/defining objects.
So I think while these courses won't take you from beginner to employable or experienced, they do serve their own purpose.
>So I think while these courses won't take you from beginner to employable or experienced, they do serve their own purpose.
Determining when you're employable can be difficult (entry-level at Google vs. some LAMP web shop) and I'm sure that some portion of people trying these programs are looking to switch careers. I found it easy to get the notion that "If I learn through a bunch of courses and books and maybe do a few projects, I can put these languages on my resume and get hired". That, unfortunately, turned out to not be the case.
I agree with you, it is equally possible to learn syntax in other ways, whether that's from a book or tutorial etc but I think these programs reach people that may not otherwise have considered starting to code. They produce a zero barrier to entry, needing zero expense and minimum effort to get started.
They also make the initial stages of learning to code 'fun' (I'm aware that's a highly subjective term however) when learning syntax, often without having grander goal in mind e.g. an app, can be a dry subject at best.
On your second point, are you referring specifically to people who complete these courses or people who teach themselves to code and build a few projects?
The experienced programmer knows it won't work first time, and does not wait until its finished before testing it. The time spend finding a bug is cubic in the distance you have coded since last thorough testing. You test the foundations are rock solid before building a cathedral on top of it. I find the newer blood writes way too much code in one go.
Good post. Though my experience with this one was slightly different:
Someone will always tell you you’re doing it wrong
In my case, it wasn't that people were telling me I was doing it wrong, it's that I saw all these people asserting the Right Way to do things and I was so worried about doing it wrong that I would get bogged down worrying about tiny irrelevant problems. But in the end what people cared about most was getting things done, and usually didn't care as much about the methods as one would believe reading the web.
The most common traits of all the best code I've worked with is consistency and thoroughness.
A researcher in programming languages once told me that when she encounters the "HTML isn't a programming language" meme she always thinks: Agda and Coq aren't Turing complete, are they also not programming languages?
The point being, I think, that drawing this bright line at Turing completeness doesn't hold up when you give it any thought, and so it's not very useful. Aside from that, you've utterly missed the point of the OP.
>Implements a Turing machine in Java without using control structures, variable declarations, method definitions, or anonymous classes. The main2 method shows the code before I removed variables. Control structures are too controlling for this day and age. Us youth yearn for the unstructured hippie days of our parents' generations."