[ misk0 @ 06.05.2010. 08:14 ] @
dakipro:Cesto se spominje OOP stil pisanja tako sto se u jednu klasu samo skupe funkcije koje imaju veze sa nazivom klase, i povede se diskusija oko toga da li je to OOP, u ovoj temi cemo pokusati da odrzimo on-topic diskusiju na tu temu, sa novim a i vec postojecim postovima na forumu.


Citat:
mitke013: Naravno, pravi OOP, ne situacije kad programer potrpa gomilu funkcija sa brdom ulaznih parametara u neku klasu.


Mozes objasniti sta znaci ova gore recenica? Klasa mora imati funkcije (metode) sa parametrima, a ti kazes da to nije 'pravi OOP'??


[Ovu poruku je menjao dakipro dana 06.05.2010. u 11:34 GMT+1]
[ dakipro @ 06.05.2010. 08:28 ] @
Postoji stil rada gde se recimo sve funckije vezane za usere ubace u users "klasu" nazovi ga tako, ali se svaka funckija koristi pojedinacno, sa ili bez pravljenja objekta. Sto ce reci, postoji objekat $users, i postoje "metode" u tom objektu, i koriste se sa $users->create(); ali se svaka metoda tretira kao funkcija, pa onda to izgleda ovako: $users->create($username, $password, $userId, $currentTime,...) sto se na kraju uopste ne bi razlikovalo od toga da se to poziva i ovako Users::create(...) a to je vec obicna funkcija, kao recimo users_create(...);

Tada je users.class.php samo kontejner za funkcije koje se koriste kao kvazi metode, nema pravog OOP-a, sta vise nema OOP-a uopste, samo postoji objekat i metode. Svaka metoda je nezavisna i uopste nema veze sa objektom (ili je veza veoma veoma mala).


[Ovu poruku je menjao Goran Rakić dana 17.06.2010. u 13:13 GMT+1]
[ dakipro @ 06.05.2010. 10:30 ] @
Zeljkova poruka sa gore pomenutog linka, objasnjenje OOP http://www.elitesecurity.org/t396391-0#2569591

Citat:

mitke013:

OOP nije gomilanje funkcija na jedno mesto pa se to mesto nazove klasom. Objekat moze nesto da uradi, a ne samo da drzi funkcije; za tako nesto moze se koristiti i include fajla koji ce ih drzati. Najjednostavnije objasnjenje: tvoj program je komandir kasarne. Imas klasu vojnik, zastavnik, kapetan.... Tebi kapetan treba da organizuje jedan od visoko-intelektualnih zahteva tipicnih za vojsku; ciscenje piste, skupljanje lisca ili nesto slicno.

Code:

$captain = Captain::getAvailable() ;

Nema parametara. Klasa ce naci slobodnog kapetana tj. onaj koji je trenutno tu i nema zaduzenja.
Code:

$captain->cleanEverything() ;

Opet nema parametara. Kapetan ce dalje da organizuje taj posao. On ce naci slobodne vojnike na slican nacin i podeliti naredjenja. Pritom:
Code:

$soldier_1->cleanLeaves() ;
$soldier_2->cleanRanaway() ;
//itd

Vojniku treba metla; moglo je znaci i ovako:
Code:

$broom = Broom::getAvailable() ;
$soldier_1->cleanLeaves($broom) ;

Ali sto bi kapetan vojniku davao metlu; nije debil, moze i sam da je nadje. Pritom, ako jednog dana se kasarna modernizuje i dobije onaj kompresor sto oduva lisce, komanda vise nije validna. Ako se vratimo u programske vode, to znaci da bi svuda gde kapetan daje vojniku metlu ili nesto drugo, moralo da se promeni. Lakse je nauciti vojnika da se sam snadje:
Code:

class Soldier extends BasicMilitaryUnit
{
  public function cleanLeaves()
  {
    $cleaningDevice = $this->getCleaningDevice() ;
    // ocisti lisce koristeci $cleaningDevice 
  }

  protected function getCleaningDevice()
  {
    return Broom::getAvailable() ;
  }
}

Static metode je uvek lakse prepraviti nego dinamicke. Uvek ih je manje, a ako je protected, automatski znas da se ta metoda ne poziva ni sa jednog drugog mesta i da ne treba da juris kroz ceo program da proveris pozive.

Sve ove klase nasledjuju BasicMilitaryUnit klasu jer je za svo vojnicko osoblje identicno da treba da jedu, srede ujutru, obuju se, izadju na smotru itd. Da ne bi to isto pisali za svakog, lakse je staviti na jedno mesto.

Jos jedan primer nasledjivanja; u vojsci se belezi skoro svaki obavljeni posao. Posto to programer zna od pocetka, u svakoj metodi koja zahteva izvestaj na kraju ce pozvati:
Code:
  public function cleanLeaves()
  {
    $cleaningDevice = $this->getCleaningDevice() ;
    // ocisti lisce koristeci $cleaningDevice 

    $this->writeReport('Ocistio sam lisce') ;
  }

a BasicMilitaryUnit ima metodu:
Code:

abstract class BasicMilitaryUnit 
{
  protected function writeReport($report)
  {
    $name = $this->getName() ;
    $rank = $this->getRank() ;
   // snimi izvestaj koristeci tekst raporta, za ime i cin se metoda sama snasla
  }
}

OK? Nije; na ovaj nacin klasa vojnik prosledjuje fixni tekst. Ako se taj tekst negde snima (baza) i jednog dana tekst promeni, baza ce imati razlicite tekstualne vrednosti za isti posao. Bolje je:
Code:
  public function cleanLeaves()
  {
    $cleaningDevice = $this->getCleaningDevice() ;
    // ocisti lisce koristeci $cleaningDevice 

    $this->writeReport(Report::LEAVES_CLEANED) ;
  }

Sad se koristi konstanta iz klase Report. Neka je vrednost const LEAVES_CLEANED = 1 ; Mi ce tu vrednost da snimimo u bazu; na osnovu tog broja se tekst raporta moze menjati bez problema, lokalizovati itd.

Koliki posao oko obicnog lisca :)



[Ovu poruku je menjao Goran Rakić dana 17.06.2010. u 13:14 GMT+1]
[ Miroslav Ćurčić @ 06.05.2010. 11:16 ] @
Citat:
Postoji stil rada gde se recimo sve funckije vezane za usere ubace u users "klasu" nazovi ga tako, ali se svaka funckija koristi pojedinacno, sa ili bez pravljenja objekta

Ovo se zove "enkapsulacija" ( ala mrzim ove komplikovane tudjice :) ) i ovo jeste vrsta OOP-a.

To sto smo time iskoristili samo 10% onoga sto OOP pruza je sasvim druga stvar. Ako mi neko pokaze svoj projekat koji koristi samo enkapsulaciju i tvrdi da je koristio OOP, necu mu nista prigovoriti, jednostavno nisam toliki cistunac.

[ mitke013 @ 06.05.2010. 13:03 ] @
Dakipro je u pravu. Dopunio bih njegov primer sledecom idejom; npr. klase IntField i TextField bi nasledjivale abstract class BaseField() . BaseField() bi imala metodu isValid() koja bi iz child elemenata pozivala protected metodu validate() i vracala odgovor da li je polje validno ili ne. BaseField() bi takodje imalo metodu
Code:

abstract class BaseField()
{
  abstract protected function validate();
}

na taj nacin, ako je programer zaboravio da kreira metodu validate() u child klasi, PHP bi ga upozorio na to. Ovo je samo jos jedan primer zasto je OOP mnogo bolji od proceduralnog koda; nadogradnja je zaista izuzetno jednostavna.

Opet primer klasa mainDbObject() bi takodje imala metodu isValid() koja bi za sva polja skupljenih iz $this->initializeField metode, uradila validaciju i greske skupila u neki niz. Programer bi onda mogao sledece:
Code:

$user = new User() ;
$user->setValues($_POST) ;
if ( !$user->isValid() ){
    $errorStack = $user->getErrors() ;
    // ponovo prikazi formu zajedno sa greskama iz $errorStack niza
} else {
    $user->save() ;
    // prikazi poruku da je uspesno snimljen novi User
}


[offtopic]
Dakipro, da li koristis Doctrine ORM?


[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:33 GMT+1]
[ dakipro @ 06.05.2010. 13:44 ] @
Ne doctrine, ovako su me poducile starije kolege u firmi (Bratislav Dimitrijevic) kao jedan dobar pristup sa varijacijama na temu.
Do tada sam i ja radio sa "enkapsulacija" kako kaze Miroslav, tek sam onda uspeo da ustvari uvidim konkretnu upotrebu silne teorije oko nasledjivanja i ostalih oop ideja.
Sad, odakle je ideja, nisam siguran, i nije mi se svidela bila instant jer zahteva dooosta projektovanja u startu, pogotovu kad si ucio manje-vise proceduralno da razmisljas, ali sada kad pogledam prednosti, meni je ovo prava stvar.
[ Mister_rap @ 06.05.2010. 14:44 ] @
Citat:
Naravno, pravi OOP, ne situacije kad programer potrpa gomilu funkcija sa brdom ulaznih parametara u neku klasu.


Aj prvo mali back na prethodnu temu...

Ko je programirao proceduralno, zna koje su mane i uslovno receno prednosti istog.
Ako nisi recimo sibao u C-u, nema smisla da previse pricamo o ovome.

Nego gomila softvera je napisana proceduralno, i to kao sto sam ranije rekako nikako ne znaci da je softver lose projektovan, necitljiv i tako dalje.
Treba u razmatranje u tim situacijama ukljuciti niz faktora, vrijeme kad se neka aplikacija razvijala prvenstveno, kao i sam PHP kao jezik posto je ovo PHP forum jelete a PHP ako se ne varam pocinje da uvodi OO od verzije 4.

Postoji citava oblast koja se bavi dizajnom softvera, i koja je prilicno interesantna, stoga koga zanima ako nije citao neke knjige na tu temu neka baci pogled malo...

Sto se tice enkapsulacije nema nista lose u istoj, NAPROTIV, ako je koristis normalno, dakle sasvim validna stvar i prilicno prirodno "razmisljanje" za neke jezike. Ideja iste je mnogo drugacija nego njena najcesca primjena u OOP-u.

OOP danas je uglavnom sveden na pravilnu upotrebu design patterna, jer je za web MVC recimo totalno prirodna stvar.
Sa druge strane postoji taj problem DBM sistema, koji jelte ne cuvaju objekte, pa otuda potreba za OR mapperima tako da po mom misljenju tu ima dosta mjesta za inovacije, tj. vec sam probao neke od "njih" i jako sam zadovoljan prvenstveno samom idejom.

U PHP-u ljudi na tom polju najcesce prave greske, a da je mozda u pozadini neka druga tehnologija mozda ne bi uopste gledali ovaj kod i spominjali Doctrine :)

Koga zanima neka baci malo pogled na MongoDB.

Ps.
Sto se tice Doctrine-a, ja ga koristim odavno, prirodno je kad koristis hibernate da i u php-u koristis nesto slicno. Ali ima dosta razloga, zasto u nekim situacijama koriscenje OR mappera nije dobra solucija bez obzira na to koliko pojednostavljuje zivot programeru :D
[ kazil @ 06.05.2010. 23:20 ] @
Zar nije umesto one abstract klase interface namenjen za takve stvari? :) http://php.net/manual/en/language.oop5.interfaces.php

[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:34 GMT+1]
[ kazil @ 07.05.2010. 00:05 ] @
Malo da se nadovezem na onaj post sa vojnicima i liscem... Odmah u pocetku da razjasnim da ne smatram to losim nacinom, nego bih ja licno to drugacije napisao :)

Moj problem sa tim pristupom je $captain->cleanEverything(); meni ova metoda govori da ce kapetan da ocisti celu bazu, sto nije tacno. Kapetan moze da sakupi vojnike, da dodeli zadatke i da raspusti vojnike (je l' se tako kaze? sluzio sam civilno :P)

Na primer:
Code (php):

<?php

$captain = new Captain();
$duties = new Duties();
$soldier = new Soldier();

$captain->setServingSoldier($soldier); // ovo moze i drugacije, npr: new Captain(new Soldier());
$captain->assignTask($captain->getServingSoldier(), $duties->getNextTask());

$captain->getServingSoldier()->doTask();

while(!$captain->getServingSoldier()->isTaskFinished()) {
    $captain->yell();
}

$captain->releaseSoldier();

 


Tacno vidim ko je kome sta dodelio i ko je sta uradio - kapetan je postavio dezurnog vojnika, zadao mu zadatak, dok vojnik ne odradi zadatak, dotle se kapetan dere, posle je slobodan.

Opet napomena, na ovakav neki nacin bih ja licno resio problem ciscenja kasarne, nije jedini nacin, nije tacan nacin, svaki problem ima vise resenja, samo je potrebno naci najbolje resenje za dati problem (previse filozofiram za 1 ujutro, je l'? :P)
[ mitke013 @ 07.05.2010. 00:55 ] @
Citat:
kazil
Opet napomena, na ovakav neki nacin bih ja licno resio problem ciscenja kasarne, nije jedini nacin, nije tacan nacin, svaki problem ima vise resenja, samo je potrebno naci najbolje resenje za dati problem (previse filozofiram za 1 ujutro, je l'? :P)

Evo ti malo filozofije za pola dva ujutru :)

Stvar ukusa, ali mi se tvoje resenje ne svidja. Bez ljutnje. Linija
Code:
$captain->assignTask($captain->getServingSoldier(), $duties->getNextTask());

cini kod necitkim i ima 2 parametra. Ja zaista ne volim parametre; klasa se sama snalazi kako zna i ume.

Druga stvar:
tvoj program je komandant kasarne, bog i batina za sve. On kad kaze kapetanu da se sve ocisti, njega zaista ne zanima kako ce to biti uradjeno. Sto se komandanta tice, kapetan moze i sam da je ocisti, njega samo interesuje da posao bude obavljen. Detalji ga ne zanimaju; vojska (prava) zaista tako funkcionise i zato ima jako malo propusta. Zamisli da komandant brine o nabavci toalet papira (zadatak cate), emotivnim problemima Laze iz izvidjaca (zadatak psihologa), pokvarenoj hrani (dezurni oficir menze) i buvama iz cebadi (problem se ignorise)...

Ako ti u programu na isti nacin dodelis zadatke, program je daleko pregledniji. Dok tvoja verzija ima ~10 linija i tvoj komandant mora da se brine cak i o pojedinacnom vojniku (sto komandant NIKAD ne radi), moja verzija ima samo
Code:

$captain = Captain::getAvailable() ;
$captain->cleanEverything() ;

Sto je ipak daleko preglednije. Ili cak perverzija:
Code:

Captain::getAvailable()->cleanEverything() ;


Citat:
Tacno vidim ko je kome sta dodelio i ko je sta uradio - kapetan je postavio dezurnog vojnika, zadao mu zadatak, dok vojnik ne odradi zadatak, dotle se kapetan dere, posle je slobodan.

Tvoj kontroler (komandant) zaista nema potrebe da zna koji je vojnik ucestvovao u ciscenju; tvoj primer bi onda ukljucio da komandant licno mora da isporuci metlu tom vojniku. Ako bas mora da zna ko su oni kako bi ih nagradio, uvek mozes ovo:
Code:

$captain->awardBestSoldiers(2) ;

gde je parametar koliko vojnika da dobije nagradu, default vrednost je da kapetan sam odluci. Kapetan ce sam odluciti koliko nagradnih dana ce podeliti tim vojnicima na osnovu drugih parametara; aljkavosti, drzanju, izvrsavanju drugih zadataka itd...

Nadam se da me razumes. Ocekujem tvoj odgovor za moje jutarnje razgibavanje mozga :)


Citat:
Zar nije interface namenjen za takve stvari? :) http://php.net/manual/en/language.oop5.interfaces.php

Da, u pravu si, interface je najbolja stvar za ovako nesto.

[ kazil @ 07.05.2010. 09:09 ] @
Po meni je ta linija bas zbog toga citkija, zato sto prima parametre :) tacnije, jer po imenu metode tacno znam sta ta metoda radi i nad kojim elementima radi to sto radi. 2-4 parametra je po meni jos ok, ako prima vise, mozda metoda zeli previse da uradi :)

Mozda moj nacin nije najbolje objasniti na primeru kasarne, jer u pravoj vojsci stvarno kapetana ne interesuje ko ce i kako da ocisti, vec samo da se sve cakli. Briga kapetana da li vojnik ima metlu ili nema. Moja metoda, ako joj treba nesto da izvrsi zadatak i to nesto joj nedostaje, baca Exception, a pozivajuci kod se stara da uhvati taj Exception i dalje odlucuje sta treba da se uradi. Vojnik ako baci Exception moze samo da nagrabusi :D

Uglavnom, idem principom da jedna metoda radi jedan zadatak (iako mi to ne polazi uvek za rukom, nisam ja tamo neki guru, jel, i dalje ucim :)). Ako vojnikova metoda clean() mora da se brine i o nabavku opreme za ciscenje, da odluci da li mu treba metla ili cetka za wc, da se raspita gde treba to da nabavi, eventualno da ceka dok se neka oprema ne oslobodi, pa tek onda da ocisti... Jeste kod koji to poziva citkiji, ali pozvani kod je vec... Ugh. Previse if-ova :)

Prednost ovog nacina: unit testing. Tacno mogu zasebno svaki deo koda da testiram bez da moram da brinem o jos malom milionu delova koda koji su zapravo samo sakriveni unutar metode koju testiram da bi test prosao ili pao i usput da testiram kako vojnik ocisti lisce ako mu dam metlu ili ako mu dam duvalicu za lisce.

Predlazem da se pogleda predavanje Miško Hevery-a, mnogo covek zna znanje: http://robertbasic.posterous.c...k-series-presents-oo-design-fo (mislim da bas u ovom videu prica o naplati sa kreditnim karticama, koji je odlican primer zasto treba napraviti separation of concerns).
Meni su licno njegova predavanja najvise promenili nacin razmisljanja i pisanja koda (ne zato sto je on rekao da tako treba da se radi, nego sam uvideo prednosti takvog nacina).
[ Predrag Supurovic @ 07.05.2010. 13:35 ] @
@mitke013: Iako se generalno slazem sa tobom, ipak ne bih isao dotle da mi broj parameterab due kriterijum dali je neki OOP dobar ili nije. Odredjena funkcija da bi odradilaposao treba odredjen broj ulaznih parametara. Ako te parametre moze sama da procita, onda ih ne treba navoditi.

Ovaj primer sa $kapetan->ocistiSve() ne pokazuje da je broj parametara bitan faktor. To je funkcija koja samo maskira gomiluprocesa koji mroaju da se obave. ciscenej svega podrazuemva ciscenje mnogo cega a to ukljucuje i razlicita sredstva za ciscenje, broj ljudi koji treba da to rade, razlicite objekte ciscenja koji se ciste na siti nacin, i slicno. Za svaki taj razlicit posao ciscenja mora postojati neki poseban metod koji ga obavlja i svaki daj metod, opet, ima neke svoje ulazne parametre.

Sve u svemu, nakupi se tu mnogo ulaznih parametara, samo treba pameno proceniti do kojih metod moze sam da ddoje a koji mu se moraju proslediti spolja. Pri tom, broj parametara zavisiod funkcije koju metod obavlja a ne od toga dali se to nekome svidja, cini mu se citkijim ili smatra daje to OOP.

Upravo je moc OOP pristupa u parametrizaciji poslova tako da jedan isti metod moze da radi vise poslova na osnovu parametara koji mu se prosledi. Recimo u ovom primeru metod $kapetan->ocistiSve() bi recimo mogao da unutar sebe kreira objekat $cistac koji bi u stvari znao da cisti sve, a cisti ono sto mu se kaze - kroz parametre. $vojnik ne mora da zna da cisti, vec je dovoljno da zna da upotrebi $cistac pa ce ocistiti sve sto mu bude naredjeno a $cistac ume.



[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:37 GMT+1]
[ misk0 @ 08.05.2010. 14:17 ] @
Nisam neki guru OOP-a, koristim ga mozda i manje ,sticajem okolnosti, nego sto bih htio ali ne vidim i dalje opravdanje za koristenje metoda bez parametara zbog toga sto 'to nije pravi OOP'. Ne kazem da sam u pravu, ali bih htio dobiti kakve reference (uputstva, dokumente) gdje je receno da se to mora izbjegava.
Mislim da je OOP u Java jako dobro rjesen ali tako jako puno objekata ima more metoda koje su override-vane sa razlicitim parametrima i tako dozvoljavaju da zapravo jedan metod radi zapravo isti posao ali u razlicitim okolnostima.

