PySweeper: Getting Started 5
It’s time for me to do a little code cleaning. I keep talking about open source, but lately it’s been all hat and no cattle (well, other than an unreleased FitNesse change I helped with). I looked for something fun involving Python. I figure I will learn pygame and eclipse PyDev and see what I can learn and teach from the experience.
I have chosen a simple little game called PySweeper. PySweeper is a minesweeper-like game copyright 2002 by Brett Smith. It is very much like the famous MineSweeper game one might find on a Windows computer (remember Windows?).
I confess to never having played minesweeper, so I actually learned the rules by reading the code. If you play minesweeper, feel free to skip the next paragraph.
The playing field is a grid of squares. Under some squares there are hidden mines (one per square) and under others there are not. The idea is that you click on a square on the grid. If you click on a mine, you are blown up and the game is over. If the square does not have a mine, but is adjacent to one or more cells that have mines, it will open up to show a count of mines present in the surrounding cells. The cell does not indicate the direction of the mine. These counts are the only clues you get as to the location of the mines. If the cell you choose is not adjacent to any mines, it will show up blank and will open all its adjacent cells. The adjacent cells act as if they are clicked on, and either show a count of mines nearby or else show a blank and open their neighbors. Sometimes one click can show you quite a lot of clues. If you believe you know where a mine is, you can mark it with a flag by right-clicking. If you correctly guess all the positions of all the mines, then you win.
Since Mr. Smith put PySweeper under the GPL I have permission to change it, publish it, and use it for whatever purposes I choose provided I pass on the same freedoms to the people who use my version of the code, and provided I make the source available when i distribute its executables. This just another way in which the GPL is a good idea. I couldn’t do this without accessing, modifying, and publishing the code, so I am most grateful to B.Smith for providing me with a solid starting point.
I am an XUbuntu (Edgy Eft) user right now, so I installed my Eclipse PyDev plugin via the wonderful Debian Advanced Packaging Tools (APT). I don’t know people live without APT. It’s the best way I’ve ever seen for managing the software on my computers. With APT, I don’t have to go looking for software to install. I don’t have any dependency problems (“dll hell” in windows parlance. I can install and uninstall all the software I want and it doesn’t make my computer slow down or get sick or die. I can very easily get upgrades (security as well as feature releases) to everything I’m running all through the same system with a single command. I have a vast catalog of software available to me for free. It’s glorious. Thanks to the Debian project for the wonderful work. Someday I must look into the code for that.
I download a compressed tar archive (.tgz) of the PySweeper-1.0 source code. I start by unzipping the code into my project directory and then I fire up up Eclipse and Pydev. Poor Pydev doesn’t know if I want to use the C python implementation, Jython (java), or something else entirely. I take a moment to configure it. It’s not hard or confusing. Now I fire up Eclipse again to see if it understands my python code. Well, it almost does. The main file of pysweeper is called “pysweeper”, with no ”.py” extension. Surely, if eclipse used the Linux file command, it would know that it’s looking at a Python program, but apparently it does not. There is no syntax highlighting at all. I sigh. Just to start the ball rolling, I rename the file “pysweeper.py” and load it up. Much better.
The default Python syntax highlighting feature is pleasing to me. Comments are a pale gray on a white background so it is easy to skip them. Mr. Smith spent some time writing comments to explain his code, but I want the code to talk to me. I might delete all but the licensing and authorship docs.
Next installment, I’ll play with the environment and get a start on cleaning some code.
Comments again. 75
In the great repositories of programming errors I found this little jewel. Aren’t we glad we had all those comments to guide us?
This is another way that comments become lies over time: nobody maintains them. Nobody maintains them because they litter up the code and programmers have to learn to look past them to see what code is doing. Sometimes we have to page down through a lot of them to find a useful bit of code. It’s why we’re glad for syntax highlighting, so we can more easily ignore them all.
The answer is probably not to write more comments, or to write them in a catchy style, or to demand that programmers look at them more carefully. Probably the answer is to obviate them (write them into the code) and delete them. We are all trained to look rather carefully at the code.
Looking at this example, can you tell why the parental control is set to three? Probably not. You could guess. More likely, you would agree if it were set to DEFAULT_SAFETY_LEVEL, but if DEFAULT_SAFETY_LEVEL is 3 you are no better off.
But what if there were constants like NO_FILTERING, MODERATE_FILTERING, and STRICT_FILTERING and DEFAULT_FILTERING_LEVEL were set to STRICT_FILTERING, and the variable were ‘parental_filtering_level’? Then there is a lot more information available to you. So you’d delete the comments. When you were testing DEFAULT_FILTERING_LEVEL would be NO_FILTERING, later you would change it to MODERATE_FILTERING , and maybe pre-release you would set it to STRICT_FILTERING. The change and its check-in comments would tell the whole story.
That having been said, I don’t know that I have interpreted the variable and setting correctly. Even having comments doesn’t tell me what the variable and the value ‘1’,’2’, or ‘3’ really mean.
This is what I mean when I say that I don’t like comments. They need to be obviated first, and then deleted. Sometimes it is even best to delete them all, and then try to figure out the code as a means of training oneself to write more descriptive code.
If the code cannot express itself, then a comment might be acceptable. If the code does not express itself, the code should be fixed. Either way, obsolete comments and those that do not add value should be dropped like a hot rock.
Inability to Look Ahead 9
I stumbled across another interesting article today on our inability to plan ahead, specifically to determine in advance what will make us happy later on.
One group has to choose which sandwiches they want for an entire week in advance. The other group gets to choose which they want each day. A fascinating thing happens. People who choose their favourite sandwich each day at lunchtime also often choose the same sandwich. This group turns out to be reasonably happy with its choice. Amazingly, though, people choosing in advance assume that what they’ll want for lunch next week is a variety. And so they choose a turkey sandwich Monday, tuna on Tuesday, egg on Wednesday and so on. It turn out that when next week rolls around they generally don’t like the variety they thought they would. In fact they are significantly less happy with their choices than the group who chose their sandwiches on the day.
This is hardly a surprise to any veteran of software development. It doesn’t prove that all planning is a waste of time (of course not!) but it shows that it’s hard to guess what we’ll want next week for lunch. I am surprised we ever know what we’ll want next year in software.
Software people for years have complained that users don’t know what they want and that the requirements keep changing. Of course they do, and of course they always have. The existence of an automated system changes any practice, and changes the set of things a practitioner will desire to do next. This has been the basis for rapid development and agile pratices for some time. It underpins the whole spiral/iterative model.
Just an observation: it is deucedly hard to plan to be happy in advance. It is hard enough to be present in the moment, and to take advantage of the opportunities that come your way. We should plan, and we should prepare (hopefully better than I do) so that we’re ready for the opportunities that come for us. We might even create a few opportunities. But we shouldn’t be surprised in a world as complex and variable as ours that we can’t nail down the future exactly, in software requirements or career planning.
Good things come ... eventually 15
There is an old adage that good things come to those who wait, provided they work real hard while waiting.
I read a blog article today that made me sad. The blogger mentioned that they were doing TDD and using Clean Code techniques and building a working system. His company, apparently distrustful of the newness of his approach, hired a consultant to come and critique the team’s code. I like that the company lets the team try new things, and that they decided to check on the team’s results. So far, this is all good.
Here’s the sad thing: the consultant (allegedly) made a number of old-school recommendations based on practices that have been obviated.
He suggested having comments and name warts and other ugliness. It was almost like he was recommending regression based on the idea that “normal” programmers aren’t able to deal with good code, being accustomed to ugly code with apologies scattered throughout. That’s unfortunate, and I suspect it’s extremely good-intentioned. I would call it a “misplaced kindness.”
I don’t know the blogger’s company and wouldn’t ask, but in general I am always surprised at how slowly transition takes place in larger companies. Body inertia (in the F=ma sense) is hard to overcome so people are using expensive version control systems that are two generations behind the times, old-fashioned waterfall methods, code documentation practices that are completely obviated, a total sense of denial toward open-source tools, and rigid frameworks whose owners have abandoned them for more workable systems. It’s an ugly situation, but on the other hand countless fads and bad ideas have caught fire only to die out. Those companies nearer the trailing edge didn’t jump on the wagon only to jump off painfully later. There is an advantage to being a late adapter.
The trick in working with the slow transition is that we mustn’t confuse frustration with failure. Ultimately, the world does move forward and new practices are eventually accepted. It is an issue of patience with those who drag behind and perseverance in moving them forward. It’s primarily a matter of education and evidence and time.
Somehow OO and dynamic languages and version control and CM and all of various other breakthroughs eventually permeate the work-o-sphere. Few of us need to ask permission to use OO or to draw UML on a whiteboard or to use color syntax highlighting or “intellisense” or word processors or our favorite text editors, but at one time we had to fight about it.
If the Agile ways are better (and I think they are) then we’ll eventually see these techniques as the mainstream and the idea of naming warts, long functions with long comments, and test-last programming will seem laughable and quaint to the most conservative organization. Refactoring tools will be the least we expect from our IDEs, and open source servers and libraries will be prevalent. I think that day is coming.
Aiming High: Good Architecture 16
I would say that a good architecture is one in which a solution can be built, tested, and deployed, and within which all points of maintenance are singular and well-placed.
Now it’s nothing new, and nothing earth-shatteringly well said maybe, but I think it’s the first time I’ve successfully managed to express what I want.
Put even more vaguely and more tersly, I could say “it works and I can continue working in it”, but that actually says less than I want.
Procrastination 36
I serendipitously received two things today. One was a link to an article on procrastination and the other was an email about YAGNI. It took me a moment or two to realise that they are talking about the same thing. In the procrastination case, it’s seen in a more negative light, and in the YAGNI case it’s exalted.
The phrase from the procrastination article that really hit me was that procrastinators “value today more than tomorrow.” That’s what Agile is like, too.
Maybe Agile is partly about creative, productive procrastination?
Curly's Guide To Software 22
In the movie City Slickers, weathered cowboy Curly told the clueless ranch noobs that he’d found the secret of life. He held up his index finger, and announced “One Thing.”
I suspect that Curly had a mighty good idea, that you should be able to do one thing supremely well instead of doing and being all things. For all our units of software, One is a very friendly number, indeed.
First we look at lines of code. A line of code has ONE statement on it. That doesn’t mean that I can’t write
if x: do yas a single line. That’s one-thing-y enough if the Y and the X are simple.
Secondly, a statement has one effect. I don’t have a single expression that increments counters and assigns values. Software in the old style of C such as
*dest++ = *src++;doesn’t get much play in my world. Avoiding side-effects is pretty widely regarded as a good idea, and I think no less so in individual statements. I will make exception for the forstatement, which is a special case. I always avoid the for loop when an iterator loop such as a for each is available.
Next we move to functions. I am increasingly fond of Meyers’ Query/Command Separation principle, and of course the python philosophy that a function should either do something or tell you something. I find that the focus on clear naming for functions helps me here, because a function whose name begs for an “and” is an ill-conceived function. Whether it’s a static or a member function or whatever, it needs to do ONE thing.
Then we move to classes. We have expounded on the Single Responsibility Principle and class normalization enough that I don’t need to flog that horse here, but you know what I’m talking about. A class that has multiple purposes or knows too much is a class that will cause problems. It is unfocused, and unstable (in that Positional Stability sense). It’s trouble. Better to do one thing very well.
Packages can easily accrue more features than they should have. We have our various principles of package dependency management to ensure that a package doesn’t know too much or do too much. Again, each should have focus. One is important.
Finally, through my life (mostly in Unixen, including Linux) I have learned the value of programs that do only one thing (perhaps with a variety of parameters and tools). I don’t like them to be both a floor wax and a dessert topping. When an application does one thing, and then starts to accrue features that really are different, I generally find great dissatisfaction. I don’t edit html in word or openoffice. I don’t use my word processor to create spreadsheets, and I don’ t do my programming in my email system. That seems more obvious than it really is sometimes, but it is yet another application of One Thing.
Scoring More Points 12
In a recent article at Agile Journal there is a nice quote from John Cunningham, regarding the tendency of metrics-collectors to major in minors
I listen to all these analysts (professionals) tell us that the keys to winning are running the ball (increasing time of possession) and stopping the run (decreasing the opposition’s ability to control the ball). Nonsense! These are not the keys. Scoring more points than the opposition is the key
There article continues to recomment useful ways of measuring the success of an agile project. It is of particular interest to organizations transitioning to agile.
Magic Comments and Magic Strings 101
You know what I hate? Okay, other than wasted vertical space and stupid programming comments… I hate magic comments. I am still an egg wrt Java but I just looked at the java comments like @noinspect. I think that these comments are “clever” in the WallyMoore school of clever == bad. Comments are supposed to be something that the compiler ignores, and sure enough they are. But here we have special semantic value given to special comments for use by bits of the development environment. Maybe it would have been better to add new syntax, new keywords, some kind of magic pragma thing, but doing this in comments is almost as bad as doing it in magic strings (as python’s doctest does).
Surely using magic comments and magic strings is evidence that we’ve run out of better ideas. It smells like a short-term hack to me. It’s frustrating, and annoying. It’s a “conceptual dog-leg”. You have to bend the idea 45 degrees to port to realize that yes, they can make it work that way. It’s a shoehorn hack.
Sure it works, but is that how it should work? Hopefully with aspects and decorators (python) and attributes and the like we can come up with something better than magic comments and magic strings.
At least I can pray we do.
Restarting 76
Today I had a problem in Eclipse—a coworker couldn’t commit.
We found he wasn’t in the svn group on the server, so that’s perfectly okay and not eclipse’s fault. After fixing that, he still could not commit, and with the same error. After an hour or so of tail-chasing, and trying the command line, I eventually realized that he was in Windows. I used standard windows answer part A: restart the app. Guess what? It worked PERFECTLY. That’s good because part B is “restart the client” and part C is the unacceptable—restart the server.
It’s amazing the kinds of unscheduled events that take time out of a day, but it was worth my time to make sure that a teammate could be productive. Especially since work was done but blocked from being checked in.
It’s another reason not to schedule 8 productive hours per day when estimating by time. The story point method is better, because we’ve absorbed all the “normal” maintenance and “average” amounts of troubleshooting into our velocity semi-accidentally. I don’t have to account specifically for the normal “noise” necessarily part of the normal software development “signal”.