interface
Ik heb het idee dat sommige OOP'ers behoorlijk vaak interfaces gebruiken.
Stel je hebt meerdere classes die iets kunnen cachen dan lijkt het me zinvol om een interface toe te passen. Echter er zijn ook classes waarvan je bijv. op voorhand weet dat je er maar 1 van nodig hebt.
Stel ik heb bijv. een Config class waar ik configuratie instellingen in op kan slaan. Ik weet dat ik aan 1 (type) class voldoende heb. Ik zal nooit andere varianten van die class maken. Is de conclusie dan ook dat dergelijke classes geen interface nodig hebben? (je gaat ze namelijk nooit uitwisselen met een andere class)
Ben benieuwd naar de reacties.
Ozzie PHP op 06/12/2013 01:55:31:
Stel ik heb bijv. een Config class waar ik configuratie instellingen in op kan slaan. Ik weet dat ik aan 1 (type) class voldoende heb. Ik zal nooit andere varianten van die class maken. Is de conclusie dan ook dat dergelijke classes geen interface nodig hebben?
Zeg nooit "nooit". Je kunt er nu van overtuigd zijn dat je iets "nooit" wilt gaan doen, maar je kunt niet in de toekomst kijken. Misschien wil je straks wel een bundel maken die je framework op een server installeert met een aparte MailConfig en een PhpIniConfig.
Het hele eiereneten is dat je wel een API op papier zet. Het schrijven van de interface dwingt je na te denken over hoe je een klasse op de buitenwereld aansluit.
Ander voorbeeldje dan. Stel ik heb een class waarin ik paths op sla. Daar heb je er maar eentje van nodig. Moet je daar dan een interface voor maken? Wat ik eigenlijk bedoel te zeggen, is dat je dan voor iedere class een interface zou moeten maken. Iedere class zou dan gekoppeld zijn aan een interface. Lijkt me niet de bedoeling?? Of wel????
Je kunt wel een duidelijke trend zien. Een toenemend aantal PHP-ontwikkelaars gebruikt dezelfde interfaces, ook al kan de achterliggende implementatie verschillen. Dat geldt bijvoorbeeld voor de Logger Interface en de Cache Interface (twee PSR-projecten) en voor de abstractere SPL-interfaces. Met dergelijke standaarden gaan we een gemeenschappelijk taal gaan gebruiken: zó zou PHP-OOP eruit moeten of kunnen zien.
Dus ja, als je een class schrijft die sterk lijkt op iets dat al bestaat in een PSR- of SPL-interface, dan zou ik de lijn helemaal doortrekken en de complete interface implementeren.
Hmm, oké... maar dus niet nodig om ze altijd te gebruiken. Thanks :)
Een interface is natuurlijk niet altijd nodig. Alleen zodra je gaat typehinten op een object, of zodra je suggereert dat een object een bepaalde method moet hebben, ga je wel over op typehintent op een interface.
Oké, maar nu heb ik bijv. een class die paths opslaat. Daar heb ik er maar eentje van. Als ik die class meegeef aan een de constructor van een ander object, dan kan ik gewoon dit doen toch?
public function __construct(Paths $paths);
Dan typehint ik dus op de class en niet op de interface.
Typehinten op de interface is beter schaalbaar. Bijvoorbeeld read(FileCache $entry) is een minder flexibele keuze dan read(CacheInterface $entry).
Natuurlijk kan het ozzie, maar of het goed is... Je bent nu volledig gelimiteerd aan alleen dat Paths object, je hebt nu elke vorm van flexibiliteit uitgesloten voor de parameter die je aan de constructor meegeeft.
Ja, helemaal mee eens. Maar van een cacher weet je dat er meerdere varianten kunnen bestaan (ook al gebruik ik zelf nog maar 1 variant). Maar in dit geval zou ik dus ook voor Cache(r)Interface kiezen.
>> Je bent nu volledig gelimiteerd aan alleen dat Paths object, je hebt nu elke vorm van flexibiliteit uitgesloten voor de parameter die je aan de constructor meegeeft.
Precies, vandaar ook mijn vraag. Normaal gesproken zou je dat niet willen. Maar een Paths object, daarvan weet je dat je er maar 1 zal hebben. Dan heb ik het gevoel dat het overkill is als je dan een interface gaat implementeren. Snap je?
Wie zegt dat je maar 1 Paths object hebt? Een SerializedPaths object, een FrozenPaths object, etc.
Een path is in mijn systeem gewoon dit "/root/foo/path/" en heeft een ID. Je hebt toch geen andere soorten paden?
Je dat is een Path, en dan heb je dus een Paths object die meerdere Path objecten heeft. Die kan frozen (locked) zijn, of serialized, enz.
Ik zou me geen situatie kunnen bedenken waarom ik paden zou willen serializen of het object zou willen locken. Ik denk dus echt dat ik aan 1 Paths object voldoende heb. (In de meeste gevallen zal dat anders zijn en zul je wel een interface nodig hebben inderdaad.)
Wat ik me nog wel afvraag. Stel je hebt een Foo class... nee, wacht, laten we het gewoon een cacher class noemen, en je wil daar een interface voor maken. Stel de cacher class moet o.a. een delete() en een deleteAll() functie hebben, maar je weet dat er meerdere classes zijn die een delete() en deleteAll() functie hebben. Is het dan de bedoeling dat je een cacher interface maakt die dan de "deleteInterface" extendt? Of stop je alle functies die in de cacherInterface thuishoren gewoon in 1 class?
Gewijzigd op 07/12/2013 16:44:45 door Ozzie PHP
En dan heb je hier twee interfaces nodig: een voor een cache entry en een voor de cache pool.
Objecten in de cache zijn in jouw opzet gerelateerd aan websites, hoewel er véél méér cacherelaties mogelijk zijn.
Ik zeg niet dat die keuze verkeerd is. Ik constateer slechts dat die keuze er is.
Als je al zó ver gevorderd bent, met zo veel doorslaggevende keuzen, zou ik inderdaad gericht typehinten op een class die een sleutelrol in het framework speelt. Maar meer in het algemeen zou ik liever typehinten op een interface.
Nee, niet altijd. Kan dus ook aan een library zijn gekoppeld.
>> Als je al zó ver gevorderd bent, met zo veel doorslaggevende keuzen, zou ik inderdaad gericht typehinten op een class die een sleutelrol in het framework speelt. Maar meer in het algemeen zou ik liever typehinten op een interface.
Voor een cacher zou ik dus ook typehinten op een interface. Maar wat zou jij doen met (bijv.) een paths class (zoals 2 berichten hierboven beschreven)?
Laten we het dan eens sterk vereenvoudigen. In het ene pad moet je \ gebruiken en in het andere pad /. Je wilt daarom typehinten op een interface die paden snapt, niet op een specifieke class die paden implementeert.
"In het ene pad moet je \ gebruiken en in het andere pad /"
"Je wilt daarom typehinten op een interface die paden snapt"
Kun je dit eens nader toelichten? Er gaat bij mij nog geen lampje branden, maar wie weet met jouw uitleg?
Maar PHP heeft al native checks ingebouwd om het juiste slashteken te gebruiken dus ik snap niet echt waarom Ward hier een interface voor wilt implementeren.