I wasted a ton of time tonight trying to convert some old Apple sample code from an obsolete version of Swift to the current one that compiles. If only I had checked the Swift Package Index first! Of course, someone else had already done it and created a package based on it.
VBA will never die
I spent all day coding in VBA for work. I’m creating Excel templates for data submissions. These templates need (at least I think they need) data validation routines that the people filling them out can run. Those routines will help prevent some data quality problems down the line.
The only tool for the job to code those routines is VBA, which is bar far the oldest language I code in on a regular basis. It is creaky, feature-limited, and its runtime is rather unstable. But if it works well enough for federal agencies (I have seen some data input forms in my time), it will work for me.
I used to think VBA was a trash language, and only trash code could be made from it. Once I learned I was stuck with it for certain tasks, though, I tried to make the most of it. Now I treat VBA like the proper object-oriented language it is. The result is that I have a lot more fun writing it, and I think that the code is easier to debug and modify in the future, too.
I keep my code clean. I keep methods as short as possible. I use long, descriptive names for methods, classes, and variables. I structure the code into classes extensively. I create classes for intermediate data structures to make other parts of my VBA code easier to understand. I refactor my code into numerous smaller classes when I find I am writing too many, or overly complex, private methods. I create and use factories to create and set up objects. I apply the principle of least privilege everywhere. I am pedantic about whether arguments are passed by reference or by value. I even use interfaces sometimes, too.
The result is code that is rigorously structured—perhaps hilariously so to the next person who will look at it. It is unlike any VBA code I have ever seen before, but it is probably a lot like many VB6 applications written in the early 2000s.
Finally back to iOS programming again
I am working on one of my iOS apps for the first time in about half a year. For many different reasons, I couldn’t bring myself to work on it for a long time. The problems I was facing with it seemed insurmountable. In truth, some of those problems still seem insurmountable, but I feel ready to move forward again with it.
Last night I stayed up late (which happens to me a lot when I am coding) and fixed a build that had been broken since the last time I touched it. I had moved a ton of functionality from a mostly-written app into a Swift package, and the transition necessitated updating hundreds of files and a few dozen method calls or property references. It was tedious work, but now that part is done. The app builds and runs, and the parts that still don’t work seem easy to fix. The new parts I have yet to write will still be a challenge, but I feel up for it now. It feels good to be back at it.
My data analysis bot
Today I spent the majority of my work day creating a massive Excel template. Tomorrow I will code the data analysis bot that will fill that template with data tables and command logs that document the analytical procedures. Over time, these two days worth of work are going to save me many, many hours.
I have always automated the data analysis part of my job, but never enough of it for my tastes. Although I am not a programmer by trade, I think like one. One of the creeds of a programmer is “don’t repeat yourself.” Sadly, at work, I repeat manual data analysis procedures all the time. Certain parts of my job resisted automation for years. Lots of work I do is ad-hoc and may never be repeated, so it rarely makes sense to automate it fully or to generalize the approach for other data files and projects. Other work I do, like pulling samples, happens all the time. I get fed up when I am performing it the same way, and no better than, how I did it years ago.
I put some though into it earlier this year and discovered that documenting the work, rather than performing it, was the biggest time-waster in my day. Documenting my work in work papers has always taken a very long time. While necessary, it is the least productive time I spend on an analysis project. (In audit, work papers are critical. They support our observations and can be followed, step-by-step, to reperform our work.)
This year, I finally figured out how to create a bot that would not only run a “standard analysis” on a certain type of dataset (that is the easy part for me), but would also document the work in an Excel work paper (that is the hard part). It is not perfect yet, but it has saved me a lot of time over the past six months. I plan to keep working on it, mostly by building new work paper templates and standard analyses, next year and into the future, so that it keeps payment me dividends.
Breakthrough!
After hours of struggle last night on an automation project I am doing for work, I had a breakthrough today. I feel good about the project for the first tome in months.
In my experience, robotic process automation (RPA) cannot be coded in the same way as, say, VBA to manipulate data. I am very good at coding in VBA, even though it is my least favorite programming language. VBA was built for traditional programmers like me. I am used to using code to manipulate data, which is how VBA works. I am not used to using programming (not even code, but commands) to manipulate the user interface around the data, which is the most important part of how RPA works.
Automating applications and websites to work on data is tricky for numerous reasons. First, unpredictable things happen at runtime, like error messages for the application or the operating system that pop up and interrupt the program flow. Websites change unpredictably, and what you expect to be there suddenly is gone. In addition, if one step in an automation does not work right, and that is not handled appropriately, the automation will just barrel on and do goodness knows what in the wrong place or in the wrong window or application. Lastly, every action takes an unpredictable amount of time to finish, for a myriad of different reasons. It is hard to predict all of the weird things that might happen at runtime, but you have to deal with them as best you can.
The one thing that has been especially bedeviling to me is that, when an automation (or, colloquially, a bot) runs, the amount of time any task within it takes is completely unpredictable. If the bot does not wait long enough after something finishes, what it needs for the next task (typically a window, menu, or other control) may not even exist yet. The bot I am building would run one day, and fail to finish the next day, solely because my computer ran more slowly sometimes.
I found that my bot started working consistently only after I stopped trying to wait a fixed number of seconds between tasks, but instead told it, every step of the way, to wait until the control it needs to interact with next exists on screen. This leads to a lot more steps that I have to add to the automation, but also to a lot less guesswork about how long a pause is necessary between actions.
I also figured out a better way to wait for long-running data tasks and macros in Excel to finish. It’s simple, but I did not know it was possible until I looked for it today: wait for the mouse cursor to change from the hourglass cursor back to a normal one. It’s just what you would do as a user, but my programmer mindset, always focused on the data rather than on the user interface around the data, made me blind to it for a long time.
With these few changes to my coding approach, my confidence, which admittedly had been shaken by the project, has grown. I now feel that a lot more is possible to build with RPA technology. It just will be more tedious to build it than I would like it to be.
“Real artists ship”; or, at what point did I lose my nerve?
“Real artists ship.” Steve Jobs said that to motivate the Macintosh team in 1983. It’s a statement that reverberates in my mind and absolutely drives me crazy sometimes. Why? Because I have tons of code that I haven’t shipped. Hell, some of my best code hasn’t shipped.
At some point, I lost my nerve. I couldn’t finish the projects I started. I couldn’t make a small change to a UI because it would inevitably spiral out into something that would require a rewrite of the entire app. I let new components I created lie unused. I let the revisions and extensions I had written for my apps linger and die on the vine. I couldn’t integrate the pieces into a coherent whole.
I let myself become too tired or too distracted to focus on the problems in front of me. I couldn’t resolve the problems I had created for myself. I couldn’t think straight, and didn’t trust that I could do it anymore.
I realize now that I was bumping into my limits as a developer, which is scary and frustrating. I opted to run away from these limits rather than to either work past them or to accept them. I am trying to do better and not get bogged down in all the feelings I have developed about this over the past couple years.
In the past I have failed. But I am trying to work through it now, to push past the fear, to move from “I can’t do this” to “I can do this,” and to get through the hard parts of getting my best code shipped. I can do it this time, and I won’t give up. All it takes is will, grit, and patience.
The UIKit Date Picker 😠
Last night I became unreasonably upset that UIKit does not let me use an inline date picker (the date picker control that looks like a calendar) as an input view (i.e., in place of the software keyboard on the iPhone). There is some kind of maximum height of the input view/keyboard area, and the top of the date picker gets truncated. I tried a lot of ways to make it work, but I guess I’ll have to wrap it in a popover and have some “special cases” code paths in my view controller to make it work. How frustrating! I just need about 15 points more vertical space!
I’m installing the Xcode 13 beta on my new Mac mini and I’m installing iOS 15 developer beta 1 on my old iPad Pro. I will probably install iOS 15 on my old iPhone 7 Plus later this weekend. Because I upgraded hardware this year, I actually have old devices kicking around for pretty much the first time ever. All it took was spending a ton of money!
I am going to try to not do any programming today. It has been a huge part of my job lately, and I enjoy getting in the zone when I do it, but it has taken a toll on my body. I have spent way too much time typing, and I feel it in my wrists, forearms, and even my shoulders.
This morning I decided to add one more feature to the app I’m developing for work. Twelve hours of coding later, I have rewritten the entire app, and am just now getting to test if that one new feature is working right. 😅
I’m up late coding. I have been up late coding many nights in a row now. I’m trying to get some of my projects completed (as much as software can be completed). I feel like I am inching uphill day after day. It’s not a bad feeling, though. I feel peculiarly tenacious lately.
Debugged!
Phew! I finally fixed a bug that bedeviled me for days. (Well, nights, because it is in my hobby project.) The fix was adding two lines of very basic code to a function that hasn’t been touched in years. I think the Swift compiler changed something about implicit protocol compliance, and it caused the function to stop processing the intended read/write logic for one of my protocol data types. I’m rewriting that library to not need that function anymore, and must code some better tests for it than I did before.
Now I can go back to writing the fun, new library that will make my code much easier to deal with going forward.
I have been using SQL for 25 years and I just learned today that SELECT [...] FROM Table1, Table2
is called a “cross join” an can also be expressed as SELECT [...] FROM Table1 CROSS JOIN Table2
. 🤦 In my defense, I must say that I have only had to use a cross join a few times in my entire career.
I’ve been coding a lot over the past week. I’m coding right now. I’m taking the core of my iOS and macOS apps and putting into a cross-platform Swift package. It’s been a fun excursion from doing UI work, but it has a purpose. I am dismayed, however, at how buggy Xcode 12.4 is. I can’t create a new file and rename it in the sidebar without trying to rename another file first. Also, automatic protocol compliance only sometimes works. Does anybody at Apple actually use Xcode, because little bugs like these should not be in there anymore.
My First NuGet Package
Last night, I published my first NuGet package: TodoTxt.Library. It is a code library meant to help develop todo.txt applications in .NET.
I wrote the code back in 2015, open-sourced it on GitHub, but otherwise left it alone because I had moved on to more macOS and iOS development by that time. This week, I upgraded the code base work on .NET 5, so that it is cross platform (rather than Windows-only, as was my original version), and figured out how to package it and upload it to NuGet, where it may have a shot at actually being used.
Tonight I published a huge update to the website for my first iOS app: SwiftoDo. What was once a one page site with a very outdated template is now a Hugo-based site full of information. There is a lot more that I could add, it is now so much better than my old site I had to publish it.
After a few evenings of work, I completed an update of my Simple Call Blocker app and submitted it to the App Store tonight. It feels good. Now I plan to start the revision of my other apps' website.
After a few days of work, I just published my new, Hugo-based website for one of my iOS apps: Simple Call Blocker. The site is not as beautiful as I would have liked, but it is way better than it was, and now I have a framework I can use to add more content to it if I need to.
One inexplicable thing I discovered today was that the git repo for one of my iOS apps did not have a working remote defined. It was pointing to a repo on BitBucket that doesn’t even exist any more. What the heck I have I been doing with it over the past couple of years?
I am putting the finishing touches on the website I am rebuilding with Hugo. I hope to go live with it sometime next week. I forgot how much work there is in building a website—even when you are not coding its theme.
There is no perfect template—just pick one
I stayed up late last night drafting a new, Hugo-driven version of one of my websites. I went from having nothing at all built to having about one third of the site done in a couple hours. The result, I think, will be more plain (and maybe more ugly) than the existing site, but it will be less janky on mobile devices.
I sank a lot of time over the past week looking for a Hugo theme that is perfect for my needs, but I couldn’t find one. For the sake of achieving my simple goal of refreshing my tiny websites, I gave up the goal of visual perfection, and am driving forward with a theme that I think is OK that works well enough for me.
From my perspective, I want my site to be easier to maintain and add content. That is more important to me than having a site that looks really slick. My old websites don’t look slick anymore, anyway: No one is fooled by outdated HTML templates into thinking that my very niche apps are developed by a huge, sophisticated software corporation.
I created an even more useful Excel VBA module that lets you resize the currently selected chart to cover, exactly, a range of one or more cells. You specify the range after you run the macro.
I created an Excel VBA module for resizing the active chart to a (hard-coded) standard size. This sort of thing is useful at work when developing reports.
I don’t know what took me so long to think to do this, but today I coded a VBA module with macros that increase and decrease Excel row height by one row at a time. I call them via the “Quick Access” toolbar, which is easy to customize.
Journal 2019-03-20
I have been working pretty steadily on finishing version 4.0 of SwiftoDo Desktop. I feel pretty good about the app, in general. It is coded in Swift now, as opposed to Objective C, and has a much more mature, and hopefully easy to support, architecture.
It will be a massive upgrade from version 3. While I would like to charge for it, even for my current customers, I feel bad enough about drastically changing an app I sold, even if it is for the better, that I am strongly considering just releasing it as a free upgrade. That’s basically my plan for the next version of SwiftoDo on iOS, which will be based on this codebase as much as possible.
My day job has been super interesting lately. I have hundreds of data analysis work papers to write, and I coded some pretty sophisticated scripts to generate all the data analytics I need to run, review, and report on. If only the software I was using made it easier to generate my work papers. I still have days and days of work ahead of me writing all the work papers that document the process. I also re-learned today about VBA’s superannuated support for interfaces, polymorphism, and delegation, for another project I am working on.
My wife has been baking cookies for Purim this week, which is a lot of fun, but incredibly tempting to me, as I have been on a low-carb diet the past few weeks. I have to loose all the weight I gained over the past 14 months, due to stress- and grief-related overeating. I am using MyFitnessPal, once again, to track my eating. I have also been doing low-paced treadmill workouts in the evenings, though not every night. So far, my diet and exercise regime has gone really well, but sweets can still be tempting.
One new wrinkle in parenting that my family is dealing with is that my two-year-old son has recently developed separation anxiety, which is normal at his age. It has lead to a good deal of interrupted sleep late at night, when he wakes up and screams “Mommy!” My wife bears the brunt of it, though. He cries for her, but not for me. I am definitely second banana during these intermittent nighttime terrors.