mappen opsplitsen?
Korte vraag. Ik zit me af te vragen... Stel ik heb 2 classes waarin ik de data van een request wil opslaan. In de ene class wil ik client data opslaan en in de andere server data. Voor welke mappenstructuur zouden jullie dan kiezen? A, B of C? (Ik snap dat er nog meer mogelijkheden zijn, maar ik zou graag weten welke van deze 3 jullie voorkeur heeft en waarom.)
A)
Of voor deze manier:
B)
Of...
C)
Het gaat me er vooral om wanneer je überhaupt over moet gaan tot het aanmaken van nieuwe directories. Je kunt zeggen dat beide classes onderdeel van het request zijn, en ze dus gewoon in de request map zetten (A). Je kunt ook zeggen dat het fenomeen "data" weliswaar tot het request behoort, maar een apart onderdeel daarvan is (B). En je kunt vervolgens binnen die data ook weer aparte mappen maken omdat het om verschillende typen, client en server, data gaat (C). Ben benieuwd naar jullie reacties en vooral hoe jullie daar mee omgaan en waar jullie je keuzes op baseren.
Gewijzigd op 25/02/2014 01:05:50 door Ozzie PHP
Daarmee vallen variant B en C af. Variant A zou ik dan wel met andere hoofdletters gebruiken als namespace:
De eerste klasse /Request/ClientData.php wordt dan met dezelfde tenaamstelling:
Behalve dat ik zou aanraden om altijd een vendor naam in je namespace op de eerste plek te zetten.
Stel je hebt een mapje met autoloaders, dan wil ik dus iedere autoloader een eigen map geven, dus zeg maar dit idee:
Code (php)
1
2
3
4
2
3
4
/autoloader/
autoloader.php // dit is de algemene systeem-autoloader
psr/
autoloader.php // een psr autoloader
autoloader.php // dit is de algemene systeem-autoloader
psr/
autoloader.php // een psr autoloader
Stel dat de psr autoloader een exception zou moeten gooien, dan gaat dat nu heel makkelijk:
Code (php)
1
2
3
4
5
2
3
4
5
/autoloader/
autoloader.php // dit is de algemene systeem-autoloader
psr/
autoloader.php // een psr autoloader
exception.php // een psr autoloader exception
autoloader.php // dit is de algemene systeem-autoloader
psr/
autoloader.php // een psr autoloader
exception.php // een psr autoloader exception
Stel echter dat ik alles in één map zou zetten, dan zou je zoiets krijge:
Code (php)
1
2
3
4
2
3
4
/autoloader/
autoloader.php // dit is de algemene systeem-autoloader
psrautoloader.php // een psr autoloader
psrautoloaderexception.php // een psr autoloader exception
autoloader.php // dit is de algemene systeem-autoloader
psrautoloader.php // een psr autoloader
psrautoloaderexception.php // een psr autoloader exception
Om dit soort lange bestandsnamen te voorkomen leek het me dus een goed idee om met mappen te werken. Maar het probleem daarvan is weer dat je heel veel mappen krijgt, waar vaak maar één bestand in staat (omdat niet zo heel veel classes een exception hoeven te kunnen gooien).
Heb je misschien nog wat advies, of een soort algemene stelregels hoe ik hier het beste mee om kan gaan?
Wouter J op 25/02/2014 10:31:12:
Behalve dat ik zou aanraden om altijd een vendor naam in je namespace op de eerste plek te zetten.
Helemaal gelijk in. Voor het gemak heb ik die even weggelaten.
Gewijzigd op 25/02/2014 13:11:00 door Ozzie PHP
Ik zou ook je vendor naam niet in je mappenstructuur opnemen, maar alleen in je namespace.
>> Heb je misschien nog wat advies, of een soort algemene stelregels hoe ik hier het beste mee om kan gaan?
Een interessant (en kort) artikel voor je: http://verraes.net/2011/10/code-folder-structure/
Ik zou één Request-hoofdcontainer gebruiken en die uitgebreider splitsen. Jouw tweedeling client/server is te veel ingegeven door netwerktechnologie. Bij het programmeren heb je eerder afzonderlijke componenten nodig voor bijvoorbeeld de POST bij formulieren, een cookie en een sessie. En die hebben meestal zowel client- als serverdata. Die tweedeling werkt daarom niet goed, denk ik: er is zowel te weinig als te veel overlapping met andere objecten, waardoor verantwoordelijkheden verkeerd verdeeld worden.
PSR heeft een eigen \Psr namespace. Daar hoort dus ook een PSR-autoloader in.
http://verraes.net/2011/10/code-folder-structure/
Thanks, dit gaat meer over welke onderdelen bij elkaar horen. Ik ben juist benieuw hoe je zo'n "onderdeel" of map op de beste manier kunt inrichten.
>> En meer praktisch vind ik het overzichtelijker als je de term data reserveert voor databases en andere vormen van data-opslag.
Ik snap wat je bedoelt, maar als ik het gewoon "client" zou noemen, dan lijkt het alsof het om de persoon "client" gaat, en niet om de data.
>> Bij het programmeren heb je eerder afzonderlijke componenten nodig voor bijvoorbeeld de POST bij formulieren, een cookie en een sessie.
Ben ik wel met je eens, maar is het nodig om voor cookie, files, get, post aparte classes te maken? Volgens mij zien die classes er toch allemaal hetzelfde uit? Ze moeten een get() en has() method hebben en dan ben je er al. In het kader van DRY (don't repeat yourself) is het toch niet goed om daar dan 4 classes voor te maken?
>> Een interessant (en kort) artikel voor je: Thanks, dit gaat meer over welke onderdelen bij elkaar horen. Ik ben juist benieuw hoe je zo'n "onderdeel" of map op de beste manier kunt inrichten.
>> En meer praktisch vind ik het overzichtelijker als je de term data reserveert voor databases en andere vormen van data-opslag.
Ik snap wat je bedoelt, maar als ik het gewoon "client" zou noemen, dan lijkt het alsof het om de persoon "client" gaat, en niet om de data.
>> Bij het programmeren heb je eerder afzonderlijke componenten nodig voor bijvoorbeeld de POST bij formulieren, een cookie en een sessie.
Ben ik wel met je eens, maar is het nodig om voor cookie, files, get, post aparte classes te maken? Volgens mij zien die classes er toch allemaal hetzelfde uit? Ze moeten een get() en has() method hebben en dan ben je er al. In het kader van DRY (don't repeat yourself) is het toch niet goed om daar dan 4 classes voor te maken?
Dan delen ze een get() en has() in een gemeenschappelijke RequestInterface of AbstractRequest, maar er is nog steeds een groot verschil tussen een $_POST en een $_COOKIE, zelfs al komen ze allemaal tegelijk binnen via één request. Met de methoden om iets uit $_POST te halen kun je geen fatsoenlijk cookie zetten.
Maar goed, eigenlijk ging mijn vraag daar dus niet echt over. Ik wil graag weten hoe ik het beste mijn mappenstructuur kan inregelen. Stel dat ik wel alles een eigen map geef, en dus voor een optie als deze zou kiezen:
Zitten daar dan nadelen aan? Wordt mijn systeem daar bijvoorbeeld trager door?
Als je het extreem snel wilt maken, laadt je PHP-opcode via één bestand per applicatie uit een RAM-cache. Maar hoe je de boel later compileert, staat los van hoe je het geheel eerst bouwt.
Sorry dat ik even een boel vraag, maar wat bedoel je hier meer? Voor de client data zou de namespace dan worden:
Vendor\Request\Data\Client
Wat vind je daar niet overzichtelijk aan?
Nogmaals, ik weet dus niet of mijn idee met mappen goed is, of beter kan. Dus vandaar dit topic. Ik hoop vooral op nieuwe ideeën te komen. Stel dat we bijv. ClientData.php wel in de request map zetten en we willen ook een bijbehorende exception, dan krijg je wel een hele lange bestandsnaam, terwijl ik juist dacht dat het idee van de namespaces (o.a.) was om niet van die lange bestandsnamen te krijgen:
Ik wil niet zeggen dat het niet kan, maar ik vraag me dus af of het een "beter" is dan het ander, en wanneer je nu wel of niet mappen moet gebruiken. Jouw eerdere opmerking over "PSR heeft een eigen \Psr namespace. Daar hoort dus ook een PSR-autoloader in." begrijp ik overigens niet. Het is gewoon een type autoloader die overweg kan met psr namespaces. Oh wacht, je bedoelt dat jij die autoloader niet in de "autoloader" map zou zetten, maar in een "psr" map?
Een PSR-autoloader is "van PSR" en hoort daarom in een eigen namespace:
Kijk, zo zie je meteen wat je aan het doen bent. Dit is niet zomaar een autoloader, maar een PSR-autoloader. En niet een voor PSR-0, maar een die we hebben geleend uit PSR-4.
Vergelijkbare logica vind je in bijvoorbeeld PSR-3:
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Psr/
Log/
AbstractLogger.php
InvalidArgumentException.php
LoggerAwareInterface.php
LoggerAwareTrait.php
LoggerInterface.php
LoggerTrait.php
NullLogger.php
LogLevel.php
Log/
AbstractLogger.php
InvalidArgumentException.php
LoggerAwareInterface.php
LoggerAwareTrait.php
LoggerInterface.php
LoggerTrait.php
NullLogger.php
LogLevel.php
Daarom zou ik bij jouw voorbeeld ook zoiets verwachten:
Wat is het verschil tussen de 0 versie en de 4 versie?
>> Een PSR-autoloader is "van PSR" en hoort daarom in een eigen namespace
Is dit jouw eigen mening.. vind jij dat het zo hoort, of zijn daar "regels" voor? Ik zou zelf een (psr)autoloader namelijk eerder zoeken in mijn autoloader map, dan in een aparte psr namespace. En als ik een psr logger zou hebben, dan zou ik die ook eerder zoeken in mijn logger map. Is dat dan fout? Ik snap jouw redenatie ook, maar "mijn" manier kan toch ook?
>> Daarom zou ik bij jouw voorbeeld ook zoiets verwachten:
Ah oké, duidelijk. Ik ben zelf niet zo'n heel erg voorstander van hoofdletters in map- en bestandsnamen. Ik zat net even te experimenteren, en het gebruik van underscores vind ik eigenlijk ook wel heel duidelijk:
Dat is een kip-en-ei-probleem: het zijn de richtlijnen uit PSR-0 en PSR-4, dus als je de PSR-standaarden wilt aanhouden, moet je de PSR-standaarden aanhouden :-)
>> Wat is het verschil tussen de 0 versie en de 4 versie?
PSR-4 is aan aanvulling op andere autoloading-specificaties, waaronder PSR-0. Daarnaast beschrijft PSR-4 wáár je bestanden moet opslaan (PSR-0 niet) en is het daarmee een antwoord op je vraag.
In mijn psr autoloader kan ik zeggen dat de namespace "Foo" moet worden gezocht in de map "bar", dus new Foo\FooBar verwijst dan naar /bar/foobar.php. Is dat dan psr-4?
>> Dat is een kip-en-ei-probleem: het zijn de richtlijnen uit PSR-0 en PSR-4, dus als je de PSR-standaarden wilt aanhouden, moet je de PSR-standaarden aanhouden :-)
Haha, ja ik hou de richtlijnen ook aan, maar ik bedoel... is het jouw eigen mening dat een psr autoloader thuishoort in een psr mapje? Je zou ook kunnen zeggen, het is een autoloader van het "type" psr en ik stop 'm gewoon in de autoloader map.
Als ik dus bijv. gebruik wil maken van een psr autoloader of logger, dan zou ik zeggen:
$autoloader = new Ozzie\Autoloader\PsrAutoloader;
$logger = new Ozzie\Logger\PsrLogger;
Eerlijk gezegd, smokkel ik wel eens. Ik heb bijvoorbeeld een PSR-0-autoloader (geen class maar een functie) in de library staan, dus op het niveau /lib/ bóven alle vendor-mappen /lib/Psr/ en /lib/Google/ enzovoort.
Verder smokkel ik ook wel eens door binnen een package op het niveau /Vendor/Package/ een config.php met een doodgewoon rijtje require-statements op te nemen. Niet netjes, maar soms is require 'config.php' wel praktisch als je toch uitsluitend iets uit één package nodig hebt.
Verder houd ik er niet zo van om rigide alles met alleen een beginhoofdletter te schrijven, bijvoorbeeld Ideal en Postnl in plaats van iDEAL en PostNL.
Ik denk dat ik alles met kleine letters ga schrijven.. tenzij het een externe library is, maar voor de rest, alles voortaan met kleine letters. Hoef ik er nooit meer over na te denken, en kan ik me ook nooit meer vergissen. Ideal, of was het nu iDEAL of IDEAL? Gewoon ideal :)
Wat betreft het psr gebeuren. Dat zijn toch gewoon richtlijnen hoe je iets kunt aanpakken? Het is toch geen library?
Weet je nog het antwoord op mijn vorige vraag?
"In mijn psr autoloader kan ik zeggen dat de namespace "Foo" moet worden gezocht in de map "bar", dus new Foo\FooBar verwijst dan naar /bar/foobar.php. Is dat dan psr-4?"
voorbeelden bij PSR-4 vind je een methode addNamespace() die een $prefix voor de namespace accepteert.
Ja, dat is PSR-4. In de Maar dat psr gebeuren is toch geen library? Het zijn toch enkel richtlijnen hoe je iets op een handige manier kunt aanpakken?
In de PSR-recommendations vind je echter wel bruikbare klassen. Officieel zijn dat vaak maar voorbeelden, maar ze zijn goed te gebruiken als library.
Even nog terugkomend op de request map...
Jij gaf dus dit voorbeeldje:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
Vendor/
Request/
AbstractRequest.php
ClientData.php
RequestInterface.php
ServerData.php
Request/
AbstractRequest.php
ClientData.php
RequestInterface.php
ServerData.php
Alle bestanden staan nu in de request map. Ik ben benieuwd of jij een voorbeeld kan geven wanneer je gebruik zou maken van een of meerdere submappen. Dus je hebt zeg maar eerst de vendor, en dan de hoofdmap. In die hoofdmap (in dit geval "request") staan nu alle bestanden, maar zijn er ook situaties waarin je een hoofdmap hebt, waar ook submappen in staan?