[linux-l] RS-232 oder USB lesen mit (Schauder...) Java Os-unabhaengig

Oliver Bandel oliver at first.in-berlin.de
Mo Sep 26 15:15:34 CEST 2005


On Sun, Sep 25, 2005 at 11:33:10PM +0200, Volker Grabsch wrote:
> On Thu, Sep 22, 2005 at 02:09:37AM +0200, Oliver Bandel wrote:
> > [...]

[...]
> Ich möchte deshalb, aus rein praktischen Gründen, keine Unterscheidung
> machen zwischen "Compiler-Fehlern" und "Laufzeitfehlern sofort beim
> starten des Programmes". Von mir aus kannst du auch die Laufzeitfehler
> (Exceptions), die Python beim Starten des Programmes eventuell
> generiert, ebenfalls zu "Compiler-Fehlern" zählen. Insbesondere zählen
> für mich auch die Fehler dazu, die meine Testsuiten erzeugen. Zwischen
> all diesen Fehlern macht es aus Programmierer-Sicht keinen Sinn, zu
> unterscheiden, welche "eher" auftreten.

Es ght nicht um eher im zeitlichen Sinne.
Das ist nebensächlich.
Es geht darum, welcher Art die Fehler sind.


[...]
> > > Wieso? Wenn du nach dem Compilieren sowieso das Programm startest,
> > > kann es dir doch egal sein, wenn es erst beim Starten den Fehler
> > > ausgibt.
> > 
> > Nein. Wenn es ein Fehler ist, der erst zur Laufzeit auffällt und vielleich erst
> > nach 10.000 testfällen, weil es sich um eine komplexe Software handelt,
> > oder vielleicht erst dann auffällt, wenn der entsprechende Testfall beim Anwender
> > ausgetestet wird, dann ist das blöd gelaufen.
> 
> Von dieser Sorte von Fehlern habe ich nicht gesprochen!
> 
> Dass der Ocaml-Compiler auch solche Dinger enttarnen kann, finde ich
> beeindruckend, jedoch waren bisher die einzigen derartigen Fehler, dass
> man sich im Methodennamen vertippt oder eine falsche Anzahl von
> Argumenten übergibt.

Diese Fehler können aber auftreten und wenn sie nicht entdeckt werden,
ist das Murks.
Und wenn man für sowas erst Testcases schreiben muß, nur weil der Compiler
nicht in der Lage ist,  diesen Job zu erledigen, dann ist das ein
Workaround. Das ist Zeitverschwendung. Beschäftigungstherapie.



> Und diese Fehler fallen sofort auf, wenn man die
> Methode auch nur irgendwie aufruft.

Und sie fallen garnicht auf, wenn man die Methode nicht aufruft!


> Insbesondere also fallen sie
> garantiert bei meinen "normalen" (inhaltlichen) Testcases auf.

Garantiert ist nur, daß es da keine Garantie gibt. ;-)

Je umfangreicher die Software, desto schwieriger bleibt es,
sowas zu handeln.


> Extra dafür
> welche schreiben brauchte ich bisher nie.

Wieso?
Woher sollen Deine testcases wissen, welche Funktionen/Methoden sie
abtesten/aufrufen sollen?



[...]
> > > > Code, der compiliert werden kann, ist schon deshalb recht solide.
> > > > Man kann nicht einfach irgendwas zusammen bauen und zur Laufzeit kracht's.
> > > > Fehlerhafter Code fällt dann schon auf, bevor er laufen könnte.
> > > 
> > > Okay, lass uns bitte von diesen Begriffen wegkommen, da sie keinen
> > > Vergleich zwischen Python und OCaml ermöglichen. Wenn das Programm
> > > beim Starten mit einem Fehler abbricht, ist das genauso gut, als
> > > wenn es beim Compilieren abbricht, weil man beides sowieso
> > > hintereinander macht.
> > 
> > Nein. Da bin ich vollkommen anderer Meinung.
> > 
> > Ich habe mal im bereich Softwaretest gearbeitet. Mit einem wirklich
> > beknackten Tool sollte ic C-Code checken.
> > Da mussten diverse Branches abgetestet werdn, oder mindestens soundsoviel Prozent.
> 
> Keine Ahnung, womit du da gearbeitet hast, aber du willst doch nicht
> von *diesen* Erfahrungen irgenwie auf Python schließen, oder? Das ist
> unsachlich und weit hergeholt. So kann man nicht diskutieren.

Das ist weder unsachlich, noch weit hergeholt.
Wenn die Sprache (in dem Falle C) es vereinfacht, toten Code
zu produzieen, der z.B. in OCaml mit Pattern Matches schnell
ausfindig gemacht worden wäre (nicht benutzte Matches oder ähnliches),
dann baut man sich selbst Falltüren ein.
Klar kann man in jeder Sprache Mist verzapfen. Aber wenn die Sprache
einem auf die Finger schaut und das Abfangen möglicher Fehler schon
von selbst übernimmt, dann ist mir das lieber so.

