[OOP] geschikt class model
ik heb meerdere meningen nodig over een 'project opzet', met name classes en extenden.
Er zijn drie specifieke onderdelen die anders gebruikt worden:
API
Waar tegen aan gepraat wordt in XML, weet niemand iets van, wordt stil afgehandeld.
Heeft db connectie nodig.
Heeft aantal db functies nodig (update, add, etc)
Heeft een aantal 'secrets' nodig opgeslagen in hoofd class (of niet dus)
(Backend) PDU Communicatie
Zelfde soort xml als API, maar dit wordt aangestuurd door de 'gebruiker'.
Heeft ook db en zijn functies nodig.
Wordt aangeroepen vanuit backend GUI
Heeft een aantal 'secrets' nodig opgeslagen in hoofd class (of niet dus)
Backend GUI
Gebruik db en Smarty om info te printen.
Heeft de 'secrets' niet nodig, maar moet wel de backend pdu comm kunnen triggeren (als new Class, niet als extended class (als $this))
Zoals het nu is, is het sowieso echt fout!
Gebruik 4 classes voor de API, waarvan de class die aangeroepen wordt, de main class is met de secrets erin. Die class heeft dus alle functies die nodig zijn in de api.
Omdat in die class de secrets zitten, en ook de db connectie, wordt ie gebruikt (extended) voor het volgende onderdeel: backend pdu communicatie. De secrets zijn keihard nodig en moeten overerfd worden, maar de db conn niet perse (wel nodig) en ook _alle_ api functies zijn beschikbaar en niet nodig.
Omdat de backend GUI de db con ook nodig heeft (en een aantal makkelijk db-data-handlers) wordt de main class weer extended voor de main GUI class. Ook daarin zitten uiteindelijk (als ie aangeroepen wordt) dus superveel (en veel te veel) functies. Weer alle API functies die niet nodig zijn.
Als je ergens een dump maakt van het object (in de GUI of in de PDU comm), is het HUGE. Ongelooflijk veel spul erin (zowel methods als properties) die niet gebruikt worden.
Het enige dat steeds gebruikt wordt (en steeds dezelfde, door deze opzet) is de db connectie. Het is SQLite en niet mijn favoriet, dus wil niet voor elke query een nieuwe db connectie maken. Begrijpelijk toch? Dus de connectie moet ergens opgeslagen worden. SQLite geeft een object terug, dus geen globale database functies (zoals mysql_connect() heeft/geeft).
Een erg belangrijk puntje is de pdu tools (api) package. Het is niet van mij :) En het is bedoeld om niet aangepast te worden. Pas de 3e en 4e class worden veranderd om aan persoonlijke wensen te voldoen... De derde wordt nu alleen gebruikt voor de constructor, waar een stel Hooks worden aangemaakt, en de vierde is de main class vh project (met de db en funcs, etc).
Je denkt vast al dat het slimmer is om het zo en zo te doen. Laat dan snel iets weten :)
Het probleem, nogmaals, is niet de db connectie die overal vanuit 1 punt beschikbaar moet zijn. API en backend worden namelijk nooit tegelijk door dezelfde 'gebruiker' uitgevoerd. Dus die kan op meer dan 1 plaats geinstantieerd worden. Geen probleem! Maar de 'secrets' in de main class staan wel maar op 1 plaats en zijn op 2 plaatsen nodig.
Ik _KAN_ natuurlijk ALLES af laten leiden van die class met secrets en db connectie. Worden nl. overal gebruikt.
Maar dan moet het PDU Tools package ge-extend worden, en daar issie niet zo goed in (en ik niet zo comfortabel).
Kan het op een nog andere manier? Een logische manier, zonder dat er 7 classes aan elkaar hangen met allemaal weer een extra stukje overbodigheid voor de volgende.
Steeds 2 of 3 die achter elkaar hangen, horen achter elkaar (PDUCommPrep -> PDUComm, en PDUToolsGeneric -> PDUToolsReceiver -> PDUToolsHandler, etc) maar _alles_ wordt aan elkaar geslingerd nu.
My doing ja :) maar ben er niet blij mee...
Tips?
Sorry voor het lange verhaal :D bedankt voor het lezen
Verder raak ik de draad in het verhaal nog een beetje kwijt, ik denk dat ik het nog een paar keer over moet lezen.
Naar mijn idee moet je eens wat lezen over programmeer-patronen, zoek bijvoorbeeld eens naar het befaamde boek "Gang Of Four" of een wat nieuwere: "Patterns Of Enterprise Application Architecture" van Martin Fowler.
Quote:
't Is inderdaad alles behalve duidelijk
nou nou nou sorry hoor :D
singleton gaat niet op in dit geval, zeker niet voor db connectie. Wil nl. niet elke keer een nieuwe db con maken en heb wel heel vaak queries nodig. Maar ook heel vaak niet in dezelfde functie. Dus kan een dbCon global maken, of opslaan in de class die gebruikt wordt. Maar singleton geeft nieuwe instance, dus met nieuwe data, dus met nieuwe connectie << naah
ken genoeg programmeermethoden, vroeg me af hoe jullie het zouden doen. Als je het niet begrijpt, zal ik proberen verder uit te leggen wat de bedoeling is. Ik kom er sowieso wel uit ( en zijn zoveel manieren, en het werkt zoals het nu is :) ), maar ben benieuwd wat als beste wordt bwschouwd door de phphulpers
dank voor reacties iig.
ken "gang of four" :) maar niet die 'wat nieuwere', dus zal es zoeken.
Als ik je verhaal lees zou ik ook zeggen wat jelmer zegt.
Vooral niet zomaar gaan extenden, maar de verschillende 'objecten' gescheiden houden.
Ik denk dat het handiger als je even een boompje maakt van de klassen en hun kinderen (hun extends) en welken nu welke nodig hebben. Gewoon simpelweg met wat lijntjes.
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Quote:
Ik denk dat het handiger als je even een boompje maakt van de klassen en hun kinderen (hun extends) en welken nu welke nodig hebben. Gewoon simpelweg met wat lijntjes.
Zie dat plaatje dat ik als eerste replie heb gepost :) Duidelijk toch? Dat is zoals het nu is.
Quote:
Singleton is toch juist bedoeld om juist altijd met de zelfde instantie te werken en niet steeds een nieuwe te krijgen?
Een static functie kan niet iets uit een class halen (niets uit $this). Een static functie is opzichzelfstaand. Toch? Dus hij maakt een instance van bijv een database class (depends on dbType dat je meegeeft), of een file handler (depends on het bestandstype dat je meegeeft), etc. Ik zou niet weten hoe een Singleton oplossing mij een instance kan geven van steeds hetzlefde object. Wel hetzelfde object natuurlijk, maar niet dezende instance van het object. Voor db class (vooral SQLite, zo heb ik begrepen) is dit niet de oplossing, omdat er steeds een live handler wordt gemaakt naar een bestand op het filesystem. Wat ik moet hebben, is een global DB instance, maar dan niet global, want ik houd niet van global :D Zoals je altijd mysql_query() kan aanroepen (de connectie is opgeslagen in de php 'buffer') als je een keer connectie hebt gemaakt, zonder de connectie mee te geven aan de functie.
Als je weet hoe het moet zou ik echt heel graag een voorbeeldje o.i.d. zien. Ik ben geen fan van Singleton, omdat ik alles zo min mogelijk aanroep en liever even opsla in de php buffer. Bijvoorbeeld in een class, in $this. Met een static functie kan ik niets uit $this halen :(
Ik maak gebruik van een DependsOn functie. Zowel met by-reference calling, als return value en ook met $this setten. Zo houd ik bijvoorbeeld de Smarty instance live en paraat. Misschien kan het ook met SQLite, maar alleen binnen het object.
DependsOn geeft een parameter mee (een constante van een class) die in een switch wordt bekeken en aan de hand daarvan wordt een waarde teruggegeven, opgeslagen in $this, of opgeslagen in de by-reference var.
Een voorbeeldje
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
class ABC
{
function mf_DependsOn( $ulDependancy )
{
switch ( $ulDependancy )
{
case ABC::Smarty:
if ( isset($this->m_objSmarty) )
{
return $this->m_objSmarty;
}
else
{
$this->m_objSmarty = new CVM_SmartyBackofficeUI;
return $this->m_objSmarty;
}
break;
case ABC::SQLite:
// zelfde verhaaltje hier, maar dan voor CVM_SQLiteDatabase("memory")
break;
}
}
}
?>
class ABC
{
function mf_DependsOn( $ulDependancy )
{
switch ( $ulDependancy )
{
case ABC::Smarty:
if ( isset($this->m_objSmarty) )
{
return $this->m_objSmarty;
}
else
{
$this->m_objSmarty = new CVM_SmartyBackofficeUI;
return $this->m_objSmarty;
}
break;
case ABC::SQLite:
// zelfde verhaaltje hier, maar dan voor CVM_SQLiteDatabase("memory")
break;
}
}
}
?>
Werkt redelijk. Zal echter in elk object instance een nieuwe connectie maken, omdat er nog geen is opgeslagen in $this.
In mijn huidige set-up heb ik maar op 1 locatie in de hele app een db connectie instance. In de constructor van CPServer.
Dank voor replies :)
Misschien snap ik Singleton niet, kan natuurlijk best ;)
Iemand makkelijk duidelijk voorbeeldje of website? Dank
Hier staat een voorbeeld van hoe ik een tijdje terug een sigleton database class gemaakt heb met zowel MySQL als ODBC.
Aangezien het al even geleden is dat ik het heb kunnen bijwerken omdat ik voor school druk ben met Java, is het niet verstandig om code over te nemen maar misschien kan je iets met het sigleton iedee.
Een beetje uitleg: Er wordt een static variabele gebruikt om de instanties op te slaan, bestaat er een instantie dan wordt die uit de static variabele gehaald, anders wordt er een nieuwe instantie gemaakt en in de static variabele opgeslagen.
Aangezien het al even geleden is dat ik het heb kunnen bijwerken omdat ik voor school druk ben met Java, is het niet verstandig om code over te nemen maar misschien kan je iets met het sigleton iedee.
Een beetje uitleg: Er wordt een static variabele gebruikt om de instanties op te slaan, bestaat er een instantie dan wordt die uit de static variabele gehaald, anders wordt er een nieuwe instantie gemaakt en in de static variabele opgeslagen.
-- edit
Ik ga naar de voorbeeldjes kijken. Dank!
-- edit
Het script van Boaz zluit het meest aan bij dat van mij, wel ongeveer wat ik vaker doe. Maar dan met DependsOn ipv getInstance :)
Zo ga ik het doen. Zet ik die functie onderaan in een class onderaan en laat elke class afleiden van die class. Kortere rijen, overzichtelijker en een hoop minder rotzooi die wordt onthouden.
dank voor jullie hulp!
Gewijzigd op 01/01/1970 01:00:00 door Majid Ahddin