class zonder public method?
Pagina: « vorige 1 2 3 volgende »
Ozzie PHP op 11/11/2013 14:48:45:
>> registreer rechtstreeks één autoload-functie (in plaats van een klasse);
Maar waar laat je die dan? Zet je die functie in je bootstrap?
Maar waar laat je die dan? Zet je die functie in je bootstrap?
Je moet ergens beginnen met een require die de pijlen richt op het Ozzie-framework. Of je dat nu de "configuratie", een "bootstrap", de "kernel" of een "environment-class" noemt, is eigenlijk lood om oud ijzer. En ja, die termen worden allemaal gebruikt, consistentie is wat dat betreft ver te zoeken.
Maar verder doet het er ook niet zoveel toe: nadat we het Ozzie-framework hebben opgestart, willen we dat het begrijpt hoe het Ozzie-dingen in de Ozzie-namespace geregeld zijn. Daar hoort een autoloader wat mij betreft bij.
Ozzie PHP op 11/11/2013 14:48:45:
>> prepend de autoload-functie (zodat deze als eerste aan de beurt is en niet — je zal ze ertussen hebben zitten — een autoloader die een directoryscan gebruikt).
Wat bedoel je precies met prepend? Ik heb maar 1 autoloader.
Wat bedoel je precies met prepend? Ik heb maar 1 autoloader.
Dat hangt van de serverconfiguratie af, want autoloaders worden gestapeld. Daarnaast hangt het af van wat je aan software van derden gebruikt, want die registreren vaak hun eigen autoloader. Als de eerste autoloader een klasse niet kan vinden, wordt de volgende ingeschakeld. Daarom wil je met prepend de eerste zijn.
Ozzie PHP op 11/11/2013 14:48:45:
Maar waarom niet in een class? Dat zal qua performance toch niks uitmaken?
Waarom een object aanmaken dat verder niet wordt gebruikt? Je hebt dan in feite twee instanties van hetzelfde: de autoload-klasse plus de door die autoload-klasse geregistreerde autoload-functie. Als je die klasse enkel en alleen gebruikt om de autoload-functie te registreren, kun je beter de functie rechtstreeks registeren.
Wat hier niet helpt, is dat PHP geen elegante Singleton kent. Van de autoloader voor je complete framework heb je maar één instantie nodig. Meerdere keren dezelfde autoloader instantiëren heeft geen zin, maar een new Autoloader() kan te makkelijk worden herhaald. Je zult daarom, linksom of rechtsom, moeten regelen dat die autoloader maar één keer wordt geladen.
Gewijzigd op 11/11/2013 15:39:50 door Ward van der Put
De class bevat dus ook de aut0load functie zelf voor het Ozzie framework.
>> Meerdere keren dezelfde autoloader instantiëren heeft geen zin, maar een new Autoloader() kan te makkelijk worden herhaald.
Ik snap je punt, maar dan moet ik de complete autoloader dus in m'n bootstrap gooien, en dan maakt ie geen onderdeel meer uit van de library. Dat vind ik eigenlijk wel jammer. Maar ik snap wel wat je bedoelt. Ik ga er nog ff over nadenken...
Code (php)
Dat heeft zowel voor- als nadelen. Zodra de constante !defined() is of ongelijk aan true is, weet je dat de autoloader niet geladen is. Maar-maar-maar: je roept daarmee buiten de klasse een globale constante in het leven. En die kan dus bijvoorbeeld buiten die klasse worden gezet. Of toevallig al bestaan, mocht iemand toevallig net dezelfde constantennaam gebruiken...
Overige opties... register functie toch public maken en handmatig aanroepen. Ik ga ervan uit dat niet zomaar iemand 'm dan aanroept.
Van de andere kant... het is de autoloader die bij het framework zelf hoort. Waarom zou iemand die zomaar aanroepen?
Wat vind jij nou overigens van de vraag of een class dan "zelfregulerend" mag zijn?
Ik verwijs weer even naar mijn eerdere voorbeeld: http://www.phphulp.nl/php/forum/topic/class-zonder-public-method/92895/1/#665442
Als een class iets configureert, moet je dan zelf de configure() method aanroepen, of dit door de constructor laten doen? Als je het de constructor laat doen, zie je niet direct dat er iets gebeurt. Van de andere kant, als je toch altijd die functie moet aanroepen, waarom zou je het dan handmatig doen? Je wil in feite alleen maar de geconfigureerde gegevens opvragen. Toch?
Even voor de duidelijkheid.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
// code...
// Doe dit a.u.b. nooit
new Autoloader;
// dit is prima zolang je $autoloader nog ergens gebruikt
$autoloader = new Autoloader;
// ook prima zolang de functie/method er iets mee doet
Static::method(new Autoloader);
function(new Autoloader);
// code
?>
// code...
// Doe dit a.u.b. nooit
new Autoloader;
// dit is prima zolang je $autoloader nog ergens gebruikt
$autoloader = new Autoloader;
// ook prima zolang de functie/method er iets mee doet
Static::method(new Autoloader);
function(new Autoloader);
// code
?>
Quote:
Ik snap je punt, maar dan moet ik de complete autoloader dus in m'n bootstrap gooien, en dan maakt ie geen onderdeel meer uit van de library.
Wat doe jij precies in je Autoload classe? Dit is nogal onduidelijk.
Is het iets zoals http://kohanaframework.org/3.3/guide-api/Kohana#init ?
Als je ALTIJD een method aan moet roepen voor het object bruikbaar is, refactor het dan zodat het deel is van de constructor.
Of de Autoloader::configure() method na het refactoren nog bestaat hangt er van af of Autoloader::configure() method later ook nog nuttig aangeroepen zou kunnen worden. Mogelijk knip en plak je dus alle code van Autoloader::configure() naar Autoloader::__construct() en verwijder je Autoloader::configure().
Gewijzigd op 11/11/2013 16:40:37 door Dos Moonen
Dos Moonen op 11/11/2013 16:39:44:
@Ward, je kunt constanten ook in namespaces zetten.
Ja, dat weet ik, maar Ozzie wil geen namespaces gebruiken...
Over de autoloader class:
In die class set ik in de constructor 2 paden. Vervolgens heb ik een autoload-method die de class-files requiret (op basis van de class-naam) en vanuit de constructor roep ik een functie aan die die method registreert (kan ook rechtstreeks vanuit de constructor maar ik vind dit wat duidelijker). Heel schematisch:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class Autoloader {
private $pad1;
private $pad2;
public function __construct() {
// set $pad1;
// set $pad2;
$this->register();
}
private function autoload($class) {
// laad een class file
// afhankelijk van de "hoofd"-namespace gebruik je pad 1 of 2
}
private function register() {
// register the autoload functie
}
}
?>
class Autoloader {
private $pad1;
private $pad2;
public function __construct() {
// set $pad1;
// set $pad2;
$this->register();
}
private function autoload($class) {
// laad een class file
// afhankelijk van de "hoofd"-namespace gebruik je pad 1 of 2
}
private function register() {
// register the autoload functie
}
}
?>
Dit is wel ff heel kort door de bocht, maar dan heb je een idee.
Dan wat betreft die configurator vraag... heeft dus niks met de autoloader te maken... stel ergens in je applicatie heb je data, bijvoorbeeld een array $foo. En die array $foo moet op de een of andere manier geconfigureerd worden. Dit doe je met behulp van de (fictieve) class FooConfigurator. Deze class is dus bedoeld om $foo te configureren. Nu is mijn vraag, voordat je de geconfigureerde gegevens kunt opvragen aan deze class, moeten ze natuurlijk eerst geconfigureerd worden. Laat je dat door de constructor doen, of doe je dat zelf door handmatig de configure() method aan te roepen. Als je het handmatig aanroept, zie je in de code beter wat er gebeurt:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$fc = new FooConfigurator($foo);
$fc->configure(); // hé, er wordt geconfigureerd!
$foo_new = $fc->get();
?>
$fc = new FooConfigurator($foo);
$fc->configure(); // hé, er wordt geconfigureerd!
$foo_new = $fc->get();
?>
Als de constructor in de class zelf de configure method aanroept, dan zie je minder goed dat er wordt geconfigureerd:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$fc = new FooConfigurator($foo);
// nu zie je niet zo goed dat er wordt geconfigureerd!
$foo_new = $fc->get();
?>
$fc = new FooConfigurator($foo);
// nu zie je niet zo goed dat er wordt geconfigureerd!
$foo_new = $fc->get();
?>
Toch lijkt me de laatste optie beter. Wat is jullie mening?
>> Ja, dat weet ik, maar Ozzie wil geen namespaces gebruiken...
Jawel! Tegenwoordig ben ik ook aan de namespaces :)
Maar het zou wel fijn zijn als jullie even uitleggen wat jullie met die opmerking over constanten en namespaces bedoelen... :-/
Gewijzigd op 11/11/2013 17:02:56 door Ozzie PHP
Dat is precies wat Wouter bedoelde met een autoloader die namespaces ondersteunt.
Je gaat toch hopelijk niet de paden in de klasse instellen ozzie, maar erbuiten?
Toevoeging op 11/11/2013 17:19:21:
Misschien moet ik het nog duidelijker maken. Dit is een autoloader die alleen voor OzzieFramework werkt. Het is niet bedoeld voor libraries van derden.
Als je dit soort dingen gaat opslaan in een klasse heb je echt OO nog niet begrepen en moet je ophouden met deze OO vragen te stellen. Ga dan eerst een maandje OO leren, zonder aan code of aan je framework te denken. Anders wordt het echt niks.
Gewijzigd op 11/11/2013 17:31:38 door Wouter J
Ozzie PHP op 11/11/2013 17:17:07:
Ja, snap ik... maar in m'n eigen Ozzie framework heb ik die 2 nodig. Als ik een library van derden ga gebruiken, dan gebruik ik hun autoloader.
Zo te zien heb je een soort master met meerdere slaves. Als dat inderdaad zo is, zou ik pad1 én pad2 doorgeven aan de autoloader, niet pad1 óf pad2.
Dat was nu dus niet de insteek. Wat betreft doorgeven van paden heb je gelijk. Zal ik nog even aanpassen. Maar ik heb dus een specifieke autoloader die alleen voor het Ozzie framework is bedoeld. Eigenlijk hoort ie dus ook niet in de library thuis.
>> Zo te zien heb je een soort master met meerdere slaves. Als dat inderdaad zo is, zou ik pad1 én pad2 doorgeven aan de autoloader, niet pad1 óf pad2.
Hij heeft ook alle 2 de paden...
Kun je nog even reageren op de FooConfigurator vraag? Dan laten we de autoloader even rusten. Ik moet even kijken wat ik daarmee ga doen.
Ozzie PHP op 11/11/2013 17:36:41:
Kun je nog even reageren op de FooConfigurator vraag? Dan laten we de autoloader even rusten. Ik moet even kijken wat ik daarmee ga doen.
Die "configurator" zal "iets" moeten "configureren", nietwaar? Naar alle waarschijnlijkheid is dat "iets" nog een "configuratie" ook. Lijkt me wel logisch.
Maar wees dan concreet. Is de configuratie één bestand? Is de configuratie één instelling? Of zijn het meerdere instellingen, bijvoorbeeld in een array? Of kan alles?
Wat Dos eigenlijk ook al zei: maak zulke keuzen expliciet in plaats van impliciet of "implied". Kies! En kies daarna door!
Dit was gewoon een simpel voorbeeld. Je hebt een of andere data $foo. Daar moet iets mee gebeuren. Wat er mee moet gebeuren maakt niet uit, maar het is altijd hetzelfde. Weet je wat? Laten we zeggen dat $foo een taart is en dat de class die taart in stukken moet snijden. Dat is het enige wat die class doet. Nu is de vraag, geef jij zelf de opdracht om die taart in stukken te snijden:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$taart_snijder = new TaartSnijder($taart);
$taart_snijder->snijTaart();
$gesneden_taart = $taart_snijder->get();
?>
$taart_snijder = new TaartSnijder($taart);
$taart_snijder->snijTaart();
$gesneden_taart = $taart_snijder->get();
?>
... of laat je de constructor de opdracht tot snijden geven:
Code (php)
1
2
3
4
2
3
4
<?php
$taart_snijder = new TaartSnijder($taart);
$gesneden_taart = $taart_snijder->get();
?>
$taart_snijder = new TaartSnijder($taart);
$gesneden_taart = $taart_snijder->get();
?>
De taart moet altijd 1x gesneden worden. Wie geeft de opdracht. Jijzelf of de constructor?
Gewijzigd op 11/11/2013 18:05:10 door Ozzie PHP
Vervolgens verklaar je het specifieke antwoord op die specifieke vraag tot een algemeen geldend antwoord op de algemene vraag.
Zo werkt het niet, hè. Niet in wetenschapsfilosofie. En meer praktisch ook niet in PHP.
Gewijzigd op 11/11/2013 18:13:23 door Ward van der Put
Een class moet 1 sepcifieke handeling uitvoeren. Deze specifieke handeling, geef je daar zelf opdracht toe, of zorg je dat de constructor dat doet?
Zo, algemener kan ik mijn vraag niet stellen :)
Waarom zou die klasse niet door andere projecten gebruikt mogen worden? OO draait om hergebruik, niks anders.
1) Waarom zouden libraries die jij kiest ooit jouw Autoloader class gebruiken?
2) Met de reflection API is het alsnog mogelijk.
In het geval van de versimpelde Autoloader is de register() method overbodig en kan je spl_autoload_register() gewoon in de constructor gebruiken.
Zonder reflection kan je zo goed als niets met dat Autoloader object. Wat me terug brengt op de vraag die ik eerder stelde.
Wat is [dan] je reden om een object aan te maken? Maak er twee static methods van zodat Autoloader een static helper class wordt. Ik zie namelijk geen enkele reden waarom je een object zou willen.
Ik verwacht dat constructors een bruikbaar object kunnen afleveren. Als ik niet genoeg parameters mee geef aan de constructor om een bruikbaar object af te leveren dan wil ik blijkbaar geen bruikbaar object. Daar hoor ik dan mijn redenen voor te hebben. Ik kan het object bijvoorbeeld als parameter doorgeven aan iets dat het verder initialiseert via setters.
Ik snap niet helemaal wat je bedoelt. Om welke 2 methods gaat het dan, en waar laat je die? Kun je misschien een heel simpel (schematisch) voorbeeldje geven?
>> Ik verwacht dat constructors een bruikbaar object kunnen afleveren. Als ik niet genoeg parameters mee geef aan de constructor om een bruikbaar object af te leveren dan wil ik blijkbaar geen bruikbaar object.
Oké... maar iemand anders op het forum zegt dat wanneer je een object aanmaakt het altijd zo goed als gebruiksklaar moet zijn. Anders heb je alleen maar een soort "omhulsel". En dat is dus lastig. De een zegt dit, de ander dat.