Aber solange Du den anderen Weg nicht mal ausprobiert hast, ist es müßig, darüber
zu reden. Das muß man mal selbst ausprobiert haben.

Und wenn man Software entwickeln will, die auch mal größer/komplexer ist,
dann ist das wirklich nicht mehr weg zu denken.

> 
> Meine Testcases gingen schnell zu schreiben und schnell durchzulaufen.

Aber geschrieben müssen die auch erst mal werden.
Wenn man das tun muß, nur weil der Copiler das nicht macht... extra Aufwand.

Man sollte seine Funktionalität testen; aber warum soll man dem Compiler
zuarbeiten, statt der einem?!



> "Umständlich" ist an Python kaum etwas.

Aber das Drumherum schon... ;-)



> 
> > Wenn man da so viele Wochen braucht, nur um den Code abzusichern,
> > inhaltlich aber auch bzgl. potentieller Abstürze, etc. dann ist das der
> > falsche Weg, wenn man die auf falshen typen beruhenden Fehler nicht schon
> > garnicht erst abtesten müsste.
> 
> Wiegesagt brauche ich keinen extra Typcheck.

Ich finde die Typ-Checks noch wichtiger als den OO-Layer.


> Lapalien wie falscher
> Methodenname etc.

Das sind nur solange Lapalien, wie man die Vorzüge statischer Checks 
nicht kennt. Typen, aber auch das vorhanden sein von Funktionen,
die man aufrufen will.


> fallen ganz automatisch auf, wenn man diese Routinen
> nur aufruft.

...wenn man...

=> Konjunktiv!

Die meisten Katastrophen bei sicherhsitskritischer Software
traten auf durch die Fehler, die man als unwichig und unwahrscheinlich
eingestuft hatte. gerade diese "Lapalien" sind es, die einem
im Ernstfall dann auf die Füße fallen.




> Und ja, ich gehe natürlich davon aus, dass meine Testsuite
> jede Funktion / Methode mindestens einmal aufruft.

Und genau DAS ist die Annahme, die das Flugzeug abstürzen läßt, das KKW
zur kernschmelze führt, den Satelliten auf die falsche Bahn wirft,
oder den Shuttle zersemmelt.



> Wenn das nichtmal
> der Fall ist,

dann ist es u.U. schon zu spät.


> dann sollte man sowas nicht "Testsuite" nennen, und erst
> recht nicht von seinem Code behaupten, er wäre gut getestet :-)

Naja, warum sich erst die Probleme herein holen?

Dieser Ansatz ist IMHO bullshit.

"Wird schon nix passieren" , "wir machen det schon",
"wir sind die Helden der Wissenschaft"...
...jaja, "unsere Testcases sind sicher".

Alles schöne Worte, aber dann kracht es trotzdem an der Stelle.



> 
> > Es ist besser, der Fehler fällt so früh wie möglich auf.
> > Um so weniger Zeit wird für's Suchen aufgewendet.
> 
> Ob er beim Compilieren oder beim Rennen der Testsuite auftaucht, macht
> für mich zeitlich keinen Unterschied.

Ob er beim rennen in der Testsuite oder erst im laufenden Betrieb
auffällt, DAS macht einen Unterschied. Und der kann auch dramatische
Züge annehmen... apropos Züge.

Bahnsignalanlagen zum Beispiel oder auch Flugzeugsoftware, in C geschrieben,
mit Testtools durch gecheckt, und dennoch ein Sicherheitsrisiko...
...das ist die Realität.

Die Praxis zeigt immer wieder: man kann sich auch auf sehr ausgefeilte Tests
nicht immer verlassen.




> So schnell kann ich gar nicht
> gucken, wie Python das Zeug byte-compiliert, gestartet, und die
> Testfälle durchgeochst ist.

Es geht nicht um die Zeit für den Testdurchlauf.
(außer, das wird seeehr aufwändig)

Es geht um die Vollständigkeit der Prüfung.

Zu behaupten, man kann das alles durchchecken ist - genau da liegt
auch ein Hauptproblem bei der imperativen programmierung -
quasi nicht möglich. Man kann da nur mit Wahrscheinlichkeiten operieren.


[...]
> > > Dies ist zwar tatsächlich ein Problem, aber kein allzu großes: Wenn
> > > du sauber programmieren willst, also dein Ziel stabiler Code ist
> > > (davon reden wir ja die ganze Zeit), dann wirst du ohnehin alles
> > > gründlich austesten müssen.
> > 
> > Selbstverständlich.
> > 
> > 
> > > Dann wirst du sowieso inkrementell
> > > Programmieren: Immer nur kleine Sachen ändern, und gleich austesten.
> > > Sobald es plötzlich einen Fehler gibt, kannst du seine Ursache sehr
> > > schnell eingrenzen
> > 
> > Aber nicht, wenn der Fehler einer eben gemachten Änderung womöglich erst
> > später auffällt.
> 
> Das sollen die Testcases verhindern.

...sollen...

...und auch die Testcases können buggy sein, oder unvollständig.  



