Thursday, March 12, 2015

Simplify Simplify Simplify

One of the things beginners do when learning how to program is to make things more complicated then they need to be. It’s a natural thing because they often don’t know the shortcuts. They may not know enough library routines or even enough language features. So they build complicated ways around what they don’t know using what they do know. It’s that old story of when you only have a hammer all your problems look like nails.

Everyone once in a while my students are the ones with the shortcut and I’m the one who over complicates things. That happened to me with a recent project. I assigned my students the project I blogged about in Simulations Are More Fun recently. As is my practice I coded up a sample solution myself. I liked my solution. It was cool. My students took an easier path though.

I over thought the problem. The problem includes the detail “If the biggest number rolled is five or six, player 2 wins” so my first thought was to determine the biggest number and then check it’s value. I got even more clever by creating a function that took two numbers and returned the value of the larger. It worked wonderfully but it added additional complexity without adding real additional value. My students just checked the two values with an OR  expression. Sort of like this:

   1: if (die1 >= 5 || die2 >= 5)
   2:     player2++;
   3: else
   4:     player1++;

Nice and simple with no extra method call overhead.It’s actually sort of elegant.

My problem, if I can call it that, is that I tend to think of solutions that scale. I’ve spent a lot of time in my career dealing with big problems and big data. This colors how I look at some problems. This problem is simple with a very small data set and this simple if works great in this case. If I had to compare a value to the highest value in an array this simple solution could be limiting. It would get complicated very quickly. Having a method that found and returned the highest value in an array (something we talked about in class when introducing arrays) would make things easier. Or at least simpler in the if statement.

This is something I will talk about in the future as I try and continue to work scalable solutions and how to design for scalability. But we’ll also have to keep an eye out for simple solutions as well.


Mike Zamansky said...

It's worth certainly worth discussion but there isn't a clear answer.

One could argue that abstracting out the test in a function call is cleaner and how much overhead is it really? Besides won't an optimizing compiler inline it anyway.

Of course, you argue the other side just as well.

The beauty is that we can have this discussion with the class over and over in many contexts and they can hopefully learn when each is appropriate.

Alfred C Thompson II said...

Great point about the optimizing compiler. That is of course yet another great thing to discuss in class.

Mike Zamansky said...

Many CS teachers come from math and in math there's usually little room for discussion/opinion.

This is how CS can be more like humanities classes - so many times where the topic isn't really about the topic but rather a platform to discuss something more open ended without a clear cut right answer.

Garth said...

I just had a similar event. We were reading data from a text file in Java in a two part assignment. The assignment said do not use an array for part two. So I do part one without arrays. Royal pain but I figured a solution with a bunch of If statements. Very ugly. So I figured I would do it with arrays anyway just for the learning experience. Piece of cake. Very simple. I would teach the kids both ways. The university professor who has been helping me with the course (remember I am learning Java as I teach it?) came over to help and demonstrated a third way to do the problem. All three worked. All three depended on skill level with the language and the tools known. After a little thought I sort of like my two solutions better than his. My solutions would transfer to almost any language. His was very Java specific. This is why this stuff is fun. The three very different solutions prompted me to ask him how he grades programming assignments. “It works and I can read it” were the main criteria. “It works” is obvious. He said variable naming and proper comments, not excessive comments, were the key to the second criteria.

Anonymous said...

I really like Casey Muratori's concept of "compression-oriented programming" and try to introduce my CS students to functions through this technique. I.e., write the simplest thing possible until you have multiple identical (or almost identical) copies of it, then -- and only then -- factor it into functions/classes/larger abstract structures. Certainly as we get more versed in writing code, we may jump immediately to writing a function when we know it will be useful, but from a pedagogical perspective, I really like introducing abstraction and higher level structures through this technique.

Also, definitely agree with Mike Zamansky about how CS can be more like humanities (or even art) than math.

Jonathan Kaye said...

Good post, this reminds me of a situation from my college days (25 years ago) that still irritates me a bit, and of course I still remember it -- from my (the student's) perspective.

The assignment involved testing a series of 3 boolean variables, whose values were not independent, for example, in the problem context, all three could not be true at the same time. Rather than putting an expression that involved all the variables, I found an equally correct expression for this situation that simply tested one value, such as testing that some_variable == false.

This worked for the problem, but the TA deducted points from my assignment because I didn't test all the values. I was upset because I knew exactly what I was doing by simplifying the expression, but the TA was trying to teach me that I should have checked the other values as well to see if they conformed to the problem context (the consistency). I understand what he was trying to say, especially because if there were a context problem, this would have been a bug that would have been very difficult to find, but I was peeved that we were not in that situation. Instead of using the opportunity to have a teachable moment, he tinged the experience with bitterness by deducting points. I think that was unfortunate, though on the other hand, I still remember the situation after all these years, maybe that sting had a lasting value.

In my programming career, I am very careful about enforcing assumptions I make by asserting possible values (ensuring values conform to the problem context I assume). In the right context for teaching others, it would be a useful discussion about optimization and possibly over-optimization.