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.

This Should Clear Things Up

Published at 07:12 on 2 August 2023

From the indictment:

The Deputy White House Counsel reiterated to Co-Conspirator 4 that there had not been outcome-determinative fraud in the election and that if the Defendant [Trump] remained in office nonetheless, there would be “riots in every major city in the United States.” Co-Conspirator 4 responded, “Well, [Deputy White House Counsel], that’s why there’s an Insurrection Act.”

Them or us. They use the power of the State to destroy us (and with it, open society), or we use the power of the State to destroy them (and enable open society to be preserved). It was always thus. As I wrote in the wake of the insurrection:

We must win and the fascists must lose. It is as simple as that. Everything  that follows flows from this simple, elementary fact.

Fascists want a world where fascism is the only principle allowed. All debate, all activity, save for the glorification of the fascist order, will be sedition. Non-fascists span the whole gamut of ideologies outside fascism, and we do not want that. The vast, vast majority of us want a world where openness, debate, and dissent are not only allowed but valued. This latter state of affairs may be termed an open society.

There is simply no compromise possible between the two positions. Either open society prevails, or fascism prevails.

12 January 2021

This is why I was so worried about the lack of a prosecution of those at the top for the events of 6 January, and this is why I am so relieved to see prosecution finally commence.

At Last

Published at 23:05 on 1 August 2023

It seems as if American democracy might finally be getting serious about trying to save itself.

The basic nature of the indictment is plain: that Trump incited the insurrection on January 6th.

I am not personally averse to insurrections, if they are against a corrupt Establishment that deserves an insurrection. If Democratic operatives had really tried to steal a legitimate victory from a Republican candidate (or, of course, the converse), then the sort of thing we saw on the 6th would be both:

  • Only to be expected, and
  • Completely justified.

As such, the false claims on Trump’s part that he was cheated out of his victory had only one logical conclusion: the one we saw play out on the 6th.

Really, nothing could be more clear.

The question now is whether all the dilly-dallying on the way to getting here makes this a case of closing the barn door after all the cows have already escaped. But as the old saying goes, better late than never.

On (Not) Being a Java Careerist

Published at 07:40 on 29 July 2023

Not to slam Java careerists. One thing they are is very smart and talented. One just has to be, in order to deal with all the gratuitous complexity bred by the traditions of that programming community.

But here’s the thing: I don’t want to devote basically all of my mental effort to doing that. I don’t want to lose my botanical knowledge, or my wide-ranging general scientific knowledge. And I would have to in order to succeed in the Java world. The mental load is just so extreme.

Even if I wanted to, I am not sure I could. I crave knowledge in a diversity of subjects. My mind would rebel, strongly, against being forced to hyperspecialize.

In a sense, this means I’m “lazy” in that I “don’t want to work very hard” at software software development. But I don’t see that as necessarily a bad thing. Why should I work harder than necessary? If there is an easier way to do a good job at something, why not choose the easier way?

Is it really intelligent behavior to continue doing something in a difficult way when you are aware that an easier way exists?

This all was, in fact, something I wondered a bit about going into this job. And I decided then that if this was the case, I wouldn’t succeed at the job, wouldn’t want the job, and would end up departing from it. And so here I am.

Why I Hate Java: An Example

Published at 20:46 on 28 July 2023

Building on this entry, let us relate a little story that transpired in the past week.

About a week ago, I make a stupid error and introduce a bug into the code. Shouldn’t be a big problem; one good thing about where I work is that there is a very extensive battery of tests for things.

But this is the Java universe we are talking about. Simplicity is not appreciated as a virtue. Both the test and build frameworks are ginormous and hypercomplex. Somehow, I still do not know why, some feature got triggered that caused the test(s) that would have detected my bug to fail to run.

Because the Java universe does not appreciate simplicity, that code base itself is ginormous and hypercomplex. If the code were not written by members of such a dysfunctional programming culture, it would have been broken up into smaller, more managable bits that communicated with each other somehow. The test log for the subset of the code I was working with would have been short enough I would have probably noticed something missing. Instead, the missing tests were buried in a little over 80,000 lines of test and build output. Can you read an 80,000 line log file without falling asleep first? I sure can’t. So I didn’t even try. Naturally, the missed tests go unnoticed.

The check-ins get rejected for other reasons, so I get to work on addressing them. Meanwhile, the whatever-it-was that caused the critical tests to get suppressed ceases to do so. So my first attempt to test the recode fails for this out-of-the-blue, off-the-wall reason. I look at my recent changes and see nothing that could cause this issue to manifest.

Not much can be done but to attempt to instrument the daylights out of the code with debug log statements and try to figure out what the heck is going on with the data as it gets operated on.

My first attempt to do so fails because the company’s network infrastructure suffers a hiccup and causes my build to fail. The company’s infrastructure is super-complex, poorly-documented, and unreliable. (Everyone else just basically accepts it because everyone else is a Java programmer and thus used to unnecessary complexity and the resulting unreliability.)

In my second attempt, I discover that for some reason the test framework suppresses all log messages. So I recode to use writes to standard output, figuring (correctly) that it won’t “intelligently” suppress those. The instrumenting turns out to be insufficient, so I add more.

Each of these iterations takes way, way longer than it should, because the code is big and bloated and complex and so takes 30–45 minutes to build. If everything was factored into smaller units, I doubt builds would take longer than 5 minutes (if that). So each iteration takes roughly 6 to 10 times longer than it should.

Finally, after at least 4 hours of effort, I locate the bug.

And this is why I hate Java. Not because of the core language itself (dated, but still not bad considering it was designed in the ’90s) or because of its runtime (still one of the best virtual machines out there), but because of the traditions of the community that uses it. A minor bug, that would have been resolved in half an hour easily, instead almost makes it into production and takes half a day to resolve.

And this happens everywhere, all the time. Everything is more difficult, more tedious, and more error prone than it should be, with a lot more busy work than there should be.

Those dysfunctional traditions are such an irritant that I have developed my own special term for them: Java community antipatterns, or JCA’s for short.

I have recently learned that I am on my way out where I work, mainly because I can’t cope with the JCA’s as well as the Java careerists. And frankly, I can’t wait till I move on. I’m already looking for another position, and it will be as far from the enterprise Java world as it can be.