> Und ich jage nach jeder größeren
> Änderung die Testsuite rüber, und ergänze vllt. noch ein paar Tests.

Du verstehst nicht das grundsätzliche Problem der Situation.
Oder Du ignorierst es einfach, oder spielst es herunter.


> Dann arbeite ich weiter, ändere Code, füge welchen hinzu, jage wieder
> die Testsuite rüber. Das geht wirklich fix. Und du machst das doch
> genauso bei der Entwicklung, oder? Und zwar solange, bis alle Tests
> erfolgreich waren.


Wie ein Schäfer, der den Zaun wegschmeisst, den Schäferhund an jemand
anderen weg gibt und dann den Schafen selber hinterher rennen muß...
...so kommt mir dieses Vorgehen vor, das Du hier rechtfertigst.




[...]
> Diese Beschränkung auf das Einfache und Übersichtliche ist es, was
> Python für mich so interessant macht. Man macht schon beim Schreiben
> viel weniger Fehler, und während ich in Java ständig ein der API
> nachschlagen musste, sind die Funktionen und Klassen in Python in
> einer flachen Hierarchie und einfach gehalten, sodass man sich das
> alles problemlos merken kann. Ich musste für gleichartigen Python-Code
> (bei Ruby war das übrigens  genauso) viel weniger Nachschlagen ("wie war
> das nochmal?"), als ich es bei meinem Java-Projekt musste.
> 
> Ich denke, dieser Vorteil dürfte auch auf Ocaml zutreffen, bin mir aber
> nicht ganz sicher. Kannst du dazu was aus Erfahrung sagen?

Naja, manchmal muß ich schon nachschlagen, wie eine Funktion hieß,
oder in welchem Modul die war oder welche Argumentereihenfole.
Aber auch das Toplevel kann einem da helfen.
Aber in C würde ich ja auch nachschauen, oder in Perl.
Manchmal hat man etwas viell. ne Weile lang nicht mehr benutzt.

Insgesamt ein sehr angenehmes arbeiten mit OCaml.
Macht man doch mal was aus'm Kopf falsch, bekommt
man ja auch gleich ne Info vom Compiler... :)


> 
> 
> > > Aber was bedeutet "testen"? Testen heißt ja nicht bloß "Syntax-Check"
> > Eben, den macht der Compiler ja schon.
> > und wenn er die Typen auch gleich testet, um so besser!
> 
> Klar, aber wenn er nur Fehler findet, die meine Testsuite genauso finden
> würde

Tut sie aber nur, WENN ....


> (ohne dass ich dafür irgendwas extra schreiben brauch), dann ist
> das ein Feature, das ich nicht brauche.

Viele Testcases sind garnicht mehr notwendig.
Insbesondere, wenn man seinen code sehr FP-like
gestalet und nicht alles wieder nur imperativ
macht, hat liegt man schon weit auf der guten Seite.


> 
> Jedoch Ocaml scheint noch ein paar Sachen mehr zu prüfen. Und *das*
> macht die Sache dann doch wieder interessant für mich. Ich werde es auf
> jeden Fall mal anschauen. Gibt es eigentlich noch andere Sprachen, die
> ähnlich streng wie Ocaml sind? Also statische Typisierung, die aber
> automatisch erkannt wird, etc.?

Gibt es nicht jede Woche neue Sprachen, die entwickelt werden? ;-)

Mit irgendwas muß man halt anfangen.



[...]
> Das mag sein. Derartigen Code habe ich bisher jedoch kaum geschrieben.
> Bei meiner aktuellen Applikation liegen die Schwierigkeiten in ganz
> anderen Bereichen.


Wolltest Du da nicht mal ein bischen mehr dazu sagen?
(Vielleicht Extra-Thread?)



[...]
> > > fallen Typfehler (d.h. bei Python: Aufrufen von nicht existierenden
> > > Methoden) automatisch mit auf.
> > 
> > Naja, und wenn die Methode nicht aufgerufen wird, weil der Testfall
> > noch nicht definiert ist?
> 
> Eine Testsuite, die es nichtmal packt, jede Methode mind. einmal
> aufzurufen ... was ist den das??

Eine Testsuite ist auch nur Code, den man schreibt.
Und auch dieser kann Bugs haben.

Die Notwendigkeit eine Testsuite zu haben bedeutet: Code kann Buggy sein.
Wenn Code buggy sein kann, und da auch eine Testsuite Code ist, kann
auch eine Testsuite Buggy sein.

Man versucht also, zwei potentiell lückenhafte Code-Haufen
gegeneinander zu stellen, so daß man die Lücken findet.

Dies mag oftmals, oder sehr sehr oft gut funktionieren;
aber den einen oder anderen Fall dekct man nicht ab
("Lapalien") und schon kracht es.

Das sind dann manchmal solche spektakulären Dinge, die die Nachrchtensender
als Katastrophen/Unfälle/... berichten.
Jahrelange Untersuchungen ergeben dann, daß irgend ein Testfall,
der bei Coe-Redesign dann vergessen wurde, dieses Problem hätte
abtesten sollen, es aber nicht tat. Oder, daß man bestimmte Fälle als
unwahrscheinlich angesehen hat.

