Thursday, November 7, 2013

Remote workers, how do you learn from each other?

There is a lot of talk about remote workers since the publication of the book, "Remote: Office Not Required" by DHH and Jason Fried. Although I have not read the book yet (I am a fan of the authors' other book, "Rework") I wonder how remote workers teach and learn from each other?

In the past I have said that knowledge work is a lonely activity. The craft of writing software seems to be one of the few where it is hard to see how more knowledgable craftsmen do their work. It is easy for master cabinet makers to do their work and be watched by apprentices. With knowledge workers, however, it is usually one person in front of one computer. Sometimes we pair program, but in general, apprentice software developers cannot sit and watch a master artfully craft some code (there is nothing preventing them from doing this, I suppose, but we tend to put up personal barriers when working on a computer).

Sadly, one can be sitting three feet away from a great programmer and never really learn anything from them if there is not a culture of teaching and learning. Great developers in a mature organization will make an effort to spread their knowledge to less experienced developers. Having been in organizations like this I know that most of the teaching takes place face to face. Teaching is always more effective when done face to face. It seems to me that working remotely adds another barrier to being able to learn from the developers around you.

If I was a fresh CS graduate hired today, I would insist on being close to seasoned developers. After all, the completion of a computer science degree really just marks the beginning of a lifetime of learning. I cannot think of a worse thing to do to a new professional developer than to isolate them from the more knowledgable.

One might argue that only great developers who are motivated and independent learners should be working remotely. It is not likely that they would learn much from their less knowledgable peers in the office anyway. I imagine that the relatively small 37 Signals only hires the best developers who are motivated learners, so I am not surprised that their environment is ideal for working remotely. Larger companies that can't attract an entire crew of these super learners would most likely want to have the ones they can attract as close to the less experienced developers as possible. They are the ones who will teach the others.

So, how does knowledge spread in a remote office? Can an inexperienced developer with a lot of potential be hired in one of these environment and expect to learn from others?

Monday, September 2, 2013

My best computer science students do these things

Recently, I went through a list of every single student I have had over the last 10+ years of teaching computer science to undergraduate students. It brought back a lot of memories (and made me feel very old). I decided to make a list of the things that I have noticed that my best students do.

1. They are hard workers
Ok, this is a really obvious one, lazy people don't accomplish much. In this case, however, I mean that computer science students have to be willing to 'try, then fail, then fix' in order to learn. There are some disciplines like mathematics, philosophy, and economics that a really bright student can learn a great deal by listening to lectures, reading textbooks, attending class, and thinking. They learn by applying their impressive brainpower to a complex topic and somehow all the abstract pieces mysteriously fit together. I am jealous of these people.

Computer programming, on the other hand, is a topic that one can only learn by building. No one has ever learned to be a great programmer by simply listening to great lectures, reading amazing books, or watching Linus or Zuck program. Similarly, no one has ever become a great artist simply by observing Picasso paint or become a great writer simply by reading and rereading Mark Twain (observing skilled craftsmen can certainly help, but it can't be the only learning technique in one's toolbox). Art and writing are also skills that one learns by building. When the students are the ones building all the pieces (code) they never just magically fit together.

Occasionally, I will get an incredibly bright student who has never had to learn by building. A humble student will recognize that there are some topics in which their passive approach will not be sufficient and they will adapt. Others don't adapt and they tend to switch majors. One has to be willing to get their hands dirty and spend six hours looking for an elusive bug or be willing to throw out three weeks of work and start over to make a program better.

2. They are creative
I am truly impressed by some of the creative approaches my students take when solving problems. Even though I have been programming longer than some of my students have been alive I don't intrinsically know the best solution to every problem. Often I will be talking with a student about a problem and I will give them some advice- I will tell them how I'd solve the problem. If there is something they don't like about the suggestion (usually when it sounds like a lot of work) it tends to create a spark in them. This spark might lead to another way of accomplishing the same end result. Their creativity is inspiring to me.

So what do you do if you are not a creative person? What if you were never good at art or don't have great personal style? It turns out that those are not the only ways express your creativity. A creative problem solver uses all of their past experiences and intuition to propose radically different solutions to problems. Often they will 'see' the problem in a different way that allows them to propose a more elegant, simple, and efficient solution. If you don't feel like you are a creative problem solver perhaps it is because you aren't listening to other people's ideas and engaging them with yours. Talking to other developers is often the best way to improve your creativity skills and become a better programmer. 

3. They are curious
My best students are very curious about how and why things work. If I tell a student that one algorithm is better than another without explaining why, the good ones will demand that I tell them why. Sometimes I am unable to convince them and they seek proof. I have had many students write programs to try to prove or disprove something that I have claimed. This is very satisfying for me as a teacher because I know that I can trust this person to always seek the truth.

My best students are also the best debuggers of code. When some of their code doesn't work they need to know why. I will see students debug their programs, sometimes for hours, trying different inputs and going down different paths of the call stack until the find out the 'why'. They then reflect on what they have discovered and burn the reason into their brains so that the next time they won't make the same mistake again.

4. They believe in magic
Ok, its probably not a good idea to believe in magic, but it is good to believe that you are a wizard. From my earliest days programming, whenever I write and then run a program it has felt like magic. Even after I learned that there is no magic happening inside the computer, I still feel like I can conjure up miracles with the spells I write in my editor.

There is something so unnatural about telling a machine to do billions upon billions of operations and have it do them so quickly and without complaint. If this feeling ever goes away I will probably stop being a programmer. I especially like to watch my students make the realization that they too can conjure up miracles. One of the benefits of being a teacher is that students (at least partially) attribute this power to me- that's awesome!

5. They are patient with themselves 
It's hard not to feel like an idiot after spending several hours debugging code only to realize the problem was a simple, easily fixable error. It's hard for some, but not for my best students. For them, finding and fixing any bug is an exciting activity. Not only do they learn something new (or what not to do in the future) but the process of moving through their living code is enlightening. Moving through code validates that everything is working as it should and provides confidence in the program they are building.

Writing complex programs is a difficult task. One should expect to encounter trouble along the way. The best programmers come to expect difficulty and do not get down when it happens over and over again.

6. They are patient with others
I always try to convince my best students to become tutors in the department. Being a tutor means learning how other people perceive programming problems, suggesting ways of looking at the problems, suggesting possible solutions, listening to the feedback about those suggestions, and guiding students towards a critical realization that they can, in fact, solve the problem that was so elusive before. In other words, being a tutor is a lot like being a professor.

I was a tutor in college and I found it fascinating. Without that experience I definitely would not have ended up being a professor. In fact, being a tutor has shaped my teaching style. I have often felt that what I do best as a teacher is talk to students about the problems and make them realize that they can solve them. I try and provide confidence.

Here are some things that unsuccessful computer science students do:
- underestimate how much time is required to 'learn by building' and don't put in the time
- don't talk to other people about what they are doing
- are afraid to ask questions
- insist on figuring things out by themselves
- are unfriendly to their peers
- they don't feel like they need to know why something works or does not work
- don't compile and run their code often enough, they don't get the feedback necessary to eliminate problems as soon as possible and they don't get to feel like a wizard
- get frustrated at themselves for making simple mistakes- it's ok, we all do it!

Monday, August 12, 2013

No one learns to program alone

I can't think of a single field where it is more important to have an active support system while learning than computer programming (by 'active' I mean actively involved with other human beings). Here's why you need to talk to other human beings while learning to code:

When our tools get confused about what we ask them to do, they are not good at explaining their misunderstanding of the problem.

Here are some things that I hear from my students in introductory programming courses:
"I have no idea what this error message means."
"The program compiled but I got this error message while the program was running and it makes no sense to me."
"The compiler told me there were 23 errors but after I fixed the first one everything was fine."

Imagine two people who know very little of each other's language but are discussing a mathematical problem. If both people understand the mathematics then the language barrier is not significant. If one person doesn't understand the problem and needs clarification from the other then the language barrier is significant. As a programmer, if you know your stuff then the language barrier is not significant. But if you are just learning to program this can be very frustrating. It's like the programmer and compiler barely speak the same language.

Having a knowledgeable human being to translate between the compiler and the beginner programmer will make learning so much easier. I often joke with my students that I will follow them around and answer all of their programming questions for a very large fee (I have had no takers yet). When I run into a student who is very frustrated I will often invite them to work in my office so that when they have a question they can get an answer from me right away. I dedicate a lot of in-class time for exactly this purpose and I think it is much more beneficial than simply listening to me lecture.

Working on a computer is a solitary activity and it is hard to see what other programmers do in similar situations.

I have written before about how knowledge work is a lonely activity. Even though my class is filled with great students who are willing to help each other learn, it is so hard for them to learn programming from one another. This is because it is hard for students to physically see each other work. There is a culture among knowledge workers (and students) of, "I work on my computer, you work on yours." I would like to see tools and techniques to open up the programming process for all to see.

In a sense, I feel that only professors like me get to break down the barrier between beginning programmers and their computers. We teachers are expected to watch others do their work. This is one of the most satisfying things about being a teacher. I'm amazed by some of the solutions my students come up with. One of the things I love about teaching is that I get to learn from my students and see their interesting ideas for solving problems.  If you are asked to solve a hard problem, you really should talk to others to see what ideas other people have about solving it. I guarantee this will broaden your horizons. 

Perhaps the title is misleading, I suppose one could learn how to program alone, but a budding programmer will learn so much more if they are actively learning from others. In my opinion, effective teaching of computer science is all about providing that support system.

Sunday, August 11, 2013

The biggest challenge to being a software developer...

The more I think about it, the more I believe that the biggest challenge to software developers these days is dealing with 'the learning gap'. The learning gap refers to the fact that when a programmer is in college they have plenty of time to learn new tools and technologies, but once finished with college and working full time, we don't give ourselves enough time to learn new things. Our field changes so fast that it is impossible for a professional developer, with at least forty hours of 'real' work per week, to experiment with all the new programming languages, frameworks, and techniques out there, let alone master them. I believe this is why programming is mostly a young person's game.

Imagine you are writing code for a big company on a stable, reliable stack. If you work on the project for a few years but don't have the time to learn new things along the way, then when the project wraps up your skills might be out of date. At that point you don't have many options. You could find a similar job (which might seem boring and repetitive but I am guessing many people will do this at least a few times), take some time off to learn the latest and greatest (all the while being unpaid), or you could take that non-technical management job (perhaps getting a raise).

As soon as you take that management job, though, you will only fall more and more behind. I have met people who have taken this path and after just a little while they lack the confidence to ever get back in the game. They seem to have forgotten just how awesome they were when they were slinging code. This premature retirement from solving complex technical problems seems like a waste to me that could be avoided if we all made learning an essential function of our jobs.

I see some obvious solutions to this problem:
- Make learning a part of the culture. In your company, make teaching to, and learning from others a measured performance goal. 
Hire people who are good problem solvers and let them learn what they need to know on the job.

While in college we have a rigid structure where we are expected to learn and practice along the way. Once we leave college most of us never have that structured learning experience again. Yes, motivated people can read books and blogs and keep up. But it is easy for even the most well intentioned developer to slowly fall behind. This is especially true once we start to acquire spouses, children, mortgages, etc.

The best way to ensure that you are keeping up is to learn in groups of your peers during work hours. I really like the idea of company sponsored 20% time, technical book clubs, meetups, fed ex days, and lightning talks because they involve peers pushing each other to stay current. I think an effort should be made for everyone on the team to work on small, less than critical projects that use experimental (or at least new-to-you) technologies. In addition, team members should work with people they don't usually work with on these projects. This is good for the employees and it is good for the companies to have a broad set of experienced people.

The main point that I am trying to make is that our peers and colleagues have to become our teachers, and our companies must support developers' teaching, learning, and experimentation. Teaching and learning should be an in-house activity. Luckily, all of this teaching and learning can easily be quantified and used as a performance measurement. If you are not actively learning from others and not making the people around you better, then you are not fully contributing to the team.

Another option to ease the problems associated with the learning gap is to hire problems solvers and let them figure out the technology stack on the job. This is especially applicable if your organization already has a strong teaching and learning culture. I wonder how many former rockstars turned middle managers at big companies would like the opportunity to get back in the game without the pressure of having to know everything before their first day on the job.

If I was hiring, instead of listing twenty impossibly diverse skills in bullet points this would be my only requirement:
Looking for an expert problem solver. Candidates should come in ready to learn new things and teach others what you have learned over the years. 
You don't know <hot new technology>, but you just spent the last several years working on an awesome product? No problem, <hot new technology> isn't that hard. If you were awesome on your last project you will be awesome on our project.  
Feel free to steal this for your next job posting. I might even apply!

Monday, April 22, 2013

Learning to become a developer is just as hard as it has always been

There are many different ways to learn how to become a software developer. One can go to college and learn about computer science for four years. Or, one can learn on their own with books or one of the many great and free online course aggregators and interactive tutorial sites. One can even get intense training in a very specific niche in the field. I would guess there are people working on even more distinctive and new ways to deliver the content a programmer needs to know in order to be effective. This is all great for those of us who love to code and want others to love it too.

However, even though there are new content delivery technologies we have to remember that learning to be a software developer has not gotten easier because of them. Acquiring the content is important, of course, but I don't believe it matters much whether you learned the content from a college professor, read it in a book, or learned it in an online course. What matters is how you grow from an inexperienced developer to an experienced one.

Imagine if you were interested in learning how to paint. You could take some courses at a college, watch online videos about painting, and even use some interactive web apps to hone a technique or two. But none of these will make you a great painter. The only way to become a great painter is to do a lot of painting (and even that doesn't guarantee that you will ever be great).

This is as true with painting as it is with developing software. The only way to become a great software developer is to write a lot of software. You will not be very good at first but then you will get better. It will be hard and frustrating. If you put enough effort into it, however, you will grow as a developer. You will not grow simply by acquiring all the content from these new teaching technologies.

Different people have different preferences for acquiring content. Having different avenues for acquiring knowledge is great but lets not make the mistake of thinking that it is any easier to learn how to become a software developer today than it was ten years ago. I believe programming is one of the purest forms of thoughtful design and creativity. It has always been hard and I believe it will always be hard.

Monday, April 15, 2013

Why modern version control stinks

I have a very tech-savvy brother who, although he is not a coder, I am absolutely certain he could pick up how to use most of the tools we software developers use. That is, with one exception- version control systems. Why do I believe I can teach my brother about complex IDE's but not version control? Because modern version control stinks!

I often think about what a version control system designed by Steve Jobs would look like. I don't know the answer but I am 100% certain it would not look like git, mercurial, or subversion. Linus is undoubtedly a genius but he was the wrong person to design the most used version control system in the world. Here are some thoughts on why git is hard to use.

Git, mercurial, and subversion were all developed within the last ten years or so. Even though they were developed in the 21st century, they seem to be designed with 1980's constraints. They are all optimized to be very disk efficient. They trade minimizing the disk impact of recording raw differences in files for recording more useful data about the programming process. Hard disks are tremendously inexpensive these days and are moving toward obsolescence. So, why don't we fill our cheap hard disks with more information about the programming process?

What information should we be recording about how a developer works with a set of files? Well, how about all of it? Because modern version control systems don't record this information one cannot:
- Write good commit messages
When writing a commit message one cannot review all the changes that were made since the last commit. Without being able to see all the changes one often can't recall all the interesting twists and turns that have happened in the coding session. More importantly, one cannot write down the reasons why some decisions were made. We remember some of these reasons for a certain amount of time but it would be nice to have a record of low level decisions for anyone who has to maintain the code later.

How often have you found yourself paralyzed by trying to come up with a short description of all the changes that took place since your last commit? It can be as hard to describe the changes as it was to write the code itself. I believe this is the cause of most of the extremely short commit messages that provide little or no value. If one could review their work I think we would have better commit messages.

- Visualize changes easily
The tool 'diff' shows the raw differences between two files. However, it does not show the order that the changes were made and does not show any context about the changes. The 'context' that I am talking about are the reasons why the changes were made. If one were able to see what order the changes were made and have a narrative to go along with those changes one might have a better sense of how the pieces fit together.

- Tell stories about the system
Commit messages could help us understand the changes in our systems if we wrote good ones. Unfortunately most of us do not. So, if we don't have meaningful commit messages and we can't visualize how the changes were made, it is unlikely that someone will easily understand the evolution of a piece of software.

Imagine that one could visualize the changes as they were made, and during this visualization a developer could pause the playback of the code and write a message about why they made a decision. Now imagine if a series of these messages could be tied together and linked to the code being played back. One could then review one's work at a natural stopping point and tell a story about the latest changes. If these stories could be searched directly from the code, for example by highlighting some code and seeing what stories include that code, then someone responsible for maintaining code could get inside the mind of the original developer and understand their thought processes. This is valuable information that doesn't get written down anywhere else.

- Teach your colleagues
With the ability to record the reasons why we do things that is linked to the code but not in code comments, developers can more easily become teachers. Working on a computer is such a solitary activity that it is hard developers to learn from each other. You might be sitting three feet away from a great programmer and never learn anything from them. We need a way to open up the programming process so that we can learn from each other.

Each one of these deficiencies limits the amount of knowledge one can acquire by working with legacy code. Each can be remedied if we rethink how version control systems can help us understand how our code has evolved. The version control system I am developing records every single keystroke, delete, copy and paste, and file operation. This information can be used to replay development sessions. A developer can replay certain parts of how their system has evolved and tell stories about it.

Monday, April 8, 2013

Learning computer science should also be about learning entrepreneurship

It costs virtually nothing to start a business that manipulates data as its main business model. The obvious reason computer science students should learn about entrepreneurship is because they have the best chance of learning how to build a business early in their careers simply by attempting to do it. They do not have to raise significant capital to get the business off the ground. The barrier to entry is high for biology, chemistry, or physics students who would like to start a science-based business.

There is a less obvious link between learning computer science and entrepreneurship, however. Developing a program and developing a company have a lot in common. When I sit down to write a complex program I know, before I even begin, that there are some things that I will need to accomplish that I have no idea how to do. I won't even know exactly what needs to be done until I have made some progress in earlier steps and get some feedback from the running program. That sounds like an accurate description of starting a business to me.

When I introduce a complex programming project to my students I tell them that there are many paths that they can go down. To be a good programmer, one has to be able to venture down one of these paths and, if they decide they have made a poor choice, back up and start again. The best programmers do not fear throwing out work that they have spent a great deal of time and effort on. The best programmers look at the journey down the wrong path as a learning experience. Inexperienced programmers bend over backwards to keep the code they have been working on even when they know it is not the best solution to a problem. They cannot bring themselves to throw out hours, days, or weeks worth of work. The worst thing that a programmer can do is to become paralyzed with the fear of failure. When there are an overwhelming number of options or paths to go down, one must choose one and start walking. They might not have chosen correctly but they can't know that until they start.

One of the great things about computer programming is the tight feedback loop that a programmer has. A developer can write some code and be able to test whether the decision they made with that code moved the program forward or not. Once a developer sees some running code that verifies their understanding of the system they look at the problem in a new way. They understand how the small piece of the solution that they just tackled will influence the rest of their work. They can now see a couple steps ahead that they couldn't see before. All progress is made by having confidence in an initial idea and then moving down the path a little farther than before (or, realizing that the initial idea was not the best, starting over with a different idea). All progress is made in baby steps.

I am going through Steve Blank's 'How to Build a Startup' course right now. When starting a business one is also faced with many choices and paths. Startups should create a minimal viable product (MVP) that does not have all the bells and whistles of a production piece of software but has enough to get feedback from customers. Then, founders must 'get out of the building' and go talk to customers. This is equivalent to running one's program and taking a few more steps down the right path. I tell my students not to write code for eight hours before compiling it for the first time. They should write a few lines of code and then run them to see what effect they had on the system. This is similar to the MVP. Building a startup on an untested theory about what your customers want is like going too long in between compiles and runs.

Founders must not fear backing up and trying something new. This is called a pivot and the founders have to repeat the process until they know they are building the right business. It is common, even expected, that startup founders fail more often than most people. Most people have an adverse relationship with failure but entrepreneurs and computer programmers are used to it. Computer science students should learn about entrepreneurship because they are conditioned to try, fail, learn, and repeat. They are unwittingly trained in the skills that most entrepreneurs find to be the hardest to learn!

Wednesday, March 27, 2013

Knowledge work is a lonely activity

Performing work on a computer is a mostly solitary activity. One can generally only reflect on one’s own experiences. It is difficult to get inspiration and learn from others. Because of the nature of our work and the tools we use it is as if we software developers go out of our way to hide how we do our work.

Imagine if you were learning to play chess but you could never play against anyone but yourself. One cannot expect to become a great chess player without being able to watch masters play the game. After they leave school many software developers are left in this situation. It is not so easy for others to watch and learn from knowledge workers doing work on a computer because working in front of a monitor in a cube is not an inviting learning environment.

The software development community is in need of tools that open up the development process to encourage learning by team members. It is critically important to:
  • get feedback from ‘masters’ about our work
  • see how developers leverage good decisions and extend their position from them
  • see how developers recover from bad decisions
The learning dilemma
Software developers need to be continuous learners to keep up with changes in the field. Young developers fresh out of college have decade’s worth of learning in front of them. The questions that I am interested in are:
  • How do software developers learn about the systems they are hired to work on so they can be effective members of a team?
  • How do software developers learn to be better programmers after they have left school?
Software developers have an incredible amount of information to learn over their careers but not much structure and guidance to acquire that knowledge. This is the learning dilemma. Some of the techniques that developers use to learn about software development after they have left school are:
Try, then fail, then fix
Failing at something followed by remedial work can lead to excellent gains in knowledge. However, this knowledge can be painful to acquire. Perhaps the most insidious characteristic of this type of learning is how difficult it is to impart the hard earned knowledge on others. Only the developer who makes the mistake and fixes it learns.

Read books and blogs
Books and blog posts on the subject of software development are great tools for professional developers to learn. However, not every topic has a high quality book or blog post written about it. Invariably, each developer encounters some level of specialization where finding reading material is impossible.

Read code
One might think that reading good code is a natural way to learn to become a better programmer. This can be tricky, however, because most developers read code left to right, top to bottom, jumping occasionally to other functions and files. But, how often is code actually written this way?

When writing code it is common to touch many different parts of many different files. The order of the additions and the deletions has an impact on how a problem was solved. Existing version control systems do not record enough of this information.

Code comments could be useful for telling a story about a system but they are not always the best place to record historical information. For example, if a developer is changing the name of a variable from ‘age’ to ‘yearsExperience’, they could write a comment about why that change was needed. That comment is really only relevant to the people who knew the old name and are interested in why the old name changed. Developers who never knew the old name are not interested in that comment. So, most developers would not write down that information anywhere.

Commit logs
On check in, developers write a commit message to the version control log. These logs could help animate the changes in a group of files if developers wrote good messages. Unfortunately, they do not. It is very difficult to write a complete description of all the changes that take place from one commit to another. Remembering and describing why we make a set of changes in a commit message is almost as hard as writing the code itself.

Code reviews 
Code reviews are an excellent way to learn from one's peers. Some of the best discussions I have ever had about software engineering have taken place in code reviews. There is a significant drawback to code reviews, however, the team only gets one chance to perform the review. If one is not lucky enough to be in that review they miss out on all the learning that takes place there. Ideally, a narrative about a code review would exist that all developers could consume.

Q&A sites
Question and answer websites that target developers and programming problems provide good opportunities for learning. One criticism of these opportunities is that they only happen when a developer is stuck. In other words, the sites provide only reactive opportunities to learn, not proactive ones.

There are clearly many people who are willing to help provide these reactive learning experiences. The people who answer questions have different motivations. Some genuinely want to help others learn something about software development. Some are building reputations that they hope to leverage professionally and some are supporting specific products. Regardless of why people choose to answer questions, they should have a chance to be more proactive.

Why don't we record more?
I have been working with my students on a new version control system that captures very fine-grained, textual information about coding sessions. It allows the sessions to be played back so a developer can tell a story about their code. These stories form a new type of program documentation that can be viewed by team members to learn about the systems they are working on and to learn how to become better developers.

I have had discussions with professional software developers about how our tool records every single keystroke and makes it available to be played back. Some are afraid of others being able to see all the mistakes that they make. Some have even asked if there was an option to 'turn off' the recording of data. 

I try to explain that all developers make mistakes and that there is value in a lot of those mistakes.  One can teach their colleagues by walking them through the misunderstandings and misconceptions they had of their system. Most of the mistakes I make are due to an incomplete understanding of the requirements, the existing system, or the algorithms being used. If I am having trouble understanding these then surely someone else might be too. Why should we all have to suffer through the same painful discovery process? 

If we recorded more data about the programming process and provided stories about the reasons why things were done a certain way it would be easier for us to teach and learn from each other. Knowledge work would become a less lonely activity.

Monday, March 25, 2013

The right way and the wrong way for learning a thinking person's craft

I have been teaching computer science to undergraduates for more than ten years. Lately, I have had a sneaking suspicion that I (and the rest of the world) am doing it wrong. One learns to write good software by first writing a lot of bad software. Then, one day, after having written a lot of code, one becomes good enough to write software professionally. For me, I first felt qualified to write software professionally at least one year after graduation. During that year or so I was paid very well to learn how to do it right. I am very grateful to the company that subsidized this learning experience for me but I have a feeling they would have preferred hiring someone ready to make a lasting contribution on or around day one.

Why aren't most freshly minted computer science graduates qualified to write code professionally?
I believe a fundamental problem with the typical undergraduate computer science curriculum is that it breaks its learning units into discrete, relatively non-overlapping units that don't emphasize an integrated, hands-on approach to learning the craft. It drives me crazy when a student asks me about the syntax for creating an interface in some programming language because they have not actually done it since their OOP class. Similarly, I feel like I haven't done my job well when they ask me how to spawn a thread because they haven't done so since their operating systems class.

Writing software is a craft. One definition of craftsman is "one that learns by doing". Cabinet makers do not take separate courses on framing, drawer construction, and finishing and then wait until they leave cabinet making school to build their first cabinet. They learn those skills by spending several hours each day practicing them. With all their other responsibilities, I would guess that the typical undergraduate computer science student does not spend several hours a day, every day, writing code. They don't, but they should. We should expect them to do that. We should set up an environment where they can do that.

Should software development be taught like a trade like cabinet making or plumbing?
An argument can be made that there should be trade schools that teach software development. Perhaps it should not be taught in the same higher education environment that students learn mathematics or biology. There is a growing movement to train software developers through mentoring and on the job training. 8th Light in Chicago is an example of doing this well.

However, writing software is a thinking person's craft. Having been around software developers for more than 15 years I believe that those who receive a liberal arts education are more interesting people. They work better with others. They are better readers, writers, and communicators. They have a distinct advantage in all of the 'soft' people skills that are as important as the 'hard' technical skills. We should not deny computer science students the opportunity to grow in these environments. This is the dilemma- software developers need a mix of a craftsman's education and a traditional college education.

The right way
If I had no restrictions in setting up a new curriculum for computer science students these are some of the things that I would do to mix learning styles:

Students who are interested in computer science will start with the traditional sequence of introductory  courses in their first two years. They will take other courses to meet full time status. In other words, there will not be any difference for freshmen and sophomores studying computer science in this new environment than in a traditional environment.

Then, after a student has committed to studying computer science, they would transition to a mix of a traditional and a craftsman's learning environment during their final two years. Students will spend at least four hours a day, five days a week, for at least the last two years of a four year education working:
  • with a mentor
  • in a lab on campus dedicated to the craft
  • with changing team members 
  • on different projects both large and small
  • during the summer (if not interning for a company)
During this mixed time, students will take one or two non-computer science classes in their off hours. Students in the program will be assessed for roughly the same knowledge as in a traditional computer science environment. In other words, they will need to know the same information about networks, operating systems, databases, etc. as a traditional CS student taking individual courses on these topics. However, they will have to learn about them through the projects they are working on.

A college would have to set up an entity to take on projects for the community, local schools, for departments and programs within the college, for churches, for local government bodies. This would be the epitome of technology-based service learning. One side effect is that it might attract more women to CS. Women are generally attracted to solving real world problems whereas the men are interested in technology for technology's sake. Everyone would start out working on someone else's open source project. Eventually, everyone would create several of their own open source projects.

Occasionally, I have excellent students who don't have a lot of interesting work to show potential employers. With this model, upon graduation, every student will have a real portfolio of work to show potential employees and real experience working in a group.

Monday, January 14, 2013

The invisibility of software and the coding warroom

Software is one of the few things built by humans that is incredibly hard for us to fully see. This is true during the construction process and after it is 'complete' (one problem is that good software is never really complete- new features are constantly added, it is made easier to use, and it gets fixed when bugs are found). It is very difficult to get a sense of how all the pieces fit together.

When asked by a layman to describe how modern software (i.e. large software) is built I like to use an analogy. Building a large piece of software is like building a skyscraper where the construction workers can only work at night and each worker has only a small flashlight to guide them. One can only see about ten feet in front of them at any one time.

We write code on small screens and can only see a tiny fraction of it at any one time. We use certain models to help get different perspectives of our systems but we cannot pick up and examine the pieces and see how they fit together like we can with almost every other thing that is engineered.

It is even harder to visualize how software changes over time. With time lapse photography one can see how a skyscraper evolves but the same is not possible with software. How does one see how some exceptional work has evolved from the early beginnings to a mature and extensible solution? Most of the code I am proud of was grown over many iterations. There is usually a good story about how the code changed over time but these stories rarely get told to anyone and almost never get written down anywhere. They stay in our heads for a little while but they inevitably escape into the ether.

In order for developers to grow and learn we must open up for examination how we do our work. One would think that knowledge workers, because of their ability to gather and manipulate data, would excel at capturing and presenting this information to their peers. However, if you look at some of our tools (our version control systems in particular) we are pretty bad at it. For example, some of the most valuable thought work that we do happens at the whiteboard. Inevitably, it gets erased shortly after we create it. We rely on our memories to store much of this valuable information and the stories about how the work has evolved. I think a more reliable storage mechanism should be used.

I have often wondered what it would be like for software developers to project their work in 'warroom' like environments. Imagine groups of developers working together where everyone could see what is happening by members of the team. This would certainly help (at least partially) solve the 'invisibility' problem by expanding our view of the system beyond the 10 foot limit.

Monday, January 7, 2013

So, you think you're a good software developer? Who have you taught lately?

The Learning Dilemma

The day one graduates from college with a degree in computer science is usually a joyous day. It is on this day, however, that most realize that their educations have really just begun (I know I felt rather unqualified at this point). All software developers have decades worth of learning in front of them. In no other field is this more true than in computer science. Our field is so new and so important that one cannot expect to make a real contribution without a serious commitment to learning over an entire career.

This knowledge will be hard to acquire, however, because there will be no more lectures, formal assignments, tutors, or professors to guide them along the right path. For a professional developer, most learning takes place while building a real system. To make matters worse, knowledge workers have an additional burden- it is extremely hard to see how others do their work.

Working on a computer is a mostly solitary activity. We sit in front of our machines and do our work. Rarely, do we invite others to see what we do or how we do it. There may be a great developer sitting three feet away from you but it is unlikely that you will ever learn anything from watching them work. Or, you may be that great developer, and you may be surrounded by lesser developers who want desperately to learn what you know. Because of the nature of work done on a computer it is not entirely clear that your knowledge will spread to the people geographically close to you. Compare this with sculptors sharing an art studio and you will see that knowledge workers are at a disadvantage.

Good Developers Teach

We have excellent teaching resources available to us, these are our best developers. There is a dangerous misconception that our 'rock star' developers are too valuable to slow down to help teach the rest of the team. I would argue that if you want to call yourself a good developer you must:
  • actively teach the people around you to become better
  • actively seek out learning experiences from others with different experiences
In other words, it does not matter who you are, everyone on the team should be held accountable for a certain amount of teaching and learning. Developers should be evaluated on how well they do both. This is something that can easily be measured. Further, team members can help each other achieve these complimentary goals by being active teachers and learners.

Our best developers should be given a venue to teach what they know. Management should survey the team to find the most obvious and high value deficiencies of the majority that can be remedied by the minority. The lesser developers on the team may not be able to teach the rock stars many things about software development but they can teach about other experiences that might be of value. For example, I learned a lot about the culture of China from a chinese co-worker of mine who was an electrical engineer. This knowledge has colored my view of offshore manufacturing and engineering ever since.

My advice for computer science students who are still in school is to try and land a job as a department tutor. You will learn how to teach others by listening to how your clients perceive their problems and coming up with suggestions that match their needs. You will take this skill with you into the 'real world' where it will be put to good use. Interestingly, since people perceive things differently and have different backgrounds you will most likely learn things from the people you are trying to teach! This is something that always amazed me while I was a tutor and still amazes me today as a college professor.