Wednesday, March 16, 2016

Up the Creek Without a Paddle: How Schools are Failing Novice Programmers

There seems to be no shortage of things to gripe about when it comes to how schools are teaching computer programming these days. Today was no different. In this post, I will talk about how schools are failing to develop the right skills and habits in students as they learn how to program. I will also explain what I think needs to be done about this problem.

With the way I've seen instruction being structured, I think many students who aspire to become professional software developers are getting off to a bad start. Even if they don't intend to pursue a career in software development, they are still not getting much of a chance to learn how to write programs properly given the way teachers are, in my opinion, focusing too much on the "how" rather than the "what" and "why" of programming.

Analogies


I'm going to use the expression "up a creek without a paddle" to describe the situation many students find themselves in these days in their computer programming courses. If you're unfamiliar with that expression, then perhaps you're more familiar with "stuck between a rock and a hard place." 

Granted, students are not really put in such difficult positions as to navigate fouled up waterways without any implements. They are not made to endure anything remotely close to the harrowing ordeal that Aron Ralston survived only by amputating his own forearm five days after it was crushed by a boulder (rock) against a canyon wall (hard place) while he was out hiking alone in a remote area in Utah. The analogies are in the way students seem to be ill-prepared to meet the programming challenges they are given by instructors.

I think the sense of helplessness these expressions convey and Aron Ralston's true-to-life story are great analogies for how students feel when they are put at a terrible and unfair disadvantage because teachers neglect to give them good basic tools that could help them get through their programming problems in less time and with less confusion and frustration.

Lessons in Teaching taken from a Swim Coach


Speaking of teachers, I have a friend who teaches young children how to swim. Cecil and I are from the same hometown in the Philippines. He used to be a competitive swimmer but the interesting thing about that is that he's not very tall. Height is obviously an advantage when it comes to competitive swimming. I would say Cecil is a just a tad over five feet on a good day. I may be slightly off with those specifics but that's not the point.

The point is that despite his height disadvantage, Cecil was able to stay relatively competitive in his youth by developing a very efficient technique. He would literally glide through the water with very little effort. Cecil was competitive because he had really good swimming form. Of course, having a competition-sized swimming pool at home didn't hurt either. 

Cecil's family, or I should say clan, collectively owns the regionally famous Timoga Cold Spring Pools which are comprised of a dozen or so swimming pools that are fed by clean, cold, crystal clear, and constantly flowing spring water. Each family in their clan owns a portion of the land through which the spring water flows. They practically have money overflowing in their front yard and they have capitalized on it and continue to prosper from it to this day. Obviously, Cecil was able to swim every day so he also developed great endurance to match his excellent form.

When I first met Cecil, he was teaching my then girlfriend and future wife how to swim. For a late learner, she did all right. What struck me about Cecil's teaching method was that he really emphasized good form. He would have my wife and her classmates practice in the shallow end working on lifting their arms above the water just enough to skim the surface with their fingers and then cupping their hands and pulling, then pushing the water under their bodies below the surface. 

He would then have them work on rolling their shoulders just right to make their arm movements more efficient and comfortable. Then he'd have them work on their flutter kick so that, too, would be efficient and require just enough effort to stabilize their bodies and keep them at the right angle in the water so that they created as little drag as possible.

I even improved my swimming technique after trying out what Cecil was teaching, so much so that I was able to keep up with him a little bit while he would swim laps after my wife's swimming classes. Of course, it turned out that he was just maintaining a slower pace for my sake, but still, I did all right for a non-competitive weekend swimmer.

Cecil now coaches for a swim club in Cincinnati, just a couple of hours down Interstate 71 and we still occasionally see each other or call to say "Hi." He stays on the dry side of swim competitions now, still teaching kids the right way to swim and get efficient at it. I hear the kids he coaches in swim club do pretty well at competitions. His two children have carried on their father's legacy, being also somewhat small in stature but big in form and efficiency as well.

Which comes first, Form or Function?


Cecil's teaching method is in sharp contrast with what I have observed from students asking questions on JavaRanch as well as what I've seen with my son, who is taking "Introduction to Computer Programming in Java" at Ohio State University this semester. It's frustrating to see my son's slow progress and the poor habits that he, too, is starting to form in just a few months of studying programming at a college level.

Rather than first teaching students basic form and good coding habits, instructors seem to be asking students to plunge right into the nitty-gritty details of the language, giving them problems to solve without any idea of a good, sensible, and systematic approach for doing so. 

This "sink or swim" approach to teaching, or so it seems to me, does not appear to be limited to students in introductory courses. Apparently, those who go on to study more advanced programming concepts are still sent off without a proverbial paddle into a creek where the current is getting swifter and more challenging to handle.

Take JavaRanch greenhorn and confused student Jason Ram, for example, the original poster in this thread on JavaRanch about calculating Degrees of Separation from Kevin Bacon. Go check out that thread first, so you understand where I'm going with this next.

Jason said that this is his second semester studying programming and that the tips I gave him on basic program organization was more than he had gotten from his instructors in two semesters. It took me less than fifteen minutes to compose the pair of responses I gave him and for him to say that it was more than what he'd gotten in two semesters is quite appalling and disappointing.