To sto ce se metoda sama snaci moze znaciti i rasipanje resursa, u smislu gore pomenute vojske. Recimo:
- Kapetan trazi da je kasarna obrisana
- Klasa vojnik ima metod 'clean' ali ne zna cime (jer nema parametara.
- Vojnik instancira novu metlu (pod uslovom da postoji u bibliotekama)
- Ocisti, oslobodi metlu
- Kapetan pogleda i kaze 'nije dobro, ajd ponovo'
- Vojnik ponovo instancira metlu, ocisti , oslobodi
...

Ovde vidim nekoliko nedostataka:
- zar ne bi bilo bolje prije ciscenja instancirati metlu i drzati je postojecom dok ne budemo sigurni da nam vishe ne treba.
- metla negdje mora postojati definisana, sta se desava ako vojnik ne moze pronaci metlu - moras napraviti okruzenje, bez toga da znas sve detalje (jer nemas parametara) i nadati se da ce ta metoda raditi. Ne saljes joj parametre pa moras pratiti exceptione i gledati sta joj fali.

Mislim da je ovde i (moj, subjektivni) trip oko toga 'drzati stvari pod kontrolom'. Jer ako ja nekoj metodi posaljem 'ocisti' ja ne znam kako ce ona ocistiti i cime ce, ali znam/nadam se da ce posao biti zavrsen. Ali ako joj recimo posaljem 'ocisti metlom i vrati je kad zavrsis' znam da sam joj obezbjedio sve potrebno i da ce zavrsiti posao.
Kazem opet, to je sve IMHO, ucim i naucicu sta je bolje ali argument 'to ti nije pravi OOP jer ima 3 parametra' mi ne pije bas vodu.
[ mitke013 @ 08.05.2010. 16:43 ] @
Citat:
misk0: Nisam neki guru OOP-a, koristim ga mozda i manje ,sticajem okolnosti, nego sto bih htio ali ne vidim i dalje opravdanje za koristenje metoda bez parametara zbog toga sto 'to nije pravi OOP'. Ne kazem da sam u pravu, ali bih htio dobiti kakve reference (uputstva, dokumente) gdje je receno da se to mora izbjegava.
Mislim da je OOP u Java jako dobro rjesen ali tako jako puno objekata ima more metoda koje su override-vane sa razlicitim parametrima i tako dozvoljavaju da zapravo jedan metod radi zapravo isti posao ali u razlicitim okolnostima.


Ne znam javu, samo sam vrlo malo citao o njoj, ali sam ukapirao da su sve te klase multi-praktik. Zato i moraju da imaju mnogo parametara jer ta klasa zaista ne moze da ti procita misli. Ok, ovo je neko moje vidjenje stvari, mozda gresim jer nisam radio u javi, ali me podseca na programiranje u c-u; svaka funkcija operativnog sistema, cak i ispis obicnog teksta, se prilicno zakomplikuje.

Kod php-a, ti znas unapred da ce vojnik da ocisti lisce, pusku, ponekad mozda i da puca... Da da, vojska nije samo ciscenje i pranje Zato ti i nisu potrebni ulazni parametri; procitaj opet moje objasnjenje i vidi sa koliko malo linija koda ti zavrsavas posao. protected metoda je ta koja ce da se pobrine oko nabavke metle.

Vrlo je bitno da public metode nemaju parametre ili imaju jako malo. Odrzavanje i prosirivanje programa je mnogo lakse jer ce ti API biti nepromenjen. Zamisli da imas metodu sa npr. 3 parametra koja se poziva sa vise mesta; ti prosiris tu metodu, automatski moras da menjas kod SVUDA gde se ta metoda poziva. Da li me sad razumes?

Citat:

- Klasa vojnik ima metod 'clean' ali ne zna cime (jer nema parametara.

Ovo sam vec objasnio.
Citat:

- Vojnik instancira novu metlu (pod uslovom da postoji u bibliotekama)

Class Broom ce da postoji u svakom slucaju, bez obzira da li ce vojnik sam da je uzme ili kapetan da mu je da.
Citat:

- Ocisti, oslobodi metlu

I to vojnik sam radi. U pravoj vojsci (ne civilnoj) niko nikome nije mama pa da mu daje metlu, ciste carape, ociscenu pusku itd. Vojnik mora sam da se snadje, nema tamo mame koja ce sve da radi za njega. Zbog tog nacina rada, u vojsci skoro nikad nema ispada.
Drugo; tom podelom rada, tacno se zna ko je pogresio.
Citat:

- Kapetan pogleda i kaze 'nije dobro, ajd ponovo'
- Vojnik ponovo instancira metlu, ocisti , oslobodi
...

Kapetana samo interesuje da posao bude obavljen. Sto se njega tice, vojnik moze i cetkicom za zube da ocisti lisce. Ali.... ovo je ipak programiranje; ako ces ti u kontroloru/action klasama (prouci MVC) da radis sve to sto u stvari treba metode da rade... pa gde je tu onda OOP?
Citat:

Ovde vidim nekoliko nedostataka:
- zar ne bi bilo bolje prije ciscenja instancirati metlu i drzati je postojecom dok ne budemo sigurni da nam vishe ne treba.
- metla negdje mora postojati definisana, sta se desava ako vojnik ne moze pronaci metlu - moras napraviti okruzenje, bez toga da znas sve detalje (jer nemas parametara) i nadati se da ce ta metoda raditi. Ne saljes joj parametre pa moras pratiti exceptione i gledati sta joj fali.

Zasto vojnik ne bio nasao metlu? new Broom() ce uraditi to za tebe.
Citat:

Mislim da je ovde i (moj, subjektivni) trip oko toga 'drzati stvari pod kontrolom'. Jer ako ja nekoj metodi posaljem 'ocisti' ja ne znam kako ce ona ocistiti i cime ce, ali znam/nadam se da ce posao biti zavrsen. Ali ako joj recimo posaljem 'ocisti metlom i vrati je kad zavrsis' znam da sam joj obezbjedio sve potrebno i da ce zavrsiti posao.
Kazem opet, to je sve IMHO, ucim i naucicu sta je bolje ali argument 'to ti nije pravi OOP jer ima 3 parametra' mi ne pije bas vodu.


To i jeste poenta; tebe ne zanima kako ce stvar biti obavljena, sve dok je ona obavljena. Ako izbacimo vojsku iz price, razmisljaj ovako: tvoj program i njegove klase imaju neki API. Ako metode nemaju parametre, API se nece narusiti. Ako dodas brdo parametara, nikad neces zavrsiti program, API nije stabilan i niko ziv se nece snaci u tvom programu.

Ali ako dodajes samo protected metode, API je i dalje isti. Nadam se da me razumes; objekat moze nesto da uradi, ne samo da drzi metode. Enkapsulacija je i dalje proceduralni kod koji se ponavlja i ponavlja i ponavlja.... cemu to?

Ako ti ne ide ovo, probaj sledece; napisi neki program koji ce slediti moju logiku. Koliko god te vuklo, odupri se tome da metode imaju parametre. Kad zavrsis kod, videces da sam bio u pravu.

U medjuvremenu, pogledaj onaj video klip sto sam postovao; jeste kvalitet los, ali ces videti prednosti mog nacina rada.
[ misk0 @ 08.05.2010. 23:47 ] @
Citat:
mitke013:Ne znam javu, samo sam vrlo malo citao o njoj, ali sam ukapirao da su sve te klase multi-praktik. Zato i moraju da imaju mnogo parametara jer ta klasa zaista ne moze da ti procita misli. Ok, ovo je neko moje vidjenje stvari, mozda gresim jer nisam radio u javi, ali me podseca na programiranje u c-u; svaka funkcija operativnog sistema, cak i ispis obicnog teksta, se prilicno zakomplikuje.

Kod php-a, ti znas unapred da ce vojnik da ocisti lisce, pusku, ponekad mozda i da puca... Da da, vojska nije samo ciscenje i pranje Zato ti i nisu potrebni ulazni parametri; procitaj opet moje objasnjenje i vidi sa koliko malo linija koda ti zavrsavas posao. protected metoda je ta koja ce da se pobrine oko nabavke metle.

Vrlo je bitno da public metode nemaju parametre ili imaju jako malo. Odrzavanje i prosirivanje programa je mnogo lakse jer ce ti API biti nepromenjen. Zamisli da imas metodu sa npr. 3 parametra koja se poziva sa vise mesta; ti prosiris tu metodu, automatski moras da menjas kod SVUDA gde se ta metoda poziva. Da li me sad razumes?


Objektni pristup problemu u sustini ne bi trebao da se razlikuje od jezika do jezika. Bar mislim..
Java (a ne samo Java) radi method overloading, to znaci imas metode:
- clean()
- clean(metla)
- clean(aspirator)
...
Znaci na osnovu poslatih (ili ne) parametara poziva se razlicita metoda, a to je za korisnika te klase poprilicno transparentno. I uglavom unutrasnja struktura se svodi na jednu kljucnu metodu koja radi posao ali ima tone parametara i kad ti recimo pozivas clean() instancira metlu i zove clean(metla) metodu. Dobijas veliki code reusability, smanjujes greske i znas sta se radi.
Mozes clean metodu pozvati sa i bez parametara, mozes je sutra prosirivati sa novim parametrima recimo clean(metla, koliko_puta) i neces narusiti backward compatibility.
Moguce je to koristiti i u PHPu (od verzije 5), ali nije bas 'fino uradjeno' vec moras da malo 'pletes' i da koristis magic methods. Dinke je napisao dobar clanak o tome

Citat:

Class Broom ce da postoji u svakom slucaju, bez obzira da li ce vojnik sam da je uzme ili kapetan da mu je da.


Gdje postoji? U drugoj biblioteci. Sta ako je nisi stavio dostupnom i klasa clean je trazi i ne dobija i onda ti salje exception. Sta ako ja hocu crnu metlu a ne bijelu, ne zove se Broom, vec NewBroomUltra..? Ako metod clean(metla) dobija parametar kao alat, tu je moja odgovornost da m usaljem alat koji ima metod 'doCleaning', a od kojeg proizvodjaca, koje boje, ja mislim o tome.

Objekt Metla mora biti dostupan u okruzenju i ako ga nema metod clean nece moci uraditi nista. A ako ja, prije nego pozovem vojnik->clean(metla) instanciram objekat metla = new metla(); znacu sigurno da ce biti i cime ociscena kasarna.

I dalje mi nisi dao odgovor: gdje pishe da public metodi ne smiju imati (da nije preporucljivo) vishe od jednog parametra? PHP nije izmislio OOP pristup i uveo ga je tek prije par godina, tako da i nije neka referenca.



[Ovu poruku je menjao Goran Rakić dana 17.06.2010. u 13:19 GMT+1]
[ deerbeer @ 09.05.2010. 08:55 ] @
Citat:

Objektni pristup problemu u sustini ne bi trebao da se razlikuje od jezika do jezika. Bar mislim..
Java (a ne samo Java) radi method overloading, to znaci imas metode:
- clean()
- clean(metla)
- clean(aspirator)
...
Znaci na osnovu poslatih (ili ne) parametara poziva se razlicita metoda, a to je za korisnika te klase poprilicno transparentno. I uglavom unutrasnja struktura se svodi na jednu kljucnu metodu koja radi posao ali ima tone parametara i kad ti recimo pozivas clean() instancira metlu i zove clean(metla) metodu. Dobijas veliki code reusability, smanjujes greske i znas sta se radi.

Mozes cak da iskoristis polimorfizam , da clean metoda prihvata samo jedan parametar i da postignes isti efekat
a to je da metoda prihvati apstraktni ili bazni objekat alatke za ciscenje , tako da neka njena override metoda
ce odraditi posao za svaku vrstu alatke za ciscenje .

A kasnije je lakse odrzavanje koda , ne moras dodati novu overload metodu za ciscenje (clean() ),
vec napises novu klasu alatke sa override metodom koja nasledjuje baznu i prosledis je kao parametar clean metodi.
A dodatni parametri za ciscenje (ako su potrebni) mogu se proslediti konstruktoru tog novog objekta alatke .

[ mmix @ 09.05.2010. 12:49 ] @
Da probam da se dotaknem nekih stvari koje ste pomenuli u temi, dosta skacete naokolo pa mozda nisam stigao da pohvatam sve detalje:


- "Naravno, pravi OOP, ne situacije kad programer potrpa gomilu funkcija sa brdom ulaznih parametara u neku klasu."
Evolucijom programiskih jezika i sto je najgore apsrtakcijom dosta se zaboravilo "ZASTO" su uopste OOP jezici preuzeli primat nad proceduralnim. Back to the basics, OOP je dobar ne zato sto je dobar programerima vec zato sto je dobar projektantima, omogucava modelovanje entiteta i interakcija izmedju entiteta tokom vremena i omogucava projektantu da programeru prenese model u tom obliku koji ce bez velikih operativnih problema biti prenesen u kod. Bez OOPa skoro ceo UML mozes da bacis u kantu. U tom konceptu klasa kao drzac statickih metoda nije OOP jer ne predstavlja entitet, entitet istina definise klasa ali entitet moze da postoji samo kao instanca. Trpanje statickih funkcija u neku klasu moze da pomogne programeru za bolje citanje sorsa ili jednostavno mora da se uradi tako jer standalone funkcije nisu dozvoljene (kao u CLRu) ali nisu OOP jer nemas instancu (objekat). Isto tako pretvarati staticke metode u instance metode iako ne menjaju state instance samo da bi bilo OOP je "varanje" i to nije enkapsulacija.

- Interfejs kao OOP
Zaboravljate da je spisak public elemenata klase UVEK default interfejs i kao takav ispunjava modelovani contract. Instanca klase je njen state + njen default interface stoga su interfejsi kao OOP pojam nezaobilazni. Medjutim, dodatni interfejsi kao interfejsi postoje da bi se omogucilo da jedna klasa apsktraktno servira vise contracta koristeci enkapsulaciju, nista manje, nista vise.

- parametrizacija metoda.
Ovo je malo tricky pitanje i vise je vezano za modeling nego za coding praksu. Vas primer sa kapetanom i vojskom je viseznacan iz prostog razloga sto vam je model nekompletan i zbog toga postoji ambiguity oko toga ko, kako i cime i treba da cisti (sto btw u vojsci predstavlja smrtni greh ). Ako biste recimo model poceli od kasarne i uveli sve zakljucno sa sredstvima u model onda bi kroz instancijaciju oficiria, vojske, prostorija, sredstava, itd u trenutku ciscenja ZNALI kroz objektnu hijerarhiju koji kapetan komanduje kojom vojskom, ko je zaduzen za sredstva i koja i koliko sredstava postoji. Onda moze da se uradi commander.getClosestCaptian().CleanAll() ili slicno i tu onda implementacija Clean() moze da enumerise raspolozive vojnike, delegira naredjenje za akvizicju sredstava i obavljanje posla. Sa druge strane implementacija CleanAll() ce verovatno morati u svom toku da koristi parametre u komunikaciji sa vojskom. Isto tako, vojna doktrina nalaze da se izdavaoc obavesti o izvrsenom naredjenju, ako kapetan ima vise nadredjenih kako ce znati ko je izdao naredjenje i kome da raportira? U realnosti identifikacija se obavlja implicitnim prepoznavanjem lika/glasa komandujuceg oficira, u OOP modelu nema implicitnog, tako da ostaje pitanje kako kapetan da zna i najlakse resenje bi bilo da CleanAll ima potpis CleanAll(Officer orderIssuingCommander)

Bez tog modela sve je podlezno razlicitim interpretacijama koje ste i izneli, moze ovako a moze i onako i po meni je rasprava koji je bolji bespredmetna jer nijedan ne valja zato sto model ne valja.
[ deerbeer @ 09.05.2010. 13:25 ] @
Citat:

Instanca klase je njen state + njen default interface stoga su interfejsi kao OOP pojam nezaobilazni.

E sad je skakljivo pitanje koliko je taj "state" objekata klase stvarno upotrebljiv u "stateless" protokolima

[ mmix @ 09.05.2010. 13:38 ] @
Ko jos pravi stateless web aplikacije :)
Protokol je stateless ali su web aplikacije itekako statfull, peko DOMa, state-a input polja do serijalizovanih server side stateova. To nije izgovor ;)
[ mitke013 @ 09.05.2010. 13:47 ] @
Citat:
misk0: Nije klasa clean, vec je metod clean koji trazi klasu /objekat Metla koja je definisana negdje van objekta vojnik. Objekt Metla mora biti dostupan u okruzenju i ako ga nema metod clean nece moci uraditi nista. A ako ja, prije nego pozovem vojnik->clean(metla) instanciram objekat metla = new metla(); znacu sigurno da ce biti i cime ociscena kasarna.

Ne bih htio da se ljutis i pizdis, nema potrebe, diskutujemo, ja mozda nesto ne znam i trazim da mi se objasni.

@deerbeer: da, i to je rjesenje recimo.


Ok, nisi me razumeo. Probaj ovo da zamislis:

u tvom programu, na 12 mesta se poziva metoda metoda $soldier->cleanLeaves($broom) ;
Ovo je samo primer i lako se moze desiti u normalnom programiranju da se toliko puta, pa i vise, pozove neka metoda.

Elem; umesto parametra $broom koji je instance NEKE metle (nije vazno koje), ti zelis da vojnik sada ocisti lisce koristeci kompresor. To znaci da ces 12 puta morati da menjas gornju liniju u $soldier->cleanLeaves($leafBlower) ;

Sporo suvise i veeeeoma lako moze da ti neki poziv promakne.

Al ajde da se primeni moja logika; vojnika naucis da uzme sam neophodni alat; jedna metoda se samo menja, ne 12++ poziva.

[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:41 GMT+1]
[ mmix @ 09.05.2010. 15:50 ] @
Ako pricamo o tih 12 instanci poziva koje planiras da izvedes bez parametara da "olaksas sebi zivot", to pretpostavlja da vojnik ima pokrivene sve scenarije odabrira jednog sredstva iz svih mogucih kombinacija raspolozivih state-ova magacina sredstava, zar ne.

Tvoji testovi, da bi bili kompletni, moraju da testiraju za sve upotrebne kombinacije magacina i svaki moguci odabrani alat. A ako testiras postupak ciscenja za svako moguce odabrano sredstvo to je isto kao da si testirao i parametrizovani metod za sve moguce ulazne parametre. Jel sad jasnije? Krateci testove ti si napravio pretpostavku kako ce magacin da izgleda i ako on ne izgleda tako imas netestiran scenario, zamazao si sefu oci sa "imam test" nad skrivenom metodom koja ne puca na tvom pretpostavljenom magacinu, a bagove, to nek resava kupac ili Q&A, jel tako? "Assumption is the mother of all fuckups"

Vidis interni state objekta je uvek parametar svakog instance metoda (predstavljeno kroz interni skriveni parametar, this npr) i tvoje testiranje mora da ukljuci taj state kao parametar. Dalje, da ti jos zakomplikujem zivot, u sorsu taj tvoj Clean() metod bi mogao da se refaktoruje na kod koji bira sredstvo i onda poziva Clean(sredstvo) specijalizaciju, sto te vraca na prvi korak. Dakle, ako nemas toliko testova, opet si zabusavao i koristio black-box prirodu metode da pokrijes potencijalne rupe Sto nas vodi ka trecem, testiranje i TDD takodje nije kompenzacija za dobar dizajn.

I da ja priupitam, zasto je ova tema u PHP forumu kad se tice teorije programiranja, zar nije AoP bolje mesto?



[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:45 GMT+1]
[ iizuzetan @ 09.05.2010. 21:50 ] @
Glavni problem je sto vecina ne shvata zasto uopste koristiti OOP. Naime, nije cilj OOP eto samo zato da bi pratili neke trendove vec da olaksa programiranje i buduce lako dogradjivanje i menjanje sajta ili programa.

Znači u suštini glavna poenta OOP je da se uoče lepo karakteristični objekti i da se lepo razvrstaju po klasama kako bi se izradio efikasan sajt sa što manje objekata i klasa.

Dobro odradjen oop je onaj da kad bilo sta hocete da dogradite ili promeniti dogradjujete to ili menjate samo na jednom mestu. Ako se desi da prilikom neke dogranje ili menjanja morate pisati na vise mesta onda niste dobro odradili OOP.
[ jablan @ 09.05.2010. 23:15 ] @
Ja ne znam za vas, ali meni se mozak isključuje čim vidim OOP primere na bazi automobila, vojnika itd. Uvek mi je bilo skroz strano da učim programerske koncepte na modelima koji najverovatnije nikad neće biti praktično modelirani i implementirani u nekom softverskom projektu (barem ne na taj način i sa tim i takvim metodama...) :)

Inače je zanimljiva tema, kako PHP programeri shvataju OOP... :)
[ mmix @ 10.05.2010. 07:57 ] @
Ne budi toliko siguran, ja sam modelovao vojnike i oficire i subclasovao ih Kad sluzis vojsku programiranjem onda pises programe za vojsku Doduse kasarne nisam modelovao, ipak je to bio program za godisnje odmore i odsustva

A inace, da, zanimljivo je citati. Verovatno zato tema i nije u AoP, mislim da im se ne bi svideli odgovori koje tamo dobiju Ocigledno je da se OOP ovde dozivljava kao problem, ne kao bonus.

Citat:
@iizuzetan: Dobro odradjen oop je onaj da kad bilo sta hocete da dogradite ili promeniti dogradjujete to ili menjate samo na jednom mestu.

Pogresno, i programer-centricno, dobro odradjen OOP je onaj koji sto vernije modeluje realnu situaciju koju implementira program. Projektant mora da ima slobodu da menja model u skladu sa promenama zahteva, ti sa druge strane kao programer to treba da implementiras, zato je dobar refaktoring alat najbolji prijatelj jednog programera.


[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:44 GMT+1]
[ iizuzetan @ 10.05.2010. 09:46 ] @
Po meni jedino sto se moze postici OOP je to da se jako efikasno organizuje nasledjivanje a funkcijskim programiranjem da bi ste ostvarili nasledjivanje trebate zvrsiti gotovo celu reorganizaciju programskog KOD-a.

Znaci ajde nabroj ti onda sta to moze OOP a sto ne moze funkcijsko programiranje, pa ce te onda i lakse shvatiti kad, gde, zasto i kako koristiti OOP.

[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:47 GMT+1]
[ deerbeer @ 10.05.2010. 10:09 ] @
Nasledjivanje jeste jedan od prednosti OOP-a ,ali uopste nije najvazniji i JEDINI ,
cak u nekim slucajevima razbija enkapsulaciju ako se zluopotrebljava i koristi nasiroko i na svakom mestu .

