Programmierstil



  • Bashar schrieb:

    IMHO sind das Kleinigkeiten, die mit Stil überhaupt nichts zu tun haben.

    Das sehe ich auch so. Stil ist etwas anderes und beschränkt sich nicht auf die Formatierung.

    Beispiel:

    int length, *p;
    if (fill(&p,&length) && length) {
      int minidx = 0;
      int minval = p[0];
      for (int k=1; k<length; ++k) {
        if (p[k]<minval) {
          minval = p[k];
          minidx = k;
        }
      }
      delete[] p;
      return minidx;
    }
    return -1;
    

    versus

    vector<int> v = vsource();
    auto it = std::min_element(v.begin(),v.end());
    if (it==v.end()) throw my_empty_exception();
    return it - v.begin();
    

    Die Aspekte bei diesem Beispiel:
    - Wie wird mit Ressourcen umgegangen (RAII vs nackte Zeiger)
    - Wird das Rad neu erfunden oder bedient man sich der std::Algorithmen?
    - Wie sieht die Fehlerbehandlung aus? Special return values oder Exceptions?



  • krümelkacker schrieb:

    - Wie sieht die Fehlerbehandlung aus? Special return values oder Exceptions?

    Exceptions im eigenen Code um sie selber zu fangen und zu behandeln?

    Exceptions dienen der Fallunterscheidung für Lösungswege die zum Zeitpunkt wo man den Code schreibt noch nicht bekannt sind. Z.B. im Falle der Frameworkentwicklung sinnvoll, da man nicht weiß was der Progger, der mit dem Framework arbeitet, mit der Info anfängt das der Vector leer ist.

    Klar ist das auch ein Style für jede Funktion eine Excep. zu entwerfen und eine try/Catch Passage einzubauen, aber kein guter.

    In dem Fall kann es auch reichen eine 0 zurück zu geben, im besten Fall an erster Stelle in der Funktion.



  • @Haarspalter

    Exceptions dienen der Fallunterscheidung für Lösungswege die zum Zeitpunkt wo man den Code schreibt noch nicht bekannt sind.

    Nö, das kann man so nicht sagen. Also kann man natürlich sagen, ich bin aber gänzlich anderer Meinung.

    Exceptions dienen zur Ausnahmebehandlung. Und das sage ich jetzt nicht weil es die 1:1 Übersetzung von "exception handling" ist, sondern weil es ausnahmsweise auch mal sehr gut passt. Eine bessere kurze Umschreibung fällt mir nicht ein.

    Ausnahmebehandlung heisst aber nicht, dass man zu dem Zeitpunkt wo man den Code schreibt noch nicht weiss wie man die Ausnahme behandeln möchte.

    Ein besseres Kriterium wäre mMn.: wo (=wie weit weg vom Aufruf) will man den Fehlerfall üblicherweise behandeln, und gibt es Anwendungsfälle wo der Fehlerfall als "normal" anzusehen ist?

    Heisst z.B. wenn ich nen Server schreibe, und da ne Database-Connection aufmachen will. In dem Fall weiss ich zwar wie ich den Fehlerfall behandeln will, aber es ist a) nicht der Normalfall dass das nicht klappt und b) will ich es nicht nahe der Stelle behandeln wo es passiert. Sondern irgendwo weit weg in einem "ich kann den Request aus irgend einem Grund nicht bearbeiten" Handler. Also schmeisse ich eine Exception. In meinem eigenen Code, und fange sie in meinem eigenen Code. Hier mit Returncodes zu arbeiten und über viele Callstack-Ebenen mit "if...return" zurückzusteigen, nur weil man weiss wie man den Fehlerfall behandeln wird, ist mMn. kompletter Unfug.

    Anderes Beispiel: sagen wir ich schreibe ein Framework das File-IO abstrahiert. Hier weiss ich nicht wie der User darauf reagieren möchte, wenn man ein File nicht aufmachen kann. In dem Fall immer eine Exception zu werfen wäre allerdings der falsche Weg, denn es gibt verschiedenste Anwendungsfälle wo verschiedenste Sachen Sinn machen.

    Es gibt Fälle wo der User z.B. gar nicht weiss ob ein File mit dem Namen überhaupt existiert, und den Fehler lokal behandeln möchte. Eine "CanOpenFile" Funktion anzubieten damit man die Exception vermeiden kann ist auch kein guter Weg, denn ob man ein File aufmachen kann oder nicht kann sich vom einen Moment zum nächsten ändern. Mal abgesehen davon dass es einen weiteren unnötigen Kernel-Call bedeuten würde. Also muss eine "TryOpenFile" Funktion her, die mit Returnwert arbeitet.

    Dann gibt es aber Fälle wo der User wie im Fall der Database-Connection das File einfach haben "muss", nicht sinnvoll weitermachen kann und den Fehlerfall auch nicht lokal behandeln will. Also bietet man zusätzlich eine "OpenFile" Funktion an die im Fehlerfall eine Exception wirft.

    Ein Framework das nur eine der beiden Möglichkeiten anbietet ist mMn. Murks.

    Noch ein Beispiel: Werte aus einer Konfigurationsdatei lesen. Hier gibt es sogar drei Möglichkeiten: TryRead, Read mit Defaultwert und Read mit Exception. Alle drei können je nach Situation Sinn machen, und ich würde alle drei anbieten.



  • Haarspalter schrieb:

    [...bla...]
    In dem Fall kann es auch reichen eine 0 zurück zu geben

    FAIL

    Haarspalter schrieb:

    Klar ist das auch ein Style für jede Funktion eine Excep. zu entwerfen und eine try/Catch Passage einzubauen, aber kein guter.

    Wer sagt denn, dass man jeden Funktionsaufruf, der mit einer Ausnahme enden könnte, in ein try/catch klammern soll? Der Witz an der Ausnahmebehandlung ist doch, dass man Ausnahmen erst dort zu fangen braucht, wo man auch weiß, wie die Situation zu meistern ist. Ob da jetzt Framework Grenzen dazwischen liegen oder nicht, spielt doch keine Rolle.



  • Das ist guter Stil, alles andere ist Kinderkacke:

    #define			      q [v+a]
    #define			     c b[1]
    #define			    O 1 q
    #define			   o 0 q
    #define			  r(v,a\
    )v<0&&(			 v*=-1,		a*=-1);
    #define			p(v,m,	    s,w)*c==*#v?2 q\
    <m?(c++		       ,d=1,3	   q=0,5      q=m,main\
    (a+3,b)		      ,o=o*s	 q,O=O*		 w q):0:
    static		     d,v[99	];main		  (int a,
    char**b		    ){d=7;     if(*c?!		  (p(+,3
    ,4 q+O*		   3,4)p(			   -,(o?3
    :(O=1,6		  )),4 q			  -O*3,4)
    p(*,4,3		 ,4)p(/				  ,5,4,3)
    p((),d,		0+3,0+				 04)*c==
    ')'?2 q	       <02?(c				++,0):0
    :(o=012	      *o+*c-			      '0',c++
    ,O=1)):	     2 q?3-			   2:printf(
    "%d/%d"	    "\n",o		       ,O))return
    1;d=a,r    (o,d)r		     (O,d)3 q
    =o<O?(4	  q=o,O)		   :(4 q=O,
    	 o);r(d,		 o)a+=3;O?
    				 1:(O=1,2
    				q=1);while
    				(2 q=o%1 q)a++;v[d]/=O;d[
    				v+1]/=O;return main(d,b);}
    

    Von Steinar Hamre / ioccc.org


Anmelden zum Antworten