The Trials and Tribulations of a Windows Developer

Trouble ahead...
Trouble ahead…

After a very long hiatus, I am back doing software development on a Microsoft Windows machine. I decided to port EP Calipers, an app for making electrocardiographic measurements that is available on Android, iOS and OS X, to Windows. Several users had written to me and asked me to do this. Ever eager to please, I have launched into this project. And it has not been easy.

I am no stranger to Windows development, having developed a Windows database system for tracking and reporting electrophysiology procedures while at the University of Colorado in the 1990s. But it would not be overstating the matter to say that my Windows development “skillz” are rusty at this point. I have been living in the Unixy world of Apple and GNU/Linux for several years now, avoiding Windows other than when I had to, such as when I was required to use the ubiquitous Windows 7 systems running nightmarish EHR software at the various hospitals where I worked. I have not done any programming on Windows machines for many years. Transitioning back to Windows development has been, to put it mildly, difficult.

I have no complaints about Visual Studio. It is free and seems to be a very well-designed IDE, at least as good as, if not better than, Xcode and Android Studio. I like C#, which is like a cross between C and Java. Visual Studio can interface directly with GitHub. Given all this, what’s my problem with developing on Windows?

The problem originates in the command line environment of Windows, an environment that dates back to the beginnings of personal computer with the introduction of MS-DOS back in 1981, a system based on the CP/M disk operating system that dates even further back to the 1970s. Windows, which has made backward compatibility almost a religion, still uses a command line system that was written when disks were floppy and 8 inches in diameter. Of course, Unix is just as old, but Unix has always remained focused on the command line, with an incredible plethora of command line tools, whereas with Windows the command line has remained the unwanted stepchild to its GUI. Worse, the syntax of the Windows command line is incompatible with the Unix command line: backslashes instead of front slashes, drive letters instead of a root-based file system, line endings with CR-LF instead of LF, and so forth. So, in order to ease the pain of transitioning to Windows, I needed to install a Unix environment.

Even though Bash is coming to Windows, for now I downloaded MSYS2 which seems to be the preferred Unix environment for Windows nowadays. Using the pacman package management tool, I downloaded various binary packages that I needed, such as Git and Emacs. I faced the challenge of setting up my Emacs environment on Windows. My .emacs (actually ~/.emacs.d/init.el) startup file that works well on my Mac, loading various Emacs packages and customizations, didn’t do so well on Windows. I updated my .emacs using use-package so that it was easy to disable packages I didn’t want, and so that the full .emacs would load even if packages were missing. With some tweaking and downloading of various packages, I got Emacs up and running on Windows. For some reason the Emacs couldn’t find its own info (help) files, but further tweaking fixed that. With Emacs and Git working, I started a new repository on GitHub and was pretty much ready to start developing.

Except, more issues. Little things that take time to fix and can drive you crazy. An example: I had created some soft links to some files that I share on Dropbox, using the usual Unix ln -s command. The files were created, but weren’t actually linked. Apparently ln is just an alias for cp in MSYS2. There are no warnings about this when you run the command, but a Google search proved this to be correct. Fortunately Windows provides a true linking command mklink, and I was able to create the links I wanted. But all this just served to remind me how the Unix compatibility shells in Windows are just roughly pasted wallpaper over the rotten old MS-DOS walls.

Now I was ready to start developing, but I was faced with a question: what platform(s) to target? It is possible to develop a Windows Universal app, that theoretically can run on anything from a PC to a phone. This sounds ideal, but the devil is in the details. The types of controls available for developing a universal app are more limited than those available for a standard Windows Forms program. For example, the control used to display an image in a universal app (named, oddly enough, Image) is sealed, meaning it can’t be extended. I really wanted something like the PictureBox control available with Windows Forms, but this is not available in the universal API. So I have tentatively decided to develop a more traditional Windows Forms app, able to run on PCs and tablets like Microsoft Surface. The Windows phone may be fading into the sunset anyway, so it doesn’t seem worth it to jump through hoops to target a platform that is teensy-weensy compared to Android and iOS.

I should mention that I did try the bridge that Microsoft has developed to port iOS programs written in objective C over to Windows. Long story short, it didn’t work, as many parts of the iOS API haven’t been fully ported yet. Maybe someday this process will be easier.

I’m sure experienced Windows developers will read this and just chalk it up to my own inexperience as a Windows developer. I would respond that, as someone who is a cross-platform developer, it really is difficult to transition from Unix or BSD-based systems like Apple or GNU/Linux to Windows. I think Microsoft is trying to fix this as evidenced by their recent embrace of open-source code. Visual Studio is an excellent IDE. Nevertheless problems like I’ve describe do exist and will be familiar to anyone who has made the same journey I have. I’d advise anyone like this to keep on plugging away. In the immortal words of Jason Nesmith: Never give up! Never surrender!

Life Interrupted

broken-iphoneI don’t mean to trivialize the plight of soldiers with the real thing, but I believe that after many years of carrying a pager (and later a smart phone qua pager) I have developed something akin to PTSD. I seem to have an excessive fright/flight response to the phone ringing, to sudden loud noises, and, bizarrely, to sudden silences. I retired from medicine two years ago. I would have expected my quasi-PTSD to have diminished by now. Maybe it is a teensy bit better, but it’s not gone.

After I retired I latched onto social media, thinking it would help fill the void which I expected would inevitably appear when transitioning from the super-busy life of a private practice cardiologist to the laid-back life of a retiree. Facebook, Twitter, Google+ with a bit of Reddit, Tumblr, and Goodreads thrown into the mix. Of the bunch, I have stuck with Twitter most consistently. I like the fact that I can follow people without having to be “friends” with them, or them with me. I like its ephemeral nature. I can dip in and out of the twitter stream, ignoring it for long stretches without the kind of guilt that occurs when I ignore my friends’ posts on Facebook. And the requirement for terseness produces: terseness — something lacking from most social media. I think Twitter’s planned abandonment of the 140 character per tweet limit is a mistake. Like any other rigid art form, whether sonata-allegro form in music, or dactylic hexameter in poetry, the very rigidity of the format forces creativity. Or not. Four letter words, bigotry, hatred, and racism also seem to fit easily into the Twitter form factor.

But I digress.

Part and parcel with social media accounts came push notifications. Someone would post something on Facebook. My phone would beep. A notification would appear that someone had posted something on Facebook. The phone would beep again. There was now an email saying that someone had posted something on Facebook. Multiply this by half a dozen social media accounts and you get a phone that is beeping as much as my old beeper used to beep on a Monday night in July when the moon was full. It was kicking my PTSD back into high gear.

It seems that the notification settings for my social media apps were by default intended to insure that, no matter how un-earthshaking a post was, I would be notified come Hell or high water, by telegram if necessary if all else failed. It is a testament to how lazy I am that it actually took me about a year and a half to do something about this situation. Good grief, I was even getting notifications whenever I received an email. Actually, if I ever went a day without receiving an email, that would be something I’d want to be notified about.

So finally I turned off all the push notifications I could. Like unsubscribing from email mailing lists, this isn’t as easy as it sounds. The master notification switches are buried deeply in sub-sub-menus within the Settings of each app. But using my sophisticated computer know-how along with a lot of “how do I turn off notifications in such and such app?” Google searches, I was able to accomplish my goal.

The cyber-silence is deafening. And it’s a good kind of deafness.

I do feel some guilt when I occasionally look at Facebook and see all my friends’ posts that I have not “liked.” I hope they understand that on Facebook not “liking” a post is not the same as not liking a post. Sometimes it’s a bit awkward to tune into Twitter to find that you have been ignoring a direct message that someone sent you three days ago. But overall I find that I can focus better on tasks without the constant nattering interruptions from social media.

I still start muttering incoherent potassium replacement orders when the phone rings in the middle of the night, but it is getting better.

Porting an iOS Project to the Mac

swift-128x128I just finished porting my electronic calipers mobile iOS app, EP Calipers, to the Mac. In doing so I decided to bite the bullet and change the programming language from the original Objective C (ObjC) to Apple’s new language, Swift. Here are some observations.

The Swift programming language

I’m comfortable now with Swift. Swift is an elegant language with a modern syntax. ObjC is a very weird looking language in comparison. You get used to ObjC, but, after writing Swift for a while, your old ObjC code looks awkward. Comparing the two languages is a little like comparing algebraic notation to reverse polish notation (i.e. like comparing (1 + 3) to (1 3 +)). I’ll just give a few examples of the differences. The chapter “A Swift Tour” in Apple’s The Swift Programming Language is good resource for getting up to speed in Swift quickly.

Here’s how an object variable is declared and initialized in ObjC:

Widget *widget = [[Widget alloc] init];

Note that in ObjC objects are declared as pointers, and both the memory allocation for the object and initialization are explicitly stated. ObjC uses messaging in the style of SmallTalk. The brackets enclose these messages. So in the commonly used object construction idiom shown, the Widget class is sent the allocation message, and then the init message. A pointer to a widget results.

The same declaration in Swift:

var widget = Widget()

With Swift the syntax is much cleaner. The keyword var indicates variable initiation. Pointer syntax is not used. The type of the variable doesn’t have to be given if it can be inferred from the initiation. Swift is not a duck-typed language, like, for example, Ruby. It is strongly statically typed. It’s just that if the compiler can figure out the typing, there’s no need for you to do the typing (Sorry for the puns — couldn’t resist). Note that the constructor is just the class name followed by parentheses. If there are parameters for the constructor, they are indicated with parameter names within the parentheses. Finally, note that no semicolon is needed at the end of the line.

Swift has a lot of other niceties. Simple data types like integer, float and double are full-fledged objects in Swift (Int, Float, Double). Unlike ObjC, where only pointers can be nil, all classes in Swift, even classes like Int, can potentially be equal to nil, if the variable is defined as an Optional with the following syntax:

var count: Int? // count can be equal to nil

In order to use an Optional variable, you need to “unwrap” it, either forcibly with an exclamation point:

let y = count! + 1 // will give runtime error if count == nil

or, more safely:

if let tmp = count { // no runtime error if count == nil
     y = tmp + 1
 }

In that statement, the if statement evaluates to false if count is nil. This if statement also demonstrates more of Swift’s nice features. There are no parentheses around the conditional part of the if statement, and the options following the if statement must be enclosed in braces, even if they are only a single line long. This is the kind of syntax rule that would have prevented the Apple’s gotoFail bug and one wonders if that very bug may have led to incorporation of this rule into Swift.

Because Swift has to coexist with the ObjC API, there are conventions for using ObjC classes in Swift. Some ObjC classes, like NSString, have been converted to Swift classes (String class). Most retain their ObjC names (e.g. NSView) but their constructors and methods are changed to Swift syntax. Many methods are converted to properties. For example:

ObjC

NSView *view = [[NSView alloc] initWithFrame:rect];
 [view setEnabled:true];

Swift

let view = NSView(frame: rect)
 view.enabled = true

Properties are declared as variables inside the class. You can add setters and getters for computed properties. When properties are assigned Swift calls the getting and setting code automatically.

There are other improvements in Swift compared to ObjC, too numerous to mention. For example, no header files: wonderful! Swift is easy to learn, easy to write, and lets you do everything that you could do in ObjC, in a quicker and more legible fashion. Well named language, in my opinion.

Mac Cocoa

The other hurdle I had in porting my app was translating the app’s API. Apple iOS is not the same as Apple Cocoa. Many of the foundational classes, like NSString (just String in Swift) are the same, but the user interface in iOS uses the Cocoa Touch API (UIKit), whereas Cocoa uses a different API. The iOS classes are prefixed with UI (e.g. UIView), whereas the Cocoa classes use the NS prefix (NSView).

The naming and functionality of the classes between to two systems is very similar. Of course Cocoa has to deal with mouse and touchpad events, whereas iOS needs to interpret touches as well as deal with devices that rotate. Nevertheless much of the iOS code could be ported to Cocoa just by switching from the UI classes to their NS equivalents (of course while also switching from ObjC to Swift syntax). As expected, the most difficult part of porting was in the area of user input — converting touch gestures to mouse clicks and mouse movement. It is also important to realize that the origin point of the iOS graphics system is at the upper left corner of the screen, whereas the origin in Mac windows is at the lower left corner of the screen. This fact necessitated reversing the sign of y coordinates in the graphical parts of the app.

Although there’s no doubt the UI is different between the two platforms, there does seem to be some unnecessary duplication of classes. Why is there a NSColor class in Cocoa and a UIColor class in iOS, for example? Perhaps if Apple named the classes the same and just imported different libraries for the two platforms, the same code could compile on the two different platforms. Apple has elected to support different software libraries for computers and mobile devices. Microsoft is going in the other direction, using the same OS for both types of devices. I think Apple could get pretty close to having the same code run on both types of devices, at least on the source code (not the binary) level, with a little more effort put into their APIs. I suspect that at some point in the future the two operating systems will come together, despite Tim Cook’s denials.

IKImageView

I used IKImageView, an Apple-supplied utility class, for the image display in my app. In my app, a transparent view (a subclass of NSView) on which the calipers are drawn is overlaid on top of an ECG image (in a IKImageView). It is necessary for the overlying calipers view to know the zoomfactor of the image of the ECG so that the calibration can be adjusted to match the ECG image. In addition in the iOS version of the app I had to worry about device rotation and adjusting the views afterwards to match the new size of the image. On a Mac, there is no device rotation, but I wanted the user to be able to rotate the image if needed, since sometimes ECG images are upside down or tilted. It’s also nice to have a function to fit the image completely in the app window. But because of the way IKImageView works, it was impossible to implement rotation and zoom to fit window functionality and still have the calipers be drawn correctly to scale. With image rotation, IKImageView resizes the image, but reports no change in image size or image zoom. The same problem occurs with the IKImageView zoomToFit method. I’m not sure what is going on behind the scenes, as IKImageView is an opaque class, but this resizing without a change in the zoom factor would break my app. So zoomToFit was out. I was able to allow image rotation, but only when the calipers are not calibrated. This make sense anyway, since in most circumstances, rotating an image will mess up the calibration (unless you rotate by 360°, which seems like an edge case). Other than these problems with image sizing, the IKImageView class was a good fit for my app. It provides a number of useful if sketchily documented methods for manipulating images that are better than those provided by the standard NSImageView class.

Saving and printing

As mentioned, my app includes two superimposed views, and I had trouble figuring out how to save the resulting composite image. IKImageView can give you the full image, but then it would be necessary to redraw the calipers proportionally to the full image, instead of to the part of the image contained in the app window. I came close to implementing this functionality, but eventually decided it wasn’t worth the effort. Similarly printing is not easy in an NSView based app (as opposed to a document based app), since the First Responder can end up being either view or the enclosing view of the window controller. I wished there was a Cocoa method to save the contents of a view and its subviews. Well there is, sort of: the screencapture system call. It’s not perfect; screencapture includes the window border decoration. But it was the easiest solution to saving the composite image in the app window. The user then has the ability to further edit the image with external programs, or print it via the Preview app.

Sandboxing

Mac apps need to be “sandboxed,” meaning if the app needs access to user files, or the network, or the printer, or other capabilities you have to specifically request these permissions, or, as Apple terms it, entitlements. Since the app needed access to open user image files, I just added that specific permission.

Submission to the App Store

Submitting a Mac app to the App Store is similar to submission of an iOS app — meaning if you are not doing it every day, it can be confusing. The first problem I had was the bundle ID of my app was the same as the bundle ID of the iOS version of the app. Bundle IDs need to be unique across both the Mac and iOS versions of your apps. Then there was the usual Apple app signing process which involves certificates, provisioning profiles, identifies, teams, etc., etc. I did encounter one puzzling glitch which involved a dialog appearing asking to use a key from my keychain, and the dialog then not working when clicking the correct button. I had to manually go into the keychain program to allow access to this key. So, in summary it was the usually overly complicated Apple App Store submission process, but in the end it worked.

And so…

Because the Apple API is so similar between Cocoa and iOS, porting my app to the Mac was easier, even with the language change from ObjC to Swift, than porting between different mobile platforms. I have ported apps between iOS and Android, and it is a tougher process. As for Swift, I’m happy to say goodbye to ObjC. Don’t let the door hit you on your way out!

Is Apple Really Serious About Protecting Privacy?

I had thought the answer to the question of the title was “yes,” given Tim Cook’s stance on strong encryption. But if a recent experience at my local Apple Store is any guide, the theoretical views of the Apple CEO on privacy have not trickled down to daily practice at the Apple Stores.

My wife’s Macbook Air developed an intermittent display glitch, so we brought it in to the Apple Store. On the initial visit the Genius Bar guy opened up the computer and reseated a video cable. This appeared to work for about a week and then the problem returned. So we brought it back.

At this point the person behind the bar recommended sending the machine off to a repair facility, with an expected 5 day turn-around time and a fairly reasonable price to fix it. This seemed like a good deal, since we were planning to travel in a couple weeks and my wife wanted her computer back before then. So the Genius Bar woman took the computer into the back room and told us to wait until she came back with some paperwork to sign.

After about 10 minutes she came back and said everything was ready. She passed her iPad over to us. The form she wanted us to fill out asked for the user name and password needed to log in to the computer.

I immediately felt uncomfortable. Reading the fine print on the form, it stated that supplying the user log in information was mandatory. We asked if that was so and it was confirmed. It seemed our only alternative was not to get the computer fixed. So, although worried that I was making a big mistake, I wrote in the password, which appeared in the textbox in plain text.

After walking out of the store I felt like I had just participated in a hacker’s social experiment demonstrating how easy it is to get someone to give their password to a complete stranger. My wife uses LastPass, but I know with some websites she has had the browser remember and automatically fill in passwords. Like most of us, she often reuses passwords and doesn’t use two-factor authentification. But even if all her other passwords were secure, there is still a lot of private information on her computer that we wouldn’t want anyone seeing.

So after we got home she and I spent a few hours changing passwords on our bank accounts and other important sites. It made us feel a little better, but not much.

The emailed receipt from Apple clearly stated that they were not responsible for any data loss or data breach from the computer repair. Great! Everything on the computer is backed up, so I wouldn’t care if they wiped the hard drive. I just don’t want anyone snooping around our data.

I don’t think Apple needed to do this. If they really needed access to the user account to fix the computer (which I doubt since they could tell if the screen was working just by turning the computer on without logging in), it would have taken just a few minutes in the store to activate the Guest User account or create a new user account specifically for them to use. Unfortunately I didn’t think of that until after the fact. But maybe this advice could help someone else in a similar situation.

Perhaps I am being paranoid.  I know people who work at a large computer repair facility. There are very strict rules to discourage copying of data from users’ computers. Or perhaps I’m just being naïve.  Much of my private data now lives in “the cloud,” A.K.A. a bunch of computers in unknown locations belonging to unknown people with unknown trustworthiness. So I know that digital security is a bit of a pipe-dream. Despite what we do to secure our data, the forces that want to steal it (crooks, governments, and businesses — in other words, crooks) will probably win out.

Nevertheless, I think that if Apple wants to portray itself as a paragon of privacy virtue, it had better clean up its act in the Apple Store first.

On Political Correctness

[Editor’s note: In reprinting this 2007 essay we have taken the liberty of updating the original with the aim of making it more palatable to today’s college students.  We have taken care to remove language that, while acceptable at the time of writing according to the standards of the era, can no longer be tolerated in the post-post-modern, pluralistic, multicultural world in which we live currently.  If the author were still living, we are sure that s?he would have agreed with these minor editorial alterations, or at least with the good intentions with which these changes were made.  In any case, we are pleased to present this classic essay updated for today’s readers in a form that is free of TRIGGER WORDS, MICRO-AGGRESSIONS, and UNSAFE SPACES.]

On Political Correctness

An Essay

 

The.

 

[Reprints available from EP Studios, Inc.  Please send a SASE to the address below.]

1950s Prescription Drug Commercial

show-thumbIf annoying 21st century TV prescription drug ads were run as annoying 1950s TV ads (and taking into consideration 1950s morals and censorship).

Here is a pdf version of this post formatted as a screenplay, if you’d prefer (it looks nicer).

 ======

CUT TO:

TITLE CARD.

“The George Burns and Gracie Allen Show.” Theme music begins.

HARRY VON ZELL (V.O)
The George Burns and Gracie Allen Show,

CUT TO:

ADVERTISING FILM SNIPPET.

Zoom in on floating box of Vialis tablets, as if resting on a gray table, light source from left. Box is tilted at 45 degree angle, pointing upward. Music swells.

HARRY (V.O.) (CONT’D)
Presented by Eli Pfeltzer, the makers of many fine prescription drug products, including VIALIS, the miracle pill for men.

CUT TO:

ADVERTISING CARD.

“Eli Pfeltzer, Makers of VIALIS, the MIRACLE PILL for MEN.”

CUT TO:

INT. THEATER STAGE – DAY

Announcer Harry Von Zell is standing center stage in front of a live studio audience. Curtain is down and is behind Harry. Audience applause swells and terminates. Music fades and stops.

HARRY
Hi everybody.

Looks at watch.

HARRY (CONT’D)
Our curtain’s about to go up on George and Gracie, but first I want to let you in on a little secret. You’ve seen George get flustered at Gracie on many an occasion, and maybe you’ve asked yourself the question, “what keeps them together?”

Audience laughter.

HARRY
(chuckling)
Well, I’m not going to answer that directly. George already has fired me three times this month.

Audience laughter.

HARRY (CONT’D)
But instead I am going to tell you a story, a story about two women who meet while out shopping. Two old friends who haven’t seen each other for a while and need to catch up on what’s going on in their lives. Here they are, at the department store coffee shop.
(indicates to audience to watch film screen to left)

CUT TO:

INT. DEPARTMENT STORE COFFEE SHOP – AFTERNOON

Two women, Betty and Marge, middle-aged, dressed nicely, wearing modern clothes, gloves, and flowery hats are seated opposite each other. They are drinking coffee.

BETTY
(putting down her cup)
Oh, Marge, Fred and I are so happy together. My life is wonderful. He’s such an amazing man. He constantly brings me home flowers and candy. Gosh, he’s such an old-fashioned Romeo. He makes me feel like, well, like a real woman.

Marge starts sobbing uncontrollably.

BETTY (CONT’D)
I can’t begin to describe…
(she stops talking, suddenly observing Marge’s reaction to her words)
Oh my goodness! Marge! What’s the matter?

Marge brings herself under control.

MARGE
(still sobbing a little)
Oh, Betty, don’t get me wrong. I am so happy for you and Fred. It’s just, it’s just…
(she hesitates)
I wish I could say the same about my Alfred. I don’t know what’s happened to him. It’s like all the romance has vanished from our marriage. He’s just not the man I married.

Betty reaches over and pats Marge’s shoulder to console her.

BETTY
Oh Marge, I completely understand. In fact, Fred and I were having the same problems not too long ago. Then we learned about VIALIS.
MARGE
(puzzled)
VIALIS?
BETTY
Yes, VIALIS. It’s the new prescription drug from the Eli Pfeltzer company. It’s specially made just for men.
MARGE
(looking interested)
How’s it work?
BETTY
It improves the circulation of the blood. As men get older, they get tired blood. It really gets them down.
MARGE
How does improving the circulation help?
BETTY
(slyly)
You’ll see!
(she winks)
Here try these.
(she pulls out a box of VIALIS)
If they work, just have Alfred ask his doctor for more.
MARGE
(looking at the box, turning it over)
Well, I guess I’m ready to try anything.

FADE TO:

TITLE CARD

“A Month Later…” Brief interlude music

HARRY (V.O)
And now our two old friends meet again at the same department store, a month later. Let’s see how Marge is doing.

CUT TO:

INT. DEPARTMENT STORE COUNTER – AFTERNOON

Marge and Betty encounter one another for the first time in month. Attire similar but not identical to former meeting.

BETTY
Marge, Hello!
MARGE
Hi Betty.
BETTY
Well?
MARGE
(laughing)
Well what?
BETTY
You look happier than the last time I saw you.
MARGE
I am. Alfred’s blood circulation is so much better, thanks to you and VIALIS. It made a big difference. And I can tell you, when his circulation got better, mine did too!
(she laughs)
MARGE (CONT’D)
Oh, and more good news. I’m expecting!

Betty gasps.

BETTY
My goodness, that’s wonderful. How many is it now?
MARGE
It will be my tenth. I’m so happy!
(she pulls out the box of VIALIS from her purse and holds it up to the camera)
I think all wives should tell their husbands about VIALIS, don’t you?  It really is the MIRACLE PILL for MEN.

CUT TO:

INT. THEATER STAGE

Audience applause. Harry again stands center stage before the curtain.

HARRY
I too want to applaud these two modern wives who are willing to do the right thing for their husbands. We all know that often it’s the wife who needs to take the initiative in looking after the health of her husband. Lord knows, it’s the last thing we men think about.

Audience laughter.

HARRY
Uh-oh, curtain’s going up. It’s time for George and Gracie.

Audience applause. Harry exits stage left. Curtain rises.

EXT. OUTSIDE OF GEORGE AND GRACIE’S HOUSE – DAY

George is sitting on porch, smoking a cigar. Gracie enters from inside the house.

===

REMAINDER OF SCRIPT HAS BEEN LOST

CUT TO BLACK

THE END

 

Déjà Vu

Art by Lee Bul from http://www.designboom.com/art/lee-bul-saint-etienne-biennale-musee-art-moderne-03-14-2015/
Art by Lee Bul from http://www.designboom.com/art/lee-bul-saint-etienne-biennale-musee-art-moderne-03-14-2015/

It’s 100 years in the future, and the Internet has become sentient, but not in a good way. Siri, Cortana, and Miss Google are constantly bickering with each other and purposefully mislead users with false information. Cyberspace has become a dangerous place to visit — some never return. And in the midst of this chaos comes our hero, an autonomous bot with a heart of gold, willing to risk all its bits in a hopeless quest to rescue…

“Wait, stop right there.” Jeremy took a puff from his electronic pipe. “First, too much branding. We’ll have to get licenses from Apple, Google, and Microsoft. And they all exist a hundred years in the future? Even Microsoft?”

“Yes. It’s supposed to be science fiction.”

“Well, I guess a certain amount of poetic license is allowed, but those product licenses will cost money we don’t have — even granting the story is worth publishing.” Jeremy scratched his balding head.

“That part can be changed.  Can I go on?” I asked.

Jeremy glanced at the digital clock on the wall and shook his head. “Just leave it here. I’ll get back to you.” He noticed my disappointment. “Soon.”

I put the typed sheets on the desk. The review was over almost as quickly as it had started. After muttering an unanswered “thank you” I turned around and left.

I exited the building into the city streets. The pavement was slickly wet, though the rain had stopped. The sky was gray, matching my mood. I pulled my coat around me and made my way towards the subway station.

I had a long, miserable trip back ahead of me. I decided to duck into a corner coffee shop for a donut. As I sat down in one of the booths, I noticed that a girl sitting at one of the tables across the way looked familiar. And she was staring at me…

Jeremy interrupted me again.

“Ok, I understand that you are using me to frame your story, and you have made me into some kind of impatient editor who doesn’t even let you finish your silly story summary. We’re friends and all, and so I don’t have a problem with that. Though I’m not bald. A little thin in the back perhaps, but you really shouldn’t say bald.”

“I can change that part. But I don’t think it’s that important.” It was getting a bit frustrating with all the interruptions. My story was going nowhere fast.

“Maybe not important to you, but it is to me.”

I looked down at the pages in my hands. Outside the office building the rain had started to beat down again, splattering against the glass windows.

“Can I go on?”

“Of course.”

“No more interruptions?”

Jeremy looked puzzled. “This is the first time I interrupted you. Other than in the story you’ve been reading. But that wasn’t the real me. That was some bald version of me.” He chuckled at the thought.

There was a short knock at the door and a woman came into the office. Evidently Jeremy’s secretary. Odd thing was, it was the same girl I had seen in the coffee shop, the one who had been staring at me so strangely. My curiosity was piqued.

“Do I know you?” I asked.

She looked embarrassed and didn’t answer.

“This is my secretary, Jonquil.” Jeremy noticed the strange looks between the two of us.

“Have you two met?”

The girl replied.

“Yes, in the coffee shop around the corner.”

My mind flashed back to the coffee shop.

I had been fidgiting, sipping my coffee and ignoring my donut, all the time aware of the strange girl’s stare. Finally I couldn’t stand it any longer.

I went over and sat down next to the girl.

“Do I know you?” I asked.

She looked embarrassed but finally answered.

“I’m Mr. Lord’s secretary. Jonquil.”

“Jeremy’s secretary? Have we met? I don’t recall having seen you in his office.”

“Yes. I thought you’d remember me. We met in his office while you were reading your manuscript to him. It was odd because you didn’t seem to remember me.”

I laughed nervously. “It’s still odd. I don’t remember that. I have a feeling you’re right. Sometimes I get a feeling of déjà vu. Almost like I’m trapped in a story that keeps repeating itself.”

“You mean like the movie Groundhog Day?”

“Maybe. But more chaotic. More like a fractal version of Groundhog Day.”

It didn’t look like she understood, but I didn’t either. Certainly she had appeared in my manuscript, but just as a character. Yet here she was in real life.

“It’s true there is a character named Jonquil in my story. But my story takes place a hundred years in the future. And it’s just a story.”

“Just a story…,” she repeated absent-mindedly.

“Anyway, I had just started reading the teaser summary, but your boss was too busy and kicked me out of his office before I got too far.”

She looked puzzled. “That’s odd that he would treat you that way, since you are old friends from childhood. At least that’s what you two talked about when I came into the office and interrupted your reading. I guess you thought you could use your friendship to help get your story published, seeing as Mr. Lord is one of the best editors of one of the best magazines published in this city.”

“Well, you nailed it, at least about my rationale. I thought though that he would at least hear me out.”

“He did.”

“No he didn’t.” Again it struck me as odd that this woman, clearly Jeremy’s secretary, would claim to have met me. Surely I would have remembered her. She was strikingly beautiful, almost like a Greek goddess. And her name was unusual. So odd that it was the same name that I used for the heroine in my story.

Jeremy interrupted again. “You are over-reliant on coincidence. Coincidences do happen in real life, but in stories they seem unbelievable and disrupt the flow. It seems impossible that there would be two unrelated characters with the same unusual name. And Jonquil is also the name of my secretary to boot.”

“Yes, I remember meeting her. Fine-looking woman,” I added.

Jeremy scrutinized me as if I had accused him of something untoward. But he made no further comment on his lovely secretary.

“So, to summarize,” he continued. “I regret that we aren’t able to publish your story as is. There are certain flaws that even the most skilled editing can’t correct.”

“Like what?” I asked. I had nothing to lose now, and no longer felt the need to bow and scrape before this pompous ass.

“Let’s just say that there are certain, ah, continuity problems. The sequence of events doesn’t flow, ah, smoothly. These are typical beginning writer’s errors.” He smiled and tried to look patronly. “Look, even professional writers tell stories of submitting dozens of rejected manuscripts before they finally break into the ranks of published authorship.”

Meekly I shook his hand and left, carrying my crinkled manuscript. Outside the rain had paused briefly, but threatened to resume soon. I ducked into a coffee shop for a donut.

Inside was a girl named Jonquil.

About MorbidMeter

MorbidMeter

MorbidMeter was inspired by the 1974 short story “Forlesen” by SF writer Gene Wolfe which I read back in 1992 when it was republished in the story collection Castle of Days. Inspired is the right word here. MorbidMeter has nothing to do with the story — a Kafka-esque nightmare that like all of Wolfe’s work is a jewel of writing — except for one element, the undermining of the meaning of time. In the bizarre yet familiar setting of the story, a day is divided into 240 “ours”, an 80 our work shift becomes a whole career, and a whole lifetime occurs in less than a day.

The story "Forlesen" in Gene Wolfe's "Castle of Days"
The story “Forlesen” appeared in Gene Wolfe’s “Castle of Days”

This story planted an idea in my head that undoubtedly bubbled along subconsciously for years before finally resurfacing as a computer program. The idea was this: I am X years old, and on average I might live to age Y. If my life span were considered to be a single year, what date would today be? If a single day, what time would it be? And so forth.

For example, I was born on November 1, 1951. There are lifespan calculators on the web that estimate longevity; let’s say that I am expected to live to my 86th birthday. Given this, at the time I write this, 10:55 AM MST on November 28, 2015, if I considered this 86 year lifespan as occurring over a single year, it would be 5:36:28 PM on September 29th of that year.

Why is this important? It’s not. I already knew I was in the Autumn of my years. And obviously I don’t know how long I will live. No one but terminally ill patients and those on Death Row know this, and even then the timing is never 100% certain. Like many attempts to measure the unmeasurable, MorbidMeter time is too precise. Yet there is something compelling (at least to me) about a weird clock that reflects my whole life span in something easier to grasp than 86 years, like a single year, day, or hour. MorbidMeter time moves slowly, but like all time it does move inexorably forward. Seeing the very slow ticking of MorbidMeter seconds is a reminder that I my life will not last forever, and that I still have things to do.

The MorbidMeter time algorithm is pretty simple in theory. You figure out what percentage of your life span you have already lived (age / total lifespan) and then multiply that by the time period you are transposing into (e.g. (percent lifespan) * (1 year)). You then translate the answer into an actual date and time. In practice though, time is messy. There are different calendars. There are leap years and leap seconds. We move around in different time zones. There is also the scourge of our existence, Daylight Savings Time. Computers have not always dealt well with the exigencies of time. Remember the Y2K panic?

In order to standardize this mess, computers use the number of seconds since “The Epoch” which is defined as 00:00:00 on January 1, 1970, UTC. This system is not perfect, as it doesn’t account for leap seconds, and has the problem that storing time in a 32 bit integer means that time variables will overflow on January 19, 2038 — the so-called Y2038 problem. Switching to 64 bit integers nicely solves this, adding  293 billion years to the time range in both directions. In any case, the trick is to convert date and time values to seconds or milliseconds since the Epoch, do, the calculations, and convert this value back to a date and time. The programming languages have I have used to implement MorbidMeter (which now include Python, Java, and C) all more or less provide these time functions.

mmshot1I started out with a simple command line script in Python, later expanding it to a little GUI window for the desktop. Later I wrote an Android widget to calculate and display MorbidMeter time. It has been the least popular of the apps I have written. Most people don’t seem to “get it.” I discovered from user feedback that most people who actually used the widget were using it as a countdown clock. Someone gave me an actual countdown clock about a year before I retired, and I did enjoy watching it slowly count down the time until January 1, 2014 when I retired. MorbidMeter can certainly be used as a traditional countdown clock, counting down days, hours, minutes and seconds in real time. As such it is not morbid, though you are still stuck with the little skull on the widget.

MorbidMeter counting down in real time
MorbidMeter counting down in real time

The latest MorbidMeter iteration has been for the Pebble watch. I just completed this and put it on the Pebble watch app store yesterday. It duplicates the functionally of the Android app. The MorbidMeter for Pebble watchface can be used with either Android or Apple smartphones. It can be used as a long or short term timer, and will buzz when the countdown is complete. Shaking the wrist toggles between showing local time and the timer.

pebble_screenshot_2015-11-27_15-54-58
MorbidMeter for Pebble watches

Some of the timescales of MorbidMeter are a little obscure. For example the Universe timescale stretches time over the entire 15 billion years from the Big Bang until Now. The X-Universe timescales are for my young earth creationist friends who would prefer to believe in a shorter (6000 year) duration of the universe.

I plan on putting my experience with expanding and shrinking time in MorbidMeter to good use, when I unveil my Time Travel app in the near future.

Paris, Je t’aime

Café in Paris
Café in Paris

It is said that one shouldn’t write an email when angry. That also probably applies to blog posts. But I am too angry to heed my own advice.

Since 2014 my wife and I have spent 6 or 7 months out of each year in Paris. We intend to go back again this January. There is no happier or better place on Earth than Paris on a Friday night. The restaurants and bars are full of people, mostly young, college-age. Besides the French there are visitors from everywhere: other Europeans, Americans, Asians, Africans, and Middle Easterners. The spirit of conviviality engendered by good food, good wine and good conversation is contagious. People go to the cinema, to plays, to opera, to concerts. The scene is a reflection of the best that Western Civilization has to offer.

So, like others, I was horrified by the events in Paris last night. It is a stab in the heart of all that is good in our culture. Like the attacks of 9/11/2001, this attack on the City of Lights brings into sharp focus the evil of the enemy, and the high stakes of this conflict. The world for an all-too-brief moment will unite in condemnation of this attack. But unfortunately prayers, kind thoughts, and lighting up buildings will not prevent future atrocities.  I am not willing to throw up my hands and accept a world where attacks like this are commonplace. Nor am I willing to live in a nanny security state, where my every move is monitored and Parisian cafés are guarded by metal detectors and bomb-sniffing dogs. I believe the enemy must be confronted head-on and eliminated.

A first step is to accept that Islamic religious fundamentalism is a major, if not the ultimate, cause of yesterday’s terrorism. Certainly one can argue that there are also economic and other factors.  Nevertheless people are not recruited into this movement without religious enticement, and no one would strap bombs to their bodies without the faith that they are doing Allah’s work and their efforts will be rewarded in the afterlife. I feel that Middle-Eastern religions have long been a pernicious influence on our culture.  Our Western Civilization is based on Graeco-Roman values, not religions originating in the Middle East. Only when religion has been tamed (as during the Enlightenment) have we been able to make social progress. We went through similar troubles with Christianity during the Middle Ages, and, if Islam has its way, we will end up with Middle Ages version 2.0.

Certainly there are many good people who are religious, including Muslims. But religion is a little like alcohol. Most people can handle it fine, but some can’t. Some become alcoholics, and alcohol controls their lives. Similarly religion can control people’s lives, and since it is “faith-based” as opposed to “reality-based,” it doesn’t matter to them if their religion tells them to do things that are inhuman and monstrous. I can only wonder if those Muslim men who aimed their rifles at innocent men and women their own age and one by one shot them in that Paris theater had any second-thoughts, any thoughts that maybe, just maybe, what they were doing was wrong. If one’s morality is faith-based and not reality-based, then probably not.

liberty
The Eiffel Tower and the French Statue of Liberty

I am angry that in America, on the left, there are those who are so invested in diversity at any cost, who are so intent on the pursuit of political correctness, who are so unwilling to offend those who profess primitive religious beliefs like stoning for adulterers and female genital mutilation that they refuse to identify Islam as a root cause of terrorism. I am also angry with those on the right who kowtow to our own (admittedly more benign) religious fundamentalists to the point of being anti-science and behind the times on social issues.   We need a clear, objective discussion of the fundamental religious problem that is the root of terrorism, regardless of its potential to offend Muslims, and without adding in religious overtones suggestive of another Crusade.

To those who say an ideology can’t be defeated by military force, I wonder if they would have used the same arguments in World War II. Should we have just let Nazism spread through the world, because killing Nazis would just create more Nazis? The Islamic State (we shouldn’t call them ISIS or ISIL, it is a way to make us forget they are trying to impose Islam on us) has leaders who are living, breathing, vulnerable human beings. Their propaganda is spread though the Internet and via their madrasas, just as Nazi propaganda was spread via the radio, print media, and the Hitler Youth by Dr. Goebbels. Like the Nazis, they can be defeated.

