Ich hasse Java
Re: Ich hasse Java
Aber eine Frage bitte noch... das mit dem "kleiner als" hab ich nicht ganz verstanden... was meinst du damit und wieso ist es schlimm wenn das öffentlich abrufbar ist?
Re: Ich hasse Java
Was ist wenn ich zwei Häuser mit einander vergleichen will? Das Haus mit den wenigeren Fenstern sei das "kleinere" Haus. Um das Minimum davon zu bekommen, soll ich Haus von Number ableiten oder was?
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Ich hasse Java
Wenn ich das richtig sehe, sind wir hier an einem Problem angekommen das funktionale (d.h. !OOP) Programmiersprachen (z.b. Haskell) durch „Meta”–Klassen (Typklassen) loesen. Alle Typen, die eine Kleiner–Als–Operation unterstuetzen, werden in einer Typklasse zusammengefasst und fuer diese wird dann die Min()–Funktion bereitgestellt. C++0x–Concepts (die ja leider aufgegeben wurden) sowie C++–Templates im Allgemeinen gehen in eine aehnliche Richtung.
Schlussendlich ist das C++/Java/C#–Klassenkonzept ziemlich engstirnig. Daher kritisiere ich bei Java auch den Zwang, alles in Klassen packen zu muessen – damit lassen sich nur zweidimensionale Strukturen abbilden, waehrend grade min() ein Beispiel fuer eine eher auf Meta-Ebene angesiedelte Funktionalitaet ist (genauer: man wird dazu gezwungen alles abzuflachen und in eine Klassenhierarchie zu pressen – das ist zwar moeglich, neigt aber dazu ziemlich verbose und ueberladen zu werden …).
Schlussendlich ist das C++/Java/C#–Klassenkonzept ziemlich engstirnig. Daher kritisiere ich bei Java auch den Zwang, alles in Klassen packen zu muessen – damit lassen sich nur zweidimensionale Strukturen abbilden, waehrend grade min() ein Beispiel fuer eine eher auf Meta-Ebene angesiedelte Funktionalitaet ist (genauer: man wird dazu gezwungen alles abzuflachen und in eine Klassenhierarchie zu pressen – das ist zwar moeglich, neigt aber dazu ziemlich verbose und ueberladen zu werden …).
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
@unique75: Ah, ich sehe das Missverständnis … du sprichst von einer Funktion, die das Ergebnis direkt dem linken Operanden zuweist und ich von einer, die den kleineren Operanden zurückgibt …
(Mal mit aussagekräftigeren Funktionsnamen:) Ja, deine Version – i.ceilTo(5); gehört zur Methode gemacht, weil sie eine der Zahlen verändert.
Meine Version ohne Wirkung – x = getMininumOf(i, 5); darf hingegen keine Methode sein.
Darauf, welche Version erstrebenswerter ist, möchte ich mich nicht direkt festlegen. Persönlich würde ich meine bevorzugen, weil sie weniger Abhängigkeiten hat und ich Funktionen mit Wirkungen meide.
(Mal mit aussagekräftigeren Funktionsnamen:) Ja, deine Version – i.ceilTo(5); gehört zur Methode gemacht, weil sie eine der Zahlen verändert.
Meine Version ohne Wirkung – x = getMininumOf(i, 5); darf hingegen keine Methode sein.
Darauf, welche Version erstrebenswerter ist, möchte ich mich nicht direkt festlegen. Persönlich würde ich meine bevorzugen, weil sie weniger Abhängigkeiten hat und ich Funktionen mit Wirkungen meide.
Wenn es öffentlich abrufbar ist, braucht man keinen Zugriff auf private Methoden und Attribute, um die Aufgabe zu erledigen. Wenn die Funktion eine Methode ist, bekommt man diesen Zugriff aber, und erhöht dadurch das Risiko, die Funktion von der Implementierung des Objekts abhängig zu machen, wo es nicht sein muss; schwächt also die Kohäsion. Öffentliche Methoden, die nur andere öffentliche Methoden aufrufen, sind i.d.R. Zeichen schlechten Entwurfs.unique75 hat geschrieben:Aber eine Frage bitte noch... das mit dem "kleiner als" hab ich nicht ganz verstanden... was meinst du damit und wieso ist es schlimm wenn das öffentlich abrufbar ist?
Zuletzt geändert von Krishty am 26.12.2010, 16:20, insgesamt 1-mal geändert.
Re: Ich hasse Java
Ich muss beiden (Biolunar und Aramis) widersprechen, aber ihr denkt alle irgendwie viel zu kompliziert. Ihr müsst euch endlich mal von der engstirnigen C++ Denkweise lösen und mal über den Tellerrand schauen (ist nicht böse gemeint, ich hab vor ein paar Jahren noch selber so gedacht, deswegen weiss ich wie verdammt schwer das ist).
min() ist eine stinknormale Instanzmethode. Es kann eine Klasse Haus geben, wenn ich zwei Häuser vergleichen will, überlade ich üblicherweise den = operator oder im Falle von "kleiner als" den < operator. Die min() Methode wird meist auf Basis des < implementiert. Will ich also 2 Häuser per min() vergleichen, so habe ich diese Methode einfach mal in der Klasse Haus zu implementieren... AUF INSTANZ-SEITE... und nicht in irgendeiner magischen Hilfsklasse auf Klassenseite. Was soll denn so ein grottenhässliches OOP :-)
Und was für ein Haus oder einen String gilt, soll einfach mal für eine Zahl ebenso gelten. Also implementiere ich eine Klasse Number, die ein min() implementiert. Es ist doch absolut schwachsinnig ein min(Haus, Haus), min(String, String), min(int, int) in irgendeiner nichtssagenden Klasse als static-Methoden zu haben. Aber dieses absolut OOP-hässliche Konzept seh ich auch ständig bei dem .NET Klassenframework. Da gibt es String-Concate Methoden auf Klassenseite, wo man es doch eigentlich der Stringinstanz selbst schicken kann, anstatt diese als 1. Parameter zu übergeben.
Lieber Aramis... mit Metaklassen hat das an der Stelle noch nix zu tun. Wenn ich dann damit anfange dann begreift keiner mehr was, weil sich viele nicht vorstellen können, dass auch eine Klasse eine stinknormale Instanz sein kann, der man genauso Methoden schicken kann.
min() ist eine stinknormale Instanzmethode. Es kann eine Klasse Haus geben, wenn ich zwei Häuser vergleichen will, überlade ich üblicherweise den = operator oder im Falle von "kleiner als" den < operator. Die min() Methode wird meist auf Basis des < implementiert. Will ich also 2 Häuser per min() vergleichen, so habe ich diese Methode einfach mal in der Klasse Haus zu implementieren... AUF INSTANZ-SEITE... und nicht in irgendeiner magischen Hilfsklasse auf Klassenseite. Was soll denn so ein grottenhässliches OOP :-)
Und was für ein Haus oder einen String gilt, soll einfach mal für eine Zahl ebenso gelten. Also implementiere ich eine Klasse Number, die ein min() implementiert. Es ist doch absolut schwachsinnig ein min(Haus, Haus), min(String, String), min(int, int) in irgendeiner nichtssagenden Klasse als static-Methoden zu haben. Aber dieses absolut OOP-hässliche Konzept seh ich auch ständig bei dem .NET Klassenframework. Da gibt es String-Concate Methoden auf Klassenseite, wo man es doch eigentlich der Stringinstanz selbst schicken kann, anstatt diese als 1. Parameter zu übergeben.
Lieber Aramis... mit Metaklassen hat das an der Stelle noch nix zu tun. Wenn ich dann damit anfange dann begreift keiner mehr was, weil sich viele nicht vorstellen können, dass auch eine Klasse eine stinknormale Instanz sein kann, der man genauso Methoden schicken kann.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
Ich glaube eher, Biolunar denkt für dich zu sarkastisch :)unique75 hat geschrieben:Ich muss beiden (Biolunar und Aramis) widersprechen, aber ihr denkt alle irgendwie viel zu kompliziert.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Ich hasse Java
Ganz im Gegenteil: min() ist eine Operation, die ich fuer jeden Typ definieren kann, der eine Kleiner-Als-Operation kennt. Natuerlich kann man das OOisieren indem ich eine Basisklassen anlege, die den Kleiner-Gleich-Operator vorschreibt und in Abhaengigkeit davon min() definiert. Ebenso kann man auch in jeder Klasse, die ein min() unterstuetzt, es auf's Neue als a<b?a:b definieren.
Beides ziemlich, wie ich schon sagte, ueberladen. Ich haette lieber eine Notation um auszudruecken was min() eigentlich ist: eine direkt aus der Praesenz eines < ableitbare Operation. Oder von mir aus auch eine aus der Negation eines max() ableitbare Operation. Daher mag ich C++'s std::min – es ist sehr praegnant und kompakt. Was man von allen Versuchen, das ganze OOisch zu loesen, nicht sagen kann.
Nochmal: ich behaupte nicht, dass man mit strikter OO nicht all das modellieren kann. Ich sage nur, dass ich mir fuer viele Dinge praegnantere Notationen wuensche.
Beides ziemlich, wie ich schon sagte, ueberladen. Ich haette lieber eine Notation um auszudruecken was min() eigentlich ist: eine direkt aus der Praesenz eines < ableitbare Operation. Oder von mir aus auch eine aus der Negation eines max() ableitbare Operation. Daher mag ich C++'s std::min – es ist sehr praegnant und kompakt. Was man von allen Versuchen, das ganze OOisch zu loesen, nicht sagen kann.
Nochmal: ich behaupte nicht, dass man mit strikter OO nicht all das modellieren kann. Ich sage nur, dass ich mir fuer viele Dinge praegnantere Notationen wuensche.
Re: Ich hasse Java
Krishty versteht mich grad auch nicht, also mach ichs mal konkret als C++ Code :-)
Ich bitte die schreckliche Formatierung zu entschuldigen, ich bin nicht so der Forenfan :-)
Wenn der Compiler halbwegs intelligent wäre hätte er so eine Klasse vordefiniert und würde jedes int als Instanz dieser Klasse anlegen. Wenn man die Klassenhierarchie richtig baut, hätte man als Oberklasse eine Klasse Number, die bestimmte Methoden polymorph vorhält, so z.B. min(). Aber das würde dann den C++ Programmieren wieder garnicht gefallen, weil sie dann virtuals brauchen, wenn mans richtig macht :-)
Code: Alles auswählen
class Integer
{
public:
Integer(int i) {value = i;}
bool operator<(const Number& param) {return this.value < param.value;}
Integer& min(const Integer& param) {if (this < param) return this; else return param;}
private:
int value;
}
Integer var1 = 5;
Integer var2 = 7;
Integer var3 = var1.min(var2);
Wenn der Compiler halbwegs intelligent wäre hätte er so eine Klasse vordefiniert und würde jedes int als Instanz dieser Klasse anlegen. Wenn man die Klassenhierarchie richtig baut, hätte man als Oberklasse eine Klasse Number, die bestimmte Methoden polymorph vorhält, so z.B. min(). Aber das würde dann den C++ Programmieren wieder garnicht gefallen, weil sie dann virtuals brauchen, wenn mans richtig macht :-)
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
Autsch. Nein, das ist weder gekapselt, noch generisch, noch erträglich zu lesen. Und hör auf, über den Compiler zu meckern und ihn mit dem Sprachstandard zu verwechseln; du kannst dir deine Zahlenklassen ja durchaus selber bauen.
Re: Ich hasse Java
Wegen der Lesbarkeit hab ich mich ja entschuldigt und was ist daran nicht gekapselt? Generisch muss das nicht sein, will man ein float so gibt es eine Klasse Float. Dann hat man auch den Vorteil Dinge wie << und >> nur in Integer zu implementieren, weil das Bitgeschiebe bei einer Float keinen Sinn macht. Da versagt übrigens die typische Bit-und-Speicher-Denkweise. Vermutlich erschlägt sich der C++ Programmierer aber wieder mal mit Templatesyntax und kritzelt 20 Methoden rein, die garnicht für floats sinnvoll sind. Ausserdem kann man mit dem obigen Konzept auch sinnvoll Dinge wie ne Klasse Fraction implementieren.
Generische Programmierung ist sowieso ein Graus wegen der Typen.
Generische Programmierung ist sowieso ein Graus wegen der Typen.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
Zum dritten Mal: min() hat Zugriff auf die Interna der Zahl, wo es nicht nötig ist. Integer ist also unzureichend gekapselt. Wenn man für solche Kümmelfunktionen Zugriff gewährt, kann man gleich alles überall öffentlich machen.unique75 hat geschrieben:was ist daran nicht gekapselt?
Kann man auch ohne.unique75 hat geschrieben:Ausserdem kann man mit dem obigen Konzept auch sinnvoll Dinge wie ne Klasse Fraction implementieren.
Gerade generische Programmierung erlaubt das Komponieren von Klassen, die du von Hand ausschreibst – ein Musterbeispiel sind die automatisch generierten Operatoren in boost, mit denen jedes Implementieren oder Verbieten aller vorstellbaren arithmetischen Operationen für beliebige Typen zum Zweizeiler wird.unique75 hat geschrieben:Generische Programmierung ist sowieso ein Graus wegen der Typen.
Zuletzt geändert von Krishty am 26.12.2010, 16:53, insgesamt 2-mal geändert.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Ich hasse Java
Wieso? Generische Programmierung im Allgemeinen oder ihre Implementierung in den gaengigen imperativen Programmiersprachen. Bei ersterem wuerde ich nicht zustimmen, bei letzterem schon.Generische Programmierung ist sowieso ein Graus wegen der Typen.
Nein, das macht der C++-Programmierer nicht. Wie wir alle wissen, debugged er 24/7 seinen Speichermanager.Vermutlich erschlägt sich der C++ Programmierer aber wieder mal mit Templatesyntax und kritzelt 20 Methoden rein, die garnicht für floats sinnvoll sind.
Re: Ich hasse Java
Lieber Aramis
ne ich meinte wirklich nur die Implementierung in den Sprachen. Es ist einfach grausam was da abgeht um Reflection, Lamdas usw. in die Sprache zu pressen. Es wird komplizierter und komplizierter und man kann schlussendlich einen winzigen Bruchteil von dem machen, was in einer echten dynamischen Sprache möglich ist. Das versuchen sie ja seit Ewigkeiten in Java/C# und jetzt wohl auch noch in C++ hinzukriegen. Wird nur nix Vernünftiges draus :-)
Meine Kommentare sind auch ein bisschen zynisch, ich weiss... also bitte nicht allzu sehr auf die Goldwaage legen wenn ich mal irgendwelche Zahlen rauswerfe :-)
ne ich meinte wirklich nur die Implementierung in den Sprachen. Es ist einfach grausam was da abgeht um Reflection, Lamdas usw. in die Sprache zu pressen. Es wird komplizierter und komplizierter und man kann schlussendlich einen winzigen Bruchteil von dem machen, was in einer echten dynamischen Sprache möglich ist. Das versuchen sie ja seit Ewigkeiten in Java/C# und jetzt wohl auch noch in C++ hinzukriegen. Wird nur nix Vernünftiges draus :-)
Meine Kommentare sind auch ein bisschen zynisch, ich weiss... also bitte nicht allzu sehr auf die Goldwaage legen wenn ich mal irgendwelche Zahlen rauswerfe :-)
Re: Ich hasse Java
Für mich sind Methoden Aktionen, die ein Objekt durchführen kann oder Anfragen, die ich an das Objekt stellen kann. Eine min/max-Funktionalität ist aber nichts was ich direkt (ohne anderes Objekt) abfragen kann oder auf dem Objekt anwenden kann. Es ändert das Objekt nicht und fragt nicht explizit nur Eigenschaften des einen Objektes ab, daher finde ich es nicht nur häßlich, sondern auch unlogisch, min/max direkt als Methode zu implementieren. Methoden dienen doch dazu ein sicheres Interface nach außen anzubieten, damit man nicht direkt auf die Member zugreifen kann. Wie Krishty schon sagte, ansonsten kann ich gleich alles public deklarieren. Wenn die Methoden nichts mit internen Membern machen, dann brauch die Methode nicht Teil der Klasse sein, dann tut es eine globale Funktion genauso und ist zudem logischer.unique75 hat geschrieben:Krishty versteht mich grad auch nicht, also mach ichs mal konkret als C++ Code :-)
Ich bitte die schreckliche Formatierung zu entschuldigen, ich bin nicht so der Forenfan :-)Code: Alles auswählen
class Integer { public: Integer(int i) {value = i;} bool operator<(const Number& param) {return this.value < param.value;} Integer& min(const Integer& param) {if (this < param) return this; else return param;} private: int value; } Integer var1 = 5; Integer var2 = 7; Integer var3 = var1.min(var2);
Wenn der Compiler halbwegs intelligent wäre hätte er so eine Klasse vordefiniert und würde jedes int als Instanz dieser Klasse anlegen. Wenn man die Klassenhierarchie richtig baut, hätte man als Oberklasse eine Klasse Number, die bestimmte Methoden polymorph vorhält, so z.B. min(). Aber das würde dann den C++ Programmieren wieder garnicht gefallen, weil sie dann virtuals brauchen, wenn mans richtig macht :-)
Dein vorher erwähntes String::add ist wieder was anderes. Es greift auf interne Member des Strings zu und ändert somit das Objekt. Es kann gar nicht global realisiert werden ohne die Member von String public zu deklarieren.
Aber gerade durch den '<' Operator sind min und max dafür prädestiniert global (oder halt im namespace) zu sein. Es macht einfach keinen Sinn soetwas an ein Objekt zu binden. Das Objekt ist nicht dazu da, etwas zu vergleichen! Es wird verglichen!
Ohne Input kein Output.
-
- Moderator
- Beiträge: 2138
- Registriert: 25.02.2009, 13:37
Re: Ich hasse Java
Ich unterbreche euch ja nur ungerne aber ich glaube das min Beispiel ist total ungeeignet ist um irgendwas sinnvolles herauszubekommen.
1) Etwas was an Java total nervt, ist dass es überhaupt Primitive gibt, für die völlig andere Regeln gelten als für alles andere. Weil es die Konsistenz aus der Sprache nimmt. Das strikt objektorientierte, was Java als Vorteil verkaufen will wurde eben nicht bis zum Ende durchgezogen. Das kann man C++ nicht vorwerfen, da C++ wenigstens in sich konsistent ist. Die meisten Typen können so entworfen werden dass sie sich in der Verwendung relativ ähnlich zu int verhalten.
Natürlich kann man jetzt über eine hypothetische Sprache philosophieren, die tatsächlich vollkommen objektorientiert ist, und auch über deren Sinnhaftigkeit. In Java hat man aber eben nur die Möglichkeit min(int,int) als statisches Member von Math o.ä. zu definieren. Und darüber hatte Krishty sich ja schon ganz zu Anfang amüsiert.
2) Ich verstehe nicht, was das ganze Argument mit den "Interna einer Zahl" soll. Die einzigen Interna die eine Zahl haben kann ist ihr Wert. Und den muss man kennen um min zu bestimmen. Ob man da jetzt direkt drankommt, über friend oder über irgendein "getValue" äquivalent, ändert am Grade der Kapselung meiner Meinung nach nicht viel. Wenn man es ganz genau nehmen will trifft bei so einfachen Typen auch jede schnittstelle Annahmen über die interna. Wenn intern ein double gespeichert ist, kann die schnittstelle kein float als vergleichskriterium zurückgeben. Wenn die Klasse z.B. rationale Zahlen als 2 unsigneds + vorzeichen ablegt, brauchst du auch genau diese Konstellation um den Wertvergleich in der selben Genauigkeit durchführen zu können.
1) Etwas was an Java total nervt, ist dass es überhaupt Primitive gibt, für die völlig andere Regeln gelten als für alles andere. Weil es die Konsistenz aus der Sprache nimmt. Das strikt objektorientierte, was Java als Vorteil verkaufen will wurde eben nicht bis zum Ende durchgezogen. Das kann man C++ nicht vorwerfen, da C++ wenigstens in sich konsistent ist. Die meisten Typen können so entworfen werden dass sie sich in der Verwendung relativ ähnlich zu int verhalten.
Natürlich kann man jetzt über eine hypothetische Sprache philosophieren, die tatsächlich vollkommen objektorientiert ist, und auch über deren Sinnhaftigkeit. In Java hat man aber eben nur die Möglichkeit min(int,int) als statisches Member von Math o.ä. zu definieren. Und darüber hatte Krishty sich ja schon ganz zu Anfang amüsiert.
2) Ich verstehe nicht, was das ganze Argument mit den "Interna einer Zahl" soll. Die einzigen Interna die eine Zahl haben kann ist ihr Wert. Und den muss man kennen um min zu bestimmen. Ob man da jetzt direkt drankommt, über friend oder über irgendein "getValue" äquivalent, ändert am Grade der Kapselung meiner Meinung nach nicht viel. Wenn man es ganz genau nehmen will trifft bei so einfachen Typen auch jede schnittstelle Annahmen über die interna. Wenn intern ein double gespeichert ist, kann die schnittstelle kein float als vergleichskriterium zurückgeben. Wenn die Klasse z.B. rationale Zahlen als 2 unsigneds + vorzeichen ablegt, brauchst du auch genau diese Konstellation um den Wertvergleich in der selben Genauigkeit durchführen zu können.
Re: Ich hasse Java
Ich zitiere: "Eine min/max-Funktionalität ist aber nichts was ich direkt (ohne anderes Objekt) abfragen kann oder auf dem Objekt anwenden kann."
Laut obiger Aussage sind sämtliche Testmethoden es NICHT wert auf Instanzseite zu liegen:
AABB::isAxisAlignedBox()
Sphere::isSphere()
Was erfüllen diese beide Methoden an Mehrwert gegenüber einer min/max-Funktion? Sie verändern das Objekt nicht, sie tun nichts damit, sie bekommen kein anderes. Sie haben nur das Wissen in der richtigen Klasse zu stehen und mit true/false antworten zu dürfen. Einen < operator schreiben alle auf Instanzseite. Was ist also daran in irgendeiner Weise logisch, ein min/max auf Klassenseite zu schieben, oder schlimmer noch in eine völlig andere Klasse. Das min/max basiert auf dem <. Sind die 4 Byte des dahinterliegenden ints, die 40 Fenster des Hauses oder die Rötlichkeit des Apfels denn nur warme Luft? Das sind für mich reale Daten, die der Objektinstanz gehören und genau diese werden verglichen.
Diese Denkweise ist in meinen Augen einzig und allein der Tatsache geschuldet, dass es native Datentypen gibt und die Leute das nicht aus dem Kopf kriegen. Ein nativer Datentyp ist halt nix und genau dieser Ansatz ist falsch. Aber ich glaube man kämpft gegen Windmühlen, bis sich vielleicht doch mal einer traut, über seinen Tellerrand zu schauen.
Letztendlich geht es wieder mal am Hauptthema vorbei.. und deswegen sage ich jetzt abschliessend... ICH HASSE AUCH JAVA... und alle gleichgearteten Sprachen, die mich mit ihrem Compilergezumpel, Linkermeldungen und Projektsettings in den Wahnsinn treiben, obwohl der Compiler vieles davon schon wissen könnte.
Laut obiger Aussage sind sämtliche Testmethoden es NICHT wert auf Instanzseite zu liegen:
AABB::isAxisAlignedBox()
Sphere::isSphere()
Was erfüllen diese beide Methoden an Mehrwert gegenüber einer min/max-Funktion? Sie verändern das Objekt nicht, sie tun nichts damit, sie bekommen kein anderes. Sie haben nur das Wissen in der richtigen Klasse zu stehen und mit true/false antworten zu dürfen. Einen < operator schreiben alle auf Instanzseite. Was ist also daran in irgendeiner Weise logisch, ein min/max auf Klassenseite zu schieben, oder schlimmer noch in eine völlig andere Klasse. Das min/max basiert auf dem <. Sind die 4 Byte des dahinterliegenden ints, die 40 Fenster des Hauses oder die Rötlichkeit des Apfels denn nur warme Luft? Das sind für mich reale Daten, die der Objektinstanz gehören und genau diese werden verglichen.
Diese Denkweise ist in meinen Augen einzig und allein der Tatsache geschuldet, dass es native Datentypen gibt und die Leute das nicht aus dem Kopf kriegen. Ein nativer Datentyp ist halt nix und genau dieser Ansatz ist falsch. Aber ich glaube man kämpft gegen Windmühlen, bis sich vielleicht doch mal einer traut, über seinen Tellerrand zu schauen.
Letztendlich geht es wieder mal am Hauptthema vorbei.. und deswegen sage ich jetzt abschliessend... ICH HASSE AUCH JAVA... und alle gleichgearteten Sprachen, die mich mit ihrem Compilergezumpel, Linkermeldungen und Projektsettings in den Wahnsinn treiben, obwohl der Compiler vieles davon schon wissen könnte.
-
- Moderator
- Beiträge: 2138
- Registriert: 25.02.2009, 13:37
Re: Ich hasse Java
"Sphere::isSphere()"
Huh?
(dynamic_cast<Sphere*>(foo)!=0)
Huh?
(dynamic_cast<Sphere*>(foo)!=0)
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
<3 :)Alexander Kornrumpf hat geschrieben:1) Etwas was an Java total nervt, ist dass es überhaupt Primitive gibt, für die völlig andere Regeln gelten als für alles andere. Weil es die Konsistenz aus der Sprache nimmt. Das strikt objektorientierte, was Java als Vorteil verkaufen will wurde eben nicht bis zum Ende durchgezogen. Das kann man C++ nicht vorwerfen, da C++ wenigstens in sich konsistent ist. Die meisten Typen können so entworfen werden dass sie sich in der Verwendung relativ ähnlich zu int verhalten.
Stimmt so nicht. Eine Gleitkommazahl kann als Interna z.B. Vorzeichen, Exponent und Mantisse haben. Man könnte nun min() so auslegen, dass es nicht einfach den <-Operator benutzt, sondern manuell erst Vorzeichen, dann Exponent und schließlich Mantisse vergleicht, um zu einem Ergebnis zu kommen. In diesem Fall wird die ganze Funktion ungültig, wenn man die Auslegung der Klasse ändert, obwohl die Funktion vom Standpunkt der Programmlogik her garnichts mit dem Entwurf der Klasse zu tun hat – min() baut auf der Verfügbarkeit von kleiner-als auf, nicht auf der Repräsentation einer Zahl. (Natürlich wäre es ziemlich dämlich, das zu tun, und man könnte es einfach sein lassen – aber eine Unschuldsvermutung gibt es bei Kapselung nicht; ich kann die Veröffentlichung eines eigentlich privaten Attributs nicht damit rechtfertigen, dass bestimmt niemand direkt darauf zugreifen wird!)Alexander Kornrumpf hat geschrieben:2) Ich verstehe nicht, was das ganze Argument mit den "Interna einer Zahl" soll. Die einzigen Interna die eine Zahl haben kann ist ihr Wert.
Nein, eben nicht. Man muss nur zwei Zahlen kennen, um sie mit kleiner-als zu vergleichen. Imo muss man sogar nur zwei weak-orderable Objects kennen. Güte, wie ich Concepts vermisse :(Alexander Kornrumpf hat geschrieben:Und den muss man kennen um min zu bestimmen.
Es gibt auch Leute, die die Scheinfundamentalität von Typen nicht aus dem Kopf kriegen und deshalb nicht verstehen, was generische Programmierung ist.unique75 hat geschrieben:Diese Denkweise ist in meinen Augen einzig und allein der Tatsache geschuldet, dass es native Datentypen gibt und die Leute das nicht aus dem Kopf kriegen.
-
- Establishment
- Beiträge: 191
- Registriert: 01.03.2009, 19:22
- Echter Name: David N.
Re: Ich hasse Java
Nachdem Alexander vorhin type classes erwähnt hat, hier ein m.E. sehenswertes »post mortem« zu C++0x concepts – Bartosz Milewski vergleicht sie mit bzw. erklärt sie anhand von type classes aus Haskell.
unique75, könntest du deine Motivation hinter der Aussage »Generische Programmierung ist sowieso ein Graus wegen der Typen« etwas genauer erläutern? Gerade in streng typisierten Sprachen ist es doch umso wichtiger, mächtige Möglichkeiten zur generischen Programmierung zu Verfügung zu haben, um Typen nicht zu einem unliebsamen Hindernis werden zu lassen (Paradebeispiel: Java vor ein paar Jahren – z.B. mit generischen Containern oder Algorithmen so viele Casts, dass der eigentliche Code schon fast untergeht)…
unique75, könntest du deine Motivation hinter der Aussage »Generische Programmierung ist sowieso ein Graus wegen der Typen« etwas genauer erläutern? Gerade in streng typisierten Sprachen ist es doch umso wichtiger, mächtige Möglichkeiten zur generischen Programmierung zu Verfügung zu haben, um Typen nicht zu einem unliebsamen Hindernis werden zu lassen (Paradebeispiel: Java vor ein paar Jahren – z.B. mit generischen Containern oder Algorithmen so viele Casts, dass der eigentliche Code schon fast untergeht)…
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
Meinst du hier? :)klickverbot hat geschrieben:Nachdem Alexander vorhin type classes erwähnt hat, hier ein m.E. sehenswertes »post mortem« zu C++0x concepts – Bartosz Milewski vergleicht sie mit bzw. erklärt sie anhand von type classes aus Haskell.
-
- Moderator
- Beiträge: 2138
- Registriert: 25.02.2009, 13:37
Re: Ich hasse Java
Aua es tut so weh. Ich habe zwar min gelesen aber lessThan(<) gedacht. Wenn man < schon hat, woher auch immer, ist min doch immer ein Einzeiler. Du willst nicht wirklich diskutieren wo man den hinpackt, wenn man ihn denn überhaupt in eine Funktion packen will (Lesbarkeit? Anderer Grund?).Nein, eben nicht. Man muss nur zwei Zahlen kennen, um sie mit kleiner-als zu vergleichen.
Aber das macht es doch nur noch schlimmer.
Wenn < kein Klassenoperator ist, dann gilt dafür alles was ich oben (fälschlicherweise) für min gesagt habe. Wenn < Klassenoperator ist, ist eine freie Funktion min aus Kapselungsgesichtspunkten doch äquivalent dazu die ursprüngliche Klasse in Zahl und ZahlImplementierung aufzuteilen wobei erstere min und zweitere < hält. Dabei kann ZahlImplementierung dann wieder ausgetauscht werden, ohne min zu beeindrucken. (Ich bin doch recht sicher mal ähnliches von Herb Sutter gelesen zu haben, dass Kapselung über Klassengrenzen geht). Jetzt wirst du sagen ha, aber das geht nicht generisch, was ja auch stimmt, aber wichtig ist doch nur dass OOP keinen Bug hat, und dass man OOP durchaus in konsistenter Weise "vorschreiben" kann. Nur Java tut das eben nicht und C++ erlaubt beides. Aber nichts davon bringt uns hier weiter.
Re: Ich hasse Java
Mhh, dynamisch casten... Ich handel mir also zur Laufzeit eine Exception ein, wenns nicht klappt. Und da soll sich noch einer aufregen dass Smalltalk zur Laufzeit eine Exception schmeisst, wenn ein Objekt die Methode nicht implementiert. Klingt für mich irgendwie gleich, nur ich muss mich vorher mit dem Typsystem erst garnicht rumärgern.
Eine min()-Funktion stützt sich auf instanzseitige Eigenschaften und Funktionen wie <. Daher gehört diese auch auf Instanzseite und nicht irgendwo hin, wo man die Instanz noch als Parameter mit übergibt. Das ist ja schon so, als würde man in C versuchen ein C++ zu bauen, indem man jeder Funktion den this-Zeiger extra übergibt. Richtiges OOP wird in Sprachen wie C++/Java/.NET eh nicht ankommen, solange die ihre primitiven Datentypen durchschleifen und jedesmal Sonderregeln gelten. Ich sag zu sowas auch nur dickes AUUUUAAAAA. Ausserdem ist die min-Implementierung nicht überall gleich, z.B. ein Point.min() kann auch einen neuen Point mit Minimum X und Minimum Y zurückgeben. Point und Number sind in Smalltalk aber von Magnitude abgeleitet, eine generelle Klasse, die einfache arithmetische Dinge wie < > usw. zulässt.
Generische Programmierung in typisierten Sprachen ist deshalb ein Krampf, weil es die Typen gibt :-)
Man versucht alles um sie wegzukriegen oder irgendwie hinzukriegen, damit es wieder typsicher aber generisch wird.
Aber eigentlich gehn einem die Typen bei Generic tierisch auf den Zeiger und man kloppt mit Tonnen von Syntax auf die Konstrukte ein.
In dynamisch typisierten Sprachen hat man all das nicht, weil zur Laufzeit entschieden wird. Was jetzt wohl das neue Schlüsselwort dynamic erledigen soll. Juhuu wieder ein Schlüsselwort mehr, gibt ja so wenige :-)
In dynamischen Sprachen bau ich mir eine Collection wie immer, nur dass ich verschiedene Objekte reinkippe. Ich iteriere genauso mit nem Zwinkern drüber und sortiere, collecte, injecte usw. wie vorher. Weil es eben keine Typen gibt, die mir das Leben schwer machen.
Im Gegensatz dazu prügelt man mit Templates oder neuerdings Concepts auf die Typen ein, bis sie weich genug geschlagen sind, das sie nicht mehr zucken :-)
Und das alles zu dem Preis das der Programmierer vielfach mehr Code schreibt, 10 Tonnen mehr Fehlermeldungen kriegt weil die Syntax so kompliziert ist und die Typsicherheit auch nicht immer hilft, weil man ja dynamic verwendet und somit dasselbe macht wie in dynamischen Sprachen.
Eine min()-Funktion stützt sich auf instanzseitige Eigenschaften und Funktionen wie <. Daher gehört diese auch auf Instanzseite und nicht irgendwo hin, wo man die Instanz noch als Parameter mit übergibt. Das ist ja schon so, als würde man in C versuchen ein C++ zu bauen, indem man jeder Funktion den this-Zeiger extra übergibt. Richtiges OOP wird in Sprachen wie C++/Java/.NET eh nicht ankommen, solange die ihre primitiven Datentypen durchschleifen und jedesmal Sonderregeln gelten. Ich sag zu sowas auch nur dickes AUUUUAAAAA. Ausserdem ist die min-Implementierung nicht überall gleich, z.B. ein Point.min() kann auch einen neuen Point mit Minimum X und Minimum Y zurückgeben. Point und Number sind in Smalltalk aber von Magnitude abgeleitet, eine generelle Klasse, die einfache arithmetische Dinge wie < > usw. zulässt.
Generische Programmierung in typisierten Sprachen ist deshalb ein Krampf, weil es die Typen gibt :-)
Man versucht alles um sie wegzukriegen oder irgendwie hinzukriegen, damit es wieder typsicher aber generisch wird.
Aber eigentlich gehn einem die Typen bei Generic tierisch auf den Zeiger und man kloppt mit Tonnen von Syntax auf die Konstrukte ein.
In dynamisch typisierten Sprachen hat man all das nicht, weil zur Laufzeit entschieden wird. Was jetzt wohl das neue Schlüsselwort dynamic erledigen soll. Juhuu wieder ein Schlüsselwort mehr, gibt ja so wenige :-)
In dynamischen Sprachen bau ich mir eine Collection wie immer, nur dass ich verschiedene Objekte reinkippe. Ich iteriere genauso mit nem Zwinkern drüber und sortiere, collecte, injecte usw. wie vorher. Weil es eben keine Typen gibt, die mir das Leben schwer machen.
Im Gegensatz dazu prügelt man mit Templates oder neuerdings Concepts auf die Typen ein, bis sie weich genug geschlagen sind, das sie nicht mehr zucken :-)
Und das alles zu dem Preis das der Programmierer vielfach mehr Code schreibt, 10 Tonnen mehr Fehlermeldungen kriegt weil die Syntax so kompliziert ist und die Typsicherheit auch nicht immer hilft, weil man ja dynamic verwendet und somit dasselbe macht wie in dynamischen Sprachen.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
Vor der min()-Diskussion waren wir hier – es gab die Behauptung, es sei gut, dass Java alles in Klassen erzwinge. Das finde ich falsch und habe min() als minimales (…) Gegenbeispiel für eine Funktion angeführt, die in keine Klasse gehört. Und dann ist das über die letzten paar Seiten ausgeufert :)Alexander Kornrumpf hat geschrieben:Wenn man < schon hat, woher auch immer, ist min doch immer ein Einzeiler. Du willst nicht wirklich diskutieren wo man den hinpackt, wenn man ihn denn überhaupt in eine Funktion packen will (Lesbarkeit? Anderer Grund?).
Was genau hast du denn gesagt? ’tschuldigung, ich kann nicht folgen.Alexander Kornrumpf hat geschrieben:Wenn < kein Klassenoperator ist, dann gilt dafür alles was ich oben (fälschlicherweise) für min gesagt habe.
Das ist doch totaler Unsinn. Jede Funktion stützt sich irgendwo auf irgendeine Eigenschaft jeder Instanz des Programms; aber soll deshalb alles in eine einzige riesige Gottklasse?! Oder überschwemmt hier dynamische Typisierung meinen Teller?unique75 hat geschrieben:Eine min()-Funktion stützt sich auf instanzseitige Eigenschaften und Funktionen wie <. Daher gehört diese auch auf Instanzseite und nicht irgendwo hin, wo man die Instanz noch als Parameter mit übergibt.
-
- Moderator
- Beiträge: 2138
- Registriert: 25.02.2009, 13:37
Re: Ich hasse Java
Ähm nein: "If you attempt to cast to a pointer type, and that type is not an actual type of the argument object, then the result of the cast will be NULL."Mhh, dynamisch casten... Ich handel mir also zur Laufzeit eine Exception ein, wenns nicht klappt.
Gut da keiner mehr Zeiger verwendet (angeblich) vielleicht auch nicht. Ich verwende Zeiger. Schande über mich.
Um herauszufinden welches von zwei Häusern weniger Fenster hat muss ich nur die Zahl der Fenster kennen, nicht den Rest des Hauses, richtig. Um aber herauszufinden ob eine Zahl kleiner ist als eine andere, muss man den Wert der Zahl kennen und zwar in einer Darstellung die mindestens so genau ist wie die interne Darstellung. Ich behaupte es ist auf einem endlichen Digitalrechner nicht möglich das wirklich ernsthaft zu kapseln. Es ist immer möglich die interne Bitzahl zu verdoppeln, bis die Schnittstelle einen zu kleinen Datentyp verwendet. Alternativ kann die Schnittstelle natürlich ein bitstring beliebiger Länge sein, aber ich denke das schadet auch mehr als es nützt.Was genau hast du denn gesagt? ’tschuldigung, ich kann nicht folgen.
Re: Ich hasse Java
Der Thread erinnert mich daran:
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Ich hasse Java
Meine Erfahrung ist: dynamic typisierte Sprachen sind a) langsam, weil statische Analyse und Typ-Inferenz schwer zu implementieren sind, b) schwer zu debuggen - ein guter Anteil der auftretenden Probleme wuerde von einem statischen Typsystem erkannt und c) saumaessig bequem, wenn a) und b) grade nicht die Suppe versalzen.
Anders ausgedrueckt: alles hat seine Vor- und seine Nachteile. Wer haette das gedacht.
Disclaimer: Ich habe keine Erfahrung mit Smalltalk. Wenn ich von dynamisch typisierten Sprachen spreche, meine ich Python, Ruby, …
Anders ausgedrueckt: alles hat seine Vor- und seine Nachteile. Wer haette das gedacht.
Genau das ist es: Typsicherheit und Generische Programmierung schliessen sich nicht aus.Man versucht alles um sie wegzukriegen oder irgendwie hinzukriegen, damit es wieder typsicher aber generisch wird.
Disclaimer: Ich habe keine Erfahrung mit Smalltalk. Wenn ich von dynamisch typisierten Sprachen spreche, meine ich Python, Ruby, …
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Ich hasse Java
Oooooh, klar klar. Dann habe ich da wohl auch versehentlich auf meine min()-Interpretation statt auf kleiner-als geantwortet … du hast völlig recht, am Ende (in diesem Fall <-Operator) muss man Zugriff auf die Interna haben … und dann gehört der Operator auch in die Klasse selber oder ist, falls alle Stricke reißen, ein Freund.Alexander Kornrumpf hat geschrieben:Um herauszufinden welches von zwei Häusern weniger Fenster hat muss ich nur die Zahl der Fenster kennen, nicht den Rest des Hauses, richtig. Um aber herauszufinden ob eine Zahl kleiner ist als eine andere, muss man den Wert der Zahl kennen und zwar in einer Darstellung die mindestens so genau ist wie die interne Darstellung. Ich behaupte es ist auf einem endlichen Digitalrechner nicht möglich das wirklich ernsthaft zu kapseln. Es ist immer möglich die interne Bitzahl zu verdoppeln, bis die Schnittstelle einen zu kleinen Datentyp verwendet. Alternativ kann die Schnittstelle natürlich ein bitstring beliebiger Länge sein, aber ich denke das schadet auch mehr als es nützt.
@rüp: :D
-
- Moderator
- Beiträge: 2138
- Registriert: 25.02.2009, 13:37
Re: Ich hasse Java
Das eigentliche Argument ist wohl dass die Klassengrenze total arbiträr ist. In vielen Fällen hat man wohl aus praktischen Gründen eine Klasse wo nach strengen Regeln eher ein Wrapper um einen Wrapper um einen Wrapper angebracht wäre. Ok, du vielleicht nicht, aber die sterblichen unter uns.
Re: Ich hasse Java
Genau das tut ihr aber. Man sieht allzu häufig eine Gott-ähnliche Math-Klasse in diversen Engines, die dann 20 oder mehr Funktionen wie sin, cos, sqrt, min, max für alle möglichen Typkombinationen überladen enthält. Das ist mal verkorkstes OOP und totaler Unsinn. Ich brauch nur in den Quellcode der OGRE-Engine schaun und krieg nen Schreikrampf bei dem OOP-Design. Aber ok dank primitiver Datentypen ist es ja auch ein Krampf in C++. Man schiebt doch solche Methoden wie min() nicht deshalb in eine Math-Klasse, nur weil sie nicht auf den Rohdaten arbeitet. Dann würde man 90% der Methoden nicht da haben wo sie sind.
Dynamische Sprachen sind langsamer, wenn es um reine Arithmetik geht. 10% eines Programms enthalten Hotspots. Da mach ich also lieber 90% richtig und für die 10% dann mal eine kleine C-Routine extern. Dafür habe ich aber eine Menge Stress gespart und bin paar Jahre eher fertig :-)
Statische Typen will man da nicht, weil es alles nur verkompliziert. Die Typen nützen auch nix gegen Runtime-Fehler wie Bufferoverflow, falscher Indizierung in Arrays usw. usw. Davor bewahrt mich aber eine VM z.B.
Debugging wie in Smalltalk (Visualworks oder Pharo) geht nicht einfacher. VisualStudio und Eclipse ist ein Krampf dagegen. Man kann im Stack beliebig zurücksetzen, eine Methode neu anfangen, Code überspringen ohne Ausführung, mit Ausführung, direkt im Debugger den Code umändern und weiterlaufen usw. Es ist wie ein Interpreter, aber im Hintergrund wird JIT-kompiliert. Und man kann mehrere Debugger gleichzeitig öffnen und quasi debuggten Code nochmal debuggen, weil man nochmal kurz ein Codeschnipsel verstehen will.
Dynamische Sprachen sind langsamer, wenn es um reine Arithmetik geht. 10% eines Programms enthalten Hotspots. Da mach ich also lieber 90% richtig und für die 10% dann mal eine kleine C-Routine extern. Dafür habe ich aber eine Menge Stress gespart und bin paar Jahre eher fertig :-)
Statische Typen will man da nicht, weil es alles nur verkompliziert. Die Typen nützen auch nix gegen Runtime-Fehler wie Bufferoverflow, falscher Indizierung in Arrays usw. usw. Davor bewahrt mich aber eine VM z.B.
Debugging wie in Smalltalk (Visualworks oder Pharo) geht nicht einfacher. VisualStudio und Eclipse ist ein Krampf dagegen. Man kann im Stack beliebig zurücksetzen, eine Methode neu anfangen, Code überspringen ohne Ausführung, mit Ausführung, direkt im Debugger den Code umändern und weiterlaufen usw. Es ist wie ein Interpreter, aber im Hintergrund wird JIT-kompiliert. Und man kann mehrere Debugger gleichzeitig öffnen und quasi debuggten Code nochmal debuggen, weil man nochmal kurz ein Codeschnipsel verstehen will.
- Schrompf
- Moderator
- Beiträge: 5045
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Ich hasse Java
Schade. Ich hatte den Thread noch gemocht, als es mit sachtem Humor über Java herging. Dann tauchte ein Fanatiker auf, liest nur Bruchteile der Antworten, sucht sich eins zwei isolierte Worte daraus aus und lässt die nächste Tirade vom Stapel. Schade drum. Wollen wir nicht zurück zum Lästern?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.