The negative space of gratitude

Barnes & Noble on a Monday afternoon.  It took the damn day to get me out of the apartment at all.

I came down here, well, because I needed to get out of the apartment. But the pretense was to buy a new copy of Victor Frankl, figuring my thoughts on man’s search for meaning might be well served by reading “Man’s Search for Meaning”.  Just a thought. More on that later. It’s a larger project

I’m sitting in Barnes & Noble in cool springs, getting a little writing done (or trying like hell) and this woman is sitting here bitching a bluehaired streak about the gifts she got for Christmas.  A frying pan that’s too small, $120 tickets to a play she didn’t want to go to.

“I could have used that hundred twenty dollars at the book store.  And I had to buy my own dinner and I could barely even choke it down.  High schools put on better plays than that.  The lighting was awful. The costumes were bad.  Ten tickets.  I guess she thought she was being nice.”

“See, my kids know better.” Her friend said. 

“Well, I know not to say anything in front of my kids any more. A couple years ago I wanted new hubcaps and I kept talking about them and hinting and Christina got me hubcaps. The kids kept saying ‘don’t get that. Grandma doesn’t want hubcaps.’ Yes grandma DOES want hubcaps.” She shook her head while staring at the table, lip curled.

“We went to that store and I saw that plate I liked and I said if I come back later and it’s still there, then I’m meant to have it. If it’s not then I wasn’t. Well we got busy and I forgot about it. They all chipped in and bought it. I don’t have the room for that thing on my wall. What am I going to do with that? Do you want it? It’s nice. But if you don’t want it it’s going to goodwill.”

“Then, my 75th birthday. They made me a cake *whupee* then the kids sang.  I’d rather they had done none of that.  Then they gave me a picture book of the whole family and I could care less. It’s in my closet. It’s pictures from the lake. I don’t go to the lake. I mean if it had had better pictures of the kids maybe.”

“Ya know they complained because the year before I wasn’t all *ha ha ha*.  So I made a point to sit there instead of just going in the kitchen by myself.”

“And they gave me a picture and it’s of the whole family together and I’m over there in the corner and they don’t understand that that picture is exactly how I feel.  And none of them understand.”

Her friend, who’s got a decade or two on her has tried twice now to change the topic, but she just keeps bringing it back to how awful her kids and grandkids are, presumably for not being psychic or something. 

She has no concept of the part she plays in her own misery.  None.

So forcefully is she rejecting anything other than wallowing in abject misery and spite that I can’t even drum up sympathy for her.

She leaves, finally, bent over her aluminum cane ten years too early, her body, outfit, and scowl a perfect depiction of her character, while her much older friend, with the posture of someone in their mid 40s walks behind her with the gate of a nurse.

I guess that’s my writing for the early afternoon shift. Wasn’t my plan. But sometimes the topic just hits you with a cluebyfour

TODO: Uh oh…testing

So I posted the code as is a couple days ago and it’s so bad it makes me itch. This morning I added a noninteractive option to add an item to the todo list if you just called it like so:

todo a “New Item”

But when I grabbed the list to test it that item was displayed as “w Item”. Now, the error is obvious but the solution could go a couple ways.

So I’ve reached the end of flying by the seat of my pants. In order to progress any farther on this I’m going to have to do what I arguably should’ve done from the beginning…

It’s time to start adding unit tests.

There are all kinds of python unit testing frameworks, modules, libraries and such. But I’m a fan of the unittest module. It’s a nice small scale xUnit style library. Works great.

I’ve got 7 functions here and my intention is to instrument all of them. I suspect this little Yak Shaving exercise is going quite some time, and add a lot of code to accommodate the necessary refactoring. You’ll see what I mean as we go along.

First, a minimal unittest based test script, and a toy of my own:

#!python

# test_todo.py

import unittest

class TestTodo(unittest.TestCase):
    
    def test_hello_world(self):
        self.assertEqual('foo','foo')

if __name__ == '__main__':
    unittest.main()
    
        

That’s about the simplest “useful” unittest script you could write. I start with that exact script every time I’m starting a tight test cycle development project. I put the hello world test just to be sure everything’s all set up right.

