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



  • Sorry dass ich mich so kurz fasse, aber 1. will ich noch weg & 2. machst du's mir recht leicht:

    Gregor schrieb:

    Jetzt mal die Gegenfrage: Wie hälst Du deinen Code halbwegs strukturiert, wenn globale Funktionen eine nennenswerte Rolle spielen? Wie gehst Du dann mit der Komplexität des Sourcecodes um? Oder bezieht sich bei dir alles auf kleine Projekte, die man eh sofort überblickt?

    Java-Package == C++-Namespace
    Was auch einleuchten dürfte wenn man sich vor Augen hält was ein "Package" logisch gesehen ist.
    Die Doku aufzutreiben ist auch kein allzu großer Akt, und auch nicht unbedingt immer so dramatisch solang man geschickte Bezeichner wählt und sich darauf verlassen kann dass das 'versprochene' korrekt implementiert ist. Ist ja auch nicht so dass man freie Funktionen nirgendwo included/importiert/your-keyword-here... oder qualifizierst du in Java sämtliche Klassen explizit?



  • finix schrieb:

    Java-Package == C++-Namespace
    Was auch einleuchten dürfte wenn man sich vor Augen hält was ein "Package" logisch gesehen ist.

    Dir ist es jedenfalls noch nicht eingeleuchtet. Ein package hat in Java weit mehr Sinn als eine namespace-Funktion. Ein package ist ein Paket von Klassen, eine einzeln sinnvolle Programmkomponente und die Klassen darin können sich gegenseitig Einblick in ihre Internas gestatten, was ein ähnlicher Mechanismus wie friend ist. In .Net wird diese Aufgabe von Assemblies erfüllt, in C++ gibt es gar kein Aquivalent dazu.

    Ein so offensichtlicher, fett geschriebener Fehler zeigt doch schon, dass du die Ideen wenigstens teilweise nicht verstanden hast.



  • finix schrieb:

    Java-Package == C++-Namespace

    Dass das falsch ist hat Optimizer ja schon gesagt. (package private...)

    Was ist den nun eigentlich ein Vorteil von freien Funktionen? Das man weniger scheiben muss?



  • Dingens schrieb:

    Was ist den nun eigentlich ein Vorteil von freien Funktionen? Das man weniger scheiben muss?

    In C++ ist ein Namespace offen eine Klasse hingegen geschlossen. Du kannst also beliebig viele neue Funktionen zu einem Namespace hinzufügen ohne das du dazu an einem zentralen Ort was ändern musst (oder neu übersetzen). Das ist der physische Unterschied. Der logische Unterschied besteht darin, dass eine freie Funktion besser verdeutlicht, dass sie unabhängig von der Repräsentation einer Klasse ist.
    Stark vereinfacht: wenn eine Klasse 10 Methoden hat und ich ändere die interne Repräsentation, dann muss ich 10 Methoden prüfen. Hat die Klasse nur 3 Methoden und dafür 7 freie Funktionen, so muss ich nur 3 Methoden bei der selben Änderung
    prüfen (wobei sich dabei natürlich rausstellen kann, dass ich 7 Methoden über 3 Hauptmethoden implementiert habe). Das ist genaugenommen natürlich kein Vorteil einer freien Funktion. Der Vorteil ergibt sich vielmehr aus der Unterscheidung zwischen zwei Arten von Methoden: eine die auf Daten zugreift und eine die nur die öffentliche Schnittstelle verwendet. In C++ kann ich diese Unterscheidung über die Verwendung von Memberfunktionen einerseits und freien Funktionen andererseits ausdrücken.

    In C++ kann eine Klasse mit minimalem Interface dank freier Funktionen zu einer Klasse mit einem (erweiterbaren) komfortabelen Interface (manche würde auch fettes Interface sagen) werden, ohne das dazu die Klasse verändert werden muss.

    Das gesagte bezieht sich natürlich nur auf C++ und ist keine Aussage über andere Sprachen. Mir ist allerdings die Diskussion hier sowieso nicht klar. Was hätte man davon, wenn man in einer Sprache wie Java aufeinmal freie Funktionen anbieten würde?
    Kommt man da nicht letztlich irgendwann zu der Frage:"was ist der Vorteil einer Ein-Paradigma-Sprache gegenüber einer Mehr-Paradigmen-Sprache?"?



  • HumeSikkins schrieb:

    Kommt man da nicht letztlich irgendwann zu der Frage:"was ist der Vorteil einer Ein-Paradigma-Sprache gegenüber einer Mehr-Paradigmen-Sprache?"?

    Nun versöhnt euch wieder vorm Osternest, lasst das Frickeln und Streiten und besinnet euch auf die wahren Werte des Lebens! Mein erstes Puzzlebuch Ostern | ISBN: 3473312932



  • Statt meine Klassen mit privaten Helferfunktionen zuzumüllen mache ich oft sowas:

    statt

    class Foo
    {
      void helper1(int);
      void helper2(string);
      void helper3(double);
      void helper(); //verwendet helper1,2,3
    };
    

    mache ich das so:

    class Foo
    {
      void helper();
    };
    
    //in foo.cpp
    namespace
    {
      void helper1(int){}
      void helper2(string){}
      void helper3(double){}
    }
    

    Meist braucht nur "helper" zugriff auf die ganzen Membervariablen und die kleinen Hilfsfunktionen von helper sind nur dazu da den code übersichtlicher zu gestalten indem details ausgelagert werden.



  • Funktionen sind auch nur Objekte.

    einObjekt := 'Hallo Welt!'.
    
    andersObjekt := [ :eachChar|
        Transcript show: eachChar ; cr.
    ].
    


  • Optimizer schrieb:

    finix schrieb:

    Java-Package == C++-Namespace
    Was auch einleuchten dürfte wenn man sich vor Augen hält was ein "Package" logisch gesehen ist.

    Dir ist es jedenfalls noch nicht eingeleuchtet. Ein package hat in Java weit mehr Sinn als eine namespace-Funktion. Ein package ist ein Paket von Klassen, eine einzeln sinnvolle Programmkomponente und die Klassen darin können sich gegenseitig Einblick in ihre Internas gestatten, was ein ähnlicher Mechanismus wie friend ist. In .Net wird diese Aufgabe von Assemblies erfüllt, in C++ gibt es gar kein Aquivalent dazu.

    Ein so offensichtlicher, fett geschriebener Fehler zeigt doch schon, dass du die Ideen wenigstens teilweise nicht verstanden hast.

    Ok, nochmal für die Leute die mit dem Begriff "Kontext" nicht klar kommen oder unfähig sind von irrelevanten Details zu abstrahieren:

    Java: Package -> package
    C++:  Package -> namespace
    ...
    


  • finix schrieb:

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

    Ich hatte bis jetzt immer den OO-Aspekt deiner Frage übersehen. Sorry.

    Naja, die Objektorientierung ist letztendlich eine Art Weltsicht. Guck da doch mal dein reales Umfeld an: Gibt es da Interaktionsmöglichkeiten, die nicht an irgendwelche Dinge oder abstrakte Konzepte gebunden sind? Gib mal das äquivalente Konzept zu einer "freien Funktion" in deinem echten Leben an.



  • Könntet ihr das Ganze mal vor dem Hintergrund einer wirklich objektorientierten Sprache sehen, wie z.B. Smalltalk. Dann wird auch meine Aussage meines letzten Posts ersichtlich.
    Nur weil Java zu beschränkt ist, um Funktionen als Objete zu behandeln, heißt das nciht, dass das generel so im Objektorientierten Universum sein muss.

    In einer Sprache wie Smalltalk ist eben alles ein Objekt, auch Funktionen (Codeblöcke mit Parametern).

    Gibt es globale Variablen, gibt es somit dann automatisch globale Funktionen und sie sind vollkommen oo, da es egal ist, ob die Variable auf einen String, eine Zahl oder eine Funktion verweist. Es stekt einfach ein Objekt dahinter, dass gewisse Nachrichten versteht und andere eben nicht.



  • finix schrieb:

    Optimizer schrieb:

    finix schrieb:

    Java-Package == C++-Namespace
    Was auch einleuchten dürfte wenn man sich vor Augen hält was ein "Package" logisch gesehen ist.

    Dir ist es jedenfalls noch nicht eingeleuchtet. Ein package hat in Java weit mehr Sinn als eine namespace-Funktion. Ein package ist ein Paket von Klassen, eine einzeln sinnvolle Programmkomponente und die Klassen darin können sich gegenseitig Einblick in ihre Internas gestatten, was ein ähnlicher Mechanismus wie friend ist. In .Net wird diese Aufgabe von Assemblies erfüllt, in C++ gibt es gar kein Aquivalent dazu.

    Ein so offensichtlicher, fett geschriebener Fehler zeigt doch schon, dass du die Ideen wenigstens teilweise nicht verstanden hast.

    Ok, nochmal für die Leute die mit dem Begriff "Kontext" nicht klar kommen oder unfähig sind von irrelevanten Details zu abstrahieren:

    Java: Package -> package
    C++:  Package -> namespace
    ...
    

    Alter Schwede... diese Details sind keineswegs irrelevant, weil packages Zugriffskontrolle zwischen Programmkomponenten regeln. Etwas in dieser Art gibt es in C++ nicht. Das sind ganz wesentliche Aspekte, die beim Design einer Anwendung beachtet werden müssen. Gerade dass es in C# auch namespaces gibt, das eigentliche Äquivalent zu packages aber Assemblies sind, sollte dir zu denken geben.



  • Helium schrieb:

    In einer Sprache wie Smalltalk ist eben alles ein Objekt, auch Funktionen (Codeblöcke mit Parametern).

    Ich kenne Smalltalk leider nicht. Kannst Du da mal ein kleines Beispiel bringen, inwiefern Funktionen da als Objekte behandelt werden bzw. wie man mit denen als Objekt umgeht?



  • finix = troll?



  • Bei Python ist auch alles nen Objekt



  • Optimizer schrieb:

    Alter Schwede... diese Details sind keineswegs irrelevant, weil packages Zugriffskontrolle zwischen Programmkomponenten regeln. Etwas in dieser Art gibt es in C++ nicht. Das sind ganz wesentliche Aspekte, die beim Design einer Anwendung beachtet werden müssen. Gerade dass es in C# auch namespaces gibt, das eigentliche Äquivalent zu packages aber Assemblies sind, sollte dir zu denken geben.

    Es ging um diese Frage:

    Gregor schrieb:

    Wie hälst Du deinen Code halbwegs strukturiert, wenn globale Funktionen eine nennenswerte Rolle spielen? ...

    Nicht darum dass Java-packages genau equivalent zu C++-Namespaces sind, nichtmal um die Sprache an sich sondern wie es man das strukturiert. Package im Sinne von "ein Paket von Klassen, Funktionalität, eine einzeln sinnvolle Programmkomponente."



  • @finix: Du versuchst hier auf einer Art Metaebene den Argumenten der anderen Diskussionsteilnehmer aus dem Weg zu gehen. Du sagst dir einfach "Alles, was die anderen bringen ist aus dem Kontext gerissen und sowieso nur auf unnötige Details bezogen.". ...oder ähnliches. Das kannst Du ja meinetwegen denken, aber wenn Du willst, dass Dich die anderen Diskussionsteilnehmer auf Dauer ernst nehmen, solltest Du etwas genauer erklären, warum welche Aussage in die falsche Richtung geht. Du gehst nämlich überhaupt nicht auf die sachlichen Argumentationen der anderen ein. Es ist, als ob man bei Dir gegen eine Wand redet: Man erhält keinerlei sinnvolle Reaktion zurück, auf der man aufbauen kann.

    Da kommt es dann natürlich auch dazu, dass jemand einen Vergleich "finix = troll?" macht. ...und Du kannst mal davon ausgehen, dass andere auch schon etwas in diese Richtung denken, auch wenn sie die Diskussion noch nicht aufgeben möchten.



  • finix schrieb:

    Es ging um diese Frage:

    Gregor schrieb:

    Wie hälst Du deinen Code halbwegs strukturiert, wenn globale Funktionen eine nennenswerte Rolle spielen? ...

    Nicht darum dass Java-packages genau equivalent zu C++-Namespaces sind, nichtmal um die Sprache an sich sondern wie es man das strukturiert. Package im Sinne von "ein Paket von Klassen, Funktionalität, eine einzeln sinnvolle Programmkomponente."

    Ja. ...und du hast bei der Beantwortung der Frage auch alles aus dem Kontext gerissen. Da gab es nämlich auch noch ein

    finix schrieb:

    Gregor schrieb:

    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.

    Auch gut, was ist an "globalen Funktionen" so furchtbar schlimm?

    davor. Du hast bei der Beantwortung der Frage keine Namespaces zur Verfügung. 😉



  • Any schrieb:

    Statt meine Klassen mit privaten Helferfunktionen zuzumüllen mache ich oft sowas:

    statt

    class Foo
    {
      void helper1(int);
      void helper2(string);
      void helper3(double);
      void helper(); //verwendet helper1,2,3
    };
    

    mache ich das so:

    class Foo
    {
      void helper();
    };
    
    //in foo.cpp
    namespace
    {
      void helper1(int){}
      void helper2(string){}
      void helper3(double){}
    }
    

    Meist braucht nur "helper" zugriff auf die ganzen Membervariablen und die kleinen Hilfsfunktionen von helper sind nur dazu da den code übersichtlicher zu gestalten indem details ausgelagert werden.

    wo ist hier den der Vorteil? die Helper-Methoden sind doch eh private, da ist es vollkommene egal ob ich 100 oder 1000 davon habe.

    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.

    globale Funktionen sind für mich Funktionen die keinen Kontex haben, zu nichts in Bezug stehen. Ein Namespace stellt aber ein Bezug her.

    Die Funktion sort(bla[] x) hat für mich keinen Bezug. Ich habe absolut keine Ahnung was sie macht, sortiert sie auf- oder absteigend? Oder mit Quiksort oder mit Mergesort?
    Quicksort.sort(bla[] x). Aha, da wird einem sofort klar, das die statische-Methode nach dem Quicksort-Prinzip sortiert.

    ein weiterer Vorteil:
    wenn ich eine Funktion sin(double x) habe im system.h und irgendwann importiere ich winsystem.h und die Header hat auch eine sin(double x)-Funktion, welche Funktion soll den nu der Compiler benutzen?

    Fazit: Globale Funktionen sind vollkommen Sinnfrei und führen nur in größeren Projekten zum totalen Chaos. Deswegen wurden ja in C++ die Namespaces eingeführt und von Java, C# und co. übernommen und verbessert.



  • Gregor schrieb:

    @finix: Du versuchst hier auf einer Art Metaebene den Argumenten der anderen Diskussionsteilnehmer aus dem Weg zu gehen. Du sagst dir einfach "Alles, was die anderen bringen ist aus dem Kontext gerissen und sowieso nur auf unnötige Details bezogen.". ...oder ähnliches.

    Mir ist nicht ganz klar was du hier mit "Metaebene" meinst, aber von meinem Verständnis des Wortes her wär damit wohl etwas wie "Zitat: 'finix = troll'" gemeint.

    Aber ich sehe was du meinst:

    Gregor schrieb:

    finix schrieb:

    Gregor schrieb:

    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.

    Auch gut, was ist an "globalen Funktionen" so furchtbar schlimm?

    ... Du hast bei der Beantwortung der Frage keine Namespaces zur Verfügung. 😉

    Hatte das gestern komplett falsch gelesen; war ein wenig abgelenkt und hab mehr oder weniger nur globale Funktionen in Anführungszeichen gedeutet... dachte der Begriff "freie Funktionen" war nicht mehr missverständlich. Ging mir also, wie schon zuvor erklärt eigentlich nur um die Antwort auf deine konkrete Frage, spricht abstrakt "Package = logische Programmeinheit" bildet sich in C++ auf Namespaces ab wie es sich in Java auf Packages abbildet.
    Von daher seh ich natürlich auch wie für Opti Details die für mich im Kontext irrelevant erschienen durchaus alles andere als irrelevant sind.



  • Gregor schrieb:

    @finix: Du versuchst hier auf einer Art Metaebene den Argumenten der anderen Diskussionsteilnehmer aus dem Weg zu gehen. Du sagst dir einfach "Alles, was die anderen bringen ist aus dem Kontext gerissen und sowieso nur auf unnötige Details bezogen.". ...oder ähnliches. Das kannst Du ja meinetwegen denken, aber wenn Du willst, dass Dich die anderen Diskussionsteilnehmer auf Dauer ernst nehmen, solltest Du etwas genauer erklären, warum welche Aussage in die falsche Richtung geht. Du gehst nämlich überhaupt nicht auf die sachlichen Argumentationen der anderen ein. Es ist, als ob man bei Dir gegen eine Wand redet: Man erhält keinerlei sinnvolle Reaktion zurück, auf der man aufbauen kann.

    Da kommt es dann natürlich auch dazu, dass jemand einen Vergleich "finix = troll?" macht. ...und Du kannst mal davon ausgehen, dass andere auch schon etwas in diese Richtung denken, auch wenn sie die Diskussion noch nicht aufgeben möchten.

    /signed


Anmelden zum Antworten