Prozedur und Funktion



  • audacia schrieb:

    uio schrieb:

    wenigstens noch abspeichern und und dann kanns weitergehen ist mal ein ganz schön großer Unterschied.

    Unerwartete Exception und unerwartete Zugriffsverletzung ist auch ein ganz schön großer Unterschied, den du geflissentlich ignorierst.

    Appendix: Um das noch etwas deutlicher zu machen: ich sagte in bezug auf Sprachexceptions "dann kanns weitergehen", und dazu stehe ich. Nach Sprachexceptions beliebiger Art und Abstammung bleiben meine Anwendungen stabil.

    Stabil ist aber zu unter Umständen viel zu wenig. Ist es korrekt? Was aber nicht am Fangen und Ignorieren unerwarteter Fehler liegt, sondern weil Du in kritischen Pfaden keine Fehler produzierst. Zum Beispiel muß bei der Ausbuchung des Buchs auch das Geld dafür eingebucht werden. Geht beim Einbuchen was schief, weil der Benutzer ein 'ß' in der Adresse hat, fliegt die Exception, Du fängst sie und machst mal locker weiter. Kunde freut sich natürlich.
    Da muß man erstmal drauf kommen! 👍
    Aber ich glaube, das geht nur in Problemstellungen, für die Java ursprünglich gedacht ist, Steuercode für Waschmaschinen und Toaster.



  • volkard schrieb:

    Zum Beispiel muß bei der Ausbuchung des Buchs auch das Geld dafür eingebucht werden. Geht beim Einbuchen was schief, weil der Benutzer ein 'ß' in der Adresse hat, fliegt die Exception, Du fängst sie und machst mal locker weiter. Kunde freut sich natürlich.

    Das ist ein Transaktionsproblem und muß natürlich entsprechend gesondert behandelt werden. Es hat aber, wie du selbst feststellst, nicht viel damit zu tun, ob ich bei unerwarteten Exceptions die Anwendung terminiere oder weiterlaufen lasse; die Datenbank ist in beiden Fällen inkonsistent, wenn ich nicht richtig vorsorge.



  • Also bei der Lektüre von

    try {
        //Berechne ...
    } catch (OutOfMemoryError e) {
        //Ein Error ist keine Exception und muss separat abgefangen werden
        e.printStackTrace();
    } catch (RuntimeException e) {
        //z.B. IndexOutOfBoundsException, NullPointerException usw.
        System.err.println("Offensichtlich ein Programmierfehler!");
        throw e; //Leite nach oben weiter
    } catch (Exception e) {
        //Fange alle restlichen Ausnahmefehler ab
        e.printStackTrace();      
    } catch (Throwable t) {
        //Das hier fängt wirklich alles ab
        t.printStackTrace();
    } finally {
        //Ob Exception oder nicht, führe das hier auf jeden Fall aus.
        System.out.println("Berechnung beendet oder abgebrochen");
    }
    

    mußte ich erstmal herzlich lachen. 😃



  • volkard schrieb:

    audacia schrieb:

    uio schrieb:

    wenigstens noch abspeichern und und dann kanns weitergehen ist mal ein ganz schön großer Unterschied.

    Unerwartete Exception und unerwartete Zugriffsverletzung ist auch ein ganz schön großer Unterschied, den du geflissentlich ignorierst.

    Appendix: Um das noch etwas deutlicher zu machen: ich sagte in bezug auf Sprachexceptions "dann kanns weitergehen", und dazu stehe ich. Nach Sprachexceptions beliebiger Art und Abstammung bleiben meine Anwendungen stabil.

    Stabil ist aber zu unter Umständen viel zu wenig. Ist es korrekt? Was aber nicht am Fangen und Ignorieren unerwarteter Fehler liegt, sondern weil Du in kritischen Pfaden keine Fehler produzierst. Zum Beispiel muß bei der Ausbuchung des Buchs auch das Geld dafür eingebucht werden. Geht beim Einbuchen was schief, weil der Benutzer ein 'ß' in der Adresse hat, fliegt die Exception, Du fängst sie und machst mal locker weiter. Kunde freut sich natürlich.
    Da muß man erstmal drauf kommen! 👍
    Aber ich glaube, das geht nur in Problemstellungen, für die Java ursprünglich gedacht ist, Steuercode für Waschmaschinen und Toaster.

    Mit C++ fstreams geht das aber viel einfacher.

    int main()
    {
    	std::ofstream f("xy:z::dsa");
    	f<<"ssfdad";
    	std::cout<<"Fertig";
    }
    

    Da fliegt keine Exception die man falsch fangen kann. Das Programm läuft einfach durch und der Kunde freut sich.

    Das Problem an den Checked-Exceptions von Java ist einfach, dass sie sie viel zu oft verwenden und dass jeder Wirtschaftsinformatiker mit Java rum hackt.

    volkard schrieb:

    Also bei der Lektüre von

    try {
        //Berechne ...
    } catch (OutOfMemoryError e) {
        //Ein Error ist keine Exception und muss separat abgefangen werden
        e.printStackTrace();
    } catch (RuntimeException e) {
        //z.B. IndexOutOfBoundsException, NullPointerException usw.
        System.err.println("Offensichtlich ein Programmierfehler!");
        throw e; //Leite nach oben weiter
    } catch (Exception e) {
        //Fange alle restlichen Ausnahmefehler ab
        e.printStackTrace();      
    } catch (Throwable t) {
        //Das hier fängt wirklich alles ab
        t.printStackTrace();
    } finally {
        //Ob Exception oder nicht, führe das hier auf jeden Fall aus.
        System.out.println("Berechnung beendet oder abgebrochen");
    }
    

    mußte ich erstmal herzlich lachen. 😃

    Wer hat das geschrieben?



  • Das hat irgendein Spaßvogel in die Wikipedia eingetragen.

    MfG SideWinder



  • geben Sie einen Benutzern schrieb:

    Mit C++ fstreams geht das aber viel einfacher.

    int main()
    {
    	std::ofstream f("xy:z::dsa");
    	f<<"ssfdad";
    	std::cout<<"Fertig";
    }
    

    Da fliegt keine Exception die man falsch fangen kann. Das Programm läuft einfach durch und der Kunde freut sich.

    Davon abgesehen, dass niemand für dieses Programm Geld bezahlen würde, 😃
    Was passiert, wenn die datei nicht geöffnet werden kann? Nichts?



  • Genau darum ging es. Wenn du alles gelesen hättest, wüstest du das jetzt die Rechnung nicht gespeichert wurde.



  • volkard schrieb:

    Also bei der Lektüre von

    try {
        //Berechne ...
    } catch (OutOfMemoryError e) {
        //Ein Error ist keine Exception und muss separat abgefangen werden
        e.printStackTrace();
    } catch (RuntimeException e) {
        //z.B. IndexOutOfBoundsException, NullPointerException usw.
        System.err.println("Offensichtlich ein Programmierfehler!");
        throw e; //Leite nach oben weiter
    } catch (Exception e) {
        //Fange alle restlichen Ausnahmefehler ab
        e.printStackTrace();      
    } catch (Throwable t) {
        //Das hier fängt wirklich alles ab
        t.printStackTrace();
    } finally {
        //Ob Exception oder nicht, führe das hier auf jeden Fall aus.
        System.out.println("Berechnung beendet oder abgebrochen");
    }
    

    mußte ich erstmal herzlich lachen. 😃

    Das ist ja auch grundlegend Falsch.
    Mein Code sieht meistens so aus:

    public void doSomething() throws MyException {
      try {
          doSomething0();
      } catch (IOException e) {
        throw new MyException(e);
      } catch (SQLException e) {
        throw new MyException(e);
      } catch ...
      finally {
      }
    }
    
    private void doSomething0()  throws IOException, SQLException, .... {
      // do some stuff
    }
    

    Aber das Java's checked exceptions were a mistake (and here's what I would like to do about it)
    Sehe ich ein, dass Checked Exceptions bei "Zwischen APIs" Probleme machen.



  • DEvent schrieb:

    Mein Code sieht meistens so aus:

    und da ist dir noch nie in den sinn gekommen dass das ein bisschen schwachsinnig ist?



  • Gibts eigentlich nichts besseres zur Fehlerbehandlung? Entweder man muss überall hinschreiben was es für Exceptions gibt oder man weiß nicht welche es geben kann. Ist doch beides Müll.


  • Administrator

    17° schrieb:

    Gibts eigentlich nichts besseres zur Fehlerbehandlung? Entweder man muss überall hinschreiben was es für Exceptions gibt oder man weiß nicht welche es geben kann. Ist doch beides Müll.

    Gibt Programme, welche den Callstack im Code analysieren und entsprechend Warnungen ausgeben können, falls irgendwo in einer Richtung eine Exception nicht gefangen wurde.

    Am besten sollte dies gleich der Kompiler machen.

    Und wieso gibt es nun den Unterschied zwischen Prozedur und Funktion? 😃

    Grüssli



  • 17° schrieb:

    oder man weiß nicht welche es geben kann

    Dafür gibt es die Doku.



  • In Sprachen wie Ada gehört der Rückgabewert einer Funktion zur Funktionssignatur. Dementsprechend kann man eine Funktion auch für unterschiedliche Rückgabewerte aber gleiche Parameterlisten überladen. Dafür darf allerdings der Rückgabewert auch nicht ignoriert werden, weil dann Mehrdeutigkeiten entstehen würden.



  • Shade Of Mine schrieb:

    DEvent schrieb:

    Mein Code sieht meistens so aus:

    und da ist dir noch nie in den sinn gekommen dass das ein bisschen schwachsinnig ist?

    Sind wir hier bei Twitter?

    Shade Of Mine schrieb:

    17° schrieb:

    oder man weiß nicht welche es geben kann

    Dafür gibt es die Doku.

    Als ob die Doku irgendein Anspruch auf Aktualität hält.
    Wenn die Doku doch genügt, wieso dann die const-correctnes von C++? Es reicht doch wenn ich in die Doku schreibe "Die Methode verändert den Zustand des Objektes nicht".



  • Shade Of Mine schrieb:

    17° schrieb:

    oder man weiß nicht welche es geben kann

    Dafür gibt es die Doku.

    Das gleiche Problem wie bei checked Exceptions. Schreibst du alle Exceptions rein die alle "Sub-Funktionen" werfen könnten oder nur die, die die Funktion direkt wirft, dann hast du wieder nicht alle? Was machst du mit sowas wie boost::signal? Da kann alles mögliche dahinter sein.



  • [quote="DEvent"
    Mein Code sieht meistens so aus:

    public void doSomething() throws MyException {
      try {
          doSomething0();
      } catch (IOException e) {
        throw new MyException(e);
      } catch (SQLException e) {
        throw new MyException(e);
      } catch ...
      finally {
      }
    }
    

    [/quote]
    Ich habe zwar keine Ahnung von Java und finde es auch ziemlich doof :p
    Aber wars nicht so, dass alle Exceptions von "Exception" abgeleitet sind, so dass Du es so machen kannst?

    public void doSomething() throws MyException {
      try 
      {
        doSomething0();
      } 
      catch (Exception e)  // fängt alle Exceptions 
      {
        throw new MyException(e);
      }
    }
    


  • Ja, kannst du. Dass DEvent kein Java kann hat er ja schon zu genüge in anderen Threads bewiesen 🤡 👍 😋



  • Vielleicht will er ja nicht alles fangen



  • DEvent schrieb:

    Aber das Java's checked exceptions were a mistake (and here's what I would like to do about it)
    Sehe ich ein, dass Checked Exceptions bei "Zwischen APIs" Probleme machen.

    Eigentlich nicht. Die hätten einfach nur ihr Interface richtig designen müssen und z.B. ne ObjectPoolException werfen können. Und ab wann so irgendwas ne "Zwischen API" sein? Jede API ist irgendwo zwischen Programm und Java API, egal ob ObjectPool, DB oder GUI.

    Ich Programmier ja schon ne Weile kein Java mehr, aber sind die noch nicht auf die Idee gekommen sowas wie Autoboxing für Exceptions zu machen?
    statt:

    public void doSomething() throws MyException {
      try {
          doSomething0();
      } catch (IOException e) {
        throw new MyException(e);
      } catch (SQLException e) {
        throw new MyException(e);
      } catch ...
      finally {
      }
    }
    

    irgendwie sowas

    public void doSomething() autoThrows MyException {
       doSomething0(); // Compiler macht automatisch "throw new MyException(e)", wenn hier checked Exceptions geworfen werden.
    }
    

    falls gleich wieder einer keine Phantasie hat und wegen finally jammert.

    public void doSomething() autoThrows MyException {
        try{
           doSomething0(); // Compiler macht automatisch "throw new MyException(e)", wenn hier checked Exceptions geworfen werden.
       } finally{...}
    }
    

    müsste dann auch gehen



  • Gerade fällt mir noch eine Situation ein, wo die Trennung zwischen Prozedur und Funktion sehr sinnvoll ist:

    // Delphi Runtime Library, SysUtils.pas:
    ...
    // Generic Anonymous method declarations
    type
      TProc = reference to procedure;
      TProc<T> = reference to procedure (Arg1: T);
      TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2);
      TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3);
      TProc<T1,T2,T3,T4> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4);
    
      TFunc<TResult> = reference to function: TResult;
      TFunc<T,TResult> = reference to function (Arg1: T): TResult;
      TFunc<T1,T2,TResult> = reference to function (Arg1: T1; Arg2: T2): TResult;
      TFunc<T1,T2,T3,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3): TResult;
      TFunc<T1,T2,T3,T4,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4): TResult;
    
      TPredicate<T> = reference to function (Arg1: T): Boolean;
    

    Hätte man nicht zwischen Funktionen und Prozeduren unterschieden, müßte man eine Prozedurreferenz etwa als TMethod<T, Void> deklarieren. Dabei ist zu beachten, daß es void eigentlich nur in C und C++ gibt. Wer schon einmal eine generische Delegatenklasse in C++ implementiert hat, dürfte auch schon unangenehme Bekanntschaft mit void und der dafür meist nötigen Sonderbehandlung gemacht haben. Der Standard sieht ja sogar spezielle return void -Ausnahmeregelungen vor, die die Angelegenheit etwas vereinfachen, aber das Problem nicht beseitigen. Hier ist eine klare Unterscheidung zwischen Prozeduren und Funktionen hilfreich.

    (Natürlich gibt das jetzt auch keinen Aufschluß darüber, was man sich ursprünglich dabei gedacht haben mag. Closures waren vermutlich bei den Altvorderen noch nicht eingeplant 🤡 )


Anmelden zum Antworten