Caution Confirmed

Published at 07:16 on 11 September 2023

Today I learned that a friend has become addicted to cetirizine and is going through withdrawal sickness after suffering an interruption in supply.

Cetirizine is more commonly known as Zyrtec. Yes, the over-the-counter antihistamine. That’s right, an antihistamine, not an opiate.

As an allergy sufferer, I have occasionally taken antihistamines most of my life as needed. The key words here being occasionally and as needed. I was originally given them by my mother as a child. It was not that long after I started being administered them that I pushed back, questioning why I was always being given a dose of them every day. Couldn’t we stop and see how bad the symptoms are without medications today?

Mom thought I was being somewhat silly for being willing to risk feeling miserable like that, all over a little worry about ingesting medication with a doctor’s approval. I felt that why should I take any medication unless I am sure I need it. (It’s not as if my allergies were life-threatening or anything.)

Such has been my policy about antihistamine usage to this day. If my allergies are making me miserable, I will medicate, and do so without guilt. Then I will cut myself off medication, and see how I feel without. If I don’t feel abjectly miserable, I will put up with low-grade symptoms and carry on. If I do feel miserable, I will take another pill.

Many, like Mom, have thought it silly bordering on Puritanical for me to be willing impose suffering on myself like this. Today I feel vindicated.

Postscript

I have also run across those who try to make me feel guilty for being willing to turn to the products of the pharmaceutical industry at all. Try alternative treatments, they say. Well, I have. They don’t work as well (often, they don’t work, period).

When I query them, I find out that such individuals inevitably either don’t have allergies, or that their symptoms are vastly less serious than mine. As such, their opinions the matter are irrelevant.

Java Community Antipatterns, an Ongoing Series

Published at 17:27 on 1 September 2023

To give you an idea of the general pathetic hilarity of the situation, I was reviewing some code at work today. It reads in a message from Kafka, obtains a validator object, and calls that object’s isValid() method on the message it receives. That method in return a ValidationResult object, whose valid() method is then called inside an if statement.

This immediately strikes me as odd. When you validate something, it either turns out to be valid or invalid. That’s it. Two options, no more, no less. Yes/no. Black/white. On/off. There is no need to create a new data type to represent a validation result, because a perfectly appropriate data type already exists, built in to Java: the Boolean. Just use that. Far simpler and cleaner.

Maybe the ValidationResult object does something special and has extended features beyond those of a Boolean? Yes, it has a message field! But wait, that field is never accessed. The only thing that is ever done with that object is to call the valid() method, whose purpose is to return the Boolean value that should have been used in the first place.

And what of the validator object? Its class definition is very simple, just one short method that makes some basic checks. If its argument turns out to be invalid, the message part of the result is set to the string “Data is not valid.” No, I am not making this up. Of course the data is not valid, you moron! That is why the valid flag is set to false! This field conveys exactly zero meaningful information.

What other code uses this validating logic? None of it, it turns out! So there was no need for the validator class, either. Could have just added a private isValid() method inside the one (short) source file where this logic is used. Would have been a whole lot clearer, because the person reading the code wouldn’t have had to open another file to determine just what the validation logic is.

So three classes, and three source files, are being used where just one would have sufficed.

Now, this was a particularly egregious example, but this sort of crap-ola happens over and over (and over) again in Java code. Needless complexity everywhere.

Why Canister Stoves Suck

Published at 08:18 on 26 August 2023

Introduction

I have blogged about this before, but it was quite a few years ago, so I figure it’s time for a rehashing.

I prefer liquid fuel stoves. Most of the world prefers canister stoves. If you read a typical guide to camping stoves, you will see it recommend canister stoves in most cases. I do not understand most of the world. This post explains why.

The Waste

You cannot safely refill canisters. There are products sold that claim to let you refill them, but they are not safe. It is too easy to get a tiny speck of dirt in the one-way valve of a canister when attempting to refill it. Then you have a gas leak on your hands. Not good.

So when a canister becomes empty, you must discard it. And since it is virtually impossible to recycle stove canisters (virtually all recycling agencies forbid them), “discarding” means throwing it in the trash.

Not Refillable

To reiterate, canisters are not refillable (see immediately previous section). When you buy a new canister stove, you get to leave home on your first camping trip with a new, completely full, canister.

From then on, except on that rare trip where your canister usage and your outings happen by luck to align, you get to take a partly-empty canister. Or you get to add to your ever-growing collection of partly-empty canisters at home. Or you get to take multiple canisters on a trip where only one could have sufficed, adding weight and bulk.

You will virtually always be juggling multiple canisters, most of them partly full.

The Absolutely Lousy Cool-Weather Performance

