An die OOP-Fetischisten- & Dogmatiker: Freie Funktionen!?



  • Was spricht aus OOP-Sicht gegen Freie Funktionen?
    (Vielleicht täusche ich mich, aber ich hab oft den Eindruck dass für OOP-Puristen Freie Funktionen das neue goto sind...)

    (edit: "OOP-Puristen" statt "OOP-Extremisten")



  • Und?!



  • Was sind denn freie Funktionen?



  • Funktionen halt (-> alle Funktionen, die keine Methoden sind).



  • .filmor schrieb:

    Und?!

    Eh? 😕
    Weißt du mit dem ?-Zeichen nichts anzufangen oder was?

    Artchi schrieb:

    Was sind denn freie Funktionen?

    Funktionen die keine Methoden sind.



  • Doch, aber ich ignoriere fettgedruckte Überschriften aus Prinzip 😉

    Gegen sie spricht, dass man versucht, alle Funktionalität in den Beziehungen zwischen den Objekten auszudrücken. Funktionen, die es durchaus noch gibt, falls man nicht krampfhaft versucht, rein objektorientiert zu programmieren, s. <algorithm>, sind allgemeine Verfahren, die nicht zum Objekt gehören, sondern etwas mit diesem anstellen.



  • Was spricht aus OOP-Sicht gegen Freie Funktionen?

    Pragmatisch gesprochen z.B.das viele OOP-only Sprachen sie gar nicht unterstützen.

    Ansonsten würde ich aber sagen: eine Funktion, die nicht auf die interne Repräsentation eines Objekts zugreifen muss, sollte, wenn möglich, frei sein. Gute Gründe dafür liefert Scott Meyers in seinem Artikel:
    How Non-Member Functions Improve Encapsulation



  • .filmor schrieb:

    Doch, aber ich ignoriere fettgedruckte Überschriften aus Prinzip 😉

    Heh. Ich hab's extra fett gestaltet damit man weiß worum's geht und sich nicht auf mein nachgelagertes blablah stürzt 😃

    .filmor schrieb:

    Gegen sie spricht, dass man versucht, alle Funktionalität in den Beziehungen zwischen den Objekten auszudrücken. Funktionen, die es durchaus noch gibt, falls man nicht krampfhaft versucht, rein objektorientiert zu programmieren, s. <algorithm>, sind allgemeine Verfahren, die nicht zum Objekt gehören, sondern etwas mit diesem anstellen.

    Und was genau ist nun so schlecht daran?
    Was bring z.B. java.lang.Math für Vorteile? (vor 5.0, oder 1.5, vor free funcs in j aka static import...)



  • HumeSikkins schrieb:

    Was spricht aus OOP-Sicht gegen Freie Funktionen?

    Pragmatisch gesprochen z.B.das viele OOP-only Sprachen sie gar nicht unterstützen.

    Klar, ging mir aber nicht so sehr (oder gar nicht) um's pragmatische sondern um die Begründung, falls vorhanden, die Idee, Ideologie die dahinter steckt (oder auch nicht) - "The OOP Mindset" sozusagen.

    HumeSikkins schrieb:

    Ansonsten würde ich aber sagen: eine Funktion, die nicht auf die interne Repräsentation eines Objekts zugreifen muss, sollte, wenn möglich, frei sein. Gute Gründe dafür liefert Scott Meyers in seinem Artikel:
    How Non-Member Functions Improve Encapsulation

    Ja, danke, aber das ist mir alles durchaus bekannt & bewusst.

    Mir geht's eher um die Begründung der OOP-Puristen gegen freie Funktionen...



  • Gib ein Beispiel. Falls du den Mischmasch à la C++ meinst: da ist der Namespace von freien Funktionen einfach unbekannt.

    Dadurch dass du dir mit deinen Headern deine Funktionen sonstwoher holst, ist gar nicht zu überblicken in welchem Kontext jetzt welche Funktion steht.

    Wenn du Methoden nur innerhalb von Klassen zulässt, hat sich das Problem gegessen: eine Methode ist IMMER einem bestimmten Objekt zugehörig, und die Definition dieses Objekts ist garantiert einzigartig.

    Im übrigen widerspricht es halt der OOP Vorstellung, dass ALLES in der Welt ein Objekt ist. In Java ist z.B. selbst eine Klasse ein Objekt. Eine Eigenschaft oder ein Verhalten ohne dazugehöriges Objekt ist irgendwie sinnfrei. Wenn du "laufen" sagst, musst du auch sagen, was dies tut.



  • finix schrieb:

    Was bring z.B. java.lang.Math für Vorteile? (vor 5.0, oder 1.5, vor free funcs in j aka static import...)

    java.lang.Math wird ja eher als so eine Art "Namespace" genutzt. Die Methoden darin sind alle statisch. Man kennt dadurch also gleich den Ort, wo man etwas über die Methoden erfahren kann. Was wäre denn die Alternative? So eine Art globale Funktionen, wo keiner weiß, wo die definiert sind, wo die Dokumentation dazu zu suchen ist, was es in diesem Themengebiet eigentlich alles für Funktionen gibt usw.? Aus diesem Grund sind static imports in Java 5.0 auch nicht gerne gesehen: Man kann mit denen nicht mehr so schnell herausfinden, wo eine Methode zu finden ist (es sei denn, man hat eine IDE, die das ausgleicht).



  • std::sort auf Iteratoren ist in C++ zehnmal mächtiger als wenn man das Ganze auf die Containerklassen beschränkt hätte. Ich definier mir nen neuen Containertyp, definier nen random-access Iterator dafür und das Ding läuft.

    Wenn ich dafür extra von ner Basisklasse ableiten müsste und dann noch die genau gleichen Membernamen verwenden müsste, etc. dann hätte ich viel mehr von der Kapselung verloren nach außen.

    Ja das ganze hätte man auch in eine Klasse "algorithms" packen können. Aber wozu? Es ist nunmal kein Objekt, es ist einfach nur ein simpler Namespace.



  • mon schrieb:

    Gib ein Beispiel. Falls du den Mischmasch à la C++ meinst: da ist der Namespace von freien Funktionen einfach unbekannt.

    Schwachfug.

    mon schrieb:

    Dadurch dass du dir mit deinen Headern deine Funktionen sonstwoher holst, ist gar nicht zu überblicken in welchem Kontext jetzt welche Funktion steht.

    Ja, super Punkt. Genau aus diesem Grund importiere ich in Java auch keine Packages die ich nicht selber kenne. Oder so in der Richtung. 🙄

    mon schrieb:

    Wenn du Methoden nur innerhalb von Klassen zulässt, hat sich das Problem gegessen: eine Methode ist IMMER einem bestimmten Objekt zugehörig, und die Definition dieses Objekts ist garantiert einzigartig.

    Häh?

    mon schrieb:

    Im übrigen widerspricht es halt der OOP Vorstellung, dass ALLES in der Welt ein Objekt ist. In Java ist z.B. selbst eine Klasse ein Objekt. Eine Eigenschaft oder ein Verhalten ohne dazugehöriges Objekt ist irgendwie sinnfrei. Wenn du "laufen" sagst, musst du auch sagen, was dies tut.

    Das ist genau Kern meiner Frage: warum widerspricht es der OOP-Vorstellung?



  • Gregor schrieb:

    finix schrieb:

    Was bring z.B. java.lang.Math für Vorteile? (vor 5.0, oder 1.5, vor free funcs in j aka static import...)

    java.lang.Math wird ja eher als so eine Art "Namespace" genutzt. Die Methoden darin sind alle statisch. Man kennt dadurch also gleich den Ort, wo man etwas über die Methoden erfahren kann. Was wäre denn die Alternative? So eine Art globale Funktionen, wo keiner weiß, wo die definiert sind, wo die Dokumentation dazu zu suchen ist, was es in diesem Themengebiet eigentlich alles für Funktionen gibt usw.? Aus diesem Grund sind static imports in Java 5.0 auch nicht gerne gesehen: Man kann mit denen nicht mehr so schnell herausfinden, wo eine Methode zu finden ist (es sei denn, man hat eine IDE, die das ausgleicht).

    Versteh mich nicht falsch, aber was du hier schreibst ist absoluter Unfug. Genau wegen solchen Äußerungen hatte ich die Formulierungen "Dogmatiker", "Fetischisten" & "Extremisten" verwandt.

    Dein erster Satz spiegelt genau meinen Eindruck wieder - weil es dass adequate Sprachmittel, sprich freie Funktionen in einem Namespace nicht gibt wird ein Objekt hergenommen und mit statischen Methoden bevölkert.

    Mit dieser Erklärung, auch wenn du nicht so deutlich wurdest, hättest du es belassen sollen; aber nein, du verteidigst diese Unzulänglichkeit nicht nur (was, gute Argumente vorausgesetzt, nichts schlimmes ist) sondern preist diese Einschränkung als Vorteil an (was ziemlich albern ist).

    Und wenn du so gegen static imports wetterst lass dir gesagt sein dass man auch in z.B. C++ auf using-Direktiven verzichten kann und versuch dich bitte nochmal an einer Antwort.



  • 3dckopierer schrieb:

    std::sort auf Iteratoren ist in C++ zehnmal mächtiger als wenn man das Ganze auf die Containerklassen beschränkt hätte. Ich definier mir nen neuen Containertyp, definier nen random-access Iterator dafür und das Ding läuft.

    Wenn ich dafür extra von ner Basisklasse ableiten müsste und dann noch die genau gleichen Membernamen verwenden müsste, etc. dann hätte ich viel mehr von der Kapselung verloren nach außen.

    Ja das ganze hätte man auch in eine Klasse "algorithms" packen können. Aber wozu? Es ist nunmal kein Objekt, es ist einfach nur ein simpler Namespace.

    Das statisch in eine Klasse zu packen ist ja auch nicht objektorientiert. Korrekt wäre es, eine Sorter-Klasse zu haben, die einen bestimmten Algorithmus implementiert und mit einem bestimmten Comparer (oder was der Algorithmus braucht) instanziert wird. Das nennt sich dann übrigens das Strategy-Pattern.



  • Optimizer schrieb:

    Korrekt wäre es, eine Sorter-Klasse zu haben, die einen bestimmten Algorithmus implementiert und mit einem bestimmten Comparer (oder was der Algorithmus braucht) instanziert wird. Das nennt sich dann übrigens das Strategy-Pattern.

    Das mach ich übrigens ganz häufig. 😃 ...aber ich bin ja wohl auch ein "OOP-Dogmatiker, -Fetischist & -Extremist"! 😮 🤡



  • Optimizer schrieb:

    Das statisch in eine Klasse zu packen ist ja auch nicht objektorientiert. Korrekt wäre es, eine Sorter-Klasse zu haben, die einen bestimmten Algorithmus implementiert und mit einem bestimmten Comparer (oder was der Algorithmus braucht) instanziert wird. Das nennt sich dann übrigens das Strategy-Pattern.

    Was ist jetzt genau der Vorteil gegenüber

    template <class RandomAccessIterator, class StrictWeakOrdering>
    void sort(RandomAccessIterator first, RandomAccessIterator last,
              StrictWeakOrdering comp);
    

    😕



  • Gregor schrieb:

    Optimizer schrieb:

    Korrekt wäre es, eine Sorter-Klasse zu haben, die einen bestimmten Algorithmus implementiert und mit einem bestimmten Comparer (oder was der Algorithmus braucht) instanziert wird. Das nennt sich dann übrigens das Strategy-Pattern.

    Das mach ich übrigens ganz häufig. 😃 ...aber ich bin ja wohl auch ein "OOP-Dogmatiker, -Fetischist & -Extremist"! 😮 🤡

    Schön dass ihr euch einig seid. Ich steh auch auf das Strategy-Pattern. Ganz toll.

    Könntest du jetzt auf mein Posting eingehen?
    Bereitet dir das Probleme oder fühlst du dir einfach auf den Schlips getreten?



  • finix schrieb:

    Optimizer schrieb:

    Das statisch in eine Klasse zu packen ist ja auch nicht objektorientiert. Korrekt wäre es, eine Sorter-Klasse zu haben, die einen bestimmten Algorithmus implementiert und mit einem bestimmten Comparer (oder was der Algorithmus braucht) instanziert wird. Das nennt sich dann übrigens das Strategy-Pattern.

    Was ist jetzt genau der Vorteil gegenüber

    template <class RandomAccessIterator, class StrictWeakOrdering>
    void sort(RandomAccessIterator first, RandomAccessIterator last,
              StrictWeakOrdering comp);
    

    😕

    Der Sorter ist zur Laufzeit austauschbar. Und es ist natürlich objektorientierter, weil der Algorithmus selber in ein Objekt gefasst ist. Das muss nicht jeder als Vorteil sehen, aber die Frage war ja an OOP-Dogmatiker gestellt.



  • finix schrieb:

    Dein erster Satz spiegelt genau meinen Eindruck wieder - weil es dass adequate Sprachmittel, sprich freie Funktionen in einem Namespace nicht gibt wird ein Objekt hergenommen und mit statischen Methoden bevölkert.

    Es existiert kein Objekt von Math. Die Methoden in Math sind an kein Objekt gebunden, es muss keins erzeugt werden, um diese Methoden zu nutzen. Die Nutzung der Klasse ist hier in der Tat äquivalent zur Nutzung eines Namespaces. Was da vorhin über "Klassen sind in Java selbst Objekte" gesagt wurde, ist auf einer ganz anderen ebene. Ich vermute mal, deshalb bist Du hier auf den Begriff Objekt gekommen.

    Vielleicht bin ich etwas zu pragmatisch, wenn ich sage, dass man Klassen einfach so als Namespace verwenden kann. Aber sag mir doch mal, inwiefern das unpassend ist. Was bietet Dir ein Namespace, was dir eine Klasse nicht bieten kann? Die Nutzung ist doch sehr ähnlich. ...nur, dass ne Klasse im Zweifelsfall auch mehr kann.

    Insofern braucht eine Sprache wie Java keine Namespaces. das wäre ein Feature, das bereits völlig äquivalent durch ein anderes Sprachfeature abgedeckt ist. Da fehlt nichts als "adäquates Sprachmittel".

    finix schrieb:

    Mit dieser Erklärung, auch wenn du nicht so deutlich wurdest, hättest du es belassen sollen; aber nein, du verteidigst diese Unzulänglichkeit nicht nur (was, gute Argumente vorausgesetzt, nichts schlimmes ist) sondern preist diese Einschränkung als Vorteil an (was ziemlich albern ist).

    Ok, könntest Du mir nochmal sagen, inwiefern das eine Einschränkung darstellt? Ich hatte das mit globalen Funktionen verglichen und halte weiterhin alles was ich dazu gesagt habe für richtig. Globale Funktionen haben Nachteile, was die ganz praktische Nutzung betrifft. Darüber kann man sich ruhig im Klaren sein.

    finix schrieb:

    Und wenn du so gegen static imports wetterst lass dir gesagt sein dass man auch in z.B. C++ auf using-Direktiven verzichten kann und versuch dich bitte nochmal an einer Antwort.

    Ich habe keine Äußerung zu C++ gemacht?!

    PS: Mit "globalen Funktionen" meinte ich bisher immer Funktionen, die sich in keinem Namespace befinden und auch nicht an eine Klasse oder ähnliches gebunden sind. Weiß nicht, ob die allgemeine Definition davon anders ist. Vielleicht liegt da ein gewisses Missverständnis zwischen uns vor.


Log in to reply