Auswertung Restriktiv vs. Robuste Entwicklung
Auf meinen Blogeintrag hin zu "Rebuste vs. Restriktive Programmierung", wo ich die Behauptung aufgestellt habe, dass es eine Frage des Charakters des Entwicklers sei, gab es mittlerweile mehr als 30 Fremdkommentare. Ein spannendes Thema, dass ich nun hier einmal zusammen fassen möchte.
Ausgangsthese war die Betrachtung des eigenen Programmierstils in Bezug auf Robustheit bzw. Restriktivheit von API-Methoden. Am Beispiel der Methode LoadCustomer(string alphaNumber), wobei die Kundennummer alphanumerisch sei, bedeutet Restriktiv (für mich wohlgemerkt), dass eine Methode nur dann einen Kunden findet, wenn die Kundennummer exakt übereinstimmt. Also keine Leerzeichen, kein null, Groß- und Kleinschreibung stimmt, alle Bindestriche und Sonderzeichen sind exakt eingegeben. In allen anderen Fällen wird eine Exception geworfen und der Kunde konnte nicht gefunden werden. Robust bedeutet, dass z.B. einfach mal Leerzeichen Links und rechts abgeschnitten werden, weil so die Chance, mehr Eingaben als gültig zu erkennen höher ist. Bei null gibts natürlich auch da ein Problem, aber Bindestriche könnte man z.B. auch ersetzen oder versuchen zu behandeln, wenn das Format der Nummer klar ist.
Es sei noch kurz erwähnt, dass ich oft mit Client-Entwicklung zu tun habe und deswegen oft von dem Szenario ausgehe, dass unter anderem Benutereingaben (bzw. ungeprüfte Eingaben woher auch immer) direkt an die API übergeben werden. Als Beispiele wurde zum Beispiel genannt, dass Controls.Add(null) oder label1.Text=null einfach nichts macht. Es stürzt nicht ab und wirft keine Exception, eine meiner Meinung nach sehr robuste und gute Entwicklungsweise.
Andere Beispiele für Restriktive Entwicklung wurden genannt, so zum Beispiel "simpler Datentyp".Parse oder auch alles was mit Sicherheit zu tun hat.
Zusammenfassend kann folgendes gesagt werden:
1. Alle beteiligten sind sich einige, dass, egal was auch immer eine Methode macht. Es muss irgendwo stehen und dokumentiert sein.
2. Eine Methode sollte im Namen schon soo viel wie möglich darüber aussagen, was sie auch tut. Als Beispiel hierfür gibt es die ganzen coolen ExtensionMethods, die da z.B. heissen First<>() oder FirstOrDefault<>(), wobei First eine Exception werfen kann (restriktiv) und FirstOrDefault einfach den Defaultwert zu dem Datentyp zurückgibt (robust). Namen wie "LoadCustomerByNumderOrDefaultAndTrimAndCaseSensitiveAndOtherSignsAreHandledToo" (ich übertreibe leicht), sind natürlich ungünstig.
3. Ein grober Nachteil meines Favoriten, nämlich der robusten Entwicklungsmethodik, ist der Fakt, dass unter Umständen Fehler "verloren" gehen könnten. Dabei sind sich auch alle einig, dass dies niemals der Fall sein sollte. Leere catch-Blöcke sind nur in Ausnahmesituationen ok und ansonsten sollte eine Exception, wenn sie schon nicht nach aussen weitergereicht wird, zumindest irgendwie irgendwo protokolliert werden. Andere Entwickler erkennen Fehler schneller und besser, wenn eine Exception geworfen und nach aussen gereicht wird.
4. Oft ist es eine Frage der Umgebung und der Anforderung, wie und wo eine API eingesetzt wird und ob sie sich an dieser Stelle restriktiv und robust verhalten soll. In Sachen Sicherheit sollte eine API immer restriktiv sein. Also hier kann nicht mal eben versucht werden, dem Benutzer unter die Arme zu greifen und seine Eingabe doch noch richtig zu interpretieren. Wenn ein Kennwort nicht exakt stimmt, dann ist es falsch. Das ist klar.
5. Es wurden einige Vorgehensweisen und Situationen genannt, die, wenn sie richtig durchgeführt und eingehalten werden, viele Fragen von vorn herein beantworten, damit nachher niemand da steht und nicht weiss, was er genau machen soll (und so vllt. eine Exception wirft oder auch nicht...). Ein Ansatz war immer vorher gut durchdachte Kontrakte zu erstellen, und wenn diese klipp und klar sind, dann stellen sich auch später keine Fragen wie :"Ja soll ich dem Benutzer nun unter die Arme greifen und Leerzeichen wegmachen bei der Eingabe einer Kundennummer???". Weiterhin wurde gesagt, dass, wenn alle Teammitglieder gut, oft, offen und ordentlich mit einander kommunizieren, es dann auch einfacher ist, Methoden die man geschrieben hat, für andere Entwickler bereitzustellen. Leider ist dieser Perfektionissmuss, der notwendig ist, damit wirklich immer alles glatt läuft, so wie es im Buche steht, oft nur Theorie. Die echte Praxis unterscheided sich aus vielerlei Gründen oft, was wohl jeder bestätigen kann, der schon in unterschiedlichen Projekten mit unterschiedlichen Kunden und unterschiedlichen Anforderungen gearbeitet hat...
6. Es kam heraus, dass die Mehrheit der Entwickler eher zur restriktiven Gruppe zählen würden, als zur robusten. Sie würden viel eher hier und da mal eine Exception mehr werfen, als eine zu wenig. Eine gute Alternative ist es aber, z.B. in seiner API einstellen zu können, ob man lieber ne Exception haben will oder nicht. So verhält sich die API entweder robust oder restriktiv.
7. So, im Endeffekt könnte man da bestimmt noch weiter diskutieren. Ich selbst habe mit meiner robusten Enwicklungsart mehr positive Erfahrungen gemacht als mit der restriktiven Variante und meine Kunden auch (Endbenutzer sowie auch andere Entwickler). Deswegen werde ich wohl dabei bleiben. Andere widerum haben genau andere Erfahrungen gemacht. Deswegen bleiben diese bei ihren Methoden. Wieder Andere sagen, wenn man sich überhaupt zwischen restriktiv und robust entscheiden muss (das macht man meiner Meinung nach aber auch oft im Unterbewusstsein), dann is schon von vorn herein irgendwas falsch.
Also die eine klare Endlösung gibt es nicht. Die Meinungen gehen auseinander aufgrund der Erfahrungen der Entwickler hier. Beide Versionen haben Vor- und Nachteile, wie Alles in der Welt. Wichtig ist nur, dass man sich überhaupt mal bewusst ist, dass es da einen Unterschied gibt und in welche Richtung der eigene Charakter aufgrund von Erfahrungen geprägt wurde...