Problem "ugnježdenih" petlji i kontrolnih struktura (previše nivoa)

Ima li ko kakav resurs u kom se ovo fino razjašnjava ?
Primjer je ova bubble sort implementacija, gdje kontrola toka stalno skače naprijed-nazad.

do {
swapped = false;
for (var i = 0; i < endIndex - 1; i++) {
if (arr[i+1] < arr[\i]) { // escaped i
aij.swap(arr, i, i + 1);
swapped = true;
}
};
endIndex–;
} while(swapped);

Posebno me interesuje kako se nositi sa tim na objektno-orijentisan način ( apstakcijama,modularno.metodama…)
Pročitao sam da se cijeli problem može lijepo objektno dizajnirati al ne mogu da povežem kako.

Pozdrav.

Svi algoritmi (u tvom slucaju za sortiranje) imaju best/worst case scenario tako da sve ovisi od namjene.

Ukoliko sortiras vise miliona instanci onda mozda neki O(log(n)) algoritam tipa Quicksort bi bio prigodniji.

Sto se tice objektno orijentisanog nacina nisam bas 100% siguran na sta ciljas, apstrakciju tipa podataka ili nesto trece…

Uglavnom nadam se da sam barem malo pomogao.

Mislim da ne moze bolje biti objasnjeno od wikipedijinog clanka. Tu imas i vizuelni prikaz kako funkcionise…

Ako sto @listener rece, zavisi na sta ciljas, mada ni OO pristup ne bi trebao biti nesto previse razlicit od datog primjera. Sve vise od toga je pretjerani overengeneering.

Ima jedna lijepa knjiga koju procitas i nemas ovakvih dilema.
Zove se Code Complete … proguglaj - cujem da se moze naci i besplatno za download na internetu …

Hm;

Bubble sort sam naveo kao primjer bez namjere da ulazim dublje u analizu određenog algoritma. Interesuje me samo način na koji se riješio problem primjenom ugnježdenih kontrola toka, i kako se to može pojednostaviti na OO način.
Sve je krenulo od toga da mi te petlje nisu nikako ulazile u glavu tj. trebalo mi je malo više napora i vremena da ih pročitam i razumijem. Ponekad sam bio toliko frustriran neuspjehom u čitanju takvog koda, da mi se činilo da griješim negdje u temelju ili moja inteligencija i znanje nisu dorasli takvim problemima. Onda su me dvije stvari prosvijetlile:

Prvo tehnički uvid - previše ugnježdenih petlji predstavlja u stvari anti pattern koji ima svoje ime (Arrow-head anti pattern).
http://www.codinghorror.com/blog/2006/01/flattening-arrow-code.html
Problem je u tome što svaki sledeći nivo povećava složenost programa kako za mašinu tako i za onog ko ga čita. For i while ugnježdene petlje takođe spadaju u Arrow-head jer su sastavljene od grupisanog ponavljanja if naredbe.

Ljudski uvid - Postoje čak i podaci koji govore da se većina programera muči sa takvim strukturama i da u praksi ne bi trebalo prelaziti tri nivoa ugnježdenja, ili čak tražiti način da se to izbjegne ( otud i moje pitanje vezano za OO pristup). Dalje, iz mog dosadašnjeg iskustva sam naučio da je itekako bitno čiji kod čitaš - ako je pitanju nekakav nafurani geek, kojem je cilj samo da stvari iskomplikuje kako bi sebe zadovoljio - onda se možeš samo zbuniti ( moj slučaj ). Tu dolazi do izražaja ljudski aspekt programiranja i uspijeh projekata kao što su Github - lijepo napisan i komentarisan program je ogledalo onog ko ga piše. Razlikovati loše napisan kod od dobrog je valjda stvar iskustva.

Code Complete sam ja preporučio u jednom postu na ovom forumu. Fenomenalna je u svom domenu.

Živjeli.

Sto se tice OOP, znam jedino da se i objekti mogu porediti, samo se to mora predhodno definisati, kada je jedan objekat “veci” od drugog. Ne znam kako bi problem vise petlji rijesio na OO nacin.

Recimo ovako:

function for_loop(b){
for(i = 0; i < 10; i++){
b(i);
};
};

function if_loop(a){
if (i < 5){
console.log(“Bla bla bla”);
};
};

for_loop(if_loop) // Bla bla bla

Ove dvije funkcije naravno mogu postati metode, pa imamo OO.
Na ovaj način se smanjuje komleksnost, ali stvara “tight coupling” ili zavisnost
što i nije problem u ovom slučaju.

“Ne znam, ne znam, to ne znam. Ja da znam, jab vam stvarno reko”.

http://www.youtube.com/watch?v=mKvKfjUUiZo

Tvoj primjer nema skoro ikakve veze sa OO-om; vise je funkcionalni (FP). Cak i ako napravis od njih metode neke klase, opet je vise FP pristup; sem toga, ako sto rekoh, to je overengeneering: niko ne pise iteracijske metode kao dio klase, jer se iste metode mogu generalizovati, cime postaju zasebne funkcije (inace se gubi apstraktnost OO-om).

Eh sad, ako zelis na OO nacin da iteriras i da to izgleda genericki, probaj koristiti koncept iteratora (C++) ili generatora (python, ruby), jer u OO svijetu jedini pravi nacin iteracije je kroz for/while/do-while konstrukcije.

Sa druge strane, ako zelis napraviti genericke funkcije za iteraciju (npr. for_loop, while_loop), prakticno ti OO i ne treba: dovoljno je da imas nekoliko kontejnera (niz, vezana lista, hashmapa) i sve operacije mozes opisati funkcijama. Ako jos uzmes da te funkcije modifikuju samo jednu stvar i ne cuvaju globalno stanje, dobijes cisti funkcionalni pristup, ala Haskell, Clojure i ekipa.

Bubble sort bas i nije najbolji primjer ovoga sto ti zelis, jer je tako dizajniran da se lako implementira u jezicima gdje je indeksiranje niza (znaci pristupanje bilo kojem elementu niza) konstantna operacija. Ako zelis da rijesis problem, kako ti kazes, ugnježdenih kontrola toka, probaj sa rekurzivnim algoritmima, npr. quicksort-om ili mergesort-om.

Ovo donekle jeste istina - trebao sam navesti da tražim rješenje problema koje ne mora uključivati OO ( ali je poželjno ) Ali kad se sve reducira na niži nivo, objekat ostaje da “visi” samo kao omotač koji je poželjno popuniti nečim :slight_smile:

Ne znam da li se može reći da je ovo više funkcionalni primjer jer je teško povući granicu.
Funkcionalni aspekt odnosno paradigma se i jeste razvila iz potrebe ( između ostalog) da se :

Tako da ispada da funkcije slijede kao nužan korak u programiranju koje se bazira na promjeni stanja.
Metoda je samo dodatna uloga funkcije.

Recimo ovako:

function for_loop(b){
for(i = 0; i < 10; i++){
b(i);
};
};

function if_loop(a){
if (i < 5){
console.log(“Bla bla bla”);
};
};

for_loop(if_loop) // Bla bla bla

Ove dvije funkcije naravno mogu postati metode, pa imamo OO.
Na ovaj način se smanjuje komleksnost, ali stvara “tight coupling” ili zavisnost
što i nije problem u ovom slučaju.[/quote]
Nekoliko razmišljanja, nešto od ovoga je već rečeno ali pokušavam da sistematizujem:

  1. OOP funkcioniše na višem nivou apstrakcije od petlji. Petlje se ne mogu transformisati na OO način jer unutar OO metoda odnosno funkcija se opet mogu (i ne moraju) nalaziti ugniježdene petlje.

  2. Iteracija (petlja) je jedan od temeljnih koncepata programiranja, odmah nakon promjenljivih, dodjele, grananja, ne možeš pobjeći od toga bez obzira koju paradigmu koristiš (OOP).

  3. U funkcionalnom programiranju neke petlje se mogu zamijeniti rekurzijom. Ovaj tvoj primjer ide više ka toj ideji ali moram reći da ti gornjim kodom nisi ništa pojednostavio problem, ustvari si ga zakomplikovao, učinio težim za razumijevanje i debugging. Između ostalog napisao si if_loop (a if nije petlja), nisi dao adekvatna imena funkcijama npr. pitanje je hoćeš li sada u komplikovanijem programu imati funkcije for_loop1 for_loop2, umjesto 4 linije koda imaš desetak itd. itd.

  4. Sve se svodi na odgovarajući način razmišljanja, nekome bolje “legne” funkcionalni način razmišljanja, nekome imperativni, nekome objektno-orjentisani. Višeparadigmatski jezici ti omogućuju da koristiš ono što ti u datom trenutku odgovara, ali onda vječito slušaš prigovore kako tvoj kod nije idiomatski i kako je teško razumljiv nekome ko ne razmišlja kao ti.

  5. Kada uspiješ “ući u glavu” onoga ko je pisao originalni kod shvatićeš da su te višestruke petlje ustvari bile najlogičnije rješenje problema i da su vrlo lako čitljive, prepoznaćeš karakteristične strukture, npr. da li petlja prolazi kroz sve članove kolekcije, unaprijed ili unazad, sa preskakanjem itd.

  6. Ako ne razumiješ algoritam najbolje je da ga ponovo implementiraš. Kroz to ćeš ga bolje shvatiti, možda ćeš uvidjeti da se nije moglo riješiti bez višestruke ugniježdene petlje ili nečega puno goreg. Naravno to se odnosi samo na učenje, kada radiš sa production kodom bolje je da ga ne diraš jer ćeš sigurno unijeti neke nove bugove. U svakom slučaju najvažnije je da što više vremena provedeš pišući kod, rješavajući probleme, prepravljajući programe i popravljajući bugove, što je bitnije od čitanja tuđeg koda jer tu imaš onaj varljivi osjećaj da ti je sve jasno ali ustvari nije.