All so Sachen sind es... die, auf die man sich nicht verlassen sollte!




> 
> 
> > Vor einer Weile habe ich mir mal Objective-C angeschaut.
> > Ist ja mit late binding extrem Flexibel. Das hat ja auch so seine
> > Vorteile. :)
> > Aber kaum hatte ich mal mit ObjC etwas herum probiert... und mich schon
> > gefreut, wie flexibel man damit ist, da kam schon genau SO ein Fehler.
> > 
> > Und DAS hat mich vielleicht genervt, ey!
> > 
> > Aber wirklich!
> > 
> > Nö, da lieb' ich doch den auf die Finger klopfenden OCaml Compiler. :)
> 
> Nenn mal bitte dein Beispiel. Was hattest du denn gemacht?


Es war nur ein kleiner Testcode. < 100 Zeilen.
Mal etwas mit ObjC herum gedaddelt, um mir diese flexible
Sprache mal rein zu ziehen.

Der Testlauf brachte genau so etwas: nicht existierende Methode.

Sowas hätte man vorher - vor dem Programmstart - wissen müssen.

Eine potentille Fehlerquelle mehr.

Wenn das bei < 100 Zeilen passieren kann ("deckt der
Testcase ab" zählt nicht), dann mache das mal bei einer Codegröße
von enigen MB, also einige 100.000 Zeilen Code.

Viel Spaß beim Testen! :->

BTW: Damit immer alles abgedeckt wird an tests müsste so eine
Testsuite eigentlich bei jeder kleinsten Änderung immer
*komplett* durchlaufen. Bei komplexen SW-Systemen dauert so etwas Wochen
und gar Monate!

Wenn man bei jeder kleinen Ändrung solche Tests fahren sollte - vergiß es!

Programmiert man funktional, also ohne nebeneffekte, dann sind die meisten
dieser Fehler/Fehlerquellen garnicht mehr vorhanden.
Genau DESWEGEN ist FP so genial: man arbeitet funktional, also nicht
mit Nebeneffekten. Dadurch wird der Code sicherer.

Deswegen sollte man in OCaml,das ja auch nicht-funktionale programmierung erlaubt,
doch bitte davon nicht durchgehend Gebrauch machen und den Code möglichst
funktional (im Sinne von FP)  gestalten.



> 
> 
> > > Wenn du also sowieso inhaltliche Tests machst, hast du automatisch
> > > auch Typ-Tests.
> > 
> > Je früher ein Fehler gefunden wird, desto besser.
> > 
> > Habe lange genug in Perl gemacht.
> > Habe damals auch so geredet. Ich sehe das mittlerweile anders.
> > 
> > Bei Perl war ich dann froh, daß es "use strict;" gibt.
> 
> Hab ich auch immer benutzt. :-)

Siehste!

Warum wohl? ;-)

Ist doch ohne viel cooler... und man hat doch Testcases...
..warum also hast Du in Per "use strict;" genutzt?
Für's auffinden von Lapalien? ;-)



[...]
> Eventuell reimplementiere ich meine Applikation nicht in Python, sondern
> Ocaml.  :-)


Aha. :)

In was läuft die jetzt?
Java?


[...]
> > > Und im "Ändern - Testen - Ändern - ..."-Zyklus
> > > werden dir Typfehler entsprechend auch "sofort" angezeigt, weil
> > > du ja nach jeder Änderung automatisch deine Testsuite drüberjagst.
> > 
> > Du gehst davon aus, daß Deine testsuite jeden Fehler findet.
> > Mit dieser Annahme begesht Du einen Fehler.
> 
> Nö, nicht alle. Schon gar nicht alle inhaltlichen. Aber alle vertippten
> Methoden-Namen findet es.


Aha, Deine testsuite dient also zum Auffinden von falschen Methodennamen bzw.
dem Fehlen von Methoden?

Dann machst Du genau das, was der Compiler erledigen sollte und hast damit also
Extra-Aufwand.

Und wenn die Testcases die inhaltlichen fehler nicht ausfindig machen,
dann sind diese Testcases aber ganz schön schlapp. :(

Auch inhaltliche tests sollte man fahren. mache ich eigentlich immer.
Schliesslich soll das Programm ja auch die Aufgabe ausführen, für die man
es entwickelt hat... deswegen Testcases!


> 
> > Das mag für die Heimprogrammierung genügen, und das mag auch
> > in der Industrie üblich sein, aber letztlich dennoch IMHO
> > fahrlässig.
> 
> Das stimmt. Aber Python oder Java sind ja noch gutartig. Wer mit C
> arbeitet, *der* ist fahrlässig. Huch, hab ich da grad was gegen Linux
> gesagt?  :-)


Ach, weißt Du, ich habe auch in C recht soliden Code gebaut.
Wenn man paranoid programmiert und immer viele Test fährt,
kann man auch mit C soliden Code schreiben.

Aber ein Restrisiko bleibt eben.
Besonders die Sache mit den Pointern, die so wunderbar leistungsfähig,
aber auch so risikobehaftet sind, oder wenn man mal über Speichergrenzen greift...

...wobei man sich z.B. bei Schleifen einfach immer eine Art angewöhnen sollte
for ( i=0; tester; i < endwert) 

und nicht jedesmal eine andere Schreibweise (doch mal ab 1 aanfangen oder so).

Oder immer unbenutzte Variablen auf 0 bzw. NULL setzt, gleich am Anfang
einer Funktion, selbst, wenn sie gleich danach mit Werten besetztt werden...

...ändert man nämlich im Code, kommentiert mal was aus, dann hat man klare
Ausgangswerte.

...oder: immer alle Parameter auf alle möglichen/unmöglichen Werte abtesten,
auch wenn man meint "daß man das sowieso nicht braucht, wenn diese Funktion
bekommt eh nur werte in dem erlaubten Bereich, und die Poiunter sind
an diser stelle eh immer != NULL".

jaja... die ganzen scheisß-Sprüche von Leuten, die nicht daran denken,
daß man an anderer Stelle womöglich mal eine Änderung macht oder nen
Bug verbricht... und es knallt dann GANZ WOANDERS, und teils ZUFÄLLIG.

...aber ich schweife ab.



> 
> > Gut, daß Du nicht sicherheitskritische SW schreibst...
> > ...obwohl: Selbst in den Industriezweigen arbeitet man
> > mit Sprachen und testtools, die unverantwortlich sind.
> 
> Würde ich sicherheitskritische Anwendungen schreiben: Glaub mir, ich
> würde ganz andere Maßstäbe ansetzen. Ocaml ist von der Warte heraus das
> beste, was ich gesehen habe (hab mich mittlerweile schon etwas schlauf
> gemacht). Gibt's da eigentlich von der Code-Sicherheit was
> vergleichbares, oder steht Ocaml da allein auf weiter Flur?

ADA soll auch sehr gut für sicherheitskritische sachen sein.
Sagt man jedenfalls... vielleicht ist es an manchen Stellen
sogar noch pingeliger. Aber vielleiht an manchen auch nicht
so gut. Da kenne ich mich nicht so gut mit aus.
Man soll sogar Wertebereiche von Int's vorgeben können.

Naja, in OCaml könnte man sich ggf. einen eigenen Typ implementiern
der dies bewerkstelligt. Am besten als abstrakten Typ.
Da das Typsystem aufpasst, daß die Typen übereinstimmen,
und wenn man da dann nur bestimmte Operationen erlaubt,
kann man auch nicht irgendwelchen Kruschelkrams damit machen. :)


Beispiel für einen Int-Typ mit festgelegten Borders:

=================================
module Limited_Int =
  (struct
    type t = int
    exception Border_exception

    let maximum = 12
    let minimum = -4

    let border_check x = if x < minimum || x > maximum then raise Border_exception else x

    let add x y = border_check (x + y)
    let sub x y = border_check (x - y)
    let mul x y = border_check (x * y)
    let div x y = border_check (x / y)

    let of_int i = border_check i

    let to_int li = li

  end
   :
  sig
    type t
    val to_int : t -> int
    val of_int : int -> t
    val add    : t -> t -> t
    val sub    : t -> t -> t
    val mul    : t -> t -> t
    val div    : t -> t -> t
  end)
=================================

Erlaubt die vier Operationen +, -, * , / nur für Werte
von einschliesslich -4 bis 12, sowohl als Eingangswerte
wie auch als Ergebnisse.


Mit Funktoren kann man das ganze parametrisiren (parametrisiertes
Modul):




================================================================

module type Borders = sig val maximum: int val minimum: int end

module BorderInt =
   functor( Border : Borders ) ->
  (struct
     type t = int
     exception Border_exception

      let border_check x = if x < Border.minimum || x > Border.maximum then raise Border_exception else x

      let add x y = border_check (x + y)
      let sub x y = border_check (x - y)
      let mul x y = border_check (x * y)
      let div x y = border_check (x / y)

      let of_int i = border_check i

      let to_int li = li


   end
:
sig
    type t
    val to_int : t -> int
    val of_int : int -> t
    val add    : t -> t -> t
    val sub    : t -> t -> t
    val mul    : t -> t -> t
    val div    : t -> t -> t
 end)


module MyRestricted = BorderInt (struct let maximum = 100 and minimum = 10 end )
================================================================

Erlaubt nur int-Werte von (inklusive) 10 ... 100.

Wegen Typprüfung kann man - hat man sich für solch einen Typ entschieden,
nicht mehr mit den normalen int's an den Wertegrenzen dran vorbei:

========================================================================
first:~ oliver$ ocaml
        Objective Caml version 3.08.0

# #use "restricted.ml";;
module type Borders = sig val maximum : int val minimum : int end
module BorderInt :
  functor (Border : Borders) ->
    sig
      type t
      val to_int : t -> int
      val of_int : int -> t
      val add : t -> t -> t
      val sub : t -> t -> t
      val mul : t -> t -> t
      val div : t -> t -> t
    end
module MyRestricted :
  sig
    type t
    val to_int : t -> int
    val of_int : int -> t
    val add : t -> t -> t
    val sub : t -> t -> t
    val mul : t -> t -> t
    val div : t -> t -> t
  end
# open MyRestricted;;
# of_int 101 
  ;;
Exception: BorderInt(Border).Border_exception.
# of_int 9;;
Exception: BorderInt(Border).Border_exception.
# of_int 10;;
- : MyRestricted.t = <abstr>
# let a = of_int 12 and b = of_int 77 and c = of_int 90 and d = of_int 10;;
val a : MyRestricted.t = <abstr>
val b : MyRestricted.t = <abstr>
val c : MyRestricted.t = <abstr>
val d : MyRestricted.t = <abstr>
# a + b;;
This expression has type MyRestricted.t but is here used with type int
# add a b;;
- : MyRestricted.t = <abstr>
# let result = to_int (add a b);;
val result : int = 89
# let neues_result = to_int ( mul b c);;
Exception: BorderInt(Border).Border_exception.
# 
========================================================================

So, nun kann man sich an wertebegrenzten Intege-Typen erfreuen.

Das sind keine Emulationen durch Objekte, sondern Datentypen.
Hat man ne Liste solche Werte (oder Array) kann man mit List.iter oder Array.iter
dann  z.B. Werte ausgeben, oder so.

Oder mit map statt iter Ergebnislisten erzeugen.

Da man die im Typ eingebaute Prüfung auf diese Weise nicht mehr umgehen
kann, macht das die ganze Programmierung dann sicher. :)

Ob man diese Datentypen dann in Listen, Arrays, anderen Moduln,
Funktionen, Objekten oder Closures nutzt, ist egal.
Sie werden behandelt wie andere Datentypen auch und eine Polymorphe
Funktion wie List.iter oder List.map kann man darauf anwenden.




> 
> > [...]
> > > Wenn dir Ocaml hingegen irgendwelche Sachen durch die Typisierung
> > > unnötig schwer macht
> > 
> > macht es nicht.
> > Warum sollte eine Sprache, die einem die Fehler früh aufzeigt,
> > einem bei tests das leben schwer machen?
> > Keines wegs.
> > Im gegenteil: ich kann mich bei der programmierung dann auf die
> > inhaltlichen Tests konzentrieren, und mir fallen nicht andauernd
> > irgendwelche casts und so'n Blödsinn auf die Füße!
> 
> Mach ich genauso. Nur inhaltliche Tests.

Das hast Du weiter oben aber ganz anders geschrieben...


[...]
> > > Stabile Software braucht
> > > in jedem Fall automatisierte Laufzeit-Tests! Das wird sich später
> > > 100fach wieder auszahlen, wenn du Bugs produzierst, die sich nur
> > 
> > Danke, danke, aber ich bin derjenige, der für seine Testgeilheit
> > meist immer erst für verrückt erklärt wurde, und hinterher am schnellsten
> > fertig war. :)
> 
> Hehe. Kenn ich irgendwie ...

:)


[...]
> > Da man das eh mit zig testcases automatisiert abtestet, braucht der Compiler
> > auch nicht die Syntax nicht zu prüfen.
> > Es richt, wenn er korrekte Syntax voraussetzen kann und dann bei koirrekter Syntax
> > korrektes Compilat erzeugt.
> > 
> > Na, gehst Du auch so weit noch mit?
> 
> Nicht ganz. Bei Typfehlern, fehlerhafter Syntax, etc. sollte zumindest
> eine Exception geworfen werden.


ein core dump ist auch eine Form von Exception. ;-)
So gesehen kann man also auch in C weiter bauen. ;-)


[...]
> > > Aber wiegesagt, das ist die "pythonische Sicht", und diese Argumentation
> > Nein, das ist DEINE Sicht der Argumentation.
> 
> Okay, ich werde besser nochmal konkreter. Folgendes ist eine gängige Sicht
> von Python-Programmierern, d.h. die "pythonische Sicht":
> 
> Ewiges Typen-Tippen und Casten (wie es z.B. in Java der Fall ist)
> provoziert mehr Fehler als es verhindert. Wenn man sowieso testet,
> spart man am Ende sehr viel mehr Zeit, als man anfangs für das formale
> Befriedigen des Compilers gebraucht hat.


Naja, wenn Du Casts als "formales Befriedigen des Compilers"
ansiehst, und nicht als Design-Schwäche...


[...]
> > > Ich weiß nicht, ob eine statisch typisierte Sprache jemals so flexibel
> > > sein kann wie z.B. Ruby oder Python.
> > 
> > Ist ja die Frage, ob man diese Flexibilität wirklich benötigt, oder sie nicht nur
> > aus mangelnder Programmierdisziplin gerne in kauf nimmt, weil einem
> > die viell. recht häufigen Typ-Probleme niht immer vor die Nase gehalten werden.
> 
> Nee, nicht Typ-Probleme, die gibt's ja sowieso, sondern ständiges
> Wiederholen, was wann welchen Typ hat. Das ist vorallem in C++ / Java
> nervend. Ocal ist offenbar anders.

OCaml erkennt den Typ automatisch. Nur in manchen ganz seltenen Fällen muß man
den Typ mal genauer spezifizieren; ist mir nur anfangs mal passiert,
als ich noch so manches nicht gepeilt hatte, wie man es besser löst.
Man kann natürlich, wenmn man will, den Typ einer Funktion auch absichtlich
einschränken; dies mag für noch rigidere Vorgehensweise manchmal Sinn machen,
daß man nur bestimmte typen erlaubt, auch wenn die Funktion z.B. polymorphic ist.



> 
> > Ich hätte ja bei Perl bleiben können. Anfangs dachte ich auch immer:
> > Naja, OCaml mag viell. für größere projekte sinnvoll sein, aber nicht für
> > kleinere Sachn, denn die kann man in Perl schneller zusammen hacken.
> 
> Hey, bitte schließe nicht, was die Sauberkeit des Programmierens angeht,
> von Perl auf Python. Auch die Python-Leute distanzieren sich sehr von
> Perl.

OK, ok.


> 
> > perl nehme ich nur noch sehr selten, seit ich OCaml nutze.
> > So ungefähr, wie ich C kaum noch nahm, seit ich Perl-te.
> > Der vermeintliche Vorteil dieser Sprachen ist aber oftmals ihr Nachteil.
> 
> Bitte schließe nicht von Perl auf alle dynamsichen Sprachen,
> insbesondere nicht auf Python.

Perl ist eine dynamische Sprache.
Da kann man zur Laufzeit auch allerlei Unsinn anstellen. :)


> Mag sein, dass Python nicht ganz so
> streng ist wie Ocaml, aber es ist sehr viel strenger und sauberer
> als Perl.

Das kann sein; nach dem, was Du so schreibst, sieht es wohl ganz
danach aus.


> Vorallem auch die APIs. Sie machen einem unsaubere "Hacks"
> schwer (weil sie nicht dafür ausgelegt sind), aber z.B. bei CGI-Scripten
> kriegt man saubere Sachen damit schneller gebacken als z.B. in PHP.

Aha.

Naja, PHP ist eh so eine Sache... ;-)
Da macht man doch eh fast alles in HTML und streut da etwas
PHP ein. :(
Aber vielleicht machen das so auch nur die kruden Wurschtelfritzen ;-)


> 
> > Mag sein, diese sind für manche Anwendungen doch besser geeignet,
> > aber IMHO muß die Anwendung solcher Sprachen (mit ihrer erhöhten
> > Bug-Wahrscheinlichkeit, die sie einbringen)  ausserordentlich begründet
> > werden, zumindest, wenn man wirlich solide Software schreiben will
> > und nicht nur herum daddeln.
> 
> Na, na ... ich bemühe mich sehr, sauber zu programmieren. Nur, weil ich
> nicht Ocaml sondern Python benutze, heißt das nicht, dass ich nur
> "herum daddel".

Naja, ich habe, wie gesagt, schon mal Softwaretests durchführen
müssen mit grottenschlechten Tools. Die Industrie setzt diese Tools
z.B. ein, um Flugzeug-Software und Bahnsignalisierungssoftware
zu testen. Eine große Firma (bekannt durch gewisse UML-Tools)
 hat diese grottenschlechte SW aufgekauft,
und ob die dadurch besser geweorden ist, sei mal noch dahin gestellt.

Jedenfalls konnte man bei dieser Kack-Software (sorry, aber man muß
es mal beim Namen nennen) das Ergebnis des Testlaufes dadurch verändern,
daß man z.B. ein zusätzliches Space im Testscript eingefügt hat.

Viel Spaß beim nächsten mal, wenn ihr eine Bahn oder ein Flugzeug besteigt.
Wenn Ihr abstürzt, liegt es vielleicht an dem grottenschlechten testtool, das
übrigens wohl zertifiziert wurde und angeblich Industriestanbdard ist...

... hätte ich über dieses grottenschlechte Scheisstool nicht so sehr
das Maul aufgerissen, hätte ich vielleicht damals eine Projektverlängerung
bekommen (und hätte in den letzen Monaten weniger abgekotzt); aber viell.
hätte ich dann eines Tages Menschentode zu verantworten gehabt und mich würde
ein schlechtes Gewissen plagen, mich nicht mal wenigstens kritisch zu dem
Teil geäussert zu haben.
Ich habe jedenfalls die Sache beim Namen genannt und auch gesagt/gemailt,
daß ich es unverantwortlich finde, so ein Tool einzusetzen.
Entscheidungsbefugnis hatte ich diesbezüglich aber nicht. Aber ich habe
es wenigstens gesagt.

Naja, so läuft das. :(


Und daß Du sicherlich bemüht bist, sauberen Code zu schreiben, das stelle ich damit
nicht in Frage.

Ich finde es aber nicht so toll, wenn man zusätzliche sprach-/compilereigene
Testmechanismen nicht nutzt.
Aber wenn Du das für Deine Spaß-Software machst, ist das Deine Entscheidung
und mag OK sein. Ober-krass finde ich es, wenn das in der Industrie gemacht
wird, und man da unverantwortlich selbst im sicherheitskritichen Bereich arbeitet.

Was nützt eine SW die Schrott ist, aber zertifiziert?!

[...]
> Zum Thema dynamische Sprachen: Ich bin mir sicher, dass mein Python-Code
> wesentlich sauberer ist und fehlerfreier, als entsprechender Java-Code.
> Und dass mich das insgesamt sehr viel weniger Arbeit in Python kostet,
> trotz laschem Compiler. Denn der Java-Compiler zwingt einem zum Erfüllen
> von sinnlosen Formalismen, und das ist IMHO noch viel schlimmer, weil
> man daran gehindert wird, sich auf das Wesentliche zu konzentrieren.

Das wesentliche wäre, diese Formalismen nicht als Formalismen anzusehen,
sonern die stellen, an denen Casts notwendig sind, umzuformulieren, so
daß keine Casts notwendig sind.

Casts sind potentielle Sicherheitsproblme und die nerven bei einem Redesign auch.
Casts machen Sachen passend, die eigentlih nicht zusammen passen.
Und sie machen diese Preßpassung auf eine Weise, die man nicht selbst
genau kontrollieren kann. Und viele Programmierer haben nicht immer im Kopf,
nach welchen Kriterien der Compiler castet.
Damit entseht dort ein nicht explizit im Code stehender Zusammenhang,
der irgendwie umgewurschtet wird vom Compiler.
Stattdessen wäre eine explizite Funktion, die die Typen konvertiert (wie in OCaml)
eine Lösung, daß auch im Code genau zu sehen ist, was da gemacht wird.
Und wenn der Compiler das nicht vorschreibt, es so zu machen, dann kommt ganz schnell
der Schlendrian da rein.


[...]
> > Erst, als ich mit OCaml dann mal
> > was anderes sehen durfte (war ein harter Kampf, am Anfang, wenn einem
> > ständig irgendwelche Typfehler gemeldet werden) und mich da auch dran gewöhnt
> > hatte, und als ich dann sah, wie viel besser man damit komplexe Probleme
> > lösen kann (während einem Perl mit seiner Abwasser-Syntax das Hirn verknotet),
> > wußte ich, daß das so viel besser ist.
> 
> Gut, so hart wird das für mich wohl nicht werden. Im Gegensatz zu C++
> oder Java sieht Ocamls Compiler immer noch freundlich aus.

Wie meinst Du das?
Wieso sieht der freundlich aus?

("wart's ab" ;-))


[...]
> > Und warum soll ich auf die Sachen, die ich bei OCaml jetzt schon habe,
> > bei Python noch drauf warten? (Du schriebst da mal was zu zip() und
> > irgendwelchen neuen features, die nicht extra Listen erzeugen.
> > => List.iter sage ich nur. :)
> 
> Das ist ein Missverständnis. Ich sagte, diesen Kram gibt's ab Python 2.4
> Aber das aktuelle Release von Python *ist* nunmal 2.4  ... ich wollte
> damit nur sagen, dass man die aktuelle Version nutzen muss, um meine
> Beispiele auszuprobieren. Das ist alles Stand der Technik, was ich hier
> erzähle!

Seit wann? ;-)


[...]
> Python glänzt durch eine einfache Syntax. IMHO auch einfacher als Ocaml.

Mag sein, wenn man sie beherrscht.
Ich finde Ocamls Syntax einfacher; habe halt mit Python noch nix gemacht.

[...]
> > > In Bereich Software-Design hättest du in Python wesentlich
> > > bessere Karten, IMHO.
> > IMHO nicht.
> 
> Mal sehen. Das werde ich ja herausfinden. Sobald ich in der Uni bin,
> saug ich mir Ocaml (ist schon im Aptitude alles ausgewählt :-)).


Fein. :)

Es gibt auch mittlerweile ne Menge guter Dokus. :)
Aber da Du ja schon FPLs kennst, ist der Umstieg für Dich
nicht so hart, wie bei mir damals. Da hatte ich nur ein bischen
mit Scheme gemacht und dann kam Haskell und OCaml (Haskell und OCaml
ne Zeit lang im Wechsel, bis ich mich für OCaml entshcied - u.a. übrigens auch,
weil es mehr Plattformen unterstützte und die Kompilierung/Installation
einfacher war als z.B. bei ghc. Und schlanker ist die OCaml-Distri auch.
Das ist für mich auch ein Hinweis, daß das cooles Zeugs ist :))


Gruß,
   Oliver



Mehr Informationen über die Mailingliste linux-l