Additional profile information on Alfred Thompson at Google+
This is the second of a serious of posts based on the book Programming Proverbs by Henry Ledgard. The index for the series is an earlier post and discussion of the list as a whole is taking place in the comments there. Comments on this "proverb" are of course very welcome here.
I used to talk to my students about the difference between "Ready, Aim, Fire" and "Ready, Fire, Aim" And for that matter "Fire, Aim Ready" Ready means "Define the problem completely" of course. One really has to know what the goal is. This involves a lot of thinking. So too does thinking about the actual code to be implemented.
There are a lot of questions to ask ones self about things as complex as algorithms and as simple as variable names and types. My own personal style is to think about the program I write for some length of time before I write the first line of code. Back in the card punch days (remember those? Probably not.) I used to write out a sort of outline on paper. I thought about the various pieces of the puzzle that make up a computer program and try to make sure I knew what I was doing.
These days with powerful IDEs I often create my outline in something that looks to the casual observer like code but really isn't. There may be function/method definitions but inside them is only comments. By the time I am thinking about the actual classes and their methods and data I often use the Class Designer in Visual Studio to block things out. By specifying the methods and data for a class I can express in detail what the interfaces will be and use comments to explain what is going to happen inside them. Bit that is really still a form of thinking on paper not coding. Only later when I think I know what all the pieces are do I start real coding.
I think this proverb applies at least as much and probably more during the debugging phase. All too often I have seen students rush to through code into a now-working program in hopes that it will "fix something." A missing "End If?" Through an "End If" statement in some semi-random place in hopes of preventing the compile error but with no thought about possible logic errors. That sort of thing happens all the time. The worst thing about that sort of "problem solving" is that it introduces more frustration than solutions. The art of desk checking code and giving serious thought to what might be wrong seems to be all but dead.
During debugging a programmer really must sit and think. They must analysis their code, the error messages and what is supposed to be going on. Understanding and defining the problem must come before adding or changing code. Think first, Program later!
I came across Doug Ross' blog the other day while I was looking at the some the searches that lead people to this blog. He suggests that Assembly language should be used as a first programming language. He states that it would make a great weed out course. And of course it would. On the other hand the very last thing we need in computer science education these days is an early weed out course.
As I has reported before a lot of people in places like Slashdot are always suggesting Assembly language as a first programming language. Bill Gates told me once that he started with Assembly and stuck with it. It worked for him he said. Of course he laughed afterwards and admitted that it wouldn't work for everyone. The man has a gift for understatement. So what then is the role of Assembly language in today's computer science education? Or perhaps (since that is what I am going to give you) what does Alfred think the role should be?
I have long said and continue to believe that the first programming course should be about basic concepts taught in a way that builds student interest and gives students some early success. I believe that this is the way to get students interested in learning the more involved, closer to the hardware, and harder to learn concepts they need for long term success.
Part of a good CS education should include some Assembly language programming. Not in the first course or perhaps the second course. The second course traditionally is data structures and I like that as an idea. But before one gets into a serious operating system or compiler course they should learn Assembly language. Actually I would like them to get some experience with both RISC and CISC based operating systems. It is all well and good to learn an Assembly language the implements a loop in a single instruction. But it may even be more useful to learn an Assembly language that doesn't even have native instructions for subtract, multiple and divide. Perhaps a micro-code language? Or perhaps something that emulates the Assembly language for the PDP-8 (PAL-III)? I mean if you are going to get close to the machine get really close to the machine.
All that being said I think that it would be interesting and probably useful to expose begriming students to Assembly language in some way. Perhaps by showing them examples and discussing what is involved in programming in Assembly language. There are some emulators and simulators that would be fun and educational for that purpose. But really let the beginners have some fun before we make them get their hands covered in bits and bytes.
This is the first of a series of posts based on the book Programming Proverbs by Henry Ledgard. The index for the series is an earlier post and discussion of the list as a whole is taking place in the comments there. Comments on this "proverb" are of course very welcome here.
For a lot of people "define the problem completely" seems pretty obvious as the only right way to do things. To others, especially lately, there seems to be an idea that one should throw something together based on partial understanding, take it to the end user to see where they are, and then go to the next step. This really seems like a waste of time to me. Oh to be sure there are often times when the end user doesn't know what they want when a project is started. Someone commented earlier that "Walking On Water and Writing a Software is easy, if the Water and Specifications are FROZEN." There is some truth to that.
Historically software developers have lived with the idea that the specification will change and things will be come if not clearer at least different. That often makes it difficult, if not impossible, to define the whole system before starting.
But actually all of that is both a digression and a missing of the point. While for some people this proverb means understanding the whole system that is often, some would say always, a problem. And I think looking at that large a picture misses the point. I think that at some point one has to reach a granularity for which this proverb makes complete sense. That granularity is when one reaches a point when the amount to be coded by one person is reached. Is that a method? A class? A module? A complete program or even a small system? At that point it is a mistake not to have the problem defined and understood completely. To do otherwise is to ensure that the code will break when it comes into contact with expectations of the user or of other code. Code that is checked in with other code and does not work as expected means that the problem was not defined completely enough and someone started coding too early. There is no excuse for that in my opinion.
This idea of defining the problem completely has interesting ramifications for the teaching/learning environment. When a teacher defines a project for an assignment or an exercise for a test they assign to students there is an obligation to spell out the requirements completely. If there is ambiguity it should be there on purpose and to allow some leeway in problem solving. Students have an obligation to read and understand the definition completely before beginning to write code. Alas they seldom do. They are a lot like some professionals I have worked with I am afraid.
What I used to say to students was "I am much too lazy to write a lot of extra words so if they are there you'd better read them all." Assumptions are risky business and no less so where graded work is involved. I encouraged questions and often I re-wrote project assignments to make sure I answered those questions in the future. This was valuable both to the student, who learned to ask questions, and for me as I learned to better specify what I wanted. We never stop learning.
What is the problem? What are your inputs? What are your outputs? What do you need to know and to do to get from the inputs to the outputs? Unless those things are defined it is much too early to write code.