<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ursecta.com &#187; Development</title>
	<atom:link href="http://ursecta.com/wp/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://ursecta.com/wp</link>
	<description>J. Martin Wehlou on Security, Software Development, and Medicine</description>
	<lastBuildDate>Tue, 08 May 2012 10:19:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Another creator pattern for clusters</title>
		<link>http://ursecta.com/wp/2011/09/another-creator-pattern-for-clusters/</link>
		<comments>http://ursecta.com/wp/2011/09/another-creator-pattern-for-clusters/#comments</comments>
		<pubDate>Thu, 15 Sep 2011 11:47:42 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[class cluster]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[creator pattern]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=1239</guid>
		<description><![CDATA[This is about Cocoa, and in particular about class clusters. The problem I wanted to solve was having a class cluster with easily extendable hierarchy without too much interdependency. In my case, I want to create a number of different UITableViewCell descendants, depending on the particular data element the cell should handle. If the data [...]]]></description>
			<content:encoded><![CDATA[<p>This is about Cocoa, and in particular about class clusters. The problem I wanted to solve was having a class cluster with easily extendable hierarchy without too much interdependency. In my case, I want to create a number of different UITableViewCell descendants, depending on the particular data element the cell should handle. If the data element has a field &#8220;string value&#8221;, then a UITableViewCell with a text field for such a string value should be created. If the data element has a field &#8220;check&#8221; representing a yes/no answer, then a UITableViewCell with a yes/no functionality widget should be created instead, and so on. In total, I have less than ten different kinds of UITableViewCell derived classes, but they could become more at any time.</p>
<p><span id="more-1239"></span>I prefer building stuff like this with an object factory in the base class. In this case, my base class is called ItemTableCell and has a factory method with a prototype like this:</p>
<pre>+ (ItemTableCell *)cellForItem:(IDRItem *)item;</pre>
<p>This function needs to determine exactly which ItemTableCell child class can hande the item passed as parameter, and then create an instance of that class. It&#8217;s easy to solve in a naive way, like this:</p>
<pre>#import "ItemTableCellStringInput.h"
#import "ItemTableCellCheckInput.h"
... another ten or so imports

+ (ItemTableCell *)cellForItem:(IDRItem *)item {

  if ([item hasStringInput])
    return [[[ItemTableCellStringInput alloc] initWithItem:item] autorelease];
  else if ([item hasCheckInput])
    return [[[ItemTableCellCheckInput alloc] initWithItem:item] autorelease];
  else if .... (another ten or so if statements)
}</pre>
<p>There are several things I don&#8217;t like about this solution. The first one is the imports, namely that the base class needs to import and know about every child class, while the child classes need to import the base class. This kind of mutual dependency works (at least it does in Objective C), but offends my sense of esthetics. What also disturbs me greatly is that stupid if-statement that is necessary to decide which class gets to create an object. That statement contains knowledge about the capability of handling data objects that properly belongs only in the particular child class that can handle the data object. The way I wrote it here, the knowledge about the data is kept in two places: the base class <em>and</em> the derived class. Not good.</p>
<p>To get to grips with this, I came up with the following freakishly simple solution which I think only works in Objective C, and not in C++, C# or similar. (It may very well work in any number of other languages I don&#8217;t know that much about, though.)</p>
<p>In this pattern, the child class knows about the base class (duh), but the base class does <em>not</em> import the child class. Instead, the base class learns about the existence of the child class at runtime, just as the app starts up. It also delegates to the child classes the decision of which class can handle a particular data item. The result is that if you add a new kind of data item and a matching kind of ItemTableCell child class, you don&#8217;t need to touch the ItemTableCell base class code at all. It still works.</p>
<p>The key to this little miracle is the NSObject class function +load. This function gets called on every class in the system at startup. In case of derived classes, it gets called on the base class first, then on child classes. In my solution, I use this function to register derived classes with the base class. The base class then keeps these child classes in an array, so it can call them one by one to ask them if they can handle a particular data item, and if so it creates an instance and hands that instance the data item. It actually turns out to be pretty simple to do. Minimalistic example code follows:</p>
<pre>@implementation ItemTableCell
static NSMutableArray *subclasses;

+ (void)load {
  [super load];
  subclasses = [[NSMutableArray alloc] initWithCapacity:5];
}

+ (void)addSubclass:(Class)cls {
  [subclasses addObject:cls];
}

+ (ItemTableCell *)cellForItem:(IDRItem *)item {
  ItemTableCell *cell = nil;
  for (Class cls in subclasses) {
    if ([cls canHandle:item]) {
      if (cell != nil)
        [NSException raise:@"Ambiguous canHandle" format:@""];
      cell = [cls subCellForItem:item];
    }
  }
  if (cell == nil)
    [NSException raise:@"No cell could handle item" format:@""];
  return cell;
}</pre>
<p>You will note that the cellForItem function does not return the first child it finds can handle an item, but runs through them all to make sure there isn&#8217;t a second child class that claims it can handle the same item. Also, it throws an exception if no subclass at all finds itself able to handle an item. Believe me, this little extra runtime effort is well worth finding obscure bugs.</p>
<p>A derived class looks like in the following (I&#8217;m just showing one, you can imagine the others):</p>
<pre>#import "ItemTableCellString.h"
@implementation ItemTableCellString

+ (void)load {
  [super addSubclass:self];
}

+ (BOOL)canHandle:(IDRItem *)item {
  return [item hasStringInput] &amp;&amp; [item doesWhateverElse] &amp;&amp; ![item doesNotDoSomething];
}

+ (ItemTableCellString *)subCellForItem:(IDRItem *)item {
  ItemTableCellString *cell = [[[self alloc] initWithItem:item] autorelease];
  return cell;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2011/09/another-creator-pattern-for-clusters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t do parts.parts</title>
		<link>http://ursecta.com/wp/2010/11/dont-do-parts-parts/</link>
		<comments>http://ursecta.com/wp/2010/11/dont-do-parts-parts/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 23:12:26 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=1091</guid>
		<description><![CDATA[I just found another weirdness in Apple&#8217;s Objective C. If you have the same name for several components of an object path, the runtime starts stuttering and behaving very badly. Intermittently, you can&#8217;t scroll, or only extremely slowly, everything turns into molasses. No errors, mind, just mindbogglingly slow. This stuttering and slowness seems to affect [...]]]></description>
			<content:encoded><![CDATA[<p>I just found another weirdness in Apple&#8217;s Objective C. If you have the same name for several components of an object path, the runtime starts stuttering and behaving very badly. Intermittently, you can&#8217;t scroll, or only extremely slowly, everything turns into molasses. No errors, mind, just mindbogglingly slow.</p>
<p>This stuttering and slowness seems to affect the simulator, mainly, not so much if you run code on your device (in my case the iPad). Also, if you run under instruments, things work better (Murphy strikes again), except I had it stutter under &#8220;Allocations&#8221; but not under other instruments.</p>
<p>I had these repeat names in two places in my code and resolving those two seems to have fixed the stuttering entirely. To illustrate what I mean, see this code snippet:</p>
<pre>
for (IDRBase *idr in <b>self.parts.parts</b>) {
   if ([idr isSuperCell]) break;
   CGRect newFrame = myCGRectDown(hugeFrame, verticalOffset);
   UIView *view = [idr getAsView:newFrame];
   if (view) {
      [returnView addSubview:view];
      verticalOffset += view.frame.size.height;
   }
}
</pre>
<p><em>(Yes, it&#8217;s the same snippet as in the <a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/2010/10/is-it-nil-or-isnt-it/" title="(100 hits)">previous example with nil or not nil</a>. Coincidence. My code does indeed consist of more than just this.)</em></p>
<p>In the very first line you see a property referred to as &#8220;self.parts.parts&#8221;. That is what screws things up. Even though the two names &#8220;parts&#8221; refer to entirely different things, and even though the code actually delivers the values it should, this repetition of identical literal names confuses the crap out of the runtime, it seems. The solution is to not name these two things the same, of course. In this case, I changed the innermost &#8220;parts&#8221; to &#8220;aParts&#8221;, resulting in &#8220;self.parts.aParts&#8221;, and hey presto, no stuttering no more.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/11/dont-do-parts-parts/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Is it nil or isn&#8217;t it?</title>
		<link>http://ursecta.com/wp/2010/10/is-it-nil-or-isnt-it/</link>
		<comments>http://ursecta.com/wp/2010/10/is-it-nil-or-isnt-it/#comments</comments>
		<pubDate>Mon, 04 Oct 2010 09:14:19 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Objective C]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=1064</guid>
		<description><![CDATA[A bit of Objective-C weirdness I don&#8217;t quite get. The weirdness occurs if &#8220;view&#8221; in the code below is nil, that is if [idr getAsView:newFrame] returns nil. You&#8217;d expect the verticalOffset not to be incremented, but it is. Even though view is nil, view.frame.size.height still evaluates to &#8220;21&#8243; (in this case) and verticalOffset gets incremented. [...]]]></description>
			<content:encoded><![CDATA[<p>A bit of Objective-C weirdness I don&#8217;t quite get. The weirdness occurs if &#8220;<strong>view</strong>&#8221; in the code below is nil, that is if <strong>[idr getAsView:newFrame]</strong> returns <strong>nil</strong>. You&#8217;d expect the <strong>verticalOffset</strong> not to be incremented, but it is. Even though <strong>view</strong> is <strong>nil</strong>, <strong>view.frame.size.height</strong> still evaluates to &#8220;21&#8243; (in this case) and <strong>verticalOffset</strong> gets incremented. (The first returned <strong>view</strong> was 21 high, the second returned <strong>view</strong> was nil in the debug run I&#8217;m referring to.)</p>
<pre>
- (UIView *)getAsView:(CGRect)theFrame {
	CGFloat verticalOffset = 0.0;
	CGRect hugeFrame = myCGRectHuge(theFrame);
	IDVBase *returnView = [[IDVBase alloc] initWithFrame:hugeFrame];
	hugeFrame = myCGRectResetToZero(hugeFrame);

	for (IDRBase *idr in self.parts.parts) {
		CGRect newFrame = myCGRectDown(hugeFrame, verticalOffset);
<strong>		UIView *view = [idr getAsView:newFrame];
		[returnView addSubview:view];
		verticalOffset += view.frame.size.height;
</strong>	}
	[returnView sizeToFit];
	return [returnView autorelease];
}
</pre>
<p>To avoid the unintended increment, I have to add the conditional <strong>if (view) {&#8230;}</strong> (which is a pretty good idea anyway, since it&#8217;s rather pointless, or maybe even bad, to add a nil as a subView):</p>
<pre>
- (UIView *)getAsView:(CGRect)theFrame {
	CGFloat verticalOffset = 0.0;
	CGRect hugeFrame = myCGRectHuge(theFrame);
	IDVBase *returnView = [[IDVBase alloc] initWithFrame:hugeFrame];
	hugeFrame = myCGRectResetToZero(hugeFrame);

	for (IDRBase *idr in self.parts.parts) {
		CGRect newFrame = myCGRectDown(hugeFrame, verticalOffset);
<strong>		UIView *view = [idr getAsView:newFrame];
		if (view) {
			[returnView addSubview:view];
			verticalOffset += view.frame.size.height;
		}
		[returnView addSubview:view];
		verticalOffset += view.frame.size.height;
</strong>	}
	[returnView sizeToFit];
	return [returnView autorelease];
}
</pre>
<p>I don&#8217;t know what the moral of this story is. I assume that if I should delve into the language reference, this will turn out to be undefined behaviour. Trying to figure out what could have been defined behaviour, I can&#8217;t come up with a reasonable answer, so I guess it&#8217;s just one of those things you should avoid doing. Maybe a compiler warning would have been nice, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/10/is-it-nil-or-isnt-it/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Method forwarding in Objective-C</title>
		<link>http://ursecta.com/wp/2010/08/method-forwarding-in-objective-c/</link>
		<comments>http://ursecta.com/wp/2010/08/method-forwarding-in-objective-c/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 08:24:32 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iOS Dev]]></category>
		<category><![CDATA[iPad]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=1023</guid>
		<description><![CDATA[I scraped together the following from a number of sources and got it to work fine and without compiler warnings. Interesting links are, among others: http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html http://macdevelopertips.com/objective-c/objective-c-categories.html But, I get ahead of myself. The idea here is to have one object forward method invocations to another. Typically, you have a class responding to method A, [...]]]></description>
			<content:encoded><![CDATA[<p>I scraped together the following from a number of sources and got it to work fine and without compiler warnings. Interesting links are, among others:</p>
<p>http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html</p>
<p>http://macdevelopertips.com/objective-c/objective-c-categories.html</p>
<p>But, I get ahead of myself. The idea here is to have one object forward method invocations to another. Typically, you have a class responding to method A, then you decide to make an instance of that class a member of an outer class and any messages for the methods sent to the outer class should be forwarded to the inner class if that&#8217;s where they are to be handled. And, of course, you don&#8217;t want to sit and write all these methods again in the outer class just so the inner class gets called. An example:</p>
<p>I have a class I call IotaDOM2TableProxy which has a method &#8220;rowsInSection:&#8221;. The class IssueWorksheet holds an instance of IotaDOM2TableProxy as a property. I now want any &#8220;rowsInSection&#8221; messages sent to the outer IssueWorksheet to be forwarded to the inner IotaDOM2TableProxy object without having to declare any &#8220;rowsInSection&#8221; method for the IssueWorksheet class. This is how you do it.</p>
<p>Firstly: the target, the IotaDOM2TableProxy class, needs no modification at all. It never knows what hit it, or rather, where the invocations come from. So we&#8217;ll not say anything more about it than that it contains the declaration of the &#8220;rowsInSection:&#8221; method (among a load of other stuff):</p>
<pre>
@interface IotaDOM2TableProxy : NSObject {
...
}
<b>- (NSUInteger)rowsInSection:(NSUInteger)section;</b>
@end
</pre>
<p>The IssueWorksheet class holds an instance of the IotaDOM2TableProxy, and does <i>not</i> declare any method called &#8220;rowsInSection&#8221;:</p>
<pre>
@interface IssueWorksheet : NSObject {
    IotaDOM2TableProxy *dom2tableProxy;
}
@property (nonatomic, retain) IotaDOM2TableProxy *dom2tableProxy;
@end
</pre>
<p>To make IssueWorksheet forward any calls it doesn&#8217;t know about to IotaDOM2TableProxy, we have to override three methods in IssueWorksheet:</p>
<pre>
- (BOOL)respondsToSelector:(SEL)aSelector {
    return [super respondsToSelector:aSelector] ||
           [self.dom2tableProxy respondsToSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature *sig;
    sig = [super methodSignatureForSelector:aSelector];
    if (sig == nil)
        sig = [self.dom2tableProxy methodSignatureForSelector:aSelector];
    return sig;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    SEL aSelector = [invocation selector];
    if ([self.dom2tableProxy respondsToSelector:aSelector])
        [invocation invokeWithTarget:self.dom2tableProxy];
    else
        [self doesNotRecognizeSelector:aSelector];
}
</pre>
<p>And this works beautifully for one, two, or any number of methods to forward. There&#8217;s just one problem: the compiler complains that IssueWorksheet &#8220;may not respond to method&#8230;&#8221; and we should always eliminate warnings. The easiest way is to declare the forwarded methods in a category, which only mildly defeats the purpose of the exercise. But it works and is safe. You do that by adding the category after the interface declaration of IssueWorksheet, so the header file will now look as follows in its entirety:</p>
<pre>
//
//  IssueWorksheet.h
//  iotaPad1
//
//  Created by Martin on 2010-06-08.
//

#import <Foundation/Foundation.h>
#import "IotaDOM2TableProxy.h"

@interface IssueWorksheet : NSObject {
    IotaDOM2TableProxy *dom2tableProxy;
}

@property (nonatomic, retain) IotaDOM2TableProxy *dom2tableProxy;

- (id)initFromFile:(NSString *)name ofType:(NSString *)type;

@end

<b>@interface IssueWorksheet (ForwardedMethods)
- (NSUInteger)rowsInSection:(NSUInteger)section;
@end</b>
</pre>
<p>In the above, I call the category &#8220;ForwardedMethods&#8221;, but you can call it anything you like. The name doesn&#8217;t matter and isn&#8217;t referenced anywhere else, but the category must have a unique name of some sort.</p>
<p>Please note: there is <i>no</i> implementation in the .m file for &#8220;rowsInSection&#8221;. The category definition suffices to shut the compiler up.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/08/method-forwarding-in-objective-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solution: open the market</title>
		<link>http://ursecta.com/wp/2010/06/solution-open-the-market/</link>
		<comments>http://ursecta.com/wp/2010/06/solution-open-the-market/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 09:00:17 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iota]]></category>
		<category><![CDATA[Medical Applications]]></category>
		<category><![CDATA[EHR]]></category>
		<category><![CDATA[EMR]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=922</guid>
		<description><![CDATA[Now we&#8217;ve arrived at the last of the solutions in my list, namely &#8220;Opening the market for smaller entrepreneurs&#8221;. There are a number of reasons we have to do this, and I&#8217;ve touched on most of them before in other contexts. The advantages of having a large all-in-one vendor to deliver a single system doing [...]]]></description>
			<content:encoded><![CDATA[<p>Now we&#8217;ve arrived at the last of the solutions in <a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/2010/05/that-was-a-rough-ride/" target="_blank" title="(81 hits)">my list,</a> namely &#8220;Opening the market for smaller entrepreneurs&#8221;. There are a number of reasons we have to do this, and I&#8217;ve touched on most of them before in other contexts.</p>
<p>The advantages of having a large all-in-one vendor to deliver a single system doing everything for your electronic health-care record needs are:</p>
<ul>
<li>You don&#8217;t have to worry about interconnections, there aren&#8217;t any</li>
<li>You don&#8217;t have to figure out who to call when things go wrong, there&#8217;s only one vendor to call</li>
<li>You can reduce your support staff, at least you may think so initially</li>
<li>You can avoid all arguments about requirements from the users, there is nothing you can change anyway</li>
<li>It looks like good leadership to the uninitiated, just like Napoleon probably looked pretty good at Waterloo, at least to start with</li>
</ul>
<p>The disadvantages are:</p>
<ul>
<li>Since you have no escape once the decision is made, the costs are usually much higher than planned or promised</li>
<li>There is only one support organization, and they are usually pretty unpleasant to deal with, and almost always powerless to do anything</li>
<li>Any extra functionality you need must come from the same vendor, and will cost a fortune, and will always be late, bug-ridden, and wrong</li>
<li>The system will be worst-of-breed in every individual area of functionality; its only characteristic being that it is all-encompassing (like mustard gas over Ieper)</li>
<li>The system will never be based on a simple architecture or interface standards; there is no need for it, the vendor usually doesn&#8217;t have the expertise for it, and the designers have no incentives to do a quality job</li>
<li>Since <a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/2010/06/solution-improved-specifications/" target="_blank" title="(101 hits)">quality is best measured as the simplicity and orthogonality of interfaces and public specs</a>, and large vendors don&#8217;t deliver either of these, there is no objective measure of quality, hence there is no quality (there&#8217;s a law in there somewhere about <em>&#8220;that which is not measurable does not exist&#8221;;</em> was it Newton who said that?)</li>
<li>Due to poor architecture, the system will almost certainly be developed as too few and too large blocks of functionality, making them harder than necessary to maintain (yes, the vendor maintains it for you, but you pay and suffer the poor quality)</li>
</ul>
<p>Everybody knows the proverb about power: it corrupts. Don&#8217;t give that kind of power to a single vendor, he is going to misuse it to his own advantage. It&#8217;s not a question of how nice and well-meaning the CEO is, it is his duty to screw you to the hilt. That&#8217;s what he&#8217;s being paid to do and if he doesn&#8217;t, he&#8217;ll lose his job.</p>
<p>But if we want the customers to choose best-of-breed solutions from smaller vendors, we have to be able to offer them these best-of-breed solutions in a way that makes it technically, economically, and politically feasible to purchase and install such solutions. Today, that is far from the case. Smaller vendors behave just like the big vendors, but with considerably less success, using most of their energy bickering about details and suing each other and the major vendors, when things don&#8217;t go as they please (which they never do). If all that energy went into making better products instead, we&#8217;d have amazingly great software by now.</p>
<p>The major problem is that even the smallest vendor would rather go bust trying to build a complete all-in-one system for electronic health-care records, than concede even a part of the whole to a competitor, however much better that competitor is when it comes to that part. And while the small vendors fight their little wars, the big ones run off with the prize. This has got to stop.</p>
<p>One way would be for the government to step in and mandate interfaces, modularity, and interconnection standards. And they do, except this approach doesn&#8217;t work. When government does this, they select projects on the advice of people whose livelihood depends on the creation of long-lived committees where they can sit forever producing documents of all kinds. So all you get is high cost, eternal committees, and no joy. Since no small vendor ever could afford to keep an influential presence on these committees, the work will never result in anything that is useful to the smaller vendors, while the large vendors don&#8217;t need any standards or rules of any kind anyway, since they only connect to themselves and love to blame the lack of useful standards for not being able to accomodate any other vendor&#8217;s systems. This way, standards consultants standardize, large vendors don&#8217;t care about the standards and keep selling, and everyone is happy except for the small vendors and, of course, the users who keep paying through the nose for very little in return.</p>
<p>There&#8217;s no way out of this for the small vendors and the users if you need standards to interoperate, but lucky for us, standards are largely useless and unnecessary even in the best of cases. All it takes is for one or two small vendors to publish de facto standards, simple and practical enough for most other vendors to pick up and use. I&#8217;ve personally seen this happen in Belgium in the 80&#8242;s and 90&#8242;s where a multitude of smaller EHR systems used each other&#8217;s lab and referral document standards, instead of waiting for official CEN standards, which didn&#8217;t work at all once published (see <a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/2010/06/solution-less-need-for-standards/" target="_blank" title="(82 hits)">my previous blog post</a>). In the US, standards are generally not invented by standards bodies, but selected from de facto standards in use, and then approved, which explains why US standards usually do work, while European standards don&#8217;t.</p>
<p>Where does all this leave us? I see only one way of getting out of this mess and that is for smaller vendors to start sharing de facto standards with each other. Which leads directly to my conclusion: everything I do with iotaMed will be open for use by others. I will define how issue templates will look and how issue worksheets and observations will be structured, but those definitions are free to use by any vendor, small or large. At the start, I reserve the right to control which documents structures and interfaces can be called &#8220;iota&#8221; and &#8220;iotaMed&#8221;, but as soon as other players take active and constructive part in all this, I fully intend to share that control. But an important reason not to let it go from the start is that I am truly afraid of a large &#8220;committee&#8221; springing up whose only interest will be to make it cost more, increase the page count, and take forever to produce results. And that, I will fight tooth and nail.</p>
<p>On the other hand, I&#8217;ll develop the iotaMed interface for the iPad and I intend to publish the source for that, but keep the right to sell licenses for commercial use, while non-profit use will be free. Exactly how to draw that limit needs to be defined later, but it would be a really good thing if several vendors agreed on a common set of principles, since that would make it easier for our customers to handle. A mixed license model with GPL and a regular commercial license seems to be the way to go. But in the beginning, we have to share as much as possible, so we can create a market where we all can add products and knowledge. Without boostrapping that market, there will be no products or services to sell later.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/06/solution-open-the-market/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solution: less need for standards</title>
		<link>http://ursecta.com/wp/2010/06/solution-less-need-for-standards/</link>
		<comments>http://ursecta.com/wp/2010/06/solution-less-need-for-standards/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 09:00:19 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iota]]></category>
		<category><![CDATA[Medical Applications]]></category>
		<category><![CDATA[CEN]]></category>
		<category><![CDATA[EHR]]></category>
		<category><![CDATA[EMR]]></category>
		<category><![CDATA[Prorec]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[TC-251]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=906</guid>
		<description><![CDATA[Around 1996 I was part of the CEN TC251 crowd for a while, not as a member but as an observer. CEN is the European standards organization, and TC251 is &#8220;Technical Committee 251&#8243;, which is the committee that does all the medical IT standardization. The reason I was involved is that I was then working [...]]]></description>
			<content:encoded><![CDATA[<p>Around 1996 I was part of the CEN TC251 crowd for a while, not as a member but as an observer. CEN is the European standards organization, and TC251 is &#8220;Technical Committee 251&#8243;, which is the committee that does all the medical IT standardization. The reason I was involved is that I was then working as a consultant for the University of Ghent in Belgium and I had as task to create a Belgian &#8220;profile&#8221; of the &#8220;Summary of Episode of Care&#8221; standard for the Belgian market. So I participated in a number of meetings of the TC251 working groups.</p>
<p>For those that are in the know, I must stress that this was the &#8220;original&#8221; standards effort, all based on Edifact like structures and before the arrival of XML on the stage. I&#8217;ve heard from people that the standards that were remade in XML form are considerably more useful than the stuff we had to work with.</p>
<p>I remember this period in my life as a period of meeting a lot of interesting people, having a lot of fun, but at the same time being excruciatingly frustrated by overly complex and utterly useless standards. The standards I had to work with simply didn&#8217;t compute. For months I went totally bananas trying to make sense of what was so extensively documented, but never succeeded. After a serious talk with one of the chairpersons, a very honest Brit, I finally realized that nobody had ever tried out this stuff in reality and that most, maybe even all, of my complaints about inconsistencies and impossibilities were indeed real and recognized, but that it was politically impossible to publicly admit to that. Oboy&#8230;</p>
<p>I finally got my &#8220;profile&#8221; done by simply chucking out the whole lot and starting over again, writing the entire thing as I would have done if I&#8217;d never even heard of the standards. That version was immediately accepted and I was recently told it still is used with hardly any changes as the Belgian Prorec standard, or at least a part of it.</p>
<p>The major lesson I learned from the entire CEN debacle (it was a debacle for me) is that the first rule in standardization of anything is to avoid it. Don&#8217;t ever start a project that requires a pre-existing standard to survive. It won&#8217;t survive. The second rule is: if it requires a standard, it should be small and functional, not semantic. The third is: if it is a semantic standard, it should comprise a maximum of a few tens of terms. Anything beyond a hundred is useless.</p>
<p>It&#8217;s easy to see that these rules hold in reality. HTML is a hugely successful standard since it&#8217;s small and has just a few semantic terms, such as GET, PUT, etc. XML: the same thing holds. Snomed CT: a few hundred thousand terms&#8230; you don&#8217;t want to hear what I think of <em>that</em>, you&#8217;d have to wash your ears with soap afterwards.</p>
<p>From all my years of developing software, I&#8217;ve never <em>ever</em> encountered a problem that needed a standard like Snomed CT, that couldn&#8217;t just as well be solved without it. During all those years, I&#8217;ve never <em>ever</em> seen a project requiring such a massive standards effort as Snomed CT, <em>actually succeed</em>. Never. I can&#8217;t say it couldn&#8217;t happen, I&#8217;m only saying I&#8217;ve never seen it happen.</p>
<p>The right way to design software, in my world, is to construct everything according to your own minimal coding needs, but always keep in mind that all your software activities could be imported and exported using a standard differing from what you do internally. That is, you should make your data simple enough and flexible enough to allow the addition of a standard later. If it is ever needed. In short: <strong>given the choice between simple or standard, always choose simple</strong>.</p>
<p>Exactly how to do this is complex, but not complex in the way standards are, only complex in the way you need to think about it. In other words, it requires that rarest of substances, brain sweat. Let me take a few examples.</p>
<p>If you need to get data from external systems, and you do that in your application in the form of synchronous calls only, waiting for a reply before proceeding, you severely limit the ability of others to change the way you interact with these systems. If you instead create as many of your interactions as possible as asynchronous calls, you open up a world of easy interfacing for others. </p>
<p>If you use data from other systems, try to use them as opaque blocks. That is, if you need to get patient data, don&#8217;t assume you can actually read that data, but let external systems interpret them for you as much as possible. That allows other players to provide patient data you never expected, but as long as they also provide the engine to use that data, it doesn&#8217;t matter.</p>
<p>Every non-trivial and distinct functionality in your application should be a separate module, or even better, a separate application. That way it can be easily replaced or changed when needed. As I mentioned before, the interfaces and the module itself, will almost automatically be of better quality as well.</p>
<p>The most useful rule of thumb I can give you is this: if anyone proposes a project that includes the need for a standard containing more than 50 terms or so, say no. Or if you&#8217;re the kind of person who is actually making a living producing nothing but &#8220;deliverables&#8221; (as they call these stacks of unreadable documents), definitely say yes, but realize that your existence is a heavy load on humanity, and we&#8217;d all probably be better off without your efforts.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/06/solution-less-need-for-standards/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solution: improved specifications</title>
		<link>http://ursecta.com/wp/2010/06/solution-improved-specifications/</link>
		<comments>http://ursecta.com/wp/2010/06/solution-improved-specifications/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 09:00:48 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iota]]></category>
		<category><![CDATA[Medical Applications]]></category>
		<category><![CDATA[approval]]></category>
		<category><![CDATA[CE]]></category>
		<category><![CDATA[NPÖ]]></category>
		<category><![CDATA[standards]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=891</guid>
		<description><![CDATA[The quality of our IT systems for health-care is pretty darn poor, and I think most people agree on that. There have been calls for oversight and certification of applications to lessen the risk of failures and errors. In Europe there is a drive to have health-care IT solutions go through a CE process, which [...]]]></description>
			<content:encoded><![CDATA[<p>The quality of our IT systems for health-care is pretty darn poor, and I think most people agree on that. There have been calls for oversight and certification of applications to lessen the risk of failures and errors. In Europe there is a drive to have health-care IT solutions go through a CE process, which more or less contains a lot of documentation requirements and change control. So by doing this, the CE process certifies a part of the actual process to produce the applications. But I dare claim this isn&#8217;t very useful.</p>
<p>If you want to get vendors to produce better code with less bugs, there is only one thing you can do to achieve that: inspect the code directly or indirectly. Everything else is too complicated and ineffective. The only thing the CE process will achieve is more bureaucracy, more paper, slower and more laborious updates, fewer timely fixes, and higher costs. What it also will achieve, and this may be very intentional, is that only large vendors with massive overhead staff can satisfy the CE requirements, killing all smaller vendors in the process.</p>
<p>But back to the problem we wanted to solve, namely code quality. What should be done, at least theoretically, is actual approval of the code in the applications. The problem here is that very few people are actually qualified to judge code quality correctly, and it&#8217;s very hard to define on paper what good code should look like. So as things stand today, we are not in a position where we can mandate a certain level of code quality directly, leaving us no other choice than doing it indirectly.</p>
<p>I think most experienced software developers agree that the public specifications and public APIs of a product very accurately reflect the inner quality of the code. There is no reason in theory why this needs to be the case, but in practice it always is. I&#8217;ve never seen an exception to this rule. Even stronger, I can assert that a product that has no public specifications or no public API is also guaranteed to be of poor quality. Again, I&#8217;ve never seen an exception to this rule.</p>
<p>So instead of checking paperbased processes as CE does, let&#8217;s approve the specifications and APIs. Let the vendors subject these to approval by a public board of experts. If the specs make sense and the APIs are clean and orthogonal and seem to serve the purpose the specs describe, then it&#8217;s an easy thing to test if the product adheres to the specs and the APIs. If it does, it&#8217;s approved, and we don&#8217;t need to see the original source code at all.</p>
<p>There is no guarantee that you&#8217;ll catch all bad code this way, but it&#8217;s much more likely than if you use CE to do it. It also has the nice side effect of forcing all players to actually open up specs and APIs, else there&#8217;s no approval.</p>
<p>One thing I can tell you off the bat: the Swedish NPÖ (National Patient Summary) system would flunk such an inspection so hard. That API is the horror of horrors. Or to put it another way: if any approval process would be able to let the NPÖ pass, it&#8217;s a worthless approval process. Hmmm&#8230;. maybe we can use NPÖ as an approval process approval test? <em>No approval process should be accepted for general use unless it totally flunked NPÖ.</em> Sounds fine to me.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/06/solution-improved-specifications/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Solution: modular structure</title>
		<link>http://ursecta.com/wp/2010/06/solution-modular-structure/</link>
		<comments>http://ursecta.com/wp/2010/06/solution-modular-structure/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 09:00:16 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iota]]></category>
		<category><![CDATA[Medical Applications]]></category>
		<category><![CDATA[EHR]]></category>
		<category><![CDATA[EMR]]></category>
		<category><![CDATA[iotaMed]]></category>
		<category><![CDATA[modularity]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=877</guid>
		<description><![CDATA[Forcing a large application into small independent parts that have to communicate with each other using minimal interfaces is always a good thing. Large monolithic applications go &#8220;fat and lazy&#8221; when there is no requirement to keep them split up. Also, the effort to expand and maintain the applications go through the roof. We know [...]]]></description>
			<content:encoded><![CDATA[<p>Forcing a large application into small independent parts that have to communicate with each other using minimal interfaces is always a good thing. Large monolithic applications go &#8220;fat and lazy&#8221; when there is no requirement to keep them split up. Also, the effort to expand and maintain the applications go through the roof. We know all that since ages, but both our IT purchasers and our vendors act as if it&#8217;s raining and it&#8217;s all business as usual. Of course, monolithic means all the business goes to one vendor, making him fat and happy, and very little requirement for thinking and effort by the purchasing organizations and the IT support. Now, if IT support considered their actual task, which is not work avoidance but the implementation and support of an effective IT organization enabling the health care staff to do a better job, things would look different.</p>
<p>The thing is, we do absolutely need modularity. The IT applications should mimic and support medicine as it is actually practiced, and not the other way around. Medical practice should not need to adapt itself to poorly conceived IT solutions. <em>(You recognize this tendency by the constant cries for &#8220;more training&#8221;. It&#8217;s all just so much nonsense. My advice: ignore them.)</em></p>
<p>Different specialities have different needs for note taking and guidelines. On the other hand, needs for handling of pharmaceutical prescriptions differ according to type of department. Internal medicine on a ward or outpatient differs from internal medicine as practices on an intensive care unit. Different needs also arise for appointments according to the ownership of the practice, regardless of speciality. And so on.</p>
<p>These differences aren&#8217;t gratuitous; they are necessary and are an inherent part of how medicine works. The attempts to eliminate these differences by large, universal systems, and their large, universal ways of working, don&#8217;t work, since they force a suboptimal way of operating on the medical profession.</p>
<p>Now, the defenders of the great unified systems, let&#8217;s call them &#8220;unicorn followers&#8221;, argue that medicine should adapt itself to how IT works, else the IT systems will be too expensive and complex. To the unicorn followers, we should say: yes, the IT systems will be more expensive, but the savings in medical practice will outpace them by orders of magnitude. Don&#8217;t suboptimize and try to save just on IT, that is not your job! Your job is to enable medicine to save lives and money through better healthcare, not through junk IT software and equipment. </p>
<p>Oh, and while we&#8217;re at it: modular systems are actually cheaper to produce and work much better, but that is something most software engineering texts explain and provide the proofs for. And you out there who purchase, or sell, or build these systems, you have read those texts, haven&#8217;t you?</p>
<p>In short, even the unicorn followers, once they&#8217;ve picked up a bit of the computer science of the last half century and started to worry about what their real task in the medical context actually is or should be, will undoubtedly see the light and start to specify new systems as modular in every possible aspect. The unicorn, just like the &#8220;one medical records system&#8221; is a mythical beast and will never be seen in real life. Even if it wasn&#8217;t mythical, it would get stuck everywhere with that unwieldy horn and die of hunger. Good riddance.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/06/solution-modular-structure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solution: Issues</title>
		<link>http://ursecta.com/wp/2010/06/solution-1-issues/</link>
		<comments>http://ursecta.com/wp/2010/06/solution-1-issues/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 09:00:18 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iota]]></category>
		<category><![CDATA[Medical Applications]]></category>
		<category><![CDATA[EHR]]></category>
		<category><![CDATA[EMR]]></category>
		<category><![CDATA[issues]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=859</guid>
		<description><![CDATA[Ah, finally we arrive at solutions. The first in the series is the elephant in the room: issues. Why do I say &#8220;elephant in the room&#8221;? Because when a doctor examines and treats a patient, he thinks in &#8220;issues&#8221;, and the result of that thinking manifests itself in planning, tests, therapies, and follow-up. When he [...]]]></description>
			<content:encoded><![CDATA[<p>Ah, finally we arrive at solutions. The first in the series is the elephant in the room: issues. </p>
<p>Why do I say &#8220;elephant in the room&#8221;? Because when a doctor examines and treats a patient, he thinks in &#8220;issues&#8221;, and the result of that thinking manifests itself in planning, tests, therapies, and follow-up. When he records the encounter, he records only planning, tests, therapies, and follow-up, but not the main entity, the &#8220;issue&#8221; since there is no place for it. The next doctor that sees the patient needs to read about the planning, tests, therapies, and follow-up and then mentally reverse-engineer the process to arrive at which issue is ongoing. Again, he manages the patient according to that issue, then records everything but the issue itself. </p>
<p>Other actors such as national registers, extraction of epidemiological data, and all the others, all go through the same process. They all have their own methods of churning through planning, tests, therapies, and follow-up, to reverse-engineer the data in order to arrive at what the issue is, only to discard it again.</p>
<p>This is what I mean by the &#8220;elephant in the room&#8221;. The problem is so pervasive, so obvious, so large, that it is incomprehensible to me how this situation ever came about and why it is so difficult to convince our IT providers about the need for this entity in our systems, and the huge range of problems that its introduction would solve. Doctors in general don&#8217;t see it either, but at least they are almost to a man (and woman) extremely easy to convince. And once they see the problem and the solution, it&#8217;s as obvious to them as it is to me. This is how it looks today with all different actors trying to make sense of a highly deficient EHR <em>(the images are taken from a presentation, and I think you may get an idea of the meaning even without my sweet voice explaining what you see)</em>:</p>
<p><a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.007.png" title="(72 hits)"><img src="http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.007-300x225.png" alt="" title="Slides.007" width="300" height="225" class="aligncenter size-medium wp-image-861" /></a></p>
<p>So, after that harangue, this is my message: we need the &#8220;issue&#8221; concept in our medical systems. If the issue concept is present in the EHR, there is no need for every doctor and every actor to keep reconstructing it from derived and deficient data. It&#8217;s very easy to adapt the issue templates to cover all the needs of the different actors, simply because it turns out they are all after more or less the same thing. This only becomes obvious once you see it from the perspective of &#8220;issues&#8221;.</p>
<p><a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.010.png" title="(78 hits)"><img src="http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.010-300x225.png" alt="" title="Slides.010" width="300" height="225" class="aligncenter size-medium wp-image-862" /></a></p>
<p>If we look at what exactly an &#8220;issue&#8221; consists of, we see that it is an ICD-10 code, or an ICD-10 code range, that defines the symptom or disease as such. Further, it contains a clinical guidline on how to diagnose and treat the disease, or how to further investigate it and refine the diagnosis, including differential diagnoses. It would entirely replace the usual medical records in daily use and it would best be presented on a touch operated slate device such as the iPad, simply because following links, making choices, and looking up information will be much more important than entering text. The text entry part will still be possible, but will be more of an exception than a rule.</p>
<p><a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.021.png" title="(65 hits)"><img src="http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.021-300x225.png" alt="" title="Slides.021" width="300" height="225" class="aligncenter size-medium wp-image-864" /></a></p>
<p>Naturally, even though you will work with &#8220;issues&#8221; instead of regular medical records, the medical records are still produced in the background, and preexisting records are both viewable and linkable through the same interface. If you look at the bottom of my little mock-up, you&#8217;ll see tabs that bring you to the old medication list, chronological records (old style EHR), referrals, lab, etc. But in general, you&#8217;ll be working in the &#8220;issue worksheet&#8221; for most of the time, only occasionally looking up information through the other tabs.</p>
<p><a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.022.png" title="(70 hits)"><img src="http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.022-300x225.png" alt="" title="Slides.022" width="300" height="225" class="aligncenter size-medium wp-image-865" /></a></p>
<p>To emphasize the radical difference between this way of working and the old EHR way of working, I made a simple mockup of the entry screen for a patient record. All you see is the patient&#8217;s name and a list of issues, some of which are subissues, or differential diagnoses that haven&#8217;t been resolved yet. For an entry screen, that is actually all we need.</p>
<p><a href="http://ursecta.com/wp/go.php?http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.023.png" title="(74 hits)"><img src="http://ursecta.com/wp/wp-content/uploads/2010/06/Slides.023-300x225.png" alt="" title="Slides.023" width="300" height="225" class="aligncenter size-medium wp-image-866" /></a></p>
<p>You may notice that &#8220;Eric the Seafarer&#8221; had breast cancer according to this screen, which is very unusual in men. But vikings were a strange and wonderful people, so I would not jump to conclusions about that.</p>
<p>Oh, better late than never: click on any image for a larger resolution.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/06/solution-1-issues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problem: no searcheability</title>
		<link>http://ursecta.com/wp/2010/05/problem-no-searcheability/</link>
		<comments>http://ursecta.com/wp/2010/05/problem-no-searcheability/#comments</comments>
		<pubDate>Wed, 19 May 2010 09:00:25 +0000</pubDate>
		<dc:creator>martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iota]]></category>
		<category><![CDATA[Medical Applications]]></category>

		<guid isPermaLink="false">http://ursecta.com/wp/?p=750</guid>
		<description><![CDATA[This post is part of a series detailing the problems of current electronic healthcare records. To orient yourself, you can start at the index page on &#8220;presentation&#8221; on the iota wiki. You will find this and other pages on that wiki as well. The wiki pages will be continuously updated. Since current electronic health care [...]]]></description>
			<content:encoded><![CDATA[<p><em>This post is part of a series detailing the problems of current electronic healthcare records. To orient yourself, you can start at the <a href="http://ursecta.com/wp/go.php?http://iota.pro/Presentation" title="(318 hits)">index page on &#8220;presentation&#8221;</a> on the iota wiki. You will find this and other pages on that wiki as well. The wiki pages will be continuously updated.</em></p>
<p>Since current electronic health care record systems have no knowledge of diseases as entities, we can&#8217;t drill down into the structure to locate necessary detail about the diagnosis or treatment of that disease. The information about diseases is spread out in the huge block of text that forms the EHR for a patient, so the only way to locate information in that is by searching on particular words or terms one could hope is related to the treatments one is looking for. Interestingly, not one of the EHR systems the author has seen has implemented even the most rudimentary search abilities such as &#8220;Find&#8221;. It&#8217;s hard to believe that these multimillion dollar systems don&#8217;t even have the features the lowly &#8220;Notepad&#8221; app has had since the inception of Windows in the 80&#8242;s, but that is the case. This leaves us with nothing else than eyeballing <em>all</em> the text manually, from start to finish. A clearly absurd state of affairs.</p>
<p>Search, even if implemented right, helps only in some edge cases. If you look for a reason why a certain medication was given or not given, it can help. If you look for treatments for a known disease, it can also help, but if you look for issues in the patient&#8217;s history that you <em>don&#8217;t</em> know about yet (the most important and most frequent search we do in an EHR in primary care), you&#8217;re out of luck even with a search function since you don&#8217;t know what you are searching for. A search can fill the function of an index, but not of a table of contents.</p>
<p>A summary of contents could be in the form of a &#8220;tag cloud&#8221;, but no EHR the author is aware of has even attempted to implement any such feature. Implementing a &#8220;tag cloud&#8221; of terms used in a medical record, if done right and with taste, could make the search problem somewhat more tractable by making it easier to navigate the old unstructured information from current EHR systems. It would not by any means replace &#8220;issues&#8221; as a structure, but would be helpful when linking legacy information to &#8220;issues&#8221; in a modern iotaMed based EHR.</p>
<p>In specialist care, the balance is somewhat different. Since searching for unrelated diseases is less frequent, a search on words or terms is relatively more important (one more often knows what one is looking for) and both a &#8220;Find&#8221; function and a &#8220;tag cloud&#8221; are even more sorely missed than in primary care. Even though both of these functions would be very useful, their usefulness arises from the fact that the lack of &#8220;issues&#8221; makes the EHR information such a mess to begin with. In the presence of &#8220;issues&#8221;, there would rarely be a reason to do a free search at all over an EHR, since information would be found in the place where it belongs.</p>
<p>This is not a reason to cast aside &#8220;Find&#8221; and &#8220;tag clouds&#8221; even for specialist care, since the legacy data in current EHR systems will be with us for a very long time still, before it all can be linked up with &#8220;issues&#8221; and brought into an &#8220;issue&#8221;-based structure. And even then, in that far future, &#8220;Find&#8221; and &#8220;tag clouds&#8221; will be essential tools, albeit not anymore the <em>only</em> tools to aid in the comprehension of the medical record.</p>
]]></content:encoded>
			<wfw:commentRss>http://ursecta.com/wp/2010/05/problem-no-searcheability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

