php.de

Zurück   php.de > Webentwicklung > Software-Design

Software-Design Diskussionen auf Profi-Niveau: PHP Lösungen auf konzeptioneller Ebene

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 14.07.2011, 01:05  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard DI Komposition

Hallo,

ich spiele momentan damit einen eigenen dic zu schreiben. er ähnelt vom aufbau her ein wenig google guice, alles wird immer gegen ein interface gebunden. das ist auch alles wunderschön so, jedoch ist mir eine tolle weitere idee gekommen.

im klartext geht es darum, wie man elegant eine klasse um funktionalität erweitert ohne diese neu zu implementieren.

möglichkeit 1.
ersetzen und erben.

ich denke diesen weg gehen die meisten di frameworks, man ersetzt einfach den kompletten service. das hat den nachteil, dass nicht unterschiedliche module identische services ersetzen können.

aus diesem grund habe ich mir was einfallen lassen um die klassen im DI elegant erweitern zu können - von unterschiedlichsten modulen gleichzeitig.

dabei setze ich frei nach clean code developer auf komposition statt vererbung. [b] in diesem thread suche ich NUR gründe dies nicht zutun. ich habe sowas vorher noch nie in einem dic gesehen, begründet? [b]

die api soll ähnlich dieser sein:

PHP-Code:
public function testDecorate() {
        
$di = new di();

        
$di->bind('istd')->to('diDecorateStd1');
        
$di->bind('istd')->to('diDecorateDecorator1')->decorated(true);
    
        
$this->assertEquals($di->get('istd')->foo(), 'foo, decorated1!');
    }

    public function 
testDecorateMultiple() {
        
$di = new di();

        
$di->bind('istd')->to('diDecorateStd1');
        
$di->bind('istd')->to('diDecorateDecorator1')->decorated(true);
        
$di->bind('istd')->to('diDecorateDecorator2')->decorated(true);

        
$this->assertEquals($di->get('istd')->foo(), 'foo, decorated1!, decorated2!');
    } 

man hat ein interface welches man an eine klasse bindet, ein $di->get([INTERFACE]) liefert diese instantz. möchte man den service mit diesem interface erweitern, fügt man einfach einen decorator hinzu. der Decorator muss logischerweise das identische interface implementieren.

ab nun liefert der di die korrekte decorierte intanz des objektes zurück. natürlich kann ein service unendlich oft decoriert werden.

der code ist hier zu finden:

https://github.com/timglabisch/pimDI...est/diTest.php

bitte beachten, dass der dic noch nicht fertig ist.
notyyy ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 14.07.2011, 01:18  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Also entweder drückst Du Dich extrem verklausuliert aus oder ich bin total begriffsstutzig. So wie ich es verstanden habe halte ich das ganze für großen Schwachsinn. Wenn verschiedene Komponenten bei Dir verschiedene Servicevarianten brauchen, dann schreib halt meherere Instanzen in den DI-Container?! Wie sollst Du sonst die Übersicht behalten, welchen Typus ein Service aktuell hat? Mit Deinem Code kann ich irgendwie gar nichts anfangen. Angemerkt sei, nicht jedes Objekt funktioniert, wenn man es dekoriert.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 14.07.2011, 01:57  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von nikosch Beitrag anzeigen
Also entweder drückst Du Dich extrem verklausuliert aus oder ich bin total begriffsstutzig.
wenn du mir sagen würdest was unklar ist, versuche ich es erneut zu erklären.

Zitat:
Zitat von nikosch Beitrag anzeigen
So wie ich es verstanden habe halte ich das ganze für großen Schwachsinn.
kannst du das näher begrunden?

Zitat:
Zitat von nikosch Beitrag anzeigen
Wenn verschiedene Komponenten bei Dir verschiedene Servicevarianten brauchen, dann schreib halt meherere Instanzen in den DI-Container?!
darum geht es in diesem thread nicht, dafür nutze ich identisch wie google guice benamte services.

Zitat:
Zitat von nikosch Beitrag anzeigen
Angemerkt sei, nicht jedes Objekt funktioniert, wenn man es dekoriert.
das stimmt, jedoch sollte dies der Ausnahme entsprechen, der decorator muss nur ein weiteres interface mit beispielsweise der funktion setParent implementieren, und natürlich das original interface.

