F3llony Posted October 22, 2012 Report Share Posted October 22, 2012 Diskusija sekojoša - parasti visur un vienmēr ir nepieciešami sistēmas-globāli objekti/mainīgie. Globāļi sucks, to mēs visi zinām. Dependency injekcijas ir labi un jauki, taču, ne vienmēr ērti. Piemērs ir modeļi - tie ir bieži lietojami, loosely-coupled un katru reizi inicializējot to vai citu modeli barot injekcijas nav gluži tas reālākais risinājums. Piemēram, modeļu bāzes klasei vienmēr nepieciešama vismaz - a: sistēmas konfigurācija b: db links. Konfigurāciju varētu organizēt kā singletonu, taču ne vienmēr būs tikai viens konfigurācijas objekts (kā manā gadījumā). Tas pats ar DB saitēm - arī itkā varētu paplašināt kā singletonu un strādāt ar vienu instanci, bet tas līdz brīdim, kad nepieciešami >1 savienojumi ar dažādiem dsn vienlaikus. Varētu jau protams veidot vairākus singletonus, bet tas būtu nemenedžējams ārprāts. Un šis nav gluži vienīgais piemērs. Sistēmas iekšējām atkarībām un sistēmas atkarīgām bibliotēkām injekcijas ir okei, bet lietām, kuras nepieciešams bieži inicializēt manuāli tas vienkārši nav ērti. Līdz šim esmu izlīdzējies ar dependency injekcijām un pa retam, kādam globālim. Tagad uzrakstīju singletonu-reģistru (lasīt - $objects->{name} = $objekts), kurā tiek reģistrētas vitālu komponenšu objektu references un pie nepieciešamības, piemēram, modeļos, tās tiek atgūtas no šī reģistra, tādējādi apejot vajadzību pēc dependencijām. Savukārt, lai novērstu gadījumu, kad reģistrā kaut kas trūkst, speciāls exception, kuru pēcāk var noķert un nohendlot. Kādas vēl ir reālas alternatīvas - bez eksotikas, kā piemēram, glabāt references apc utml.? Link to comment Share on other sites More sharing options...
marrtins Posted October 23, 2012 Report Share Posted October 23, 2012 Ar APC jau tie paši globāļi vien sanāktu. Lai objektam vajadzīgos settingus no ārpasaules uzstāda pats programmeris: ->setDb($handle) ->setConfig($config) Kāda vaina? Link to comment Share on other sites More sharing options...
Joyride Posted October 23, 2012 Report Share Posted October 23, 2012 Singletoni tie paši globāļi vien ir. DIC var papildināt, lai prot nodrošināt dependencies un nebūtu tas manuāli jādara. Sākumā atbrīvo modeļus (precīzāk - entities) no dependencies, datu atlases un saglabāšanas funkcionalitāti pārnes uz mapperiem, kaut kādas kompleksas darbības ar entities - uz servisiem. Tas nodrošinās ērtu darbu ar entities, nereizējoties par dependencies, piemēram, $user = new \User. User entity ir pilnīgi vienalga, no kurienes dati tiek ņemti, vai no datubāzes, vai no kāda webservisa. Core objektus, kā arī mapperus un servisus reģistrē iekš DIC. // Bootstrap.php $dic->config = $dic->share(function ($dic) { $cfg = new \Config; $cfg->loadFromFile('path/to/config.php'); return $cfg; }); // Pārējie core objekti: Request, Response, Dispatcher, Logger utt $dic->db1 = $dic->share(function ($dic) { return new \Db_Mysql($dic->config->db1); }); $dic->db2 = $dic->share(function ($dic) { return new \Db_Pgsql($dic->config->db2); }); $dic->user_mapper = $dic->share(function ($dic) { return new \User_Mapper($dic->db1); // Vai arī citu DB konekciju, kas ir reģistrēta iekš DIC }); // User_Controller.php class User_Controller extends \Controller { private $user_mapper; public function __construct(\User_Mapper $user_mapper) { $this->user_mapper = $user_mapper; } public function list() { $this->view->users = $this->user_mapper->getActiveUsers(); } } // Dispatch // "Maģija" iekš Dic::create() ir gaužām vienkārša: ar Reflection iegūst izveidojamās klases dependencies (konstruktora parametrus) un tad tos meklē pie savām reģistrētajām dependencies. // Ja prasītā dependency nav reģistrēta iekš DIC, tad metam exception. Kad savācam vajadzīgo, tad izveidojam prasīto objektu (hint: newInstanceArgs() f-ja). // Un to, protams, var lietot ne tikai kontrolieriem, bet jebkuram objektam. $controller = $dic->create('User_Controller'); $controller->list(); // Vēl viens piemērs - gribam padot otro DB konekciju (PostgreSQL) un izveidot mapperi paši + lietot config: class User_Controller extends \Controller { private $db; private $config; public function __construct(\Db $db2, \Config $config) { $this->db = $db2; $this->config = $config; } public function list() { $mapper = new \User_mapper($this->db); } } Link to comment Share on other sites More sharing options...
codez Posted October 23, 2012 Report Share Posted October 23, 2012 (edited) Kā ar gadījumu, kad vienas funkcijas ietvaros vajag kaut kādo lietot, bet ne vienmēr. Ja padod kā dependency injection, tad tas tiek inicializēts lieki. Piemēram: function __construct(Log $log, Db $db){ if ($db->lalala()){ $log->error('lalala'); } else { //... } } Tas protams ir vienkāršs gadījums, bet reāli varētu būt 3,4,5 depnedencies un gadījumi, kad neizmanto nevienu, vai tikai vienu un tad tie tiek lieki inicializēti. Edited October 23, 2012 by codez Link to comment Share on other sites More sharing options...
daGrevis Posted October 23, 2012 Report Share Posted October 23, 2012 http://en.wikipedia.org/wiki/Multiton_pattern Neder? Nepatik? Link to comment Share on other sites More sharing options...
F3llony Posted October 23, 2012 Author Report Share Posted October 23, 2012 Kā ar gadījumu, kad vienas funkcijas ietvaros vajag kaut kādo lietot, bet ne vienmēr. Ja padod kā dependency injection, tad tas tiek inicializēts lieki. Tas protams ir vienkāršs gadījums, bet reāli varētu būt 3,4,5 depnedencies un gadījumi, kad neizmanto nevienu, vai tikai vienu un tad tie tiek lieki inicializēti. Also, this. http://en.wikipedia....ultiton_pattern Neder? Nepatik? Multitons ir tas pats klašu reģistrs, ko minēju topikā, ar atšķirību, ka multitons ir tas pats singletons ar vairākām instancēm. Tas neatrisina problēmu kolekciju veidošanai. Link to comment Share on other sites More sharing options...
Lauris Posted October 23, 2012 Report Share Posted October 23, 2012 Pimple DIC Notice that the anonymous function has access to the current container instance, allowing references to other objects or parameters. As objects are only created when you get them, the order of the definitions does not matter, and there is no performance penalty. Ir arī shared objects. Link to comment Share on other sites More sharing options...
marrtins Posted October 23, 2012 Report Share Posted October 23, 2012 Shared objekts=globāls mainīgais :D Link to comment Share on other sites More sharing options...
Kavacky Posted October 23, 2012 Report Share Posted October 23, 2012 Nē, nezinām vis. Nu nav tie globāļi ļaunums. Tā saka tikai tāpēc, lai n00bi neliek visus mainīgos globālajā. Link to comment Share on other sites More sharing options...
daGrevis Posted October 23, 2012 Report Share Posted October 23, 2012 Pimple... :D Link to comment Share on other sites More sharing options...
F3llony Posted October 23, 2012 Author Report Share Posted October 23, 2012 (edited) Nē, nezinām vis. Nu nav tie globāļi ļaunums. Tā saka tikai tāpēc, lai n00bi neliek visus mainīgos globālajā. Globāļi ir ļaunums jo nav iespējams atsekot un limitēt to, kas, kur un kāpēc tur tiek glabāts, kas, kur un kāpēc to izmanto utml sīkas nianses... Edited October 23, 2012 by F3llony Link to comment Share on other sites More sharing options...
marrtins Posted October 23, 2012 Report Share Posted October 23, 2012 To tāpat nav iespējams izdarīt :D Kas man kā programmētājam liedz kaut ko glabāt tur kur tas nav paredzēts? Jāizmanto API? Neizmantošu. Glabāšu failiņā :D Link to comment Share on other sites More sharing options...
Kavacky Posted October 23, 2012 Report Share Posted October 23, 2012 Link to comment Share on other sites More sharing options...
Joyride Posted October 23, 2012 Report Share Posted October 23, 2012 (edited) Kā ar gadījumu, kad vienas funkcijas ietvaros vajag kaut kādo lietot, bet ne vienmēr. Ja padod kā dependency injection, tad tas tiek inicializēts lieki. Tavā piemērā Log klase ir pietiekoši "populārs" objekts, kas noteikti tiek lietots daudz kur. Nu inicializēts tiks šeit, nevis nākamajā klasē, kur tāpat tiks lietots, kas par to? EDIT: Ja nu ļoti vajag, tad var jau padot konteineru: function __construct(Dic $dic) { if ($dic->db->lalala()) { $dic->log->error('lalala'); } else { //... } } Edited October 23, 2012 by Joyride Link to comment Share on other sites More sharing options...
F3llony Posted October 23, 2012 Author Report Share Posted October 23, 2012 (edited) To tāpat nav iespējams izdarīt :D Kas man kā programmētājam liedz kaut ko glabāt tur kur tas nav paredzēts? Jāizmanto API? Neizmantošu. Glabāšu failiņā :D Pēc otrās reizes, kad tev paprasīs pārrakstīt visu moduli pret doto API tā, lai tas to izmantotu tā, kā tas ir paredzēts arhitektūrā, tev vairs par "failiņiem" i domāt negribēsies. Nepārproti, es fanoju par loose-coupling, bet dažreiz kaut ko limitēt ir ne tikai vajadzīgs, bet pat nepieciešams. Kaut vai tāpēc, lai varētu izsekot "kura kretīna kods $x= true pārvērš par $x = WTFOBJEKTS?!11"... Tu idiotu tēlo un oftopiku dzen uz pilnu slodzi, jeb tikai brīvajā laikā? Edited October 23, 2012 by F3llony Link to comment Share on other sites More sharing options...
Recommended Posts