<?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>meier-online</title>
	<atom:link href="http://meier-online.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://meier-online.com</link>
	<description>Der Blog von Karsten Meier</description>
	<lastBuildDate>Wed, 16 May 2012 17:55:17 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Attribut oder Property?</title>
		<link>http://meier-online.com/2012/05/attribute-or-property/</link>
		<comments>http://meier-online.com/2012/05/attribute-or-property/#comments</comments>
		<pubDate>Wed, 16 May 2012 13:46:57 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Fallen]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=836</guid>
		<description><![CDATA[Eine Falle beim Update von jQuery In einer bestehende Webanwendung wollte ich die JQuery-Bibliothek von Version 1.4.X auf 1.6.x aktualisieren. Zum größten Teil gab es keine Probleme, nur an folgender Stelle funktionierte es nicht. In der Webseite gibt es eine Textbox und ein Drop-Down-Menü zur Schnellauswahl häufig benutzter Begriffe. Wenn man aus dem Menü etwas [...]]]></description>
			<content:encoded><![CDATA[<p>Eine Falle beim Update von jQuery</p>
<p>In einer bestehende Webanwendung wollte ich die JQuery-Bibliothek von Version 1.4.X auf 1.6.x aktualisieren. Zum größten Teil gab es keine Probleme, nur an folgender Stelle funktionierte es nicht.<span id="more-836"></span></p>
<p>In der Webseite gibt es eine Textbox und ein Drop-Down-Menü zur Schnellauswahl häufig benutzter Begriffe. Wenn man aus dem Menü etwas auswählt, soll der gewählte Begriff in die Textbox geschrieben werden. Dazu nutze ich die folgenden Funktionen:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> put_selected_in_textbox<span style="color: #009900;">&#40;</span>selectbox<span style="color: #339933;">,</span> textbox<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> sel <span style="color: #339933;">=</span> selectbox.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'selectedIndex'</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>sel <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> txt <span style="color: #339933;">=</span> selectbox.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'option:selected'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    textbox.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>txt<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
    textbox.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;???&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #003366; font-weight: bold;">function</span> connect_select_to_text<span style="color: #009900;">&#40;</span>selectbox<span style="color: #339933;">,</span> textbox<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  selectbox.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'change'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    put_selected_in_textbox<span style="color: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> textbox<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
jQuery<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    connect_select_to_text<span style="color: #009900;">&#40;</span> jQuery<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_of_select'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> jQuery<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#id_of_textinput'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Mit jQuery-1.6 funktioniert das plötzlich nicht mehr. Der Debugger brachte ans Licht, das die Methode selectbox.attr(&#8216;selectedIndex&#8217;) jetzt &#8220;<em>undefined</em>&#8221; liefert. Nach einigen Suchen fand ich den Grund:</p>
<p>jQuery unterscheidet jetzt genauer zwischen Properties und Attrubuten. In der <a title="Offizielle Dokumentation der Methode prop" href="http://api.jquery.com/prop/" target="_blank">Dokumentation zu der Methode prop()</a> findet  man darüber auch eine Begründung.</p>
<p>Meine Übersetzung:</p>
<blockquote>
<p>Auf die Properties selectedIndex, tagName, nodeName, nodeType, ownerDocument, defaultChecked, und defaultSelected greift man mit der prop() Methode zu. Vor jQuery 1.6 war es möglich, auf diese Properties mit attr() zugreifen, dies liegt jedoch nicht im Verantwortungsbereich der attr() Methode. Denn diese Properties haben keine dazugehörigen Attribute und sind deshalb <strong>nur</strong> Properties.</p>
</blockquote>
<p>Da fragt man sich schon was denn jetzt eigentlich der Unterschied zwischen Attributen und Properties ist.</p>
<p> Im Java-Beans-Programmiermodell werden die Eigenschaften jeweils Properties genannt, man greift auf sie mit getX() und setX() zu. In Ruby on Rails hingegen heißen die Felder eines ActiveRecords &#8220;attributs&#8221;. Im &#8220;normalen&#8221; Englisch bezeichnet man mit Properties etwas ist, was man besitzt, z.B. Grundstücke oder Häuser(real property), aber auch die &#8220;intellectual property&#8221;. Das hilft uns aber irgendwie nur wenig weiter.</p>
<p>Offenbar beziehen sich bei jQuery die Attribute auf die in HTML/XML-Tags definierbaren Attribute. Also sind z.B. href und title Attribute des a-tags. Die definierten Attribute des <code>select</code>-Tags findet man in der <a title="Offizielle Dokumentation zum select-Tag " href="http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.6" target="_blank">HMTL 4.01 W3C-Spezifikation</a>.</p>
<p>Alles, was so nicht definierbar ist, ist demnach kein Attribut.</p>
<h3>Ende gut, alles gut?</h3>
<p>Doch gerade, als es anfing Sinn zu ergeben, bin in der DOM-Spezifikation, die den Zugriff auf HTML-Elemente von Javascript regelt, auf folgenden Satz gestoßen:</p>
<blockquote><p><a title="Property Attributes" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-642250288" target="_blank">1.6.1. Property Attributes</a></p>
<p>HTML attributes are exposed as properties on the element object.</p></blockquote>
<p>Als Entwickler bleibt der unbefriedigende Zustand, das die Begriffe Properties und Attribute je nach Kontext etwas anderes bedeuten, und manchmal sogar in verschiedenen Versionen derselben Bibliothek verschieden definiert sind</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2012/05/attribute-or-property/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails ActiveRecord: count, length oder size?</title>
		<link>http://meier-online.com/2012/03/rails-activerecord-count-length-size/</link>
		<comments>http://meier-online.com/2012/03/rails-activerecord-count-length-size/#comments</comments>
		<pubDate>Sun, 25 Mar 2012 11:34:58 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Sql]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=820</guid>
		<description><![CDATA[Die objektorientierte Datenbankschnittstelle &#8220;ActiveRecord&#8221; bietet gleich drei verschiedene Methoden zum Bestimmen der Anzahl: count(), length() und size(). Alle drei Methoden liefern das gleiche Ergebnis. Was nehmen wir wann? Warum ist es überhaupt wichtig? Nimmt man die falsche Methode, dann erzeugt unsere Ruby-on-Rails-Anwendung überflüssige Datenbankabfragen oder braucht mehr Speicher als eigentlich nötig. Die Anwendung skaliert dann [...]]]></description>
			<content:encoded><![CDATA[<p lang="de-DE">Die objektorientierte Datenbankschnittstelle &#8220;ActiveRecord&#8221; bietet gleich drei verschiedene Methoden zum Bestimmen der Anzahl: count(), length() und size().</p>
<p lang="de-DE">Alle drei Methoden liefern das gleiche Ergebnis. Was nehmen wir wann? Warum ist es überhaupt wichtig? Nimmt man die falsche Methode, dann erzeugt unsere Ruby-on-Rails-Anwendung überflüssige Datenbankabfragen oder braucht mehr Speicher als eigentlich nötig. Die Anwendung skaliert dann schlechter. Um mir die Unterschiede zwischen den Methoden leichter zu merken habe ich folgendes Schema erstellt.</p>
<p lang="de-DE"><span id="more-820"></span></p>
<p lang="de-DE"><strong>count</strong>: das lese ich als Befehl.<br />
Der Befehl wird an die Datenbank weitergegeben, die Datenbank führt dann eine SQL-Anfrage &#8220;select count(*) from &#8230;&#8221; aus.</p>
<p lang="de-DE">Diese Methode ist perfekt wenn wir wirklich nur die Anzahl wissen wollen: Es werden keine überflüssigen Daten von der Datenbank zur Anwendung geschickt, sondern nur die Anzahl zurückgegeben. Die Datenbank ist bei dieser Art von Anfragen meist auch schneller, weil sie die Anfrage nur aus ihren Index beantworten kann.</p>
<p lang="de-DE">Wenn die Daten aber schon in unserer Anwendung verfügbar sind, wird trotzdem ein Datenbankaufruf abgesetzt.</p>
<p lang="de-DE"><strong>length</strong>: eine physikalische Eigenschaft.</p>
<p lang="de-DE">Die length()-Methode liefert die Länge des Arrays (bzw, der Assoziation oder der Relation).</p>
<p lang="de-DE">Wenn die Daten schon im Speicher sind, wird die Datenbank nicht gefragt. Wir haben dann eine Datenbankanfrage gespart.</p>
<p lang="de-DE">Beispiel: wir zeigen in der View eine Tabelle mit unseren Daten, und darunter die Anzahl der Elemente. Die Daten mussten wir sowieso schon aus der Datenbank laden, deshalb wäre es Unsinn die Datenbank nochmal nach der Anzahl zu fragen.</p>
<p lang="de-DE">Wenn die Daten noch nicht in unseren Speicher sind, schlägt die Magie von ActiveRecord zu. Das Array wird befüllt (populated). Dazu wird die Datenbank nach allen Werten der betreffenden Objekte gefragt. Die Objekte werden komplett aufgebaut, mit allen Attributen, um dann durchgezählt zu werden.</p>
<p lang="de-DE">Wenn wir nur die Anzahl wissen wollen ist das natürlich unnötig. Dann ist count() besser.</p>
<p lang="de-DE">Wenn wir die Daten aber sowieso gleich brauchen ist das genau richtig.</p>
<p lang="de-DE"><strong>size</strong>: die abstraktere Version von length.</p>
<p lang="de-DE">Wenn Daten schon da sind, ruft die size() Methode intern length() auf. Wenn die Daten noch nicht da sind, ruft size() intern stattdessen die count()-Methode auf. Das klingt wie die perfekte Mischung.</p>
<p lang="de-DE">In einem Fall ist size() Methode trotzdem eine schlechte Wahl: Wenn wir die Daten kurz danach doch noch brauchen, haben wir einen überflüssigen &#8220;select count&#8221;-Datenbankaufruf erzeugt.</p>
<p lang="de-DE">
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2012/03/rails-activerecord-count-length-size/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LwUIT 1.5 erste Erfahrungen</title>
		<link>http://meier-online.com/2011/10/lwuit-1-5/</link>
		<comments>http://meier-online.com/2011/10/lwuit-1-5/#comments</comments>
		<pubDate>Sun, 09 Oct 2011 13:21:06 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JME]]></category>
		<category><![CDATA[LWUIT]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=794</guid>
		<description><![CDATA[Sun hat mit „Java Mobile Edition“ (JME) die Softwareplattform geschaffen, die weltweit auf Milliarden von Handys funktioniert. Die Plattform ist inzwischen in die Jahre gekommen, und besonders für die Gestaltung der Benutzerschnittstelle bietet Sie nur wenig, um die Möglichkeiten heutiger Handys auszunutzen. Mit LWUIT  wurde ebenfalls von Sun eine Bibliothek für die Gestaltung von Benutzerschnittstellen [...]]]></description>
			<content:encoded><![CDATA[<p>Sun hat mit „Java Mobile Edition“ (JME) die Softwareplattform geschaffen, die weltweit auf Milliarden von Handys funktioniert. Die Plattform ist inzwischen in die Jahre gekommen, und besonders für die Gestaltung der Benutzerschnittstelle bietet Sie nur wenig, um die Möglichkeiten heutiger Handys auszunutzen.</p>
<p>Mit <a title="Projekt LWUIT Startseite" href="http://lwuit.java.net/" target="_blank">LWUIT</a>  wurde ebenfalls von Sun eine Bibliothek für die Gestaltung von Benutzerschnittstellen vorgestellt. LWUIT unterstützt Touchscreens und Animationen. Ein Jahr lang konnte man zwar in dem <a title="LWUIT-Blog" href="http://lwuit.blogspot.com" target="_blank">Blog</a> eines LWUIT-Entwicklers die Weiterentwicklung verfolgen, es gab jedoch keine neuen Versionen. Ich habe schon befürchtet, dass der neue Eigentümer Oracle das Projekt ganz einschlafen lässt. Das der genannte Blog bei Google liegt und nicht bei Sun bzw. Oracle wertete ich ebenfalls als Indiz, dass das Projekt für die Firma nicht besonders wichtig zu sein scheint.</p>
<p>Anfang August 2011 ist schließlich doch noch die Version 1.5 veröffentlicht wurden.</p>
<p><span id="more-794"></span></p>
<h3>Erfahrungen beim Upgrade.</h3>
<p>Die Größe eine Handyprogramms ist immer noch ein Thema. Preiswerte oder ältere Handy haben oft Grenzen für die Größe eines Javaprogramms. Auch die Datenübertragung ist für viele Nutzer weiterhin noch nicht kostenlos.</p>
<p>Die Bibliothek war für eine JME-Bibliothek schon in Version 1.4 sehr groß, und der Umfang die Bibliothek ist nochmal gestiegen. Zum Glück entfernt der Obfuscator die unbenutzten Bibliotheksbestandteile recht effektiv. Für zwei verschiedene Programme komme ich mit allen Resourcen auf folgende Werte nach dem Umstieg von 1.4 auf 1.5:</p>
<pre>Programm A: 212kb -&gt; 245kb</pre>
<pre>Programm B: 417kb -&gt; 456kb</pre>
<p>Die Entwicklungsversion der Anwendung B mit Debuging-Informationen und ohne Obfuscator war über ein 1MB und ließ sich in der Standardeinstellung des JME-SDK nicht starten. Man kann die erlaubte Größe aber durch ändern einer Konfigurationseinstellung anpassen:</p>
<pre>Datei: jwc_properties.ini
system.jam_space = 1000000</pre>
<p>Die beiden Anwendungen ließen sich leicht upgraden. Kritisch war in der IDE Netbeans nur, wirklich alle Referenzen auf LWUIT 1.4 aus dem Projekt zu entfernen, auch in den eigenen Bibliotheken.</p>
<p>Es gab einige „Deprecation Warnings“, die leicht zu beheben waren. Der Resourceeditor hat in 1.5 sehr große Änderungen erfahren. Geändert wurde der Umgang mit den „selected“ und „pressed“ Zuständen. Hier musste man die Anwendungen im Detail überprüfen und teilweise nachbessern. Insgesamt ging die Umstellung aber problemloser als befürchtet.</p>
<h3>Mehrzeilige Elemente</h3>
<p>Aus meiner Sicht unvollständig ist immer noch die Unterstützung von mehrzeiligen Elementen. Ein Label ist zunächst mal nur einzeilig, ebenso wie ein Button, oder eine Checkbox.</p>
<p>Von den einfachen UI-Elementen kann einzig das TextArea-Eingabefeld mit mehrzeiligen Text umgehen. Immerhin lässt sich das ausnutzen:</p>
<p>Für ein einfaches mehrzeiliges Label kann man ein Eingabefeld verwenden, es auf nicht editierbar setzen und die UIID manipulieren, so dass die Stilinformationen eines normalen Labels genutzt werden:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #003399;">TextArea</span> descLabel <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">TextArea</span><span style="color: #009900;">&#40;</span>descriptionText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
descLabel.<span style="color: #006633;">setEditable</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
descLabel.<span style="color: #006633;">setUIID</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Label&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2011/10/lwuit-1-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ilias Skins</title>
		<link>http://meier-online.com/2011/07/ilias-skins/</link>
		<comments>http://meier-online.com/2011/07/ilias-skins/#comments</comments>
		<pubDate>Fri, 15 Jul 2011 11:39:43 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Ilias]]></category>
		<category><![CDATA[LMS]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=744</guid>
		<description><![CDATA[Bedarfsgerechte Anpassung eines webbasierten Lernmanagementsystems Ilias ist ein sogenanntes Lernmanagementsystem (LMS), d.h. ein System für webbasierte Bildungsangebote. Es ist ein sehr umfassendes System, das neben den Inhalten in Onlinekursen auch Kommunikationsmöglichkeiten wie Foren, Mail und Chat integriert. Beim Einsatz eines solchen Systems eines solchen Systems im Kontext einer bestehenden Organisation tritt meistens der Wunsch auf, [...]]]></description>
			<content:encoded><![CDATA[<h3>Bedarfsgerechte Anpassung eines webbasierten Lernmanagementsystems</h3>
<p><a title="Offizielle Projektwebseite Ilias" href="http://www.ilias.de">Ilias</a> ist ein sogenanntes Lernmanagementsystem (LMS), d.h. ein System für webbasierte Bildungsangebote. Es ist ein sehr umfassendes System, das neben den Inhalten in Onlinekursen auch Kommunikationsmöglichkeiten wie Foren, Mail und Chat integriert.</p>
<p>Beim Einsatz eines solchen Systems eines solchen Systems im Kontext einer bestehenden Organisation tritt meistens der Wunsch auf, die Gestaltung der Benutzeroberfläche zu verändern.</p>
<p><a href="http://meier-online.com/blog/uploads/ilias-magazin-2skins-512.png"><img class="alignnone size-full wp-image-760" title="Das Ilias-Magazin mit zwei verschiedenen Skins" src="http://meier-online.com/blog/uploads/ilias-magazin-2skins-512.png" alt="" width="512" height="305" /></a></p>
<p><span id="more-744"></span></p>
<p>Gründe hierfür sind beispielsweise:</p>
<ol>
<li>Differenzierung: Man möchte sein Angebot nicht wie jedes andere aussehen lassen.</li>
<li>Man möchte es an das eigene Coperate Design anpassen, dazu gehört das Unternehmenslogo und die Farbgestaltung</li>
<li>Konkrete Bedürfnisse der Anwender: In unserem Projekt wollen wir die Bedienung vereinfachen, in dem wir selten benutzte Optionen weglassen.</li>
<li>Vorschriften, die einzuhalten sind. Das können vorgeschriebene Benennungen sein, oder Ergonomierichtlinien für die Schriftgröße</li>
</ol>
<h3>Wie Ilias Webseiten generiert</h3>
<p><a href="http://meier-online.com/blog/uploads/Ilias-Inhaltsgenerierung-normal-512.png"><img class="alignnone size-full wp-image-748" title="Schema der Ilias Inhaltsgenerierung" src="http://meier-online.com/blog/uploads/Ilias-Inhaltsgenerierung-normal-512.png" alt="Ilias Inhaltsgenerierung mit CSS, Bildern, Templates, Sprachdateien und Datenbank" width="512" height="384" /></a></p>
<p>Eine von Ilias erzeugte Seite enthält wie andere Webseiten auch CSS-Stilvorlagen und Bilder. Zu den Bilder gehören Icons sowie Hintergründe, beispielsweise um Rahmen mit abgerundeten Ecken zu erzeugen.</p>
<p>Weder die Bilder noch die Stilvorlagen werden direkt von Ilias beeinflusst, sondern werden vom Webserver ohne Veränderung aus dem Dateisystem ausgeliefert. Der Ilias Kern selbst erzeugt die HTML-Struktur, und verwendet dafür Inhalte aus der Datenbank sowie Textfragmente aus sprachabhängigen Textdateien und baut sie mit Hilfe von Templatedateien zusammen.</p>
<p>Wollen wir die Erzeugung der Webseiten jetzt anpassen, können wir den Quelltext von Ilias selbst verändern. Bei einer neuen Version von Ilias hätten wir dann aber das Problem, die eigenen Änderungen mit den offiziellen Änderungen zusammenzuführen. Zum Glück gibt es eine Alternative:</p>
<p>Ilias bietet einen Mechanismus, die Erzeugung der Webseiten mit sogenannten Skins zu verändern, ohne dafür die Quelltexte von Ilias selbst verändern zu müssen.</p>
<p>Darüber hinaus können verschiedene Skins für verschiedene Nutzer freigeschaltet werden, oder man kann den Nutzern die Auswahl des Skins überlassen. (<a title="Ilias System Admin Handbook: Manage Skin" href="http://www.ilias.de/docu/goto_docu_pg_34282_1985.html">Siehe Beschreibung der Skin Einstellungen</a>)</p>
<h3>Was ist ein Ilias-Skin?</h3>
<p>Formal betrachtet ist besteht ein Ilias-Skin aus einem Verzeichnis. Es enthält eine Konfigurationsdatei sowie eine Menge von anderen Dateien. Diese Dateien werden von Ilias anstelle der eigenen genutzt, überschreiben sozusagen die Originaldateien.</p>
<p><a href="http://meier-online.com/blog/uploads/Inhaltsgenerierung-skin-512.png"><img class="alignnone size-full wp-image-780" title="Schema der Inhaltsgenerierung mit einem Ilias-Skin" src="http://meier-online.com/blog/uploads/Inhaltsgenerierung-skin-512.png" alt="" width="512" height="384" /></a></p>
<p>Ein Skin beeinflusst zunächst mal natürlich die Darstellung. Dies geschieht durch eigene Versionen von CSS-Stilvorlagen und von Bildern.</p>
<p>Zum Teil kann sogar die Funktionalität mit einem Skin verändert werden. Es lassen sich nämlich die zur HTML-Generierung genutzten Templates im eigenen Skin überschreiben.</p>
<p>Trotzdem hat man als Autor eines Skins nicht immer die volle Kontrolle. Teile des HTML-Codes werden von den Ilias-Kernsystem selbst erzeugt und lassen sich nur durch Änderung am Quelltext verändern. Das betrifft insbesondere die Struktur von Eingabeformularen.</p>
<p>Auch die Texte wie beispielsweise die Beschriftungen von Buttons gehören nicht zum Skin. Die können statt dessen mit einer eigenen Sprachdatei unabhängig vom Skin verändert werden.</p>
<p>Details, wie man eigene Skins erstellt, lesen Sie demnächst in zweiten Teil dieser Artikelserie.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2011/07/ilias-skins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eins plus Zwei</title>
		<link>http://meier-online.com/2010/12/one-plus_two/</link>
		<comments>http://meier-online.com/2010/12/one-plus_two/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 17:42:11 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Fallen]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Typumwandlung]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=726</guid>
		<description><![CDATA[Eine Überraschung in Ruby. Selbst bei so etwas einfachen wie der Addition von Zahlen gibt es manchmal Überraschungen. Doch der Reihe nach. Wenn wir den interaktiven Ruby-Interpreter &#8220;irb&#8221; starten, können wir in als einfachen Rechner nutzen. irb&#62; 1+2 =&#62; 3 So weit so praktisch. In der Programmierpraxis liegen Zahlen häufig als String vor, z.B in [...]]]></description>
			<content:encoded><![CDATA[<h3>Eine Überraschung in Ruby.</h3>
<p>Selbst bei so etwas einfachen wie der Addition von Zahlen gibt es manchmal Überraschungen. Doch der Reihe nach. Wenn wir den interaktiven Ruby-Interpreter &#8220;irb&#8221; starten, können wir in als einfachen Rechner nutzen.</p>
<pre>irb&gt; 1+2
=&gt; 3</pre>
<p>So weit so praktisch. In der Programmierpraxis liegen Zahlen häufig als String vor, z.B in Textdateien oder als Formularparameter in Webseiten. Probieren wir also folgendes:</p>
<pre>&gt; input="1"
&gt; input+2
TypeError: can't convert Fixnum into String</pre>
<p>Richtig, wir müssen in Ruby erst explizit den String in einen Integer umwandeln. Dafür gibt es die Methode to_i</p>
<pre>&gt; input.to_i+2
=&gt; 3</pre>
<p>Ok, damit es etwas besser aussieht, fügen wir ein Leerzeichen ein</p>
<pre>&gt; input.to_i +2
=&gt; 1</pre>
<p>Huch? Was war das? Ist unsere Variable vielleicht überschrieben worden? Probieren wir es mal direkt:<br />
<span id="more-726"></span></p>
<pre>&gt;"1".to_i+2
=&gt; 3</pre>
<pre>&gt;"1".to_i +2
=&gt; 1</pre>
<p>Bei einen Leerzeichen vor dem Pluszeichen und keinem Leerzeichen nach dem Pluszeichen gibt es ein anderes Ergebnis. Wo kann dieses Ergebnis herkommen? Probieren wir andere Zahlen:</p>
<pre>&gt;"2".to_i +2
=&gt; 0</pre>
<p>Es wird immer rätselhafter!</p>
<pre>
&gt; "1".to_i +1
ArgumentError: illegal radix 1
</pre>
<p>Aha, es gibt eine Spur. Vielleicht schaut wir uns die Dokumentation der Methode &#8220;to_i&#8221;genauer an:</p>
<p><a title="Dokumentation Ruby String Klasse" href="http://ruby-doc.org/core/classes/String.html#M000787">http://ruby-doc.org/core/classes/String.html#M000787</a></p>
<p>Die Methode to_i hat demnach einen optionalen Parameter Namens &#8220;radix&#8221;. Der String kann als Zahl im Hexadecimal-, Decimal, Octal- oder Binärsystem interpretiert werden.</p>
<p>Weiter steht dort momentan: &#8220;This method *never* raises an exception.&#8221; Also soll die Methode, falls sie auf Grund von unerlaubten Eingaben zu Fehlern führt, immer 0 liefern, und niemals eine Exception erzeugen. Gut, wenn das so exakt dokumentiert ist. Leider ist die Aussage so nicht richtig, denn der ArgumentError ist schließlich auch eine Exception.</p>
<p>Wie hilft uns dies jetzt, das eigenartige Verhalten zu erklären? In Ruby kann man die Klammern auch bei einen Funktionsaufruf weglassen. Offenbar macht unser Rubyinterpreter aus:</p>
<pre>"1".to_i +2</pre>
<pre>"1".to_i( +2 ) =&gt; "1".to_i( 2 ) =&gt; 1</pre>
<p>Der String &#8220;1&#8243; wird als Binärzahl interpretiert, und liefert dann die Zahl 1. Eine Addition findet nicht mehr statt. So lässt sich auch erklären:</p>
<pre>"2".to_i(+2) = 0</pre>
<p>Ruby versucht den String &#8220;2&#8243; als Binärzahl zu interpretieren. Das geht nicht, weil Binärzahlen nur aus 0 und 1 bestehen. Ruby liefert dann wie dokumentiert einfach eine 0 zurück.</p>
<p>Insgesamt bleibt dabei ein ungutes Gefühl: Selbst bei einer einfachen Addition kann durch hinzufügen oder weglassen von Leerzeichen aus einen korrekten Programm ein Falsches werden. Leider der Preis, den man in Ruby  für den Verzicht auf Klammern zahlen muss. In diesen Fall ermöglicht  der optionale Parameter der Methode &#8220;to_i&#8221; diese Mehrdeutigkeiten. Optionale Klammern in Zusammenspiel mit optionalen Parametern sind leider eine gefährliche Kombination.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2010/12/one-plus_two/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mehrsprachige Webseiten mit Ruby on Rails (3)</title>
		<link>http://meier-online.com/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/</link>
		<comments>http://meier-online.com/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 10:02:16 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Mehrsprachigkeit]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=656</guid>
		<description><![CDATA[Teil 3 &#8211; Qualitätssicherung Texte gehören zu den Teilen einer Anwendung, die häufig geändert werden. Wenn dann noch externe Übersetzer im Spiel sind, kann es leicht zu fehlenden Übersetzungen kommen Wir möchten deshalb automatisch testen, dass es zu allen Texten in Sprache A auch Übersetzungen in Sprache B vorhanden sind. Ein solcher Test allein hilft [...]]]></description>
			<content:encoded><![CDATA[<p>Teil 3 &#8211; Qualitätssicherung</p>
<p>Texte gehören zu den Teilen einer Anwendung, die häufig geändert werden. Wenn dann noch externe Übersetzer im Spiel sind, kann es leicht zu fehlenden Übersetzungen kommen</p>
<p>Wir möchten deshalb automatisch testen, dass es zu allen Texten in Sprache A auch Übersetzungen in Sprache B vorhanden sind. Ein solcher Test allein hilft schon sehr, und sollte ja nicht so schwierig sein.<br />
<span id="more-656"></span></p>
<p>Leider gibt es dabei eine Überraschung: in der Internationalisierung-API findet sich zur Zeit (Rails 2.3.5) keine Möglichkeit, alle Schlüssel aufzuzählen (sprich iterieren). Man muss also offenbar die Yaml-Dateien selbst einlesen, um an die Menge aller definierten Schlüssel zu kommen. Unserer Test wird dabei leider abhängig von der konkreten Art der Datenhaltung.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">texts_hash = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'config/locales/de.yml'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Wie haben nun einen rekursiven Hash. Um alle Schlüssel zu überprüfen, extrahieren wie sie mit einer gesonderten Funktion. Diese Funktion ist einfach rekursiv aufgebaut.<br />
<img src="http://meier-online.com/blog/uploads/rails-i18n-hash.png" alt="Extrahieren der Schlüssel aus einen verschachtelten Hash" title="rails-i18n-hash" width="400" height="240" class="alignnone size-full wp-image-670" /></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> deep_hash_key<span style="color:#006600; font-weight:bold;">&#40;</span>hash, prefix<span style="color:#006600; font-weight:bold;">&#41;</span>
  hash.<span style="color:#9900CC;">keys</span>.<span style="color:#9900CC;">sort</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>key2<span style="color:#006600; font-weight:bold;">|</span>
    val = hash<span style="color:#006600; font-weight:bold;">&#91;</span>key2<span style="color:#006600; font-weight:bold;">&#93;</span>
    newprefix = prefix.<span style="color:#0000FF; font-weight:bold;">nil</span>? ? key2 : <span style="color:#996600;">&quot;#{prefix}.#{key2}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> val.<span style="color:#9900CC;">is_a</span>? <span style="color:#CC00FF; font-weight:bold;">Hash</span>
     deep_hash_key<span style="color:#006600; font-weight:bold;">&#40;</span>val, newprefix<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      newprefix
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Wollen wir jetzt die Übersetzungen für alle Schlüssel prüfen lauert die Zweite Falle: Wenn die Übersetzung eine Variableninterpolation enthält, erhalten wir einen Fehler beim Aufrufen der translate() Methode ohne den passenden Hash. Offenbar liefert uns die API auch keinen Zugriff auf den String ohne Interpolierung. Da uns in diesen Test nur die Existenz einer Übersetzung interessiert, und nicht ihr konkreter Wert, fangen wir die Exception &#8220;MissingInterpolationArgument&#8221; einfach auf.</p>
<p>Für eine deutsche Anwendung mit Übersetzungen in Englisch und Französisch sieht dann der Test so aus:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> test_all_texts_should_exists
  texts_hash = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'config/locales/de.yml'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  de_keys = deep_hash_key<span style="color:#006600; font-weight:bold;">&#40;</span>texts_hash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'de'</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">flatten</span>
  <span style="color:#9966CC; font-weight:bold;">for</span> lang <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'de'</span>, <span style="color:#996600;">'fr'</span>, <span style="color:#996600;">'en'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    I18n::locale = lang
    <span style="color:#9966CC; font-weight:bold;">for</span> key <span style="color:#9966CC; font-weight:bold;">in</span> de_keys
      <span style="color:#9966CC; font-weight:bold;">begin</span>
        val = I18n.<span style="color:#9900CC;">translate</span><span style="color:#006600; font-weight:bold;">&#40;</span>key, <span style="color:#ff3333; font-weight:bold;">:default</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span>, :<span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">I18n::MissingTranslationData</span>
        val = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">I18n::MissingInterpolationArgument</span>
        val = <span style="color:#0000FF; font-weight:bold;">true</span>  <span style="color:#008000; font-style:italic;"># there was a value, only an argument is missing</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      assert_not_nil<span style="color:#006600; font-weight:bold;">&#40;</span>val, <span style="color:#996600;">&quot;key missing for locale #{lang}: #{key}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Wenn jetzt eine Übersetzung fehlt, liefert der Test eine Fehlermeldung der Art:</p>
<pre>
test_all_texts_should_exists(LocalisationTest): key missing for locale en: users.edit.title</pre>
<p>Die fehlende Übersetzung können wir dann ergänzen, bevor wir eine neue Version der Anwendung veröffentlichen. </p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Classics reloaded: Das Assert-Makro von C</title>
		<link>http://meier-online.com/2009/09/assert/</link>
		<comments>http://meier-online.com/2009/09/assert/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 14:41:43 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Assert]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Qualitätswerkzeug]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=618</guid>
		<description><![CDATA[Die erste Version des folgenden Textes stammt noch aus dem Jahr 1996. Er enstand, weil ich bei den damaligen Arbeitgebern beobachtete, dass viele C-Entwickler nicht wussten, was es mit assert() auf sich hat. Hier kommt die Wiederveröffentlichung: Selbstidentifizierende Fehler Es gibt in ANSI-C einen Mechanismus, viele Fehler auch ohne Debugger aufzuspüren: Das Assert Macro. Ein [...]]]></description>
			<content:encoded><![CDATA[<p>Die erste Version des folgenden Textes stammt noch aus dem Jahr 1996. Er enstand, weil ich bei den damaligen Arbeitgebern beobachtete, dass viele C-Entwickler nicht wussten, was es mit assert() auf sich hat. Hier kommt die Wiederveröffentlichung:</p>
<h3>Selbstidentifizierende Fehler</h3>
<p>Es gibt in ANSI-C einen Mechanismus, viele Fehler auch ohne Debugger aufzuspüren: Das Assert Macro. Ein Teil des Problems liegt in Deutschland wohl auch im Namen: Assert ist ein Wort, welches im allgemeinen im Englisch an der Schule nicht benutzt wird.</p>
<p><span id="more-618"></span>Meine Übersetzung hierfür lautet Zusicherung. Das Assert Macro prüft diese Zusicherung, und druckt, falls es schief geht, seine eigene Datei mit Zeilennummer im Quelltext aus. Ein Beispiel:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> readFile<span style="color: #009900;">&#40;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> filename
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> buffer
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> filehandle<span style="color: #339933;">;</span>
    assert<span style="color: #009900;">&#40;</span> filename <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    assert<span style="color: #009900;">&#40;</span>strlen<span style="color: #009900;">&#40;</span>filename<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    assert<span style="color: #009900;">&#40;</span>strlen<span style="color: #009900;">&#40;</span>filename<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> MAX_FILENAMELEN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    filehandle <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span>filename<span style="color: #339933;">,</span> READ_ONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ...
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Falls jetzt irgend jemand meine Funktion mit falschen Parametern aufruft, z.B. mit einem leeren String, passiert während des Programlaufes folgendes:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">assertion failed in file readfile.c, line 34:
strlen(filename) &gt; 0
program aborted</pre></div></div>

<p>Der Tester, wer immer das ist, kann in der angegebenen Datei die Zeile aufspüren, in der der Fehler auftrat, und erfährt dann, dass die Funktion readFile mit einem Leerstring aufgerufen wurde. Oft hat man damit schon die Fehler gefunden, in den anderen Fällen hat man zumindestens einen Anhaltspunkt.</p>
<p>Frage: <em>Sollte man nicht eine wasserdichte Fehlerbehandlung machen?</em></p>
<p>Welcome to Reality! Die obige Lösung ist ein Einzeiler. In der Praxis bedeutet dieses: Ein assert() schreibt man auch hin, wenn man meint, das ein bestimmter Fall in der Praxis nie und nimmer auftreten wird. Im obigen Beispiel ist der Programmierer der Aufruffunktion dazu verflichtet, der Funktion einen Buffer zur Verfügung zu stellen. Wenn der Buffer bei NULL liegt, hat er Mist gemacht. Bei der Länge des Filenames kommt es auf die Anwendung an: Falls hier ein vom Endbenutzer eingegebener String direkt benutzt wird, ist die assert Lösung allenfalls während der Prototypphase erlaubt.</p>
<p>Die Fehler, von denen man damit rechnet, dass sie während des normalen Betriebes auftreten, sollte man selbstverständlich auch korrekt abfangen.</p>
<p>Das Assert hat auch seinen Sinn, wenn es nicht feuert: Bei einer Fehlersuche kann ich sicher sein, dass ein bestimmtes Problem nicht aufgetreten ist, dass ich den Fehler also woanders suchen muss.</p>
<p>Nicht zuletzt teile ich den armen Leuten, die mein Programm einmal warten müssen, etwas über meine Intention mit: Der Pointer darf kein NULL-Pointer sein, der Dateiname soll weniger als X Buchstaben haben, &#8230; Das alles kann man auch in die Kommentare schreiben, aber nur Code lügt nicht.</p>
<p>Frage: <em>In C++ und Java gibt es doch den Exception Mechanismus.</em></p>
<p>Ja der ist oft noch besser, aber leider auch noch etwas komplizierter. Vieles, was ich gesagt habe, läßt sich auch auf diesen Mechanismus übertragen. Leider kann man sich auch nicht immer aussuchen, in welcher Sprache man programmiert.</p>
<p>Frage: <em>Wenn diese Fehlermeldung dann im laufenden Betrieb beim Kunden auftritt, ist das doch eher peinlich. Und das Programm wird doch bestimmt größer und langsamer? Das heisst doch, nacher muß ich alle asserts() wieder rausnehmen?</em></p>
<p>Zum Glück nicht! Das Assert läßt sich durch einen Compilerschalter aktivieren oder deaktivieren. Wenn in irgendeiner Headerdatei steht:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define NDEBUG</span></pre></div></div>

<p>oder in der Makedatei:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">-DNDEBUG</pre></div></div>

<p>so wird für das Assert kein Code erzeugt, so als ob man alle assert Zeilen rausediert hätte.</p>
<p>Frage: <em>Wie funktioniert das eigentlich?</em></p>
<p>Das Geheimnis liegt im Zusammenspiel von Preprocessor und Compiler. Das Assert ist als Macro implementiert, im allgemeinen in der Datei assert.h. Das Grundgerüst ist folgendes:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#ifdef NDEBUG</span>
<span style="color: #339933;">#define assert(exp)</span>
<span style="color: #339933;">#else</span>
<span style="color: #339933;">#define assert(exp) \
 ( (exp) ? (void) 0 : _assert(#exp, __FILE__, __LINE__))</span>
<span style="color: #339933;">#endif</span></pre></div></div>

<p>Das sieht doch reichlich kryptisch aus, ist jedoch gar nicht so kompliziert: Macros sind Textersetzer. Mittels #ifdef&#8230;#else&#8230;#endif wird dafür gesorgt, das nur Code erzeugt wird, falls das Symbol NDEBUG nicht definiert ist. Dann wird nämlich assert zusammen mit seinen Argument durch einen leeren String ersetzt, der Compiler bekommt die betreffenden Zeilen nicht einmal zu Gesicht. Im Debugfall setzt der Compiler die Wörter __FILE__ und __LINE__ durch die aktuelle Quelldatei (nicht iassert.h, sondern die Datei der Aufrufstelle) und die aktuelle Zeilennummer. Der Ausdruck #exp wird durch den aktuellen Ausdruck als String ersetzt.</p>
<p>Die eigenartige Klammerstruktur (xxx ? yyy : zzz) gehört zum normalen C Sprachumfang, wird jedoch von wohlerzogenen Programmierern nur in Ausnahmefällen wie diesen verwendet. Es ist etwas wie ein verkürztes if-statement. Die Backslashes am Ende der Zeile verlängern die Zeilen, da der Macromechanismus ausschließlich zeilenorientiert arbeitet. Insgesamt erzeugt der Preprozessor aus der Zeile</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">assert<span style="color: #009900;">&#40;</span>strlen<span style="color: #009900;">&#40;</span>filename<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>die Zeile</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>strlen<span style="color: #009900;">&#40;</span>filename<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">:</span> _assert<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;strlen(filename &gt; 0&quot;</span><span style="color: #339933;">,</span> __FILE__<span style="color: #339933;">,</span> __LINE__<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Die tief im Inneren einer Library definierte Funktion _assert() gibt die Argumente, z.B. mit printf(), auf den Bildschirm aus und bricht das Programm ab.</p>
<p>Frage: <em>Alles schön und gut, aber ich programmiere mit einem Fenstersystem, manchmal programmiere ich auch Anwendungen ganz ohne Bildschirm. Was nun?</em></p>
<p>Viele Benutzer haben Glück: In einigen Entwicklungsumgebungen gibt es ein assert(), das ein Pop-up-Fenster öffnet. Ansonsten lohnt es sich für solche Fälle, ein assert-Macro selbst zu schreiben.  Das prinzipielle Vorgehen ist dabei, eine Ausgabefunktion zu schreiben, die die betreffende Ausgabe irgendwohin ausgibt, die Datei assert.h zu kopieren und statt des _assert die eigene Ausgabefunktion aufzurufen. Die Ausgabe kann in eine Logdatei, über die Soundschnittstelle, als Email, als Fax, oder als was auch immer erfolgen.</p>
<p>Ähnlich ist auch in anderen Programmiersprachen zu verfahren. Meistens bieten die Hersteller irgendeine Entsprechung zu __FILE__ und __LINE__ an, selbst wenn es nicht im offiziellen Sprachstandard ist.</p>
<p>Frage: <em>Das ist ja toll, was man mit Macros alles machen kann, ich habe da gerade eine Idee &#8230;</em></p>
<p>Vorsicht: Wer Macros einsetzt, nur um ein paar Zeilen Code zu sparen, wird es irgendwann bitter bereuen.</p>
<p>Ich habe mal bei einer Firma ein Macro entdeckt, das dazu dienen sollte, Teile eines Records in einen anderen zu kopieren. Dieses Macro war schon mehrere Jahre bei dieser Firma im Einsatz, leider war es nur manchmal korrekt. Ich habe mit mehreren anderen Entwicklern lange vor dem Macro gesessen, um herausfinden, was es eigentlich tat. Es arbeitete ganz gut. Je nach dem, mit welchem Record man es aufrief, überschrieb es jedoch einen verbotenen Speicherbereich. Das Macro war bestimmt für etliche Abstürze verantwortlich, auch bei ausgelieferten Systemen. Die Firma war übrigens kurze Zeit später pleite &#8230;</p>
<h3>Zurück ins Jahr 2009</h3>
<p>Im Jahr 2009 werden Assert-Methoden oft in Unit-Tests verwendet. Dagegen ist auch nichts einzuwenden. Beim vorliegenden Text ging es mir aber um etwas anderes: die Verwendung von Assert im Programmtext selber. Diese Asserts können auch bei unerwarteten Fehler helfen. Sie sind auch allgemeiner: Sie prüfen Aussagen über das Programm, die immer gelten sollen, nicht nur bei bestimmten Testdaten. Asserts im Programmtext selbst sind deshalb auch bei Nutzung von Unittests nützlich.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2009/09/assert/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

