Since I deleted my social media accounts (and I’m not sorry), it may be that the one or two humans who look at this blog may not know that I’m updating a different blog with status updates on our rebuild process. If you are at all interested, or would ever consider asking me the question, in person, “How’s the house coming along?” then you really ought to be checking out the household blog.
I just went on a week-long vacation wherein I was programming, among other things, in locations with dodgy or nonexistent network connections. My offline Swift modifications worked great; so, local mirroring of packages is a total win!
But here’s a thing: a dinner conversation got me working in Flutter again. And, a few days before we left for this vacation, I got a note from JetBrains saying that they’re gonna adjust their subscription rates for, among other things, IntelliJ IDEA. Now, it’s been a few years since I did any Java development and I was starting to think maybe I would let my JetBrains subscription lapse. So I tried out Visual Studio Code with its Flutter plugins and rediscovered that Flutter really, REALLY, doesn’t like to be offline. So, okay, fair enough, I’m only even considering Flutter as a language for developing an app to be deployed to browsers, so the live operating environment requires a real Internet connection. Still, it’s kind of obnoxious.
Ooooh, and then, on the transcontinental flight home, I found that VS Code doesn’t like to attach to a Docker instance if there’s not an active connection to the Internet. Because, sure, I’ve got VS Code locally, and the instance is local, and in fact the container instance has had VS Code connected before, but I just restarted VS Code, and yet VS Code still wants to go off and download a debugger into the container. Just in case, you know, there’s been an update. And if it can’t, well, fuck you.
Which means that while I’m on this world cruise where the ship is in the middle of some ocean somewhere, God forbid I should need to reboot my computer.
There’s this problem that comes when one deals with a complicated system or process for a long time — one internalizes all the details and complexity, and starts to factor all the weird inner workings of the system into communication about the system. In human terms, this is where professional jargon comes from. There’s stuff to be said about that, but that’s not what I’m thinking about right this second.
What’s got me going off today is this swell warning from the documentation of a framework I’m using:
Combine’s Publishers.Concatenate operator, which this function uses, can leak when its suffix is a Publishers.MergeMany operator, which is used throughout the Composable Architecture in functions like combine(_:).
Here are some questions that come to mind:
- Leak what? Memory? Threads?
- Are all the functions in Composable Architecture which use this dangerous
Publishers.MergeManyoperator marked, so that I’ll know not to use them with this code?
- The guys who develop The Composable Architecture are undoubtedly smart and skilled. But do they really think that it’s a great idea to be fully aware of all the implementation details behind every API call you make?
This last one is the part that gets me. This kind of deep knowledge is good, possible, and even necessary when you’re writing small, tightly scoped bits of code that you want to optimize like crazy. However, once you start writing code that spans multiple platforms and does lots of different things (such as, a desktop app, a phone app, a server app, the backing database, as well as load balancer and mail gateway) then there are just too many things to keep track of. Knowing all the implementation details of every API your code calls would mean taking weeks to write a single function, forgetting other stuff (like your wife’s name) to make mental room, or both.
And then, saying to consumers of your code, “I had to know all this stuff, so you should, too,” is just the capstone of arrogance.
Which is why that warning in the documentation really just means, to me, “Don’t actually call this function.”
I’m currently working on a suite of programs (which sounds a hell of a lot fancier than, “a couple of apps and a database,” — word to the wise, &c.) that deals with people. A person record has, as an option, a birthdate. You never know, someone, somewhere, might like to commemorate great-great-great-uncle Ralph’s birthday somehow.
Anyway, because I am a contrary old geezer, I’m writing all this stuff in Swift. There’s a server and a client, so of course I need to serialize the data as it gets transported between the two. Ultimately, the data resides in a database (because of course it does) and that’s currently Postgres — could become MySQL or something else, but who cares, there’s a swell abstraction layer between my code and the actual database. So, the birthday is really a date; I’m not doing astrology so I don’t care about where in the world the birth happened, nor when during the day. I just want a year, month, and day. And of course, I know, there are lots of calendars that are currently in use, so whatever, I still need some kind of an instant to store.
So. ISO-8601 is a sort-of standard, and the link here goes to Wikipedia rather than the actual specification because reading a standard can cause blindness and I don’t want that on my conscience. It defines a way that dates are supposed to be represented in text form. It looks kind of like “year-month-day T hour:minute:second.nanoseconds Z offset” where “offset” is what you need to add (or subtract) to GMT to get the local time zone.
I started off just trying to use the default serialization of the Date object in Swift, but that produces a bare integer (probably seconds since the epoch). So obviously, that didn’t work (if it had, I wouldn’t be writing this). Next, I tried being explicit about it on the client side. But that’s a problem, because if I’m going to all the trouble of doing an ISO 8601 encoded date, that includes a time zone, and that’s baloney because the client application isn’t collecting a time of day. So now I’m thinking, fine, I need to collect a Gregorian date and from that date, extract the year, month, and day, and then store those. Because the effect I’m trying to produce is that when a user looks at a calendar they can say, “Oh, tomorrow is the 105th anniversary of the birth of aunt Helen.”
For crying out loud. So no, I should not store a birthday as a Date object; I should store it as my own weird non-standard business object and translate it upon reading it from storage.
I’m working on a new application. I got the basics done, and because I’m an old crank, I made the data storage a file. So, you can do all kinds of cool things with the data you enter, and you can do it without having a network connection. It’s like a spreadsheet!
But then, my target user said, “I really want to be able to collaborate with other people on this. It shouldn’t be a document, it should be a web service.”
“This time,” I thought, “I’m going to be smart and actually design the API before I just bang something together!” Isn’t it cute, how I’m all optimistic like that?
Anyway, I looked around and found that nowadays all the cool kids are using OpenAPIs to define their services. It also turns out that Insomnia understands openapi, so I can document the API in one editor pane and then in the next tab over I’ve got request stubs already defined for all the endpoints. That’s actually pretty cool!
But, as usual, it’s never all good news. For starters, the openapi definition is either JSON or YAML. Gross. But at least the editor lets you collapse sections, so it’s relatively tidy. But, and this isn’t just Insomnia, it’s everything that manipulates openapi stuff: the parsing of the definition is done by swagger, which doesn’t understand openapi version 3.1 (which was released last year). Not that I actually care all that much, since I’m not intending to use any features introduced there — 3.0 is good enough for now. Still, it’s an irritant.
Also, Insomnia doesn’t let you save the definition to the local filesystem. If you want to save the definition somewhere, you can hook up git and push your definition to some repository somewhere, or you can just copy and paste it from Insomnia into SubEthaEdit or whatever.
Oh, and the other irritant that got me to start writing this post in the first place: syntactically significant indentation, and a domain-specific editor that doesn’t show you the indentation level or make it easier to be at the right indentation than at the wrong one! Seriously, I feel like the guys who developed YAML were probably Python programmers.
Got an email just now, from the marketing department of a company that makes some server software that I occasionally use. The notification of new email popped up on my screen, with a snippet of the body saying that cyberattacks are increasing in sophistication and volume, so I should…presumably, the rest of the email was a pitch for me to go spend some time and money listening to them explain how they can offer me security as a service.
There are a couple things about that email that make me cross.
* It’s emotionally manipulative. They want to sell me something I don’t need (granted, someone might need it) or want, and the opening line is, essentially, “be afraid.” Because people who are afraid make the best decisions about what to do next, don’t they? I hate people who take advantage of this. They claim that they’re doing something to help you, but that’s actually a lie: they’re doing something to help themselves to your resources. Any benefit you derive from the transaction is purely incidental. Every time an email like this lands in my inbox, I’m being lied to by someone who wants to take my stuff, and the lie is, “I want what is best for you.” Seriously, marketing people suck.
* Cyberattacks are increasing in sophistication and volume, sure, but it’s gonna take a really sophisticated cyberattack to compromise my gravity operated clock. The solution to crappy software is not more crappy software, but less. These guys are tying to sell me software, so they’re going to claim that it’s rock solid. But anyone who has ever done serious programming knows that any such claim is a hope rather than a statement of fact. Anyone who says otherwise is trying to sell you something, and they don’t care about your well-being.
You know what else is increasing in volume, if not sophistication? This kind of marketing. Everyone wants the general populace to be scared, because scared people are easily manipulated, and that manipulation isn’t just about money — it’s about everything. Political decisions. Economic decisions. The world is huge, but finite, and I bet that the marketing folks are looking at population increase and thinking about Malthus and they’re sharing their fear.
It’s bill-pay day, so of course I’m confronted once more with several payment portals that have security theater. What do I mean by that? I mean, stuff that looks like it’s some kind of security (preventing theft of personal information, verifying that the actor is the right person, etc.) but which doesn’t actually provide any security. Sort of like the bit where you have to take off your shoes when going through airport security — that doesn’t do anything useful, but it makes people feel as though something useful is happening.
So here I have to deal with four separate payment portals. The situation is, I’m paying a bill. I’m trying to give someone else money. And here’s what the someone else wants:
- Enter my checking account number and the bank’s routing number, since paying with a credit card incurs the credit processing fee. But, the paste operation is disabled on these fields. So I have to type these numbers.
- And, I have to type them twice, to make sure they’re the same.
- Fill in a CAPTCHA before submitting the payment form.
What the first step does for the portal is a mystery. Why should I be unable to paste the routing number and account number, which I copied from my banking website or my password manager? It makes no sense. I’m much more likely to make a mistake while typing than while doing copy/paste.
The second step is a legacy from the days before copy/paste. That’s an error detection step to catch mistakes on data entry. If you allow copy paste, you don’t need that step. If you disallow copy/paste, then you do need it, but why are you disallowing copy/paste? (Special bonus frustration: the fields are marked as password fields, so you can’t even read what you’ve entered — it’s all just asterisks or bullets.)
The third step is an utter mystery. I’m not entering a password, I’m paying a bill. The information displayed on the “payment received” page is the same as the information required on the “submit payment” page: account number and payment amount. As I’ve written before, who cares whether a robot submits the information?
Walking along the street this morning, I saw this: a bearded old man, bundled up in woolen hat and puffy jacket, covered in blankets, surrounded by shapeless lumps of textile – possibly tarps, or sacks – sitting in a wheelchair and parked at the edge of a convenience store parking lot. He had, somewhere, a radio tuned to a talk show. The flat quality of the voices led me to think it an AM station, which makes sense, since FM is mostly commercials interspersed with occasional music. The main voice was a woman’s, confidently using logical fallacies to promote divine creation of a flat earth.
I can delete my social media accounts and refuse to read the hyperbolic news items in the press, but that’s actually a privilege. When my dad was in hospice, the residents of the house were parked in the living room with a TV tuned to Fox and that’s what they got. I think there’s money to be made, making the helpless feel even more afraid, and I think that people are already doing it.
It’s pointless to kill your television if you leave your radio alive.
Obviously, I haven’t thought deeply about this. All I know right now is that I feel sorry for that old guy in the wheelchair. I want him to know God loves him and he doesn’t have to accept illogical nonsense about cosmology for that to still be true. And I feel sorry for all the other scared and angry people who need to be comforted by a voice telling them that the world is flat and there’s a vast scientific conspiracy trying to pull one over on them. Because the conspiracy is that voice, and if they’re listening, then they really need to be hearing something else. I wish I knew what it was.
Today’s entry in the “put a computer on it” dopeslap file comes from Ars Technica. Turns out that ancient IoT devices are actually a giant security risk. If only someone had pointed this out at some time…
Okay, so, maybe sticking the Internet into everything isn’t such a great idea? Maybe?
Imagine a world where Russian hackers can’t use your doorknob to steal access to your bank account…
You know what’s dumb? Putting a “Prove you aren’t a robot” widget on your invoice payment flow. Imagine for a moment that you’re a service provider and you’ve done some work for someone. You send them an invoice, and now they want to pay you some money. With me on this hypothetical journey? Good.
Now. A web browser submits some payment information to your payment portal — credit card number, invoice number, payment amount, all that good stuff.
Do you, who want to get paid, actually care whether it’s a script or a human who’s submitting that information? Let me give you a hint: no, you do not. All you want is your money.
The “protection” offered by a CAPTCHA has nothing to do with this flow. ZOMG, why am I seeing this crap this morning?