Wednesday, October 11, 2017

This is why we don't put changelogs in source files any more.

This is a piano key. It belongs to a piano that we inherited from my sister-in-law, who inherited it from the school where she worked, who inherited it from a church sometime in the 1940s. We think it's about 90 years old.
The previous owners had the tuner sign and date this key when they maintained the piano. This is convenient, because you already have the piano disassembled, and you're looking right at the key anyway, so might as well. And then when you've got the piano disassembled because you're maintaining it, and you're looking at the key, you can see when you had it maintained last.
However, the time when you really need to know "when did I get the piano maintained" isn't when you have the piano disassembled: it's when you're thinking about getting the piano maintained again. The real place you want it is in a calendar or a journal, outside the piano.
Likewise, you generally care about the change history of your source when you're looking at the source control tool, trying to understand how it changed over time--not when you're down in the bowels of the code.
I mean, it's neat to have something to read while you have the piano disassembled, but that's not really the best place to store the data.

Wednesday, May 16, 2012

It's probably been done.

I started programming in junior high, writing BASIC code on a Commodore 128. At the time the only learning resource I had was the owner's manual and some issues of Compute!'s Gazette, so I was almost completely self-taught. I don't think I had actually heard the words "computer science".

If you've never programmed in BASIC of that era, understand that:

  1. There were no "functions"; a program consisted of a list of steps, executed linearly, with some control structures sprinkled in and plenty of GOTO jumps
  2. Variables were all global
  3. Variable names were limited to two letters
There was a limited bit of "subroutine" support: GOSUB was like a GOTO that remembered where it came from, and a RETURN would start executing from the next line after the GOSUB.  But since all variables were global, subroutines couldn't be reentrant.

So I got the clever idea that instead of using variables in a GOSUB routine, you could use arrays, and then have a variable that kept track of how many times you'd entered the subroutine. Sure, you had to define the maximum number of times you expected to GOSUB before you started returning, but at least you didn't have to remember whether or not the variable you were about to mutate was going to munge a previous call.

It was brilliant.

And when I got to college I learned that I'd "invented" the call stack and recursive functions. Rather a let-down, that.

So, grab your 8502 and load up a JMP 2011, when I wrote a blog post on "Stages of Competency":
I thought it was pretty remarkable how consistently I saw the progression from "awareness" to "familiarity" to "functional understanding" to "understanding" to "competence" in myself and in others.

Pretty insightful, huh?

Turns out that pattern is a simplified subset of an educational classification system called Bloom's Taxonomy.

And it was first proposed in 1956.

So, yeah, that insight you thought you just had? It's probably been done.

Friday, November 11, 2011

3 Simple Rules That Will Make You a REAL Superstar Developer



"Prima Donna" Rule 1: Write lots of code.


"Neil Peart" Rule 1: Read lots of code.


Prima Donna Rule 2: Write your code quickly.  


Neil Peart Rule 2: Finish your code quickly.  








Behold, the Underlying Principles












Wednesday, October 26, 2011

Mojo Reset (or, The Cunning Plan)

For the past few months, I've been enjoying Mike Pirnat's monthly "mojo checks"--monthly checkups that turn weak "New Year's Resolutions" to like-a-boss mojo maximization.

This coming month (November), I'm starting the same thing. Why November? Because I can, dammit.

And I don't want to wait until January.

And November is, of course, the mojo month, Why? Because this one goes to 11.

A Target-Rich Environment

So for the past two weeks or so, I've been working on The Cunning Plan: the list of things I'm going to target for maximal mojification. It includes 16 targets that divide roughly into three categories.


This covers both day work-related and non-work-related but professional targets.
  1. Obey the checklist. I'm not a naturally organized person, which means that when I'm really on the hook for something I have to compensate. One of the tools that I've found works well is a simple checklist for things that have to happen the same way every time. I learned this doing stage crew for a local theatre production--if I don't write down every pre-curtain, intermission, and post-show prep step, on paper, and then run down the list, I'll miss something. Similarly, there are things I really should do the same way every day when I start work: check builds, check for important email, look over today's schedule. The actual steps aren't important (and may change over the year); using the checklist consistently is the target.
  2. Speak twice at work. I'm at the career stage where that's expected of me. I don't mind doing it, but if I don't actively look for opportunities, it won't happen. Anything with an audience of more than one team will suffice. Last year I did twice, so that's what I'll shoot for this year.
  3. Do a lightning talk at PyCon. I had a pretty decent lightning talk in mind last year, and I forgot all about it until the last day. (Boo). I don't know what, but I can do something this year.
  4. Attend PghPy 6 times. Like Mike, I don't have a good excuse for not attending the local Python users' group. It used to conflict with my daughter's voice lessons, but that's changed, so now I have even less of an excuse. 50% attendance isn't that hard.
  5. Release one Android app. I've started three, got each to some level beyond "Hello, World!", and then neglected to take any of them further. So the easy stuff, most of which is done for you by the framework or comes straight out of the tutorials, I can do--but I don't have much feel for the real meat of Android development. I need to get one app sufficiently finished to the point of releasing it publically in some minimally-useful, 1.0-level form. I don't know what it will be, but after all, I have a whole year to do it.
  1. Blog monthly. Like most of the blogging world, I keep saying I'm going to do this, and don't. And it would be cheesy beyond cheesy to include these mojo check posts, so this really means twice per month.
  2. Read 50 books. In 2011 I decided I was going to attempt 100 books. That's turned out to be wildly optimistic. I'm on track to come in just under 50, so 50 seems like a good goal for next year.
  3. Miss no birthdays or anniversaries. Outside of my own nuclear family, I'm terrible at this. I can remember my kids' and wife's birthdays and my own anniversary, and I've never missed one of those. But I have to think a bit to remember my siblings' or parents' birthdays, and don't even ask me about my in-laws'. So for the next year I'm going to acknowledge (i.e., a present or at least a card, neither of which is a zero-day panicked Amazon gift certificate) all birthdays and anniversaries for my parents, my in-laws, my siblings and their families, and my siblings-in-law and their families. I mean, this is 2012. We have Google Calendar. There's no reason to miss any of them anymore--we're only talking about roughly 30 dates.
  4. Lead music four times at church. The small church we've started attending has one do-everything music director, who plans the service, plays guitar or piano, sings, and does a host of other things. When she heard that I play guitar, she was happy to hear that she might actually get a Sunday off once in a while. I did this once last year for Father's day. It didn't go well, but I suspect that doing it more often would help. But in order to do that, I'll have to...
  5. Practice guitar at least three times a week. No, I don't intend to become the next Zed Shaw. [Feel free to fill in your own snarky followup comment here. I'll wait till you're done.] But this is probably the absolute minimum to maintain a non-embarrassing level of competency in order to hit the above target.

