Confidentiality of the right thing

If we use “issues” as the top level item in the EHR, instead of the “encounter”, it comes naturally to attach confidentiality attributes to the issue instead of the department, doctor, or encounter. That’s a huge improvement. Let’s take an example to show why.

As things are in current systems, confidentiality walls or borders are located around certain services. The reasoning goes that if a patient doesn’t want his psychiatric problems to be known, then any records entered by the psychiatrist should be confidential and not accessible by other specialities. This is so screwed up. The psychiatrist is usually the one that handles embarrassing psychiatric problems, but this is not necessarily so. The psychiatrist may actually treat the patient for something entirely un-embarrassing like a headache or irregular menstruation or hives, and does that mean that the patient’s hives now are confidential? Of course not, but that’s not how the systems we have reason.

Let’s take another example. If I, as a GP, treat a patient for syphilis, there’s no confidentiality attached to it. If the same patient was treated for the same disease by a venereologist, then there is confidentiality. This is bloody nonsense, but this is how things generally work. In the system I’m working mostly, that is not a problem, since no confidentiality is implemented at all. (Don’t ask…)

It must be obvious to most that it is the “issue” that should have confidentiality attributes attached. If the patient doesn’t want the news about his syphilis to spread, the issue “syphilis” should be confidential, irrespective of which doctor or speciality that treats the patient. It’s up to the patient to decide if he wants any other particular specialist or department to know about this diagnosis.

The danger with all these confidentiality limits is that a disease that normally isn’t important to the treatment of another disease, may occasionally be extremely important, but remains hidden. If confidentiality is attached to issues, and issues to the patient, then there is the possibility of the system warning the user of hidden pathologies that are important, simply since this system actually knows what an issue is, and that other issues may include warnings about the simultaneous presence of these issues, including pharmacological interactions.

For instance, our syphilitic patient has a problem with suspected neuropathy, but the syphilis is hidden from the neurologist examining the patient. If the clinical guideline for “peripheral neuropathies” includes the differential diagnosis “syphilis”, the system is able to warn the physician that there are hidden issues that are related to the workup he is currently performing and that he should take steps to be allowed to unlock this information.

Having issues

In my last post I described the positioning of the SRR record and I also painted it as a form that can either be predetermined in the form of a clinical guideline record or a free form record to which the doctor can add steps, or a mixture of both. Since we don’t want to keep calling this thing an “SRR”, and we can’t call it a “symptom” or a “pathology” or a “disease” for reasons I’ll soon get to, I think we need to call it an “issue”.

It would have been natural to call it a “problem”, but there’s a problem with calling it a “problem”, namely that 50 years ago or so, Wade described the Problem Oriented Medical Record (POMR) which has a lot of the characteristics of what we here describe, but still differs on some crucial points. And since I don’t want to run in to prejudices connected with POMR and get remarks like “it’s old hat”, “we know about that”, “it never worked”, and more, I prefer to call it something else. And “issue” it is for now. Especially since I can’t think of anyone calling this an “issue” up to now.

Recapping, we have a list of “issues” under the entity “patient”. Each “issue” can be a symptom, a disease, a hypothesis, a plan, or even in some cases a therapeutic regimen. Let’s run through a couple of examples just to illustrate what it is, and what it is not.

“Diabetes type 2” is an issue. It has diagnostic criteria, recommended follow-up lab tests, regular checkups and referrals, recommended therapies, diagnostic codes, and contra-indications such as “careful with some diuretics”.

“Migraine” is an issue, and so is “tension headaches”. Interestingly, “headache” is also an issue with its own recommended diagnostic steps, but it also has a list of differential diagnoses, including both “migraine” and “tension headaches”. A “headache” is not a diagnosis but a symptom, but it needs to be a first class “issue” anyway, since that is the “issue” we’re working with until we can replace it with a more definite diagnosis.

So now we encountered the “replacing” of issues. This can happen in the “headache” case, among many others. The patient presents with headaches, and immediatly gets a “headache” issue assigned, which is prefilled with a differential diagnosis including among other things “migraine” and “tension headaches”. As the physician needs to exclude “migraine” first, the issue “migraine” is attached to the main issue “headaches” and you can work through the recommendations in “migraine”. If “migraine” is confirmed, it actually is lifted a level and replaces the main issue “headache” which is then removed from the list. If, on the other hand, “migraine” is excluded after some examination, the “migraine” subissue is removed and it is marked as “excluded” in the list of differential diagnoses in the “headache” issue. And so forth.

Don’t become nervous when you see all this insertion, moving, and deletion. That is how it looks to the user, but behind the scenes, everything is saved, version controlled, listed, and is being audited like there’s no tomorrow. Except we don’t want to actually see any of that unless we ask for it.

What’s this SRR thing, then?

In my last post, I arrived at the conclusion that the main element in the electronic healthcare record should be a list of problems and each of those problems should be an SRR, that is a document that is updated with  the most recent data pertaining to this problem, not a document that gets replaced and shoved out in a queue as in a TAS. (Back up a few posts to find the definition of these terms.)

Ok, fine, if you accept that, we now have a problem of defining the contents of this SRR, this problem document. It could very well start out as an empty document or a document with a few predefined sections such as “Tests”, “Clinical signs”, “Medications”. Under each of those sections, the doctor could then add in the tests and signs he plans on doing or checking and then later check them off or fill in results. That’s certainly one viable method.

But we’ll soon notice that most problems people show up with are pretty common and have established guidelines we can reuse. For diabetes, for instance, we very well know which tests we want to perform, which values constitute diagnostic values for the disease and which follow-up referrals and exams that need to be done. Even criteria for reporting the problem to different tracking databases are pretty clearcut. So it would only be natural to keep these guidelines in a common database so all doctors using the same system will follow up the same disease the same way. Additionally, if the guideline changes at some point in time, the diagnostic and treatment plans of patients already in the system will signal the change to the physician the next time the patient is seen.

But won’t it be prohibitively expensive to set up all these guidelines? Um, no, it’s already been done. All these guidelines exist at least on paper and in most places in the world as PDF documents. But in some places, such as Sweden, we even have them in an almost immediately useful form. Just check out the site viss.nu and there you have them. These guidelines can be used almost without change in an electronic healthcare record system, if checkboxes and input fields are added and a copy of the guideline is linked to the individual EHR patient file.

In conclusion, we actually do have the SRR we need for the medical records. It’s either an empty document the physician can add his planning to, or it is a predetermined guideline adapted for this system, but taken from one of the many excellent repositories of clinical guidelines that already exist. Which then also finally get to be used in real practice.

Data kinds and the medical record

In my previous post, I described the two kinds of data that I think I see in most, if not all, applications. The two kinds are the “state reflecting record” (SRR) and the “transformation additive series” (TAS). Cumbersome names, I admit, but if you have a better idea, let’s hear it.

A medical record, be it on paper or in a computer, is built up of only a TAS, with no SRR in sight. That is, it consists of notes, each by a certain person and on a certain date and time, and added in chronological order. Each note consists of the patient’s complaints, results of examinations, answers from referrals, medication changes, conclusions, plans, or any combination of these. Even if the note contains a summary of earlier notes or a summary of the patient’s current state or history, this summary is still part of the note and thus embedded in a record that is just one element in a TAS.

In some systems you’ll find a summary document about the patient as a whole, and this document is updated with the most important new findings or treatments as you go along, but it has no direct connection to the chronological notes and is usually of such poor quality that it really can’t be considered an SRR.

The list of current medications, however, does qualify as an SRR, but its scope is limited to just medications. Interestingly, there is usually no TAS connected to this medication list, so the chronological information that is very important especially for medications, is missing or very hard to recover.

The most important information for the physician when seeing the patient is not when things happened or who made it happen or recorded whatever happened, but what the current state of the patient and his pathologies is. It used to be, back when patients had the same doctor for many years, that this information was stored inside the doctor’s head. The information he had trouble remembering, such as exactly when he did exactly what, was the only information that was recorded in the medical record.

But today, there generally isn’t any doctor around that knows the patient and the lack of a document describing the patient’s current state is a real problem. Doctors have developed a habit to reconstruct the current state of the patient from the historical records, but this is a very laborious and error prone process. What makes it worse is that it has to be reconstructed at every new encounter, since there is no way to store that current state so it can be reused and expanded upon at the next encounter. There simply is no such mechanism available in the medical records systems.

As a concrete example, let’s assume I see a patient for a general checkup. First, I have to scan through the notes to make a mental list of all the ailments he has or has had, while at the same time figuring out how each of those ailments have evolved and are currently treated. For instance, I may find a mention of a high blood glucose level three years ago, another high level a couple of months later, together with a conclusion that the patient has type 2 diabetes and that medication is started. Half a year later I find a note that the medication was insufficient and that a second product was added. The next three notes are about a stomachache the patient developed, and then I find another note telling me his diabetes is now under control. I haven’t seen any mention of an ophthalmology referral to check the state of the patient’s retinas, so I have to run through the notes one more time looking for that. If I don’t find any, I’ll have to write a referral note for that.

If I had had a form for diabetes type 2 with the medication field containing the current medications and the ophthalmology referral field still empty, I’d known all this in a flash and with a much greater confidence, but there is no such thing, so I’m forced to go through this frankly ridiculous process of reconstructing that form in my mind every time I see a patient.

Oh, and don’t forget, the patient may have several problems, each of which has to be evaluated like this. Some of these problems I don’t even know about until I run across them in some old note. Finally, once I’ve worked myself through this process, only then can I actually start working with the patient.

If we go back to the SRR vs TAS view of data, it’s clear that the SRR is simply missing and I have to reconstruct the SRR every time I see a new patient. This worked back in the time when I still remembered the state of the patient (the SRR) from the last time I saw the patient, but nowadays most patients I see I’ve never seen before, so this system fails abysmally.

A tale of two data kinds

In my neverending quest to straighten out the electronic healthcare record, I have to introduce a view on data that is essential if I’ll be able to explain what’s wrong with the current model and how it should be fixed. As always when we’re in a mess with the design of systems, we climb the abstraction ladder a level of two to find the underlying (“above lying?”) abstractions, just like particle physicists try to find ever smaller components of components.

I’m seeing all applications using two kinds of data, one that is continuously updated to reflect the current state and the other where one adds records to reflect changes to data. I’ll call these, with very unsatisfactory names, the “state reflecting record” (SRR) and the “transformation additive series” (TAS). I’ve intentionally used really unusual terms to make it easier to search for these terms later. By the way, I’m absolutely positive I can’t have invented this view of data, but so far I’ve not come up with any references to literature describing it this way. I’d be really grateful for any pointers to preexisting descriptions. So, lacking any references, I’ll have to describe it here as well as I can.

If we start with the state reflecting records (SRR), this can be exemplified by an image in an imageeditor. Whatever the editor does to the image changes that one image data blob from one state to the next. Whatever you do, it’s just that one blob. A text document, or a blog post like this one, are other examples of SRR. As long as we don’t add any other kind of data structures linking to the SRR, there is no way of telling what the SRR looked like before the most recent change, or even what that change was. The SRR only reflects current state of some object or collection of objects. A relational database is another example of an SRR, by the way (if we leave the transaction log out of consideration).

Transformation additive series (TAS) are quite another animal. A keystroke logger is TAS based, for instance. Every keystroke creates a new record. Even a backspace doesn’t remove a previous record but adds a new record containing the backstroke. A network communication session is a TAS. More and more packets are piled on. The change records in a source control system forms a TAS. In principle, a TAS consists of a growing number of records, each immutable, added in a series, where any subset of the series corresponds to a transformation of some other object. A TAS must in principle always refer to something else, and that “something else” has to be in essence an SRR.

Having these two cleancut types of data, we can now form a number of data design patterns from them. “Patterns” is taken to mean “desirable patterns”, while “antipatterns” is taken to mean “undesirable patterns” that, by implication, are seen in the wild to a disturbing degree and should be avoided if possible.

Patterns

If we start with desirable patterns, or just “patterns”, we can describe a few typical ones easily. Most, but not all, patterns employ an interacting set of SRR and TAS elements. Employing the principle of not duplicating data or relationships, we first find that we have to select either the SRR or the TAS as the primary data and the other as the secondary data. In a functioning pattern, we should require that the secondary data kind should be fully derivable from the primary.

Pattern 1 – SRR only

Typical application: a simple paint program. The image itself is the SRR. The paint program may have a single level undo function, which in a practical sense doesn’t qualify as a TAS, but if it has an unlimited level undo function, it is not any longer a simple SRR pattern. This pattern is clean, there is no possibility of conflict of data since there is just the one instance, the SRR itself.

Pattern 2 – TAS only

A sniffer log of network traffic is a typical TAS only. There is no conflict possible here either, not as long as you don’t try to make sense out of the captured packets, and if you do, it’s not a “TAS only” pattern anymore.

Pattern 3 – TAS primary

Any system that contains both an SRR and a TAS, but where the SRR can be fully reconstructed from the TAS belongs in this pattern. A typical example is version control systems. If you lose your original document, you can still recreate it from just the TAS, the series of change records. An accounting system can also be built this way, but rarely is. If each invoice, payment and other entry is kept in a TAS, you can always reconstruct any general ledger, sum, report, or tax form at any time simply from the TAS. Sadly, most real world accounting systems don’t exploit this idea, leading to the sad apps we see today.

In this pattern, you will often find a single immutable SRR, the start state. I still regard it as a “TAS primary” pattern.

Pattern 4 – TAS primary, SRR cache

A minor, but in practice very important, variation on the previous pattern is when the SRR is fully reconstructable from the TAS and an optional SRR start state, and is kept for performance reasons. Micrografx Paint, may it rest in peace, worked like this if I remember right. Or maybe it was Micrografx Designer. Or both. In this app you modified the image any way you liked, but each modification resulted in a change record in the “history” panel. From this “history” panel you could delete any step and rebuild the image from the beginning with that step omitted. So the current image could be reconstructed from the starting image plus the history. The final image is kept in Micrografx Paint as a cache so the program doesn’t have to rebuild the image constantly. That would have been much too slow. But losing the current image wasn’t a problem. Consistency was guaranteed, only the history record, the TAS, actually had authority over how the image would look. If the TAS and SRR gave different results, the SRR was corrupt. By definition.

This pattern also contains an inherent consistency verification on the TAS, namely that the SRR that is built from a complete TAS must make sense. If the SRR is an image, this is difficult to ascertain, since any image is valid, even if you can’t make sense out of it if you’re a human. Just look at some modern art and you’ll get my drift. But in many other cases, such as accounting or medicine, a TAS can contain records that result in an invalid SRR. Another example is source code control. If the source code change records are invalid, the source code you build up from the change records may not be compilable. This test is only valid if you require all source code to compile before you log it into the source code control system, of course.

Adobe Photoshop also has some of this functionality, but the history record seems not to be sufficient to rebuild the image, so this would form an antipattern.

Antipatterns

Now for the antipatterns. When reading any of these antipatterns, think of real examples in your own environment, and you’ll soon discover that these systems you know and hate are bottomless sources of irritating inconsistencies and bugs. That’s no coincidence. Most of that has as a root cause the unresolved ambiguity between what’s primary and what’s secondary in the data kinds.

Antipattern 1 – SRR primary, derived TAS

A text document in a word processor with the “track changes” function switched on. You still modify a single SRR, the document itself, but every change is causing the creation of a record in a TAS in the background. Since the TAS will never be complete enough in practice to reconstruct the document itself if it’s lost, the TAS can’t be primary. But the SRR can never reconstruct the TAS either, so the TAS isn’t fully secondary.

Audit logging in most applications fit this pattern as well. The secondary TAS is a rather improvised collection of data pointing to datetime, user, kind of records or whatever else popped into the developer’s mind when writing it, usually missing the pieces of data you turn out to really need later. Since the TAS is derived and doesn’t have any function to fill at all during normal system usage, it’s functionality is never put to the test until it is too late.

Antipattern 2 – Undecided primary

Most accounting systems can’t make up their mind what’s primary and what’s secondary. When you input an invoice into the system, it’s not reflected in the general ledger until you “post” it and once you do you can’t change it anymore. There’s no way to “unpost” or to rebuild the general ledger from recorded invoices. It’s as if the invoice series (TAS) rules until you “post” them, and then the SRR rules even though the TAS is still there. There’s no end to the confusion and assbackwardness that results from all this. (Don’t tell me the law requires this, in most countries it doesn’t. The law generally requires that you should not be able to do undetectable changes to your accounting, which is something else entirely. Don’t get me started.)

Conclusion

The only patterns that seem to work consistently are thus either SRR or TAS only, or combinations where the TAS is primary. There seems to be no instances where the SRR is primary and a connected TAS is still useful and reliable. Surprisingly, most real world systems seem to be build in exactly this way, that is with a primary SRR and a tacked on TAS with a confused division of responsibilities. Not so surprisingly, most of these systems have a lot of problems, many of which can be directly tracked to this confused design.

What’s next?

In the next post, I’ll get into how this relates to medical records. I can already divulge that medical records as they are today, are pure TAS based. Think about that in the meanwhile.

Subversion server on Snow Leopard server

As I already bragged about, I got me one of those delicious little OSX Mini Snow Leopard Server boxes. So sweet you could kiss it. I just got everything together to make it run a subversion server through Apache, too, and as a way to document that process, I could just as well make a post out of it. Then I can find it again later for my own needs.

First of all, subversion server is already a part of the OSX Snow Leopard distribution, so there is no need to go get it anywhere. Mine seems to be version 1.6.5, according to svnadmin. Out of the box, however, apache is not enabled to connect to subversion, so that needs to be fixed.

We’ll start by editing the httpd.conf for apache to load the SVN module. You’ll find the file at:

/etc/apache2/httpd.conf

Uncomment the line:

#LoadModule dav_svn_module libexec/apache2/mod_dav_svn.so

Somewhere close to the end of the file, add the following line:

Include "/private/etc/apache2/extra/httpd-svn.conf"

Now we need to create that httpd-svn.conf file. If you don’t have the “extra” dir, make it, then open the empty file and add in:

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn
  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile /private/etc/apache2/extra/svn-auth-file
  Require valid-user
</Location>

Save and exit. Then create the password file and add the first password by:

sudo htpasswd -c svn-auth-file username

…where “username” is your username, of course. You’ll be prompted for the desired password. You can add more passwords with the same command, while dropping the -c switch.

Time to create svn folders and repository. Create /usr/local/svn. Then create your first repository by:

svnadmin create firstrep

Since apache is going to access this, the owner should be apache. Do that:

sudo chown -R www firstrep

Through Server Admin, stop and restart Web service. Check if no errors appear. Then use your fav SVN client to check if things work. Normally, you’d be able to adress your subversion repository using:

http://yourserver/svn/firstrep

Finally, don’t forget to use your SVN client to create two folders in the repository, namely “trunk” and “tags”. Your project should end up under “trunk”.

Once up and running, this repository works perfectly with Panic’s Coda, which is totally able to completely source code control an entire website. If you don’t know Coda, it’s a website editor of the text editor kind, not much fancy graphic tools, but it does help with stylesheets and stuff. It’s for the hands-on developer, you could say.

The way you manage a site in Coda is that you have a local copy of your site, typically a load of PHP files, which are version controlled against the subversion repository, then you upload the files to the production server. Coda keeps track of both the repository server and the production server for each site. The one feature that is missing is a simple way of having staged servers, that is uploading to a test server, and only once in a while copy it all up to the production server. But that can be considered a bit outside of the primary task of the Coda editor, of course.

You could say that if your site isn’t mission critical, but more of the 200 visitors a month kind, you can work directly against the production server, especially since rolling back and undoing changes is pretty slick using the Coda/subversion combo. But it does require good discipline, good nerves, and a site you don’t really, truly need for your livelihood. You can break it pretty bad and jumble up your versions, I expect. Plus, don’t forget, the database structure and contents aren’t any part of your version control if you don’t take special steps to accomplish that.

Coda doesn’t let you access all the functionality of subversion. As far as I can determine, it doesn’t have provisions for tag and branch, for instance. But it does have comparisons, rollbacks and most of the rest. The easiest way to do tagging would be through the command line. Or possibly by using a GUI SVN client, there are several for OSX. I’m just in the process of testing the SynchroSVN client. Looks pretty capable, but not all that cheap.

.NET considered harmful

A friend of mine just told me about what an MS evangelist said at a symposium on multicore (paraphrased), after getting the question:

“Did MS consider that cache awareness for programmers in multicore development?”

…and he answered:

“The average developer is not capable of handling that kind of level of detail. … Most developers are that ignorant. Welcome to the real world.”

To me, this explains a lot. It explains why .NET looks like it does, and to clarify what I mean by that, let me simply copy in extracts from what I had to say about it in a private forum just weeks ago. In what follows, the italics are brief extracts of comments from others. The rest is my own text. It’s not always in a totally logical order and it starts out in midflight, but it’s a synthesis of a longish thread on a security related forum.

Continue reading “.NET considered harmful”

App store or Dashcode?

Over the last week or so, I’ve spent a lot of time with the WDC 2009 sessions, and Dashcode, at least in its upcoming 3.0 version, seems to be amazingly capable. The results are almost indistinguishable from SDK apps (for want of a better label). And, they don’t go through the app store. And, they download to the phone and can run offline as well, including a local database.

This is probably what Apple hinted at when the iPhone 1.0 was introduced, except nobody would believe it was a useful way of creating apps. Neither did I back then, but now I do. Interestingly, the hassles with the iTunes policy (see previous blog entry) also pushes me in that direction. Maybe they did it on purpose? Read a much sharper and more enjoyable version of the same idea at Factory Joe.

Damn, I’m so proud of myself

This morning I started developing for the iPhone (it arrived two days ago, what took me so long?). After watching a load of presentations from WWDC 2009 (you have to pay for that, but boy is it worth it), I got really curious about Dashcode. This environment lets you develop web applications and it looked really impressive. So I took half an hour to implement a webapp based RSS reader. Then I spent a couple of hours trying to find out why it didn’t work. I still don’t know, but I think it’s due to crappy 3G performance in my living room. Works fine outside.

If you’ve got an iPhone, try it out for yourself. Once you’ve got it loaded in Safari, tap the plus sign down below and save it to the home screen. Next time you start it from the home screen as if it was a real app, it will look like a real app, without any Safari chrome to give it away. You’ll also notice that the icon is totally crap, just a grey rectangle. But what do you expect from a developer that only this morning started up the IDE for the first time?

If you open up this app in Safari on the desktop, that works as well, but looks like just any old web page, but grayer. In Firefox it fails. In Explorer… who cares?

The link is:

http://ursecta.com/UrsectaReader/