die möglichkeit den service zu ersetzen bleibt ja bestehen.
notyyy ist offline   Mit Zitat antworten
Alt 14.07.2011, 01:59  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Zitat:
wenn du mir sagen würdest was unklar ist, versuche ich es erneut zu erklären.
Fangen wir doch hiermit an:
Zitat:
im klartext geht es darum, wie man elegant eine klasse um funktionalität erweitert ohne diese neu zu implementieren.
Ein halbwegs konkreter Anwendungsfall trüge auch zum Verständnis bei.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 14.07.2011, 02:18  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von nikosch Beitrag anzeigen
Ein halbwegs konkreter Anwendungsfall trüge auch zum Verständnis bei.
hier geht es um klassische komposition:

http://www.clean-code-developer.de/R...ritance_FCoI_3


vererbung und direkte abhängigkeiten. instanzen können von klassen welche das selbe interface implementieren relativ einfach "erweitert" werden indem diese die originalklasse dekorieren. der beispielcode sollte da eigentlich gut zeigen.


$di->bind('istd')->to('diDecorateStd1');
$di->bind('istd')->to('diDecorateDecorator1')->decorated(true);

hier hat man nun eine instanz von diDecorateDecorator1 welche das interface istd implementiert. der instanz wurde eine instanz von diDecorateStd1 welche identisches interface implementiert übergeben.
notyyy ist offline   Mit Zitat antworten
Alt 14.07.2011, 02:54  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Der Link beschreibt ein Vorgehen, keinen Anwendungsfall.
Zitat:
vererbung
beschreibt ein Prinzip, keinen Anwendungsfall.
Zitat:
und direkte abhängigkeiten
beschreibt ein Problem, keinen Anwendungsfall.
Zitat:
instanzen können von klassen welche das selbe interface implementieren relativ einfach "erweitert" werden indem diese die originalklasse dekorieren
Ja, das nennt man Decorator.

Zitat:
$di->bind('istd')->to('diDecorateStd1');
$di->bind('istd')->to('diDecorateDecorator1')->decorated(true);

hier hat man nun eine instanz von diDecorateDecorator1 welche das interface istd implementiert. der instanz wurde eine instanz von diDecorateStd1 welche identisches interface implementiert übergeben.
Sorry, aber Deine Code wie auch Sätze bleiben Kauderwelsch für mich. Wenn Du den Dingen mal gescheite Namen geben würdest, meinetwegen auch Beispielnamen, dann verstünde ich viell. was. Mit rekursiven Abstraktionen wie „diDecorateDecorator1“ kann ich beim besten Willen nichts anfangen. Das sieht für mich so aus, als wären sowohl Dein DI-Container, als auch der angeforderte Service dekorierte Objekte.

Im Übrigen heißt Komposition mitnichten automatisch Decorator.
Zitat:
der instanz wurde eine instanz von diDecorateStd1 welche identisches interface implementiert übergeben.
Wo das im Schnipsel passieren soll, sehe ich nicht. Nur weil beide ans selbe Interface gebunden werden, heißt das doch nicht automatisch, dass dekoriert wird. Was machst Du überhaupt bei Objekten, die zwei Interfaces bedienen? Oder meinst Du mit Interfaces die Bezeichner, über die Du die Services anforderst? Warum nennst Du die dann Interfaces? Fragen über Fragen.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 14.07.2011, 07:49  
Erfahrener Benutzer
 
Registriert seit: 30.07.2008
Beiträge: 1.169
PHP-Kenntnisse:
Fortgeschritten
xm22 sorgt für eine eindrucksvolle Atmosphärexm22 sorgt für eine eindrucksvolle Atmosphärexm22 sorgt für eine eindrucksvolle Atmosphäre
Standard

Ich verstehe das irgendwie auch nicht. Eher sehe ich Gefahren, weil man, wie nikosch schon anmerkte, überhauot nicht mehr weiß, welche Methoden der Service nun anbietet. Wenn er ledliglich ein Interface anbietet, dann ist ja alles klar.

Wenn man jedoch diese Klasse erweitert und dann dort, wo man den Service per Interface abruft, die Erweiterung benutzen will, dann könnte man sich den Aufruf per Interface wieder sparen und diesen direkt per Bezeichnung abrufen. Da hast Du dann die selbe Problematik wie in dem anderen Thread von Dir.

