xilent_xage schreef op donderdag 15 juli 2010 @ 17:29:
Ok, die loop lag dus aan de brakheid van mijn voorbeeld, in mijn werkelijke code heeft elke class zn eigen constructor. Anyway , ik begin inmiddels gezien de vele opmerkingen te geloven dat het toch een kwestie is van een verkeerde OO-structuur.
Ik zal even toelichten wat ik probeer te bereiken:
- Mijn index.php doet niks anders dan een config file inlezen en op basis van de instellingen een bepaalde versie van mijn framework aanroepen.
- Mijn framework bestaat uit een soort backbone die inkomende requests afhandelt.
- Deze backbone begint met het aanroepen van een aantal objecten die overal in de code gebruikt moeten kunnen worden: Een urlparser, de output-handler, de debugger/profiler, de sql-connectie enz.
- Al deze objecten zijn netjes OO gebouwd, dus als class met properties en methods.
- De objecten hebben mekaar nodig, zo geeft de sql-connectie bij elke query netjes een debuglog aan de debugger/profiler. En de urlparser moet bij de database kunnen.
Bovenstaande opzet leek me hiervoor geschikt, maar blijkbaar kan dat niet, of moet ik een andere opzet kiezen. Hoe zouden jullie dit doen?
Tot op heden gebruikte ik daarvoor steeds global, maar het lijkt me dat dat met een iets meer OO-benadering beter moet kunnen?
Klinkt goed. Het is natuurlijk wel zo dat de afhankelijkheden allemaal 'heeft een' relaties zijn en geen 'is een' (wat je een beetje leek te doen in de topicstart).
De sql-connectie heeft dus een logger nodig en
is dit natuurlijk niet. De database en logger hebben dan ook geen overeenkomstig gedrag. Deze relaties los je over het algemeen op met dependency injection, klinkt fancy maar dit kan bijvoorbeeld makkelijk door de dependency mee te geven aan de klasse die hem nodig heeft in de constructor:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| class Backbone {
protected $logger, $database;
public function __construct() {
$this->logger = new Logger();
$this->database = new Database($this->logger);
}
}
class Database {
protected $logger;
public function __construct(Logger $logger) {
$this->logger = $logger;
}
public function query() {
// query stuff here
$this->logger->log($debugInfo);
}
} |
Zoiets dus. Zo kun je overal de dependencies doorgeven waar ze nodig zijn.
Het is wel zo dat je al snel sommige objectpointers door je hele applicatie door aan het geven bent (met name loggers en databases

) en dat kan al snel voelen alsof je veel te veel loze code hebt die niks anders doet dan objecten doorschuiven. Je kan dit eventueel oplossen door van deze objecten
singletons te maken, wat ook nog enigszins verdedigbaar is voor database en (zeker) logging objecten. Ik zelf gebruik echter nooit singletons omdat ze net als global variables een global state in je programma introduceren waardoor afhankelijkheden tussen klassen al snel onduidelijk worden en de afhankelijkheden ook minder dynamisch te veranderen zijn (zie ook:
http://www.c2.com/cgi/wiki?GlobalVariablesAreBad).
Er zijn ook wel andere mogelijkheden zoals extra abstractielagen toevoegen, maar dit maakt het geheel al snel veel te abstract en omslachtig voor wat je waarschijnlijk in eerste instantie nodig hebt
Zoiets wat je bedoelde?
offtopic:
Wat een geblaat altijd over PHP en hoe slecht het wel niet is, maar het heeft naar mijn mening een van de duidelijkste manuals. Die zin vind ik ook totaal niet dubbelzinnig aangezien het verwachte gedrag wel heel erg wordt geïnsinueerd. Om het dan gelijk ambigu te noemen...
[
Voor 4% gewijzigd door
Shagura op 15-07-2010 19:11
]