Hirdetés

Keresés

Új hozzászólás Aktív témák

  • fordfairlane

    veterán

    válasz Sk8erPeter #15409 üzenetére

    Ebben igazad van, de tulajdonképpen ez ilyen Singleton+Factory minta egyvelege.

    Nem tudom, minek az egyvelege. Külön osztály végzi a példányosítást, és a példány felügyeletét futásidőben, ennyi. A Singletonnal szemben a leggyakoribb kifogás, hogy keveredik az objektum hagyományos szerepköre, a domain-funkció, és a példányosítási-futásidejű implementálási technika, és ezért nehezen tesztelhető.

    Itt nem keveredik, szét van választva. Persze lehet tovább alakítani, hogy automatikus tesztekre alkalmasabb legyen, dependency konténerrel és társaival, de ez már végképp olyan szint, amivel semmiképp nem terhelnék egy kezdőt. Már ez is sok volt neki. :)

  • Sk8erPeter

    nagyúr

    válasz fordfairlane #15402 üzenetére

    Ebben igazad van, de tulajdonképpen ez ilyen Singleton+Factory minta egyvelege.

    (#15403) DNReNTi :
    "Mért lenne gáz? :U Adatbázis kapcsolat kezelésére szvsz nem igen van jobb megoldás."
    Egyrészt szerintem az ironikus hangvételből kiderült, hogy nem feltétlenül tükrözi a véleményemet a dolog, még ha bőven van is igazsága az azt ellenzőknek, tehát nincs szükség a szemforgatásra (arra amúgy sincs, ha szakmai vitát akarunk nyitni), másrészt meg javaslom, keress rá a topicban (pl. Athlon64+ kolléga itt kardoskodik ellene: [link]), illetve Stack Overflow-n és más forrásokban is, hogy mik is az érvek a Singleton-minta ellen; az "Adatbázis kapcsolat kezelésére szvsz nem igen van jobb megoldás" mondatra meg az a válasz, hogy van, akik meg tudják oldani nélküle, tehát lehet jobb megoldás. Most is előkapható a sablon-érv, hogy "nincs legjobb megoldás". :)

  • fordfairlane

    veterán

    válasz Sk8erPeter #15401 üzenetére

    Talán rosszul tudom, de a singleton egy olyan objektum, ami önmagát állítja elő, futásidőben egyszer. Ez nem saját magát állítja elő, hanem a PDO-t.

  • Sk8erPeter

    nagyúr

    válasz fordfairlane #15398 üzenetére

    Vigyázz, mert mindjárt megkapod, hogy a Singleton qrva gáz. ;]

    "Majdnem olyan, mint egy Singleton"
    Hogy érted azt, hogy majdnem olyan? Jelen formájában ez konkrétan Singleton-minta.

  • fordfairlane

    veterán

    válasz fordfairlane #15397 üzenetére

    Én egy ilyet használok:

    <?php
    class DbFactory {
    private static $instance;

    private function __construct() {}

    private function __clone() {}

    public static function getInstance() {
    if(!self::$instance) {
    self::$instance = new PDO("dsn", "user", "pass", array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    ));
    }
    return self::$instance;
    }
    }

    Bárhol szükséged van adatbáziskezelésre, ennyiből megkapod a handlert:

    $dbh = DbFactory::getInstance();

    A DbFactory csak egyszer csinál objektumot az első meghívásnál, után ugyanazt adja vissza minden további meghívásnál. Majdnem olyan, mint egy Singleton.

  • Sk8erPeter

    nagyúr

    válasz PumpkinSeed #14826 üzenetére

    Nem, nem jó. Ha ilyesmikkel játszadoztál eddig, nem csodálom, hogy szívásnak érezted az egészet. Részletesen felsoroltam a teendőket ahhoz, hogy az UTF-8-karakterkódolással (és így a mindenféle nyelvben megtalálható specifikus karakterekkel, ékezetekkel, és egyéb, speciális karakterekkel) ne legyen problémád.

    "Na én ezt nem akarom minden egyes gyakoroló feladatnál megcsinálni. :D"
    Ezt remélem, csak viccnek szántad. :D Ne már. Legegyszerűbb módon legyen egy vagy több fájlod, amiben mindenféle ilyen lépést megcsinálsz, és ezeket egyszerűen include-old mindig az index.php-dban, és kész.
    Ezen fájlok valamelyikében kiküldöd az UTF-8-as fejlécet (a header() fv. mutatott használatával), máshol megnyitod a kapcsolatot az adatbázissal (ezt is úgy, hogy már a kapcsolat elején beállítod az UTF-8-karakterkódolást, ahogy írtam; hogy singleton-mintán keresztül kommunikálsz az adatbázissal, ami esetleg nehezíti a unit testet, vagy más, az tök mindegy most ebben a fázisban még, mivel valszeg azt sem tudod, mi az a singleton vagy a unit test). Az előző step-by-step útmutató szerintem eléggé világos.

    A fájljaidnak alapértelmezetten amúgy is UTF-8 without BOM-kódolásúnak kellene lenniük, egyszerűen az általad használt fejlesztőeszközben állítsd be (bár a fejlesztőkörnyezeteknél ez az alap, csak az egyszerűbb, Notepad++-szerű szövegszerkesztőknél szokott default lenni az ANSI, mármint Windows-on), hogy mindig UTF-8 without BOM-kódolású fájlokat hozzon létre.

    Az adatbázisban is érdemes (szerintem) alapértelmezettre állítani valamelyik utf8_ kezdetű collationt.

    Nem hiszem, hogy ezek olyan bonyolult lépések lennének. Hidd el, hogy az összhaszon nagyobb lesz vele, mintha lusta vagy egyszer ezt az utat végigjárni. Például akkor megtanulsz adatbázist kezelni, és nem bohóckodsz fájlokba írogatással és azokból olvasással olyan műveletek esetén, amiket illene adatbázissal elvégezni.

    Adatbázis-kezelési ismeretek nélkül manapság egy fejlesztő akár éhen is halhat.

  • fordfairlane

    veterán

    válasz trisztan94 #14049 üzenetére

    Ugy ertettem, hogy melyik a legjobb hozza, mondjuk ab kapcsolat, listazas, stbstb.

    A patternek továbbra is probléma-, nem pedig nyelvjárásfüggőek. Mondom, attól függ, hogy mire akarod használni az adott patternt. Például MV* architektúráknál a PHP-ban is az observer patternt szokták használni, ahogy minden más nyelvben, ahol felhasználói interaktivitást kell kezelni.

    Listázáshoz Iteratort. ab kapcsolat? Adatbázis kapcsolatra gondolsz? Singleton, DI konténer Factory methoddal, stb...

  • Sk8erPeter

    nagyúr

    válasz pvt.peter #13428 üzenetére

    Igazából azt pötyögted be, ami kommentekben is megtalálható, túl sok új nincs benne. Ez a query1(), query2() elég mágikus név, mit akarsz vele megvalósítani? Mindenesetre már az elnevezés is rossz. De legfőképp az, hogy fel akarod fedezni a spanyolviaszt: ne akarj n+1-edik adatbázis-kommunikációs wrapper osztályt csinálni, ott a mysqli és a PDO, valamint remek ORM-ek vannak. Írtad, hogy a mysql_ függvények használatára vagy kényszerítve, de ezt az érvet sajnos nem tudjuk elfogadni. :DDD Tehát minimum mysqli vagy PDO, a mysql_ kezdetű függvények használatáról 2013-ban már nincs is értelme beszélni.
    Volt már korábban itt egy (v. több) hitvita a topicban, hogy Singleton-minta jó-e vagy sem, a vége az lett, hogy több érv szól a nem mellett (itt olvashatsz róla többek közt: [link], meg persze a topicban, a Singleton szóra rákeresve).

  • rt06

    veterán

    válasz cucka #13122 üzenetére

    "Attól, mert egy osztályból várhatóan csak egy példány lesz, még nem indokolt a singleton használata."
    miert?
    milyen hatranya lehet?

  • cucka

    addikt

    válasz fordfairlane #13121 üzenetére

    Én nem javasolnék singletont ilyen esetben. Meg úgy őszintén, jól el kell gondolkoznom, hogy mikor fordult elő utoljára, amikor singletonra lett volna szükségem. Attól, mert egy osztályból várhatóan csak egy példány lesz, még nem indokolt a singleton használata.

  • fordfairlane

    veterán

    válasz H.O.D. #13119 üzenetére

    Használhatsz Singletont.

    <?php
    class Osztaly {
    private $prop1;
    private $prop2;

    private function __construct() {}
    public static function getInstance() {
    static $instance = null;
    if($instance == null) {
    $instance = new Osztaly();
    }
    $instance->prop1 = "ezt belerakom";
    $instance->prop2 = "ezt meg ide";

    return $instance;
    }

    public function getProp1() {
    return $this->prop1;
    }

    public function getProp2() {
    return $this->prop2;
    }
    }

    $o = Osztaly::getInstance();

    $o2 = Osztaly::getInstance();

    var_dump($o === $o2);
    ?>

  • fordfairlane

    veterán

    válasz H.O.D. #13117 üzenetére

    A konstruktor nem hívódik meg. Kívülről nem hívható, belül nincs példányosítás. Ez egy hibás egyveleg a statikus és egy singleton osztálynak.

  • Soak

    veterán

    válasz Agyasima #12416 üzenetére

    Szerintem elösször nem konkrétan a nyelvet kéne tanulmányoznod, hanem a programozási szokásokat, koncepciókat , hogy kicsit képben legyél. Azért mondom ezt, mert nekem az a tapasztalatom, hogy a neten lévő 1000 tutorialbol 995 használhatatlan vagy csak azoknak jó akik épp valamiért nem tudnak vagy lusták valamit leprogramozni, de látják ha egy kódban hiba van és/vagy be tudják az illeszteni a sajátjukba.

    Ilyenekre gondolok, hogy : MVC, SQL security (injection), XSS, Singleton, OOP, stb (akinek van kedve kiegészthet) .

    Ezeket ha beírod a googleba akkor el tudsz indulni valahol és rá tudod hangolni kicsit a gondolkodás módodat a programozásra és esetleg találsz olyan problémákra megoldást amiről azt sem tudtad, hogy léteznek :) . A kezdő tutorialokkal vigyázni kell, mert azok általában annyira elegek, hogy össze tudj valahogy kalapálni egy 'Hello World'-öt meg két adatbázis query-t a lehető legegyszerűbben, ami máris elindított a rossz irányba .

    Amiket fent leírtam azok egy rész egy kezdőnek is kötelező, másik része kicsit haladóbb, de szerintem abban itt mindenki egyet ért, hogy rosszat nem érdemes tanulni mert ha komolyabban akarsz vele foglalkozni akkor előbb utóbb úgyis ki fogsz lyukadni ezeknél és akkor rájösz, hogy egy csomó időt elvesztegettél a hülyeségre.

  • Peter Kiss

    őstag

    válasz Lacces #11264 üzenetére

    A dependency injection-ben semmi sötét mágia nincs, annyiról szól, hogy egyértelműen megmondod, mi kell az adott objektumot létrejöttéhez/működéséhez, vagy épp egy metódus működéséhez ahelyett, hogy valami kiskaput válassz: ez lehet a new operátor (pfuj :DDD ) vagy épp az említett singleton vagy singleton-jellegű global object. Constructor-okban lehet sokszor olyat látni, hogy a paraméterlistája tök üres, de van benne vagy 5-ször valamilyen példányosítás new-val vagy mással (ez egyébként amiatt is bukta megoldás, hogy a ctor-okban nem végzünk semmilyen műveletet gyakorlatilag [példányosítás, adatbázishoz kapcsolódás, bármi ilyesmi]).

    A container ezen csak annyit segít, hogy ne kelljen annyit írnod, hogy egészen egyszerű legyek. Ha lenne egy olyan osztályod, aminek a ctor-a kérnek másik 3 objektumot, akkor nem szívesen írnál ilyeneket mindenhol, ahol kellene:

    new (new (), new (), new ())

    A container-ek ezen tudnak segíteni: az adott megoldás leírását használva felépíted, hogy, ha valaki X objektumot kér, akkor annak a függőségeit hogyan oldja fel, és utána csak ennyit kell írnod:

    container.GetService(type)

    Általában a container-ekhez járnak különböző lifetime service-ek (vagy írhatsz sajátot), ilyennel tudsz singleton-féle működést előidézni.

    ---

    Az a final indoklás nem győzött meg, teljes osztályt szerintem a legritkább esetben kell lezárni. Ha azt szeretnéd, hogy valami az öröklődés ellenére is változatlan maradjon, azt rakd private-re vagy final-re, és kész.

  • Peter Kiss

    őstag

    válasz Lacces #11262 üzenetére

    Azt, hogy mit zársz le, és mit nem, nehéz kérdés, általában érdemes arra törekedni, hogy kiterjeszthető legyen majdnem minden osztály, de a kötelező dolgokat ne ronthassa el senki sem.

    A singleton faszság, azért. :DDD Ha singleton-szerű működést akarsz, akkor használj dependency injection container-t (de egyébként is érdemes).

    ---

    Egyébként a válaszoló is csinál érdekeset, a beállítások betolásának biztosan nem így kellene lennie (parse_ini_file-os történetre gondolok), illetve szerintem ctor-ban nem szabad kapcsolódni az adatbázishoz (én is csinálok ilyeneket, de fokozatosan jövök le a cuccról).

  • Lacces

    őstag

    válasz Peter Kiss #11261 üzenetére

    Hm, érdekes.
    Lenne pár kérdésem :)

    Amúgy egy Auth osztálynál, amit valszeg már nem fog tovább kiterjeszteni ( alosztályt létrehozni belőle), azt miért nem zárja le final kulcsszóval?

    Másik kérdésem, adatbázis kapcsolódásnál, miért nem használja a singleton minta implementálását?

  • Sk8erPeter

    nagyúr

    válasz Soak #10932 üzenetére

    Pedig erről volt hosszasan témázás korábban - Singleton vagy globális megoldás vs. egyszeri példányosítás, de Singleton nélkül.
    A staticot meg épp neked mondtuk el korábban, hogy miért nem jó, keress vissza.

  • fordfairlane

    veterán

    válasz cucka #10236 üzenetére

    Ezt értem, csak azt nem, hogy lett belőle antipattern. Semmi logika nincs azokban a magyarázatokban, amelyek a singletonoktól akarnak "megvédeni".

  • cucka

    addikt

    válasz fordfairlane #10212 üzenetére

    Az, amit írsz a singleton-ról, az alapvetően jó, viszont pusztán elméleti. Igen, elméletileg a singleton valóban egy hasznos pattern. A php fejlesztés rögvalóságában viszont:
    - Tudod mi van, ha két adatbázis kapcsolat objektumot hozol létre? Semmi sincs. Egy élő rendszeren rengeteg adatbázis kapcsolat létezik egy időben. Tehát itt egy olyan veszélytől (több példány létrehozása) véd meg a singleton minta alkalmazása, amely veszély nem is létezik.
    - Egy tipikus php alkalmazásban a keretrendszer hozza létre az adatbázis objektumot, nem maga az alkalmazás. Nem áll fenn a veszély, hogy az alkalmazás véletlenül több példányt hoz létre belőle, mert egy példányt sem fog létrehozni.
    - Az adatbázis wrapper osztályt tipikusan valamilyen globális változón keresztül éred el. A többszörös példányosítás itt is értelmét veszti.

    Egy cseppet sem akarok a design pattern-ek ellen beszélni, de szerintem egy tipikus php-s környezetben a singleton elméleti előnyei elméletiek maradnak. 5 évig voltam php fejlesztő, egyetlen egy alkalomra sem emlékszem, amikor olyan problémába ütköztem volna, amit a singleton pattern megold.

    (#10235) RootRulez
    Hol akadtál el?

  • Sk8erPeter

    nagyúr

    válasz fordfairlane #10212 üzenetére

    #9911 környékén én is érveltem a Singleton mellett, igazából csak annyit, hogy azért annyira nem ördögtől való szerintem a használata, de olvass csak vissza, a véremet akarták. :DD

    ========

    (#10207) Soak :
    fájlnevekre is alapvetően a whitelisteket érdemes alkalmazni: tehát azt mondod meg, milyen karaktereket engedsz, nem azt, hogy mit nem szabad használni, minden neked nem tetsző karaktert egyszerűen kivágsz a fájlnévből, vagy behelyettesíted egy általános helyettesítő karakterrel, ami neked tetszik, lehet ez egy aláhúzás (_), kötőjel, vagy egyéb, olyan karakter, ami nem okozhat problémát egyik platformon sem (pl. ne akarj egy » jelet tenni a fájlnévbe :D).

  • fordfairlane

    veterán

    válasz cucka #10206 üzenetére

    Bocs, de nem értem. Nem arról van szó, hogy a keretrendszer valamit megcsinál helyettem, mert mi van akkor, ha nem csinálja meg, másrészt a futási idő szintén érthetetlen érvelés. Egyébként is a keretrendszer használhat singletont, én nem? :)

    Van egy erőforrás, amiből egy van. Fájlrendszer, adatbázis kapcsolat, socket egy kiszolgáló felé, whatever. Ezt a valamit be akarod burkolni egy osztállyal. A Singleton egy "creational pattern", ami az egyszeri példányosítási funkciót belezárja az objektumba, tehát az alkalmazásnak nem kell ügyelnie, hogy ne hozzon létre fölöslegesen új példányt, ha futás során több heylen is hozzá akar férni ehhez az objektumhoz. Egy singleton objektum ugyanolyan kutyaközönséges objektumnak néz ki a guest kód számára, mint a példányosított. Miért baj ez?

  • cucka

    addikt

    válasz fordfairlane #10187 üzenetére

    A singleton elsősorban olyan szoftvereknél használatos minta, amelyek sokáig futnak és van egy olyan komponensük, amely valamilyen külső erőforrást használ.
    PHP-nál a szkripted minden egyes oldalletöltődésnél lefut, az objektum élettartama nagyon rövid, ráadásul az adatbázis objektumot jellemzően a keretrendszer hozza létre, egy példányban. Egyszerűen nincs előny abból, ha a singleton mintát használod.

    (#10204) Soak
    Ez tetszett :D

  • cucka

    addikt

    válasz mobal #10180 üzenetére

    Nem baj a singleton, csak nincs igazán értelme egy php-s adatbázis osztálynál, fölöslegesen bonyolítja a kódot.

  • Sk8erPeter

    nagyúr

    válasz mobal #10180 üzenetére

    Olvass vissza, #9911 környékén kezdődött a vita a Singletonokról.
    Linkek esetén meg legfeljebb akkor szóltam be, ha a linken található tutorial gány megoldásokat mutatott be, nem szoktam ok nélkül pampogni, mindig megmagyarázom, ha valami baj van a linkelt cuccal. Legközelebb az indoklást is olvasd el, hátha átjön. :)

  • mobal

    nagyúr

    válasz Sk8erPeter #10179 üzenetére

    Nem értem miért baj a Singleton. Én szeretem alkalmazni. Régebben mindig Sebességszabi is kikapott a linkelésért ;]

  • Sk8erPeter

    nagyúr

    válasz mobal #10177 üzenetére

    "Mindjárt jön kutyi és kikapok, hogy miket linkelgetek"
    Miről beszélsz? Miért szólnék be azért, hogy belinkelsz egy tutorialt? Magyarázatot követelek. :D

    Inkább Athlon64+ fogja letépni a fejedet a Singleton-minta javasolásáért. ;]

    (#10174) papa019 : igen, erre gondoltam.

  • Sk8erPeter

    nagyúr

    válasz Tele von Zsinór #9923 üzenetére

    "Feltételezem, a kód C#-ból van"
    Igen, rögtön gondoltam, de nem igazán volt világos, hogy ez most hogy jön ide, PHP-s témához, amikor kizárólag a PHP-re jól alkalmazható, itt érvényes mintákról beszéltünk korábban.
    Éppen ezért mondtam, hogy most fel lehetne ilyen alapon hozni Singletonra az ablakkezelő objektumokat is, de mivel ilyen PHP-nél nincs, tök felesleges ilyenről beszélni.

    Lambda: jahh, oké, closure néven oké, most már ezen a néven is. :)

    Ja, eddig is világos volt, hogy miről beszél, hogy nehéz hozzá unit testet írni. Én viszont azt mondtam, hogy vannak esetek, amikor erről felesleges beszélni, pl. most egy naplózó osztály esetén nem biztos, hogy valaki hatalmas bűnt követ el, ha nem passzolgatja inkább a controllereknek a már létrehozott példányt, hanem használ egy nyamvadt singleton-példányt, azt' kész.
    Van, amikor úgy logikus, hogy 1 példány legyen valamiből, és azt csak macerás passzolgatni össze-vissza, ezért jól jön néha a Singleton minta, ennyit állítok. Aztán ha már unit testekről van szó, nyilván át kell gondolni, hogyan lehet ezt átvariálni.

    Egyébként az adatbázis-kapcsolódáshoz nem biztos, hogy egy request során csak egyet akarunk, ezért nem is biztos, hogy olyan jó "klasszikus" példának a Singleton alkalmazására, mert elképzelhető, hogy valaki egy request során több adatbázishoz is szeretne csatlakozni.

    ===================

    (#9924) Athlon64+ :
    ezek szerint elbeszélünk egymás mellett, nem értetted meg, miről magyaráztam. Most itt fentebb leírtam még egyszer. PHP-ről beszélünk, könyörgöm, ne keverjük már ide a C#-ot, meg a többi nyelvet, mert nyilván nagy különbségek lehetnek.

    "A tervezési minták átívelnek a nyelveken."
    Nem mondod komolyan, TÉÉÉNYLEEG?? :W
    Azért ne nézd már hülyének az embert. Inkább próbáld megérteni, miről beszél. Pl. arról, hogy attól még, mert mondjuk van értelme ablakkezelő objektumról beszélni egy másik nyelv, más jellegű felhasználása során, attól még nem biztos, hogy hasonló minta alkalmazható egy nyomorék PHP-s webalkalmazás esetén.

  • Tele von Zsinór

    őstag

    válasz Sk8erPeter #9922 üzenetére

    A service locator patternre hozott példát, hogy hogy működik ez .NET alatt. Feltételezem, a kód C#-ból van, ott van ilyen szintaxisa a template-eknek. Első ránézésre valahol a Factory és a Dependency Injection keverékének tűnik.

    Lambda, vagy más néven névtelen függvények. A php világban leginkább closure néven ismertek.

    Becsatlakozva kicsit az épp folyó témába: nagyon sokáig használtam én is singletonokat, leginkább a már említett adatbázis-kapcsolat miatt, mert hogy abból legfeljebb egyet akarunk egy request során. Aztán amikor elkezdtem belemászni a tesztelésbe, meg láttam, mennyire is nehéz az ilyenekre épülő kódhoz unit testet írni (avagy: lehetetlen), gyorsan leszoktam róla.

    Jelenleg a Dependency Injection a leginkább használt mintám, erre egy gyors és könnyen érthető megvalósítás a Pimple. Pár sorral megoldható, hogy a $app["log"] első híváskor példányosítsa a logger osztályt, a többi meg ugyanazt kapja vissza - mock osztályokkal innentől nagyon könnyen tudom például azt tesztelni, hogy egy service x függvénye y paraméterekkel meghívja-e annyiszor a loggert, ahányszor kell. Analóg módon az adatbázist (mondjuk $app["db"]) is le tudom cserélni a tesztek alatt egy erre tökéletes (akár tömbökkel működő) implementációra, amivel pontosan azt tudom tesztelni, amit akarok: a controllereimet.

    És ez csak a felszín. Nagyon érdemes utánaolvasni részletesebben, kezdésnek Fabien Potencier cikksorozatának első két részét ajánlom.

  • Sk8erPeter

    nagyúr

    válasz Peter Kiss #9921 üzenetére

    Várj, most PHP esetén milyen dll-ekről beszélünk? :D
    "Lambdákkal"? :F Lehet, hogy sok volt a mai utazás, és fáradt vagyok, de most nem esik le.
    Service locatorről fogalmam sincs, nem használtam még, de erről ezt találtam (nem javasolja).
    Mivel már idekevertük a szezont is a fazonnal (dll-ek?), nem vágom, egyáltalán PHP keretein belül beszélünk-e a Singleton osztályok létjogosultságáról.

    Én szimplán azt állítottam, hogy pl. egy Logger osztálynál teljesen megfelelő megoldás egy Singleton használata, statikus metódusokkal, hogy mindenki hozzáférjen, tök felesleges bonyolítani egy ilyen osztályt. Mindent lehet még nyakatekertebben is megoldani, hogy aztán arra recskázhasson a fejlesztő, hogy ő milyen ügyes volt, de vannak esetek, amikor tökéletes időpocsékolás ilyennel rajoskodni.

  • Peter Kiss

    őstag

    válasz Sk8erPeter #9920 üzenetére

    Singleton-t még logger osztállyal sem használnék. Van mindenre sokkal okosabb és jobb megoldás, erre pl. egy service locator lenne az egyik (e mögé be lehet tenni, hogy csak egy instance lehet mindig, de ki hogyan szereti) lambdákkal. Ez egyébként nagy királyság, a már említett DLL-ből kintre csak ennyi látszik: DLL.GetService<TService>();

  • Sk8erPeter

    nagyúr

    válasz Peter Kiss #9919 üzenetére

    Találtam egy jó összefoglalót arról, hogy miért is NEM feltétlenül indokolt a Singletonok használata (amiről tulajdonképpen Te is beszélsz):

    http://gooh.posterous.com/singletons-in-php

    "Singletons are not unique snowflakes
    In languages where objects live in an application server, Singletons can be used to keep memory usage low. Instead of creating two objects, you reference an existing instance from the globally shared application memory. In PHP there is no such application memory. A Singleton created in one Request lives for exactly that request. A Singleton created in another Request done at the same time will still be a completely different instance. And it will occupy it's own memory. Those instances are not linked to each other. They are completely isolated, because PHP is a Shared-Nothing architecture. You do not have one single unique instance, but many similar instances in parallel processes. Thus, one of the two main purposes of a Singleton is not applicable.

    Don't construct twice, it's all right
    Advocates of the Singleton in PHP often argue it's still useful to be able to limit an instance within a single request. The aforementioned database classes being the most prominent example. But the much easier solution would be simply not to instantiate a second instance. If anyone can make sure there is just one instance, it's the developer. If you need to have the same instance in many classes, use Dependency Injection. Just create one, inject everywhere. That will also save you the hassle of deconstructing your Singleton once you notice you need a second instance of it all of a sudden.
    Another example where Singletons are often applied but don't make sense is classes like FrontControllers. While conceptually it makes sense to say "There may be only one FrontController", it is superfluous to ensure it from an architectural viewpoint. A FrontController is usually instantiated only once in your application's control flow anyway. If you don't write a new Foo; anywhere else, you already made sure there is just one instance. So you ain't gonna need the Singleton here. Don't express concepts in your code that are never used.

    Don't shoot yourself in the foot
    The Singleton's other purpose (to have a global access point to the instance) is undesirable in PHP. The desire for that usually stems from having an architecture where objects pull in their dependencies. Like any globals and statics, the Singleton's getInstance() method creates coupling to the global scope. This makes Unit-Testing harder. There is ways to mitigate this, but in general, the cost to mitigate is higher than to simply avoid the Singleton in favor of Dependency Injection. This is especially true in those situations, where the Singleton is applied but never instantiated twice anyway."

    Itt van egy hosszabb témázás magyarul erről:
    http://weblabor.hu/blog/20100727/php-egyke-ososztaly

    ============

    Hadd mondjak ellenérvet is (már úgyis megszokhattátok, hogy ez a rész is mindig jön a hsz.-eimben :D):
    [link]
    Pont ez jutott nekem is eszembe elsőként, amit itt írnak az elfogadott válaszban, hogy pl. egy Logging class esetén tipikusan jól használható egy Singleton osztály, mert ott felesleges tesztelésekről beszélni (valszeg nem a naplózásért felelős osztály a legfontosabb, amit tesztelni kellene), plusz teljesen elfogadható lehet ennek a mintának az alkalmazása, mert más módon szépen összehozni a rendszerrel feleslegesen macerás lehet.

    Saját példa az, hogy bizonyos esetekben csak nagyon macerás módon, adott esetben a teljes rendszer újratervezésével lehetne normálisan beépíteni a rendszerbe egy több helyen szükséges változó Singleton nélküli használatát - tipikusan olyan rendszerekre gondolok, ahol jelenleg még nem elsősorban az OOP-szemléletet követik, hanem egyelőre inkább globális függvényekét (bár van elmozdulás az OOP irányába): mint a Drupal.
    Más megoldás nyilván a globális változók használata, ami tulajdonképpen hasonló lehet a Singletonokhoz, de kicsit mégis más. Pl. Drupalnál szükségem volt már ilyenre: [link].

    A másik: csak hogy egy kicsit pontosítsunk, a Singleton-osztályok használata elsősorban PHP-nél felesleges. Aztán más nyelveknél vannak bőven kivételek, mint pl. egy ablakkezelő objektum használata.

    Ettől függetlenül tényleg fennáll, hogy a lehető legritkább esetekben szabad használni, alapvetően a már említett szempontok miatt kerülendő. Főleg PHP-nél (lásd az idézett cikket).

    ===

    DE további ajánlott linkek:
    http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

  • Speeedfire

    félisten

    válasz Peter Kiss #9916 üzenetére

    Lehet, hogy csalóka. De mi számít akkor ezekben az esetekben?
    Átláthatóság? Sebesség? Továbbfejlesztés? Vagy miért nem "előnyös" a static és a singleton?

  • Peter Kiss

    őstag

    válasz PazsitZ #9912 üzenetére

    A Singleton anti-pattern, tesztelhetetlen alkalmazást eredményez, illetve fogalmad sem lesz arról, hogyan működik az alkalmazás.

    Elég csak arra gondolni, mi van akkor, ha kapsz egy egyébként működő kódhalmazt, amit használni szeretnél, de rejtett dependency-k vannak benne a singletonok miatt. Sosem szabad ilyet csinálni.

    Példa:

    <?php
    /* ... */
    $controllerFactory = $this->_controllerBuilder->GetControllerFactory($this->HttpContext);

    $controller = $controllerFactory->CreateController($this->HttpContext);

    if (!$controller->GetType()->ImplementsInterface("\\System\\Web\\Mvc\\IHttpHandler") || !$controller->IsStateLess()) {
    $sdsf = new SessionProviderFactory();

    $this->SessionManager = new SessionManager($this->HttpContext, new UsersAndGroupsDataContext(), $sdsf);
    $this->SessionManager->Validate();

    $this->HttpContext->Session = $this->SessionManager->GetCurrentSession();
    }

    if (!$controller->Execute($this->HttpContext, $this->_actionInvokers->GetActionInvoker(typeof($controller)))) {
    throw new \Exception("Failed to execute action: " . $this->HttpContext->Route());
    }
    /* ... */

    Itt mondhatnám én is a $this->HttpContext átadása helyett, hogy akkor HttpContext::Instance() az egyes helyeken (kihagyva a metódusok paraméterlistájából), mert itt ugyanazt jelenti, de azt eredményezné, hogy még számomra se lenne világos, minek mire van szüksége.

    A példában szereplő if block egyébként még javításra szorul.

  • PazsitZ

    addikt

    válasz Speeedfire #9905 üzenetére

    Ha már bejelntkezett userről van szó miért nem állítod be belépéskor a setState-el hogy a user isAdmin true vagy false. Bár ekkor még implicit nincs lekezelve a belépett kilépett kérdés, de jobb esetben ezt önmagában rbac szabályokkal gondolom lekezeled a controller hívás előtt.

    Jah most olvasom csak végig, hogy gyakorlatilag Athlon64+ is ezt javasolja. :U

    (#9911) Athlon64+:
    Azért a singleton se ördögtől való dolog.

  • Peter Kiss

    őstag

    válasz Speeedfire #9910 üzenetére

    Static dolgok használata könnyen gyorsan spagetti kódot eredményez, fogalmad sem lesz, mi zajlik a rendszerben, tesztelhetőségről ne is beszéljünk.

    A másik, hogy ha ezt a kérés során folyamatosan használod mondjuk 5 alkalommal, akkor ötször fog ez így lefutni?

    Kódírás folyamán mindig érdemes lefektetni pár szabályt, amit betartasz, pl.:
    static változóba nem rakok semmit, ami állapotot tárol (singleton is kinyírva)
    static csak olyan lehet, ami valamilyen service-szel kapcsolatos (nálam ilyen a Path osztály, ez csak a mappák, fájlok neveit machinálja string-ként, az IsAdmin cuccod ilyesmi, de rossz a megközelítés*)

    Ezeket igyekszem mindig betartani, de a saját kis reflection kiegészítésem miatt én is tárolok dolgokat static változóban, de azok nem is változnak, amíg az osztály maga nem változik meg. Érdemes úgy tekinteni a static elemekre ilyen szempontból, mintha a PHP nem shared nothing elveket vallana.

    ---

    Static cuccokkal van olyan gond, hogy simán keresztülhúzod az OO elveket. Most egy felhasználóról akarod megmondani, hogy admin avagy nem admin úgy, hogy gyakorlatilag kiszeded az egészet a rendeltetési helyéről, hiszen maga a User meg tudja mondani magáról az-e, ahogyan ez látszik is.
    A kereted ad hozzáférést egy user nevű field-hez, az mi? Nem tudod egész véletlenül megmondani a rendszernek, hogy oda egy profibb objektumot toljon be? Mert akkor ennyi lenne: Yii::app()->user->admin; és nincs ez a static borzalom benne a rendszerben.

    Maga a design is lehet rossz: nem egy bit kell arra, hogy admin-e, hanem hegeszteni kell olyan Role rendszert, amibe ezt szépen bele lehet kódolni.

    ---

    Én is használtam Singleton-t, de utána alig bírtam kiírtani a rendszerből, nagyon rossz ötlet. Nem tudom, mennyire jött át a dolog, de ha most nem, majd rájössz. :K

  • PazsitZ

    addikt

    válasz Speeedfire #9712 üzenetére

    Persze
    A Yii-nél a model() egy static osztálypéldáyosítás.
    lásd pl. singleton pattern esetén. is static hívással pédányosítod az osztályt (persze ott a lényeg, hogy mindig csak egy objektum példány létezik).

    Lényegében ez egy shortcut. a példádban is első eset 2 sor második egy sor és rögtön fűzhető a query. sőt, mivel mindegyik query építő AR model fgv. az objektummal önmagával tér vissza így szépen fűzhetőek a hívások.
    Modelnev::model()
    ->with('masikTabla')
    -> ...
    ->findbypk(2);

    PHP 5.4-től viszont már lehet többek között majd ezt is:
    (new Modelnev)->findbypk(2);

    De végiggondolva a static fgv. hívás valahol jogosan megengedhető akár példánycontext felől is.

    $keresendo_elem = new Modelnev;
    $keresendo_elem->model();
    Modelnev::model();

    Mivel a static fgv nem függ az objektumtól miért ne lehetne hívni objektumból?
    Visszafele nem igaz, mert egy objektum állapotától adattagjaitól függő metódust meghívsz egy osztályra, ami nem példány, akkor ugye mit kezdjen a method a nem létező példánytagok nélkül?

  • cucka

    addikt

    válasz Sk8erPeter #6934 üzenetére

    Szerintem adatbázis-kapcsolati objektumok létrehozásához érdemes lehet a Singleton-mintát alkalmazni.
    Szerintem annyira nem érdemes. Alapvetően PHP-s webfejlesztés során túl sokat nem nyersz a tervezési mintákkal. (Elsősorban a php gyenge típusossága miatt, másodsorban a webfejlesztés sajátosságai miatt). Persze, lehet használni, semmi baj sincs vele.

    Én személy szerint a PDO-t használom, és ajánlom is a használatát.
    Jelenleg kezdek egy hobbi projektet és nézegettem ezt is mint lehetséges eszközt, de hát a tudása az nagyon erősen konvergál a nullához egy komoly orm-hez képest.

  • Sk8erPeter

    nagyúr

    válasz Alukard #6929 üzenetére

    Szerintem adatbázis-kapcsolati objektumok létrehozásához érdemes lehet a Singleton-mintát alkalmazni. Többnyire az embernek dinamikus weblapok készítésekor egyetlen adatbázis-kapcsolati objektumra van szüksége, persze lehetnek kivételek, de általában előbbi a jellemző.
    A kódodban a protected láthatóságú tagváltozóknak semmi szerepe nincs, mivel nem rendeled hozzájuk az értékeket (nincs ilyen sor: $this->sql_host = "localhost"; stb.), hanem csupán lokális érvényességű változóid vannak (pl. $sql_host), így azoknak nem sok értelme van. Mivel tulajdonképpen úgyis csak egyetlen helyen (connect() függvény) csatlakozol az adatbázishoz, nem biztos, hogy érdemes egyáltalán eltárolni ezeket az értékeket az objektumon és leszármazottain belül máshol is elérhető tagváltozókba.
    A "var" kulcsszó használata elavult, és igazából értelmetlen is jelen esetben, az nyugodtan lehetne protected (vagy private, de akkor a leszármazottak nem látják).
    Az előbbieken túl a $query-ket sehol nem ellenőrzöd, nem kerülöd el az esetleges SQL Injectiont vagy rosszindulatot nem feltételezve csupán esetleges hibákat azzal, hogy escape-eled az átadott stringet (mysql_real_escape_string).
    Plusz ha már OOP, akkor már kivételeket is illendő lenne használni, ez a die() ill. ekvivalense, az exit() nagyon ronda megoldás, ahelyett, hogy a megfelelő helyeken kezelnéd az egyes hibákat, egyből leállítod a szkript futását.
    Ezenkívül a hibaüzenetbe is muszáj belekötnöm: ez a "Ne zaklasd a rendszergazdát" elég furcsa egy hibaüzenet, inkább neked kéne elnézést kérned a júzertől, hogy para van az adatbázissal, nem még jól le is cseszni. :DD

    Én személy szerint a PDO-t használom, és ajánlom is a használatát. Támogatja az adatkötést, plusz azt, hogy ne kelljen explicite mindenhol escape-elni a stringeket (elintézi magának), és még sok egyebet, ráadásul full objektumorientált, és szerintem áttekinthetővé teszi a kódot.
    Feltettem pastebinre azt az osztályt, amit a Singleton-mintának megfelelően írtam, általában ezt az osztályt használom adatbázis-kapcsolat kiépítésére. A konstruktor és a copy konstruktor privát láthatóságú, így kívülről nem példányosítható tetszőleges számban az objektum.
    Van egy külön konfigfájlom, ahol definiálom a saját konstansokat, többek közt az adatbázis-jelszót és -felhasználónevet, ezeket a konstansdefiníciókat most az elejére tettem, középen jön maga az osztály, az osztály kódja alatt pedig egy példa látható a használatára: [PDO Singleton DB class].
    Hátha bárki hasznát veszi.

  • LW

    őstag

    Visszatértem és még mindig csak kérdezek. :B
    Az összetartozó eljárásokat, ill. függvényeket tartsam egy osztályban (akár singleton), vagy csináljak belőlük sima globális függvényeket?
    Mert egyébként ez nem igényelne osztályt, de így mégis rendezettebb.
    üdv. LW

  • cucka

    addikt

    válasz LW #6896 üzenetére

    Nem muszáj singleton-t használni, tulajdonképpen elsőre bőven jó egy olyan osztály, ami valóban oop-s és elvégzi a dolgát, az osztályt használó kód majd biztosítja azt, hogy csak 1 példány legyen belőle.
    (A session amúgy is egy globális valami és egy darab van belőle)

    Itt találsz példát singleton osztályra.

  • LW

    őstag

    válasz cucka #6894 üzenetére

    Köszönöm. Kerestem pár példakódot úgy vélem értem a singleton osztályokat. Estére rendbe rakok mindent.

    Ha az osztály példányosítása után szükségem van a singleton osztályra egy másik programblokkban, akkor az első példány referenciáját használom?

    Egyáltalán nem sértő. Tisztában vagyok vele, ezért is kérdezek tőled/tőletek. ;)
    Nem tanítottak nekem php programozást, de más (egyébként objektum orientált) nyelvet is csak futólag. Ha minden igaz, öt nap múlva megkezdődnek egyetemista éveim.

  • cucka

    addikt

    válasz LW #6893 üzenetére

    Egy gyors ránézés után egyértelmű, hogy nálad nem jött át, hogy mire jó az abstract osztály.

    A kódod gyakorlatilag globális függvények halmaza, amiket egy osztályba tettél. Na ettől nem lett oop-s a kód.

    Az absztrakt osztály lényege, hogy ez egy osztály, aminek néhány függvénye csak deklarálva van, de nincsenek definiálva (abstract függvények). Ez azt jelenti, hogy az osztály megmondja, hogy milyen pontosan függvényekre van szükség a működéséhez, de ezeket a függvényeket a leszármazottak kötelesek implementálni.
    A fentiek alapján ki lehet jelenteni, hogy a te osztályod teljesen fölöslegesen használja az "abstract" kulcsszót, mert pont a lényeg hiányzik belőle.

    Amire neked ennél a session osztálynál szükséged lenne, az egy rendes példányosítható osztály, ami singleton (tehát egy időben csak egy példánya létezhet, nézz utána wikin, hogy hogyan és miért).
    Az alkalmazásod indulásnál példányosítja a session osztályt, majd használja azt. Természetesen az osztály függvényei nem statikusak, mert annak semmi értelme nincs ebben az esetben.

    Szólj ha valami nem kerek :)

    (Egyébként egy nem sértőnek szánt megjegyzés: sokkal jobban járnál, ha fognál egy komoly php-s framework-öt és elkezdenéd használni, illetve megpróbálnád megérteni, hogy hogy működik, mert nekem innen úgy tűnik, hogy azért van egy-két lyuk a tudásodban, amit be kéne foltozni ahhoz, hogy értelme legyen a saját framework írásának)

  • lezso6

    HÁZIGAZDA

    LOGOUT blog

    válasz zhagyma #2556 üzenetére

    Pont azért találták ki az OOP-t, hogy hatalmas nagy kódmennyiség mellett is átlátható legyen a program. OOP lényege, hogy egy helyre kerül az adat és annak feldolgozása.
    Dehogy gyakorlati példát is mondjak: mysql_ függvények vs MySQLi class

    Illetve ott van a rengeteg OOP pattern: factory, adapter, singleton, stb. :))

Új hozzászólás Aktív témák

Hirdetés