Co-founded a tech startup as CTO with no developers on staff - yet. I ended up having to code the tools I wanted/needed and learned things I would have never learned if I'd just, "learned to program" in my free time. Have a goal.
EDIT: I have a comp-sci degree; it taught me very little about 'programming'.
Every book I read by a real-world programmer - never does this. They always put testing in a separate chapter or never address it at all, example: programatic programmers.
Even any tutorials online or in a user group - it's never done. It's always talked about. I come from a engineering background so I really wanted to programming the "right" way. But here is so little code that includes testing that I can use to "tutor" myself. Even opensource.
Source code control, deployment and testing are all baked into the tutorial from the very first section where coding is started. It's also available in print form.
Thanks, I will when I get back into rails. I have given up on it as of right now. It nice to know there are more resources that include testing than there were 2 years ago for rails.
I've always gotten the impression that TDD is one of those things that many people think they should do, but have a hard time making a habit (so it's not surprising it gets more talk than action).
Speaking of books, Real World Haskell covers testing pretty early on; granted, being Haskell, whether or not it qualifies as "Real World" is still a little subjective at this point.
If you're looking for resources to tutor yourself, there are some TDD katas out there (I admittedly haven't tried it myself, though) - http://www.osherove.com/tdd-kata-1/
Schools that have switched to the How to Design Programs (http://www.htdp.org/) curriculum for their intro classes would beg to differ! Of course, whether that specification+testing approach to development is carried through to the rest of the curriculum is another story :-)
* become more sensitive to your daily pain points and
move to eradicate them
* read other people's code
* before sitting down to build anything, think:
"is there an easier way to solve it?
* learn about good architecture and engineering
practices, but don't worry about them until
a) you know what you're building
b) they're a problem.
* learn programming languages in different
programming paradigms.
Your idea about tracking daily pain points was the most important thing I ever did, as well-- sort of.
I tracked, over a one year period, every single defect that made it into production that I had to correct. I did this at the inspiration of a book on continuous improvement I read. I analyzed the underlying causes of the defects, organized them by category, made Pareto charts, and looked at my underlying procedures to see how I could avoid them.
What I learned surprised me, and changed the way I approached projects from then on. What I learned was that by far the number one problem I needed correct in order to avoid production defects and downtime had nothing to do with my code.
I discovered that the number one cause of avoidable defects in production had to do with the quality of my test data, differences between production environments and test environments, and discipline in how code gets promoted to production. And of course establishing a process for such things as promoting code-- a process which is formalized, followed, every time, and continuously improved as needed.
Learning this gave me a new respect and appreciation for the importance of a faithful and realistic staging environment that mirrors production as closely as possible. It's often impractical or expensive to various degrees to replicate or simulate a production environment faithfully for a variety of reasons. What I learned is that not all projects deserve the expense and trouble of that faithful reproduction of the production environment, running production loads in staging. But to whatever degree we don't do that, we take on more risk, and it's good to at least understand those risks.
Perhaps I'm talking more about project management, infrastructure, process and procedure than about pure "programming". But what I learned through this one year exercise was that often times when people think about wanting to get better at programming, improvements in some of those areas are really what's needed to get to the higher tiers of excellence.
"I tracked, over a one year period, every single defect that made it into production that I had to correct. I did this at the inspiration of a book on continuous improvement I read."
It was "Improving Software Quality: An Insider's Guide to TQM" from Wiley. A lot of people fear the idea of formalized process, thinking that it is going to saddle them down with the useless baggage of unneeded red tape and forms. It's actually quite the opposite. It's all about keeping processes as simple as possible, even simplifying existing processes.
I wrote build scripts for my projects that tracked:
1. Syntax errors on compile (it was C).
2. Test failures.
3. Time of the run.
4. Lines of code.
Then I used R to create graphs and reports that were generated periodically. About once an hour I'd go look at them and see what synax+failure levels were per line of code at that time. I'd then plot this as a run chart and start trying to find causes of my high defect indicators.
Eventually it got to where I found a bunch of the ways I wrote defective code and started to avoid them. I have a set of macros for C now that prevent it, and I use the patterns in my other coding.
It was pretty insane though. I don't recommend it for anyone, and definitely not on a project you have to do for a living. Well, maybe if it's a missile command system or medical device.
This is awesome. Do you remember any of the causes of high defect indicators? And why wouldn't you recommend it? Too much work?
I made a thing that takes a screenshot every ten seconds while I work and another thing that sticks them in a window with a slider so I can look at them in sequence.
Just yesterday I noticed that I had been daydreaming a lot lately. So I made something that would go through the sequence of screenshots and compare each image with its previous one and count every instance where the two images were the same (or almost the same). That gave me a pretty good indicator of how much time I spent daydreaming. If the numbers are right, then when I'm working on something boring I spend as much as 40% of my time not actively typing or anything -- just thinking about random shit. I'm thinking I'll try mindfulness meditation for a while and see if that cuts down on the daydreaming at all. We'll see how it goes...
The main thing that caused defects was not handling default cases in logic. Things like not filling in the dangling else of an if-statement, not trying to return a value from a function no matter what, and not having a default: in a switch. By always trying to include at least a comment there, or an assert it forces you to think about the logic of the whole statement and prevents bugs galore. Combine that with unit tests and you've got a good solid start.
I don't recommend it because it's an insane amount of work above just writing code. I think it'd be something I'd force on high speed students in a kind of "Boot Camp" situation, but not on anyone else. In fact, I think most programmers couldn't handle having a giant bag of evidence staring them in the face telling them they suck. Also I think most programmers wouldn't get the stats behind the analysis and just keep screwing it up.
I play guitar when I have to think about stuff. I take one to work, and when I'm stuck I bust out my guitar, a pen, and a note pad. I then noodle and practice, and as ideas come into my head I write them down without filtering.
Has anyone made a plugin or anything of that sort which abstracts away the grunt work of using this sort of system? It sounds like a great thing to try out were it not for the opportunity cost of trying it.
Not that I know of. I imagine emacs or vim has good error-line parsing which you could steal/copy and get really good results. You could then extend it to work on any language you wanted.
Biggest thing I couldn't get right was automatically connecting frequency of errors to particular lines or modules. I found that I made the same mistakes over and over, and I had to just spot them and jot down what not to do or think of a ninja way to avoid it. I also found that there was a strong correlation between syntax/test failures while writing code and how bad the code was.
What would have helped is if I could calculate the stats per function, line, or file and then have some pattern analysis spit out common grammatical structures that I do which are correlated with errors. It'd be something like:
function/while/if/return 24% chance of defect found in blah.c:func1 and blah.c:func2
Then it'd get closer to predicting defects and letting me go check the spots it recommends.
But, never got around to it since it became really insane after a year already without that level of analysis.
Yes, I have. We used to call it "debugging", but I guess everything has to have a name before the cool kids will use it.
However, this wasn't about find a bug but preventing defects by using evidence to retrain my behavior. The approach is to assume nothing, then use simple graphs and data to look for places where you can change how you do stuff to improve your code. It's not hard, just really tedious.
I coded, a lot, on things just beyond my ability. IMO this is the path to success in anything: practicing, a lot, on something just beyond your current ability. It's not always the most fun though, because since it's just beyond your ability, it's hard and sometimes frustrating.
Start getting paid to do it. Once you have feedback coming in from customers who are your bread and butter, and you start trying to implement that feedback to keep them happy only to find your framework was ill thought out, you'll quickly learn to do things right from the start. Reading proper technique is useful, peer review is useful, but that first time you sit up all weekend revamping several core routines because you didn't plan well you'll learn more than the other two combined about not cutting corners. (edit: this also applies to learning to test properly too)
Disclaimer: the above comment may or may not be based on several moronic experiences the poster is too embarrassed to confess to over his 20-ish years in the 'biz'. Maybe.
I wrote a parser and lexer by hand. Building the mental abstractions to figure out how a syntax tree should be constructed and walked was amazing.
It gave me the tools to visualize how code is structured, how to avoid poorly structured code, and how program flow actually works.
The first revision took me around 6 months to implement, and the second about 3 days. Worth every moment of futzing around and hacking and designing.
The language is getting rewritten (this time with an actual grammar!), and I'm finding it still has a mountain of useful things to teach me about programming.
I can't recommend it enough. :)
I did this too! After the second time I became bored with writing parsers by hand and now I'm trying to write a parser generator instead. It's extraordinarily good fun.
Did you cheat and use a regex library in your lexer, or did you build a regex engine aswell?
I built recursive descent parser, and a lexer using the posix regex libary in 2 days first attempt and extra 14 days for semantic analysis and x86 code generation which operated by walking the ast. Most of those days were mostly learning x86 assembly. I can't understand 6 months, unless you did everything from scratch like the regex engine I.E Constructing NFA's, converting to DFA's etc etc.
I think I cheated and used an existing regex library - it's been a while.
As far as the 6 months, it was my first major, major project and required so much learning and research on just how to structure code that it took a long time to craft.
It didn't help that the design was so complex that debugging it was a chore. :)
If you're only focusing on the 'writing really good code' aspect, sure. But in the wider world, writing a book can be a spectacularly bad way to invest your time.
I've made way more money from my "Slicehost vs Linode" article than I have from my portion of "Tcl and the Tk Toolkit, 2nd edition", even though the latter required a ton of hard work.
Totally agree. I have a whole series of "Using ..." tutorials that I've written, just for the purpose of learning - having to write in a style where you're explaining something to others forces you to truly understand the subject matter. As an added bonus, you then have some handy reference materials.
Or you could use code reviews. At work, every few weeks, I'm obliged to start a code review and have others take a stab at my code. Of course I want that code to be nice, concise, readable, understandable, well documented, well tested, etc, because they will all be looking at it very closely. It has worked wonders for the overall quality of my code.
One of the best ways to improve any skill is to exercise the skill in public; the more demanding the public the better. This is true of writing and of speaking and of most kinds of research. Advice like "get a mentor" or "work with the best" or "learn by teaching" is also a special case of this general principle. We become what our friends demand us to be.
Yes interesting, could you please get into more detail ? Can you remember how long it took to write the On Lisp code ? And was writing the text quicker than the code ?
Was it a lot easier to write Ansi Common Lisp afterwards ?
I'd add to that having already been paid for it and needing to hand off to others to maintain. I guarantee that the next project you do will be at a whole new level.
Personally I've taken great strides every time I've changed job - being forced to learn a new set of skills and new problem domains, plus interacting with different (hopefully more experienced) people have always been very beneficial to me.
Lot of good things here, but there's 2 I haven't seen:
Learn a new language. In particular, learn one that requires thinking about programming in a different way. Coming from Basic, C, C# and PHP, learning Ruby was a real eye-opener and improved my coding.
Find a mentor. Watching someone code who is better than you at some (or all) aspect(s) is a very quick way to polish your skills. Especially if you can ask questions and have them suggest improvements.
Introducing variety into my routine always improves my programming skills.
I started in high school writing homework helpers in Java and C++, and writing graphing calculator scripts to make fun patterns. Then I worked with other programmers, and started structuring my code to make it understandable to others. Then I started ACM programming competitions, and learned to rigorously solve problems. Then I found Python, and learned that finishing can be quick and easy. Then I got an internship at a major corporation, and discovered I never want to be an enterprisey programmer. Then I got a GSoC gig and learned to collaborate remotely and make estimates. Then I got a real job and learned to work with code for months and years, instead of churning out small projects, and the importance of finishing early and often. Then I experimented with Lisp, and learned the importance of abstraction, community, and salesmanship. Then I played around with Tornado and started learning about the web. Recently, I got a better job and started learning the importance of testing, the importance of listening to users, and the value of a second set of eyes. Recently, I've started experimenting with the Android SDK, learning the power and limitations of major constraints.
There were 2 projects back in the university that made me improve my programming skills: building an OS (multithreading based on a DOS system) and building a compiler (using JavaCC).
In a different way, learning Lisp and Prolog, which basically widen your perspective.
Also, I have a question; most people say that they learn by reading good code, which I agree. Do you have any recommendation of a piece of code that you consider it has "something to teach"?
Well, at the time (2004), it was extremely unexplored territory. Social networks themselves were almost brand new, and the idea of creating a distributed, open source one was almost unheard of. The nearest project (DiSo) didn't show up for two years after that.
Also, my intention quickly became more than just a social networking app, and I really wanted to turn it into a framework for social apps. So that brought up all kinds of issues of MVC framework design and how to build an API and other large architectural issues.
Not to mention that a lot of the project I've had to do myself, with both very little precedence, and very little help (comparatively). Some of that was my fault, for not being better at documentation and project management, but I also learned that soliciting help for open source projects is a lot harder than The Cathedral and The Bazaar made it out to be.
It's easier now, that the groundwork has been set, and there are competing projects I can look at and learn from, but the first few years of flying blind was a hell of a crash course.
Before you can learn programming, you must first learn programming concepts. This is why smart universities teach you how to do programming rather than teach a language alone. eg: You can implement a SQL JOIN query but do you understand what the SQL JOIN query does?
Otherwise, you may find yourself being stuck to certain languages (and functions!) which can be pretty bad. eg Using if then when a switch would be clearer and quicker. Or, applying indexes to every field in the hopes it'll make the database quicker. etc.
That said, I found the best way to learn a language is to do an (Extremely small!) side project for a certain area. eg eCommerce website? Pretend you only want to sell 4 items (2 per page) and attempt to make it pretty so you understand how designers design. And aim to understand WHY the code does what it does. (There are more ideas and projects out there)
If you're going to attempt a start up, I suggest learning frameworks and APIs. Both typically save lots of money and time until you become commercially viable to cost (by then, you should be profitable).
94 comments
[ 2.8 ms ] story [ 168 ms ] threadProgram 16 hours a day. 7 days a week. Then sit and beam at my work.
PS don't program 16 hours a day. I had put ice packs later on my arms from the pain.
also get a super monitor, awesome keyboard, and a comfortable chair.
EDIT: I have a comp-sci degree; it taught me very little about 'programming'.
Even any tutorials online or in a user group - it's never done. It's always talked about. I come from a engineering background so I really wanted to programming the "right" way. But here is so little code that includes testing that I can use to "tutor" myself. Even opensource.
I find this very odd.
Source code control, deployment and testing are all baked into the tutorial from the very first section where coding is started. It's also available in print form.
Speaking of books, Real World Haskell covers testing pretty early on; granted, being Haskell, whether or not it qualifies as "Real World" is still a little subjective at this point.
If you're looking for resources to tutor yourself, there are some TDD katas out there (I admittedly haven't tried it myself, though) - http://www.osherove.com/tdd-kata-1/
I tracked, over a one year period, every single defect that made it into production that I had to correct. I did this at the inspiration of a book on continuous improvement I read. I analyzed the underlying causes of the defects, organized them by category, made Pareto charts, and looked at my underlying procedures to see how I could avoid them.
What I learned surprised me, and changed the way I approached projects from then on. What I learned was that by far the number one problem I needed correct in order to avoid production defects and downtime had nothing to do with my code.
I discovered that the number one cause of avoidable defects in production had to do with the quality of my test data, differences between production environments and test environments, and discipline in how code gets promoted to production. And of course establishing a process for such things as promoting code-- a process which is formalized, followed, every time, and continuously improved as needed.
Learning this gave me a new respect and appreciation for the importance of a faithful and realistic staging environment that mirrors production as closely as possible. It's often impractical or expensive to various degrees to replicate or simulate a production environment faithfully for a variety of reasons. What I learned is that not all projects deserve the expense and trouble of that faithful reproduction of the production environment, running production loads in staging. But to whatever degree we don't do that, we take on more risk, and it's good to at least understand those risks.
Perhaps I'm talking more about project management, infrastructure, process and procedure than about pure "programming". But what I learned through this one year exercise was that often times when people think about wanting to get better at programming, improvements in some of those areas are really what's needed to get to the higher tiers of excellence.
Which book?
1. Syntax errors on compile (it was C). 2. Test failures. 3. Time of the run. 4. Lines of code.
Then I used R to create graphs and reports that were generated periodically. About once an hour I'd go look at them and see what synax+failure levels were per line of code at that time. I'd then plot this as a run chart and start trying to find causes of my high defect indicators.
Eventually it got to where I found a bunch of the ways I wrote defective code and started to avoid them. I have a set of macros for C now that prevent it, and I use the patterns in my other coding.
It was pretty insane though. I don't recommend it for anyone, and definitely not on a project you have to do for a living. Well, maybe if it's a missile command system or medical device.
I made a thing that takes a screenshot every ten seconds while I work and another thing that sticks them in a window with a slider so I can look at them in sequence.
Just yesterday I noticed that I had been daydreaming a lot lately. So I made something that would go through the sequence of screenshots and compare each image with its previous one and count every instance where the two images were the same (or almost the same). That gave me a pretty good indicator of how much time I spent daydreaming. If the numbers are right, then when I'm working on something boring I spend as much as 40% of my time not actively typing or anything -- just thinking about random shit. I'm thinking I'll try mindfulness meditation for a while and see if that cuts down on the daydreaming at all. We'll see how it goes...
curl http://zedshaw.com/dbg.h
The main thing that caused defects was not handling default cases in logic. Things like not filling in the dangling else of an if-statement, not trying to return a value from a function no matter what, and not having a default: in a switch. By always trying to include at least a comment there, or an assert it forces you to think about the logic of the whole statement and prevents bugs galore. Combine that with unit tests and you've got a good solid start.
I don't recommend it because it's an insane amount of work above just writing code. I think it'd be something I'd force on high speed students in a kind of "Boot Camp" situation, but not on anyone else. In fact, I think most programmers couldn't handle having a giant bag of evidence staring them in the face telling them they suck. Also I think most programmers wouldn't get the stats behind the analysis and just keep screwing it up.
I play guitar when I have to think about stuff. I take one to work, and when I'm stuck I bust out my guitar, a pen, and a note pad. I then noodle and practice, and as ideas come into my head I write them down without filtering.
Basically, you need a hobby. :-)
It is good practice to compile C/C++ programs with high warning level, and fix all the warnings before shipping.
Biggest thing I couldn't get right was automatically connecting frequency of errors to particular lines or modules. I found that I made the same mistakes over and over, and I had to just spot them and jot down what not to do or think of a ninja way to avoid it. I also found that there was a strong correlation between syntax/test failures while writing code and how bad the code was.
What would have helped is if I could calculate the stats per function, line, or file and then have some pattern analysis spit out common grammatical structures that I do which are correlated with errors. It'd be something like:
function/while/if/return 24% chance of defect found in blah.c:func1 and blah.c:func2
Then it'd get closer to predicting defects and letting me go check the spots it recommends.
But, never got around to it since it became really insane after a year already without that level of analysis.
However, this wasn't about find a bug but preventing defects by using evidence to retrain my behavior. The approach is to assume nothing, then use simple graphs and data to look for places where you can change how you do stuff to improve your code. It's not hard, just really tedious.
Disclaimer: the above comment may or may not be based on several moronic experiences the poster is too embarrassed to confess to over his 20-ish years in the 'biz'. Maybe.
The first revision took me around 6 months to implement, and the second about 3 days. Worth every moment of futzing around and hacking and designing.
The language is getting rewritten (this time with an actual grammar!), and I'm finding it still has a mountain of useful things to teach me about programming. I can't recommend it enough. :)
I built recursive descent parser, and a lexer using the posix regex libary in 2 days first attempt and extra 14 days for semantic analysis and x86 code generation which operated by walking the ast. Most of those days were mostly learning x86 assembly. I can't understand 6 months, unless you did everything from scratch like the regex engine I.E Constructing NFA's, converting to DFA's etc etc.
As far as the 6 months, it was my first major, major project and required so much learning and research on just how to structure code that it took a long time to craft. It didn't help that the design was so complex that debugging it was a chore. :)
Hence the V2 rewrite that took a couple of days.
You should do this. You don't even need a publisher, you could approach your topic like Zed Shaw did with "Learn Python The Hard Way".
Or you could do a series of blog posts. You WILL get feedback and this will improve your skills.
I've made way more money from my "Slicehost vs Linode" article than I have from my portion of "Tcl and the Tk Toolkit, 2nd edition", even though the latter required a ton of hard work.
Learn a new language. In particular, learn one that requires thinking about programming in a different way. Coming from Basic, C, C# and PHP, learning Ruby was a real eye-opener and improved my coding.
Find a mentor. Watching someone code who is better than you at some (or all) aspect(s) is a very quick way to polish your skills. Especially if you can ask questions and have them suggest improvements.
I started in high school writing homework helpers in Java and C++, and writing graphing calculator scripts to make fun patterns. Then I worked with other programmers, and started structuring my code to make it understandable to others. Then I started ACM programming competitions, and learned to rigorously solve problems. Then I found Python, and learned that finishing can be quick and easy. Then I got an internship at a major corporation, and discovered I never want to be an enterprisey programmer. Then I got a GSoC gig and learned to collaborate remotely and make estimates. Then I got a real job and learned to work with code for months and years, instead of churning out small projects, and the importance of finishing early and often. Then I experimented with Lisp, and learned the importance of abstraction, community, and salesmanship. Then I played around with Tornado and started learning about the web. Recently, I got a better job and started learning the importance of testing, the importance of listening to users, and the value of a second set of eyes. Recently, I've started experimenting with the Android SDK, learning the power and limitations of major constraints.
I can't wait to see what the future holds.
- Work with the smartest people you can.
- Strive for beautiful code.
- Keep simplifying.
In a different way, learning Lisp and Prolog, which basically widen your perspective.
Also, I have a question; most people say that they learn by reading good code, which I agree. Do you have any recommendation of a piece of code that you consider it has "something to teach"?
Also, my intention quickly became more than just a social networking app, and I really wanted to turn it into a framework for social apps. So that brought up all kinds of issues of MVC framework design and how to build an API and other large architectural issues.
Not to mention that a lot of the project I've had to do myself, with both very little precedence, and very little help (comparatively). Some of that was my fault, for not being better at documentation and project management, but I also learned that soliciting help for open source projects is a lot harder than The Cathedral and The Bazaar made it out to be.
It's easier now, that the groundwork has been set, and there are competing projects I can look at and learn from, but the first few years of flying blind was a hell of a crash course.
Otherwise, you may find yourself being stuck to certain languages (and functions!) which can be pretty bad. eg Using if then when a switch would be clearer and quicker. Or, applying indexes to every field in the hopes it'll make the database quicker. etc.
That said, I found the best way to learn a language is to do an (Extremely small!) side project for a certain area. eg eCommerce website? Pretend you only want to sell 4 items (2 per page) and attempt to make it pretty so you understand how designers design. And aim to understand WHY the code does what it does. (There are more ideas and projects out there)
If you're going to attempt a start up, I suggest learning frameworks and APIs. Both typically save lots of money and time until you become commercially viable to cost (by then, you should be profitable).