Functional decomposition is one of the first basic steps towards managing the complexity of both the problem as well as the solution to that problem. Without properly breaking down the problem and solution into smaller component parts, you end up with a confusing jumble of unreadable code similar to what Jason posted as his working solution. In this case, it was around seventy (70!) lines of code jammed into the static main() method. 

How can this be acceptable for a student who is well into his second programming course? Don't get me wrong, I'm not faulting the student here. It's the teachers who I think are to blame for this, for not teaching the students about code hygiene and basic problem decomposition and organization.

The Fountain of All Evil Programs


This is the never-ending source of the sloppiness and cruft that I have seen in a lot of code written by developers in the real world. Code that was seemingly written to just get it done, without much regard to cleanliness and proper design and organization. I often see code written in Java, an object-oriented language, that can't even pass as good procedural code, written by people who are paid to write enterprise-class programs. It's horrific!

It's like the ever-flowing cold spring water that feeds the dozens of pools in Timoga. Only this water is murky, foul, and unpleasant. Nobody wants to touch it, much less swim in it. And it's the developers who know better who have to go and clean it up.

There seems to be an abundant amount of bad code constantly flowing into our applications and stagnating there, creating a stench that at times becomes so unbearable that organizations have to spend enormous sums of money to clean up. Take a fairly recent poster child for messed up projects, Healthcare.gov. That is a failure on so many different levels, not the least of which is bad code. And we all had to pay for that cleanup, one way or another. 

Pity the fools who had to get their hands dirty with that awful code that was the first few incarnations of Healthcare.gov. This gives a good visualization of just how ugly it was. But then again, some of those people who were brought in to clean up the mess probably made off like bandits afterwards. Again, that's not the point though. Overall, there were very few winners and many losers in this fiasco. Thankfully, enough was done to get it out of the sewer and into a usable state.

You Don't Have to Look Far To Find Sh*t Code


You don't really have to go far up Sh*t Code Creek or explore the recesses of Conundrum Canyon to see how professional programmers can create labyrinths in their programs that take months of laborious effort, patience, and perseverance to escape, in such epic proportions that would put Aron Ralston to shame. Heroic and monumental efforts often have to be made to save poorly written programs so they can survive further use and abuse by increasingly demanding users and adopt to ever-changing business needs.

All it takes for most developers to find themselves eyeballs deep in the muck of bad code is to open up their current project and go to some code that they didn't write. Or even some code that they did write just a few days or hours ago. What's worse is that many programmers don't even realize they're standing in cr*p code and that they probably contributed to the mess. It's all done in a day's work and as long as the lights stay on, everything is smelling roses. 

Well, everything isn't smelling roses. They just don't know how deaf their noses are or have become. Or maybe it's the smell of roses like that at a funeral home, that masks other more unpleasant and morbid smells. Whether it's hubris, delusion, or ignorance, too many developers wallow in muck day in and day out and still don't seem to be bothered too much to do anything about it.

This is why I spend most of my time as a technical leader doing code reviews and teaching basic hygienic coding and refactoring. I have to teach programmers about basic design principles, how to recognize and fix code smells, design smells, test smells. Sure, it's fun seeing lights go on in people's heads but we have a job to do, things to get done. Business is asking us to do things faster. Oh, and by the way, could we also make it better while we're at it? Sure, right on it, boss (with excessive amount of sarcasm dripping).

Forgive Them, For They Know Not What They Do


I guess it's fitting that I write this during the season of Lent, when forgiveness, understanding, reconciliation, and love are things we should be meditating upon and practicing more consciously and deeply.

I stopped seeing programmers who write bad code or do nothing about it as evil a long time ago. I just found that this is not a useful attitude. Sure, I still resent having to clean up the slash and burn mess that itinerant consultants leave for me when they move on to other projects but I no longer want to hack into their social media accounts and deface their profiles. Or find their brand new imported cars at their new places of work and leave a poignant message with my keys. 

As cathartic as that may be for a few moments, besides the fact that it's illegal and potentially life changing for me, it really serves no useful purpose for anyone. The rest of us are still left holding the bag and looking at a huge refactoring and cleanup effort, with more of what's left of our gray hairs and gray matter sitting on death row, waiting to die from frustration and exasperation.

For our Colleagues in Academia


We in the industry need to start reaching out to our colleagues in academia and make them aware that they are creating problems for the rest of us out here in the real world with their outdated and appallingly ineffective teaching methods.

We need them to include instruction on basic coding form, coding hygiene, design principles, and design thinking. We need instructors to teach students about automated testing and encourage them to collaborate with each other instead of stubbornly enforcing strict rules against plagiarism and academic misconduct. Sure, we need to ensure integrity and proper learning and see to it that work is done honestly and by the individual to whom credit is being given. But we also need to balance that with realistic approximations of how these young people will do their work when they eventually join the workforce and get paid to do a job.

New programmers need to be taught that there are higher ideals in software development. They need instructors who will help them understand that software development is more than just writing classes, objects, methods, functions, loops, variables, data structures, algorithms, and just getting something to work. 

Programming is still as much of an art as it is a science. Programming is a creative process. It's a way of organizing your thoughts and telling a clear, coherent story in a language that not only computers can interpret and execute in a way that's congruent to what we intended it to be executed. Programs also need to be written in a way that its human author and other humans who are interested in sharing the story can easily understand and wrap their heads around it. Programmers are authors and it's high time we start living up to that title and teaching new would-be authors the ins and outs of the craft.

We need our colleagues in academia to do this from the very start, when students are still clean slates and have not yet formed any lasting habits, good or bad. Let's choose to do good by them and help cultivate in them the things that will make them better authors of software. 

Let's stop sending them up the creek without paddles or into remote canyons with only a cheap multi-tool and a dull two-inch blade in their pockets. Let's take a cue from my friend, Cecil, and teach them how to swim with proficiency and watch in wonder and joy as they start learning how to cut through the murky waters of software development with effortless efficiency and graceful elegance.

For our Colleagues in the Trenches


We in the industry have our work cut out for us as well. 

We need to get our heads out of our private and public clouds. We need to step out of our nice, shiny, new containers. Let's take a minute and put down all those nice, shiny new toys we're all eager to play around with and look around us long enough to notice that there are kids out there who are literally struggling to just get even a simple class to work properly. They don't even know how to use JUnit to save their lives!

We need to start rehabilitation programs for disadvantaged programmers who came out of school saddled with poor coding habits. Many of them lack the knowledge and understanding of basic frameworks of thinking for tackling complex problems in the ways that we professional developers—and by "professional" I don't just mean getting paid to write software, I refer to those who practice good coding and design and adhere to software craftsmanship principles and values—have learned and refined through years of experience and learning from mistakes. 

Let's not sit idly by and watch these young developers go through the same kind of pain that we had to go through in our day and still often do to this day. They are our colleagues now and hopefully someday we will be happy and proud to call them our peers. But we need to get involved and engaged with them for that to happen. As I said in this post about serendipity and in the one before it about general programming guidelines, we can't just leave it to luck and we can't just send the kids out there ill-prepared to overcome the challenges that they will inevitably have to take on.

Let's help them learn by sharing our knowledge and experience. Let's share and help them experience the joy we feel when we know we've done a good job. Let's help develop the love for craftsmanship and professionalism in our colleagues and soon-to-be peers. In that way we can all change the world for the better. That's a goal worth going up the creek for or cutting off a limb. But let's hope it never comes to that.

It's All A Big Circle of Aiki To Me


I'll close this with a thought about the Aiki arts and how all of the above ties in with the philosophy and teachings I have received through years of study and practice in the dojo. 

As I explained in my Spring cleaning post last night, Aiki is the root of Aikido, which means "the way of love and harmony" or so I've come to take it to mean. There are other, more literal translations of course, but I think I have read and heard enough of the founder's thoughts and have practiced the art long enough to grok that it really refers to the ideas and ideals that the words "love" and "harmony" encompass.

That, in essence, is what I'm calling for. We need to strive for ai nuke or mutual preservation. Competition is good. It motivates us to get better, to hone our skills, to push the edges of our abilities, and to soar to greater heights. But we can't let competition get in the way of progress either. Competition is good when it's beneficial for everyone. It's not so good when there are more losers than there are winners.

Don't get me wrong, I'm not saying that I subscribe to the idea that "everyone is a winner" and that we need to start giving out "participation medals." I personally think that's counterproductive in the long term. Good Aikido instructors will tell their students, "Good! Good! But this is how you can make it better…"  We need to encourage, not coddle. We need to lift up, not prop up.

Many practitioners of Aikido and martial arts with similar philosophies believe that if everyone subscribed to the teachings of O'Sensei Morihei Ueshiba and other like-minded martial artists, we would be well on our way to achieving world peace. That was the founder's ultimate goal in creating Aikido. 

Morihei Ueshiba grew up a warrior in a time and culture where the warrior mentality and spirit of ai uchi (mutual destruction; winning at all costs including, if necessary, sacrificing your own life while taking your enemy's) was still very prevalent and was the accepted and expected ethos.  

O'Sensei saw and experienced war and the horrors that men can inflict on other men. He wanted to change that. Creating Aikido was his way of changing things for the better. He took brutally effective techniques that had been tried and tested on the battlefield and adapted them to be more humane and life-preserving. We need to foster the spirit and way of ai nuke, or mutual preservation. There are now millions of people all over the world who study Aikido and walk that way.

You don't have to become a student of Aikido or study martial arts. Just be aware that this is where we are coming from, those of us who are. That's our goal and that's why we do the things we do the way we do them.

The principles and values of peace, love, and harmony are universal and touch all people and things. You can join us on this path, if you choose to do so. There's plenty of room on this road for those with similarly-aligned ideals and goals, no matter what their flavor or manifestation.

You might have noticed that there are many links in this post. Some of those links lead to related topics that I mention in the new blog description. If you follow them, you might start getting a sense of the kind of interconnectedness I see when I write about the things that I do. It's all a big circle of Aiki to me.

Peace be with you in this season of Lent.

No comments: