Bin ich noch null oder was?

24. September 2008

Da ich ja wieder mit einem Code-Review “beauftragt” wurde, mussten ja wieder Dinge für Coding-Horror abfallen. So wie auch folgendes kleines C# Konstrukt. Habe wieder alles Unnötige weggelassen. Man betrachte folgende kleine Klasse:

Image

Die Klassenvariable obj wird zuerst mit null initalisiert. Im Konstruktor wird dann überprüft, ob obj schon auf ein Objekt referenziert und wenn nicht, wird eine Instanz angelegt. Wenn wir mal in die C#-Language-Spezifikation sehen, steht dort was beim Instanziieren einer Klasse (Referenced-Type) passiert.

- A new instance of class T is allocated. If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.

- All fields of the new instance are initialized to their default values (§?5.2).

- The instance constructor is invoked according to the rules of function member invocation (§?7.4.3). A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor as this.

Gehen wir also davon aus, das wir genug Speicher hatten und das Objekt tatsächlich angelegt werden konnte. Dann kann man dort nachlesen, das zuerst die Membervariablen (Fields) initialisiert werden. Das heisst in unserem Beispiel, das die Variable obj mit null Initialisiert wird (was auch defaultmässig passieren würde, wenn man das “= null“ weglässt) bevor der Konstruktor aufgerufen wird. Danach folgt gleich der Konstruktoraufruf. Dort wird dann auf null überprüft, was obj wie wir ja jetzt wissen “zwingend” sein muss. Somit ist diese Überprüfung im Konstruktor völlig seinfrei.

Die Initalisierung von obj kann also direkt in der Klasse erfolgen:

Dieses vorgehen hat aber einen Haken. Wenn die anzulegende Klasse (hier object) eine Exception schmeisst und diese in der eigenen Klasse (ObjectMania) abgefangen werden soll. Dann muss die Instanziierung im Konstruktor erfolgen:

Abschliessend nochmal zur Frage, ob es sinvoll ist obj mit null vorzubelegen. Im Prinzip wäre es egal, da alle neue Referenzen den Wert null haben. Von Microsoft wird jedoch empfolen, Variablen stets mit einem Defaultwert zu initalisieren (MCTS Kurs: 70-536).

If und If gesellt sich gern

09. April 2008

Heute ist mir bei einem Code-Review wieder ein kleines Schmankerl unter die Augen gekommen.
Wie immer reduziere ich es auf das Wesentliche…

Der Aufbau war wie folgt:

if( A )
{
    a;
}
if( !A )
{
    b;
}
else
{
    c;
}

Als kleine Denksportaufgabe, könnte Ihr euch ja mal RatzFatz überlegen, wie das wohl einfacher geht… Und wenn Ihr eine Idee habt, einfach den ganzen Artikel anschauen…

Weiterlesen »

Pseudodynamsicher l-value

29. November 2007

Ein System kann man ja nur von Innen heraus zerstören, deshalb habe ich mir überlegt wie ich zurückschlagen kann. Wenn ich die Menschen schon nicht dazu bringen kann, über ihren eigenen Code nachzudenken, so muss ich sie wenigstens dazu bringen sich über meinen Gedanken zu machen :-)

Mir ist aufgefallen, das viele Programmierer den “tertiären”-Operator ?: überhaupt nicht mögen. Ich finde richtig eingesetzt, ermöglicht er an vielen Stellen einfach schöneren und auch lesbareren Code. Aber da ja eine Aversion gegen diesen Operator zu herrschen scheint, habe ich mir ihn für die ersten Gegenschläge zum “Freund” gemacht #grins#

Folgendes kleines Konstrukt habe ich mir ausgedacht:

iTo < iLastTo ? iTo : iTi += fPrecision ? pi_i64SlaveRaster : pi_i64NetRaster;

Na was macht diese kleine Programmzeile? Ist doch nicht so schwer, oder? :-)

Weiterlesen »

this kann doch nicht sein…

14. Juni 2007

Von einem Arbeitskollegen habe ich folgendes kleines Schmuckstück erzählt bekommen, welches ich zum besseren Verständnis einfach mal in ein kleines, kurzes und zusammenhängendes Beispiel gegossen habe:

class MeineKlasse
{
public:

void set( int x )
{
if( this == NULL ) throw new ArgumentNullException();
this.x = x;
}

private: int x;
};

Zu dieser Originalität fällt mir nichts ein, was ich darauf noch sagen könnte…

Wenn “de Morgan” leise graut…

24. Mai 2007

Heute bin ich in unserem Quellcode auf folgendes Schuckstück gestoßen:

if( x1 >= x2 || ( !( x1 < x2 || y1 < y2 ) && z1 >= z2 ) )
{
// Do other very crazy stuff
}

Als ich dies gelesen habe, hat mich sofort ein komisches Gefühl beschlichen ohne sofort zu wissen warum (Intuition?). Dann habe ich den Ausdruck mal näher untersucht.

Zuerst habe ich mal !( x1 < x2 || y1 < y2 ) aufgelöst.
Nach den Gesetzen von De Morgan ist !( A || B ) = !A && !B. Das ergibt:

!(x1<x2) && !(y1<y2)

Wenn jetzt x1<x2 bzw. y1<y2 wahr ist, so ist x1>=x2 bzw. y1>=y2 falsch. Daraus folgt:

!( x1 < x2 || y1 < y2 ) == x1 >= x2 && y1 >= y2

Dies setzen wir wieder in die gesamte Logikgleichung ein:

x1 >= x2 || ( x1 >= x2 && y1 >= y2 && z1 >= z2)

Dies entspricht dem Boolschen Ausdruck A || ( A && B && C ). Wenn A also true ist, ist perse der ganze Ausdruck wegen der Veroderung mit A true. Ist A false, so kann der ganze Ausdruck nur noch true werden, wenn A && B && C true wird. Da A in diesem Fall aber false ist, ist A && B && C auch immer false. Somit entspricht dieser Ausdruck einfach A.

Dies bedeutet, die obige if Anweisung kann auf folgende reduziert werden:

if( x1 >= x2 ) {…}

Unless – if mal anders

21. Mai 2007

Es gibt große Firmen, bei denen etwas nur perfekt ist, wenn möglich viel Funktionalität in die Software gekloppft wird. Dies artet auch schonmal in diversen Allmachts- und Weltherschaftsgedanken aus. Ich bin jedoch der Ansicht, etwas ist erst dann perfekt wenn man bei gleichbleibener Funktion nichts mehr weglassen kann. Einige Kollegen meiner Zunft sehen dies ähnlich und bemühen sich die Code-Massen in Zaun und übersichtlich zu halten. Aus diesem Grund enstehen z.B. in diversen Programmiersprachen neue Schlüsselwörter. Eines dieser Schlüsselwörter ist in der Sprache Perl entstanden: unless

Die Funktionsweise ist schnell erklärt: unless ist eine negierte if Abfrage. Sie ist aus der Idee enstanden, das Fehlerbehandlungen in der Regel durchgeführt werden, wenn eine Aktion fehlgeschlagen ist. Mit einer if Abfrage muss dann im Normalfall die Fehlerabfrage erneut negiert werden um in den entsprechenden Anweisungsblock zu verzweigen.
Beispiel:

if( ! FileExist(”test.txt”) )
{
// Fehlerbehandlung
}

Mit Hilfe des unless Schlüsselwortes, kann dies noch ein quäntchen Schöner formuliert werden:

unless( FileExist(”Test.txt”) )
{
// Fehlerbehandlung
}

Bei dieser Formulierung kann nun nichts mehr weggelassen werden und ist somit in meinen Augen “perfekt”.

Warum komme ich darauf? Es gibt einige Zeitgenossen die sich auch für eine unless Schreibweise erwärmen können, auch wenn dieses Schlüsselwort nicht existiert. Denn folgendes Programmkonstrukt habe ich neulich entdeckt:

if( FileExist(”test.txt”) ); else
{
// Fehlerbehandlung
}

Dieses Konstrukt ist sehr unschön, da es den natürlichen “Lesefluß” unterbricht. Ist man der Meinung, dass dieses Vorgehen eine Bereicherung für die Quelltextqualität ist, so sollte man an “zentraler” Stelle eines der beiden folgenden Makros definieren:

#define unless( arg ) if( arg ); else

oder

#define unless( arg ) if( ! ( arg ) )

Es wäre auch eine gute Idee dieses Vorgehen in den Programmierrichtlinien festzuhalten. Überredet man nun noch seinen Editor unless als Schlüsselwort anzuzeigen, hat man eine ziemliche Bereicherung für einfache Fehlerfälle.

Was man aber dann tunlichst vermeiden sollte ist, einen else Zweig an seine unless Abfragen anzuhängen. In solchen Fällen ist wegen der Lesbarkeit stets eine if Abfrage zu verwenden.

Ihr Postfach ist voll

02. Mai 2007

Als ich heute mein Postfach checkte, erhielt ich die Meldung das mein “Postfach auf dem Server voll” sei! Bei quotierten Exchange-Postfächern natürlich keine Seltenheit. Diese eMail hatte ich aber 27 mal in meinem Postfach. Da stellen sich mir mehrere Fragen:

  1. Kann das Postfach schon voll gewesen sein, wenn noch 27 mal diese Warnungsmail reinging?
  2. Wird das Postfach automatisch “leerer”, wenn man diese eMail häufiger verschickt?
  3. Verschickt mein Unternehmen soviel “unnötige” eMails, das eine wichtige Botschaft nur durch Häufigkeit Beachtung findet?
  4. Wieviel Prozent der eMails die ich pro Tag bekomme, kann ich ungelesen löschen ohne das es jemand merkt?
  5. Warum gibt es keine Kriesenbegrenzungsexceltabelle, wo ich nachlesen kann ab welchem Datum mein Postfach höchstwahrscheinlich die Grenze seiner Kapazität im Begriff ist zu “sprengen”?
  6. Warum habe ich jetzt das dumpfe Gefühl, das genau Punkt 5 umgesetzt wird, wenn das einer meiner “Entscheider” hier liest?

Es gab ein Fehler im ganzen eMail-Konzept. Und zwar das diese nix kosten. Jede eMail sollte von Hause aus pro Empfänger immer 1 Cent kosten. Privat sinds pro Monat vielleicht ein paar Euro. Aber die sämtlichen firmeninternen Spammails würden stark reduziert. Alle lästern über Spam, aber auch hier sitzt der Feind häufig nicht ausserhalb des Systems…

Das Management

18. April 2007

Das Management

Steckt ein Projekt mal in der Kriese,
schreibt die Buchhaltung nur noch miese,
muss vieles Überdacht,
und es oft auch über Nacht,
optimiert oder gar verbessert werden.
Um das Projekt nicht zu gefährden.
Was natürlich offensichtlich ginge,
wenn viele dieser “kleinen” Dinge,
die man blind und taub erträgt,
mit einer Verbesserung erschlägt.
Auch viele der komplexen Sachen,
würden kaum noch ärger machen,
wenn man kühl mit Sachverstand,
die Probleme löst: Hand in Hand!
Doch Änderungen werden nicht pragmatisch umgesetzt,
nein, es wird sich erstmal hingesetzt.
Und ganz alleine mit sich selbst wird dieser Wechsel,
durchgeplant mit Powerpoint, Project und mit Excel.
Mit diesem Dreigestirn der Hölle,
gelingt es auf die schnelle,
sämtliche Probleme kleinzuklicken,
bis sie an sich selbst ersticken.
Um die Durchsicht zu erschweren,
wird man auch die Abkürzungen stark vermehren.
Terminologien werden neu erfunden,
und man denkt: Das Problem ist nun verschwunden.
Und in einer dieser tausend Excellisten,
wird es fortan nun sein dasein fristen.
Doch was die Führungskraft sich ausgedacht,
hat selten den Erfolg gebracht.
Und kein Mensch blickt fortan mehr:
Wo kommen die Probleme her?
Nun ist das Problem verlagert,
ausgedörrt und abgemagert,
totgeschwiegen und verbannt,
doch ungelöst und wohlbekannt.
Doch kommt der Tag wo dies erkannt,
das er nur ein neuen Namen für das Problem erfand,
wird die Führungskraft sich nicht bequemen
die Verantwortung dafür zu übernehmen.
Nein vielmehr wird beklagt und angemahnt,
das alles was man da so wohl geplant,
mutwillig von allen anderen sabotiert
und nicht nach Plan entwickelt wird.
Dies wird dann auch annerkannt,
denn niemand, auch jene mit Verstand,
haben je begriffen, was diese Listen sagten
und fühlen sich schuldig weil sie nicht fragten.
Und jener der den Manager nun richtet,
ist sich selbst sehr wohl verpflichtet.
Denn ein Urteil über diese Führungskraft,
auch ein Präzendenzfall gegen ihn selber schafft.
Eine Krähe hackt der anderen kein Auge aus,
drum kommt er ohne Konsequenz da raus.
Um bestätigt und dadurch mit gestärkter Kraft,
er stetig neuen, größeren Bockmist schafft.
Und die Moral von dem Gedicht:
Gemanagte Problemlösungen gibt es nicht!
Doch managende Probleme sind sehr häufig,
dies ist uns allen sehr geläufig!

