ArcaOS 5.0: UNIAUD Update

I have discovered that part of my UNIAUD  audio driver problem can be solved. Using the command line UNIMIX.EXE, I can manually set the speaker output level. Turns out that there was actually sound being generated, but only to the headphone jack.

There’s still another problem, however: desktop sounds repeat and are very noisy and filled with static.

I will be publishing a few screenshots of ArcaOS in the coming days.

VistA Innovation?

VistA cannot evolve if its MUMPS code is viewed as the unfortunately obsolete back-end for Node.js applications.

If we buy into the current prevailing wisdom that we should essentially leave VistA’s MUMPS code in maintenance mode, enshrining its current structure and shortcomings, we are implicitly asking for it to be slowly phased out, and replaced with something else.

Adding blobs of red and mouse support to ScreenMan forms is not VistA innovation.

Building hundreds of new RPC broker calls for consumption by Javascript code is not VistA innovation.

Building tools to paper over the cracks in KIDS and DIFROM is not VistA innovation.

Writing web frameworks that expose MUMPS globals and VistA RPCs is not VistA innovation.

Even if you use every DevOps tool and agile methodology that is trending on Reddit while you’re doing these things, it’s not VistA innovation.

We can wax eloquent at great length saying that lab and scheduling are the keys to the kingdom, but the very best lab and scheduling packages really aren’t VistA innovation.

We are at this point essentially putting lipstick on a pig. The pig may be a tremendously powerful and intelligent wild boar that can do thousands of things normal pigs can’t do, but wrestling with it will still leave a bruise.

That’s not to say that DevOps tools, web frameworks, packaging ideas, or any of these projects and ideas aren’t innovative. They are, and everyone who does that work deserves praise and appreciation for it. But these are accessories. Nice, useful, pretty, and even essential accessories. But are they VistA? No. VistA is 30,000+ MUMPS routines, written in a style that was in vogue during the Reagan administration.

VistA’s entire MUMPS codebase needs to be refactored. Not replaced, but refactored in a way that reflects all the great and useful techniques that computer science has taught us since the underground railroad went mainstream. And yes, I mean APIs. I mean separation of concerns. I mean (perhaps controversially) that the SAC needs to quit forbidding mnemonically useful identifiers, and instead start forbidding us to leak data through local variables. Well-defined interfaces, that cannot speak to any component of the software that is more than one layer of abstraction away from it. Interfaces forming a strong contract between the software and the developers who develop against it.

MUMPS is more than up for the task. We have scoped variables with NEW. We have call by value and call by reference. We can pass complex objects to and return complex objects from well-defined methods in the form of MUMPS extrinsic functions and the glorious dot operator. Every modern implementation of the MUMPS language supports at least 31-character identifiers and large routines, so that routine names like ZZTQPRL3 are now not only unnecessary, but indefensible.

VistA cannot survive if we have the hubris to maintain that its design is sacrosanct, and superior by definition to new technologies. Along with this, we can no longer pretend that medical software is any different from other complex software, nor can we lie to ourselves and say that MUMPS–or hierarchical database technology in general–is inherently superior to other database technologies in our domain, and finally, we cannot continue insisting that advances made in programming methodology and software architecture don’t apply to us.

It’s been asserted–but not once effectively proven or even rationalized–that these computer science concepts (layers of abstraction, interface contracts, APIs, and separation of concerns) somehow don’t apply to medical software, or to VistA. I’ve personally heard arguments ranging from “APIs are an attack vector” to “VistA is a living organism, unlike any other software.”

Poppycock. Absolute rubbish. So completely wrong as to be comical.

First, VistA is utterly loaded with APIs. Every time someone calls into Kernel or FileMan, that’s an API. Every time someone writes a new RPC, that’s an API. And every one of them is as much an “attack vector” as it is in modern software. The only real difference is that ours aren’t well-architected, ours don’t separate concerns, ours are poorly documented, ours require way too many arguments, and ours have horrible names that nobody can remember.