Sve veze izmedju objekata/ klasa koje organizujes u programu mogu se svesti na tri nacina :
IS - nasledjivanje
USING - jedan objekat koristi drugi kroz neku od svojih metoda
i HAS - jedan objekat sadrzi drugi i njegov 'zivotni vek' je odredjen prvim

U dobro organizovanim projektima prednost se uvek daje vise apstraktnim interfejsima i
kompoziciji objekata (USING i HAS vezama ) nego samom nasledjivanju .



[ mmix @ 10.05.2010. 10:13 ] @
OOP je OBJEKTNO orijentisano programiranje, ne NASLEDNO orijentisano programiranje
Ne-apstraktna sealed klasa koja nikog ne nasledjuje ali ipak implementira neki entietet je savrseno validno OOP. Ja razumem tvoj post, to je razmisljanje bazirano na lone-wolf praksi i teoriji koja kaze da je OOP code laksi za upgrade. Cinjenica medjutim je da se refaktorizacija koda obavlja veoma veoma cesto i da OOP tu ne pomaze apsolutno ni malo.


[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:48 GMT+1]
[ deerbeer @ 10.05.2010. 11:04 ] @
Citat:

OOP je OBJEKTNO orijentisano programiranje, ne NASLEDNO orijentisano programiranje

E , a kad vidim negde klasa A nasledjuje B nasledjuje C nasledjuje D .. i jos ti kaze
neko da je to 'suvi' OOP digne mi se kosa na glavi :D
[ mmix @ 10.05.2010. 11:39 ] @
Pa nekad je tako i bilo, kad je OOP bio nova i hip stvar Sto vise nasledjivanja to bolje, ako moze i visestruko, jos bolje ako niko sem tebe ne razume to je premium bonus . Nasledjivanje je tada i vidjeno upravo kao spas za ono sto iizuzetan prica, sa ove distance naivno verovanje da ce modifikacije na base klasi automatski propagirati promenu ponasanja naslednika bez potrebe za dodatnim modifikacijama u naslednicima. Medjutim, to nije ispalo tako iz dva razloga, kao prvo to zahteva veoma poseban i rigorozan stil programiranja u kome je funkcionalnost naslednika uvek DODATAK na funkcionalnost baze i da se taj odnos nece menjati u buducnosti, takav monaski stil programiranja retko ko praktikuje i prilicno je rigidan za promene. Drugo, funkcionalno mnogo je realnija situacija u kome specijalizovani entitet ima neku funkcionalnost UMESTO funkcionalnosti bazne klase cime se uprkos naslednoj liniji prekida funkcionalna doslednost (prosto receno sve zavisi da li, kako i kada pozivas inherited metod, ako ne pozoves uopste nevazna je promena u bazi tj ako promena obuhvta i specijalizaciju mora da se iskodira posebno za svaku specijalizaciju). Ne kazem naravno da je nasledjivanje postalo irelevantno u OOPu, sta vise polimorfizam je i dalje veoma jak instrument u u potrebi klasnih hijerarhija za npr. agregatne operacije, kao target za template (generics) specijalizaciju, ORM alati i dalje mapiraju flat podatke u klasne hijerarhije, itd, itd. Medjutim suprotno uvrzenom verovanju, nasledjivanje nije uopste nesto sto smanjuje kod i njegovo odrzavanje, bili su neophodni refaktoring alati da popune tu supljinu.
[ Nikola Poša @ 10.05.2010. 11:41 ] @
Citat:
mmix: I da ja priupitam, zasto je ova tema u PHP forumu kad se tice teorije programiranja, zar nije AoP bolje mesto?

Ja mislim da je ova tema sada u potpunosti otišla van domena PHP foruma...
[ mitke013 @ 10.05.2010. 12:18 ] @
Citat:
@iizuzetan: Dobro odradjen oop je onaj da kad bilo sta hocete da dogradite ili promeniti dogradjujete to ili menjate samo na jednom mestu.

Pogresno, i programer-centricno, dobro odradjen OOP je onaj koji sto vernije modeluje realnu situaciju koju implementira program. Projektant mora da ima slobodu da menja model u skladu sa promenama zahteva, ti sa druge strane kao programer to treba da implementiras, zato je dobar refaktoring alat najbolji prijatelj jednog programera.


Ne, iizuzetan je u pravu, 100%. Posto uvek dajem primere, evo ti jos jedan:
trenutno radim na programu i 5 objekata deli zajednicku metodu isRateable(). Ona treba da vrati true/false u zavisnosti od 3 parametra: stanje $_COOKIE-a, da li je korisnik ulogovan i da li postoji setovan tag rateable(nije bitno sta je).

I svuda gde se iscrtavaju zvezdice za glasanje, pre toga stoji
Code:

{if $object->isRateable()}
// iscrtaj zvezdice
{/if}...


Juce sam tu metodu prosirio da onaj koji je kreirao taj objekat, ne moze da glasa za njega. Gde sam to uradio? Pa samo u toj metodi isRateable; ostatak programa nisam ni pipnuo.
Kako sam to uradio? Tu metodu sam prosirio tako sto sam unutar nje ubacio sledeci kod:
Code:

return $this->rateable 
        && !isset($_COOKIE[strtolower(get_class($this)) . '_' . $this->id]) 
        && User::isUserLogged() 
        && $this->getUser()->id != User::getLogged()->id ;  // ovo je nova linija


Posto svi objekti vec imaju getUser(), ja sam dodao SAMO jednu liniju u isRateable() i sprecio da korisnik koji je kreirao Playlistu, Album, Song i Event glasa za njih.


Citat:
KAKO ce vojnik da uzme leafBlower iz magacina sredstava ako trenutno u njemu nema istih? Znaci postoji logika odabira koja ZAVISI od TRENUTNOG stanja magacina sredstava, samim tim STANJE magacina sredstava je tebi skriveni parametar za cleanLeaves(),


Da, naravno! Zato sam i rekao; vratice false ako ne moze da nadje metlu a u svoj errorStack moze da stavi i razlog zasto POSAO nije obavljen. Vec sam rekao ali ponovicu; kad pozovem Doctrine-ovu metodu isValid() , mene samo zanima da li je objekat validan ili ne. Ako me interesuje zasto nije, pitacu ga sa $soldier->getErrorStack(). Ili smatras da ni programer Doctrine ne zna OOP?



[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:50 GMT+1]
[ mmix @ 10.05.2010. 12:19 ] @
Pa dotice se donekle. Moji postovi i sluze da vam pokazu koliko je u stvari PHP daleko od koncepta OODa i uopste OOPa kao njegovog instrumenta. Nije mi cilj da omalovazavam PHP ali ni vi bas niste sigurnio sta vam to OOP donosi u PHP sto je tako fundmentalno drugacije i onda se hvatate za pojedinacne aspekte OOPa i promovisete ih iz posledice u uzrok i razlog zasto su vam neophodni. Pocnimo od toga koliko vas serijalizuje PHP objekte i deserijalizuje pri svakom pozivu? Koliko koristite polimorfizam u svojim PHP projektima?Imate li modele z svoje hijerarhije ili je sve onako odokativno ad-hoc?

[ mitke013 @ 10.05.2010. 12:43 ] @
Citat:
Pa nekad je tako i bilo, kad je OOP bio nova i hip stvar Sto vise nasledjivanja to bolje, ako moze i visestruko, jos bolje ako niko sem tebe ne razume to je premium bonus . Nasledjivanje je tada i vidjeno upravo kao spas za ono sto iizuzetan prica, sa ove distance naivno verovanje da ce modifikacije na base klasi automatski propagirati promenu ponasanja naslednika bez potrebe za dodatnim modifikacijama u naslednicima. Medjutim, to nije ispalo tako iz dva razloga, kao prvo to zahteva veoma poseban i rigorozan stil programiranja u kome je funkcionalnost naslednika uvek DODATAK na funkcionalnost baze i da se taj odnos nece menjati u buducnosti, takav monaski stil programiranja retko ko praktikuje i prilicno je rigidan za promene.


Evo, ja bas primenjujem taj monaski stil pisanja. Kod mene se objekti nasledjuju ovako:

class User extends BaseUser extends AbstractBaseModel extends Doctrine_Record itd...

dalje nisam gledao, niti me zanima. Da, znam da je gornja linija neispravna, ne mora niko da me opominje, to je samo primer nasledjivanja.

Sve zajednicke stvari za objekte drzim u toj AbstractBaseModel klasi. Bez parametara, metode tipa isRateable() rade savrseno za sve postojece i buduce klase. Ne ponavljam isti kod na 4 mesta vec ga drzim na jednom i samo ga tu menjam. E to je OOP; kad ja izmenim funkcionalnost dodavanjem samo jedne linije koda, na samo jednom mestu. Svaki programer moze da nastavi moj rad.


[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:51 GMT+1]
[ mitke013 @ 10.05.2010. 12:52 ] @
Citat:
mmix: Pa dotice se donekle. Moji postovi i sluze da vam pokazu koliko je u stvari PHP daleko od koncepta OODa i uopste OOPa kao njegovog instrumenta. Nije mi cilj da omalovazavam PHP ali ni vi bas niste sigurnio sta vam to OOP donosi u PHP sto je tako fundmentalno drugacije i onda se hvatate za pojedinacne aspekte OOPa i promovisete ih iz posledice u uzrok i razlog zasto su vam neophodni. Pocnimo od toga koliko vas serijalizuje PHP objekte i deserijalizuje pri svakom pozivu? Koliko koristite polimorfizam u svojim PHP projektima?Imate li modele z svoje hijerarhije ili je sve onako odokativno ad-hoc?


Svi smo tu da naucimo nesto novo.

Jel ono OOD greska u kucanju ili zaista jeste neka skracenica? Google mi ne vraca nista za PHP OOD.

Sto se tice serializacije: zasto bi neko, ikada, serializovao objekat? Koja je poenta toga?

Polimorfizam: ja ga ne koristim, ne treba mi.

Ovo za modele iz hijerarhije nisam razumeo. Da li mozes da mi malo uprostis pitanje?

Citat:

Nije mi cilj da omalovazavam PHP ali ni vi bas niste sigurnio sta vam to OOP donosi u PHP sto je tako fundmentalno drugacije


Ja znam zasto koristim OOP; radio sam proceduralno ranije (mracna vremena, ne zelim da pricam o tome ) ili koristio polovicni OOP; metode sa brdom parametara ali sam tako morao. Taj isti kod ni ja sad ne bih razumeo, a ne neko ko bi nastavio moj rad.

Sada pisem programe minimum 5 puta brze nego ranije, kod je daleko citljiviji, lako je prosiriv itd. Da, jeste malo sporiji, ali koga jos briga za dodatnih 100-200 ms po pozivu?
[ bondja @ 10.05.2010. 13:22 ] @
Nebavim se PHP-om (Delphi, Java, C#) dodao bih:

OO kod je onaj kod kojeg imate veoma malo (tezi se 0) podataka koji se razmenjuju izmedju objekata.
Dakle sto manje parametara u procedurama, preko kojih bi se podaci razmenjivali.

Ako vec mora da postoji prenos/razmena podataka, onda koristi Design by Contract, Preconditions, Postconditions, tako da zastitite proceduru od poziva sa pogresnim vrednostima parametara.

Btw, favorizovati sadrzavanje naspram nasledjivanja, i na taj nacin obezbediti enkapsulaciju.

Pozdrav!
[ jablan @ 10.05.2010. 15:58 ] @
@mmix: Glede modeliranja vojnika; to sam i ja radio 6 meseci tamo, i mogu ti reći da ti model apsolutno ne odgovara realnom. U vojsci vojnik se ne predstavlja instancom, već brojem. :)

Citat:
mmix: Pa nekad je tako i bilo, kad je OOP bio nova i hip stvar :)

Treba biti korektan: OOP nikad nije bila nova i hip stvar. Postala je hip tek 10-15 godina nakon što je izmišljena, slično funkcionalnom programiranju.

@iizuzetan: Red je da prvo naučiš terminologiju. Ono što ti zoveš "funkcijsko" programiranje je zapravo imperativno ili struktuirano. Funkcionalno programiranje je nešto sasvim treće, koncept koji se bogu hvala još nije primio među PHP rajom, inače bi bilo ovoliko x2 bisera.

Citat:
bondja: OO kod je onaj kod kojeg imate veoma malo (tezi se 0) podataka koji se razmenjuju izmedju objekata.

I sam poziv metode je razmena podataka između objekata. Iako se donekle slažem da je najbolji kod onaj koji ne postoji, ipak ne bismo trebali da idemo u krajnost.
[ Majestic @ 10.05.2010. 19:14 ] @
Lijepo vam je @mmx govori al necete ga slusati

Ja ne radim u PHPu nego u C# al cu malo rec neke osnove o OOPu.

OOP koristi sljedece --> naslijedivanje, enkapsulacija (ucahurivanje), polimorfizam (viseoblicje), nadjacavanje (override)
Za pocetak je potrebno shvatiti ove pojmove da bi uopce pricali o OOPu.

Principi:

1) Minimizirati dostupnost članskih varijabli i metoda klase
npr. private string ime;

2) Češće koristiti sadržavanje, manje nasljedivanje

Naslijedivanje:
- ponovno iskorištavanje postojeće funkcionalnosti
- postojeća funkcionalnost se proširuje kako bi se dobila nova
- osnovna klasa - nju se nasljeduje
- sadrži zajedničku funkcionalnost
Loše strane --> Mogući problemi kod učahurivanja (enkapsulacije) - implementacijski detalji osnovne klase vidljivi izvedenoj klasi
- izmjene osnovne klase utječu na izvedenu klasu
Sadrzavanje (agregacija ili kompozicija):
- ponovno iskorištavanje postojeće funkcionalnosti (eng. reuse)
- postojeća funkcionalnost se grupira i koristi u ostvarenju nove funkcionalnosti
- nova funkcionalnost se ostvaruje tako da se dijelovi posla delegiraju sastavnim elementima grupirane funkcionalnosti
Lose strane --> Puno objekata
Sučelja objekata moraju biti dobro definirana kako bi ih se moglo dobro iskoristiti prilikom grupiranja


3) Programirati u odnosu na sučelje, ne implementaciju

Sucelje --> Grupa metoda/svojstava koje klasa implementira
Druge klase znaju da mogu pozvati bilo koju metodu implementiranog sučelja neovisno o klasi koja je implementirala sučelje
Klasa može implementirati po volji mnogo sučelja
Metode sučelja predstavljaju pravi podskup svih metoda koje neka klasa implementira

Implementacija sucelja --> Klasa implementira metode sučelja
Klasa se na taj način obvezuje da će davati usluge (metode) implementiranog sučelja
Korisnici sučelja se ne oslanjaju na konkretne klase već na samo sučelje


4) Open/Closed Principle

- klase bi trebale biti otvorene za proširivanje, a zatvorene za modifikaciju
- trebalo bi težiti dizajnu klasa koji se neće morati mijenjati kada dodu zahtjevi za novom funkcionalnošću
- najbolji način za proširenje sustava je dodavanje nove funkcionalnosti, a ne mijenjanje postojeće funkcionalnosti
- postiže se uz pomoć apstrakcije, polimorfizma, nasljedivanja i sučelja

5) Liskov Substitution Principle

- funkcije koje koriste osnovnu klasu moraju raditi s izvedenim klasama bez da znaju o kojim se točno izvedenim klasama radi

6) Dependency Inversion Principle

- klase više razine ne smiju direktno ovisiti o klasama niže razine već i jedne i druge moraju ovisiti o apstrakcijama
- apstrakcije ne smiju ovisiti o detaljima
- detalji smiju ovisiti o apstrakcijama

7) Interface Segregation Principle

- klase ne bi smjele ovisiti o sučelju kojeg u potpunosti ne koriste

Nisam stavio primjere pa ce neke stvari biti teze shvatit ali ih mozete naci na netu. Ovo su u pricipu osnove OOPa.
Na ovo jos treba dodati oblikovne obrasce (design patterns) + aspektno orijentirano programiranje
[ VladaSu @ 10.05.2010. 19:19 ] @
Citat:
mitke013
Sve zajednicke stvari za objekte drzim u toj AbstractBaseModel klasi. Bez parametara, metode tipa isRateable() rade savrseno za sve postojece i buduce klase. Ne ponavljam isti kod na 4 mesta vec ga drzim na jednom i samo ga tu menjam. E to je OOP; kad ja izmenim funkcionalnost dodavanjem samo jedne linije koda, na samo jednom mestu. Svaki programer moze da nastavi moj rad.


Ovo isto postizes ako napises u jednom fajlu jednu funkciju i radis include tog fajla.

Mislim da se pravi oop moze postici kada se na jednoj stranici napravi vise puta isti objekat koji u razlicitim delovima koda dobijaju razlicite parametre i nezavisno i paralelno obavljaju poslove.
Ako na svakoj stranici kreiram objekte koji se ne ponavljaju ili se ponavljaju ali redosledno (kreiraj, odradi, zavrsi, kreiraj, odradi, zavrsi) onda se kod vrlo lako moze svesti na fajl sa skupom funkcija i par globalnih promenljivih.

Tesko je postici pravi OOP u php-u. Kada me neko pita sta je OOP najlakse mu objasnim na primeru excel tabele gde postoji mnostvo polja, redova i kolona i gde polje u zavisnosti od tipa moze da ima donekle razlicite funkcije i osobine i da funkcionise nezavisno od ostalog dela tabele.

Mislim da se OOP programiranje u php-u uglavnom svodi na citiljiviji kod a o samoj primeni OOP mislim da se moze samo delimicno iskoristiti.
[ Dejan Carić @ 10.05.2010. 20:38 ] @
Citat:
mitke013:
trenutno radim na programu i 5 objekata deli zajednicku metodu isRateable(). Ona treba da vrati true/false u zavisnosti od 3 parametra: stanje $_COOKIE-a, da li je korisnik ulogovan i da li postoji setovan tag rateable(nije bitno sta je).

Ovaj primer gde 5 klasa nasleđuju baznu klasu sa metodom isRateable može da prođe u nekim jednostavnijim slučajevima, dok ćeš u drugim itekako narušiti arhitekturu.
Recimo razvijaš neki sistem gde korisnici mogu da ocenjuju entitete kao što su Audio Fajl, Video Fajl i Tekstualni Fajl unutar neke kategorije. Ali onda imaš uslov da video fajl možeš da oceniš samo ako prethodno nisi ocenio audio fajl. U tom slučaju Video Fajl treba da bude svestan eniteta Audio Fajl da bi implementirao svoj isRateable(), a to nije dobro, zar ne?

Citat:
mitke013:
Evo, ja bas primenjujem taj monaski stil pisanja. Kod mene se objekti nasledjuju ovako:

class User extends BaseUser extends AbstractBaseModel extends Doctrine_Record itd...

Prvo, jako je teško ispratiti takav kod jer trebam da znam šta je u BaseUser, šta je u AbstractBaseModel, šta u Doctrine_Record itd (otvaram i prolazim kroz 5 različitih fajlova).
Pretpostavljam da neka od ovih baznih klasa zna kako sebe da sačuva u bazi. Zanima me samo kako rešavaš transakcijsko čuvanje parent/child objekata.
Recimo imaš enitete Račun i Stavka. Šta se dešava ako neki programer početnik uradi Racun.Stavka[2].Save(), a Račun prethodno nije sačuvan u bazi?
Zanima me samo zbog tih silnih baznih klasa koje nasleđuju jedna drugu.
Znam da je primer nebulozan, ali nagledao sam se svega, pa ako već Stavka ima public metod Save...

[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:56 GMT+1]
[ mitke013 @ 10.05.2010. 21:10 ] @
Basexxx klasa sadrzi samo definicije za taj objekat npr. imena kolona, pravila za validaciju itd. Nista posebno. Doctrine_Record je deo Doctrine ORM paketa. Tako da bi neko ko nastavi moj program morao samo da pogleda npr. klasu User i klasu AbstractBaseModel da bi dobio API. Ako ce da menja pravila za validaciju, onda samo menja BaseUser.

Citat:

Zanima me samo kako rešavaš transakcijsko čuvanje parent/child objekata.

Doctrine se sam brine da kad snimim neki objekat, automatski se snimaju i child objekti, naravno kroz mysql transakcije. Ako sam bio saban koji pre toga nije pozvao isValid() vec samo udarim save(), bacice mi exception.
PS: Doctrine uvek radi DEEP validaciju, po defaultu. Ko hoce moze da je iskljuci, ali zaista ne vidim razlog tome.


[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 01:58 GMT+1]
[ Dejan Carić @ 10.05.2010. 22:02 ] @
Citat:
mitke013:
Izvini, nisam bas najbolje razumeo ovaj problem, ali recimo da bih onda uradio ovako: klasa video fajl ce imati svoju metodu isRateable(), opet bez parametara, koja ce da nasledi onu iz AbstraBaseModel (override).


Code:

Category category = new Category();

AudioFile audioFile = new AudioFile();
audioFile.CategoryId = category.CategoryId;
file.Rate();

VideoFile videoFile = new VideoFile();
videoFile.CategoryId = category.CategoryId;

Kako će sada videoFile.IsRateable() da vrati false kada on nema pojma za ovaj audio fajl koji je smešten unutar iste kategorije?

Citat:
mitke013:
Basexxx klasa sadrzi samo definicije za taj objekat npr. imena kolona, pravila za validaciju itd. Nista posebno. Doctrine_Record je deo Doctrine ORM paketa