Langer Rede kurzer Sinn: Wenn man die Services, die Du erweiterst, per ursprünglichem Interface abruft (So habe ich es verstanden), dann wird der Abruf per Interface obsolet.
xm22 ist offline   Mit Zitat antworten
Alt 14.07.2011, 08:51  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Sofern du einen neuen oder veränderten Service Nutzen möchtest, implementiere das Interface und injiziere diesen Service in deine abhängige Komponente. Alles andere ist nicht anwendbar.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 14.07.2011, 16:21  
Erfahrener Benutzer
 
Registriert seit: 12.05.2005
Beiträge: 1.038
PHP-Kenntnisse:
Fortgeschritten
notyyy befindet sich auf einem aufstrebenden Ast
Standard

ich versuche es nochmal genauer zu erklären. ich wollte nicht unnötig viel code posten da er ja sowieso auf github verfügbar ist.

angenommen wir einen service, nennen wir ihn SayHelloService. wir benötigen für den service ein interface sowie die implementation.

PHP-Code:

inferface iSayHelloService 
{ public function sayHello(); }

class 
sayHelloServer implements iSayHelloService  {
 public function 
sayHello() {
  return 
'hello';
 }


nun können wir den service beim DiC registrieren:

PHP-Code:
$di = new di();
$di->bind('iSayHelloService')->to('sayHelloServer'); 
wenn wir den service nun benötigen, fragen wir den DI nach der standard implementation für das interface iSayHelloService.

PHP-Code:
$di->get('iSayHelloService'// returns instance of sayHelloServer 
alternativ kann man den service automatisch injizieren lassen:

PHP-Code:

class otherService {

/....

/**
* @inject
*/
function getSayHelloService(iSayHelloService $service) {
 
$this->service $service;
}

/...


nun kommen wir zur eigentlichen problematik, jemand möchte den helloWorldService erweitern, die einfachste möglichkeit wäre einen anderen service zu schreiben und den SayHelloervice zu ersetzen.

PHP-Code:
class ANDERER_sayHelloServer implements iSayHelloService  {
 public function 
sayHello() {
  return 
'was anderes!';
 }

nun könnte dem DIC gesagt werden, dass dieser service an das interface iSayHelloService gebunden werden soll.

idr. ist es jedoch so, das man einen service nur erweitern möchte un die original funktionalität nicht stören möchte, eine möglichkeit wäre:

PHP-Code:
class LOGGING_sayHelloServer extends sayHelloServer  implements iSayHelloService {
 public function 
sayHello() {
  
logger::log('sayHello called...');
  return 
parent::sayHello();
 }

nun hat man den service erweitert, alles wunderbar. - oder?

was passiert nun, wenn der service um weitere Funktionalitäten erweitert werden soll? Die Anzahl der Funktionalitäten sind unbekannt, bekannt ist nur das sie alle das interface iSayHelloService implementieren.

wenn man mal den dic vergisst, würde ich den weg über einen decorator lösen:

PHP-Code:
$service sayHelloServer_LOGGER(new sayHelloServer_FOO(new sayHelloServer_BAR(new sayHelloServer()))); 
dabei ist nur zu beachten, dass alle klassen welche decorieren, als konstruktor das "vaterobjekt" entgegen nehmen können und alle das interface iSayHelloService implementieren.

identisches verhalten möchte ich meinem DiC beibringen.

[php]
$di = new di();
$di->bind('iSayHelloService')->to('sayHelloServer');
$di->bind('iSayHelloService')->to('sayHelloServer_LOGGER')->decorated(true);
$di->bind('iSayHelloService')->to('sayHelloServer_FOO')->decorated(true);
$di->bind('iSayHelloService')->to('sayHelloServer_BAR')->decorated(true);

$di->get('iSayHelloService') // returns sayHelloServer_LOGGER(new sayHelloServer_FOO(new sayHelloServer_BAR(new sayHelloServer())));
[php]

ist die erklärung verständlicher?
notyyy ist offline   Mit Zitat antworten
Alt 14.07.2011, 16:33  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Warum wird ein Service an ein Interface gebunden und darüber abgefragt? Korrigiert mich, falls das typisch für DIC/IOC ist, aber ein Interface muss doch nicht zwingend ein gesamtes Objekt beschreiben und auf der anderen Seite können durchaus mehrere Objekte (also auch Services) das selbe Interface implementieren.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php komposition, komposition php, komposition php wiki, komposition in php, komposition php code, komposition statt vererbung, php class komposition, kompositionen php, guice beispielcode, di php, php klassen komposition

Alle Zeitangaben in WEZ +2. Es ist jetzt 01:37 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum