Python Asteroids+Invaders on GitHub

What general notions might we draw from the past few days’ work? What do you see that I do not?

Over the past several articles, I’ve been improving the code, while paying attention to the signs and signals that I used to observe the need for change, and the specific steps I took to improve things.

Signals

Confusion
When we read a class or method, is our initial reaction “???”. Take any sense of confusion as a sign that there is trouble in the neighborhood.
Listen to the Need for Comments
Kent Beck said “A comment is the code’s way of asking to be made more clear”. When I feel that the code needs comments, I look hard for alternatives, which may come from better names, more cohesive methods, breaking up a class, or any of a number of ways of making code better.

The signal is often the same, the feeling that we need a comment here.

Listen to Your Fears
Is there code in your system that you are afraid to change? If it never does need to change, perhaps that’s OK. If, as seems to happen often, it does need to change, perhaps it needs to improve as well as change.
Feature Envy
If a method on one class makes multiple references to instances of another class, this is often a sign that the other class is missing one or more capabilities (features). Adding the indicated feature almost invariably improves clarity and reliability.
Too Much Going On
Does this class do too much? Are some of its members varying at a different frequency than others? Does it have phases of operation? Is there just too much of it?

These are often signs of trouble. Generally there is more than one idea lurking here, suggesting that we need more like one object per idea.

Actions

Meaningful Names
Renaming the saucer’s earlier helpers from e.g. Ready to PostInitStrategy helped to illuminate what was going on. Even renaming denom to total_distance helped in another place.

Arguably, the prior day’s replacement of strings like “ok” with elements of an enum like CycleStatus, with values like CONTINUE, was little more than a renaming.

We will encounter this notion many times. If I gave advice, which I do not, but could only give one piece of advice, I might well choose “Use Meaningful Names”.

I continually try to get better at doing this.

Replace Primitives with Objects
From the standpoint of clarity, a specialized class is likely to be far more clear than use of a primitive string or number. An enum is better than a string. An instance of Vector is better than a bare sequence of length two.

This is a lesson that I continually have to relearn, a guideline that I continue to violate. It’s an eternal struggle.

Yes, it is probably possible to have too many little classes and objects. This has never been a problem for me, I seem to work well away from that danger line.

I continually try to get better at doing this.

Test, Test, Test

Tests in the TDD style shouldn’t be called tests, but I don’t know of a word that I prefer. They do serve as correctness checks and safety checks, but they are so much more.

They make us the first users of the object and APIs that we invent, which helps us understand what’s easy, and what isn’t.

It turns out that testable objects tend to be better objects, easier to use, more focused on doing a few things wel, and just generally better.

In particular, when something breaks in the code and tehre is no test for it, creaing that test focuses our attention, isolates the problem, and prevents similar occurrences later.

I continually try to get better at doing this.

Encapsulate Ideas
If we have an idea in our heads, we do well to put it into the code very explicitly.

I had a complex idea, initializing the Saucer after creating it. Providing the InvadersSaucerMaker, which is in essence a factory object, simplified the code for the saucer substantially, avoiding a complicated bit of switchery to allow it to initialize itself in phases.

I continually try to get better at doing this.

Ways of Working

Slow Down
I make far more mistakes from trying to go fast than when I proceed slowly in small steps. “Slow is smooth, smooth is fast”. Since this quote appears to have originated in the Navy SEAL teams, you might prefer Lao Tzu: “Nature does not hurry, yet everything is accomplished”. In T’ai Chi, we practice the moves very slowly, learning to make them perfectly.

However we cut it, when I try to go too fast, I make more mistakes and do not notice them as soon. The result is that when I finally do notice them, I may have shipped a bug, and I invariably seem to waste more time fixing the problem than I may have saved by rushing.

See Hill: Many More Much Smaller Steps.

Automated Refactoring
Generally speaking, the automated refactorings in your IDE are safe. It’s usually possible to improve the code substantially with essentially zero risk, by using those machine refactorings.
Experiment, Then Do
Sometimes we feel comfortable taking a series of small steps, because we have a good sense of where we’re going. But sometimes … we may see a glimmer of an idea, but are not sure whether it will work or quite how to put it in.

In these cases, it can be wise to “spike” the solution, implementing as much of it as we need to to understand, perhaps even implementing essentially all of it, to be sure it will reach from end to end.

Then, it is often wise to roll back the code and do it again, seeking small safe steps from here to there.

How often is “often”? In my experience, the second effort always comes out better than the first. I don’t always throw away my experiments: sometimes I go forward from them. But I’ve never regretted throwing something away and doing it again. I find that doing it the next day is best for me.

Try to Get Better
Practice can help us get better at doing something, but often when I wish I were “better” at something, I really just mean that I wish I did it more often during actual work, not just deliberate practice. I don’t have a magical way of making that happen, but what I try to do is to change some little habit so that I’ll occasionally be reminded, at just the right time, to do the thing that I want to do better.

I have occasionally committed failing tests and pushed them to GitHub. I think PyCharm has a setting to make that harder to do, or perhaps even impossible. I’ll find that setting and try it. (Bummer, I think. It allows the commit and pops up a notification. Must decide if that’s OK. Probably can’t be better than what I do now, which is commit without the message popping up. I’ll try it for a while.)

Summary

Those are the main observations I’ve made over the past several articles. What have you noticed? What have I missed? Send me a toot or an email if you think of something.

See you next time!