Šta radiš u slučaju kada trebaš da izmeniš perzistentni sloj? Imaš zahtev da ne koristiš Doctrine ORM, već neki drugi ORM ili da u potpunosti izbaciš ORM, a svi entiteti ti nasleđuju upravo Doctrine_Record? Entitet može da se učita iz baze, ali takođe može i pozivom nekom web servisu, iz xml fajla, itd.

Citat:
mitke013:
Ako ce da menja pravila za validaciju, onda samo menja BaseUser. isValid()

Želim da kažem da ovo može da prođe samo u nekim jednostavnim slučajevima kada je potrebno izvalidarati da li je uneseno ime i prezime, itd.
U slučajevima kada validnost nekog entiteta zavisi i od drugih entiteta u sistemu, tada ili validaciju moraš da izmestiš na drugo mesto ili sve te druge entitete moraš da zbudžiš u jedan da bi ono IsValid bez parametara moglo da radi.

Citat:
mitke013:
Doctrine se sam brine da kad snimim neki objekat, automatski se snimaju i child objekti, naravno kroz mysql transakcije. Ako sam bio saban koji pre toga nije pozvao isValid() vec samo udarim save(), bacice mi exception.

E pa to je ono što me i zanima. Ako child objekat sme da se sačuva samo preko svog parent-a, zašto child ima public Save metod?
Ovo govorim sa strane korisnika tvog API-ja.

[Ovu poruku je menjao Dejan Carić dana 11.05.2010. u 00:02 GMT+1]
[ deerbeer @ 10.05.2010. 22:48 ] @
Citat:

Šta radiš u slučaju kada trebaš da izmeniš perzistentni sloj? Imaš zahtev da ne koristiš Doctrine ORM, već neki drugi ORM ili da u potpunosti izbaciš ORM, a svi entiteti ti nasleđuju upravo Doctrine_Record?

'Rusi' se 90% njegovog koda . Umesto tog silnog nasledjivanja mogao je da razdvoji apstrakciju od implementacije ORM-a
i kroz abstract factory da 'bira' engine koji ce aplikacija koristiti .
Kad se pojavi novi brzi i bolji :) implementira ga nezavisno, a ostatak aplikacije se ne bi menjao ,
tj, potpuno bi bio transparentan za za bilo koji ORM ili engine ..
http://en.wikipedia.org/wiki/Bridge_pattern

Citat:

Želim da kažem da ovo može da prođe samo u nekim jednostavnim slučajevima kada je potrebno izvalidarati da li je uneseno ime i prezime, itd.
U slučajevima kada validnost nekog entiteta zavisi i od drugih entiteta u sistemu, tada ili validaciju moraš da izmestiš na drugo mesto ili sve te druge entitete moraš da zbudžiš u jedan da bi ono IsValid bez parametara moglo da radi.

To i jeste fora , sto posmatra oop usko ,
samo kroz funkcionalnost jedne klase pa otud i metode bez parametara koje rade sve .

[ Sapphire @ 10.05.2010. 22:50 ] @
Znate šta je problem - vi gledate OOP na način da tražite mjesto da ga negdje uglavite, samo zato jer se radi o "trendu", a ne o konkretnoj potrebi za koju vidite rješenje jednom od objektnih tehnika / design pattern-a. Netko je rekao da se sve može postići samo funkcijama - i to je tačno, ali na isti način kao što je sve moguće postići asemblerskim kodom (može i niže, ko želi).

Pustite sada nasljeđivanje, polimorfizam i ostale sitnice. Glavni razlog OOP-a je povećanje abstrakcije, i lakše sagledavanje na stvari - to je ono što treba biti motiv za sve. Pomenute tehnike su tu da ostvare taj motiv, ništa više. Abstrakcija koja se postiže micanjem na veći stepen razvoja (na objektni pristup sa funkcijskog) je neprocjeniva tehnika koja je omogućila software ovakvim kakav je danas; i da napomenem da pod tom vrstom software-a ne mislim na kernel-e sistema ili neke mission-critical procese sa veoma ograničenim resursima gdje je sve osim asemblera/C-a "preteško". Programi od nivoa naprednih dokument editora (kao MS Word) pa do ERP sistema bi bili nemogući za izvesti bez OOP-a.

Problem većine PHP programera sa shvatanjem OOP-a i racionalizaciom njegove primjene je u nedovoljnoj kompleksnosti njihovih projekata. Ruku na srce, većina ne piše iole komplikovanije enterprise sisteme, kamoli šta drugo. Lako je koristiti funkcijsko programiranje na bazi sa 5-10 tabela.

Šta OOP omogućuje?

OOP omogućuje da za početak particionišete (princip enkapsulacije) dijelove sistema tako da umjesto da vodite računa o 48 stvari odjednom, vi smanjite taj broj na recimo 5-6. Uzmite za primjer evo komunikaciju sa bazom podataka koju stalno spominjete. Bez OOP-a, vaš kod se svodi za CRUD (Create, Read, Update, Delete) funkcije od kojih svaka odrađuje neki dio posla. Uzmite za slučaj da imate bazu sa 40 tabela. To je ~160 funkcija. Uzmite da morate imati transakcijska ograničenja na određene radnje koje uključuju određene skupove tih funkcija (recimo, prebacivanja novca u banci s jednog računa na drugi uključuje upis u tabelu transakcija, te dva update-a u tabeli stanja racuna - sa jednog + na drugi -). Ovo bi morali odraditi tako da napravite novu funkciju koja obuhvata te 3 u transakcijski okvir sa BEGIN - COMMIT - ROLLBACK. To dodaje još 30-ak funkcija. Uzmite onda da odjednom morate voditi audit logove svih korisničkih radnji, svih transakcija. Gdje ćete to uraditi? Mjenjati tih svih 30 funkcija?
Nemojte samo sada reći, pa dobro - to se može prebaciti na stored procedure u bazu. Pozivanje tih stored procedura sa parametrima nije ništa drugo nego micanje problema na drugo mjesto plus uvođenje dodatne kompleksnosti razdvajanjem koda na dodatna dva sloja (iako, to je normalna praksa ako je potreba za time realna - kao u bankama gdje je sigurnost podatka na prvom mjestu).

Particionisanje se radi pomoću par tehnika. Nema smisla objašnjavati šta znači referencirati jedan objekt iz drugog (asocijacije itd...). Najvažnija tehnika je definisanje granica vidljivošću podataka i funkcija. Private / public / protected oznake postoje ne radi otežavanja stvari, nego olakšavanja programiranja uvođenjem konceptualih granica u kod. Lako je vama sa 10 funkcija znati koju treba kada pozivati. Uzmite da bilo koji teži scenario zahtjeva da se slijedi tačno definisan postupak za neku radnju. Uzmite da neki objekt HTMLPage ima funkcije (mrzim ovo zvati "funkcije" kad je u OO svijetu pravilno reći metode, ali eto...) CreateHeader(), CreateBody(), CreateFooter(), bez parametara, koje sve same znaju odraditi. Da bi sve ispravno radilo, potrebno je pozvati ih u tome redoslijedu. Ko kaže da se neće naći neki rookie programer koji će ih pozvati nepravilno - i unijeti bug u program? Ko kaže da kada bude postojalo 2000 funkcija kroz 40 file-ova da nikada neće biti situacija da se nešto pozove nepravilno? Ograničenja koja sami postavljamo u OOP-u pomažu da se takve vrste grešaka svedu na minimum. Stavite ove tri funkcije na private vidljivost, tako da ih kod van klase ne može pozivati. Napravite public funkciju koja poziva ove tri u pravilnom redoslijedu. Public funkcija je vidljiva vanjskom svijetu, private nisu - te zato nitko ih ne može niti direktno zloupotrijebiti.

Upotrebom particionisanja stvarate black-box kocke koda za čije korištenje ne morate znati apsolutno ništa o njima. Za shvatanje toga primjenom OOP-a, ne morate koristiti sve OOP tehnike (ne treba vam niti nasljeđivanje, niti polimorfizam). Jedan od najosnovnijih design pattern-a je layering, tj. podjela koda u slojeve. Ako svaki sloj predstavimo objektima, i u svakome pozivamo samo objekte sloja ispod - dobiva se ogromna organizacija koda, a o manjoj mogućnosti grešaka i preglednijeg koda da se ne priča. UI sloj može pozivati poslovnu logiku, ona može pozivati sloj za komunikaciju sa bazom podataka, itd... Čak i ako sve ostavite u funkcijama, kad ih barem stavite u zajednički objekt, osiguravate da onaj koji ih poziva zna šta radi, jer mora instancirati taj "layer".

Netko je naveo da se kod može organizirati i jednostavno kroz file-ove i include naredbe. Istina, samo što taj pristup nema niti jednu od ostalih OOP osobina osim smanjenja veličine koda (i to samo djelomičnog smanjenja). Time ne dobivate nikakvu abstrakciju, ne možete postaviti nikakva ograničenja, te nema polimorfizma i nasljeđivanja, što je najjača OOP osobina.

Govoreći o polimorfizmu i nasljeđivanju, da nastavim s njima na primjeru rada sa bazom podataka. Pravilnom upotrebom osnovnog modela nasljeđivanja možete napraviti po objekt za svaki entitet koji imate u bazi. Prvo na što ćete naići je osobina da svaki taj entitet (tabela) ima ID. Zašto to onda ne prebaciti u zajedničku nad klasu? Jedini varijabilni parametar nad-klase može biti ime tabele entiteta. Funkcija za dobavljanje sljedećeg ID-a iz baze je ovisna u većini scenarija samo o imenu tabele u kojoj se traži ID, što je kvalificira da ide u nad-klasu. U složenijem scenariju, kada to nije dovoljno, ili kad se koristi neka složenija tehnika, napravite objekt IdGenerator, koji ima funkciju Generate(). Nasljeđivanjem napravite objekte kojima je IdGenerator nad klasa, i od kojih svaka implementira funkciju Generate() prema svome određenom scenariju. Jedna može dobavljati ID preko MAX() SQL funkcije. Jedna može koristiti posebnu tabelu samo za ID-eve. Jedna može iskoristiti SQL Server ili Oracle pogodnosti. Mogućnosti su neograničene. Ona naša prva nad-klasa za sve entitete, koja sadrži funkciju za generisanjeg sljedećeg ID-a, može jednostavno delegirati taj posao na konkretnu instancu IdGenerator klase, što nije ništa drugo nego najjednostavnija primjena polimorfizma.

Drugi primjer je nešto što nedostaje PHP-u, a to je objektna hijerarhija za mnoge očite stvari. Recimo, u PHP-u ja ne mogu da se oslonim da postoji neka funkcija koja će se automatski pozvati kada je potreban string tip podataka. Jezici kao C# ili Java imaju realizacije ToString() funkcije koja je implementirana u baznoj Object klasi, koju svaka klasa implicitno nasljeđuje (znači, nasljeđivanje + polimorfizam). PHP nema DateTime objekte, pa da mogu raditi sa vremenskim zonama, ili da ih mogu oduzimati da dobijem TimeSpan objekt koji sadrži podatke oduzimanja dva datuma. Primjera je hrpa.

Čak i bez sofisticiranih alata, za ne-presložene projekte, moguće je da sami napravite osnovni framework za manipulaciju tabelama u bazi podataka, koji se zasniva na jednostavnom nasljeđivanju entitet klase, i dopunjavanju imena tabele, i polja u bazi podataka. ORM-i rade to isto, samo sa još jednim slojem između, i gomilom ostalih mogućnosti kao što su Identity Maps, Lazy Loading, Query objekti, itd...

Pošto ovaj post nije pokušaj objašnjavanja nekome tačno gdje i kako može primjeniti OOP - uzmite fino knjigu "Design Patterns: Elements of Reusable Object-Oriented Software" i pročitajte je od korica do korica sa vježbanjem i pokušavanjem dubokog razumijevanja svakog primjera. Ja nisam upotrebljavao OOP ni 20% dok nisam počeo čitati ovu knjigu. Sada ne shvatam kako to nisam prije znao - jednostavno dobijete taj osjećaj povezanoti sa OOP pristupom da ništa drugo nema smisla.



Što se tiče konkretnih postova u ovoj temi, gledanje OOP-a kao broj parametara u metodama je loše. Nitko vas ne ograničava da imate metodu sa 5 parametara, niti metodu bez i jednog. Cilj je praviti kod koji se ravna prema SOLID principima, a to je već nešto što zahtjeva mnogo i mnogo rada, truda i volje za pravilnim OOP-om. Iz ovih principa dobivaju se svi design pattern-i od kojih eto za vas web programere, MVC je neprocjenjiv.

Principi koji se isto stalno spominju, i prožimaju s ostalima, su tight i loose coupling. Poenta je imati što manji broj dependency-a među objektima, tako da izmjena na jednome ne pravi ripple-effect na ostalima. Broj parametara naravno pomaže u tome, ali ne može se jednostavno reći sad ću praviti funkcije bez parametara, i to je to.

BTW, OOP nije niti blizu kraja, nakon njega imate TDD, pa dalje da se ne priča ... A sve je u svrhu povećanja abstraktnosti, osiguravanja od bug-ova, i što kvalitetnijeg razvoja software-a...
[ mitke013 @ 10.05.2010. 22:53 ] @
Citat:
E pa to je ono što me i zanima. Ako child objekat sme da se sačuva samo preko svog parent-a, zašto child ima public Save metod?
Ovo govorim sa strane korisnika tvog API-ja.


E pa to se desava kad koristis bilo koji ORM. Jednostavno, stvari tako funkcionisu i ja to nikako ne bih izbacio. Evo ti primer:
Song uvek pripada nekom Album-u. Ali, ja mogu da napravim posebno izmenu Song-a, ali mogu i jednu jedinstvenu formu gde ce se u isto vreme editovati Album sa svim pripadajucim Song-ovima. To sto ti pitas mi nikako nije jasno; ako ne zelis da Song koristi direktno save() metodu, nemoj da kreiras formu za njeno editovanje. Jednostavno.

Mala forma za editovanje pesme ce koristiti $song->isValid(). Velika forma za izmenu Album-a, zajedno za pripadajucim pesmama, koristice $album->isValid(). Ako samo jedna pesma ne prodje validaciju, isValid() vraca false. Ako pokusas ipak da snimis, dobices exception. Vrlo, vrlo jednostavno, ne vidim nikakav problem.


[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 02:01 GMT+1]
[ Sapphire @ 10.05.2010. 22:58 ] @
Citat:
deerbeer:Umesto tog silnog nasledjivanja mogao je da razdvoji apstrakciju od implementacije ORM-a .


Offtopic na OOP principe: kome je još stalo da ORM framework abstraktuje pomoću Abstract Factory-a? Baze može mijenjati slobodno kroz ORM (ne znam za Doctrine, ali pretpostavljam). Ako sad treba zamjeniti i čitav ORM, to je onda daleko jednog prosječnog, čak i veoma nad-prosječnog PHP projekta. Jbg, ne pravi svaki drugi PHP programer Facebook aplikacije ...

Nekada svu priču traženja savršenstva treba svesti i na ono najmanje što zadovoljava. Keep It Simple and Stupid - KISS.
[ VladaSu @ 10.05.2010. 23:08 ] @
@Mitke
Po meni ako metoda moze da se svede na ovakvu funkciju onda mi to bas i nije neka prava primena OOP;
function isReateable()
{
global var1, var2; //umesto $this->var1; $this->var2;
}


A sto se tice brzine pisanja koda obicno ti FW imaju gomilu gotovih funkcija pa je zato brze kodiranje.
Dobro napisani skupovi funcija takodje mogu da mnogo ubrzaju izradu stranice i ne bih poredio.

Hocu da kazem da bi sve to kroz php moglo da prodje kao proceduralno programirane (mozda nekada losije mozda nekada bolje, ali moze) za razliku od nekih drugih programskih jezika kao sto je recimo C#.net gde nista ne bi moglo da prodje kao proceduralno!
[ Dejan Carić @ 10.05.2010. 23:27 ] @
Citat:
mitke013:
Ukoliko treba neki drugi ORM, nema problema, procitacu dokumentaciju za njega. Ukoliko zeli bez ORM-a, nek nadje drugog programera. Ukoliko zeli proceduralan kod, nek nadje drugog programera. Vrlo jednostavno. Nemam NIKAKVU nameru da radim bez ORM-a i da rucno pisem validaciju, sql query-e, migracije i sve ostalo sto jedan ORM radi. Ali bas nikakve! To bi mi bilo jednako kao kad bih iz notepad-a morao da pisem php kod ili da izmisljam novi jQuery i slicno.
I btw, kad poslodavcu kazem da koristim out-of-the-box ORM resenje umesto nekog mog nedokumentovanog sklepa, sta mislis sta ce pre odabrati?


Pa evo ti primer:
Ja imam jako poverljivu bazu podataka sa korisnicima i nekim proizvodima.
Hoću da angažujem tebe da mi napraviš online web shop, ali ne mogu da ti omogućim pristup bazi jer su tu njihovi matični brojevi, stanja na računima, itd.
Umesto toga, ja sam napravio web servis i napravio metode koje ti omogućuju da dobiješ samo one stvari koje su ti potrebne.
Kako ćeš ti preko tog tvog framework-a da instanciraš nove entitete preko komunikacije sa mojim web servisom? Nikako.
A mene baš briga koje ćeš ti rešenje da koristiš dokle god je to brzo i pouzdano.

Citat:
mitke013:
Da, tacno, ko jos menja ORM tek tako


Sutra IBM izbaci novu verziju baze, ja puknem $10.000 na licencu i hoću da se web shop vrti na njoj. Upite koje ćeš da izvršavaš nad njom su u 99% slučajeva isti kao i za MySQL, ali gle malera, Doctrine npr. ne podržava tu verziju baze, dok neki drugi ORM podržava.

Hoćeš li:
1. Čekati 3 meseca da Doctrine izbaci podršku za novu bazu
2. Promeniti ORM
3. Odbaciti visokobudžetni projekat
[ mitke013 @ 10.05.2010. 23:27 ] @
Citat:
VladaSu: @Mitke
Po meni ako metoda moze da se svede na ovakvu funkciju onda mi to bas i nije neka prava primena OOP;
function isReateable()
{
global var1, var2; //umesto $this->var1; $this->var2;
}


Ti ozbiljno koristis global? Bez ljutnje, ali koriscenje global-a je veooooooooma los pristup programiranju (da ne kazem neku ruzniju rec). Pa zamisli da ja treba da nastavim dalje tvoj kod a $var1 konstantno dobija neku cudnu vrednost jer sigurno necu gledati svaku funkciju koje se poziva pre i posle moje. Zamisli da i moja funkcija ubaci nesto u global, a zatim se pozove neka koja totalno poludi. Tvojom logikom, ja bih morao da proverim SVAKU funkciju pre nego sto sednem da radim. Mojom logikom, proveravas samo tu metodu.

[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 02:05 GMT+1]
[ mitke013 @ 10.05.2010. 23:47 ] @
Citat:
Dejan Carić: Sutra IBM izbaci novu verziju baze, ja puknem $10.000 na licencu i hoću da se web shop vrti na njoj. Upite koje ćeš da izvršavaš nad njom su u 99% slučajeva isti kao i za MySQL, ali gle malera, Doctrine npr. ne podržava tu verziju baze, dok neki drugi ORM podržava.

Hoćeš li:
1. Čekati 3 meseca da Doctrine izbaci podršku za novu bazu
2. Promeniti ORM
3. Odbaciti visokobudžetni projekat


Promenicu ORM. Znaci, necu koristiti fromArray($_POST) vec cu koristiti useArray($_POST) ili koja vec. Ili jos bolje; ja od doctrine-a ionako koristim nekih 6-7 metoda:
fromArray, synchronizeWithArray, isValid, save i mozda jos koja. Ostale metode nisu vezane za ORM, tj. metoda isRateable() nema veze sa Doctrine-om. Znaci, u baseModel klasi bih napisao nesto poput:
Code:

public function fromArray($data)
{
   return parent::useArray($data) ;
}


tako da bi prelazak na novi ORM bio prilicno brz i jednostavan proces. Sto se tice baznih definicija npr. $this->hasColumn() gde se opisuje kolona u tabeli i njena validacija, to bi svakako moralo da se promeni jer to DIREKTNO zavisi od ORM-a i njegovog API-a. Moja gruba procena je da bi sa doctrine-a na npr. propel, za projekat koji ima visejezicku podrsku i 15 razlicitih objekata (bez many2many za prevode) trebalo u vrh glave 20 dana. Ako poznajem taj ORM i radio sam u njemu, ne bi trebalo vise od 3-4 dana, ORM programi su jako zaista jednostavni za koriscenje.

Citat:
Ja imam jako poverljivu bazu podataka sa korisnicima i nekim proizvodima.
Hoću da angažujem tebe da mi napraviš online web shop, ali ne mogu da ti omogućim pristup bazi jer su tu njihovi matični brojevi, stanja na računima, itd.
Umesto toga, ja sam napravio web servis i napravio metode koje ti omogućuju da dobiješ samo one stvari koje su ti potrebne.
Kako ćeš ti preko tog tvog framework-a da instanciraš nove entitete preko komunikacije sa mojim web servisom? Nikako.


Zasto si tako uveren u to? Ja dovlacim instance objekata koriscenjem Doctrine_Query klase. Umesto nje, koristio bih mogu klasu ciji je API identican Doctrine_Query klasi, ali bi podatke uzimao preko metoda koje si mi ti omogucio.
Drugo: posaljes mi sql dump gde bi 10 linija koda izmenila poverljive podatke. Jos jednostavnije i brze. Za program koji trenutno radim sam i dobio SQL dump za izmenjenim licnim podacima. Nema username-a, nema email-a, pa opet radim.
[ VladaSu @ 11.05.2010. 13:21 ] @
@mitke