Second, software is software is software. The things that make an operating system unmaintainable make an EHR unmaintainable. The things that make a word processor maintainable make an EHR maintainable. Even the argument that hierarchical databases are somehow inherently better-suited to medical data than relational databases (or network databases, or any other database) is specious and silly. Perhaps this was arguably true in the 1970s, but it is not true today. Every data structure that you can represent in FileMan, you can represent in Oracle or MySQL or DB2, with minimal fuss. Look at Practice Fusion. Look at Amazing Charts. The hip, new EHRs are all based on modern databases. It can be done.

It’s been argued that MUMPS’ lack of schema makes it easier to change the database to match the evolution of medical data without re-writing the software. Again, rubbish. Once FileMan is in the picture, we are right back to employing a schema that requires UI modifications once we change it. FileMan enforces its own schema on data organization. True though it is that external modules like ScreenMan make it relatively easy to propagate schema changes into the user interface, this same sort of ease exists in relational databases with technologies like ORM, LINQ, and others. And today, there are methodologies that make it even easier to propagate schema changes all the way up to the UI. If software developers employs proper separation of concerns and strong interface contracts, changes to the schema are transparent to the UI.

VistA admits of no such discipline.

In VistA, user interface, business logic, schema definition, and data storage are tangled together like Christmas lights in the box in Grandma’s attic. You can’t even programatically define a new FileMan file; it’s all done through interactive green-screen UIs, and distributed in KIDS builds, the installation of which are notoriously error-prone.

MUMPS has the facilities to make all of these nightmares disappear, and where it shines is in throughput, robustness, and scalability. It has great facilities for indirection, data hiding, abstraction, and all the other tools we need to make VistA even more awesome than it is. Just takes some time and dedication. It’s also fast. Extremely fast. Like, bullet train fast.

And VistA is awesome. The developers in its community are awesome and have tons of enthusiasm. But today, its core infrastructure needs some serious attention. MUMPS and VistA are kind of like a gorgeous Tudor mansion: scores of beautiful, ornate, and useful rooms, but all the pipes leak, the wallpaper is peeling, and the light in that one downstairs bathroom is always flickering for some reason. And we’ve lost the blueprints.

The VA wants to bulldoze the house and put up a shopping mall, a Best Buy, and a McDonald’s. In the meantime, they’ll throw some glue behind the wallpaper and set up buckets underneath the leaky pipes.

But the house is free for public consumption and improvement! So instead of doing what they’ve been doing, let’s fix the plumbing, put in some new wallpaper, and fix the electrical system. And while we’re at it, we can add central heating and a gourmet kitchen.

That is VistA innovation.

Contradictions

What I want as a computer user vs. what I want as a computer programmer are often polar and contradictory opposites.

As a programmer, I want computer languages and operating systems that give me complete, direct, and possibly dangerous control over the hardware. The power to not only create blisteringly fast and efficient code, but also to bring down the whole machine on a whim. If I can break the hardware in the process, all the better.

This is the essence of my earliest exposure to programming: writing BASIC programs in MS-DOS, with assembly language for the performance-critical sections. Translating the assembly language into the hexadecimal digits representing machine code, loading these codes into a BASIC string, and calling the address of the string directly. Getting into the muck of segmented memory, PEEKing and POKEing memory directly, engaging in dirty tricks to push the hardware to its limits, writing self-modifying code to squeeze every bit of power out of every CPU cycle. The antithesis of the UNIX philosophy.

As a user, I want all of the above to disappear, and programmers to be forced into high-level, safe, and nominally interpreted languages, on protected-mode operating systems that erect impregnable walls between software and hardware. As a user, I essentially want my computer to be as much of an appliance as my toaster.

If I get what I want as a programmer, the users’ lives become frustrating, and the audience and ultimate reach of computing is reduced.

If I get what I want as a user, most programmers’ lives become tedium and drudgery, as they’re reduced from engineers to technicians.

However, if I get what I want as a programmer, perhaps computers become once again the exclusive domain of geeks who will never again equate a CD-ROM tray to a cupholder or ignore the distinction between the web and the Internet, or refer to crackers as hackers. Doesn’t sound like a bad outcome, from my perspective.