Yes, "health" is also personal, but these items fit with each other more closely than they do with the items in the "Personal" category:

  1. Keep all medical appointments. Here I'm talking about the regularly-scheduled, "periodic maintenance" things: eye exam, dental cleaning, "get these tests redone in 6 months" things. I have a habit of letting them slide so that "every 6 months" becomes "oh, right, I was supposed to do that last month, right? No? Last year?". Most places will let you schedule up to a year in advance now, so there's no good reason to fail this one.
  2. Give blood 4 times. I used to be pretty good about this, but I've fallen off the wagon. It's a little like the "regular maintenance" appointments--I know I can and should do it every 8 weeks, but 8 weeks stretches into 8 months. So I should be able to handle once every 13 weeks.
  3. Run at least 3 times per week. Indoor treadmill or outdoors, at least 2-3 miles. But realistically it needs to be more frequent and longer, because the next three targets are...
  4. Run two 5k races. I'm not sure why I've never run one, but there's no reason I can't find two free weekends out of 52.
  5. Run one 10k to 10-mile race. Again, I've never done one of these. The Pittsburgh Great Race is in September, and there are other similar races around. No reason not to.
  6. Run the Half. In 2009 I ran the Pittsburgh Half Marathon with my brother. Training up for it and running it were a phenomenal experience. I wanna do that again. In 2010 I got a horrible upper respiratory infection and couldn't run; this year I waited too long to register, and the half filled up. I've already registered for 2012, which means that now I can use the sunk cost fallacy in my favor for once!
So that's it, other than the "meta-target":

  1. Check in publically every month, without fail.

Keep me honest, Intarwebs.

Tuesday, September 06, 2011




The Problem









So instead, I cranked up DreamPie.

Secret Weapon #1: DreamPie







Secret Weapon #2: ctypes


>>> import ctypes
... file_mode = 0x80000000 # GENERIC_READ from <winnt.h>
... open_existing = 3 # from <winbase.h>
... buffer = ctypes.create_string_buffer(100)
... bytes_read = ctypes.c_ulong(0)
... buffer.value



What a chore. Did I mention I'm lazy?


Secret Weapon #3: PyWin32



>>> import win32file # for CreateFile
... import win32con # for constants
... win32con.GENERIC_READ,
... 0,
... None,
... win32con.OPEN_EXISTING,
... 0,
... None)
... win32file.ReadFile(hfile, 50, None)

The Final Secret Weapon


>>> import win32api, win32file, win32con
>>> win32file.GetCommMask(hfile)
0: 0
>>> win32file.SetCommMask(hfile, win32con.EV_RLSD)
Traceback (most recent call last):
File "", line 1, in
win32file.SetCommMask(hfile, win32con.EV_RLSD)
AttributeError: 'module' object has no attribute 'EV_RLSD'
>>> win32file.SetCommMask(hfile, win32file.EV_RLSD)
>>> win32file.GetCommMask(hfile)
1: 32
>>> win32file.EV_RLSD
2: 32
>>> win32file.WaitCommEvent(hfile)
3: (0, 32)





Wednesday, August 10, 2011

Stages of Competency


0: Awareness


1: Familiarity



2: Functional Understanding




3: Understanding






4: Competence





Wednesday, October 20, 2010



  • 3.1.2, because that's what we're targeting for new development
  • The most recent 3.2 alpha, for testing
  • A 3.2 trunk install, for testing patches


So starting from Ned's script, I came up with switchpy:
  • Supports Windows Python versions from 2.5 up to 3.2

C:\src\myscript>switchpy 25
Switching to Python at C:\Python25\...
Python is now C:\Python25\

test object 1: C:\src\myscript

myscript\tests\ ...


C:\src\myscript>switchpy 31
Switching to Python at C:\Python31\...
Python is now C:\Python31\

platform win32 -- Python 3.1.2 -- pytest-1.3.1
test object 1: C:\src\myscript

myscript\tests\ ...