Ne koristim global i znam za posledice samo sam hteo da kazem da OOP nije samo citljiviji kod vec nesto sasvim drugo i u php-u sustina promice, OOP se koristi za citljiviji kod i nasledjivanje koje opet moze i funkcijama da se resi. Nema nesto slucajva kada je MORAM da koristim OOP;
I kod klase moras da setujes $this->var1 i $this->var2 pa bi trebao da znas kada i kako se setuju a istovremeno moras da otvoris 10 fajlova da bi to pronasao.
Opet kazem da sam za OOP zbog nekih drugih stvari ali ne zbog pravljenja objekata i nasledjivanja, najvise zbog gomilu gotovih stvari na kojima je radjeno godinama, brznu savladavanja tih stvari i pronalazenju zajednicke logike medju programerima jer te OOP navodi sa slicno razmisljamo.
[ Radovan__III @ 11.05.2010. 13:43 ] @
Ako neko kad pomisli da OOP misli na nasledjivanje ?! Onda po mom skromnom misljenju vi kreirate tako "nekvalitetan kod" da je to neverovatno. Ne kazem ja da je naslednjivanje zabranjeno, ali kljuc je interfejs ! Ako neko ovde uopste govori u OOP a u svom kodu se ne oslanja u ogromnoj meri na interfejse taj slobodno moze da se batali OOP
[ dakipro @ 11.05.2010. 15:51 ] @
Mitke013, zamolio bih te za malo manje samo-promocije ovde. Ok je davati primere koda ali u dobro broju slucajeva je ocigledno da je promocija necega drugog u pitanju. Recimo video za "paginaciju u jednom redu" si zakacio bar 3 puta na ovoj temi, i na jos par tema (btw, paginacija u jednoj liniji koda nije nista previse inovativno i ne vidjeno do sada). Zadrzi diskusiju na idejama boljeg programiranja, bez prozivki, tj ne na tome kako je tvoj kod bolji od drugih kako ne bi dolazilo do offtopic prepucavanja ciji je manji (ili veci) kOd i ko koliko zaradjuje zbog toga.
Dobar deo ovde opisanih stvari nije niciji licno izmisljeni stil, tako da nema potrebe ulaziti u licnu prozivku.

Usput, kompetentnost da li je neko dobar u programiranju ne moze klijent oceniti, jer da on zna kako treba, sam bi ga isprogramirao in the first place. Uspesnost u poslovanju nije merilo kvaliteta koda i obrnuto, a ovde se diskutuje o programiranju, ne o poslovanju
[ jablan @ 11.05.2010. 16:15 ] @
Citat:
Radovan__III: Ako neko ovde uopste govori u OOP a u svom kodu se ne oslanja u ogromnoj meri na interfejse taj slobodno moze da se batali OOP

Džiiz... Šta ću ja jadan koji kodiram u pure-OOP jeziku koji ne poznaje koncept interfejsa... :) Kako ću ja da batalim OOP?
[ Miroslav Ćurčić @ 11.05.2010. 21:51 ] @
Potpisujem ovo kako je Saphire objasnio OOP.
[ Nikola Poša @ 11.05.2010. 22:21 ] @
Citat:
Drugi primjer je nešto što nedostaje PHP-u, a to je objektna hijerarhija za mnoge očite stvari. Recimo, u PHP-u ja ne mogu da se oslonim da postoji neka funkcija koja će se automatski pozvati kada je potreban string tip podataka. Jezici kao C# ili Java imaju realizacije ToString() funkcije koja je implementirana u baznoj Object klasi, koju svaka klasa implicitno nasljeđuje (znači, nasljeđivanje + polimorfizam). PHP nema DateTime objekte, pa da mogu raditi sa vremenskim zonama, ili da ih mogu oduzimati da dobijem TimeSpan objekt koji sadrži podatke oduzimanja dva datuma. Primjera je hrpa.

Što se implementacije toString-a tiče, PHP to i te kako podržava: http://www.php.net/manual/en/l...p#language.oop5.magic.tostring.

Za rad sa datumom/vremenom, PHP ima sasvim solidnu built-in klasu: http://php.net/manual/en/book.datetime.php.

Aj' daj još neki primer, pa da vidimo dal' PHP ima rešenje i za njega, a kladim se da ima.


Goran Rakić: Mala dopuna za bolje razumevanje toka diskusije. U PHP-u je ovoo toString čist hack, uostalom i zove se magična metoda toString. Mali problem je što ne postoji typecasting operator kao što to postoji u nekim drugim jezicima, ali to nije prepreka za OOP koncept. Veći problem je što ne postoji method overloading, mogućnost da se pozove različita metoda za različite tipove argumenta metode. Može da se imitira switch-om i instanceof operatorom.

[Ovu poruku je menjao Goran Rakić dana 16.06.2010. u 02:15 GMT+1]
[ logic_rabbit @ 12.05.2010. 08:50 ] @
Mijesate ovde mnoge stvari. Mislim da je ono sto vas interesuje prvi od SOLID principa http://en.wikipedia.org/wiki/Solid_(object-oriented_design)
Single responsibility principle koji kaze objekt tj. klasa treba da ima jednu i samo jednu odgovornost. Odnosno klasa mora imati samo jedan razlog da se mijenja.

Zasto je ovo bitno?
Zbog pisanja unit testova. Kad pisemo unit testove bitno je da klasa ima samo jednu odgovornost i da mozemo da izoliramo tu klasu od ostalih u projektu i da je testiramo nezavisno od drugih klasa.
U slucaju da ne pisete unit testove za svoj kod, da ne koristite patterne i slicno onda mozete i potrpati sve funkcije u jednu klasu onda nije ni bitno...



[ mitke013 @ 12.05.2010. 10:00 ] @
Citat:
logic_rabbit: Mijesate ovde mnoge stvari. Mislim da je ono sto vas interesuje prvi od SOLID principa http://en.wikipedia.org/wiki/Solid_(object-oriented_design)
Single responsibility principle koji kaze objekt tj. klasa treba da ima jednu i samo jednu odgovornost. Odnosno klasa mora imati samo jedan razlog da se mijenja.

Zasto je ovo bitno?
Zbog pisanja unit testova. Kad pisemo unit testove bitno je da klasa ima samo jednu odgovornost i da mozemo da izoliramo tu klasu od ostalih u projektu i da je testiramo nezavisno od drugih klasa.
U slucaju da ne pisete unit testove za svoj kod, da ne koristite patterne i slicno onda mozete i potrpati sve funkcije u jednu klasu onda nije ni bitno...


Clanak na wikipedii je uzasno kratak i nista nije rekao. Ajde objasni svojim recima tu ideju.

Koliko mi se cini, ti si za to da se funkcije tipa getCreatedAt() i getUpdatedAt() drze u klasi npr. Objecttimes (ili slicno, nije vazno), isRateable(), isVoted() u klasi Statistics itd...? Ili nisam dobro razumeo
[ logic_rabbit @ 12.05.2010. 18:00 ] @
Hm SOLID principi su defacto standard za OOP vec nekoliko godina... Detalje o njima mozete lako pronaci na netu. Jedan od linkova Uncle Bob

E sada neda mi se citati ovaj ogroman post, ali mislim da bi prije bilo getCreatedAt() i getUpdatedAt() u klasi npr. Objecttimes, funkcija isRateable() u klasi Rating
isVoted() u klasi Voting i sl.

Ako vas interesuje najbolji nacin da naucite SOLID principe preporucujem sledecu seriju videa:
http://www.dimecasts.net/Casts/ByTag/SOLID%20Principle


[ stough_ser @ 19.05.2010. 13:42 ] @
@Tema

ja recimo klase pravim da budu realne. mislim da sadrze ono shto objekt treba da ima.
i funkcije i atribute,

a uvek imam i jednu ili par statichnih klasa
uglavnom Misc klasu

koja mi sluzi za sve funkcije koje nisu vezane za objekte
a uvek ima i takvih tipa dodajDane($brojDANA), checkInputFormat($nekaPromenljiva) ...
[ Goran Rakić @ 15.06.2010. 23:29 ] @
@mitke013, ostali:

Deluje mi da je ovde između ostalog problem da se razume ideja Responsibility-driven design OOP projektovanja i ideja Separation of concerns modularnog programiranja.

Na primer, ona tvoja metoda sa četvrte strane koja koristi $_COOKIE je glupost teška. $_COOKIE podatak tu mora da bude ubrizgan spolja u stanje objekta, a ne da objekat posegne napolje u kontekst. U tom trenutku si ubio svaku enkapsulaciju koja je važan koncept.

Naučio si neke ideje napamet (ono što si napisao o globalnim promenljivama, za šta se slažem) i ne vidiš dalje od njih. U ovom slučaju tvoj $_COOKIE nije ništa drugo nego globalna promenljiva. U diskusiji pišeš kilometarske postove sa jednim te istim kodom jer ti se tako čini kako imaš nove argumente, to je iritirajuće i naporno za čitanje.

Dobra tehnika koja će unaprediti kod koji pišeš je da razmišljaš o nekom korisniku dela aplikacije, jednog objekta. Šta je to što taj objekat radi? Koje podatke deli? Da li je stanje potpuno enkapsulirano u objektu ili se nešto ubrizgava spolja? Da li je objekat dovoljno modularan da nezavisno postoji?

Drugi savet je da malo zaboraviš na ORM, jer ORM != OOP.

ORM ima ružnu naviku da spoji tvoj objekat domena (ono sa čim radiš u aplikaciji) i reprezentaciju tog objekta u bazi podataka, što ja osim u najjednostavnijim slučajevima tumačim kao dve potpuno različite stvari.

Da bi SoC živela u kodu, objekti moraju da budu neuvezani (coupling). Ovim teškim nasleđivanjem i stapanjem slojeva, uz razrušenu enkapsulaciju ti dobijaš izrazito spregnut sistem u kome nemaš šansi bilo šta da čačneš na infrastrukturnom polju.

Brzinu razvoja vidiš samo zahvaljujući primeni Doctrine ORM-a, na račun brzine izvršavanja. Izgleda da imaš sreću da radiš samo sa jednostavnim modelima podataka, čim od njega do sada nisi dobio ospice.
[ mitke013 @ 16.06.2010. 01:23 ] @
Citat:
Goran Rakić: @mitke013, ostali:

Deluje mi da je ovde između ostalog problem da se razume ideja Responsibility-driven design OOP projektovanja i ideja Separation of concerns modularnog programiranja.

Na primer, ona tvoja metoda sa četvrte strane koja koristi $_COOKIE je glupost teška. $_COOKIE podatak tu mora da bude ubrizgan spolja u stanje objekta, a ne da objekat posegne napolje u kontekst. U tom trenutku si ubio svaku enkapsulaciju koja je važan koncept.

Glupost? Prilicno teska rec od nekoga ko nije postavio nijedan primer koda. Ako si vec samoproklamovani guru (mozda i jesi, ne znam), zasto ne postavis neke primere koda kako bih razumeo? Najlakse je obrisati gomilu mojih postova jer se ne slazes za mnom; daj da vidimo i konkretan razlog.
Citat:

Naučio si neke ideje napamet (ono što si napisao o globalnim promenljivama, za šta se slažem) i ne vidiš dalje od njih. U ovom slučaju tvoj $_COOKIE nije ništa drugo nego globalna promenljiva. U diskusiji pišeš kilometarske postove sa jednim te istim kodom jer ti se tako čini kako imaš nove argumente, to je iritirajuće i naporno za čitanje.

Sto se tice tih napamet ideja, ti si jedan od onih koji samo ostavljaju linkove ka nekim tutorialima i definicijama. Ja sa druge strane kroz primer objasnjavam kako radim, a da si pogledao bolje, video bi da se isti kod bas i ne ponavlja toliko.
Citat:

Dobra tehnika koja će unaprediti kod koji pišeš je da razmišljaš o nekom korisniku dela aplikacije, jednog objekta. Šta je to što taj objekat radi? Koje podatke deli? Da li je stanje potpuno enkapsulirano u objektu ili se nešto ubrizgava spolja? Da li je objekat dovoljno modularan da nezavisno postoji?

Nezavisno? Ne razumem te; zasto ne bih imao zajednicke metode u basemodel klasi ako tu istu metodu dele svi objekti? Konkretno iz posta koji si obrisao je metoda getTitle(). Jel treba da je ponavljam 32 puta zato sto imam 32 klase?
Citat:

Drugi savet je da malo zaboraviš na ORM, jer ORM != OOP.

ORM ima ružnu naviku da spoji tvoj objekat domena (ono sa čim radiš u aplikaciji) i reprezentaciju tog objekta u bazi podataka, što ja osim u najjednostavnijim slučajevima tumačim kao dve potpuno različite stvari.
Citat:

Ne vidim nista lose u tome da klasa (npr. Category) ima svoje logicke funkcije dok se BaseCategory stara o reprezentaciji u bazi. Reci mi sta fali ovom pristupu?
Citat:

Da bi SoC živela u kodu, objekti moraju da budu neuvezani (coupling). Ovim teškim nasleđivanjem i stapanjem slojeva, uz razrušenu enkapsulaciju ti dobijaš izrazito spregnut sistem u kome nemaš šansi bilo šta da čačneš na infrastrukturnom polju.

Naveo sam primere; ti ne znas koliko je taj sistem spregnut ili nije.
Citat:

Brzinu razvoja vidiš samo zahvaljujući primeni Doctrine ORM-a, na račun brzine izvršavanja. Izgleda da imaš sreću da radiš samo sa jednostavnim modelima podataka, čim od njega do sada nisi dobio ospice.

I to sam postovao, ali si verovatno i to obrisao. 'Jednostavan model podataka' tesko da je mogucnost da svaki objekat moze, ali ne mora, biti visejezican i da jedna metoda getTitle() se sama brine o tome. Naravno, deep validacija prevoda se podrazumeva. Kako sam to resio? U mom 'nategnutom' sistemu objekat koji je visejezican ima metodu 'getTranslationRelation()'. Ok, cudan naziv, ali to je sve. Od tada pa nadalje, objekat je visejezican. Pored nove many2many klase tipa CategoryTranslation, apsolutno nijedna metoda vise nije potrebna.
U pravu si, vrlo nategnuto i tesko vezuje ruke nekom ko bi nastavio moj rad

ps.
kad si vec uhvatio zalet sa brisanjem mojih poruka, ostavi ovu bar do ujutru. Nema smisla ubiti je pre nego sto sunca vidi u zivotu

Druga stvar:
zato sto ti radis na drugaciji nacin, ne znaci da ja mozda nisam u pravu
[ Goran Rakić @ 16.06.2010. 12:09 ] @
Teška reč reći za neki kod da je glupost? Jesi li uopšte pročitao objašnjenje zašto je to glupost i zašto je tvoja priča o enkapsulaciji potpuno bušna? Sinoć sam ti preko PP već odgovorio da ne radim cenzuru teme, prođi od početka do kraja kroz poruke i javi ako misliš da sam bilo gde prikrio tvoje mišljenje. Ponavljanje istih argumenata i kačenje gomile primera koji ne služe diskusiji neću da dozvolim.

Kada se govori o couplingu misli se samo na final klase (implicitno ili eksplicitno definisane). Naravno da apstraktna klasa nije objekat sama za sebe. To ponavljanje o kome ti pričaš niko nije pomenuo.

Ostatak poruke je irelevantan za diskusiju.
[ mitke013 @ 17.06.2010. 04:03 ] @
Citat:
Goran Rakić: Teška reč reći za neki kod da je glupost? Jesi li uopšte pročitao objašnjenje zašto je to glupost i zašto je tvoja priča o enkapsulaciji potpuno bušna?
Ostatak poruke je irelevantan za diskusiju.

Ok, ako je glupost, reci mi kako da uradim. I molim te, bez nekih dodatnih copy&paste definicija ili linkova, interesuje me bas konkretni primer gde metoda treba da vrati isRatable() na osnovu cookija, da li je posetioc ulogovan i da to nije njegova pesma.

Ako vec gresim i pisem 'gluposti', ajde da naucim nesto novo.
[ Goran Rakić @ 17.06.2010. 11:55 ] @
Rekao sam ti već, ubrizgaj taj $_COOKIE['nesto'] spolja kao parametar metode. Nemoj da koristiš globalnu promenljivu unutar klase, to nije enkapsulacija, to je prikrivanje kompleksnosti i mazanje očiju.

Još bolje ako taj $_COOKIE predstavlja posetioca, penesi objekat posetioca ili sesije kao parametar.

Sada tvoja klasa ne izlazi više u globalni prostor da zahvati svoj kontekst. Drugo, pisanje unit testova je lakše jer sada možeš lepo da preneseš vrednost $_COOKIE i proveriš metod za različite situacije. Treće klasu možeš i da iskoristiš u kodu koji se ne izvršava preko veb servera i umesto $_COOKIE koristiš nešto drugo.

Razmisli i da li ti se isplati da refaktorišeš kod tako da ovaj uslov o logovanju izmestiš spolja, tj. da isReatable() proveri da li vlasnik pesme nije preneti korisnik i možda još neke druge uslove, a da grananje vršiš po uslovu ($user->isLogged() && $song->isReatable($user)). Onda iz nekog trećeg koda možeš da ignorišeš ovo o prijavi i skriptom oceniš pesme za korisnika Peru Perića ako nisu njegove, nešto što bez refaktorisanja ti ne možeš da izvedeš. To bi bilo poštovanje dogovora o nadležnostima. Pesmu ne zanima da li je korisnik prijavljen.
[ mitke013 @ 17.06.2010. 13:29 ] @
Izvini na povecem postu, ali mislim da je 100% vezan upravo za temu i da bi bio svima interesantan a ne samo tebi i meni:

Citat:
Goran Rakić: Rekao sam ti već, ubrizgaj taj $_COOKIE['nesto'] spolja kao parametar metode. Nemoj da koristiš globalnu promenljivu unutar klase, to nije enkapsulacija, to je prikrivanje kompleksnosti i mazanje očiju.

Prva verzija i jeste radila tako jer se ni meni u startu nije svidjalo da metoda uzima cookije. A onda sam ukapirao da je bezveze slati nesto sto metoda moze i sama da uzme, zar ne? Kao sto imam metodu User::isLogged() koja proverava session sama, tako sam ovde iskoristio kukije.
Pisanje testova je tako mnogo lakse jer metoda radi ono sto zelim; konkretno
Code:

{if $song->isRateable()}
//ispisi zvezdice za glasanje


Onaj ko nastavi moj program nema potrebe uopste da dodatno razmislja u kukijima i njihovim imenima, assign-u toga i slicno.

Drugo; ako mu od spolja posaljem kuki, ja onda moram da svuda ponavljam koji je to kuki, npr. $_COOKIE['votedsong_1'] ili slicno. Suvisno. Na moj nacin samo sam na jednom mestu rekao kako ce se kuki zvati i to je to. Plus, .tpl fajl je daleko pregledniji u odnosu na:
Code:

{if $song->isRateable($smarty.cookies.votedsong_1)}
//ispisi zvezdice za glasanje



Kad vec pricas o enkapsulaciji, evo njene definicije:
Citat:
encapsulation
2. The ability to provide users with a well-defined interface to a set of functions in a way which hides their internal workings. In object-oriented programming, the technique of keeping together data structures and the methods (procedures) which act on them.
(1998-09-07)


Obrati paznju na 'in a way which hides their internal workings'. Moj nacin upravo to i radi. Zamisli sada da radim na tvoj nacin, tj. da postoji metoda npr. Status::isSongRateable($song, $user, $cookie) kojoj bi slao te neophodne podatke.
Problemi:
1. Kad god se poziva metoda, moram da obracam paznju na redosled parametara
2. Testovi; nemoguca misija. Sta ako korisnik nije ulogovan? Znaci da bi u kontroleru (tj. testu) mora da $user konstantno postavljam na null
3. Jos veci zbrlj u .tpl-u koji bi pozivao tu metodu
4. Jednog dana ukapiram da je mozda bolje da $user bude zadnji parametar (samo primer). Onda moram da uradim refactoring SVAKOG mesta gde se ta metoda poziva!
5. Jednog dana pozelim dodatni uslov za mogucnost glasanja, npr. da samo odredjena grupa user-a moze da glasa (opet, samo primer). Opet refactoring svakog mesta gde se metoda poziva; moj nacin zahteva samo jednu liniju unutar metode Song::isRateable()

Pogledaj sta je enkapsulacija:
http://stackoverflow.com/quest...ion-with-simple-example-in-php
http://en.wikipedia.org/wiki/Information_Hiding
Citat:
Treće klasu možeš i da iskoristiš u kodu koji se ne izvršava preko veb servera i umesto $_COOKIE koristiš nešto drugo.

Izvini ovo nisam razumeo. Kako to mislis da se ne izvrsava preko web servera? Moj program ce se izvrsavati samo interno, u okviru jednog sajta, i nikada nece imati potrebu da ga neko sa strane pita da li se moze glasati za pesmu ili ne.
Ili te nisam razumeo, nikad nisam radio SOAP ili slicno. Ako mozes, pojasni mi, zaista me interesuje konkretan primer ili situacija (znaci ne ono; kad budes radio xxx godina, kasce ti se samo ili slicno )
Citat:
Razmisli i da li ti se isplati da refaktorišeš kod tako da ovaj uslov o logovanju izmestiš spolja, tj. da isReatable() proveri da li vlasnik pesme nije preneti korisnik i možda još neke druge uslove, a da grananje vršiš po uslovu ($user->isLogged() && $song->isReatable($user)). Onda iz nekog trećeg koda možeš da ignorišeš ovo o prijavi i skriptom oceniš pesme za korisnika Peru Perića ako nisu njegove, nešto što bez refaktorisanja ti ne možeš da izvedeš.

