Door
Milo S
op 17-01-2013 19:36
gewijzigd op 17-01-2013 19:37
4.887 views
Goede avond allemaal,
Ik ben al enige tijd bezig met het uitdenken van een CMS. Ik probeer zoveel mogelijk functionaliteiten in te voegen zodat ik gelijk op veel punten terecht kom en zoveel mogelijk leer. Dat is immers het voornaamste doel van dit project.
Nu heeft Wouter J mij in een vorig topic behoorlijk geholpen. Aan de hand hiervan ben ik toch nog verder gaan zoeken naar uitleg over interfaces en abstract classes. Ik vroeg mij nu af gebruik ik het nu niet overkill? Is mijn huidige opzet wel OOP? Zou ik hiermee verder kunnen als ik een simpele cms wil bouwen? Mis ik dingen?
Ik zou alle delete() methods weghalen uit de view classes. In mijn ervaring gebruik je dat nooit. Je maakt de pagina pas op op het moment dat je alle gegevens hebt, dus je weet op dat moment al wat er op de pagina moet komen en wat niet.
In je hele applicatie maar 1 interface? Elke klasse heeft recht op zijn interface.
Tevens heb je het nut van interfaces nog niet helemaal door. Een constructor is naar mijn mening totaal niet iets wat in een interface thuis hoort. Een interface voeg je toe om zeker te zijn dat een bepaalde klasse bepaalde methods heeft. Bijv:
<?php
class Dog
{
public function playSound()
{
echo 'Woefwaf';
}
}
class Person
{
private $animal;
public function setAnimal(Dog $animal)
{
$this->animal = $animal;
}
public function makeAnimalHappy()
{
$this->animal->playSound();
}
}
$dog = new Dog();
$person = new Person($dog);
$person->makeAnimalHappy(); // >> 'woefwaf'
?>
Nu typehinten we op de Dog klasse, dit zorgt ervoor dat de $animal property alleen een Dog klasse kan zijn. Hierdoor weten we zeker welke methods hij heeft.
Maar stel je voor dat onze persoon geen hond maar een kat heeft? Dan werkt deze methode dus niet. We moeten onze applicatie met het oog op flexibiliteit dus aanpassen. Hoe kunnen we er nou voor zorgen dat de method playSound() beschikbaar is in de Person klasse? Dat doen we door alle dieren een interface te laten implementeren die vastlegt dat deze klasse minimaal de method playSound heeft:
<?php
interface AnimalInterface
{
public function playSound();
}
class Dog implements AnimalInterface
{
public function playSound()
{
echo 'Woefwaf';
}
}
class Cat implements AnimalInterface
{
public funciton playSound()
{
echo 'Miau';
}
}
// we kunnen ook leuke dingen doen :)
abstract class SilentAnimal implements AnimalInterface
{
final public function playSound()
{
echo '';
}
}
// deze is nu stil, hij kan NOOIT geluid maken
class Ant extends SilentAnimal
{
}
class Person
{
// ...
public function setAnimal(AnimalInterface $animal)
{
$this->animal = $animal;
}
// ...
}
?>
[offtopic]Sorry, dit gaat weer alleen over interfaces. Ik kijk binnenkort nog wel eens naar het complete plaatje.[/offtopic]
Als ik het alleen even over de User_Interface, User klasse, abstracte Role klasse en de moderator / admin / customer klasse heb zou ik het heel anders moeten doen.
Omdat ik in alle gevallen een username en password wil weten van een gebruiker zal ik dit vast kunnen stellen in mijn interface.
Vervolgens kan ik hier mijn userclasse op implenteren. Als ik dan de rollen erbij haal, moderator / administrator / klant extend ik deze van elkaar of de abstracte Role klasse.
Is dit een beetje het princiepe wat jullie bedoelen? Of zou jij, Wouter, zeggen Roles moet ook een interface hebben om zo zijn punten vast te leggen? Door nu een abstract klasse ervan te maken heb ik toch altijd de benodigde functies maar kan ik toch (eventueel) oneindig uitbreiden.
@ Erwin,
Zo had ik hier nooit over nagedacht. Als je dat wel doet zie je inderdaad in dat de kans klein is dat jij met een klasse (bijvoorbeeld) je formulier veld weghaalt. Aan de andere kant stel nou dat het wel nodig is?
Ik ben nog steeds bezig met hetzelfde systeem, steeds probeer ik vraagstukken uit te sluiten en ben tot de conclusie gekomen dat ik het graag een stap voor stap wil doorlopen. Als de eerste basis maar goed is dan kan ik namelijk met een goede ondergrond verder borduren. Ik ga proberen minstens iedere avond een stap verder te komen, willen jullie mij hierbij helpen?
De eerste opzet voor de interfaces en klasse ziet er als volgt uit:
User_Interface
User [color=red]implements[/color] User_Interface
Authentication [color=red]implements[/color] User_Interface
Role_Interface
Role [color=red]implements[/color] Role_Interface
Moderator [color=red]extends[/color] Role
Administrator [color=red] extends [/color] Role
de nieuws klasse implenteer ik in de page klasse, omdat dit feitelijk hetzelfde is plus wat uitbreidingen. Voor de Page mapper geld dan dus ook dat hij ook data van de News klasse kan opslaan, of moet ik hier dan wel een extra mapper voor gebruiken?
Allereerst zou ik eens gaan nadenken welke naming conventions je gaat gebruiken. Ik raad je de PSR-0 standaarden aan. Deze zijn opgezet door de PHP Fig (Framework Integration Group). Deze groep wil bereiken dat iedereen ong. dezelfde standaarden gebruikt, waardoor je erg makkelijk iemand anders library kan gebruiken.
Authentication implements User_Interface
Lijkt me niet correct. UserInterface zou de overkoppelende factor voor een User moeten zijn. Authentication is het kijken wie de huidige bezoeker is. Authentication gaat uit eindelijk een User maken.
Allereerst zou ik geen specifieke mapper interfaces voor elke mapper maken. Ik zou 1 grote MapperInterface maken die sowieso de CRUD (create, read, update en delete) functies verplicht stelt.
Ten tweede moet de UserMapper ook totaal geen UserInterface implementeren. Overal waar je 'implements' hebt staan moet je kunnen veranderen in 'IS EEN'. Je kan niet zeggen UserMapper IS EEN User.
De rollen staan bij de gebruiker in de database. Hier hoef ik dan geen Role_Mapper voor aan te maken, want dat gaat dan via de User_Mapper, toch?
Exact
de nieuws klasse implenteer ik in de page klasse, omdat dit feitelijk hetzelfde is plus wat uitbreidingen. Voor de Page mapper geld dan dus ook dat hij ook data van de News klasse kan opslaan, of moet ik hier dan wel een extra mapper voor gebruiken?
Als de News klasse andere waardes bevat dan de page klasse heb je hiervoor een aparte mapper nodig.
Page_Mapper implements Page_Interface
Weer hetzelfde als voor UserMapper en Authentication.
Image_Interface
Image implements Image_Interface
Ik zou je interface globaler maken, bijv. MediaInterface. Hierdoor heb je mooi alle typen media, youtube filmpje, afbeelding, ect. op gevangen. Tevens kun je alsnog een ImageInterface behouden als je vindt dat de afbeelding andere methods heeft dan een youtube filmpje. Je krijgt dan Image implements MediaInterface, ImageInterface
Image_Mapper implements Image_Interface
Zie andere Mapper opmerkingen
Database implements Database_Interface
MySQL extends Database
Om duidelijk te maken zou ik MySQL suffixen met 'Database', MySQLDatabase.
UserInterface
User [color=red]extends[/color] UserInterface
Authentication
RoleInterface
Role [color=green]abstract[/color] [color=red]implements[/color] RoleInterface
Moderator [color=red]extends[/color] Role
Administrator [color=red]extends[/color] Role
Bij de media interface kunnen altijd andere media klasse worden toegevoegd, bijvoorbeeld een music klasse...
Ik vraag mij af of ik wel een dergelijke database klasse nodig heb, kan ik hier niet PDO voor gebruiken? Nadeel zou zijn dat ik heel de zooi aan moet passen wanneer ik iets anders wil gebruiken. Hoe zien jullie dat?
Kloppen mijn aanpassingen nu wel? Ik kan niet wachten om verder te borduren...
Oké, je hebt de relaties nog steeds niet door. Allereerst kan 'UserMapper implements User' natuurlijk nooit, User is een klasse en moet dus geëxtend worden. En vervolgens zeg je nu UserMapper IS EEN User, is dat waar?
Jou tutorial gelezen te hebben ben ik tot de volgende conclusie gekomen...
IS EEN = implements
HEEFT EEN = extens
Niet waar?
Wat betreft de page class ben ik dronken geweest denk ik.
Mijn gedachte gang was dat ik de methodes van page wilde vast stellen voor de news klasse, maar die extend al van page welke die functies al verplicht is door de pageInterface.
Snap je wat ik bedoel?
Ik voer de wijzigingen door en ben benieuwd of dit dan de sleutel is..
Inderdaad, dat is niet waar. :) Zowel extends als implements is een IS EEN relatie. Een HEEFT EEN relatie is niet iets wat je vastlegt bij het definiëren van een klasse. Een voorbeeld:
<?php
class Page
{
// ...
}
// NewsPost IS EEN Page
class NewsPost extends Page
{
private $author;
// NewsPost HEEFT EEN Author
public function setAuthor(User $author)
{
$this->author = $author;
}
}
?>
Allereerst kan 'UserMapper implements User' natuurlijk nooit, User is een klasse en moet dus geëxtend worden
Dan hier van uitgaande ga ik de volgende gedurfde uitspraak doen... Je gebruikt extends zodra je een class IS EEN class relatie hebt en je gebruikt implements zodra je een class IS EEN interface relatie hebt.