Ending on a high note

Today I went into my place of work, and picked up all the stuff I’d left in and around my desk. Then I spent a few hours making sure none of my non-work info was left on my laptop, especially my password manager and iCloud account. Left my keyfob on my desk. Then I took my laptop to FedEx Office and sent it back to our head office in Connecticut. And that is it. Forty years of work as a professional computer programmer is over.

I counted it up a few months ago when I was writing my resignation letter, and I make it somewhere between 20 and 22 different jobs depending how you count it. That includes 1 month contracts and two 6 year long permanent jobs and everything in between. It doesn’t include two occasions where I was unemployed for several months in a row. Sometimes it sucked, sometimes it was great, but I’m never sorry that I chose this path.

Early on in the history of this blog, I started a series of “bad job experiences” posts. I stopped that after one of the people I’d mentioned in a post found the blog and disputed some of the things I said about it. I realized these posts might show up when I’m looking for work and potential employers Google my name and that might be harming me. I’d much rather they found my 100,000 plus Stackoverflow points or even my pathetic GitHub profile than that.

Weirdly, even though I had fodder for that series even at the best jobs I had, I am hard pressed to find anything like that to write about my last job. I started at Skillsoft on 5 January 2020. By late March, we very quickly transitioned to working from home. Skillsoft management were great – one of the first things they did was immediately give us a day off to recover from the “stress” of the change. I’d had 7 years of previous experience with working from home and I thrive in that environment, but I took the day off, of course. They then put two weeks of “special leave” in our online time manager that we could take for COVID related emergencies, like providing support for sick family members or needing time to arrange things for your children. I think our sick leave was officially “use as much as you need, but we’ll probably need a doctors note if it drags on too long”.

I loved just about everything at this job. It was fast paced without being frenetic, you weren’t pressured to meet unreasonable deadlines, the tech stack was good, the other developers very approachable. Pat, the team leader was always willing to get on a slack call and walk you through any problems you had. Usually I tried to call my team mate Daquanne rather than Pat because Pat had so many other calls on his time and Daquanne was great at explaining things. I kind of hated sprint demo day, I did at my previous Agile jobs as well, but I got through them ok. And when we were in the office, Michelle would make cookies on demo day.

Other than the stress of demo day, the only nit I could pick was my co-worker Uyen who wore a lot of perfume. I’m over sensitive to perfume, and it would frequently make me sneeze even when she was at her desk and I was at mine. I bought a little USB powered fan to try to blow air towards her desk, and I guess it worked but I only had it for a week when we went to full work from home. Anybody need a cheap fan? She also had an accent which made it hard to understand her over Teams, so I didn’t go to her for help unless it was something where she was the subject matter expert, like our Fastly configuration.

We had a small team, and everybody got to work on front end and back end as per our own inclinations. Everybody had their areas of comfort but they also didn’t seem to mind if you picked up a story in their area or suggested a different approach in a code review. I can honestly say this was the best team I’ve ever been on – I’ve worked with other very smart very good programmers, but every other team had a person or two who you just hoped they’d go away and stop dragging down the rest of you. I’m hoping that doesn’t mean I was the drag.

I’ve been looking forward to retiring for a long time. I’m not going to stop programming – I’ve got a couple of projects I want to work on, and maybe I’ll do some bug fixing for open source projects. It sounds like log4j could use some help?

But also, I’ve been looking forward to having more time for paddling and biking. With more time to train, I was hoping I could try to do the Adirondak Canoe Classic. Unfortunately I’ve been having massive problems with pain in my hips and butt. This summer, I actually had to stop paddling during races to lift my butt out of the seat a few times to relieve the pain. And that pain has gotten worse over the last few months. I can’t paddle, or even sit in a car or a desk chair for more than 45 minutes without being in intense pain. In our recent trip to BC, there were several times I thought I was going to scream I was in so much pain. If I can’t find a solution for the pain, I’m not sure what I’m going to do.