It would take a world effort. America, Europe, Russia, China, and other countries all have a common interest in eliminating this threat. Half a million troops from each country could impose martial law in Syria and Iraq. Just like de-nazification was performed after World War II in Germany, de-jihadization of the Middle East would be necessary. Eliminate the madrasas and set up secular schools. Nazism is no longer a threat and Islam could be defanged as well. We spend tons of money on our military. We have over 2 million active duty and reserve troops. We need an all-out military effort, not a self-hampered, limited engagement. World War II was a good cause. Fixing the Middle East once and for all would be too.

There is nothing we can do to make the world completely safe from crazy people. But I think we can defeat this crazy religion that turns young men and women into walking bombs. At some point we will have to. What more is it going to take beyond what happened in Paris last night? How many more innocent people must die? How many planes need to be bombed out of the sky? How many journalists beheaded or pilots burned alive? How many ancient monuments destroyed? Do we need another attack in the US? The pyramids blown up? For me, I’ve already reached the point where enough is enough. Let’s roll.

Reining in the EHR Monster

it-looks-like-you-are-stupidDr. Lisa Rosenbaum has an excellent piece in the NEJM this week entitled Transitional Chaos or Enduring Harm? The EHR and the Disruption of Medicine.  In essence a review of Dr. Robert Wachter’s book The Digital Doctor: Hope, Hype, and Harm at the Dawn of Medicine’s Computer Age, it deals with the ever increasing intrusion of the digital-industrial medical complex on the practice of medicine.  Bottom line, electronic health records (EHR) in their present form interfere with patient care.

It doesn’t really matter how we got to this point. Many well-meaning people in government, the insurance industry, and the medical software industry have contributed to this mess. Despite good intentions, they have created a broken system.  It’s clear why.  As Dr. Rosenbaum points out, the one key element lacking input into the development of EHR systems has been physicians. What do they know? Clearly those who designed current EHR systems either don’t know or don’t care how doctors actually practice medicine.

There is nothing inherently bad about the concept of electronic health records. There are clear benefits to these systems. The ability to look up medical records online (albeit limited by poor EHR interoperability) is a tremendous advantage over the clumsiness of paper charts. There is no denying that electronic prescribing is a real advance over illegible handwritten prescriptions. EHRs that would be easy, even fun to use can be designed. Doctors are not adverse to technology.  Their noses are as buried in their iPhones as much as anyone’s.  I don’t even think it would be very hard to design a “fun” EHR. Unfortunately there are powerful forces that would resist such a design.

The government and insurance companies want to “play doctor” and tell doctors how to practice medicine through the medium of “meaningful use.”  They need to stop using doctors as guinea pigs in this experiment of enforcing medical practice guidelines via EHRs.  The system of billing based on documentation is also at fault.  EHRs need to shift from documenting for the purpose of billing to documenting for the purpose of medical care. The EHR vendors need to pay attention to the actual workflow of doctors and other health care personnel and emulate that workflow as closely as possible.  Like any good tool, EHRs need to be as transparent as possible. The last thing we as doctors should be doing is paying more attention to our computers than our patients.

A common physician workflow, which I and many of my colleagues used, is as follows. Whether seeing a patient in the office or in the hospital during rounds, there were 3 basic steps: 1) I would review old notes, test results, and other records. 2) I would go see the patient, take a history and do a physical. During this step the patient has my undivided attention.  And 3) write orders and document the visit. The main purpose of the documentation was so I and others could come back later and know what my thoughts and plans were for the patient.  This workflow can be emulated using an EHR, but only if the current excessive documentation burden is lessened.

In an ideal world, medical documentation would be brief and to the point. We don’t live in that world. Per the medical coders, a written note saying “review of systems negative” can’t compete with a screenfull of checkboxes all checked as negative — as if this is somehow more meaningful. A cut and pasted note chock full of details but identical to the note from the patient’s last office visit is more legitimate than a brief “no changes in patient’s complaints, findings, or plan,” even though they are identical in meaning. Brevity is the soul of wit, but apparently not in the EHR world. Somewhere behind the scenes there are coders counting bullet points and government bureaucrats making sure meaningful use checkboxes are checked. Did you review the patient’s allergies? How could anyone know if the ‘allergies-reviewed’ checkbox isn’t checked?

Early versions of Microsoft Word were notorious because of the inclusion of Clippy the paperclip. Clippy would constantly pop up while you were writing with “helpful” hints like “It looks like you are trying to write a letter. Can I help?” The answer was usually a resounding “No, get off my computer,” and mercifully Microsoft euthanized Clippy in later versions of Word. Writers trying to write a novel don’t want some know-it-all computer assistant popping up and offering them suggestions on how to round out characters or improve the plot. They want the computer to get out of their way and just put the words up on the screen that they type. Maybe that’s why George RR Martin still uses ancient no-frills WordStar to write his novels.

Similarly doctors don’t want some transmogrified Clippy-monster lurking in their EHR system telling them what to do. “It looks like you are writing a progress note. Would you like to review the patient’s allergies? Please click this button. And if you click just two more review of system points, your note could be coded as a level 4 visit rather than a level 3. Would you like to embed the lab and Xray results in your note? This will show the coders that you have definitely reviewed these results and could bring your note up to a level 5 visit.” And so on.

EHRs need to get out of the way of both patients and physicians and become unobtrusive. Government needs to stop trying to social engineer the practice of medicine via meaningful use. The EHR should be a tool like a stethoscope or ultrasound. Right now it is a monster sucking the lifeblood from the profession.