Ankündigung

Einklappen
Keine Ankündigung bisher.

OO-programming is a synonym for procedural-programming

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #31
    moin moin,

    So diesesmal ein etwas kürzerer Beitrag

    Gliederung:

    0. Allgemeines
    1. Zitate
    2. Weitere Ausführungen oo vs pop
    3. Definition von pop und oo
    4. Was mich an oo stört (Zusammenfassung)
    5. Fallbeispiel
    6. GoF und Sonstiges
    7. Schlusswort


    0. Allgemeines:
    Da mir jetzt schon öfters aufgefallen ist, dass ihr einen Bezug zu PHP herstellt.
    Ich möchte eher allgemeine Paradigmen von oo und pop besprechen und nicht irgendwelche auf irgendeine Sprache bezogene Paradigmen
    Vlt. erkennt ihr auch daran mein Denkmuster. Möglichst generisch und flexibel programmieren. Und genau da macht mir oo irgendwie einen Strich durch die Rechnung (vermutlich)

    1 Zitate:

    In einen Service. Ein User kann sich nicht selbst Bannen. Ein User hat eigentlich kein richtiges Verhalten. Du kannst dem User aber Verhalten geben: Durch Erweiterungs-Klassen.
    Ja genau Service! Die Logik bzw. das Verhalten wird schön in einer extra Klasse bzw. prozedur gekapselt und nicht dezentral aufgeteilt. Ist ganz meiner Meinung!
    Das Prinzip von Erweiterungsklassen hab ich hier aber nicht wirklich verstanden, welchen Mehrwert hab ich denn hier?
    Wenn ich jetzt ausgehend vom User wissen möchte ob er gebannt ist, dann muss ich die Erweiterungsklasse derefernzieren, ok! Spinnt man das ganze aber weiter, dann könnte es am Ende so aussehen, dass ich ne class user hab mit nix drinnen und nur Erweiterungsklassen draussen herum baue?!?

    Und da schon die nächste Frage, woher bekommt der UserBanCtrl die Referenz auf diese Erweiterungsklasse. In deinem Beispiel von der Factory ganz frisch. Aber normalerweise wohl doch dann von einer globalen Stelle, einer Registry oder global von der Datenbank, oder?

    Würde mich über weitere Ausführungen hier freuen....


    Ich sehe in meiner Implementation immerhin den Unterschied, dem BanUserCtrl für BannableFactory etwas zu geben, was die "Bann-Regeln" anders interpretiert oder eine andere Datenquelle zur Hilfe nimmt. Wie mache ich so was elegant prozedural?
    Ich vermute du sprichst hier sowas wie DI an? Ein anderes Verhalten einspritzen.

    Dazu muss ich nochmal etwas ausholen.

    Assembler: indirekte Addressierung:

    lese ich einen indirekten wert bspw. aus einem register (äh quatsch ist glaube ich sogar semantisch verboten aus nem register indirekt zu dereferenzieren)..... also aus ner Speicherstelle, dann ist der Wert den ich lese die Referenz auf eine weitere Speicherstelle und lese diesen dann!

    entspricht diese Speicherstelle nun einer Funktion, so kann ich während des Laufen des programms an der ursprünglichen Stelle, also an der Stelle die dann die Dereferenzierung angibt einen anderen Wert eintragen, der dann dafür sorgt, dass eine andere Funktion angesprungen wird.

    In PHP funktioniert das glaube ich mittels call_user_func oder so.....
    in C wird ein Funktionspointer dereferenziert
    Und in der OO-Programmierung ist es die polymorphie, die bspw. mittels interfaces umgesetzt wird
    => Machen aber alle vier semantisch das gleiche!

    Um bspw. später if else zeugs zu vermeiden, setze ich einmalig (bzw. später auch änderbar) so einen Funktionspointer.

    In obigen Beispiel gibt der dann die "Bann-Rgeln"-Strategie vor!
    Die Frage ist nur, WO ich diesen Funktionspointer abspeichere?
    An einer globalen Stelle (oo und pop möglich), oder lokal (nur oo möglich)

    Und hier muss ich dir tatsächlich recht geben, dass es wohl strukturierter Ist das Verhalten direkt im objekt abzuspeichern.
    Aber das ist hier auch das einzigste was OO "besser" kann als pop.

    Naja hier kommt ein klein wenig Zustand dazu, was aus dem Service ohne Zustand einen Service mit etwas Zustand macht.
    Aber die Kernproblematik besteht hier weiter, wir verwenden einen Service, der eher global agiert!
    Und für mich stellt sich die weitere Frage, von woher bekommt der Service seine Strategien? Meine Antwort darauf wäre von einer globalen Stelle! Nichts anderes macht doch DI aus, oder?
    Und die zweite Frage, woher bekommt der Service seine Nutz-Daten, also die Entity-objekte? Auch hier wäre meine Antwort von einer globalen Stelle!

    Ein weiterer Service wird dann später vermutlich diesen Service hier verwenden.
    Bei einem Spezialfall des Bannes wird er vermutlich direkt "Unterprozeduren" verwenden müssen, um Logik an der entsprechenden Stelle gezielt ersetzen zu können! Also Logik die nicht durch einfache DI auflösbar wäre!



    Der typischste Fall für ein mehrdimensionales Objektdesign ist wohl eine Baumstruktur. Also ein DOM, eine Verzeichnisstruktur, oder eine Window-Component-Lib. Es gibt gute Gründe, warum man das eher nicht prozedural macht. OpenGL war lange Prozedural. DirectX war schon immer (auch) Objektorientiert. Ein wunder: Die überwiegende Zahl der Entwickler nutzt DirectX gerne und OpenGL nicht.
    Ich bin mir nicht ganz sicher ob du verstanden hast, was ich gemeint habe. Eventuell kannst du hier deine Aussage noch etwas weiter Ausführen


    Man kann alles als OO durchgehen lassen, was OO ist. Sub-Methoden-Aufrufe sind nicht zwangsläufig OO, nur weil sie in einem Objekt stattfinden. Das kann ganz normale prozedurale Verkettung sein. Hab ich keine Schmerzen bei, wenn es das Problem fachlich korrekt, bzw. ideal löst.
    Was ist dann zwangsläufig OO, das würde mich interessieren^^

    Mehrdimensionalität ist dann die sogenannte Rekursion. Und das ist ebenfalls korrektes OO.
    Zur Rekursion bzw. Divide and conquer komme ich später noch
    und wie ich dezentrale und zentrale algorithmen sehe


    Wie kann ich diese einzelnen Concerns prozedural aufteilen, so dass ich jeweils klar abgetrennte Subsysteme habe, die sich um die einzelnen Belange kümmern? Zumal diese Subsysteme dann wahrscheinlich wieder Abhängigkeiten zu anderen Komponenten haben, die dann die Anbindung zu einer Datenquelle stellen, etc. Das mündet bei prozeduraler Programmierung nur wieder in übergreifenden Funktionsaufrufen mit kreuz- und quer-referenzierten oder -kopierten Structs. Das ist von der herangehensweise ganz anders als OOP. Für einige kleine Belange mag das so besser funktionieren. Aber für komplexe Geschäftsanwendungen mit viel Code ist das einfach nichts. Und OOP eignet sich eigentlich auch für alles, was man mit prozeduralen Paradigmen erledigen kann. Warum also nicht gleich OOP?
    Wie machst du es also in OOP?
    Parameter stehen für mich für Flexibilität und Dynamik. Beides wird durch oo eher eingeschränkt, oder wie kann ich genauso dynamisch und vor allem flexibel in oo sein
    Ein konkretes Beispiel, das am besten eine Transformation von prozedur(lange paremterliste){sub_routinen_aufrufe, etc} ins oo zeigt, würde mich mal interessieren


    Man kann alles als OO durchgehen lassen, was OO ist. Sub-Methoden-Aufrufe sind nicht zwangsläufig OO, nur weil sie in einem Objekt stattfinden. Das kann ganz normale prozedurale Verkettung sein. Hab ich keine Schmerzen bei, wenn es das Problem fachlich korrekt, bzw. ideal löst.
    Fachlich ist sogar mein Assemblercode bzw. VHDL korrekt und semantisch tut es auch das gleiche. Man macht es aber trotzdem nicht, weil man anders besser bzw. effizienter im Sinne von man kommt schneller zum Ziel coden kann.
    Jetzt würde mich auch interessieren ob man auch zum Ziel kommt, wenn man derartige Ausnahmen auslässt und wirklich reines OO programmiert? Und vor allem interessiert mich wie dieses OO dann aussehen muss


    Ja, falsch. Das geht bei OOP ebenfalls genau so. Absolut kein Unterschied zu deiner Variante, bis auf, dass es diesen "globalen" Kontext nicht geben muss. Oder anders ausgedrückt: Die OOP-Experten mit dem schwarzen Gurt nutzen keine globalen Informationen und keine globalen Objekte(Singleton)/Methoden(Statisch), sehr wohl aber in Objekten verschachtelte prozedurale Ansätze.
    Naja die Frage ist hier doch viel mehr ob zentralisierter Code prozedural ist und dezentralisierter eher OO?
    Und die zweite Frage ist, wenn kein globaler Kontext, wie ist dann der globale Kontext zu dividen? Und wie komme ich dann an die divideden (aufgeteilten) Informationen?



    Dann profitiert man eben nur unvollständig. Was auch immer das bedeuten soll. Klingt jedenfalls besser, als gar nicht zu profitieren.
    Ja diese Profitierung würde mich auch interessieren


    Erklär du uns doch vielleicht umgekehrt mal anschaulich, wieso sich bei prozeduraler Programmierung immer alles – auch die Probleme von OOP, die du feststellst – in Wohlgefallen auflöst.)
    Naja wie ihr selber schon gesagt habt ist OO ne Erweiterung von POP. Die Probleme lösen sich also nicht durch POP auf, sondern exisitieren hier noch gar nicht. Und ich meine hier insbesondere Datenstrukturkopplungen, Wo welches Verhalten hin? dezentralen Algorithmus (der meiner Meinung nach nur in sehr wenigen Fällen das gelbe vom Ei ist.... später dazu mehr)

    Auch das was ein M. Fowler schreibt, kann und sollte man kritisch betrachten:

    http://blog.ralfw.de/2010/08/leiden-...-oop-2010.html
    sehr interessanter blog eintrag!
    Eigentlich spiegelt er auch meine zwei ansichten wieder, oder?

    Also erstere, dass ban_user weder zu user noch zu admin gehören kann -> man muss eine Service-Klasse einführen!
    Zweitere: 1D-Ansicht ist gut MehrD nicht!
    Heißt er findet den ADT (abstrakten Datentyp) einer Liste gut umgsetzt. Die Operationen arbeiten ja auch wirklich nur auf den eigenen Daten. Den Rest sieht er kritisch (also sonstige Zusammenfassungen)

    Stimmt das in etwa so? Hab den Text vor ein paar Tagen durchgelesen und jetzt nicht mehr wiederholt.....




    2. Weitere Ausführungen oo vs pop

    Also pop kann man zentralisiert wie auch dezentralisiert programmieren.
    OO steht eher für dezentral

    Stimmt das in etwa so?

    Zentral heißt ich habe eine prozedur, die alles steuert bzw. ein Service-Objekt (proezduraler Ansatz) das alles steuert
    Dezentral heißst ich habe eine prozedur die leitet die Anfrage weiter und soweiter und am ende wird gemäß des Divide and Conquer wieder alles gemerged?

    Hießt ich code Klassen mit Baisfällen und Merge-Klassen....?

    Kann man das so ungefähr sehen, bzw. ist es das, was OO ausmacht?

    Den Voteil von zentral sehe ich darin, dass, ich Teilergebnisse im Algorithmus wiederverwenden kann und auch in abhängigkeit von den Teilergebnissen den Algorithmus steuern kann

    siehe dazu (wobei das sogar ne Mischform ist)

    ->Aufruf->Aufruf->Aufruf
    ->Aufruf
    ->Aufruf
    ->Aufruf->Aufruf->Aufruf
    ->Aufruf
    ->Aufruf


    Beim Divide and Conquer Algorithmus kann ich Teilergebnisse aus einem Rekursionspfad nicht im anderen verwenden! Zumindest nicht trivial. Über eine globale Konstruktion wäre dies möglich!

    welche Vorteile bringt es dezentral zu programmieren?

    Und ist dezentral reines oo und zentral pop und eine Mischform aus beidem praktisches oo (wobei in der Mischform das zentrale dann der Service darstellt?)


    Soweit hierzu


    3. Definition von pop und oo

    pop: ich habe eine prozedur, diese verwendet weitere Funktionen (vor allem aber auch Sequentiell, also in zentraler Form)
    Die Daten bekomme ich über parameter, eventuell auch zu entity-objects oder arrays zusammengefasst
    persistente Daten werden via eines globalen Layers in die Datenbank eingetragen bzw. gelesen. Dieser Layer ist von überall aus Zugreifbar

    oo:
    Kapselung von verhalten und Daten
    dezentraler Algorithmus?
    wie komme ich hier an die Daten, bzw. wo sind die gespeichert?... diese Struktur wird doch auch von was globalen aufgebaut oder?

    4. Was mich an oo stört (Zusammenfassung)

    Datenstrukturkopplung wie schon in den anderen Thread erwähnt
    Unentschlossenheit wo ich welches Verhalten hindesigne
    reiner dezentraler Algorithmus, da hier Flexibilitätseinbußen, weil mir hier nicht alle Teilergebnisse überall zur Verfügung stehen (Hier meine ich wirklich Teilergebnisse, also Produkte, die während des algorithmus anfallen)


    5. Fallbeispiel


    Also wenn ich ne Anwendung entwerfe, dann sieht das folgendermaßen aus

    In der Regel hab ich einen Use-Case bzw. ne Anforderung an eine Funktion/Prozedur

    Diese schreibe ich komplett aus... -> 1 Funktion/prozedur (die beiden begriffe verwende ich im folgenden synonym)

    dann geh ich so vor, ich zerkleinere die Funktion in kleinere Teilabschnitte.... Diese kann ich ja dann später super wiederverwenden, wenn ich nur an einem Teil-feature dieser Anforderung interessiert bin
    Natürlich gehe ich nicht immer so vor, sondern schreibe auch mal erst ne Sub-funktion etc (also middle-out), oder sogar bottom-up.

    Jede einzelne Funktion, die ich geschrieben habe ist super wiederverwendbar und ich hab nix umsonst geschrieben


    Um konkreter zu werden.... gehe ich nochmal auf das ban_user problem ein

    ich schreibe eine prozedur ban_user($to_user,$ban_user,$force_ban=false, array $weitere_flags)

    diese checkt dann erst mal ob der $ban_user berechtigt ist zu bannen
    diese checkt anschließend ob $ban_user berechtigt ist den zu ihm in bezug stehenden user zu bannen (also ob dieser im hirachisch unterlegen ist)
    diese checkt ob $ban_user sein tageslimit an bans heute schon überschritten hat
    und und und

    bei force_ban wird diese checks umgangen

    erst anschließend wird der ban durchgeführt, dabei müssen wieder x Daten an y-vielen Entitiies bzw. Daten geändert werden
    Tritt hierbei nochmals eine Exception auf und ist diese nicht kritisch wird der ban weiter durchgezogen
    ist die exception kritisch dann wird auch hier wiederrum ein rollback durchgeführt

    In der Regel sollten keine Exceptions auftreten, da die checks dies abedecken sollten.... doppelt hält aber besser^^

    Eventuell werden auch Emails versendet, einmal an den ban_user und and den $to_user.... in abhängigkeit von weitere_flags werden diese forciert oder aber die default einstellungen des users genommen, die über eine sub-prozedur abgefragt werden (also über eine wohldefinierte und abstrakte schnittstelle!)

    Ich arbeite also auf globalen Daten, aber nur mit wohldefnierten schnittstellen (also via parameter)


    So diese prozedur kann vom user verwendet werden, also ich gebs über den ActionControll-Mechanismus nach draussen
    Oder aber ich möchte dieses Feature innerhalb verwenden.
    Beispielsweise schreibt ein Admin ne Nachricht an den User dass er gebannt wird. Mein Texterkennungssystem erkennt dass es sich um eine derartige Nachricht handelt und ruft dann die prozedur ban_user(....) mit den entsprechenden Parametern auf!

    Oder aber es ist nicht erlaubt, dass der User sein Name in etwas unArtiges ändert, auch bei dieser Änderung wird diese Prozedur aufgerufen!
    Wichtig ist hierbei zu wissen, dass ich des möglichst flexibel gestalten möchte. also diesen Aufruf aus changeName() aufzurufen wäre falsch, DA:

    Wenn der Name vom System aus, oder von einem dazu berechtigten Admin in etwas UnArtiges geändert wird, dann soll ban_user nicht aufgerufen werden, also:

    changeNameSpecial()-> changeName() //wobei diese funktion dem system und dem ber. Admin vorenthalten ist
    changeNameNormal()->changeName() und eventuell ->ban_user() //diese wiederum nur dem User, oder aber auch dem System, wenn man will, dass eventuell ein UserBan durchgeführt wird, wenn das System auch einen Unartigen Namen vergibt


    wie ihr seht bin ich sehr auf flexibilität aus!

    Bin mal gespannt wie ihr das mit richtigen und wirklich reinem OO besser hinbekommt......



    ​6. GoF und Sonstiges


    Hier jetzt mal ganz nüchtern die Frage an euch, wie stellt ihr euch OOA und dann vor allem OOD (oo-Design) vor und zwar nicht nur auf den Problembereich bezogen, sondern auch auf den Lösungsbereich bezogen?
    Also alle "technischen Klassen" (sowas wie Services oder etc) mit einbezogen
    Wobei wie wir ja oben (siehe Fowlers Beitrag) gesehen haben, sind Services ja eigentlich nicht zu verwenden!

    Welche Klassenrollen verwendet ihr
    würde mich über eine Aufzählung und ne kurze Erläuterung freuen
    bspw.
    User-Entity
    USer-Service
    User-UseCase
    User-Action

    also sowas in der Art und dann auch die semantische Bedeutung davon und vor allem die feingranularen Unterschiede
    Gibt ja für Geschäftsprozesse und UseCases auch kleine und feine Unterschiede

    Ich kenne mich da natürlich nicht so ganz gut aus, weiß bloss, dass es hier Unterschiede gibt


    Dann noch die Frage sind einzelene Rollen-Klassen als Layer zu sehen?
    Bspw. geht man bei nem Service von nem Service-Layer aus, dann hätte ich des Problem, dass ich später von einer Entity-Klasse keinen Service aufrufen dürfte, da sonst das strenge Schichtenmodell verletzt werden würde?!?


    Wäre aber doof, weil ich ja bspw. bei nem changeName (mit flexibilitätseinbußen) ja bspw. einen Service aufrufen möchte (also für mich klingt Service nach wie vor so, wie wenn es eine Prozedur wäre, auch dann wenn Strategien eingespritzt werden, um den Algorithmus zu konkretisieren.... siehe Codebeispiel von rkr)

    Die GoF hat ja so schöne Design-Patterns entworfen. Wenn ich in Rollen und Layern code, wo kommen diese Patterns dann zum tragen? Vermutlich hauptsächlich in den Service-Klassen? (also die Verhaltensbasierten Patterns)???



    Noch ne weitere Frage zum Single-Responsibility-Prinzip:

    Wenn ich eine Entity-Klasse habe, dann ist die einzige Verantwortung hier, alle Entity-Attribute zu halten.... richtig?
    Wenn ich eine Service-Klasse habe, dann ist die einzige Verantwortung hier, das Verhalten ausführen zu können.... richtig?

    Wenn ich eine dezentrale Objektstruktur habe, dann ist die Verantwortlichkeit der Basisklassen eine einzige Verantwortlichkeit zu haben und die Aufgabe bzw. die Verantwortlichkeit der Merge-Klassen, die Ergebnisse von den rekursiv tieferen Klassen zu mergen und zu verarbeiten,....richtig?


    Dazu noch eine weitere Frage:

    Welchen Sinn macht es für eine Klasse mehr als eine öffentliche Methode zur Verfügung zu stellen? Welchen praktischen Sinn macht dies? Und verletzt es das Single-Responsible Prinzip? Ich würde sagen JA!

    An der Stelle möchte ich noch kurz was zur Datenstrukturkopplung ergänzen:
    Möchte ich eine Aufgabe iterativ mehrmals erledigen, dann hab ich in der oo ein großes Problem
    Konkret:

    ich habe bspw. ne Tabelle voller Geburtsdaten (diese ist extern.... Speise ich also extern in das System ein).... Diese Daten gehören semantisch zum User!

    Möchte ich jetzt also bspw. das Durschnittsalter berechnen, dann muss ich ja über alle User iterieren und mir davon dann das Durchschnittsalter bilden
    Problematik hier ist einerseits, ich bin an den User gebunden, also an die komplette Datenstruktur vom User und andereseits ein ein hochwertiges Objekt, das via new erzeugt werden muss
    Zerstückle ich den User bspw. in Subklassen (eine bspw. die fürs alter zuständig ist), dann bekomme ich zumindest die Datenstrukturkopplung einigermaßen in den Griff
    Zweiteres aber nicht! ich muss jedes mal ein Objekt, welcher Klasse dann auch immer erzeugen, dann die Geburtsdaten hineingeben und dann darüber iterieren!

    Jedes mal new aufzurufen macht ein haufen Overhead!.... einfacher wäre es wenn ich direkt mit den geburtsdaten arbeiten würde

    Ok ich merke gerade, dass das Beispiel eher ungeignet ist, weil ich das Verhalten eh externalisiert habe.

    Ein besseres Beispiel wäre gewesen, wenn ich ein internes Verhalten gehabt hätte und dieses iterativ jedes mal hätte aufrufen müssen!
    Also bspw. statt den Algorithmus komplett im Service zu haben, übernimmt bspw. der User noch das Geburtsdatum in eine Zahl umzuwandeln, oder so!
    Aber ich denke meine Kernproblematik hier wird klar.... Ich muss jedes mal new aufrufen statt einfach mit einer prozedur zu arbeiten , die die Daten ganz einfach via Parameter übergeben bekommt

    Die Methode ist also auch an die Klassen eigenen Attribute gekapselt, was bei einem iterativen Darüberlaufen und "einfachen" Daten einen haufen Overhead erzeugt!

    Vlt. wird es durch folgendes noch etwas klarer:

    PHP-Code:
    class A
    {

        
    $daten x

        
    function do_something($daten_y){..../*mache was mit $this->x und mit $y*/}

        function 
    setX($var x)
        {
            
    $this->x=$x;
        }

    }

    //und später dann

    foreach($datensatz)
    {
        
    $a=new A;
        
    $a->setX($datensatz[relevante Daten]);
        
    Ergebnisverarbeitung $a->do_something(5);
    }


    //einfacher und effizienter wäre gewesen

    function do_somethingStrich($x$y){....}

    foreach(
    $datensatz)
    {

        
    Ergebnisverarbeitung $do_somethingStrich($datensatz[relevante Daten],5);

    Ich denke damit ist meine Problematik klarer geworden
    Wäre A eine noch etwas aufgeblähtere Klasse, müssten eventuell im Konstrukor noch weitere Daten gesetzt werden, die aber in do_something() gar nicht benötig werden würden




    7. Schlusswort

    sondern denke, dass du irgendwie versuchst, um das Thema OO herumzukommen und die Argumente dafür so streust, dass du dir und anderen dann erfolgreich einreden kannst, dass OOP nichts dolles ist.
    Nein ich möchte damit nur meine Bedenken äußern bzw. aufzeigen, dass vieles auch in prozeduraler Programmierung möglich ist!
    Bzw. wie ihr ja selbst gesagt habt, ist OO nur eine Erweiterung zu Prozeduraler programmierung
    Ich zeige damit nur, dass Dinge, die ihr öfters als alleiniges Merkmal der oo zuschreibt, auch in pop möglich ist (wie z.B Polymorphie)

    Was ihr aber auch sagt ist, dass oo einfach ein anderes Denkmuster ist, und genau um das geht es mir. Ist es das dezentrale Denkmuster (divide and conquer)?
    Wenn ja wie sieht es praktisch aus?
    Welche Rollen-Klassen gibt es.
    Wie sind die anzuwenden?

    Wo kommen die Daten her?
    Wie greife ich auf Daten von aggregierten Strukturen zu. Gebe ich Subobjekte zurück, oder "repgorammiere" ich die Schnittstelle zu tieferen Objekten, da ja eigentlich die Internas und damit auch die Sub-Objekte verdeckt werden sollten (information-hiding)????

    Wenn Daten nicht global sind, wie komme ich dann an diese Daten in einer bestimmten methode?, Wie werden die Daten verteilt?

    Naja solche Sachen interessieren mich.... oben in meinem Text habe ich ja einige geannant, würde mich über Antworten freuen!


    Du darfst mir gerne ein Best Practivse von OOA und OOD geben! Würde mich echt interessieren wie du so ne Anwendung entwirfst. Aber nicht nur leeren Code, sondern auch kommentierten Code, in dem du beschreibst, warum du folgende Design-Entscheidung getroffen hast und warum diese eventuell besser ist als eine andere..... also ein ausdifferenziertes Beispiel



    Ich denke ich habe sicher noch irgendwelche Gesichtspunkte vergessen
    Werde, wenn ich mich an diese erinnere, bei Gelegenheit nachliefern.

    Übrigens das dezentrale Währungsystem Bitcoin kratzt gerade eben an der 210 USD Marke. Eine wichtige Marke.... Naja 220USD war eigentlich wichtiger, da diese durchbrochen worden ist..... naja wir werden sehen!
    Schauen wir mal ob das dezentrale System überlebt
    Ich denke das ist ein guter Abschluss^^

    lg knotenpunkt

    Kommentar


    • #32
      Ein kleiner Tipp knotenpunkt:
      Wenn dir OOP so extrem gegen den Strich geht, dann benutz es halt einfach nicht.
      Offensichtlich versuchst du ja aktiv, OOP schlecht zu reden. Dazu kann ich nur sagen: Wenn du sowieso voreingenommen an die Sache ran gehst, und es hier eigentlich nur darum geht, zu versuchen anderen ihre Programmierart schlecht zu reden, dann brauchst du keinen Thread in einem Forum aufmachen. Dafür hätte ein Post in einem Blog durchaus gereicht.
      Zitat von derwunner
      "Ein FISI ist auf gut-deutsch der Netzwerker. Das heißt Du gehst rauß zum Kunden oder auf die Straße und verlegst Leitungen" - derwunner 2015

      Kommentar


      • #33
        Zitat von knotenpunkt Beitrag anzeigen
        Da mir jetzt schon öfters aufgefallen ist, dass ihr einen Bezug zu PHP herstellt.
        Komisch, wo wir doch in einem PHP-Forum sind...


        Zitat von knotenpunkt Beitrag anzeigen
        Das Prinzip von Erweiterungsklassen hab ich hier aber nicht wirklich verstanden, welchen Mehrwert hab ich denn hier?
        Das ist eigentlich auch schon das Grundproblem, weswegen dieser Thread überhaupt keinen Sinn macht. Dir fehlt einfach wichtiges Grundlagenwissen bezüglich Softwarearchitektur.

        Kommentar


        • #34
          Nein, du nutzt eine Factory. Wenn du es richtig machen willst, dann gibt es nur zwei Orte, wo du das new-Schlüsselwort verwenden darfst: Im Bootstrap oder in einer Factory
          nur so nebenbei angemerkt: fuer diese Regel gibt es mehrere Ausnahmen: zum einen Exceptions (throw new \InvalidArgumentException) und zum anderen Value Objects.
          Diese sollten Immutable sein und deshalb muessen die im Falle von Aenderungen immer neu angelegt werden: http://stackoverflow.com/questions/4...-why-immutable
          https://github.com/Ma27
          Javascript Logic is funny:
          [] + [] => "", [] + {} => object, {} + [] => 0, {} + {} => NaN

          Kommentar


          • #35
            Hey,

            ich hab mir schon vor längerer Zeit Notizen zu weiteren Fragen gemacht, bin aber bisher nie dazu gekommen diese zu veröffentlichen.....


            Zitat von NotizVonMir
            ablauf hängt von der laufzeit ab, heisst ein algorithmus benötigt bspw. zwei objekte und es wird zur laufzeit entschieden was der algorithmus damit macht, abhängig vom zustand dieser objekte, wie diesen Fall sinnvoll in oo-design giessen?
            was ich damit sagen möchte ist, dass der alorithmus nicht durch eine klasse repräsentiert werden kann mit festem zustand.
            do_sth(obj1,obj2) //prozeduraler ansatz wäre hier die lösung
            do_sth(){use this->obj1 AND use this->obj2} wäre hier dann nicht korrekt

            und um die flexibilät zu behalten -> ist das ganz überall so, weil ich mich zur Compilezeit, oder aber auch ungerne zu Programmstart oder zu wenigen Programmzeitpunkten für etwas Festes entscheiden möchte


            Zitat von NotizVonMir
            wie algorithmus, der mehrere objekte benötigt um zu funktionieren in oo giesen? (ist ja so erst mal prozedural)
            ähnliches bzw. gleiches Problem hier

            Zitat von NotizVonMir
            ​​​​​​​wie damit umgehen, dass ich anfangs eh ne big klasse habe, die dann halt die schnittstellen der einzelnen objekte aufruft..... bspw. jede webanfrage wird erst mal in commands unterteilt und dann distribuiert
            ​​​​​​​ist hier die verantwortlichkeit dann einfach so zusehen, dass die aufgabe darin besteht die commands aufzuteilen und weiterzugeben?
            kA was ich mir genaueres dabei gedacht habe, aber ich ich beantworte mir die Frage mal selber: Ich denke ja die Verantwortlichkeit besteht genau darin wie ich es beschrieben habe


            Zitat von NotizVonMir
            feste module verdrahten via DI, problem ist nur dass das eher eine art anfangst-configuration des programms ist, wenn ich aber direkt in der laufzeit erst entscheiden möchte wie was eingesetzt wird, und vlt. sogar mitten im algorithmus.....
            ja das greift eigentlich nochmal meine erste notiz auf!



            So jetzt nochmal zusammenfassend:
            Das Problem das ich hier habe, seis in den Service-Klassen als auch in den Geschäftsklassen ist das, wenn ich irgendwo festen Zustand habe ich unflexibel werde!
            In den Service-Klassen könnte dieser Zustand bspw. ne andere Service-Klasse sein..... Sinnvollerweise sollte ja mein Algorithmus sich ja dann auch auf diese Membervariablen(die bspw. ne andere Serviceklasse referenziert) beziehen.
            Aber eigentlich vieler meiner Algorithmen möchte keinen festen Zustand verwenden, sondern erst zur Laufzeit und eventuell abhängig von diversen Faktoren entscheiden welche Service-Klasse oder andere Buisness-Klassen verwendet werden sollen

            Einfaches Bspw.: Meine Email-Service-Klasse:

            Sie hat bspw ne Membervariable die da heisst: Emailprovider (gmx, web, was eigenes, .....)
            Jetzt möchte ich aber erst in meinem Algorithmus entscheiden welchen Provider ich verwenden möchte..... bspw. in jeder geraden Stunde gmx.de und in jeder ungeraden Stunde web.de / oder abhängig an wen die Email geht
            => ein Setzten des Emailproviders via DI ist hier sinnlos
            => DI allgemein ist sinnlos, wenn man überall diese Flexibilität geniesen möchte
            => fester Zustand ist sinnlos, wenn man Flexibel sein möchte

            Frage wie ist das mit OO zu vereinbaren?
            Frage wie würdet ihr das ganze Programmieren, um meine genannte Flexibilität zu erhalten


            PS: ich möchte es dynamisch und nicht statisch (bei mir wird immer in letzter Sekunde entschieden was verwendet wird) <- wie programmiere ich schön OO dass ich weiterhin nach diesem Prinzip leben kann?



            Zweites Anliegen:

            Ich habe meine schöne objektorientierte Welt aufgebaut: bspw. Mensch

            class Mensch
            class Arm
            class Hand
            class Finger
            class Fingernagel

            eine schöne Komposition ist entstanden: Mensch->Arm->Hand->Finger->Fingernagel
            So die Frage ist ziemlich simpel:

            Wie lese ich aus meiner Komposition Werte aus und wie setzte ich diese, oder allgemein, wie führe ich Operationen darauf aus:

            Meiner Meinung nach gibt es zwei Ansätze (leider beide mal wieder nicht wirklich gut, wie ich finde)

            1 Ansatz: Facade
            ich klopfe meine Menschkomposition flach, heisst:

            ich ziehe alle Schnittstellen von tieferen Kompositionsklasse wie z.B. Fingernagel in die davor und die davor und die davor usw.
            Heisst ich habe nacher Fingernagelschnittstellen in Finger, Hand, Arm, und Mensch (oder aber nicht so krass: nur in Mensch)
            ..... Sowie bei allen anderen Schnittstellen (wichtigen Schnittstellen) auch!

            Submodul,klassen sind also alle schön verdeckt/gehided, hinter der Facade class Mensch. Schön und gut so sieht es von außen also wie das gute alte prozedurale programmieren aus
            Das tolle an der Facade an sich ist ja, mich interessiert auch nicht ob alles dahinter oo programmiert ist oder funktional oder sonst wie!


            2. Ansatz: Subklassen/module nach vorne reichen:

            Heisst Client macht getArm()->getHand()->getFinger()->getFingernagel()->do-operation(); / -> retrieve-data();

            Kapeslung/Information-Hiding wird leider aufgebrochen!



            Die Facade ist meiner Meinung ganz hübsch, aber halt im prozeduralen Stil, und wenn das dahinterliegende OO-programmiert ist, ein haufen Schnittstellen-geschubse und Overheadprogrammierung
            Zweiter Ansatz ist auch hübsch, steht aber OO-Prinzipien entgegen


            Eine weitere Frage dazu: wenn ihr Observer registriert, wo registriert ihr diese?, nur auf der class Mensch, oder aber wenn ihr jetzt nen Fingernagel-Observer haben wollt, den dann auch direkt auf der fingernagel-class?


            Das bis hierhin sind nur meine Gedankengänge, jetzt bin ich an euren interessiert!

            Zusammenfassende Fragen:

            Wie löst ihr OO sinnvoll mein Email-Problem (mit der Flexibiltät, erst sehr spät, also im Algorithmus selber zu entscheiden wie was gemacht wird)?
            -> also auch gerne generell: flexible Algorithmen
            Ihr habt eine Objektstruktur, wie greift ihr auf darunter Liegendes zu/ wie manipuliert ihr es/wie reordert ihr die Struktur/ wie observiert ihr das ganze/ wie lasst ihr Events durch das ganze fließen.


            Die zusammenfassende Fragen, dürft ihr auch mal unvoreingenommen von meinen Gedankengängen beantworten, würde mich echt mal interessieren, was da so die Best-pracisen sind^^
            Beide Thematiken habe ich in diesem Thread schon mal irgendwo leicht angerissen



            lg knotenpunkt

            Kommentar


            • #36
              Um dein Email-Problem so präzise wie nur möglich zu erklären, müsste ich jetzt zu sehr ausholen.
              Du hast OOP nicht verstanden. Deine Flexibilität ist eigentlich keine. Du solltest so weit es möglich ist mit "immutablen" Objekten arbeiten. Deine Email-Problematik gibt es so nicht, weil du das Modell falsch denkst. Du hast nicht für jeden Email-Dienst einen eigenen Service. Du hast nur einen Service, der unterschiedliche Konfigurationen bekommen kann.
              Vielleicht schreibe ich morgen mehr. Bin jetzt Kino.

              Gesendet von meinem Nexus 5X mit Tapatalk

              Kommentar


              • #37
                Ich bin mit rkr nicht zu 100% einverstanden. Du kannst für jeden Dienst einen Service haben und hast dann einen Dienst, der entscheidet, welcher der Maildienste angesprochen wird. Also Klasse -> MessageSendService -> MailMessageService.

                Das kann dann beispielsweise über einen Event sein (oder eine Konfiguration). Was, wenn du morgen nicht Mail via GMX sondern WhatsApp versenden willst?
                [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                Kommentar


                • #38
                  Das ist klar. Ich meinte auch explizit die Unterscheidung zwischen verschiedenen Mail-Diensten, bei denen sich nur die Zugangsdaten unterscheiden.
                  Die Unterscheidung zwischen verschieden-artigen Diensten wäre dann so richtig.

                  Kommentar


                  • #39
                    Zu dem zweiten Anliegen (Zugriff auf Objekt in tief geschachtelter Struktur):

                    Pauschalantworten dazu gibt es nicht. Das macht auch eine konkrete Beantwortung im Grunde nicht möglich, weil eben keine echte Problemstellung existiert, sondern nur ein konstruiertes Beispiel.

                    Praktisch wirst du selten die Notwendigkeit haben, dich über so viele Ebenen zu hangeln. Wenn du beispielsweise so was hast…

                    Code:
                    function f(Mensch $mensch)
                    {
                        $fingernagel = $mensch->getArm()->getHand()->getFinger()->getFingernagel();
                        $fingernagel->doSomething();
                    }
                    …, wäre die naheliegende Frage: Wieso muss f Mensch kennen, wenn die Funktion nur mit Fingernagel arbeitet? → function f(Fingernagel $fingernagel)

                    Es ergibt bei einer Besprechung davon dann ohne Kontext einfach keinen Sinn, etwa davon auszugehen, dass ein solches Umschreiben keine Option ist. Derlei theoretische Worst-Case-Szenarien sind eben gewissermaßen per Definition so konzipiert, dass jedem Vorschlag mit einem „aber wenn das nicht geht“ begegnet werden kann.

                    Letztlich wird es dann wohl einfach zu einer Stilfrage, aus der sich meines Erachtens schwerlich eine best practice ableiten lässt, weil dazu fallbezogen argumentiert werden müsste.

                    Mensch könnte mit einer eigenen Methode eine Abkürzung zum Fingernagel erhalten. Das wäre kontextlos nicht meine erste Wahl, weil es eher syntaktischer Zucker ist als eine Notwendigkeit (an den Fingernagel ist auch auf dem langen Weg durch den Objektgraphen zu kommen), aber ausschließen würde ich die Option trotzdem nicht.

                    Ebenso denkbar wäre eine Wrapper-Klasse nach dem Schema:

                    Code:
                    $fingernagel = (new MenschWrapper($mensch))->getFingernagel();
                    * * *




                    1 Ansatz: Facade
                    ich klopfe meine Menschkomposition flach, heisst:

                    ich ziehe alle Schnittstellen von tieferen Kompositionsklasse wie z.B. Fingernagel in die davor und die davor und die davor usw.
                    Heisst ich habe nacher Fingernagelschnittstellen in Finger, Hand, Arm, und Mensch (oder aber nicht so krass: nur in Mensch)
                    ..... Sowie bei allen anderen Schnittstellen (wichtigen Schnittstellen) auch!

                    Submodul,klassen sind also alle schön verdeckt/gehided, hinter der Facade class Mensch. Schön und gut so sieht es von außen also wie das gute alte prozedurale programmieren aus […]
                    Es ist wie gesagt schwierig, Pauschalantworten zu suchen und zu finden. Regeln im Stil von „Ich mache das immer so“ gibt es auf der Ebene eigentlich nicht. Möglichst flache Zugriffsmethoden für alle möglichen Objekte anzubieten, ergibt allgemein eher wenig Sinn. Das ist richtig erkannt. Grundsätzlich ist jede „unnötige“ Methode, die das öffentliche Interface erweitert, mit einem gewissen Argwohn zu betrachten, weil sie die Sache erst mal komplexer macht.

                    2. Ansatz: Subklassen/module nach vorne reichen:

                    Heisst Client macht getArm()->getHand()->getFinger()->getFingernagel()->do-operation(); / -> retrieve-data();

                    Kapeslung/Information-Hiding wird leider aufgebrochen!
                    Wobei dazu argumentiert werden kann, dass der Client auch bei $mensch->getFingernagel() genauso die Mensch-Instanz kennt und dadurch auch Zugriff auf Arm, Hand und Finger hat.

                    Das Problem ist in der Hinsicht eher, dass die Mensch-Instanz übergeben wurde.

                    Eine weitere Frage dazu: wenn ihr Observer registriert, wo registriert ihr diese?, nur auf der class Mensch, oder aber wenn ihr jetzt nen Fingernagel-Observer haben wollt, den dann auch direkt auf der fingernagel-class?
                    Auf die Frage würde ich auch auf die gleiche Art antworten, wie ich es bisher getan habe: Es hängt vom Anwendungsfall ab. Es ist schwierig, bei so was das richtige Maß aus Einfachheit und Flexibilität zu finden. „Beliebig kompliziert“ geht immer, ist aber natürlich ab einem gewissen Punkt nicht mehr sinnvoll.

                    Wenn du eine Kunden-Klasse für ein Shopsystem schreibst, kannst du zum Beispiel die Fingernägel mit als Daten modellieren, weil irgendwann der „Nagelstudio mit individuellen Designs“-Anwendungsfall kommen könnte, aber sinnvoll ist das bestimmt nicht.

                    Kommentar


                    • #40
                      Der eigentliche Unterschied zwischen OOP und PP ist eigentlich nur die Verwaltung von State und Behavior. Traditionell gibt es in OOP- und in FP-Sprachen Moeglichkeiten, Behavior in einem Container zu kapseln und als Parameter rumzuschicken. Alles andere kann man mit PP im Grunde auch machen. In OOP-Sprachen sind das Methoden eines Objekts und in FP-Sprachen sind das FC-Funktionen (Monaden etc). In PP-Sprachen gibt es eigentlich nur State.

                      PHP verwaessert diese Definition ein wenig, weil es hier jetzt auch Lambda-Funktionen und Closures gibt, die man in einer rein prozeduralen Anwendung als Parameter rumschicken koennte. Das eroeffnet einem Entwickler zwar einige Moeglichkeiten, die man andernfalls nur mit OOP oder FP haette, aber viele Features bleiben dann doch wieder nur OOP (gegenueber PP) vorbehalten: Typisierung, Ableitung, Referenzierung und internes Statehandling. Und davon sind im Alltag auch nur die Typisierung, das Referenzhandlich und as Statehandling interessant.

                      Ein Objekt ist ja eigentlich nichts anderes als ein Array plus Datentyp, der aussagt, von welcher Klasse die Methoden kommen. Methoden sind eigentlich statisch - sie haben selbst keinen objektspezifischen State (was man mit Reflection aber aendern kann). Gemeint ist, dass fuer alle Objekte eines Typs (ohne Reflection) die gleichen Verhaltensregeln seiner Klasse gelten - nur die Daten sind jeweils immer unterschiedlich.

                      OOP ist ein Denkmodell. Jedes Objekt ist im Grunde sein eigenes kleines Program, mit eigenem State und eigenen Funktionen (Methoden). Fuer mich als Entwickler ist es um Welten einfacher, komplexe Programme so zu strukturieren, dass Alles in kleine Problemloeser gekapselt wird. Und ich glaube, ich habe das schon mal geschrieben, aber OOP kann alles, was PP kann. PP kann aber nur einen Teil von dem, was OOP kann.

                      Zitat von knotenpunkt Beitrag anzeigen
                      wie damit umgehen, dass ich anfangs eh ne big klasse habe, die dann halt die schnittstellen der einzelnen objekte aufruft..... bspw. jede webanfrage wird erst mal in commands unterteilt und dann distribuiert
                      ist hier die verantwortlichkeit dann einfach so zusehen, dass die aufgabe darin besteht die commands aufzuteilen und weiterzugeben?
                      Im Grunde kommt sowas daher, dass du deine Problemdomain nicht richtig analysiert hast und somit keine, der eigentlichen Problemstellung gerechtwerdende Struktur aufgebaut hast.

                      Zitat von knotenpunkt Beitrag anzeigen
                      feste module verdrahten via DI, problem ist nur dass das eher eine art anfangst-configuration des programms ist, wenn ich aber direkt in der laufzeit erst entscheiden möchte wie was eingesetzt wird, und vlt. sogar mitten im algorithmus.....
                      Kommt drauf an. Aber ja, es geht normal erst um die Anfangskonfiguration. Wenn du im laufenden Betrieb Entscheidungen treffen willst, dann brauchst du entsprechende Komponenten, die diese Entscheidungen treffen koennen und selbst wiederrum die eigentliche Arbeit an Komponenten weiterdelegieren koennen, die sie wiederrum via DI gezogen haben. Und ja, du hast da irgendwo eine IF- oder ein SWITCH-Mechanismus, der die Entscheidung trifft, wie in PP. Nur da denkst du wieder ausschliesslich in Daten und nicht in Dingen.

                      Zitat von knotenpunkt Beitrag anzeigen
                      Das Problem das ich hier habe, seis in den Service-Klassen als auch in den Geschäftsklassen ist das, wenn ich irgendwo festen Zustand habe ich unflexibel werde!
                      Du hast die selbe Menge und Art von Zustand, wie in der PP auch. Ich habe es oben ja schon geschrieben: Dein Ziel sollte sogar sein, moeglichst feste Zustande zu haben. Das macht anfangs alles etwas schwieriger zu denken, spaeter ist der Wartungsaufwand bei Aenderungen aber niedriger, weil es weniger Ueberraschungsmomemte gibt - dieses "warum steht da jetzt eigentlich dies und das in dieser Variable drin?". Aber das ist im Grunde so sehr Geschmacksfrage wie PP statt OOP zu verwenden.

                      Falls du hier Bedenken hast, dann schau dir mal Elixir an - eine FP-Sprache, die keinen veraenderbaren State kennt und im Moment ueberraschend stark gefragt ist - gerade im Webumfeld. PHP kann aber sowas nicht ausreichend, weil dem Interpreter zu viel entsprechende Logik fehlt, um Operationen wie "etwas an Listen anhaengen" effizient abzubilden, denn diese sind in FP-Sprachen eben auch immutable. Oder "Tail Call Optimization" bei Rekursionen, weil es auch keine FOR-Schleifen gibt.

                      Zitat von knotenpunkt Beitrag anzeigen
                      Aber eigentlich vieler meiner Algorithmen möchte keinen festen Zustand verwenden, sondern erst zur Laufzeit und eventuell abhängig von diversen Faktoren entscheiden welche Service-Klasse oder andere Buisness-Klassen verwendet werden sollen

                      Sie hat bspw ne Membervariable die da heisst: Emailprovider (gmx, web, was eigenes, .....)
                      Jetzt möchte ich aber erst in meinem Algorithmus entscheiden welchen Provider ich verwenden möchte..... bspw. in jeder geraden Stunde gmx.de und in jeder ungeraden Stunde web.de / oder abhängig an wen die Email geht
                      => ein Setzten des Emailproviders via DI ist hier sinnlos
                      => DI allgemein ist sinnlos, wenn man überall diese Flexibilität geniesen möchte
                      => fester Zustand ist sinnlos, wenn man Flexibel sein möchte
                      Siehe oben.

                      Zitat von knotenpunkt Beitrag anzeigen
                      Frage wie ist das mit OO zu vereinbaren?
                      Frage wie würdet ihr das ganze Programmieren, um meine genannte Flexibilität zu erhalten

                      PS: ich möchte es dynamisch und nicht statisch (bei mir wird immer in letzter Sekunde entschieden was verwendet wird) <- wie programmiere ich schön OO dass ich weiterhin nach diesem Prinzip leben kann?
                      Wie oben schon geschrieben. Du ziehst dir nicht die konkreten Services via DI, sondern einen Service, der die Entscheidung fuer dich trifft. Easy as that (nein, ich bin kein Freund davon an Interfaces den Postfix Interface zu haengen):

                      PHP-Code:
                      <?php
                      interface MessageService {
                          public function 
                      create(): Message;
                          public function 
                      send(Message $message);
                      }

                      trait 
                      MessageFactory {
                          public function 
                      create(): Message {
                              return new 
                      Message();
                          }
                      }

                      class 
                      GmxMessageService implements MessageService {
                          use 
                      MessageFactory;
                          
                      /* ... */
                      }

                      class 
                      WebDeMessageService implements MessageService {
                          use 
                      MessageFactory;
                          
                      /* ... */
                      }

                      /**
                       * Will be used if the recipient is an valid phone number
                       */
                      class WhatsappMessageService implements MessageService {
                          use 
                      MessageFactory;
                          
                      /* ... */
                      }

                      class 
                      RulebasedMessageService implements MessageService {
                          use 
                      MessageFactory;
                          
                      /* ... */
                      }

                      class 
                      MessageSenderCtrl {
                          
                      /** @var MessageService */
                          
                      private $messageService;

                          public function 
                      __construct(MessageService $messageService) {
                              
                      /* GmxMessageService? WebDeMessageService? WhatsappMessageService? RulebasedMessageService? DI! */
                              
                      $this->messageService $messageService;
                          }

                          public function 
                      someAction() {
                              
                      /* ... */
                              
                      $this->messageService->send(
                                  
                      $this->messageService->create()
                                  ->
                      setSender(/* ... */)
                                  ->
                      setRecipient(/* ... */)
                                  ->
                      setSubject(/* ... */)
                                  ->
                      setText(/* ... */)
                              );
                              
                      /* ... */
                          
                      }
                      }
                      Zitat von knotenpunkt Beitrag anzeigen
                      Zweites Anliegen:

                      Ich habe meine schöne objektorientierte Welt aufgebaut: bspw. Mensch

                      class Mensch
                      class Arm
                      class Hand
                      class Finger
                      class Fingernagel

                      eine schöne Komposition ist entstanden: Mensch->Arm->Hand->Finger->Fingernagel
                      So die Frage ist ziemlich simpel:

                      Wie lese ich aus meiner Komposition Werte aus und wie setzte ich diese, oder allgemein, wie führe ich Operationen darauf aus:

                      Meiner Meinung nach gibt es zwei Ansätze (leider beide mal wieder nicht wirklich gut, wie ich finde)
                      Kommt drauf an, was du machen willst. Es gibt hier keine OneSizeFitsAll-Loesung, da es meistens auch drauf ankommt, wo die Daten herkommen und ob Aenderungen am Datenmodell auch sofort mit der Datenquelle abgeglichen werden sollen und wo die Validierung stattfindet.

                      Zitat von knotenpunkt Beitrag anzeigen
                      2. Ansatz: Subklassen/module nach vorne reichen:

                      Heisst Client macht getArm()->getHand()->getFinger()->getFingernagel()->do-operation(); / -> retrieve-data();

                      Kapeslung/Information-Hiding wird leider aufgebrochen!
                      An welcher Stelle wird da dein Information-Hiding aufgebrochen?

                      Kommentar


                      • #41
                        Ich hatte eigentlich insgeheim gehofft, dass das Thema allmälich beendet ist. Es wurde schließlich größtenteils alles gesagt, bzw. angerissen, oder?

                        Naja, wie auch schon vor Jahren gesagt habe: OOP ist nicht die Frage, sondern die Antwort. Klar mag es Gemeinsamkeiten geben, zwischen PP und OOP, das ist ja nur ein Aufsatz auf PP, um PP Design Fehler zu beheben. Kommt Zeit kommt Rat, so war es eben auch in der Programmierung. In der Luftfahrt stand am Anfang auch das Propellerflugzeug, heute haben wir Jets. Ähnlich verhält es sich mit PP und OOP. Das ist ein ständig wandelnder Prozess, der mit der Zeit geht. Gründe etwas altem hinter zu trauen zu suchen, hat keinen Zweck. Die Änderung hat sicherlich seine Gründe, die vielleicht nicht sofort nachvollziehbar erscheinen.

                        Lambda Expression, bzw. Ansätze der funktionalen Programmierung hat heutzutage jede Objektorientierte Programmiersprache, wurde Zeit, dass das auch endlich in PHP Einzug hielt. Folgelogisch, dass die Grenzen verwischen. Richtig Spaß machen diese Expressions aber eigentlich nur, wenn man Threads in die GUI einreihen will, wie im klassichen C# WPF Beispiel (z. B. Chat Client nach "Thread per Task"-Prinzip: Für jeden verbundenen Chat Teilnehmer/Client einen Thread. Wenn also mehrere Leute gleichzeitig Nachrichten versenden, dann muss für die Anzeige auf der GUI per Einreihung dafür Sorge getragen werden, dass keine Deadlocks entstehen). In diesem Kontext sehen Lambda Expressions sehr elegant aus und ersparen auch die ein oder andere Code Zeile, als wenn man das alles rein mit Klassen Objekten aufziehen würde. Außerdem braucht man dank Lambda Expression und functions delegates keine ganzen Klassen mehr für einen Threads. Ob das mittlerweile auch schon in der PHP pthreads Extension geht, weiß ich nicht, schön wäre das aber.

                        PHP 7 ist auf einem guten Weg, ich hoffe das bleibt so und wir können uns bald über Klassen Sichtbarkeiten freuen. Wenn die standardmäßig public wären, dann wäre das auch noch ganz easy abwärtskompatibel.

                        Kommentar


                        • #42
                          Naja, dass OOP die Antwort auf alles ist, würde ich jetzt auch nicht laut sagen wollen. Es ist für eine bestimmte 'Klasse von Problemen' die richtige Antwort.*


                          PP eignet sich gut für systemnahe Programmierung, bei der möglichst keine Performanceverluste durch das eingesetzte Werkzeug entstehen sollten. Besonders GC und das häufig nicht vorhandene Pointer-Management machen OOP hier zu keiner vernünftigen Lösung.*


                          Wenn du unter Einsatz von entsprechender Hardware möglichst effizient Nebenläufigkeit abbilden willst und deine Geschäftslogik nicht unter einer nicht-sequenziellen Abarbeitung der Daten leidet, dann ist FP die richtige Wahl.*


                          Wenn du komplexe Geschäftsprozesse abbilden willst und die Wartung von einer klaren Struktur und wohldefinierten Zuständigkeiten profitiert, dann kommst du schwer an OOP vorbei.*


                          Es gibt weitere Paradigmen, die sich für bestimmte Probleme besser eignen, als OOP. Beispielsweise*Deklarative Programmierung*(HTML, CSS, XML, YAML) und andere.*


                          Da wir hier in einem PHP-Forum sind, und PHP an sich kaum vom prozeduralen Modell profitiert (zumindest weit weniger als vom objektorientierten Modell) habe och mich hier klar positioniert. Außerdem war die Prämisse ja, dass OOP eigentlich nur verkompliziertes PP ist. Zumindest habe ich es so verstanden.*

                          Kommentar


                          • #43
                            Zitat von rkr Beitrag anzeigen
                            PP eignet sich gut für systemnahe Programmierung, bei der möglichst keine Performanceverluste durch das eingesetzte Werkzeug entstehen sollten. Besonders GC und das häufig nicht vorhandene Pointer-Management machen OOP hier zu keiner vernünftigen Lösung.
                            C++ hat keinen GC und unterstützt Pointer. Aber ehrlich gesagt würde ich nicht freiwillig C++ programmieren

                            Kommentar


                            • #44
                              Zitat von hellbringer Beitrag anzeigen

                              C++ hat keinen GC und unterstützt Pointer. Aber ehrlich gesagt würde ich nicht freiwillig C++ programmieren
                              ach wieso? Ich habe gestern ca 4 Stunden gebraucht, um herauszufinden wie man in C++ __DIR__ macht https://github.com/BlackScorp/DwarfF...er.cpp#L37-L42 und wie man ein foreach macht https://github.com/BlackScorp/DwarfF...er.cpp#L74-L76

                              easy als nächstes muss ich mal finden wie man SplFileInfo in C++ umsetzt sowie str_replace (aktuell sieht es aus als müsste ich std::regex_replace nutzen)
                              apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                              Kommentar


                              • #45
                                Zitat von BlackScorp Beitrag anzeigen
                                als nächstes muss ich mal finden wie man SplFileInfo in C++ umsetzt sowie str_replace (aktuell sieht es aus als müsste ich std::regex_replace nutzen)
                                Ok, als reiner PHPler kennt man warscheinlich viele Systemfunktionen nicht. In C++ kann man viele Systemfunktionen direkt nutzen, die man aus der Bash kennt. Also atime, mtime und ctime sollten in irgendeinem Header vorhanden sein. str_replace müsste es auch so 1:1 in C++ geben. Die PHP Funktion ist ja nur eine Kopie davon. In Punkto "Abschreiben" war das PHP Core Team ja schon immer gut...

                                hellbringer C++ hat sehr wohl eine Garbage Collection, das neue C++ zumindest, also alles ab C++ 11 hat auch eine darunter liegende VM und wird nur noch in Byte Code kompiliert. Das alte C++ hat keine Speicherverwaltung aka Garbage Collection. Um das Löschen von Variablen musste sich dort, wie auch in C, der Programmierer selbst kümmern. Aber man hat aus den anfänglichen Desing-Fehlern gelernt. Deswegen ist C++ 11 um vieles geiler als sein Vorgänger.

                                Kommentar

                                Lädt...
                                X