That’s also going to impact my other major goal of retirement – traveling with Vicki. Again, I’m not looking forward to long car rides. Flying business class seems acceptable, especially those amazing pods we got on the flight home from BC. And let’s not even think about what the new COVID variant might mean to our booked Viking cruise.

So I guess task # 1 of the new year will be pounding the desk at my doctor until I get a solution to my pain problems or medication to manage them.

2018 Look Back

2018 started out pretty shitty. I was unemployed, and my unemployment insurance had run out. Depressed due to the long employment search and other things, I started the year out of shape and overweight, only to be hit with two massive bouts of sickness that pretty much wiped out my winter training and dieting, meaning I hit the racing season with very few miles under my belt and a lot more fat under there.

I got a job in February, and while it was interesting the pay was quite low – I’d actually earned more as a full timer with benefits in 2001 than I was earning as an hourly contractor with no benefits at this job. So midway though the year I left that job for another which paid much better. I hate to be a job hopper like that but the difference in pay was hard to believe.

Because of the reduced financial circumstances this year, I didn’t do a lot of the “away” things I’ve done in previous years – no TC Surfski Immersion Weekend, no Canadian Surfski Champs, no Gorge, no Lighthouse to Lighthouse. Instead I concentrated on doing as many NYMCRA races as possible, even camping out to save money instead of getting hotels for away races. I did several races I’ve never done before, including the two days of Madrid and the lovely Blue Mountain Lake race.

Even better, the USCA national championship races were held in Syracuse. I had two really good 10 mile races – unfortunately both races were 12 miles. Both times I lead a pack of racers for the first 10 miles, then faded and got passed by all of them in the last 2 miles. Definitely something to work on this year.

I started the season completely out of shape with the intention of racing my way into shape, hoping to peak with the USCA Champs. It worked pretty well, and in spite of my tactical errors there, I had a really good race at Long Lake. I was hoping to continue with the final race of the season, the Seneca Monster, but it got cancelled.

In other good news, I really dialed in my video production workflow, aided by the fact that I now have a high end iMac. Also, I got a really amazing carbon fibre GoPro mount for the front of my kayak – not only lighter than my older aluminum one, but also more aerodynamic. After the end of the season, GoPro released a new camera, the Hero 7 Black, with a much touted “Hyper Stabilization” mode. I bought one and tried it out and it is pretty amazing. I can’t wait to use it for races next year.

I also bought a new boat – I did some side work for a pilot friend of mine and used part of the money to buy a V8 Pro, a more stable boat than my V10 Sport, but still pretty fast. During interval workouts on the bay, I found I could just put the power down instead of bracing and trying to keep upright.

One of my daughters got engaged this year. I really like her fiance and they seem really good together.

Both of my parents had health setbacks this year. I think this coming year’s travel plans will have to mostly involve visiting them.

Reimplementing Part 3

This is part 3 of my self-imposed project to reimplement the UI for an old website. You can read part 1 and part 2.

After some playing around with the “Step 2” interface, I realized that I really needed better error checking. I had error checking on the individual fields of the Geographic Panel, but no “overarching” check that all the fields were filled or all were unfilled. Plus I wanted the user to see the errors on the Geographic Panel even if you’ve closed the panel, and I also wanted to disable the “Start Generating” button until the errors are cleared. While I was at it, I added an error message if you don’t have any waypoint types selected. I’ve made those changes and pushed them to my GitHub project as the fourth commit and I’ve pushed it as a replacement to the previous mockup here.

I haven’t worked on this all week because of other calls on my time (work, job search, kayaking), so I haven’t made a start on the backend yet. But I’m thinking I’m going to be doing it in Python with Flask or Pyramid and SQLAlchemy. The original website is written in Perl, and frankly, I think the job market for Perl programmers is pretty rapidly shrinking and nobody is doing modern websites in Perl. But speed is of the essence, so that leaves Python or Java. The decision will probably come down to whichever of those two frameworks has better support for PostGIS.

Re-implementing Part 2

As described in my previous post, I gave myself a project to reimplement an old website using new technologies in order to prove to myself and to potential employers that I can do all the modern stuff.

The “Step 1” prototype was completed 15 days ago. I only wrote about it early today because I was debating with myself whether I should write up each step or do it all at the end. But during that time I’ve managed to get the static HTML page re-written as a React+Redux dynamic front end. I included the deficiencies I mentioned in the first post – the accordion panels open and close with a click anywhere on the title bar, and I’ve added “disclosure triangles” to make it more obvious that the title bars are meant to expand.

It doesn’t talk to a back end yet (it just simulates it using setTimeout), but it does so some nice interactive features

  • The title panes on each accordion panel update based on what you’ve chosen in the panel
  • It updates the countries, states and provinces in the “Country/State/Province” panel based on the latitude and longitude range you entered in the Geographic Area panel.
  • The state checkboxes don’t show up until you check the “US” checkbox in the country list, and similarly, the province checkboxes don’t show up until you check “CA” in the country list.
  • The “Start Generating” button is disabled unless you’ve selected at least one entry in the Airport Types, Navaid Types or Fixes in Charts panels.

Even taking into account the fact that I was learning as I went, I think the code looks ok. I tried to make some common base classes, but in many or most cases, I discovered that convolutions required to make it general weren’t worth it and I just ended up with similar but not identical code – case in point: the various “*Check” classes. I also ended up putting several classes for each accordion panel together in one file – I’m not sure if that’s considered best practices, but it seemed to make sense to me.

The mockup is here. This code is now the third commit on this project on GitHub.

So for a next step, I was planning to write a back end. The back end would have no actual HTML pages returned, just a bunch of AJAX calls and responses, mostly all returning JSON. So I was thinking Django, which is what I’ve been using for the last several years, would be too heavy for that. Similarly, the Java back ends I’m familiar with are also pretty heavy. On the other hand, the existing backend is written in Perl, and frankly, I don’t want to do anything in Perl anymore. I wonder if Flask and SQLAlchemy would be a good choice?

I’ll also have to figure out how to read and store cookies so we can store a session id just like the existing site does, but that’s probably not a big deal.

I also have to think of how the file generation will work. In the old code, I spawned off (fork/exec) a program to generate the file, and then had the web server process looking at the log file the generator task to see how far it had gotten. That made sense when the back end computer was busier and the generator task took 5-10 minutes – I didn’t want to tie up an Apache thread for that long, plus I could use a very primitive hand-rolled bit of Javascript to show progress. These days generating takes less than a minute, so I’m wondering if I couldn’t just do a return “Content-type: application/octet-stream” directly in the Apache thread. I’ll have to investigate.

A much more minor change I’m thinking of is in the country list putting the US and Canada at the top of the list instead of being strictly alphabetical because most of the users of the site are from the US or Canada and it would make it easier to find them.

Cosmetically, I reused the banner from the old site. It doesn’t really match the light and clean look of the rest of the site. I should probably make something more in keeping with the look I’m going for. Similarly, the favicon looks like a Palm Pilot which was fine when most people were using my data for Palm Pilots, but kind of wrong for GPX.

Someday, I’d like to add a simple map that can use to select the geographic area. Even better would be displaying or even picking countries, states, and provinces on the map. I’ve done some quick googling and I can’t find a good map library.

Also, if I could get the backend working fast enough, it would be cool to give a running count of how many waypoints the user is going to get in his file with the current parameters.

Update: See Step 3

Re-implementing an old web site in a modern style (Part 1)

So a few weeks ago I found out that my contract was going to be ending early due to a loss of funding. This is a great shame, not least because it gave me the opportunity to learn a bunch of new technologies, and also because I’ve really enjoyed working from home with minimal supervision. It’s been really helpful to my kayaking training to be able to go out and train during the afternoon and work in the evening after it gets too dark to paddle. It’s unfortunate timing because my contract ends at the end of April, and we’d already booked our cruise for two weeks towards the end of May.

But I’ve discovered a bunch of things since I’ve started looking for work:

  • Getting remote work is hard, even if you have 7 years of remote work.
  • Lots of potential employers want to see your work and your code, or worse, they want to see your GitHub profile. The problem with that is that most of my code is written for employers who don’t allow me to share the code I’ve written for them, and the websites I’ve worked on have been internal rather than facing the internet, so I can’t show them. Even worse, the only thing I’ve got on GitHub is a WordPress plugin that I forked for a project I did for the local kayak shop in exchange for a new boat. I used to contribute more to open source projects, but that was before the days of GitHub and mostly it involved emailed patch files. That was back in the days when I didn’t have so many hobbies and obligations.
  • While I’ve been doing a lot of JavaScript over the last 7 years, I haven’t used any of the cool frameworks. We’d actually made the decision to transition our project at my soon-to-be-ex job to Angular, but we never got around to it.
  • A whole bunch of companies are embracing coding exercises as an evaluation process. I don’t blame them – I’ve given interviews and I’ve received them, and they are an utterly shit way of evaluating people’s technical ability. But it is time-consuming if you have to do this for every company you apply to.

So I thought it would be useful if I could do a bit of a project that I could show to people, and put the code on GitHub, just like all the cool kids. And it should obviously use a JavaScript framework. And you’d think that I’d choose Angular, but there is a particular job here in Rochester that is currently top of my want list, and they use React, so I thought I’d use React.

So having made a decision on the front end technology, what I needed to do was pick a project. And the obvious candidate is my navaid.com website. While I keep the data updated loading FAA and Eurocontrol data every 56 days, I haven’t updated the UI in many years, and it shows. I’ve got several data generators there, but most of them are for Palm Pilot programs, so they’re probably not worth updating. But the GPX generator at http://navaid.com/GPX/ is still viable. So I’ll only reimplement that one.

The first step is to make a mockup of the new site. Actually, the first step was to watch a bunch of tutorial videos for React. Which start off teaching you about WebPack and ES6, and then React, and then React-Redux. I wasn’t 100% sure if I needed Redux, but it seemed like a good way to separate the data state code from the render code. But after watching the videos, it was time to write the mockup.

Obviously, since I have been using Bootstrap for the last several years, it would be easiest to make something modern and presentable using it. I just had to find a nice theme with a CDN. I settled on the “Paper” theme from Bootswatch, which has a nice simple clean look.

The obvious thing was to replace the multiple pages of the original GPX interface with a single page. The existing interface saves your last set of parameters in the database linked to a cookie and re-uses them next time you come back, and I’ve heard from users that they often just click through to the end and hit the action button without changing any of those parameters, so I thought it would be good to be able to display what they’ve loaded so they review to make sure that they don’t need to change anything and click the “Start Generating” button. So I decided on an accordion panel where the header for each type of filter shows what’s selected for that type and if you click on the header, you can modify it. Hard to describe, hopefully, easy to see in action.

So it took a few days, but the mockup is here. The code is the first commit on this project on GitHub.

After playing with it a bit, the first thing that leaps out at me is that the accordion panels should open when you click anywhere on the title bar, not just on the text. Also, Vicki suggested that the color of the accordion panel is a little blah and I should make it a nice light blue. You’ll see that in generation 2.

Update On thing I forgot to mention: While Bootstrap has support for responsive design, I made no attempt to make it work on mobile devices because generating and downloading large files isn’t something you’re likely to do on a phone or tablet. Probably the only change I’d have to make for mobile would be to use <div class=”row”> and <div class=”col-xs-12 col-md-4″> instead of tables, and possibly some tweaking of the padding or margin around checkboxes because they appear to overlap the label text a bit in Chrome and Safari on my iPad (although they don’t overlap in Chrome on my desktop when I choose “iPad mode”).

Also, as per a comment below, I’m also going to look at increasing the text size if I can do it without messing out up the look. The default font is 13px, which I’ve always thought was plenty big, but the Roboto font is a bit “thin”. I like it because it looks elegant, but maybe it doesn’t work at 13px? Bootswatch has some other clean themes, maybe I’ll have a look at some of them instead.

Update: You can read Part 2 and Part 3.