Marcell Kluth

&& geht sogar in if(…)

15. März 2007

Dieser Beitrag ist wieder vom “Ist doch klar, sowas macht doch keiner”-Typus. Leider sieht die Sache ganz anders aus. Folgendes sehe ich JEDEN Tag häufiger:

ififif 1

Ganz schlaue Experten gehen sogar einen Schritt weiter und optimieren die Klammern weg, weil es Tipparbeit spart und “sinniger” erscheint:

ififif 2

Ich weiss nicht wie es anderen “Durchschnittsprogrammierern” geht wenn sie so etwas sehen, ich jedenfalls habe das Gefühl das sich meine Retina ablöst… Für alle die noch nicht gesehen haben, warum dies Augenkrebs verursachen kann, hier nochmal der Hinweis: Es gibt für logische Ausdrücke Boolsche-Operatoren. Jede Programmiersprache hält ein paar griffige bereit. Die Untermenge postuliere ich jetzt einfach mal auf UND, ODER und NICHT! In C/C++/C# werden sie mit &&, || bzw. ! ausgeschrieben. Eine saubere Formulierung dieser Abfrage wäre somit:

ififif 3

Eine Ausrede die ich diesbezüglich nicht mehr hören kann ist: Ja, früher hat ja in den if’s noch mehr dringestanden. Das ist dann alles nach und nach rausgefallen. DAS IST KEINE AUSREDE! DAS IST BULLSHIT! Wenn ich etwas aus/in einer if (oder sonstwo) lösche/ändere/hinzufüge, habe ich nicht nur das Privileg sondern auch die hoheitliche Pflicht sich den umgebenen Quellcode anzuschauen. Und sollte ich durch meine Änderungen ein solches Konstrukt “hinterlassen”, bin ich nicht besser als jener, der sowas initial in die Tastatur rotzt.

ANSI-C – Darf ich alles?

15. März 2007

Dieser kleine Beitrag soll verdeutlichen, auch wenn ein ANSI-C Compiler Quellcode fehlerfrei übersetzt, es noch lange nicht heisst, dass die Ergebnisse immer vorhersagbar sind. Dazu betrachten wir die folgende, vermutlich aus ästhetischen Gründen entstandene Anweisung (x sei mal 1):

y = x++ + ++x;

Was könnten wir nach dieser Anweisung in y erwarten? Wir könnten zum Einen von links nach rechts durchgehen und sagen: x ist erst 1, also steht schonmal 1 + ++x dort. Das ++x wird aber vor der Addition erhöht, also ist es schon 2. Somit erwarten wir 1 + 2 = 3. x wird danach nochmal hochgezählt und hätte nach dieser Anweisung 4.

Zum Anderen könnten wir aber auch sagen, dass das x vor dem gesamten Ausdruck inkrementiert wird. Also hätten wir 2 + 2 = 4 für y. Und x wäre nachher sogar 5.

Dies verdeutlicht, obwohl diese Anweisung von jedem ANSI-C Compiler übersetzt werden kann, kann Ergebnis nicht vorhergesagt werden. Solche Sonderfälle werden in diesen Standards nicht aufgeführt, da es viel zu viele wären. Der Programmierer hat dafür zu sorgen, das dem Compiler klipp und klar ist, was von ihm erwartet wird. Solche Fehler können auch noch Unscheinbarer sein. Oben fällt die ungewöhnliche Struktur ja gleich ins Auge. Aber es kann auch einfacher und optisch “verschleiert” vorkommen. Ein Beispiel, wo es nicht sofort ins Auge gesprungen wäre:

z = ( x + y + z ) / ++x;

Also immer ein wachsames Auge für solche Unstimmigkeiten haben. Und selbst wenn der Compiler solche Anweisungen eindeutig auflösen könnte, sollte man auf die Komplexität und Lesbarkeit achten. Denn ich möchte persönlich keine Anweisung ala

++x += –x *= ++x -= -x;

verstehen müssen. Auch wenn es ein ANSI-Compiler ohne murren übersetzt.