Uf... pogubio sam se. Ako mislis 'spolja' da to bude logika u kontroleru, to ne dolazi u obzir. Kontroler samo spaja logiku (model) i prikaz (view); ne vidim nikakav razlog da neku dodatnu logiku ubacujem i u kontroler.

Edit Goran Rakić: Code format. Rado bih i isekao drugu polovinu poruke i ovaj unit test jer mislim da ne govori apsolutno ništa novo ali ti si osetljiv na to pa će ostati.

Isekao ja, slobodno jos malo skrati. Trol u meni je nadvladao razum


[Ovu poruku je menjao Goran Rakić dana 17.06.2010. u 18:55 GMT+1]

[Ovu poruku je menjao mitke013 dana 19.06.2010. u 12:30 GMT+1]
[ masinac_1 @ 19.06.2010. 06:39 ] @
Hm, citao sam poslednjih 10-ak dana par tema na kojima se savetuje da se bezi od nekih stvari kao djavo od krsta.
Zasto je strasno ubaciti malo php-a u view html? Ili da php posalje par podataka js-u jer je tako mnooogo jednostavnije i brze u oderdjenoj situaciji. Ili da kontroler obavi koju logicku operacuju vise kako bi kasnije model bio potencijalno korisniji. Dobar primer je bas ovde za $_COOKIE.
Pravila postoje i ona kazu da treba izbegavati mesanje html-a i php-a, mesanje php-a i js-a, da model obavlja radnje prema instrukcijama koje mu daje kontroler (tj. poziva ga da radi nesto) a da pri tome kontoler "nema pojma" zasto, kako i sl. Ali sve je relativno, zavisi od situacije. Mislim da uopste nije strasno prekrsiti neko od ovih pravila ako postoji veliki razlog i ako se filozofija nece (bar ne mnogo) ugroziti i ako je to tako sitno i ocigledno da nece dovesti u zabunu onog ko kasnije nastavi da radi na projektu. A tu su i komentari izmedju ostalog.

Generalno voditi se idejom da se nesto uradi u sto manje linija koda (1-2) i preterivati u tome je vrlo slicno prebacivanju novcanika iz jednog dzepa u drugi i misleci da imas duplo vise kesa, samo sto je ovde novcanik u stvari supljina/prazno u kontroleru i modelu. Radnjama koje treba da se urade je samo promenjena lokacija i nista vise, one su i dalje prisutne. Ok je to da bi estetski bilo lepse, da bi bilo razumljivije ali se moze doci do gubitka funkcionalnosti tih modela ako se nesto sitno promeni u kotnroleru sto rezultuje zavlacenje u klase i menjanje svega i svacega, mozda i ponovno pisanje modela.
Recimo ovi kolacici su parametar od kog zavisi izlaz modela. Sta ako se ta ista logika kasnije bude obavljala u zavisnosti od nekog prugog parametra? Nece moci da se prosledi modelu, jer on sam trazi kolacice, ne ocekuje od taj parametar od kontrolera. Ako bi se pak deo logike stavio u kontroler pa da obradi kolacice i jasno kaze modelu sta da radi (trazi u bazi.. raducka na tome malo i posalje u view), onda bi taj model bio upotreblim i ako se promeni parametar od koga zavisi sta dalje.

Al', dobro, ne mora da znaci da je tacno samo zato sto ja vidim smisao u tome, ja sam jos uvek samo pocetnik :). Ali vidim da jos neki, mnogo iskusniji od mene, razmisljaju ovako, tako da mislim da sam u pravu za ovo iznad - html, js, php (nema veze sa ovom temom ali ima sa sustinom poslednjih postova) i bukvalno shvatanje da kontroler radi sto manje - skoro uvek nista.
[ mitke013 @ 19.06.2010. 11:35 ] @
Citat:
Recimo ovi kolacici su parametar od kog zavisi izlaz modela. Sta ako se ta ista logika kasnije bude obavljala u zavisnosti od nekog prugog parametra? Nece moci da se prosledi modelu, jer on sam trazi kolacice, ne ocekuje od taj parametar od kontrolera. Ako bi se pak deo logike stavio u kontroler pa da obradi kolacice i jasno kaze modelu sta da radi (trazi u bazi.. raducka na tome malo i posalje u view), onda bi taj model bio upotreblim i ako se promeni parametar od koga zavisi sta dalje.


Pa to i jeste poenta. Ako kolacice saljes svaki put kad ti treba neki info iz modela, a jednog dana odlucis da ti kolacic vise ne treba nego recimo informaciju o tome da je neko glasao cuvas u bazi, lakse je izmeniti jednu liniju u modelu nego 30 mesta odakle se ta metoda poziva.
Isto ti je i za $_SESSION. Sto bih stalno slao nesto sto model moze i sam da uzme? Konkretno se ova metoda poziva iz view dela, pa bi kod bio jos i totalno necitljiv.
[ masinac_1 @ 19.06.2010. 12:09 ] @
Pa nije problem da li model moze ili ne nego da li treba.
Ti svakako moras napisati par redova za prijem i obradu kolacica da bi se formirao (ili ne) upit ka bazi. Sam upit mora u model, sad je samo pitanje gde ces da prihvatis kolacice. Nece biti manje linija ako to stavis u model - bice isti broj, recimo minimalan da se operacija inicira.
Prema onome sto su meni objasnjavali (i u skladu je sa definicijama), rekao bih da kontroler treba da dodje do kolacica ili nekog drugog podatka/input sa client side, a ne model. Ako je bas frka da u kontroleru za tu akciju postoje 1-2 linije onda pozvati neki helper koji ce samo to da obavi i sta vrati poslati modelu.
Taj hepler jednostavno neces vise pozivati kada dodje do promene kljucnog parametra od kog zavisi sta se salje u view, model ce i dalje biti funkcionalan bez bilo kakvih izmena a u kontroleru ces imati tih 2 linije koje su vrlo bitne :).
Citat:
Wiki: The controller receives input and initiates a response by making calls on model objects. A controller accepts input from the user and instructs the model and viewport to perform actions based on that input.
[ mitke013 @ 19.06.2010. 13:16 ] @
Citat:
masinac_1
Prema onome sto su meni objasnjavali (i u skladu je sa definicijama), rekao bih da kontroler treba da dodje do kolacica ili nekog drugog podatka/input sa client side, a ne model. Ako je bas frka da u kontroleru za tu akciju postoje 1-2 linije onda pozvati neki helper koji ce samo to da obavi i sta vrati poslati modelu.


I meni su slicno objasnjavali za slanje $_SESSION['user_id'] klasi modela i dobili smo uzas od koda; refactoring toga je prakticno nemoguca misija zbog obima programa. Ako ti neko objasnjavao, ne znaci automatski da je i u pravu

Ok, generalno si u pravu; ni meni se ne svidja narocito ta ideja o $_COOKIES, ali je stvar ipak mnogo bolja nego da kolacic saljem kao parametar. Gle; u view delu programa se ta metoda poziva;
Code:

{foreach from=$allSongs item=song}
  {if $song->isRateable() }
   {include file='_common/rating.tpl'}  // ovo ce da iscrta zvezdice za glasanje
  {/if}
{/foreach}

Ovo je potpuno normalna situacija u view delu programa; petlja koja mi ispise sve pesme i za neke dozvoli da glasas ili ne. Stvarno nemam bolju ideju od ove da to uradim. Ako imas, veruj, promenicu, ali bez da dodajem logiku u kontroleru.


[ masinac_1 @ 19.06.2010. 13:53 ] @
Ovako bih ja to uradio.
Zvezdice postoje bez obzira da li se moze glasati ili ne. Uostalom lepse je kad se vide svuda a ne kad je isarano (ako je to lista pa jedna pesma ima zvezdice a druga nema - kontam da jeste zbog foreach). Uz to zvezdice mogu da prikazu i rejting (prve dve recimo jedne boje a ostale druge boje - rejting 2).

Znaci isRatable() bih uklonio iz view dela. Ubacio ajax za glasanje, onclick u sam tpl. Jedna java funkcija po ucitavanju stranice poredi id svakog elementa (pesme) sa kolacicima i ako ima poklapanja uklanja onclick pa posetioc moze da klikce koliko hoce. Dodao bih isRateble() u akciju koja se poziva nakon klika na zvezdicu za svaki slucaj.

I ono za rejtig, zvezdice razlicite boje - isto js moze da uradi. PHP samo napravi taj element a js mu promeni klasu kao sto uklanja onclick.

[Ovu poruku je menjao masinac_1 dana 19.06.2010. u 15:06 GMT+1]
[ galahad @ 19.06.2010. 14:14 ] @
Pratim temu od početka, al' reko' "aj' malo da zakuvam"

Koja je poenta OOP-a (odnosno kvazi-OOP) u jeziku koji nije OO?

Aj' da se ne lažemo, klase, objekti i sva ta čudesa itekako imaju smisla kada je u pitanju aplikacija, koju kad pokreneš radi. Ali kad je PHP u pitanju, PHP skripte nisu aplikacije koje stalno rade, već se pokreču, objekti kreiraju u letu, i po završetku rada - nestaju. A onda Jovo nanovo.

Kontam ja to, preglednije je kad postoje klase, i u njima su tematski grupisane funkcije (to što se zovu metodi, apsolutno ne menja činjenicu da je u pitanju funkcija; nije šija nego vrat). Ali me jako izluđuje kad ljudi krenu da pljuju recimo po proceduralnom programiranju, i kao OOP je majka svih stilova programiranja. Možda i jeste, ne ulazim u to šta je bolje... Ja sam programer, a posao programera je pre svega da napravi da nešto radi. Da li je on to uradio procedualno, objektno, ili kosmički, apsolutno je nebitno, klijentu posebno, ako program radi ono što treba da radi.

Što se tiče čitljivosti i šta ti ja znam... Čitljivo je i proceduralno, a i OO, AKO je dobro iskomentarisano i dokumentovano. Ako nije, džaba svi objekti na svetu, ako ne znaš šta oni rade... Pa zaboga, koliko godina su se isključivo proceduralni programi pisali? I to je neko održavao, ne? Dobra dokumentacija je majka...

Srećem se sa raznoraznim programima, koje su drugi radili, a na mene spalo da održavam, i tu ima svačega, a najmanje dobro dokumentovanog i OOP koda. Kada bih bio toliko isključiv, mogao bi da se oprostim od 90% posla koji mi dolazi.

Sve u svemu, kako kažu, "za dobru svinju nema loših pomija", tako i ja kažem, "za dobrog programera, ne postoji loš stil programiranja"...

Mislim da se to zaboravlja u poslednje vreme, svi su se nešto dali u dizajniranje, teoretisanje. Sedi prika lepo i programiraj, nije bitan način, bitno je da radi, i da je dobro dokumentovano...


EDIT:
I ja bih izbacio isRateable() iz view-a... Ionako po koncepciji, view prikazuje i samo prikazuje informacije, ne bavi se logikom... Sto masinac_1 rece, isto bih tako uradio...
[ mitke013 @ 19.06.2010. 14:26 ] @
Citat:
masinac_1: Ovako bih ja to uradio.
Zvezdice postoje bez obzira da li se moze glasati ili ne. Uostalom lepse je kad se vide svuda a ne kad je isarano (ako je to lista pa jedna pesma ima zvezdice a druga nema - kontam da jeste zbog foreach). Uz to zvezdice mogu da prikazu i rejting (prve dve recimo jedne boje a ostale druge boje - rejting 2).

Znaci isRatable() bih uklonio iz view dela. Ubacio ajax za glasanje, onclick u sam tpl. Jedna java funkcija po ucitavanju stranice poredi id svakog elementa (pesme) sa kolacicima i ako ima poklapanja uklanja onclick pa posetioc moze da klikce koliko hoce. Dodao bih isRateble() u akciju koja se poziva nakon klika na zvezdicu za svaki slucaj.

I ono za rejtig, zvezdice razlicite boje - isto js moze da uradi. PHP samo napravi taj element a js mu promeni klasu kao sto uklanja onclick.

[Ovu poruku je menjao masinac_1 dana 19.06.2010. u 15:06 GMT+1]


Evo problemi u tom pristupu:
1. sajt mora da radi i bez javascripte; klijent tako trazi zbog mobilnih telefona
2. nema jave u sajtu
3. ovo za zvezdice; klijent trazi zvezdice preko kojih moze da se glasa, ili da se ispise procenat (bas broj da pise tipa 87%) ako ne moze da se glasa. Dok me placa, ne postavljam suvisna pitanja
4. mislim da je prevelika komplikacija raditi preko js-a tu proveru; znaci da bi za npr. 25 pesama po listi (koliko je trenutno podeseno) moralo 25 puta preko ajax-a da se pita moze li se glasati za pesmu ili ne. Suvise, suvise i komplikovano i sporo. Logiku drzim dalje od Javascript-e; meni ce biti razumljivo, ali tesko i nekom ko nastavi moj program.

Mislim da sam se jedino za**bao to sto koristim smarty. Da sam koristio php kao templating engine, programer bi imao code completition. Al jbg, sad me nesto mrzi da menjam 40-50 stranica minimum, sajt je povelik (masala )

ps.
glasanje radi na sledeci nacin: svaka zvezdica ima <a href="{//url za glasanje}" class="ajax" target="#rating" >{slika zvezde}</a>
Ovo je primer, nije bas ovako ali da lakse razumes.

Ako je iskljucena JS, klik na zvezdicu vodi na moj kontroler koji prvo 'glasa' za pesmu, a zatim opet ucita istu stranicu.
Ako je ukljucena JS, jQuery ce detektovati 'class="ajax"', pa ce preko ajax-a da pozove isti kontroler (kao i gore) koristeci 'href' atribut. Kontroler ce preko metode isAjax() znati da ovaj put treba da ispise SAMO rezultat u procentima, a ne celu stranicu. JS ce preko atributa 'target' taj odgovor ispisati u id="#rating". Sve skupa je oko 7 linija JS koda jer sam ubacio zatamnjivanje tog id-a dok rezultat ne stigne preko ajax-a.

[ mitke013 @ 19.06.2010. 14:37 ] @
Citat:
galahad: Pratim temu od početka, al' reko' "aj' malo da zakuvam"
Koja je poenta OOP-a (odnosno kvazi-OOP) u jeziku koji nije OO?
...
Sve u svemu, kako kažu, "za dobru svinju nema loših pomija", tako i ja kažem, "za dobrog programera, ne postoji loš stil programiranja"...

Mislim da se to zaboravlja u poslednje vreme, svi su se nešto dali u dizajniranje, teoretisanje. Sedi prika lepo i programiraj, nije bitan način, bitno je da radi, i da je dobro dokumentovano...
EDIT:
I ja bih izbacio isRateable() iz view-a... Ionako po koncepciji, view prikazuje i samo prikazuje informacije, ne bavi se logikom... Sto masinac_1 rece, isto bih tako uradio...

Kako PHP nije oop?
To sto objekti nestaju nakon izvrsavanja skripte, isto je kao sto i funkcije i sve ostalo nestaje kad pises proceduralni kod. Ne razumem poentu. Drugo; da OOP nije bolji, ne bi svi frameworks-i i svi ozbiljni programi bili OOP. Ja zaista ne znam ni kako bi se izvrsilo testiranje (phpunit) proceduralnog koda, ali verovatno moze.
Citat:

Mislim da se to zaboravlja u poslednje vreme, svi su se nešto dali u dizajniranje, teoretisanje. Sedi prika lepo i programiraj, nije bitan način, bitno je da radi, i da je dobro dokumentovano..

Kod mene je drugaciji sistem jer uglavnom radim programe od nule. Vecina mojih klijenata je imala program koji 'radi', ali ga ne moze nastaviti niko sem originalnog autora. Uvek pokazujem moj program kad licitiram i dobijam posao bez problema jer imam taj minimalisticki pristup; sto manje koda, sto krace metode, bez parametara. Veruj, mnogo ljudi to ceni vise nego da program 'samo radi'.
Citat:

I ja bih izbacio isRateable() iz view-a... Ionako po koncepciji, view prikazuje i samo prikazuje informacije, ne bavi se logikom... Sto masinac_1 rece, isto bih tako uradio...

Nema problema, samo mi recite kako da izvedem to sto mi treba. I ja sam mnogo teoretisao oko ovoga, ali ne dolazim do bolje ideje od te. Masinac je predlozio JS, ali to ne dolazi u obzir jer sajt mora da radi i bez javascript-e. A i ne zelim da tako jednostavnu stvar zakomplikujem sa previse koda.
[ masinac_1 @ 19.06.2010. 14:40 ] @
Citat:
mitke013: za npr. 25 pesama po listi (koliko je trenutno podeseno) moralo 25 puta preko ajax-a da se pita moze li se glasati za pesmu ili ne. Suvise, suvise i komplikovano i sporo. Logiku drzim dalje od Javascript-e; meni ce biti razumljivo, ali tesko i nekom ko nastavi moj program.


Preko ajax-a samo glasanje, a uklanjanje onclick na osnovu kolacica - server nema pojma.
Ubacujes isRateble() u akciju u kontroleru koja se poziva kada se klikne na zvezdicu a ne za utvrdjivanje da li da je moguce onclick ili ne.

U svakom slucaju, radi kako ti kaze onaj ko te placa. Ja (pa i ostali cini mi se) komentarisem kako bi bilo ispravno, jednostavno i funckcionalno. :)
[ mitke013 @ 19.06.2010. 15:26 ] @
Citat:
masinac_1: Preko ajax-a samo glasanje, a uklanjanje onclick na osnovu kolacica - server nema pojma.
Ubacujes isRateble() u akciju u kontroleru koja se poziva kada se klikne na zvezdicu a ne za utvrdjivanje da li da je moguce onclick ili ne.

U svakom slucaju, radi kako ti kaze onaj ko te placa. Ja (pa i ostali cini mi se) komentarisem kako bi bilo ispravno, jednostavno i funckcionalno.


Razumemo se ko gluv i nem ; ako browser NEMA js (npr. neki mobilni telefoni), glasanje i dalje mora da radi. Kod pesama ce ili da ostavi mogucnost glasanja (preko tih zvezdica) ili ce samo da ispise procenat (87% i nista vise). Tvoj predlog zahteva ukljucenu JS kako bi se ili iscrtale zvezdice ili ispisao rezultat. Tako sam te razumeo.
ps:
pored cookies provere, metoda proverava jos i da li je korisnik ulogovan i da ulogovani korisnik nije vlasnik te pesme. Korisnik ne moze glasati za svoj fajl.
[ masinac_1 @ 19.06.2010. 15:37 ] @
Jasno mi je sta kazes. Nema js. Ok. :)
Naglasio sam u proslom postu samo to da se onclick omogucava u zavisnosti od kolacica a ne preko ajax-a pa server pa... itd. Ajax dolazi na red tek kada je moguc klik tj. kada se klikne.

Ako nema js onda tako kako radis i to je to. Jedino je pitanje gde ces da postavis prijem kolacica a gde logiku. Na tebi je odluka. :)
[ mitke013 @ 19.06.2010. 15:43 ] @
Citat:
masinac_1: Jasno mi je sta kazes. Nema js. Ok.
Naglasio sam u proslom postu samo to da se onclick omogucava u zavisnosti od kolacica a ne preko ajax-a pa server pa... itd. Ajax dolazi na red tek kada je moguc klik tj. kada se klikne.

Ako nema js onda tako kako radis i to je to. Jedino je pitanje gde ces da postavis prijem kolacica a gde logiku. Na tebi je odluka.


Ok, nisam te razumeo; malo mi zaribao 'onclick'

Stavio sam tu logiku za kukije u model da ne bih morao svuda $object->isRateable($_COOKIES['song_' . $object->id]) ; jer bih onda morao i da saljem $_SESSION['user_id']. jbg... tezak je zivot nas umetnika

Posto je ovo otislo malo offtopic, mod bi uskoro mogao i da malo skrati pricu. Moju, verovatno sam opet previse nasiroko pricao
[ masinac_1 @ 21.06.2010. 09:01 ] @
I sta je ustanovljeno vezano za pravilno OOP ? :) ...evo sta sam ja razumeo.

Grupisanje funckija u klasu i pozivanje pojedinih metoda bez pravljenja objekta nije OOP zbog odsustva objekta.
Isto takvo pozivanje nije strasno ako postoji objekat a potrebna je samo jedna mala metoda iz ogromne klase koja pozivanjem pravi veliki objekat (a nije potreban u tom momentu).
Ako postoji objekat i kroz njega se sve radi uz povremeno pristupanje metodi iz neke leve klase bez pravljenja objekat, postoje dakle klase i metode koje se koriste (u velikoj vecini slucajeva) preko $this to bi trebalo da bude OOP. Oscilacije i kompromisi mogu kod uciniti manje fleksibilnim, nepogodnim za nadogradju, razumevanje i slicno. Ali ako postoji objekat i postuje se filozofija OOP-a u osnovi, imamo metode i klase smisljeno rasporedjene i pristupa im se kako treba onda je i to OOP, samo los (zbog tih oscilacija).
Za MVC sam u poslednjih par postova rekao kako ga razumem, da ne ponavljam.