It’s probably better for humanity that I don’t get my way. Just don’t take away my old DOS machine and my old assembler, lest I become even more of a curmudgeonly old fart than I already am.

Hmm.

Memories and Dynamic Textboxes

Around 2000, I had the dubious honor of enhancing–under contract–a VB6 application that interfaced to MODBUS radio telemetry units. Instead of using a ListBox or some other appropriate control, it employed a control array of TextBox controls to visualize raw sensor voltages from remote units.  The kicker to all this was that the code was all attached directly to a timer control that would go out and poll the units (this subroutine was about 20 pages long, mixing up MODBUS parsing, UI updates, radio communication, and virtually every part of the application munged together). When this code needed to do something with the received data, it read it back from the dynamic text boxes it had created during its poll cycle.

Dynamic textboxes are bad, mmmkay?

Dynamic textboxes are bad, mmmkay?

I refactored the code into a much better system and UI without dynamic textboxes. The new UI showed a tree view of all remote units and allowed reporting on each one, as well as fancy charts and graphs. Each sensor on each remote unit could have a custom math formula to turn its raw voltages into human-readable data. My version also logged data to a SQL Server database for archival and later analysis.

I was supposed to be hired by the company that originally made the software in order to turn it into a full-fledged SCADA (systems control and data acquisition) suite, but various situations with them and the organization to which I was contracted precluded that job move.

I have long since moved into the Linux and medical systems world, most recently doing Node.js development and EHR support. But this, my first programming job, has always stuck with me as a real “baptism by fire” moment, with which many fun memories are associated. I still have a fond place in my heart for VB6–with all its warts–but the process of creating from memory the little UI mock-up for the image I used on this post (which was done in VB6 in a Windows NT 4.0 virtual machine on my Linux box) makes me realize how far we’ve come and why we should never hope to go back.

What I want in a platform…

Just a small wishlist/rant:

Hardware

No more software buttons. Why do hardware engineers feel the need to make my volume controls, mute button, and power button require intervention from the operating system? Do it in hardware. I really don’t want a volume change to have to wait on the kernel to schedule the handling of its interrupt.

Whether this is a laptop, desktop, or server, make the chassis out of steel that doesn’t flex. I’m not so weak that I need a one-ounce laptop to be satisfied with life.

Casework should be toolless, and components modular easily field-upgradable–even on a laptop. Come up with several form factors for a laptop chassis, and allow the guts to be upgraded over time. Standardize, standardize, standardize. The largest one or two form factors for a laptop should not make weight a consideration.

Plenty of USB ports is a definite must, but I also want internal 10/100/1000 Ethernet and one RS-232 serial port. Also, give me a modular bay that can accommodate a 5.25″ device (optical drive, or even a floppy).

Instruction Set and CPU Architecture

A nice, orthogonal CISC instruction set with lots of flexible datatypes and addressing modes. Lots of general-purpose registers. Give me an instruction to copy bytes, words, etc. directly from RAM to RAM. Don’t make me sidestep through a register. If you can’t do this in pure hardware, microcode it. I don’t particularly care if we’re big-endian or little-endian, but I do like the POWER ISA’s ability to switch endianness. I want a flat virtual memory address space. If we have hardware multitasking (which we should) and the ability to support both little- and big-endian byte ordering, allow me to have different endianness per task segment. Allow CPU microcode to be software-upgradable.

I want several rings of privilege, and although I’m aware that ring transitions require lots of work, please optimize them as much as humanly possible. Don’t give me CALL instructions that are so inefficient as to be less usable than combinations of many more primitive instructions.

Give me lots of I/O channels (with DMA, obviously). I/O processing should be offloaded properly to a specialized ASIC or ASICs. Each I/O bus (PCIe, VME, SCSI, etc.) should be connected to an I/O processor ASIC, and this processor should have a uniform API  in the firmware (see below) abstracting away the differences between the various attached buses.

Give me massive L1 cache, and good support for multiple CPUs. Multiple complete CPU support should be given more priority than multiple cores/threads per CPU.

Firmware

I want a firmware with a fully-realized CLI. Give me a dedicated Ethernet interface for firmware, and allow me to natively redirect console output with VNC over this Ethernet connection, or via ssh if the console is not in graphical mode. The CLI should give me the ability to enumerate all hardware devices, configure things like SCSI IDs, memorable device aliases, Ethernet MAC addresses, etc. I should be able to boot from any partition on any connected storage with a simple command. I should also be able to dump registers and do kernel debugging through this CLI.

The firmware should have an API that is fully supported in all CPU modes without hacks like virtual 8086 mode. This API should allow me to enumerate and access all devices and memory easily. It should be available to a first-stage bootloader.

More to come…

The MUMPS Community: A Commodore Analogy

Eric S. Raymond’s Jargon File defines Amiga Persecution Complex as follows:

The disorder suffered by a particularly egregious variety of bigot, those who believe that the marginality of their preferred machine is the result of some kind of industry-wide conspiracy (for without a conspiracy of some kind, the eminent superiority of their beloved shining jewel of a platform would obviously win over all, market pressures be damned!) Those afflicted are prone to engaging in flame wars and calling for boycotts and mailbombings. Amiga Persecution Complex is by no means limited to Amiga users; NeXT, NeWS, OS/2, Macintosh, LISP, and GNU users are also common victims. Linux users used to display symptoms very frequently before Linux started winning; some still do.

The MUMPS community too often falls victim to this syndrome, frequently lamenting its small size. “We must train up the next generation of…” begins all too many sentences here. While there’s no harm in seeking out and training new MUMPSters, I don’t believe it is strictly necessary for us to win in the numbers game. We also too frequently look to large government agencies like the VA to bring about our wishes instead of bringing them about ourselves: a feat I believe to be well within our reach.

For illustration, let’s look at the saga of the Amiga personal computer.

The Amiga was developed in the early 1980s by Hi-Toro, which would later become Amiga Corporation, in turn acquired by Commodore Business Machines. Vastly ahead of its time, the  1985 Amiga included a Motorola 68000 processor, dedicated custom ICs for multi-channel waveform sound, full-color graphics, sprite-based animation, fast memory transfers, the unique feature of having all system bus timings evenly divisible by the clock frequency of NTSC video, and a GUI-based virtual memory operating system with preemptive multitasking. The system improved steadily through the 1980s and early 1990s, until a series of business and technological missteps led to the 1994 bankruptcy and liquidation of Commodore. The Amiga technology was purchased by German PC retailer ESCOM AG, which continued to manufacture slightly facelifted versions of the last Amiga systems offered by Commodore, until ESCOM AG met its own demise in 1996. Eventually, the Amiga patent portfolio was snapped up by PC manufacturer Gateway 2000. Many vague promises were made to the Amiga community about a new generation of Amiga hardware and software, but none were ever delivered, and ultimately, two Gateway 2000 employees, Bill McEwen and Fleecy Moss, bought the Amiga patents from Gateway 2000, forming Amiga Inc.

The small Amiga Inc. began once again manufacturing the late Amiga models, and licensed Haage & Partner to develop and release AmigaOS 3.5 and 3.9, the first AmigaOS updates since the Commodore bankruptcy. Keep in mind that both Amiga Inc. and Haage & Partner are tiny, private companies, and mere blips compared to Commodore and Gateway. Amiga Inc. also licensed the Amiga branding for the AmigaOne line of PowerPC-based Amiga systems, production of which continues today. Amiga Inc. licensee Hyperion Inc., a tiny video game porting firm, has released AmigaOS 4.0 and 4.1, bringing substantial improvements to the platform. The Amiga, long since declared dead by the mainstream technology press, now has:

  • Modern hardware systems with fast CPUs and modern expansion busses based on original board designs–considered a substantial accomplishment for the small companies that produce them
  • A modern and blisteringly fast operating system (AmigaOS 4.1) with modern web browsers and a large number of native applications

All of this was accomplished by a very small and dedicated community with a minimum of resources, one which thumbed its nose at the slow-moving giant (Gateway 2000). I may be crucified for saying this, but either of these major components (hardware platform and operating system) are significantly more complex, more difficult, and more expensive to implement than any EHR. Amiga systems have been in near-constant production since 1985, weathering multiple sales and bankruptcies, and continue to serve their small and faithful community well.

IBM OS/2 is another such example. I will not go into great detail, but to say that IBM abandoned the technology, only to have it licensed and improved upon by a tiny outside ISV (Serenity Systems Inc.) under the name eComStation, and the operating system–much like the earlier mentioned Amiga platform–continues to be improved to serve its faithful user community to this day.

MUMPS and VistA are very similar: technologies well-loved by their fiercely dedicated communities, declared dead by the mainstream press, largely stagnated at the hands of their large corporate and governmental implementers (who either have no business case to innovate in the space, or have an active goal of replacing the technology simply because it’s not new). The community built up around the technology should try to be a Serenity Systems Inc., a Bill McEwen, a Fleecy Moss, rather than waiting on our own Gateway 2000 (the VA) to deliver our favored technology’s salvation. If tiny companies can acquire an expensive, closed-source, proprietary platform, improve upon it, and handle the logistics of manufacturing a physical product, this community has more than enough manpower, talent, and resources to do the same thing for MUMPS and VistA. The difficulty is that our community has shown an alarming propensity towards talking about solutions and creating grand visions while seeming to hope that the code required to make them happen will simply pop out of the ground (or that the VA will open the floodgates and all will be as it was in VistA’s halcyon days–a pretty plot for a fairy tale, but highly unlikely given the entrenched dynamics of Washington politics).

Lest I come across as a Debbie Downer, there are pockets of this community that give me encouragement every day: VistA is about to have long-awaited modern user interfaces thanks to the highly commendable efforts of Sidney Tarason at Astute Semantics, which have a “wow factor” I haven’t ever before seen in this space. MUMPS and VistA users now have two open-source choices for building web apps that access MUMPS and VistA data: Rob Tweed of M/Gateway Developments has released the elegant, modern, and fast EWD.js, exposing MUMPS and VistA within the highly popular Node.js environment, while I personally have released CFMumps, which provides a cohesive high-level API for developing MUMPS and VistA web apps in ColdFusion and Railo–both environments that sit firmly in the J2EE model, while exposing a highly-simplified view thereof. Both are great candidates for VistA and MUMPS exposure and modernization in the web space, but we should not fall into the thinking that either is an acceptable substitute for evolving the core technologies of VistA, which means MUMPS code, and improving MUMPS code should involve evolving the MUMPS language. This has to be a community process, as the vendors have no reason to care, and the VA is unlikely to start caring.

If the entire community can draw from the spirit of Astute Semantics, M/Gateway Developments, and Coherent Logic Development, and get its nose out of politics and into code, much can be accomplished very quickly.

Let’s get coding!

Java: Why no true constants?

I find it odd that Java–a language intended to facilitate and encourage the development of elegant programs–never finalized (no pun intended) a way of expressing true constants. The closest you can get is “final” variables, that can only be initialized once, i.e.:

private static final int MSG_ERROR = 1;

But, they fall short, as they can’t be used in place of a constant expression, such as a “case” label in a “switch” construct; i.e., this will fail:

switch(msgLevel) {
case this.MSG_ERROR:
// do something
break;
}

because javac doesn’t consider a “final” variable to be a constant expression. You’d have to do:

switch(msgLevel) {
case 1:
// do something
break;
}

Which renders the case label’s purpose less than intuitive. Sure, we could use a comment after each case label, but that’s rather hack-ish, in my opinion: one of the most widely accepted best practices for writing clear code is to avoid the use of “magic” numbers (numeric constants that aren’t self-explanatory). In the case of Java, the language itself forces us–in certain cases–to use them. For a statically-typed language–even one with built-in garbage collection and automatic memory management–this seems a rather shameful trade-off. Apparently, Java reserved a keyword for constants early on, but it was shelved somewhere around 2005.

Why, Java? Why?