Note I said “cool” not “cold” above. Canister stove fans like to act as if performance issues only kick in during wintertime conditions. Unless you limit your camping to South Florida and the coastal parts of Southern California, this is a lie.

Once a canister gets below the ¼ full mark, performance issues start kicking in around 10˚C (50˚F). A canister stove operating under such conditions can’t hold a full flame for more than about a minute. Output will then start rapidly declining, eventually reaching simmer levels.

A full canister can indeed offer acceptable performance down to about the freezing point, but see the previous section. You will almost never be operating your stove on a full canister. You will almost always be operating it on a partly-full one.

In my part of the world, overnight temperatures can drop below 10˚C pretty much any time of the year, even in the middle of the summer. In the mountains, they can drop to around 0˚C even in midsummer (yes, I have woken to frosty mornings in July and August). Cold mornings are exactly when I want my hot cup of tea and hot oatmeal most, and they are exactly when a canister stove will refuse to deliver same in a timely manner. Canister stoves disappoint, even in the summer.

The solution, of course, it to take multiple canisters on a trip, so you can switch to a full or nearly full one on such mornings. And again, you end up juggling multiple canisters in various stages of partial emptiness, and sooner and more often than simple unrefillability would dictate.

Liquid Fuel Stoves Solve All of These Problems

  • Less waste. Liquid fuel is sold by the gallon in thin-walled containers that use less resources than a canister.
  • Refillable. Just top off the tank before you leave on your weekend outing. No need to take extra fuel. No need to juggle partly-empty canisters.
  • Cold-weather performance. A liquid-fuel stove will operate at full blast until the tank is empty, no matter how cold it gets overnight.

About High-End Canister Stoves

There are some high-end models of canister stove that solve the cool-weather issues. They do this by operating with their canisters upside-down. Effectively, they are liquid-fuel stoves that use the pressurized liquid inside a canister, instead of highly refined gasoline, as their fuel. Many of them can, in fact, operate on gasoline simply by changing tanks.

This solves the cold-weather problem. Unfortunately, you are still stuck with unrefillable canisters. Given these stoves are as complex as liquid-fuel stoves (because they are liquid-fuel stoves), they are as expensive as them. Since one is spending that sort of money anyhow, why not just spring for a refillable gasoline tank and use the stove that way?

Where I Think Canister Stoves Make Sense

All the above said, there are some situations where I think a good argument exists for canister stoves:

  • Group campouts with the pyrophobic. Lighting a liquid fuel stove is not so simple as lighting a canister one. The process can intimidate some people. Many modern canister stoves even come with built-in igniters, making them even more like a kitchen stove.
  • Air travel to areas where canisters are available. It is hard to completely clean all traces of fuel from a liquid-fuel stove, and if there is literally so much as the faintest whiff of gasoline on one, airport security will probably confiscate it. Not a trace of gas remains on the stove part of a canister stove more than a few minutes after use. So it is easy to take the stove, provided you can procure a canister or two after you land. (You will probably have to leave a partly-used canister behind, but that is a relatively minor loss.)
  • Budget-sensitive, infrequent use. Canister stoves cost significantly less than liquid fuel ones. If you don’t go camping very often, the better performance of a liquid-fuel stove might not be worth the extra money.

They are simply not the default best choice for most as they are so often claimed to be, that is all.

Putin Regains Some Strength

Published at 12:24 on 24 August 2023

Of course Putin did it. There is a well-established history of Putin’s adversaries suffering unfortunate “accidents.” The chances of this being a bona-fide accident are somewhere between slim and none.

Putin had to do something like this to regain some strength after showing himself to be the pathetic weakling who ran away and hid when threatened and then thanked his challenger for standing down. That is emphatically not how a strongman deals with his adversaries. Unfortunate “accidents,” by contrast, are a classic.

The trouble is, Putin still turned tail last June, and still then thanked Prigozhin for standing down. He can’t undo those things. He’s regained some strength, but he has a ways to go before he looks once again like the strongman Putin of old.

More challenges to Putin’s authority are still possible. Likely, even.

Soon: Put Up or Shut Up Time

Published at 22:33 on 23 August 2023

Trump has been warned not to threaten jurists or poison potential jurors.

So of course he will. He has no self-control, and his whole life up to this point has taught him that as a hereditary member of the wealthy class, the laws that apply to the little people do not apply to him.

At that point, again it becomes put up or shut up time for the legal system (just like it did when Trump instigated an insurrection). Norms that are not upheld cease to be norms.

Cutting Over to LaTeX

Published at 15:15 on 20 August 2023

The above use of StUdLy CaPs courtesy of a community somewhat enamored of them. An overly-cute quirk that for a long time made me shy away from that document preparation system. It’s silly, to be sure, and hardly the No. 1 reason, which is that I had by that time:

  • Already had learned troff, which provides the same general functionality,
  • Often I did not have access to a laser printer, and troff shares an input language with nroff, which can produce passable output on a simpler and at the time much more common typewriter-like printer. TeX and LaTeX, by contrast, are useless if you don’t have access to a laser printer, phototypesetter, or graphics display.

Time passes. LaTeX grows to be way more popular than poor old troff. Users deveop and share all sorts of macros to do just about anything you want. Those same users have many online forums that can be searched if you get stuck or puzzled. troff gains nothing equivalent. Get frustrated buy troff‘s inability to set text that wraps around illustrations (a standard book publishing technique).

So yeah, it was time. The final push that made spend most of a day reading Knuth’s definitive description of his program was my resumed job search, the desire to make a résumé that breaks a few of the rules (using some of my favourite fonts), and the difficulty of getting good font support for troff. By contrast, there are modern versions of TeX that can read standard font files.

(Yes, I know there are modern versions of troff that can apparently read standard font files. The rub is, they lack certain extensions to standard troff in the version I have been using, extensions that I am making use of, so I would have to rewrite anyhow. Plus. troff still can’t format output by wrapping around illustrations. Why not rewrite in the more powerful and full-featured alternative?)

Anyhow, I’ve now learned enough of LaTeX to make it do what I want to do… for now, which was the goal.

The Go Programming Language: Too Minimalist

Published at 18:55 on 15 August 2023

I first ran into this many years ago, when Go was first released by Google and I played with it a bit. I ran into a situation where a ternary (aka conditional) operator would be handy, only to discover that it doesn’t exist in Go. OK, then, maybe I can use an if statement as an expression? Sorry, in Go if is strictly a statement and not an expression. So I sighed, introduced an extra variable into my code that otherwise would not be needed, and coded an if / then / else statement.

Then earlier this year I run into an issue with Helm, which is written in Go. I was trying to use it to generate a YAML file from a template, and was getting tripped up because Helm was sometimes inserting newlines into the output. This can happen in Python, too, but there is a way to disable the feature. Surprisingly, there was no way to disable it in Helm, because Helm of course uses the Go YAML library, and that feature is absent there. You will get your gratuitous newlines, and you will shut up and learn to like it. Lovely.

Maybe those two experiences should have been sufficient to warn me, but no. I was determined to give Go another chance. So I decide to revisit the language by rewriting a Python program in it.

That program’s purpose is to detect and report characters and byte sequences in source code files that are likely to be troublesome. My motive for writing it was when I once wasted most of my day trying to find a Java bug caused by a Unicode zero-width space in a source file. So it ends up being a pretty good exerciser of a language’s character set conversion libraries.

Again, Go fell short in the feature department. One of the Unicode character classes is Cn, unassigned code points. Such things, being undefined in behavior by the Unicode standard, are nothing but trouble and so should be reported as troublesome. But wait! Go does have a library that defines Unicode character classes, but for some reason the Cn class is missing. It’s possible to code around this (with some lossage) so I do.

Then I run into another problem: detecting invalid byte sequences in an input file. Go simply replaces these with the Unicode replacement character, code point U+FFFD. But what if a source file has such a character in it, then what? In Go, it is impossible to tell if the character is actually there (and sometimes I might want to allow it, and let it silently be accepted), or if it was inserted by the appropriate encoding.Decoder method in response to encountering an invalid byte sequence (which should definitely always be reported).

In Python or Java (and I assume most other languages), it is no problem: one can tell the decoder to signal an error on an invalid byte sequence if returning replacement characters is somehow unacceptable. Not so in Go. You will get replacement characters, and you will shut up and learn to like it.

It’s still possible to write the program, of course. It just ends up being unnecessarily quirky, failing sometimes to detect unassigned characters, and raising false alarms about bad byte sequences if a file contains completely valid replacement characters in it.

But why? Why choose a programming language that breeds quirks and unexpected surprises? Such things are bad, whether they arise from excessive complexity or excessive minimalism.

And these are not the only examples I have run across (both in the last few days and earlier), either; they are merely the ones that fit best into the story I have related here.

It all makes me appreciate more just what a good job Guido did in striking a good compromise between complexity and minimalism in the Python programming language.

Java Community Antipatterns, an Ongoing Series

Published at 08:35 on 12 August 2023

So I’m starting to play with the Go programming language again, mainly because in many ways it’s the anti-Java (it is not even a fully object-oriented language, by design). It was written mainly by Rob Pike, who is part of the old Bell Labs software culture that is generally skeptical of object-oriented programming, for many of the same reasons that I have come to be skeptical of it. One of those reasons is that excessive reliance on the object paradigm tends to breed unnecessary complexity.

Generally, when I have a question, I can find an answer in the documentation fairly easily. This morning, I had a build system question I could not easily find an answer to. So I decided to figure it out by looking at what the developers of a well-known, open-source software project in Go had done. I chose Helm.

It only took a few minutes of examining the source code to figure it all out. With Java, I would have pissed away half a day, easy. Instead of a Makefile, there would have been pom.xml (Maven) or build.gradle (Gradle). Both are incredibly complicated compared to Make, and both inevitably involve the use of multiple plugins that are also incredibly complicated. I would have been combing through documentation and scratching my head for hours.

Instead, boom! Answer obtained, in the space of a few minutes. The way it should be.

And Helm is not a small or simple project. In other words, despite its simplicity, Go seems to be every bit as powerful and useful a language as Java. More powerful and more useful, in fact, since it is easier to use, and one can spend time focusing on designing software instead of battling the (unnecessary) complexity of the overall programming environment.

But wait, there’s more! Just like the gratuitous complexity of the standard Java class library has proven contagious, the clean simplicity of the base Go programming environment seems equally contagious. I decided to satisfy a bit of intellectual curiosity about how Helm did something. This is something that frequently takes me hours with a Java project. But not here! Within a minute, I found the relevant bit of source code and my question was answered.

Which, again, is the way it should be.

The Garmin Drivesmart 66 Keeps Disappointing

Published at 21:26 on 11 August 2023

The suckiness that is the GPS I mistakenly purchased just keeps on coming.

Last week, I tried to use the device to count down the miles to the unmarked turnoff for where I was going camping east of Chinook Pass. Knowing how generally useless it is for navigating urban traffic, I used a smartphone and Google Maps until I reached Enumclaw, then shifted to the Garmin as I was about to leave cell coverage.

And the piece of junk directs me to go literally hundreds of miles out of my way and get there via Snoqualmie Pass. Yes, from Enumclaw. To get some idea of just how staggeringly bad that routing is, here is a map showing the route Google Maps recommends to the same general area (i.e., the obvious route, the one any sane person would take). It is necessary to zoom out a bit to see the route via I-90 and I-82 that it wanted me to take.

I mean, sure, it’s harmless in this case because I knew better, but what if I didn’t? What if I was using the thing to navigate in unfamiliar territory instead of using it to count down the miles to a turnoff that it had been a few years since I last took?

The Drivestupid 666 only realized the obvious routing once I had travelled most of the way to Chinook Pass, after spending nearly an hour recommending I turn around.

Ukraine’s Counteroffensive Has Failed

Published at 19:21 on 9 August 2023

This spring, it was coming Real Soon Now.

The anticipated start date came and went, and it was still coming Real Soon Now.

Then it basically dropped off the news radar and we stopped hearing about it. There have been no stories about the sort of big territorial gains one would expect given a successful counteroffensive.

This is, by contrast, exactly what we would expect given a failed counteroffensive. No belligerent will ever admit their grand plans have failed. If the counteroffensive had yielded significant territorial gains, you had darn well better believe it would be all over the media. But a failure will just get swept under the rug and not talked about. As we have seen.

Overall, the conflict has still gone far better for Ukraine than originally anticipated (remember, I was expecting Kiev to fall and the situation to degrade into an prolonged occupation facing guerrilla warfare). It’s just that this particular phase of it has gone significantly worse than anticipated for Ukraine.

This should not be reason for despair. No war goes exactly as planned even for the eventual victor. The Confederates scored important battle victories over the Union. The Axis defeated the Allies in many battles, and even ended up completely occupying some of them.

This was always going to be a long, ugly, bloody slog. Like it or not, if the Russian leadership wants to be in Ukraine, Russian troops will be in Ukraine, and there is really not much Ukraine or the West can do to stop that (at least not overnight).

Russian troops will only cease to be in Ukraine there when the Russian leadership decides to withdraw them. This is a natural consequence of the disparity in military strength between the two nations. The Russian military is not particularly well run, but Russia is so much larger a country that it still is the more militarily powerful of the two.

It is a situation much like Afghanistan (for both the Soviet and US-led invasions). Both the USSR and the USA were (and in the case of the USA are) much more powerful than Afghanistan. So long as the occupier wanted to be there, it was there. It was only when the occupier decided that the costs of the occupation were no longer worth it that the occupier decided to leave. And getting to that latter decision took many years.