Jel tako?
[ mitke013 @ 21.06.2010. 12:55 ] @
Citat:
masinac_1: I sta je ustanovljeno vezano za pravilno OOP ? .


Ustanovljeno je sledece:
1. previse trolujem u slucaju nedostatka kofeina; sto rece moj tutor: radim na kafu i cigarete
2. ja sam zagovornik minimalistickog pristupa programiranju; sto iz obuke, sto iz iskustva, shvatio sam da se takav pristup uvek isplati. Kod je kraci, lakse se testira, mnogo se lakse radi refactoring
3. sem mene, ostatak komentatora preferira slanje parametara
4. bilo je takodje postova (mislim da su i oni stradali tokom poslednjeg ciscenja teme) gde je neko rekao da klase trebaju biti potpuno odvojene; to mi je suludo resenje jer program je (npr.) motor a klase su delovi tog motora. Samo zajednickim radom taj motor funkcionise. Konkretan primer je ono User::isLogged() koji interno poziva nekih 10-15 metoda mog programa (nije bitno zasto) u klasama Song, Category itd.... Ako bih krenuo tom logikom da tih 10 metoda ne sme da poziva metodu User::isLogged(), to znaci da bih 10 puta morao da napisem
Code:

public function imeMetode()
{
  if ( isset($_SESSION['user_id'] AND // ostatak uslova)
  // uradi nesto
}

Problem; ovde se proverava samo $_SESSION sto znaci da remember me funkcionalnost uopste ne postoji. Ako hocu i to jednog dana, onda moram da u svakoj od tih 10+ metoda ubacim i proveru stanja kukija. Za nije lakse:
Code:

public function imeMetode()
{
  if ( User::isLogged() AND // ostatak uslova)
  // uradi nesto
}

Poenta:
API je tu da sakrije interni rad. Sto bi gornju metodu trebalo uopste da zanima kako se proverava da li je korisnik ulogovan ili ne? Mozda pozelim da jednog dana koristim bazu za to?
5. mislim da ces morati da krenes od prve stranice. Pogledaj sta je ko rekao i zakljuci sam.
[ Goran Rakić @ 21.06.2010. 19:24 ] @
MVC obrazac nije isto što OOP stil programiranja. Postoji posebna tema o MVC obrascu. (Obrisane dve poruke viška iz ove teme.)
[ masinac_1 @ 21.06.2010. 21:27 ] @
@mitke013
A moze se i po statovanju sesije proveriti i podatak smestiti u objekat kao true/false, ili 1/2/3 uz sta bi mogle i privilegije da se odrede (recimo: registrovan, mod, admin) i to pozivati iz objekta.
Ovo je u sustini slicno tvom samo sto metoda kojom proveravas vrednost za userLogged trazi u objektu a ne direktno preko sesije/kolacia, to je uradjeno kad se startovala sesija sa metodom in one prve klase.

Jako je slicno, ali ima mala razlika. Sta je vise OOP... sta deluje da je vise OOP?

@Goran Rakić
Dobro kazes. I ja sam skrenuo sa teme.. al' reko pomenuto je u posledjih nekoliko postova pa ajd usput :) .. ipak to nije za ovu temu.
[ mitke013 @ 22.06.2010. 23:32 ] @
Citat:
masinac_1: @mitke013
A moze se i po statovanju sesije proveriti i podatak smestiti u objekat kao true/false, ili 1/2/3 uz sta bi mogle i privilegije da se odrede (recimo: registrovan, mod, admin) i to pozivati iz objekta.
Ovo je u sustini slicno tvom samo sto metoda kojom proveravas vrednost za userLogged trazi u objektu a ne direktno preko sesije/kolacia, to je uradjeno kad se startovala sesija sa metodom in one prve klase.


Ako sam te razumeo, i ne bas. User::isLogged() je ovo:
Code:

        public static function isLogged()
        {
            return isset($_SESSION['userID']) ;
        }


Nema kreiranja objekta dok bas ne zaskripi . Tj:
Code:

        /**
        * Return instance of logged User
        * @return User
        */
        public static function getLogged()
        {
            if ( !self::isLogged() )
                throw new Exception('User is not logged in') ;
            if (self::$loggedUser==null){
                $loggedUser = Doctrine_Query::create()
                    ->from('User u')
                    ->where( 'u.id=?', $_SESSION['userID'] )
                    ->fetchOne() ;
            
                self::$loggedUser = $loggedUser ;
            }
            return self::$loggedUser ;
        }


self::$loggedUser se koristi kako se ne bi instancirao isti objekat kad god nam treba logovani korisnik. Tj. samo prvi put ce se raditi instanca citanjem iz baze, od tada pa nadalje se koristi isti objekat.
[ mitke013 @ 24.07.2010. 10:27 ] @
Citat:
Rekao sam ti već, ubrizgaj taj $_COOKIE['nesto'] spolja kao parametar metode. Nemoj da koristiš globalnu promenljivu unutar klase, to nije enkapsulacija, to je prikrivanje kompleksnosti i mazanje očiju.

Još bolje ako taj $_COOKIE predstavlja posetioca, penesi objekat posetioca ili sesije kao parametar.

Sada tvoja klasa ne izlazi više u globalni prostor da zahvati svoj kontekst. Drugo, pisanje unit testova je lakše jer sada možeš lepo da preneseš vrednost $_COOKIE i proveriš metod za različite situacije. Treće klasu možeš i da iskoristiš u kodu koji se ne izvršava preko veb servera i umesto $_COOKIE koristiš nešto drugo.

Razmisli i da li ti se isplati da refaktorišeš kod tako da ovaj uslov o logovanju izmestiš spolja, tj. da isReatable() proveri da li vlasnik pesme nije preneti korisnik i možda još neke druge uslove, a da grananje vršiš po uslovu ($user->isLogged() && $song->isReatable($user)). Onda iz nekog trećeg koda možeš da ignorišeš ovo o prijavi i skriptom oceniš pesme za korisnika Peru Perića ako nisu njegove, nešto što bez refaktorisanja ti ne možeš da izvedeš. To bi bilo poštovanje dogovora o nadležnostima. Pesmu ne zanima da li je korisnik prijavljen.


Kako dugo nisam trol.... postovao nista, rekoh da posaljem nesto i obradujem siroke narodne mase svojim nepresusnim znanjem

Elem; bas juce, klijent je pozeleo da umesto kukija koji traju neko vreme (podesivo iz admin dela, mislim da je 30 dana), glasanje bude moguce izvesti samo jednom. Znaci baza. Kako se glasanje za pesmu moze obaviti na ~8-9 razlicitih stranica, dogovorili smo cenu od 50 evra jer covek nema pojma da je meni trebalo 15 minuta da izmenim samo tu famoznu metodu isRateable() (obrati paznju; nema parametara i dalje) gde sam uslov iz kukija zamenio citanjem podatka iz baze. Metoda Song::rate($rate) je takodje pretrpela izmene; umesto da salje kuki, glas se upisuje many-2-many u SongVoting tabelu . Da sam slusao vase savete, pored ovih metoda morao bih da menjam i tih 8-9 stranica, samo za glasanje za pesmu. Verovatno mu ne gine jos minimum 50e jer u programu postoji glasanje i za albume i za korisnike.

Sta je jos i poenta? Covek je bio presrecan sto sam to izmenio za tako sitnu lovu, misleci valjda da cu morati sve te stranice da menjam, testiram da li rade itd. A ja sam to uradio pisuci Phpunit test i proverio samo jednu stranicu preko browser-a.

Mislim da ovo jos jednom pokazuje zasto je vazno koristeci moj minimalisticki pristup. Zamislite da umesto 8-9 stranica, imate 20++ koje koriste 'neku' cesto koriscenu metodu (nije vazno koja, bitna je poenta). To sto je metoda citanjem kukija izasla u 'globalni prostor' nema nikakve lose strane; to je globalni prostor pa je globalni, znaci da je namenjen pristupu sa bilo koje strane u bilo kom trenutku.
PS:
to nije isto sto i koriscenje 'global' funkcije.
[ lermi @ 17.08.2010. 15:08 ] @
Pratio sam čitavu temu, pa pošto je ne nekoliko mjesta otišla u off (jer je ovo PHP forum), htio nih nešto da pitam. Valjda se može primijeniti na PHP.

1. Buni me kada kažete da je bolja praksa u kojoj metode u klasi ne dobijaju parametre. Kako onda da ih ubacim u klasu? Javnim atributima? Neko se pobunio protiv goriščenja "global" - ovo se ne odnosi na public atribute u klasi?

2. Recimo da imam 100 fajlova koji se obrađuju jednom klasom. Da li je bolje za svaki fajl u petlji kreirati novu instancu klase, ili napraviti jedno instancu pa pozivati Obrada.load(fajl) i Obrada.run()?


[ Goran Rakić @ 17.08.2010. 15:14 ] @
Citat:
lermi: 1. Buni me kada kažete da je bolja praksa u kojoj metode u klasi ne dobijaju parametre. Kako onda da ih ubacim u klasu? Javnim atributima? Neko se pobunio protiv goriščenja "global" - ovo se ne odnosi na public atribute u klasi?


Koliko se sećam, samo jedan učesnik teme to kaže.


Citat:
2. Recimo da imam 100 fajlova koji se obrađuju jednom klasom. Da li je bolje za svaki fajl u petlji kreirati novu instancu klase, ili napraviti jedno instancu pa pozivati Obrada.load(fajl) i Obrada.run()?


Da li Obrada zavisi samo od datoteke koja se obrađuje ili ima i neka spoljna svojstva? Ako ima, ja bih inicijalizovao klasu, to je valjda service obrazac, i onda pozvao nad svakom datotekom u petlji. Ukoliko postoje neke specifičnosti obrade, napravio bih male klase koje predstavljaju svaku vrstu obrade, i onda bi ih servis pozivao (to je valjda delegate/helper obrazac)
[ mitke013 @ 17.08.2010. 15:43 ] @
Citat:
lermi: Pratio sam čitavu temu, pa pošto je ne nekoliko mjesta otišla u off (jer je ovo PHP forum), htio nih nešto da pitam. Valjda se može primijeniti na PHP.

1. Buni me kada kažete da je bolja praksa u kojoj metode u klasi ne dobijaju parametre. Kako onda da ih ubacim u klasu? Javnim atributima? Neko se pobunio protiv goriščenja "global" - ovo se ne odnosi na public atribute u klasi?

Goran je u pravu, to sam jedino ja tvrdio i kroz brdo primera, verujem i dokazao.

Nisi razumeo poentu. Naravno da moras da imas parametar ako zelis da preimenujes neku slika npr. 'slika.jpg'. Tada bi radio $image->rename('ja na moru')->save() a ta instance bi fajl preimenovala u 'ja-na-moru.jpg' . Ako taj fajl vec postoji, onda bi preimenovala u 'ja-na-moru-1.jpg' itd. Ovo je zbog google-a jer sam negde procitao da pretrazivaci vole ovakva imena fajlova.

Cela prica se najvise odnosila kroz primer o glasanju za neku pesmu. Umesto da se koristi metoda $song->isRateable() bez parametara jer instanca moze i sama da zakljuci da li se moze glasati ili ne, bilo je predloga poput:
Song::isRateable($songId, $_COOKIE['$songId'], $_SESSION['userID'], .... ), ili da se to resi javascriptom ?!? i slicno. Mrzi me bas da gledam opet gomilu postova.
Prakticno, saljes nesto sto instanca moze da izvuce; suvisno. Mozda jednog dana hocu da se to resi citanjem podatka iz baze sto se i desilo; pogledaj opet ovaj post kad se ta situacija konkretno i desila. Da sam koristio princip slanja brda parametara, bilo bi mi potrebno mnogo vise od 15 minuta za refactoring. Morao bih da promenim svaki template (sajt je poveci) gde prikaz zavisi od toga da li se za pesmu/album/korisnika moze glasati ili ne.
Ako ukapiras ovaj problem, vrati se opet na moju pricu o jadnom vojniku, letecoj metli i zlom kapetanu.
Citat:

2. Recimo da imam 100 fajlova koji se obrađuju jednom klasom. Da li je bolje za svaki fajl u petlji kreirati novu instancu klase, ili napraviti jedno instancu pa pozivati Obrada.load(fajl) i Obrada.run()?


Nisam bas siguran da sam razumeo problem, ali ajde da probam. Ako imas 100 fajlova, verovatno imas i 100 upisa u bazu sto je i logicno (zbog referenci tipa one-2-many, many-2-many itd). Ako su to recimo 100 slika kojima hoces da promenis velicinu thumbnail-a, ja bih kreirao 100 instanci na sledeci nacin:

Code:

$allImages = ImageTable::getInstance()->createQuery()->execute() ; // ovo ce da kreira niz sastavljen od instanci klase Image za svaku sliku koju imas

foreach ($allImages as $image)
  $image->resizeThumb(100,80)->save() ;


Mislim da ti je najbolje da celu temu pazljivo procitas i sam doneses zakljucak. Ali pazljivo, jer ipak sam ja jedini bio zagovornik teorije 'objekat je tu da nesto uradi a ne da bude drzac funkcija', sto ti izgleda promaklo
[ Goran Rakić @ 17.08.2010. 15:47 ] @
Citat:
mitke013: ipak sam ja jedini bio zagovornik teorije 'objekat je tu da nesto uradi a ne da bude drzac funkcija', sto ti izgleda promaklo :


Ovo nije tačno, a moglo bi da se razume i kao uvredljivo.

Citat:
...createQuery()->execute() ; // ovo ce da kreira niz sastavljen od instanci klase Image za svaku sliku koju imas


Zato što imaš višak memorije, pa da se ne baci?


[ mitke013 @ 17.08.2010. 16:16 ] @
Citat:
Ovo nije tačno, a moglo bi da se razume i kao uvredljivo.


Mislim da nije uvreda nekom reci da mu nesto promaklo u citanju 50KB teksta. Malopre sam pogledao sve postove (na brzaka) i cini mi se da mi jedino dakipro dao podrsku ovde .

Citat:
Zato što imaš višak memorije, pa da se ne baci?


hmm.... Koga briga za memoriju? Taj veliki program koji sam radio je zahtevao migraciju stare baze na novu. Tu je bilo oko 600 slika i 1200 mp3 fajlova. Za svaku sliku se kreira i thumbnail posto stari program to nije radio; ako posetioc ode na listu top25 pesama, a pesma ima sliku od 200KB, stari kod je to ucitavao pa osedis dok se ne ucita cela stranica. Znaci, mora thumb.

Isti kod iz gornjeg primera sam koristio za migraciju tih slika i kreiranje thumb-a. Na serveru je memory limit za proces standardnih 64MB, nikakav problem nije bio. Jedino sto sam jos dodao je $image->free() nakon snimanja, kako bi se oslobodili resursi. Linija koja bi trebala da se doda u gornji kod.

Kako zapravo OOP radi; samo prva instanca neke klase zauzima puno prostora. Npr. instanca klase Image nek zauzme 2MB; realno je posto koristim Doctrine koji nije neki stedisa. Svaka naredna instanca ne uzima vise od 100KB. Ne zaboravi da je to instanca u active-record patternu; znaci OOP prikaz kolone iz tabele. Fajl na koju cilja kolona 'filename' se ne ucitava u memoriju dok ne zatreba.
[ lermi @ 17.08.2010. 16:27 ] @
@Goran Rakić
Razmijem. Očito je cilj napraviti vrlo preciznu raspodjelu posla, radi veće efikasnosti.

@mitke013
Pročitao sam temu od početka, posebno Safirov post i raspravu o skrivenim metodama i sjetio sam se kako ja mogu da preradim neke svoje programe. Nažalost, malo sam teže ispratio tvoje zvjezdice, više me je interesovala programerska praksa.

Razumijem ja da objekat mora da dobije parametre, ali moja dilema je šta je najbolja praksa. Ali me buni da li je riječ o a) globalnom namespaceu (koji je dostupan apsolutno svemu) ili b) namespaceu klase.

Ja nikad ne bih odjednom stvorio 100 istih instaci u memoriji, kao što ti predlažeš. Ni na pamet mi nije palo da to uradim, niti jednom (pogotovo ne na serveru). Pitanje je glasilo, u principu, da li klasu treba stvoriti 100 puta dajući joj svaki put nove parametre za inicijalizaciju, ili je treba stvoriti samo jednom, mijenjajući samo atibute?

Uzgred, ti ovdje nisi jedini koji pravi razliku između proceduralnog i OO programiranja, funkcija i parametara, metoda i atributa...


[ Tudfa @ 17.08.2010. 17:13 ] @
Citat:
mitke013
Code:
$allImages = ImageTable::getInstance()->createQuery()->execute() ; // ovo ce da kreira niz sastavljen od instanci klase Image za svaku sliku koju imas

foreach ($allImages as $image)
  $image->resizeThumb(100,80)->save() ;


Uf.. Nije ovde samo problem memorija, vec i vreme izvrsavanja. Ne znam da li je sistem tako organizovan da je velicina thumb-a uvek ista ?
Ako jeste, zasto bi svaka instanca klase Image nosila informaciju o velicini thumb-a, umesto da to stoji u nekoj config tabeli ?
I samo na jednom mestu radis update ?

Drugo, recimo da hoces da radis update nekog tamo polja i setujes mu novu rednost, istu za svaki red, kao sto si u ovom primeru radio ( i da se to odrazi na 100 redova),
jesi razmisljao da radis jedan update sa WHERE klauzulom ? Da li si svestan koliko je velika razlika u vremenu izvrsenja,
kad radis jedan UPDATE sa WHERE i 100 UPDATE-a tako u for petlji (plus zauzece memorije za kreiranje objekata) ?

Mislim da bih ovo update-ovanje prvo trebalo probati da se izvede jednim upitom, pa ako nije zgodno, raditi drugacije.

Nesto ovako:
Code:
$ids = array(...);//ovde skupis id slika cije to neko polje hoces da promenis

$query = "...";//kreiras upit, iskoristis petlju

$db->query($query);//izvrsis upit koji si dinamicki kreirao

I taj upit jedan upit ce se izvrsiti oko 30-40 puta brze, ako ne verujes probaj sam jer ja sam imao slicnu situaciju,
i nije isto kad ti se update koji ce se odnositi na 300 redova izvrsi za 1.5 sec i za 0.04 sec.

Btw, nemoj da shvatis ovo kao neko odvracanje citalaca od tvog nacina rada, ima i on svojih prednosti...
Ovo se odnosilo samo na brojke.
[ Tudfa @ 17.08.2010. 17:49 ] @
Citat:
mitke013:To sto je metoda citanjem kukija izasla u 'globalni prostor' nema nikakve lose strane; to je globalni prostor pa je globalni, znaci da je namenjen pristupu sa bilo koje strane u bilo kom trenutku.
PS:
to nije isto sto i koriscenje 'global' funkcije.
Sa ovim bih se slozio, i procitao sam postove protiv ovoga, i i dalje ne vidim neki praktican razlog zasto to ne raditi bas tako.
A izgleda da i programerska ekipa iz Zend-a nema nista protiv toga, jer se taj princip koristi u klasama ZF-a. Jednostavno lakse, manje komplikovanja..
[ mitke013 @ 17.08.2010. 18:47 ] @
Citat:
Tudfa: Uf.. Nije ovde samo problem memorija, vec i vreme izvrsavanja. Ne znam da li je sistem tako organizovan da je velicina thumb-a uvek ista ?
Ako jeste, zasto bi svaka instanca klase Image nosila informaciju o velicini thumb-a, umesto da to stoji u nekoj config tabeli ?
I samo na jednom mestu radis update ?

Moram da ispravim sebe; kod koji sam postovao NIJE taj koji sam zapravo i koristio. Sad sam pogledao moju Image klasu i evo kako izgleda taj deo za thumb:
Code:

        /**
        * After saving to DB, check if image is changed (like resized) and update image and thumb if needed
        * 
        * @param Doctrine_Event $event
        */
        public function postSave(Doctrine_Event $event)
        {       
            if ( $this->imageChanged ){
                $image = $this->getWorkingImage() ;
                $image->save( $this->getFilePath() ) ;
                
                $thumb = $image ;
                $thumbName =$this->getThumbPath() ;
                $thumb->adaptiveResize($this->getThumbWidth(), $this->getThumbHeight()) ;
                $thumb->save($thumbName ) ;
                
                $this->imageChanged = false ;
            }
            parent::postSave($event) ;
        }

        /**
        * Set size of created thumbnails
        * 
        * @param integer $width
        * @param integer $height
        */
        public function setThumbSize($width=false, $height=false)
        {
            if ($width)
                $this->thumbWidth = $width ;
            if ($height)
                $this->thumbHeight = $height ;
        }

        /**
        * Get thumb width; returns default from Settings if none is provided from controller
        */
        protected function getThumbWidth()
        {
            return $this->thumbWidth==null ? Settings::getInstance()->getThumbWidth() : $this->thumbWidth ;
        }
        
        /**
        * Get thumb height; returns default from Settings if none is provided from controller
        */
        protected function getThumbHeight()
        {
            return $this->thumbHeight==null ? Settings::getInstance()->getThumbHeight() : $this->thumbHeight ;
        }


Znaci; ako nisi podesio velicinu thumba pozivom $image->setThumbSize(x,y), instanca image ce uzeti vrednosti koje su u settings.ini fajlu a citaju se Settings klasom. Migracije sam obrisao da bih video bas tacan kod za to, ali recimo da je samo ovo:
Code:

foreach ($allOldImages as $oldImage) {
  $image = Image::createFromFilename($oldImage->.... kolona koju je prethodni programer koristio..) ;
  if ( $image->isValid() )  
    $image->save() ;
  $image->free() ;
}


Ovo iznad je API kako se koristi moja klasa. Validacija (izmedju ostalog) proverava da li je fajl zaista jpg, gif ili png, ostale formate ne dozvoljava (nije bitno zasto).
Citat:


Drugo, recimo da hoces da radis update nekog tamo polja i setujes mu novu rednost, istu za svaki red, kao sto si u ovom primeru radio ( i da se to odrazi na 100 redova),
jesi razmisljao da radis jedan update sa WHERE klauzulom ? Da li si svestan koliko je velika razlika u vremenu izvrsenja,
kad radis jedan UPDATE sa WHERE i 100 UPDATE-a tako u for petlji (plus zauzece memorije za kreiranje objekata) ?
...

Btw, nemoj da shvatis ovo kao neko odvracanje citalaca od tvog nacina rada, ima i on svojih prednosti...
Ovo se odnosilo samo na brojke.


Ne zaboravi jedno: slika mora da se ucita, resizuje na odredjenu velicinu, uradi validacija i tek onda snimi. Zato mora da se to uradi jedna po jedna slika. Bulk update tabele ne vazi u ovom konkretnom slucaju.
[ mitke013 @ 17.08.2010. 18:59 ] @
Citat:
Tudfa: Sa ovim bih se slozio, i procitao sam postove protiv ovoga, i i dalje ne vidim neki praktican razlog zasto to ne raditi bas tako.
A izgleda da i programerska ekipa iz Zend-a nema nista protiv toga, jer se taj princip koristi u klasama ZF-a. Jednostavno lakse, manje komplikovanja..

Hvala, nisam znao za ovo. Mozda ekipa iz Zend-a prati ovaj forum i krade ideje?
[ Tudfa @ 17.08.2010. 19:54 ] @
Ja to gledam ovako:

Kao sto je u okviru magicne metode __get() iz Zend_Controller_Request_Http klase,
potrebno da se pristupi nekoj od superglobals da bi uradila potreban posao,
tako si i ti imao potrebu da u svojoj klasi u nekoj metodi pristupis nekoj od superglobals.

Stoji da su te klase razlicite namene,
ali zajednicko za obe klase je da im je u okviru metoda bilo potrebno da pristupe nekoj od superglobalnih promenljivih da bi obavile posao.

A tu sad dolazimo do onoga, zasto u metodi gde je potreban pristup superglobalnoj promenljivoj,
u tvom slucaju klasa Song(ako se ne varam), to ne raditi nego proslediti parametar, sto je to korisno, kad je ovo nekako prirodnije ?

Iskreno nikad nisam o ovome razmisljao mnogo, jednostavno sam koristio superglobals direktno tamo gde mi zatreba.
[ masinac_1 @ 18.08.2010. 00:31 ] @
Citat:
mitke013: Song::isRateable($songId, $_COOKIE['$songId'], $_SESSION['userID'], .... ), ili da se to resi javascriptom ?!? i slicno. Mrzi me bas da gledam opet gomilu postova.

Mitke legendo... stalno nesto zakomplikujes. :))

Priznajem da se nisam puno upustao u razumevanje svakog napisanog posta, neke cak nisam ni procitao u celosti. Ali sto se tice ovog ..->isRateable() i javascript-a secam se tacno o cemu se radilo... i kontekst u kom si to pomenuo uopste ne ogovara onome o cemu je zapravo bilo reci.
Mozda mislis na neku drugu situaciju gde se pominjalo resenje sa js (samim tim bez metode isReateble)?

Uglavnom, isReatable se nalazi u view delu gde po filozofiji MVC-a ne treba da bude. Moj predlog je bio, ako vec hoces da radis ispravno (sa akcentom na OOP-u), da izbacis logiku iz view dela (prosiris akcenat i na MVC). Da napomenem da i ja pozovem neku metodu (to su ustvari view helperi) iz view-a, ali posto nastojis da radis sto ispravnije, onda sa tog stanovista isReatable nema sta da trazi u view. :)
Zato sam predlozio da view servira kod browser-u normalno kao da je moguce glasanje, a js da na osnovu kolacica po ucitavanju iskljuci mogucnost glasanja, usput sredi zvezdice da prikazuju rejting itd. A u akciji koja odradjuje glasanje normalno dodati proveru da je korisnik autorizovan.
Verovatno bih uradio kao ti (ako zanemarim pravilo mvc-a). Ovo sto sam predlozio definitivno nije za "?!?" jer je jasno i u zavisnosti od situacije moze da bude resenje ako izbacujes logiku iz view. Ponovih opet... valjda si sad razumeo. :)

edit:
E da, ovo sa slikama i zauzecem memorije... pa stvarno, zar nije cilj programera da poveca kapacitete softverskim putem, a ne kupovinom hardvera? Naravno kada i ako je u mogucnosti. Ovde je evidentno da se lako moze uticati na performanse bez nadogradnje hardvera.
[ mitke013 @ 18.08.2010. 11:19 ] @
Citat:
masinac_1: Mitke legendo... stalno nesto zakomplikujes. )

Haha... Pa znas kako je; sunce przi, forum jedva ziv, mrzi me da radim, sportska povreda me sprecava za neki basket.... Negde to mora da izadje
Citat:

Priznajem da se nisam puno upustao u razumevanje svakog napisanog posta, neke cak nisam ni procitao u celosti. Ali sto se tice ovog ..->isRateable() i javascript-a secam se tacno o cemu se radilo... i kontekst u kom si to pomenuo uopste ne ogovara onome o cemu je zapravo bilo reci.
Mozda mislis na neku drugu situaciju gde se pominjalo resenje sa js (samim tim bez metode isReateble)?

Uglavnom, isReatable se nalazi u view delu gde po filozofiji MVC-a ne treba da bude. Moj predlog je bio, ako vec hoces da radis ispravno (sa akcentom na OOP-u), da izbacis logiku iz view dela (prosiris akcenat i na MVC). Da napomenem da i ja pozovem neku metodu (to su ustvari view helperi) iz view-a, ali posto nastojis da radis sto ispravnije, onda sa tog stanovista isReatable nema sta da trazi u view.
Zato sam predlozio da view servira kod browser-u normalno kao da je moguce glasanje, a js da na osnovu kolacica po ucitavanju iskljuci mogucnost glasanja, usput sredi zvezdice da prikazuju rejting itd. A u akciji koja odradjuje glasanje normalno dodati proveru da je korisnik autorizovan.
Verovatno bih uradio kao ti (ako zanemarim pravilo mvc-a). Ovo sto sam predlozio definitivno nije za "?!?" jer je jasno i u zavisnosti od situacije moze da bude resenje ako izbacujes logiku iz view. Ponovih opet... valjda si sad razumeo.

Ma razumeo djavola verovatno. Gle; ti si ovim predlogom logiku iz view dela prebacio u logiku javascript-e. Sto je iskreno, losije resenje cak i od Song::isRateable($songId, @$_COOKIE[$songId], @$_SESSION[]... )

Trebao si da procitas ceo post (gore si naglasio da nisi sve procitao). Ja imam petlju tipa

Code:

foreach ($allSongs as $song) {
  if ($song->isRateable()
   // iscrtaj zvezdice
}

... i to je to. Logika se nikad ne moze izbaciti 100% iz view dela; cak se i foreach moze smatrati nekom logikom. Ovaj moj dodatni 'if'; JS ne dolazi u obzir jer je ovo php problem, znaci da je if u view delu zaista neophodan. Ali je ovo tema o slanju parametara metodi ili ne.
Citat:


edit:
E da, ovo sa slikama i zauzecem memorije... pa stvarno, zar nije cilj programera da poveca kapacitete softverskim putem, a ne kupovinom hardvera? Naravno kada i ako je u mogucnosti. Ovde je evidentno da se lako moze uticati na performanse bez nadogradnje hardvera.


Ne

Kakav crni hardware, ja sam cicija koja placa shared hosting od $10 mesecno na hostgatoru. Ogranicenja su: 64MB po procesu, 25% CPU zauzeca ne duza od 2 minuta i 25 DB konekcija po sekundi. Sve ostalo je neograniceno. U gornjim primerima sam objasnio kako brdo instanci iste klase zauzima smesnu memoriju. Drugo; migraciju necega radis samo jednom. Ne mogu da zamislim nijedan sajt koji bi na stranici prikazao 600 slika php-om (tipa <img src="show.php?id=15">), pa da se mozda i prekoraci ovaj limit.
Verujem da i ostale hosting kompanije imaju slicna ogranicenja.
Poenta:
Doctrine+Smarty koje koristim mi zauzmu oko 6MB. Program o kome je rec u peak-u zauzme 10 MB i to samo na prvoj stranici. Na njoj ima:
1 instanca klase Banner
2++ instanci klase Translation; trenutno su dve jer je sajt na spanskom i engleskom
5++ instanci klase News; toliko trenutno ima vesti koje se prikazuju
30 instanci klase Song koje se ucitavaju iz 6 puta po 5 komada, zavisno od broja pregleda, ocene itd.
oko 30 instanci klase Category
8 instanci klase Staticpage
5 instanci klase Image za najaktivnije korisnike

Pritom:
Klase News, Category i Staticpage imaju prevode sto znaci da se radi 'leftJoin' sa prevodom tipa CategoryTranslation itd
Za Songs se radi leftJoin sa Dailyvisits i Statistics tabelama/klasama.
Na sve to dodaj 213 'recenica' za prevod sajta koje se ucitavaju za svaku stranicu.

Sve to se izvrsi za ~400ms i zauzme dodatnih 4MB na mom shared serveru. Da li sad razumes zasto se ne treba zezati sa optimizacijom? Ta prva stranica je bas prepunjena, a opet sam zauzeo tek 1/6 dozvoljene memorije.
I jos:
Sve ovo su bas instance objekata. Doctrine moze rezultate da vrati i kao array i da ustedi memoriju i poveca brzinu. Ali.... 4MB i 400ms za sve ovo? Koga briga za HYDRATE_ARRAY...

Za modove:
ovo za HG nije reklama jer vidite da nigde nema referal link. Mislim da ne krsi TOS.

PS:
Uz sliku je screenshot zauzeca memorije. Kod za ovo je:
echo memory_get_peak_usage() .'<br />' ;
echo memory_get_usage() .'<br />' ;

Nek me neko ispravi ako sam pogresio kako se meri zauzece.

[ masinac_1 @ 18.08.2010. 19:50 ] @
Procitao sam tvoj post i znam za tu petlju. Kontas da se bas na njoj i zasniva to sto sam napisao :D

Kako bre covece moze da bude losije resenje?! Logika je u metodi do koje se dolazi posle klika na zvezdicu. Js je tu kao prilikom registrovanja da proveri unete podatke, ali ti podaci prolaze proveru i kroz php. Js je nekako usput tu.

Ajd, dobro... misljenja sam da ces tesko naci browser u kom je iskljucen js, tako da je cak i pozeljno u nekim situacijama rasteretiti php tako sto se deo posla prenese u js. U tvom slucaju kazes mora bez js, ok.. ali to si na kraju rekao. Moje resenje nije za takvu situaciju, ali da je blesavo, pa tesko... u protivnom google, youtube i sl. rade totalno pogresno. :)
[ Goran Rakić @ 18.08.2010. 19:56 ] @
Citat:
mitke013
Da li sad razumes zasto se ne treba zezati sa optimizacijom? Ta prva stranica je bas prepunjena, a opet sam zauzeo tek 1/6 dozvoljene memorije.


To znači da ne možeš da imaš više od šest simultanih poseta. Vreme odziva stranice ti je preko 1s (400ms + output + dok prođe kroz mrežu), što je jako sporo. Generalno, veoma si aljkav.

Podržavam stav da su prerane optimizacije nepotrebne, ali imati sistem koji se ovako rasipa nije za ponos.

Koliko upita izvršavaš za tu jednostavnu stranicu?
[ mitke013 @ 19.08.2010. 00:33 ] @
Citat:
Goran Rakić: To znači da ne možeš da imaš više od šest simultanih poseta. Vreme odziva stranice ti je preko 1s (400ms + output + dok prođe kroz mrežu), što je jako sporo. Generalno, veoma si aljkav.

Podržavam stav da su prerane optimizacije nepotrebne, ali imati sistem koji se ovako rasipa nije za ponos.

Koliko upita izvršavaš za tu jednostavnu stranicu?


Ja aljkav? Prilicno jaka rec za nekog ko predlaze Song::isRateable($songID, @$_COOKIE[nesto], @$_SESSION[nesto]).... Ove @ simbole moras da stavis kako bi sprecio ispis gresaka ako element ne postoji. I ja aljkav?

Vrati se na moje postove gde lepo pise sledece:
64 MB po procesu!

To znaci po PHP procesu, ne po sekundi. Po sekundi mi jedini limit 25 konekcija, sto takodje lepo pise gore.

Gorane; zasto je toliki problem procitati moju poruku? I ja sam kao OOP pocetnik prvo pitao 'zar gomila instanci ne zauzima previse memorije', pa kad sam dobio odgovor, vise nisam postavljao takva pitanja. Ako sam gore SVE lepo objasnio, cemu onda prozivka da sam aljkav? Navodno si 'oop guru', a sa druge strane postavljas ovakva pitanja, iznova i iznova.

Ali dobro; jednom si izjavio da je OOP 50 puta sporiji od proceduralnog, verovatno sam sam kriv sto nisam odmah ukapirao sa kakvim 'strucnjakom' pricam.
ISPRAVKA: Moja greska, ovo nije Goran izjavio vec drugi clan.

A u primerima mog koda se aljkavost zaista nigde ne moze videti. Tvoj primeri; samo jedan koji je koristio 'global'. Sve ostalo je copy&paste definicija prepisana iz nekog udzbenika. Ti bas nikad nista nisi konkretno rekao.

Drugo:
400ms za sve sto sam naveo je nikakvo vreme. Opet pricas 'gluposti' (kako ti volis da opisujes): dok prođe kroz mrežu!? Da ne treba mozda i da posetiocima sajta platim brz net mozda? Treptaj oka ti 400ms; jel ti pricas samo da bi nesto rekao? Koliko vreme tvoji programi (koje sumnjam da uopste imas) trose CPU vremena? Da li uopste razlikujes vreme izvrsavanja logike od vremena ucitavanja sajta? Sta ako stranica treba da prikaze sliku od 3 MB; da nije mozda moj PHP kriv i za sporo ucitavanje kod korisnika na modemu?

Nakon sto je Tupfa rekao da Zend koristi isti nacin rada kao i ja, vise ne komentarises ovo o 'superglobals' i kako je glupost to sto metoda ume i sama da uzme to sto joj treba. Verovatno nije 'glupost' kad neko zvucno ime tipa Zend radi tako, ali ako to ja predlozim, i time poljuljam tvoj imidz samoproklamovanog gurua, prica je skroz drugacija.

Verovatno ces kao mod da obrises ovu poruku, ali ovo nije prvi put da me direktno prozivas tako da cu je sigurno obnavljati. Da me proziva neko ko je pokazao da zna da programira; nema problema, poklonimo se kralju i slicne stvari. Ali ovakve gluposti, pogotovo na es-u, tesko mogu da ignorisem.

Citat:
Ajd, dobro... misljenja sam da ces tesko naci browser u kom je iskljucen js, tako da je cak i pozeljno u nekim situacijama rasteretiti php tako sto se deo posla prenese u js. U tvom slucaju kazes mora bez js, ok.. ali to si na kraju rekao. Moje resenje nije za takvu situaciju, ali da je blesavo, pa tesko... u protivnom google, youtube i sl. rade totalno pogresno.

Problem nastaje kad sajt posecuju botovi; oni se ponasaju kao browser bez JS.

[Ovu poruku je menjao mitke013 dana 19.08.2010. u 13:05 GMT+1]

[Ovu poruku je menjao mitke013 dana 19.08.2010. u 13:06 GMT+1]
[ Goran Rakić @ 19.08.2010. 02:00 ] @
Nemam nameru da brišem tvoju poruku, ne znam zašto stalno pokrećeš to pitanje. Ni jednom ti nisam obrisao poruku u kojoj iznosiš kritiku na moj račun, uopšte nemam problem sa takvim porukama.

Inače, memory_limit koji sada vidim da hostgator koristi ne određuje limit po procesu kako si napisao već je to interni limit unutar PHP-a pri alokaciji i važi za jedno izvršavanje skripta. Osim pri obradi spoljnih datoteka to je sasvim dovoljno za bilo šta rasipnički što zamisliš. Ograničenje po Apache procesu je nešto sasvim drugo, pošto je to onda limit na memoriju koje dele sve niti unutar učitanog php modula.

Ja uopšte ne komentarišem koliko objekti zauzimaju prostora, sam si rekao da tvoja skripta traži 4MB u vrhu.

Ne znam gde sam izjavio da je OOP 50 puta sporiji od proceduralnog?

Ostale komentare nisi razumeo i pogrešno ih tumačiš (global, cookie, unit test, poziv metode, vreme izvršavanja), pa nema svrhe da se raspravljamo.




[Ovu poruku je menjao Goran Rakić dana 19.08.2010. u 03:21 GMT+1]
[ mitke013 @ 19.08.2010. 12:02 ] @
Citat:
Goran RakićNemam nameru da brišem tvoju poruku, ne znam zašto stalno pokrećeš to pitanje. Ni jednom ti nisam obrisao poruku u kojoj iznosiš kritiku na moj račun, uopšte nemam problem sa takvim porukama.

Mislim da bi trebao da ih obrises jer ovo prelazi u trolovanje.
Citat:

Inače, memory_limit koji sada vidim da hostgator koristi ne određuje limit po procesu kako si napisao već je to interni limit unutar PHP-a pri alokaciji i važi za jedno izvršavanje skripta. Osim pri obradi spoljnih datoteka to je sasvim dovoljno za bilo šta rasipnički što zamisliš. Ograničenje po Apache procesu je nešto sasvim drugo, pošto je to onda limit na memoriju koje dele sve niti unutar učitanog php modula.

Zato sam i postavio URL. Mozda se ne izrazavam pravilno i po knjigama, ali su poentu svi ukapirali. Ko nije; pa tu je URL.
Citat:


Ja uopšte ne komentarišem koliko objekti zauzimaju prostora, sam si rekao da tvoja skripta traži 4MB u vrhu.

Ne znam gde sam izjavio da je OOP 50 puta sporiji od proceduralnog?

E ovo se izvinjavam, pobrkao sam te sa drugim clanom. Rec je o ovom postu ; u secanju mi nije tacno ostalo i ko je izjavio ovo. Jos jednom, izvinjavam se.
Btw, da li je ovo takodje vezano za OOP? Ili je netacno ovo sto si izjavio (da objekti uglavnom imaju samo CRUD operacije) ili nisam razumeo? Ako je rec o perfomansama, isti post mozes i ovde da stavis.
Citat:


Ostale komentare nisi razumeo i pogrešno ih tumačiš (global, cookie, unit test, poziv metode, vreme izvršavanja), pa nema svrhe da se raspravljamo.


Ako ih preformulises na manje definicija a vise primera, drage volje cu odgovoriti na kulturan nacin. Bez prozivki i bez vredjanja, jer je ovo ipak ES. Ja jos nikome nisam rekao da pise gluposti ili da je aljkav.
Citat:

@masinac_1

Sad sam konacnooo ukapirao na sta mislis. Bio sam na sajtu youtube-a i video da opcija za glasanje postoji cak i ako ne mozes to da uradis.
Ok, ali mi se resenje nesto i ne svidja (pazi, ovo je iskljucivo sad stvar ukusa, nista vise) jer mi se cini da malo zbunjuje. Mozda bi mi se vise svidelo kad bi novi klik za glas pokazao 'e batice, vec si glasao', umesto da mi uvek prikaze rezultate cak i kad se moj nije uracunao. Ili, da mi po ucitavanju stranica odmah kaze da sam vec glasao i da ne mogu opet.
[ Tudfa @ 19.08.2010. 16:25 ] @
@mitke013

Samo da podsetim, da neko ne shvati pogresno, ja sam tvoju klasu Song i Zend_Controller_Request_Http uporedio
jedino u smislu da obe imaju metode koje uzimaju vrednosti iz superglobalnih varijabli, a nisam uporedjivao,
raspodelu poslova, i bilo sta drugo.

Znaci akcenat je na onoj Goranovoj recenici da je lose to "izlazenje u globalni prostor" citanjem vrednosti superglobals u okviru metode neke klase.
Recimo u tom ZF, cak i da necu u toj famoznoj metodi da uzmem nesto iz superglobals i time "izadjem u globalni prostor",
tu vrednost cu negde morati da uzmem, i recimo ako je to u kontroleru gde cu napraviti taj objekat i njegovoj
metodi proslediti vrednost iz $_COOKIE, sam time opet uradio isto, jer je i taj kontroler klasa, i sve to radim u njegovoj metodi,
pa mu to dodje na isto.

E sad npr. ja nikad ne bih sam, u okviru neke metode koristio kljucnu rec global da bi dohvatio npr. db instance,
ali ono sto je vec samo po sebi tu, kao sto je $_SERVER, $_COOKIE, $_SESSION kazem koristim kad zatreba.

Inace ovakvo koriscenje global kljucne reci se moze videti u phpbb3 verziji foruma, i niko ne dize veliku famu oko toga.
U prilogu je njihova user klasa(session.php, u kome se nalazi session i user klasa, zanimljiv je recimo metod setup iz user klase i koriscenje global kljucne reci)
i eto meni licno se ne svidja takav stil, ali ocigledno da to ne smeta popularnosti tog foruma.