PHP osztály - OOP v. csak annak látszik?
Abban szeretnék segítséget kérni, hogy a mellékelt osztály megfelel-e az objektum orientált programozás elveinek, vagy csak annyit csináltam, hogy egy függvény gyűjteményt beraktam egy class kulcsszóval kezdődő blokkba?
Bónusz kérdés: elkövettem-e benne valami komolyabb baklövést?
A User osztály egyébként csak arra szolgálna, hogy a kiválasztott azonosítóhoz tartozó adatokat betöltse + egy metódus segítségével tudja ellenőrizni a user jelszavát.
(későbbiekben ezen keresztül intézném az authentikációt, esetleg az authorizációt is)
ui: egyáltalán szabad itt ilyet kérdezni vagy e célra keressek más fórumot?
■ Bónusz kérdés: elkövettem-e benne valami komolyabb baklövést?
A User osztály egyébként csak arra szolgálna, hogy a kiválasztott azonosítóhoz tartozó adatokat betöltse + egy metódus segítségével tudja ellenőrizni a user jelszavát.
(későbbiekben ezen keresztül intézném az authentikációt, esetleg az authorizációt is)
ui: egyáltalán szabad itt ilyet kérdezni vagy e célra keressek más fórumot?
<?php
class User {
const ID = 'id';
const NAME = 'name';
const PASSW = 'passw';
const NICK = 'nick';
protected static $db; // Jó az nekem, hogy ez az adatbázis objektum statikus? (egyelőre úgy tűnik, igen)
protected $prepSQL;
protected $userdata=array(); // A user adatait tartalmazó tömb. Indexelés lehetőleg a fenti osztály konstansokkal!
function show($s){ echo "<p>".$s."</p>"; } // Debug célra, törölhető
// A user adatok lekéréséhez használt SELECT összeállítása.
// Paraméterbe a feltételt kell írni. A visszaadott objektum felhasználása(execute) előtt
// szükséges egy bindValue vagy bindParam!
// a bindColumn hívások a userdata tömbbe irányítják a SELECT kimenetének oszlopait.
private function setupUsertabSQL($cond){
$sql=self::$db->prepare("SELECT uid, mailaddr, nick, pwdhash FROM usertab WHERE ".$cond);
$sql->bindColumn('uid',$this->userdata[self::ID],PDO::PARAM_INT);
$sql->bindColumn('mailaddr',$this->userdata[self::NAME]);
$sql->bindColumn('nick',$this->userdata[self::NICK]);
$sql->bindColumn('pwdhash',$this->userdata[self::PASSW]);
return $sql;
}
function __construct($p){ // Konstruktor. A paramétere lehet string, ekkor usernév/e-mail alapján szedi elő a usert az adatbázisból,
// vagy lehet integer, ekkor az UID alapján keres.
try {
if(!isset(self::$db)){
try {
self::$db=new Database(); // Új adatbázis kapcsolat, ha még nincs
// Ha valami gáz lenne...
} catch(PDOException $e) {
echo "<p><b>Adatbázis hiba a kapcsolódáskor!</b></p>";
echo $e;
throw $e;
}
}
// Mivel a metódus overload nem működik, kénytelen voltam így szétválasztani a két esetet (string v. int a paraméter)
// Ezt is egyszerűsíteni kellene, mert ez a majdnem teljes copy/paste kicsit gusztustalan.
if(is_string($p)){
$this->show("User by name");
$this->userdata[self::NAME]=$p;
$this->prepSQL=$this->setupUsertabSQL("mailaddr=:mailaddr"); // A preparált SELECT-hez hozzárendelem a megfelelő változót,
// paraméterként és végrehajtom
$this->prepSQL->bindParam(':mailaddr',$this->userdata[self::NAME]);
// Ha a paraméter integer, az eljárás nagyjából mint fent, csak usernév helyett UID-re keresek.
} elseif(is_integer($p)) {
$this->show("User by id");
$this->userdata[self::ID]=$p;
$this->prepSQL=$this->setupUsertabSQL("uid=:uid");
$this->prepSQL->bindParam(':uid',$this->userdata[self::ID]);
// Ha az osztály példányosításakor hibás paramétert kapott a konstruktor, akkor gáz van...
} else {
$this->userdata=array();
$this->show("Hiba történt!");
throw new Exception('Hibás paraméterezés');
}
$res=$this->prepSQL->execute();
$res=$this->prepSQL->fetch(PDO::FETCH_BOUND); // Elméletileg egyetlen sort adhat vissza a lekérdezés, talán nem ártana egy
// ellenőrzés és hibajelzés, ha többet. (a rowCount működése a PHP doksi szerint
// bizonytalan selectek esetében - viszont az adatbázisban egyedi kulcsként szerepelnek
// a lekérdezhető oszlopok, így lehet, hogy az ellenőrzés már túlzott paranoia)
// A fetch-nek átadott PDO::FETCH_BOUND jelzi, hogy a bindColumn segítségével
// párosított változókba kell tenni az eredményt.
if(!$res){
$this->show("sikertelen");
$this->userdata=array(); // Ha sikertelen, akkor biztos-ami-biztos törlöm a userdata tartalmát, bár nem biztos,
// hogy van jelentősége - azt nem tudom, hogy egy Exception kiváltásán kívül hogyan
// tudnám megakadályozni az objektum létrehozását a konstruktorból.
} else {
$this->show("sikeres"); // Ha sikeres a lekérdezés, akkor a userdata tömb már ki van töltve, nincs teendő
}
} catch(PDOException $e){
echo "<br>adatbázis hiba<br>";
throw $e;
}
}
function getName(){ return $this->userdata[self::NAME]; }
function getId(){ return $this->userdata[self::ID]; }
function getData(){ return $this->userdata; } // A user valamennyi adatának visszaadása, egyetlen tömbként (referenciák még mindig!!!)
// Jelszó ellenőrzése. Mivel a "salt" értéke is benne van a hash-ben, egyszerű az ellenőrzés
function checkPass($pw){
return crypt($pw,$this->userdata[self::PASSW])==$this->userdata[self::PASSW];
}
}
// Ideiglenesen itt van az adatbázist leíró osztály, ezt majd ki kell emelni, mert az adatbázis nem csak a userek adatait tartalmazhatja!
class Database extends PDO {
function __construct(){
return parent::__construct('mysql:host=localhost;dbname=adatbazis','minimaljoguuser','egyjelszo'/* , array( PDO::ATTR_PERSISTENT => true )*/ );
}
}
?>
Az adatbázis kapcsolatnak nem
A konstruktorba semmiképp nem jó, ha ilyesmiket teszel, ott néhány metódus meghívása kellene, hogy legyen, nem pedig normál kód. Ha van egy if-elseif-...-else szerkezeted, akkor minden benne lévő blokkot kiemelhetsz külön metódusba. Ha valami általános dologról van szó, akkor az összes ilyen metódus kimehet egy külön osztályba, vagy egy abstract class-be, amiből örököltetsz.
A show helyett unit testeket kéne írnod az osztályhoz.
A private helyett én protectedet használnék mindenhol a helyedben, ha meg nem akarsz továbbörökíteni egy osztályt, akkor meg tedd elé a final kulcsszót.
Köszi
Egy dologgal vitatkoznék: a final protected látható a leszármazottak felől, ezt nem biztos, hogy akarom (pontosabban: egyáltalán nem szeretném, ez annyira "intim" rész... akar lenni... :) )
Maga az osztály egyelőre csak kezdemény (mást ne mondjak, normál körülmények közt ennél több paramétere van egy usernek), azért dobtam fel a kérdést, mert ha eleve rossz úton járok, akkor nem szeretnék ennél több munkát belefektetni.
Részemről folyt.köv. este, addig még rágódok egy sort azon amit írtál.
Final osztálynak nincsen
Nem leszármazottról beszéltem
(bocs, kicsit hosszú lett)
final class Test{} class
Ezzel viszont letiltom a Test
Ez attól is függ, hogy mit
Egy apróságon elakadtam:
Egy-egy függvény hívása
Egyébként igen, az olvashatóság miatt kell külön tenni. Van egy optimális függvényhossz, amit azért érdemes tartani. Annál a legolvashatóbb a kódod. Ha annál hosszabb függvények vannak, akkor nem látod ránézésre, hogy mit csinálnak, ha annál rövidebbek, akkor meg képtelen vagy normális nevet adni nekik.
A másik ami miatt én külön szoktam tenni, hogyha esetleg úgy döntök, hogy mégsem konstruktorból hívom meg az adott dolgot, akkor már ne kelljen átírni. A private helyett is azért szoktam protectedet használni, hogyha mégis örököltetni akarok, akkor ne kelljen mindenhol átírnom...
Osztályoknál egyébként metódusok vannak és nem függvények/szubrutinok... :-)
Osztályoknál egyébként
Tudom, de amikor én programozni tanultam, akkor volt COBOL,PL/I, FORTRAN, meg Assembly. (meg néhány, ezekhez hasonló nyelv, amikkel nem foglalkoztam)
Mivel az akkor tanultakra céloztam, nem emlegethettem metódust.
És általában azért "drága" (legalábbis az akkori programnyelvek esetében), mert a függvényhívás kapásból azzal indít, hogy egy ugrás az adott kódrészletre, a stack macerálása (visszatérési cím, dinamikus változóknak tárhely foglalás, ilyesmi...) plusz a függvény/szubrutin végén, visszatérés előtt némi nagytakarítás. Ez mind megspórolható volt, ha a kódot közvetlenül oda írom, ahol használom.
Én ezt elhiszem, de azóta
Persze java esetében igazából mindegy, mert ott úgyis befordítja a kódot a java engine nyelvére. A php esetében nyilván valamennyit lassítani fog, de mondjuk egy adatbázis kérés több időt fog elvenni, mint a legtöbb függvényed együtt...
Szerintem ez megfelel az OOP
Elképzeléseim szerint lesz
Legnagyobb bajom ezzel az egész OOP-vel, hogy fogalmam sincs, mikor, mit érdemes önálló osztályba tenni.
Tankjú!
főnevek
persze ezt szó szerint venni botorság lenne, de el lehet indulni rajta.
Ha úgy gondolod, hogy egy
Zavart érzek az erőben :-)
OO környezetben mi a szokásos eljárás arra az esetre, ha pl. egy usert objektumként kezelek, ami kizárólag a már létező usereket hivatott modellezni(*), de a példányosításkor kiderül, hogy nem szerepel az adatbázisban?
- létrehozom az objektumot üres adatlappal?
- mint fent, de dobok egy Exceptiont?
- a new-val történő példányosítás helyett... nem jut eszembe a pontos kifejezés, valami "factory" rémlik: statikus metódusból gyártom le a példányt és NULL-t adok vissza objektum helyett, ha nem tudom létrehozni?
- esetleg van lehetőség rá, hogy a new adjon vissza NULL-t? Ezt hogy lehet kivitelezni? Gúgli nem segített (nem is tudom igazán, hogy mit kellett volna keresnem)
Ha jól sejtem, mindegyik variációra van példa (kivéve tán az utolsót, mert az mintha nem létezne PHP-ben) és inkább a szándékaim alapján kellene kiválasztani a megfelelő módszert, nem lehet egyik v. másik módra ráfogni, hogy "ez az üdvözítő megoldás".
* - abban sem vagyok biztos, hogy egy ilyen objektum, mint pl. egy felhasználó esetében érdemes foglalkozni a létrehozáskor azzal, hogy szerepel-e az adatbázisban v. sem. Utóbbi esetben két utolsó variáció eleve kiesik.
- mint fent, de dobok egy
Én erre szavazok, vagy példányosítás előtt ellenőrzöd az adatbázist...
Ha szigorúan veszem azt, amit
Végülis az Exception is szimpátikus. :)
Factory
Igen, ez tiszta, de fentebb,
vagy példányosítás előtt
Nem tűnik úgy, mintha elvetettem volna... :-)
Mindkettő jó megoldás, ízlés kérdése szerintem...
Mondjuk ha csinálsz egy User példányt, aminél beállítod az email címet meg a jelszót, aztán azzal próbálsz beloginolni, akkor az sem fog feltétlen létezni az adatbázisban, a regisztrálásnál szintén ez a helyzet....
Példányosítás előtt - ebből
---------
De még1x: ez a fenti csak egy tesztelésre szánt kezdemény, inkább csak próbálgatom, mit sikerült megtanulni az OOP dolgaiból, felhasználni közvetlenül nem akarom.
Regisztráció eleve elég zűrös ügylet, ha nem akarok spam botokat regisztrálni, ha valamelyest biztonságos oldalt akarok, akkor a login is elég macerás... szóval ez a class még elég kevés.
Majd írok cikket a
Átfutva a kommentek nagy részét
A fenti osztályodról nem mondható el, hogy megfelel-e az OO elveknek, mert az OO elvekben az objektumok közötti sokféle reláción van a legnagyobb hangsúly. Azaz, hogy egy osztály leszármazottja-e egy másiknak vagy sem, egy objektum hogyan kapcsolódik egy másikhoz, egy objektumot létrehoz-e egy másik objektum, stb. és ezek miértjei. Főként a miértjei. Az objektum orientáltság egy fejlesztési szemléletmód, amiben a hansúly az elvonatkoztatáson van:
- Objektumként értelmezek mindent olyan elemet (a specifikációban, vagy a létező világban) ami feladatok jól meghatározott, logikailag összefüggő csoportját látja el és kezeli az ehhez szükséges adatokat. Példálul a felhasználó, "amiről" tudjuk, hogy látogatja az oldalt, kattintgat, űrlapokat tölt ki, stb. Vagy egy labdát, ami tud pattogni és gurulni.
- Megállapítom, hogy melyik objektum milyen tulajdonságokkal bír és milyen műveleteket végezhet. Tudom, hogy a felhasználó látogatja az oldalt és vannak (lehetnek) neki profiladatai. Kell tehát rögzíteni az ő profiladatait, az utolsó látogatása idejét (ha ez érdekes adat), tudom, hogy bejelentkezhet és kijelentkezhet (metódusok), hogy adatokat küldhet például űrlapokon keresztül, amelyeket fel kell dolgozni. A labdáról elmondható, hogy van felszíne, átmérője és tömege (tulajdonságok), el lehet rúgni vagy gurítani, pattanhat (metódusok).
- Megpróbálok elvonatkoztatni, prototipizálni. A felhasználóról elmondható, hogy vannak adatai, amelyek állíthatók, a felhasználó maga pedig törölhető is ezért (vagy nem, ez specifikáció függő persze) és elmondható, hogy bizonyos egyéb műveleteket is lehet vele végezni. Ez egy szülő osztály leírása már. A labdáról elmondható, hogy elhelyezkedik valahol a térben.
- Így kialakítok egy alapvető osztályt, amely kapcsolatban áll egy adattárolóval (jellemzően egy adatbázis kiszolgálóval) és pontosan egy rekordot tartalmaz adatként, mint tulajdonság, valamint néhány metódust, amivel az adatokon végezzük a műveleteket. A labdás példáról most leszállok.
- A szülőosztályban felmerül az adatbázis, mint jellemző. Ez felveti annak a szükségességét, hogy rendelkezzünk egy adatbázis osztállyal, amely kapcsolatot biztosít a rendszerünk és az adatbázis kiszolgáló között, lehetővé téve az adatok manipulálását és lekérését.
- Az egyszem adatunk egy rekord szerkezet. Ez felveti a szükségességét annak, hogy legyen egy osztályunk, ami ilyen adatszerkezeteket kezel.
- Máris kiderült, hogy a felhasználó OO szemléletű megvalósítása magával vonta +3 osztály szükségességét (a szülőosztályét, az adatbázis elérőét és a rekordot kezelőét).
Eztán azt mondhatjuk, hogy a felhasználó osztályunknak van egy elvont szülője, amely rendelkezik az alábbiakkal:
- Egy tulajdonság, amely az adatbázis kiszolgáló objektumra mutat
- Egy tulajdonság, amely tárolja és kezeli az adatbázisból kivett pontosan egy darab rekordot
- Egy metódus, amellyel beemeljük a megfelelő adatsort a rekord tulajdonságunkba
- Egy konstruktor, amelynek meghatározható, hogy melyik rekordot kell majd beemelni
Ekkor világossá válik, hogy rekord kezelő osztály (amelyet a rekord kezelésére kell majd példányosítanunk) az alábbiakkal kell hogy rendelkezzen:
- Egy asszociatív tömb (gyűjtemény, hash, stb.), amelyben a beemelt adatokat tároljuk.
- Egy jelző tulajdonság, ami "igaz", ha az adatok módosultak.
- Egy tulajdonság, amely az adatbázis kiszolgáló objektumra mutat.
- Egy metódus, amellyel az adatbeemelés megtörténik a megfelelő azonosító alapján.
- Egy metódus, amellyel az asszociatív tömb (vagy annak konkrét eleme - megoldás függő) lekérdezhető.
- Egy metódus, amellyel a tömb elemei módosíthatóak. Be kell állítja a jelző tulajdonságot.
- Egy metódus, amellyel a rekord törölhető az adatbázisból.
- Egy metódus, amellyel a rekord mentésre kerül az adatbázisban, ha a jelző tulajdonság szerint az adatok módosultak.
- Egy konstruktor, amely a megkapja és tárolja az adatbázis elérő objektum referenciáját, ill. egy kapott azonosítóval meghívja az adatbetöltő metódust.
- Egy destruktor, amely az objektum megszűntetése előtt a biztonság kedvéért meghívja a rekord tároló eljárást. Itt még szorgalmi feladat megoldani, hogy hogyan kezelje az objektum azt, ha a rekordot törölték (gyaníthatóan ehhez is jelző kell, amit az adatmentő ellenőrizhet, kerülendő azt, hogy nem létező rekordot akarjunk menteni).
Az adatbázis elérő osztályra és objektumra nem térek ki, PHP-nál maradva legyen ez a PDO osztály (lásd php.net/pdo).
Ez után visszatérünk a felhasználóhoz és megállapítjuk a többlet képességeit a szülőosztályhoz képest:
- Adott egy jellemzője, amely az utolsó bejelentkezése idejét tárolja
- Képes bejelentkezni az azonosítója és jelszava segítségével
- Képes kijelentkezni
- Megállapítható róla, hogy be van-e jelentkezve vagy sem (elérhető-e hozzá betöltött rekord, vagy sem)
- Képes megállapítani és betölteni az utolsó bejelentkezése időpontját
- Képes egyéb adatokat küldeni (amelyeket szűrni kell bizonyos szempontok szerint - tegyük hozzá, a legtöbb keretrendszer ezt a felhasználói ténykedést nem a felhasználó osztályába sorolja, hanem külön segédosztályokat hoz létre a feladatra)
- Kell majd egy konstruktor, amely elvégzi a szükséges inicializáló műveleteket (ellenőrzi a bejelentkezettséget pl a munkafolyamati változóban tárolt érték alapján és betölti az utolsó bejelentkezés idejét a megfelelő tulajdonságba, majd meghívja a szülőosztály konstruktorát [amely betölti a felhasználó rekordját] - sarkítva).
Eztán elmondhatjuk, hogy a felhasználót helyesen elvonatkoztatva és a problémát alaposan körüljárva kaptunk 3 újrahasznosítható osztályt. És ezen a ponton révbe értünk, ez az OO szemlélet egyik legfontosabb hasznossága: kiemelhetünk osztályokat és újrahasznosíthatjuk anélkül, hogy az adott osztályoknak tudniuk kellene azt, hogy ki/mi használja őket. A rekord szempontjából lényegtelen, hogy felhasználó rekordjáról beszélünk, vagy egy esemény (pl naptári bejegyzés) rekordjáról. Az adatbázis elérő szempontjából lényegtelen, hogy rekord kezelésére vagy csak egy egyszerű időbélyeg kiolvasására használjuk. Stb.
Ha eszerint nézem a fenti kódot, akkor valóban nem felel meg az OO szemléletnek (bár az adatbázis leválasztása egy jópont!).
Még valami: szóba került jóhamar a Factory minta. Szerintem mielőtt beleveszne az ember ezekbe (az egyébként igen hasznos) módszertanokba, érdemes megpróbálni ezek ismerete nélkül megoldani feladatokat. Mert az OO tervezési minták nagyon elvontak, és aki érteni is akarja őket, nem csak megpróbálni alkalmazni ("hátha ez lesz a jó" alapon), az először sajátítsa el helyesen az OO szemléletű elvonatkoztatás módszereit.
Feszültség oldásnak: a világon valójában minden leírható OO szemlélettel - kivéve a Nőt ;-)
(inkább úgy mondanám, hogy eddig egyik állításomat sem cáfolta a gyakorlat :D, jellemzően determinisztikus dolgok írhatóak le OO megközelítésből, a Nő archetipikusan nem mindig ilyen :-) - bocs lányok, nem cinkelek, sőt, ez olyan dolog, amiért nagyon tudlak titeket tisztelni :-))
Most azon gondolkodom, hogy
----
Egyelőre csak annyit: nem szándékom "hátha ez is jó lesz" alapon dolgozni, de korábban is írtam, hogy még csak ismerkedem az egész témával.
Az OOP v. csak annak látszik kérdés meg mindössze onnan jött, hogy néhány fórumon találkoztam olyan reakcióval, hogy a kérdező nem objektum orientált programot ír, csak class-okba csomagolja a függvényeit. :)
Köszi szépen, hogy ennyi időt fordítottál rá, megpróbálom alaposabban feldolgozni amit írtál, aztán folyt.köv. (ha le tudom úgy írni, hogy ne tűnjön kötekedésnek :) )
----
Végeredményben ott tartok (tképp ezen "rugózok" közel fél éve), hogy nem igazán tudom az (egyébként sem túl kidolgozott) elképzeléseimet objektumokra/osztályokra lebontani. Többek közt azért sem, mert egyik végletből: minél több dolgot összezsúfolni egyetlen objektumban, a másikba esek: olyan szinten kezelni objektumként mindent, hogy pl. egy usernév is önálló objektum legyen. Persze ez csak egy kiragadott példa, rengeteg ilyen "apróság" van, amin nem tudok átlépni.
Köszönöm a válaszodat. Ha
Persze, veled nem is ez a helyzet, ez már a topik elnevezéséből világos volt, de szerettem volna átadni egy kevés tapasztalatot azért, hogy világosabb legyen, mitől lesz OO szemléletű egy kód (vagy bármi).
A mostanában divatos tervezési mintákkal való dobálózás ellen is ugyanilyen elánnal küzdök, és ennek az oka pont az, hogy tapasztalataim szerint 5 OO fejlesztőből csak 2-nek van fogalma arról, mi az OO valójában. A szemléletmód ismerete nélkül alkalmazott patternek pedig életveszélyessé válnak, mint a napos csibe kezében a gépfegyver. Általában az ilyen pattern-bozótharcosok munkája után következnek a végeláthatatlan refaktorálások, amik egyébként is gyorsan vezetnek egy egész rendszer újraprogramozásának igényéhez. Utóbbival nincs feltétlenül baj, de kerülni kell azt, hogy egy terméket a megrendelő (ügyfél vagy munkáltató) kétszer fizessen ki pusztán azért, mert valakik valamikor nem értettek meg egy fejlesztési szemléletmódot, amiből aztán olyan rendszert építettek, mint egyes angol házak, ahol a második szint folyosójáról nyíló ajtó a (földszinti) kertre nyílik, nem egy szobára.
Ezért igyekeztem úgy válaszolni, hogy neked is válaszoljak, és azoknak is, akik csak olvassák a fórumot és nem értik igazán, mitől OO valami.
Az egyébként egy elméleti félreértésből ered, ha valaki annyira OO akar lenni, hogy egy usernévre is osztályt akar írni. Az OO szemléletmód eleve abból indul ki, hogy minden dolog leírható objektumként, az objektum maga pedig egy osztályból (vagy prototípusból) kerül példányosításra - ergo minden leírható osztályként vagy prototípusként. Azokon a nyelveken is, amelyek nem támogatnak semmilyen OO szintaktikai elemet. Mert ez szemléletmód, nem pedig szintaktika. Szóval a fenti elvet sokan úgy fordítják le, hogy akkor mindennek, még a primitív típusoknak is osztályban a helyük. Ez pedig baromság. Az elv helyes értelmezése az, hogy a primitív típust primitív osztály valósítja meg, amely rendelkezik egy értéktároló tulajdonsággal és számos értékadó, értéklekérő metódussal, valamint általában egy típus lekérésre alkalmas metódussal. Ezeket a nyelv elfedi és a nyelv implementációjától függően vagy lehetőség van felülbírálni (operator overloading pl.) vagy nem. Egy primitív típus tehát felfogható osztálynak akkor is, ha egyébként nem ebben a szemléletben készült és valósult meg nyelvi szinten. Hacsak nem szükséges kiterjeszteni az adott primitív típust, akkor nincs tehát szükség osztály keretet írni rá. Persze, sok esetben hasznos lenne, de törekedni kell a nyelv szemléletmódjának koherens alkalmazására is, mivel a legtöbb esetben ez jobb futási teljesítményhez vezet, de legalábbis többnyire kevesebb hibát tesz lehetővé.
Kis türelmet kérek, még nem
Szerk.: usernév, mint objektum. Persze, ahogy én írtam, az hülyeség - csak próbáltam érzékeltetni, mennyire bele tudok kavarodni az objektum orientált programozásról olvasottakba. :)
Annyi realitása azért van neki, hogy pl. Java-ban, Ruby-ban, meg tán Python-ban is, a stringek eleve objektumként működnek.
Más kérdés, hogy ezt nem kell feltétlenül megírnom. Bár ha arra gondolok, hogy esetemben ez leginkább egy e-mail cím lenne, akkor máris nem tűnik akkora marhaságnak (legalábbis számomra) - lehetne neki pl. ellenőrző metódusa, ami akár szintaktikailag, akár fizikailag ellenőrzi, hogy valódi, működőképes cím-e... és több hirtelen nem jut eszembe. :)
Hátja, de ezt olyan hosszú
Meg tudlak érteni, de hajnali
Ne sajnáld, én speciel
Részvét :D Majd legközelebb
Eredetileg vitatkozni
Próbáltam az általad írtak alapján átgondolni azt, amit eddig elkövettem ("kissé" már eltér a topic fejlécében látható kódtól) és közben kipróbáltam, mi történik a destructorban, ha megkérem, hogy írjon magáról egy sort egy log táblába.
Most beleerőszakoltam egy metódusba, de egyértelmű, hogy pl. a log írása önálló osztályért, objektum(ok)ért ordít... Hajjjajjjjjj... és még bele se kezdtem igazán... Azt hiszem, ez picit nagyobb falat lesz, mint terveztem. De OOP lesz, ha beledöglök is! :)
(<panaszkodás on>látszik: amit anno műveltem, azt ma úgy hívják, hogy code monkey... magasabb szintű tervezéshez semmi közöm sem volt :) :( )
Ha sok objektumod van, akkor
Visszatérve a konstruktorod szétbontására:
Az is_string-es rész kapásból egy metódus, az is_integeres rész szintén egy metódus... Az if-es részt bármilyen jóérzésű ember feltenné egy olyan osztályba, ami az User-t hívja, szóval egy controllerbe.
A kapcsolat létrehozásáért egy factory kéne, hogy felelős legyen, nem pedig az User (főleg nem statikusan...), a factory-t pedig érdemes beinjektálni. Én ilyenkor sokszor csinálok egy olyan factory-t, ami factory-kat gyárt, és azt injektálom mindenhova.
Konstansok helyett én csinálnék egy fieldMap-et, ami alapján a bindelésnél kapásból meg lenne az adott mező típusa, és nem kéne kézzel beírni.
(off: Gyakorlatilag az egész rossz, amit írtál, de legalább ki lehet indulni belőle :D)