Vorstellung der Sprache C-mol - methodenorientierte Softwareentwicklung



  • Seh ich das eigentlich mit der Formulierung der folgenden Maxime richtig:

    Cmol legt einfach nochmals ein Abstraktionslevel auf mein Klassensystem welcher es mir ermöglicht, für gleiche Aktionen mit unterschiedlichen Objekten die selbe Methode aufzurufen?

    -junix



  • @Bashar:
    Interessant! Also CLOS kannte ich vorher noch gar nicht. Habs mir halt nur mal kurz angesehn. Aber es scheint tatsächlich einiges an Übereinstimmung zu C-mol zu geben. Kann man diese "generischen" Areas auch vererben (wie in C-mol), so dass man die Prolog/Epilog-Idee (bzw. Before/After) auf höheren Abstraktionsebenen weiterführen kann?

    @junix:
    Wie gesagt: Ich dachte eigentlich ich hab schon ein paar ganz gute Beispiele angeboten. Natürlich ist es so, dass sich C-mol umso mehr lohnt, je größer das Projekt ist, aber ich hab hier ja auch schon ein paar Anwendungsfälle beschreiben. Nochmal der Verweis zu einer Übersicht, die die Anwendungsgebiete meiner Meinung nach recht gut zusammen fast:

    http://www.mosd.net/files/MOP-Overview.pdf



  • @junix:
    Ich würde nicht unbedingt sagen, dass es ein Abstraktionslevel auf das Klassensystem legt. Ich würde aus Sicht eines Objektorienierers eher sagen, die MOP stellt eine Art "Querverstrebung in der Klassenhierarchie" dar!

    Ansonsten ja: Es werden sonst gleichartige Aktionen auf verschiedene (sich in einer Klassenhierarchie befindende) Klassen verteilt. Mit C-mol werden solche gleichartigen Aktionen in einer Methode zentralisiert.



  • Wenn ich mir dieses Paper so ansehe, dann bekomme ich immer mehr den Eindruck hier will sich jemand u die Design-Phase der Applikation drücken und die gute alte VHT-Programmierung (Vom Hirn ins Terminal)wieder aufleben lassen... Bei dem in dem von dir erwähnten Paper beispiel wäre für mich eigentlich der Schritt zu einer CDrawableObject-Basisklasse von Vornherein logisch...

    -junix



  • SendKey schrieb:

    Ansonsten ja: Es werden sonst gleichartige Aktionen auf verschiedene (sich in einer Klassenhierarchie befindende) Klassen verteilt. Mit C-mol werden solche gleichartigen Aktionen in einer Methode zentralisiert.

    Aber worin liegt da der Sinn? Letzendlich muss ich ebenso in meiner KLasse eine Paint-Methode bereitstellen, die von der zentralen Methode aufgerufen werden kann.

    -junix



  • Wieso wird jetzt auf einmal auch noch die imperative Programmierung eingebracht? Bis auf in der Assemblerprogrammierung ist die doch total in vergessenheit geraten.

    In der prozeduralen Programmierung konnte ich einfach Module anderer Projekte nehmen und die dort definierten Prozeduren im neuen Projekt weiterverwenden. Das war kein Problem, da es nur einen kleinen Satz fest definierter Typen gab.

    In der OOP hat man diesen Vorteil ebenfalls. Mann kann Klassen aus alten PRojekten problemlos weiterverwenden und sogar durch Ableitungen an neue, spezielle Situationen anpassen. Man baut den Vorteil also sgar weiter aus.

    Die MOP macht das ganze jetzt zu nichte. Eine Methode ist für einen festen Satz an Typen definiert und das war's. Habe ich ein ähnliches Problem in einem neuen Projekt darf ich alles neu Entwickeln. Auch wenn ich innerhalb dieser Entwicklung wenig Redundanzen habe ist die neuentwicklung an sich kaum zumutbar. Diese Erkenntnisse habe ich jeden Falls aus dem Drehbar-Beispiel gezogen.

    Gibt es einen festen Satz an Typen bzw. Klassen, der sich garantiert nicht erweitert ist die MOP ganz groß. Sollte es sich aber um eine Klassenhirachie handeln, die, sei es auch nur gelegentlich, erweitert wird, ist die MOP (um's ganz krass aus zu drücken) für'n Arsch.



  • @Heluim:
    Sicher könnten die beiden in dem Fall beide eine Methode aufleiten, was aber keine schöne Lösung wäre. Das wäre eine Art C++ Lösung, die man in C-mol geschrieben hat. Ist das Projekt methodenorientiert geplant worden, wäre eine Person mit der Entwicklung aller Drehroutinen und damit mit der Entwicklung der Dreh-Methode beauftragt. Somit wären eben alle gleichartigen Routinen bei einer Person.

    Ja, aber es gibt viel öfter Projekte, die Teile alter Projekte wiederverwenden wollen. Und genau das verhindert die MO.

    Sowohl die Syntax wie auch die "semantischen" Regeln sind alle (fast) identisch wie in C++ und daher denke ich sehr "intuitiv" für C++ Programmierer anzuwenden.

    Mich stört das Semikolon nach Methoden unheimlich. Was soll das da? Das wirkt irgendwie falsch. Ich bin es gewohnt, das Semikolons da sind, wo ich sie brauche. Hinter class steht eins, weil ich direkt Objekte instanzieren kann. Hinter Funktionen steht keins, weil es keinen Sinn machen wüde. Hinter Methoden steht eins, obwohl es keinen Sinn macht.

    Was ist z.b., wenn ich nicht nur einen pro- und epilog brauche, sondern auch zwischendurch einen abschnitt haben, der für alle zielklassen gleich ist. wie komme ich denn in c-mol weiter? muss ich dann 2 methoden definieren?

    Schon komplett die alten Ansätze verdrängt und Komplett auf MO umgestiegen? Schreib dir 'ne Funktion, die von der Methode verwendet wird. Vielleicht wäre es nett, wenn man innerhalb von Methoden Funktionen definieren könnte, die dann privat sind, und nur dazu dienen besser strukturieren zu können und Redundanzen zu vermeiden.



  • Was fehlt sind erweiterbare Methoden. Jemand definiert eine Methode mit Pro- und Epilog und den von mir im letzten Posting und von Korbinian geforderten privaten Funktionen und jeder kann für seine Klasse neu Handlings definieren.

    methode Foo () {
       Foo () 
       { ... }
       ~Foo () 
       { ... }
    
       // Klasse, von der man bereits weiß, das sie behandelt werden muss
       void <Bar> ()
       {
       }
    private:
       int helper_function ()
       { ... }
    };
    
    // Später jemand anders, der mein ein Baz sollte ebenfalls behandelt werden:
    
    handle Foo::<Baz>()
    { ... }
    

    So könnte man Redundanzen vermeiden.



  • SendKey schrieb:

    @Bashar:
    Kann man diese "generischen" Areas auch vererben (wie in C-mol), so dass man die Prolog/Epilog-Idee (bzw. Before/After) auf höheren Abstraktionsebenen weiterführen kann?

    Hm, wie genau meinst du das? Ich hab mich wie gesagt mit C-mol aus Zeitgründen noch nicht befasst ... vielleicht kann ich die Frage in ein paar Tagen beantworten.

    Helium schrieb:

    Wieso wird jetzt auf einmal auch noch die imperative Programmierung eingebracht? Bis auf in der Assemblerprogrammierung ist die doch total in vergessenheit geraten.

    C++ ist eine imperative Sprache.



  • hm, ich glaub mein problem ist nicht ganz verstanden worden:

    Korbinian schrieb:

    Was ist z.b., wenn ich nicht nur einen pro- und epilog brauche, sondern auch zwischendurch einen abschnitt haben, der für alle zielklassen gleich ist. wie komme ich denn in c-mol weiter? muss ich dann 2 methoden definieren?

    damit meinte ich sowas:

    method MyMethod 
    {
        MyMethod()  { /* Prolog */ }
        ~MyMethod() { /* Epilog */ }
    
        void <Klasse1>
        {
            /* Spezifisches zu Klasse1 */
            CodeDerFürAlleZutrifft();
            /* Spezifisches zu Klasse1 */
        }
    }
    

    wie würde man das sinnvoll in c-mol realisieren?

    junix schrieb:

    Wenn ich mir dieses Paper so ansehe, dann bekomme ich immer mehr den Eindruck hier will sich jemand u die Design-Phase der Applikation drücken und die gute alte VHT-Programmierung (Vom Hirn ins Terminal)wieder aufleben lassen... Bei dem in dem von dir erwähnten Paper beispiel wäre für mich eigentlich der Schritt zu einer CDrawableObject-Basisklasse von Vornherein logisch...

    und genau das meinte ich mit "wenn man aber ein weitsichtiger programmierer ist, erkennt man gleiche sachen im voraus, und kann sie gleich zusammenfassen". Man braucht sich nicht ums design kümmern.

    SendKey schrieb:

    Wenn in der OOP Programmierer Klassen ableiten um ihre speziellen Klassen zu implementieren, muss jeder Programmierer Ahnung von dem haben, was er implementieren soll.

    ja das macht sinn 😉

    SendKey schrieb:

    Das kann unter Umständen heißen, dass sich mehrere Programmierer damit beschäftigen müssen, wie man die Klasse in eine Datei schreibt, wie man sie dreht, wie man sie visualisiert, etc.

    Auf jeden fall! Wenn iche Klasse KuchenMitSahne habe, dann weis doch ich genau, wie dieser Kuchen mit Sahne gezeichnet werden muss, und welche informationen ich abspeichern muss. um das dann ein ein einheitliches vormat zu klatschen (die datei), kann ich in der design-phase richtlinien festsetzen, und z.b. eine xml-lib zur verfügung stellen.

    SendKey schrieb:

    Gut, meiner Meinung nach hab ich ja schon versucht einige solcher Beispiele zu bringen.

    jo, aber nicht solche beispiele, die ich wollte. ich wollte ein beispiel, das in c++ schwierig zu realisieren ist. deine waren in c++ sehr leicht und elegant zu realisieren (ohne großes nachdenken)

    Aus dem jetzigen fasse ich mal zusammen:

    • die funktionalität von c-mol ist extrem leicht anhand templates und richtig angewandter vererbung/polymorphie nachzubilden (und meines erachtes übersichtlicher)
    • bei der entwicklung muss ich sowohl in c-mol als in c++ acht geben, dass ich nichts doppelt code. in c-mol muss ich dauernd schauen: muss es in pro-/epilog, in c++ muss ich schauen: "hab ich das schonmal geschrieben? wenn ja: auslagerung eine eine externe (template)funktion"
    • die aufteilung, wer über was bei der entwicklung bescheid wissen muss, erscheint mir bei OOP klarer und besser (effizienter) aufgeteilt

    => ich hab immer noch keinen grund, mir c-mol anzueignen 🙂



  • @Helium:

    Helium schrieb:

    Eine Methode ist für einen festen Satz an Typen definiert und das war's. Habe ich ein ähnliches Problem in einem neuen Projekt darf ich alles neu Entwickeln. Auch wenn ich innerhalb dieser Entwicklung wenig Redundanzen habe ist die neuentwicklung an sich kaum zumutbar. Diese Erkenntnisse habe ich jeden Falls aus dem Drehbar-Beispiel gezogen.

    Man kann doch auch von Methoden erben, wie bei Klassen: Handlings hinzufügen, andere überschreiben, etc. und die neue Methode somit an die neue Situation anpassen! Das ist doch genau das was Du meinst, oder? Es muss also nichts neuentwickelt werden...

    @Bashar:
    Methoden kann man vererben (aufleiten). Dabei werden die Prologe und Epiloge "gestaffelt" um deren Vorteile auch auf höheren Abstraktionsebenen weiter nutzen zu können. Beispiel:

    C-mol Code:

    method M1()
    {
        // Prolog von M1
        M1();
    
        // Handling für Klasse C1
        void <C1>();
    
        // Epilog von M1
        ~M1();
    };
    
    method M2()
    {
        // Prolog von M2
        M2();
    
        // Handling für Klasse C2
        void <C2>();
    
        // Epilog von M2
        ~M2();
    };
    
    // M3 ist Integralmethode und erbt alle Handlings von M1 und M2; Prologe/Epiloge werden "gestaffelt"
    method M3() : M1, M2
    {
        // Prolog von M3; enthält Gemeinsamkeiten der Prologe von M1 und M2
        M3();
    
        // Epilog von M3; enthält Gemeinsamkeiten der Epiloge von M1 und M2
        ~M3();
    };
    

    Ein Aufruf von M3 würde so aussehen:

    C-mol Code:

    C1* pC1_Inst;
    ...
    M3()<-pC1_Inst();
    

    Prolog und Epilog Aufrufsreihenfolge wäre dabei:

    --> Prolog von M3;
    ----> Prolog von M1;
    ------> Handling für C1;
    ----> Epilog von M1;
    --> Epilog von M3;

    Analog natürlich auch für C2.

    @Korbinian:
    Wenn Du das von Dir beschriebene Problem sauber methodenorientiert lösen willst, wäre dies denke ich der beste Ansatz:
    Mach zunächst eine Methode, in der Du ein großes Multihandling für die entsprechenden Typen oder bei Bedarf sogar ein Template-Handling mit dem identischen Code implementierst. Im Prolog und Epilog dieser Methode rufst Du dann eine weitere Methode auf, in der wiederum Handlings definiert sind, dort jedoch unterschiedlich mit den Klassenspezifischen Codeteilen.

    @junix:
    Ich denke die Design-Phase hat mit C-mol noch immer die gleiche Bedeutung. Man kann genauso wie man Klassenhierarchien entwirft auch Methodenhierarchien entwerfen, man kann Prologe/Epiloge z.B. mit UML-Sequenzdiagrammen modellieren, etc.



  • @Helium:

    Eine Methode ist für einen festen Satz an Typen definiert und das war's. Habe ich ein ähnliches Problem in einem neuen Projekt darf ich alles neu Entwickeln. Auch wenn ich innerhalb dieser Entwicklung wenig Redundanzen habe ist die neuentwicklung an sich kaum zumutbar. Diese Erkenntnisse habe ich jeden Falls aus dem Drehbar-Beispiel gezogen.

    Das wäre nicht von Nachteil, wenn es eine weltweite Library für Typen gäbe, deren Benutzung zum Standard werden würde, und deren Pflege akkurat ist, sodass nicht pipapo in die Library hineinkommt. Das wären Dinge, die ich als echten Fortschritt ansehen würde - speziell, wenn es von Universitäten durchgeführt werden würde und nicht-lizensierbares Allgemeingut wäre.



  • SendKey schrieb:

    @Korbinian:
    Wenn Du das von Dir beschriebene Problem sauber methodenorientiert lösen willst, wäre dies denke ich der beste Ansatz:
    Mach zunächst eine Methode, in der Du ein großes Multihandling für die entsprechenden Typen oder bei Bedarf sogar ein Template-Handling mit dem identischen Code implementierst. Im Prolog und Epilog dieser Methode rufst Du dann eine weitere Methode auf, in der wiederum Handlings definiert sind, dort jedoch unterschiedlich mit den Klassenspezifischen Codeteilen.

    hm, das hört sich etwas kompliziert/aufwändig an. mal 2 möglichkeiten, dass mit c++ zu realisieren:

    // Möglichkeit 1:
    // Natürlich kann man sowas auch in ne klasse klatschen, um streng OOP zu bleiben
    template <class T> void Prolog(T myT)
    {
        // Bla
    };
    template <class T> void Epilog(T myT)
    {
        // Bla
    };
    template <class T> void ZwischenFunktion(T myT)
    {
        // Bla
    };
    void machWasMitClass1(Class1 c1)
    {
        Prolog(c1);
        // Spezial für Class1 vorbei, allgemeiner zwischenteil
        ZwischenFunktion(c1);
        // weiter Spezial für Class1
        Epilog(c1);
    }
    
    // Möglichkeit2
    class Base
    {
        public:
            Base();
            virtual ~Base();
            virtual GanzeFunktionMitProUndEpilog() = 0;
            void Prolog();
            void Epilog();
            void AllgemeinerZwischenteil();
    };
    
    class Derived : public Base
    {
        public:
            Derived();
            virtual GanzeFunktionMitProUndEpilog()
            {
                Prolog();
                AllgemeinerZwischenteil();
                Epilog();
            }
    };
    
    int main()
    {
        // Das die polymorphie müsste nicht umbedingt angewandt werden
        Base *obj = new Derived();
        obj->GanzeFunktionMitProUndEpilog();
        delete obj;
    }
    

    obs in c-mol genau so einfach ging, aber das liegt vielleicht daran, dass ich in c-mol nicht eingearbeitet bin.

    SendKey schrieb:

    Ich denke die Design-Phase hat mit C-mol noch immer die gleiche Bedeutung. Man kann genauso wie man Klassenhierarchien entwirft auch Methodenhierarchien entwerfen, man kann Prologe/Epiloge z.B. mit UML-Sequenzdiagrammen modellieren, etc.

    hm, natürlich hast du immer eine design-phase. nur musste da halt nimmer so genau acht geben. eine junix hat schon recht: eine gute designphase spart dir sowieso mehrfach angewendeten code.

    und ich hab imme rnoch kein beispiel, wo sich c-mol anbietet (also von c++ vorteilhaft abhebt)



  • und ich hab imme rnoch kein beispiel, wo sich c-mol anbietet (also von c++ vorteilhaft abhebt)
    

    Du könntest dir einen sematischen Vorteil schaffen, indem du als OO-Methode das definierst, was das Objekt kann und als MO-Methode das, was mit dem Objekt gemacht werden kann.



  • Ok, hier einfach mal das konkrete Beispiel in C-mol:

    C-mol Code:

    method SpezielleTeileAnfang()
    {
        void <Klasse1>();
        void <Klasse2>();
    };
    
    method SpezielleTeileEnde()
    {
        void <Klasse1>();
        void <Klasse2>();
    };
    
    method GanzeMethodeMitAllem()
    {
        // Prolog
        GanzeMethodeMitAllem()
        {
            SpezielleTeileAnfang()<-that();
        }
    
        // Epilog
        ~GanzeMethodeMitAllem()
        {
            SpezielleTeileEnde()<-that();
        }
    
        // Multihandling für identischen Teil; bei Bedarf auch Template-Handling
        virtual void <Klasse1*, Klasse2*>();
    };
    
    int main()
    {
        // Polymorphie müsste hier nicht umbedingt angewendet werden 
        BasisKlasse *pObjekt = new Klasse1(); 
        GanzeMethodeMitAllem()°pObjekt();
        delete pObjekt; 
    }
    

    Man kann doch nicht sagen, dass es kompliziert(er) aussieht, oder? Aber vielleicht ist es auch einfach nur Geschmackssache... 🙂



  • bei Bedarf auch Template-Handling

    Was heißt das nun wieder?

    Das wäre nicht von Nachteil, wenn es eine weltweite Library für Typen gäbe, deren Benutzung zum Standard werden würde, und deren Pflege akkurat ist, sodass nicht pipapo in die Library hineinkommt. Das wären Dinge, die ich als echten Fortschritt ansehen würde - speziell, wenn es von Universitäten durchgeführt werden würde und nicht-lizensierbares Allgemeingut wäre.

    Willst du mich verarschen? Es kann doch keine Bibliothek geben, die Klassen für alle Bereiche bereitstellt. Uns selbst wenn diese Bibliothek gigantisch wäre könnte Sie trotzdem keine MO-Methoden enthalten, da ich unter Garantie für meine Zwecke Klassen spezialisieren muss, die dann natürlich nicht von der Methode abgedeckt würden.

    Um mein Problem mit der MO nochmal etwas rauszuheben: In der OO kann ich tausende Klassen von einer gemeinsamen Basis ableiten und alle werden mit Funktionen, die für die Basisklasse gedacht sind arbeiten. Aber ich kann wohl kaum mehrere Methoden parallel aufleiten. Das macht keinen Sinn. Methoden sind ja nicht Polymorph und nicht, wie Objekte, übergebbar. Das heißt ich kann einer Funktion, die eine Methode verwendet stattdessen eine Aufgeleitete Methode verwenen lassen. Ich habe auch keine Ahnung, wie ih mir das vorstellen soll.

    void fertiger_Code (Eigenschaft & objekt)
    {
       ...
       objekt.oo_methode()
       ...
    }
    

    Ich kann jetzt jede Klasse, auf die 'fertiger_Code' angewendet werden soll die Schnittstelle Eigenschaft implementieren lassen (oder das Protokoll verwenden lassen, oder welche Terminologie ihr auch immer bevorzugt). Und es wird funktionieren. Ich muss mich um den Algorithmus nicht mehr kümmern.

    void fertiger_Code (Basis & objekt)
    {
       ...
       mo_methode()°&objekt();
       ...
    }
    

    Sowas kann nicht gehen. Wird die Hirachie, die an 'Basis' hängt (egal, was Basis jetzt ist) erweitert muss ich direkt die Methode abändern, was ich vielleicht nicht darf oder kann. Aufleiten bringt mir gar nichts. Eine Erweiterung der Hirachie funktioniert also nicht, bzw. ich kann das Verhalten für meine Hirachieerweiterung nicht angeben.

    In der OO überschreibe ich einfach Methoden der Basisklasse, um das gewünschte Verhalten zu erziehlen. In der MO muss ich in fremden Dateien rumpfuschen um die Methoden für meine eigenen Klassen anzupassen.



  • Willst du mich verarschen? Es kann doch keine Bibliothek geben, die Klassen für alle Bereiche bereitstellt.

    Warum soll es die nicht geben? Und pass Deine Wortwahl mir gegenüber mal an.



  • OK, entschuldigung. Willst du mich veräppeln?



  • Ich veräppel eigentlich nur offensichtliche Trolle.
    Jene Library wäre ja wohl auch eher als Library of Libraries gedacht.
    Über das Simtelnet sind solche Funktionssammlungen ja auch lange genug im Netz gewesen (okay, über die Qualität müssen wir uns da nicht streiten).
    Aber wenn ich mir z.B. Allegro ansehe, dann sind da etliche Typen so konstruiert, dass es keine Notwendigkeit gibt, sie wieder und wieder zu erstellen. Das mag mit einer Library wie DirectX auch so sein, aber sie unterliegt schlicht und einfach einer Firma und ist auch nicht portabel.
    Das wiederum sieht mit OpenGL ganz anders aus. (Wobei wir uns ja wohl einig sind, dass OpenGL mit C++ kaum etwas zu tun hat)
    Und warum sollte eine solche Library nicht zusammen mit anderen tauglichen an einer Position im Web zu finden sein, die sich dann eben nicht gegenseitig überschneiden, sondern fein hierarchisch geordnet sind?



  • Ich glaube langsam komme ich dahinter, wofür man die MO benutzen kann. Ich wollte Sie immer innerhalb einer Hirachie einsetzen, was unmöglich zu sein scheint. Aber man kann Sie wuederbar einsetzen, um mehrere Hirachien zusammenzuführen. Wenn sich mit zwei oder mehr Hirachien ein und die selbe Aufgabe erledigen lässt, verlagert man diese aufgabe in eine Methode. Diese nutzt indirekt die polymorphen Eigenschaften der jewieligen Hirachien aus, hat also keine Probleme mit Erweiterungen.

    @Bitsy: DirectX ist eine ganz andere Art von Bibliothek, als ich meinte. Du wirst wohl kaum in deinen Projekten ausschließlich die paar Klassen deiner Grafik, Sound, etc. Bibliothek verwenden, sondern für dein Programm speziell tonnenweise Klassen schreiben, die sich zumindest teilweise wiederum in Hirachien befinden. Diese Klasen brauchst du in diesem Projekt und möglicherweise auch einige von denen in nachfolgenden Projekten. Aber die Kannst du doch nicht einfach alle in eine Bibliothek packen. Da hast du doch blitzschnell eine Sammlung mit Millionen von Klassen zusammen.


Anmelden zum Antworten