But because programmers are lazy and I’m an exemplar of the form (lazy, not programmer) that’s not good enough. I have two little scripts I use to run this thing for me. Warning: These instances are windows batch files. If you need bash scripts and can’t translate them, seek help on ye olde innertoobz

First, the outer script, testloop.bat:

REM testloop.bat - a test running script

@echo off

:beginning

call .\runtests.bat

goto :beginning

It’s a goofy script that loops forever and calls something; in this case “runtests.bat”, below:

@echo off

@echo running tests...

.\test_todo.py

@echo ...tests complete

REM Ping timeout trick to sleep.
@ping 127.0.0.1 -n 3 >nul

Okay, I know what you should be thinking: Why the actual crap is that separated into 2 scripts and what’s with the ping?

The ping trick is a simple way to implement an N second timer. The command line ping pings a network host once every second, pass it a numeric parameter (-n 3) to give it the number of iterations to perform. So this is a cheap easy way to create a 3 second timer.

Now, why two scripts? To answer that I’ve got to walk you through my development cycle a bit.

Once I have this setup I kick off testloop.bat in a console window. It scrolls test results, which don’t dump a lot to stdout unless one of the tests fails. When a test fails (which, when I’m doing something close to TDD, is all the time) it’s obvious what’s going on. Sometimes a change will break a crapton of tests. Plus, once a project starts growing I’ll have lots of test scripts. But I’m REALLY lazy and don’t want to bother stopping and starting the test runner every time I have a structural change (or if I need to increase the delay because the stack trace from unittest is flying by a little quick.)

By keeping the guts of “what test scripts are REALLY being run and how long should it wait between executions” in an INNER script, I can just edit that at will and the outer script will pick up the changes without me having to EVER CHANGE FOCUS OUT OF MY EDITOR.

It sounds like a bullshit optimization. But in fact anything that takes me out of the editor (emacs or sometimes Visual Studio Code or PyCharm) slows me down.

So in practice I’m staring at my editor screen while this thing is scrolling out in my periphery. I have the editor split vertically with the test script I’m working on in one pane and the code I’m testing in the other pane. My eyes don’t have to move. I don’t have to reach for the mouse.

If an error shows up I glance over at it, then start coding the correction (be it to the test or to the code.)

So in those three little scripts, the python test script and the two batch files, my workflow is pretty much as streamlined as it can possibly be.

An advanced side-effect of this is that if my unit tests get too big (i.e. if I’m dumb enough to add connections to external resources like a database or a network resource to my tests, making them something absolutely NOT unit tests) it becomes obvious FAST because I’ll notice the dramatic speed reduction.

I was going to start adding the actual tests in this post, but I think this sidebar into my testing workflow stands well enough on its own.

Who knows, maybe my next post won’t be a straight stream of consciousness, won’t THAT be a treat!

An 0.1 todo command line script

I think I’m going to make an attempt at live-blogging this project. A post every day or two, with code snippets at least, maybe the full source because what do I give a crap about the source.

I DO need to install a code formatting plug-in for wordpress. Until then, code snippets are going to be just awful things wrapped in

<pre> tags.

So…

After I posted that yesterday (which was actually a simple electronic journal entry that I finished and said “meh, post it”) I opened an editor and started dicking around with an interactive console-based python script, just to see how far I could go in one shot.

It’s funny because it has add/list/save/load functionality (automatically loading on startup, saving on add.) There’s no removal/mark as completed function yet.

But imMEDIATELY my brain started firing off in all kinds of funky directions.

So here’s the 0.1 version (well, it’s probably 0.0.0.0.0.0.0.1, but who’s counting.) It has the most basic functionality, and a non-interactive option for just spitting the list to stdout.

Call it with nothing enters the interactive command loop:

todo.py

Call with ‘l’ (for list) and it’ll just spit the current todo list to stdout.

todo.py l

#!python

import os
import sys

filename = 'todo.dat'
items = list()

def save_items():
    fh = open(filename,'w')
    for item in items:
        if item != '':
            print(item,file =fh)
    fh.close()

def load_items():
    if not os.path.isfile(filename):
        return
    
    fh = open(filename,'r')
    eof = False
    while not eof:
        line = fh.readline()
        if not line :
            eof = True
        items.append(line.strip())

def add_item(foo):
    if len(foo) >2:
        items.append(foo[2:])
    else:
        item = ' '
        while item is not '':
            item = input("+ ")
            items.append(item)
    save_items()

def list_items():
    for item in items:
        print("\t",item)

def complete_item(foo):
    item_to_complete = None
    if len(foo) >2:
        item_to_complete = int(foo[2:])
        del items[item_to_complete]
        save_items()


def command_loop():
    bail = False
    while not bail:

        foo = input("> ")
        print(foo)

        if foo[0] == 'q' or foo[0] == 'Q':
            bail = True
        elif foo[0] == 'a':
            add_item(foo)
        elif (foo[0] == 'c' or foo[0] == 'f'):
            complete_item(foo)
        elif foo[0] == 'l':
            list_items()
            
def run():
    load_items()

    if len(sys.argv) > 1:
        if sys.argv[1] == 'l':
            list_items()
    else:
        command_loop()

if __name__ == '__main__':
    run()

So what’s this then? Here’s a script that maintains a local text file with a static name and gives you a couple commands (add, list, complete, quit) represented as one letter commands, to maintain a list, one item per line in the file. There’s a LOT wrong with it. BUT it works. It’s not production ready, and it’s particularly inelegant and it has no damn tests. All it’s supposed to be is a simple sketch, the code equivalent of a functional whiteboard diagram.

Next time I’ll either start ripping it apart for inclusion of more features, or for a serious restart. We’ll see. I’m still winging it.

Light thoughts about minimally architectured cluster apps

I’m having a Melanio V and one of their draft rootbeers.  I just don’t remember it being this good.

I picked up the “Wicked Cool Shell Scripts” book a few times today when I was in B&N before heading out for a bite (a cheeseburger at J. Alexander’s, skip it.) I almost walked out with it a few times; checked the price on amazon (within $2 with the discount at B&N.)  But then I realized that there’d really be no reason to use bash over python or perl for most of those things. 

It’s a function of designing a low level component architecture that splits responsibilities into multiple individual processes.  As long as I’m not walking all over myself with the storage back end, there’s almost no reason not to design this (todo list/project manager) that way.  I could take all the analytics and set them up as mixins that run independently and just decorate the damn data.  There’s no reason to use a complicated storage format when I can just store the data in flat files for maximum flexibility.  Hell, even if I create a little library for storing stuff in a tabular format (a wrapper around csv with some type checking) I’d be in perfectly good shape just building on that.

Then if I wanted to get fancy I could port a tool at a time over to straight C.  It’d be golden.  Then add a call wrapper that I could use to run mocks or actually just call web services as well, then I could microservice the whole damn thing. 

Now if I take that and start drawing out from there, I end up with something that starts to look like a lot of the late 90’s Agent Architecture diagrams.  Now, that never really MEANT anything. But the ability to transport asynchronous tasks across architectural boundaries transparently is an awfully useful concept.

The granted flexibility would drop the barrier to entry, from an architectural perspective if nothing else, to near zero.  Functional components could be added by banging out a simple script.  Worry about where the hell it lives later.

That would be predicated on some kind of minimal service registry, something that’d play the dispatch game. Now of course THAT would be an external service as well.

[Not what I was looking to write about. But as long as it’s sticking to a single topic and is going back and forth with some actual thought, I’ll take it.  Writers have the cleanest closets.]

So let’s get down to brass tacks:

  • A todo list is a list of tasks, persisted, with (initially) a description. 
  • There’s an application that can add items to the list.
  • There’s a user interaction that can “complete” items on the list, which removes them from the visible list
  • The storage format should be text based, easily readable by humans or other programs.
  • The storage format must allow for flexibility of future expansion without interfering with minimal functionality.  This suggests a simple numeric index of items that can be used as a foreign key to other applets freely.

I’m going to sketch out some minimal implementations of these.  They don’t make a WHOLE lot of sense to me without an actual gui front end, web based or otherwise.  Actually I quite prefer otherwise.  The massive proliferation of web-based guis for everything just makes me kinda crazy.  I’d rather a java or other kind of desktop front end, even if the back end was http, local or not. 

These are stream of consciousness right now. But I find the first few attempts at putting something down generally involve me sweeping and shoveling out the crap in my head to get down to the good stuff.