goto

Započeo gagi, 09.11.2010, 13:03

prethodna tema - sledeća tema

holodoc

10.11.2010, 23:22 #15 Poslednja Izmena: 10.11.2010, 23:24 od holodoc
Citat: gagi44  10.11.2010, 22:11Iz ovog zaključujemo da ne pričamo baš o istim stvarima. Ti isključivo razmišljaš o desktop računaru i korisniku koji sedi za tastaturom. Pored računara čiji si vlasnik ti, verovatno i tvoja veš-mašina, automobil i televizor imaju  svoje"računare" a ako imaju sreće da su novije generacije možda ga imaju i toster i četkica za zube. :) Tu se i te kako vodi računa o resursima i brzini izvršavanja, posebno u domenu hard real-rime sistema. Zaista bih voleo da ne moram da se zamlaćujem ovakvim stvarima, ali na žalost moram.
Zaista ne znam odakle si zaključio da ja "isključivo razmišljam o desktop računarima i korisnicima za tastaturom" kad ja sve vreme govorim u kontekstu razvoja a ne korišćenja softvera :) Što se tiče pomenutih veš mašina, automobila i televizora to je već posebna sfera programiranja više orijentisana ka hardveru čiji je zadatak uglavnom da realizuje mnogo jednostavnije algoritme od onih koji se koriste u klasičnoj softverskoj industriji u pravom smislu te reči (desktop, web i druge namenske aplikacije). Međutim za detalje oko optimizacije koda za programiranje mikroelektronike moraćeš ipak da konsultuješ nekoga ko se bavi time pošto se ja bavim isključivo klasičnim razvojem softvera ;)
Citat: gagi44  10.11.2010, 22:11Ono što sam želeo da istaknem jeste da sam u praksi naišao na nešto što odudara od onog što smo učili u knjigama i da sam malo promenio razmišljanje u pogledu proceduralnog programiranja.
Pa pazi, sasvim je normalno da se praksa razlikuje od teorije. Zato se i uče ili stiču odvojeno :D
Citat: gagi44  10.11.2010, 22:11Jednostavno,  postoje slučajevi u kojima goto čini kod preglednijim od bilo kog drugog rešenja a to je ono što mi ranije ne bi palo ni na kraj pameti. Uz to, mogu znatno da unapredim performanse a to mi je dovoljan razlog da u svojim rešenjima žrtvujem preglednost koda jer na raspolaganju nemam mnogo resursa i ne mogu ih proširiti. Možda grešim i treba da odbacim ovo rešenje tako da bih voleo da čujem argumente koji su bazirani na konkretnim primerima.
Možeš li da daš neki konkretan primer koda ili algoritma koji ne može da se reši ni na koji drugi način osim korišćenja bezuslovnih skokova i obrazloženje zbog čega misliš da je kod koji sadrži bezuslovne skokove pregledniji? :) Ja ću argumentaciju svog stanovišta započeti predlogom da napraviš anketu među iskusnijim programerima (jezik i platforma nisu bitni) i priupitaš ih šta misle o bezuslovnim skokovima (ukoliko su ih uopšte ikada koristili :) ) ili da bar pročitaš jedan članak (u stvari to je deo poglavlja a knjigu negde imam već u elektronskom obliku) iz knjige koja se da kažemo malkice ozbiljnije bavi ovom problematikom. Pre nego prokomentarišeš članak obrati pažnju na to da se isti odnosi gotovo isključivo na jezike koji nemaju sistem prekida kontrole tokova i da članak čak pokušava na neki način da odbrani ideju korišćenja bezuslovnih skokova u određenim situacijama. Dakle jedini pravi bastion obožavalaca tog pristupa nalazi se u redovima za današnje pojmove već antikviteta od programa tipa Pascal-a itd. (ne mogu da se setim da li beše FORTRAN ima bilo kakav ekvivalent prekida kontrole toka.).
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

gagi

Pričao si o serveru a zatim o jednokorisničkom sistemu koji ne gubi na performansama (???) kada se prekorači memorija jer postoji virtuelna memorija. Iz toga zaključih da su to uglavnom desktop računari. U linkovima koje sam prosledio se govorilo i o preglednijem kodu. Možeš se uveriti u linuks kernelu, Freescale-ovim BSP paketima a da ne bi gubio vreme ja ti dajem odmah jedan link koji predstavlja dobar primer
http://www.cprogramming.com/tutorial/goto.html
Mislim da je ovde jasno da je goto bolje rešenje i da je kod pregledniji. Na pitanje da li mogu da ti dam algoritam koji nije moguće rešiti bez goto mogu samo da odgovorim novim pitanjem - Da li postoji neki algoritam koji nije moguće napisati na više načina? Naravno, samo jedno rešenje je optimalno a u gore navedenom primeru je jasno koje. Ozbiljan članak je dao profesor, mislim da autor ima dovoljnu težinu. Liberty (Marjan ga je spomenuo) reče da mu je bilo potrebno svega par puta u životu dakle zaključuje se da ipak ni on nije protivnik a i on ima neki ugled koliko ja znam ( i iskusan je programer). Teorija i praksa po meni nisu i nikako ne mogu biti odvojeni procesi, već je to jedan proces koji u našem primeru mora biti kontinualan. Ovde doduše ne mogu da se ne setim jedne šale koja glasi:  "In theory, theory and practice are the same. In practice, they are not."  :)

Takođe želim da se osvrnem i na priču o jednostavnijim algoritmima i klasičnoj softverskoj industriji. Nije mi baš jasno šta je to klasičan softver a šta je to "ono ostalo". Pisao sam neke aplikacije koje su se izvršavale dva dana na izuzetno močnom serveru, probao sam i da pišem one koje se izvšavaju u deliću sekunde na sistemu sa par hiljada bajtova ram memorije a malo nešto baratam i sa ovim klasičnim softverom i ne mogu da kažem šta je lakše a šta teže. Svaki ima svoju težinu, svaki nosi neke posebne izazove i svaki ima svoju posebnu draž.  Ja imam tezu da svako ko radi neku aplikaciju mora savršeno da poznaje alate koje koristi (programski jezici, tehnike programiranja, razvojna okruženja i slično) i  mora odlično da poznaje oblast kojoj je aplikacija namenjena (na primer ako radi obradu signala koja stiže od digitalnog stetoskopa mora da zna šta traži u tom signalu, što znači da mora da poznaje malo medicine). Kod "mikroelektronike" moraš još da poznaješ i malo elektronike. Sve pojave u okruženju kod ovakvih sistema se odvijaju u realnom vremenu i ne smeš sebi dozvoliti da ih ispustiš u nekim situacijama a resursi su ti jako skromni. Kada nastane bug tokom testiranja na terenu teško je pronaći uzrok jer je teško reprodukovati tu situaciju sa terena u laboratoriji  a greška može da nastane kako zbog greške programera tako i zbog nekih uvrnutih razloga kao što je stalno uključivanje hidrofora u obližnjoj zgradi. Nema moćnih alata za ubijanje buba koje su ti na raspolaganja, ne možeš da zabodeš brejk. Dakle daleko više nepoznatih faktora je u igri što ti zagorčava život. Algoritmi mogu biti jednostavni na svim platformama, ali mogu biti i izuzetno komplikovani bez obzira na platformu. Verovatno su algoritmi koji su smešteni u jednu ploču ne veću od grafičke a koja obrađuje nekoliko telefonskih poziva daleko komplikovaniji od onih koje smo svi zajedno ikad pisali. I podela na hardver i softver nije kruta i kao što neko reče "hardver je okamenjen softver". Ono što je softver današnjice može biti hardver sutrašnjice i obrnuto tako da je svako programiranje pomalo okrenuto ka hardveru.  :)

holodoc

11.11.2010, 01:55 #17 Poslednja Izmena: 11.11.2010, 02:38 od holodoc
Citat: gagi44  11.11.2010, 01:12Pričao si o serveru a zatim o jednokorisničkom sistemu koji ne gubi na performansama (???) kada se prekorači memorija jer postoji virtuelna memorija. Iz toga zaključih da su to uglavnom desktop računari. U linkovima koje sam prosledio se govorilo i o preglednijem kodu.
Nadam se da nemaš nameru da kažeš da jedan od ta dva računara ima virtuelnu memoriju a drugi ne jer ako je tako nadam se da si već položio Arhitekturu računara. U suprotnom si obr'o bostan ako profesor Ranđić ovo pročita :D

Mislim danas ćeš teško uspeti da nađeš operativni sistem koji ne koristi virtuelnu memoriju pošto većina koristi multitasking kernel. U prevodu i server i jednokorisnički sistem koje sam naveo u svom postu koriste virtuelnu memoriju bez obzira na to što možda implementiraju virtuelnu memoriju na drugačije načine. Na Windows baziranim sistemima virtuelnu memoriju čini raspoloživi RAM u kombinaciji sa tzv. page fajlovima dok se na UNIX-olikim sistemima virtuelna memorija najčešće formira kombinacijom RAM memorije i swap particija.

Ostatak poruke i posebno ovaj primer za koji si dao link ću morati da proučim detaljnije malo kasnije ili eventualno u toku sutrašnjeg dana pošto imam još nekih sat-dva da završim neki posao a već sam na izdisaju sa koncentracijom. Ne brini se neću zaboraviti ;)
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

gagi

Ne, nisam mislio da jeda od ta dva rаčunara nema virtuelnu memoriju već da postoje mnogo manji sistemi kod kojih ovi mehanizmi ne postoje. Pogledaj kod pa reci da li je narušena preglednost koda i da li postoji bolje rešenje. Ubedi me.  :)

marjan

11.11.2010, 23:30 #19 Poslednja Izmena: 12.11.2010, 00:06 od marjan
Ih, što ste neki :\
LM, gagijev primer je u stvari primer koji navode i K&R u svom klasiku.
Na kraju, kažu:
Citat
With a few exceptions like thosed cited  here, code that relies on goto statement is generally harder to understand and to maintain that code without gotos. although wea re not dogmatic about the matter, it does seems that goto statements should be used rarely, if at all.

-----

Hej, kako to da sam odmah po slanju poruke imao Utisak +1?? Mnogo pametan SMF, a? :))

Doduše, rasipa memoriju - pre neku poruku sam dobio "kilobajt" uz profil - pre sam bio bajt. LOL

goto sleep;
Unix is user-friendly—it's just choosy about who its friends are.

gagi

Hvala Marjane, to mi je promaklo.  :) Kao u svim stvarima u životu, tako i ovde treba naći meru. Mislim da postoje primeri gde je Dijskstra u pravu, ima i oblasti gde je Knuth u pravu. Stalni sukobi poput onih Mac vs PC, Intel vs AMD, Linux vs Windows, Gibanica vs Pizza... Mogu da postavim bezbroj tema i svaka od njih će izazvati pravi mali rat i podeliti ljude u minimu dva tabora. Elem, ono što htedoh reći jeste da je istina negde u sredini, pa tako goto u malim količinama može biti pravi lek a u prevelikoj meri može postati otrov. Sve je na programeru i ipak od njegovog kvaliteta zavisi kvalitet krajnjeg rešenja (tj programa) a ne od alata koje koristi. Što reče Njegoš u rukama Mandušića Vuka svaka će puška biti ubojita. Evo i ternarni izrazi mogu biti loši:
http://csl.tfc.kg.ac.rs/forum/index.php/topic,319.0.html

holodoc

12.11.2010, 22:18 #21 Poslednja Izmena: 12.11.2010, 23:29 od holodoc
Kasnim malo sa svojim odgovorom zbog posla koji je još uvek aktuelan tako da se unaped izvinjavam što ovoga puta neću biti u prilici da napišem kilometarski post  >:D< EDIT: Ipak se ispostavilo da je kilometarski post u pitanju  :boodala:

@gagi44
Pogledao sam ponovo stranicu za koju si dao link i mogu da kažem samo da nisi mogao da odabereš bolji primer za demonstraciju zašto su argumenti za korišćenje goto-a u stvari njegovi najveći neprijatelji :) U stvari sad kad je Marjan pomenuo da se seća te deonice koda iz K&R setio sam se da sam već vodio raspravu na ovu temu .

Pre nego što počnem sa izlaganjem moram da napomenem da je autor korišćenjem pseudo koda u stvari nesvesno (a možda i namerno :dzavo:) izbegao da demonstrira kontraindikacije koje mogu da imaju pokušaji da se uz pomoć goto komande napravi veštački sistem izuzetaka, što je upravo ono o čemu članak govori.

Prvi ozbiljan previd autor je napravio kad je kompletan "cleanup" kod smestio na jedno mesto gde će se bezuslovno pozivati nakon svake greške u kodu koja treba da ima za zadatak da kontroliše tok nakon nastanka greške i preduzme sve što treba da ne dođe do neke štete. Na prvi pogled sve izgleda super jer i exception sistem ovako funkcioniše. Postoji kod koji se proverava u try bloku pa ako dođe do exceptiona odgovarajući catch blok se pozabavi problemom. E upravo je u podebljanom tekstu poenta celog problema :dzavo: U svim programskim jezicima koji podržavaju izuzetke oni ne služe samo za lakše rešavanje situacija kad se pojave greške nego i da obezbede jednu od najbitnijih stvari kod izuzetaka - apstrakciju kroz tzv. sistem "custom exceptionsa" :) Ovim principom bezuslovnog skoka na zajednički "cleanup" kod u potpunosti je uklonjena apstrakcija koda i to je prvi korak koji garantuje prerano penzionisanje.

Krećem sa ilustracijom. Uzeću primer programera koji je dobio zadatak da napiše neko programče i koji je zbog čestog dahtanja šefa za vratom rešio da pojednostavi svoj program i iskoristi sledeću strukturu u jednoj od funkcija koja ima za cilj da radi neku složenu obradu podataka.int big_function()
{
    int ret_val = [success];
    /* do some work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    /* clean up*/
    return ret_val;
}


Programer je uspeo da na vreme završi svoj zadatak i da napiše ne baš tako složenu funkciju u kojoj se pri kraju poziva kod za "cleanup" operacije koji nije komplikovan. Dan kasnije programer dobija zadatak da proširi svoju funkciju tako da ona izgleda sad ovako:

int big_function(){
    int ret_val = [success];
    /* do some work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    /* clean up*/
    return ret_val;
}

Programer je sada prisiljen zbog velikog broja različitih ret_value vrednosti da kraj funkcije proširi sa if ili switch petljama. U idelanom slučaju kada je ret_val jednoznačno određen možda može da se koristi i switch.
int big_function()
{
    int ret_val = [success];
    /* do some work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    if(ret_val == 1){
        /* Cleaning case 1 */
    }
    if(ret_val == 2){
        /* Cleaning case 2 */
    }
    if(ret_val == 3){
        /* Cleaning case 3 */
    }
    if(ret_val == 4){
        /* Cleaning case 4 */
    }
    return ret_val;
}

Programer je srećan što je uspeo da nađe rešenje za svoj problem ali dan kasnije dobija zadatak da funkciju proširi tako da omogućava obradu ne samo jednog tipa podataka (recimo brojeva) nego i nizova struktura. Sada očigledno postoji potreba za drugom metodom čišćenja podataka ("cleanup") i programer se nalazi pred teškim problemom jer mora da pronađe način kako da koristi drugačiju metodu čišćenja za drugačije tipove podataka. Kao što je poznato C ne podražava bilo kakve oblike overloadovanja pa programer sada dolazi u nezavidnu situaciju da razmišlja o tome da kreira ili dupli set if petlji (u gornjem slučaju bi to bilo ukupno 8 if petlji za dva tipa podataka) ili da razmišlja o koraku od koga svakom iskusnom programeru trne zubi - dodavanje još jedne labele  [-(

Programer se ipak odlučuje za goto pristup i shvata da će goreti u programerskom paklu. Njegov kod sa izgleda ovako:
int big_function()
{
    int ret_val = [success];
    /* do some work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end2;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end2;
    }
end:
    if(ret_val == 1){
        /* Cleaning case 1 */
    }
    if(ret_val == 2){
        /* Cleaning case 2 */
    }
    if(ret_val == 3){
        /* Cleaning case 3 */
    }
    if(ret_val == 4){
        /* Cleaning case 4 */
    }
    return ret_val;
end 2:
    if(ret_val == 1){
        /* Cleaning case 1 */
    }
    if(ret_val == 2){
        /* Cleaning case 2 */
    }
    if(ret_val == 3){
        /* Cleaning case 3 */
    }
    if(ret_val == 4){
        /* Cleaning case 4 */
    }
    return ret_val;
}
Jel treba da objašnjavam šta se dešava kada trećeg dana project manager dođe i kaže da se funkcija pokazala toliko dobro da želi da omogući i obradu nekog trećeg tipa podataka (dovoljno je da kaže druge strukture) i programer bi bio lud ako sebe ne bi spasio i skočio u najbliži bunar.

U sledećem postu ću da demonstriram kako se ovakve zamke rešavaju i to na konkretnom primeru koji sam upravo iskucao.

NASTAVLJA SE >>
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

holodoc

12.11.2010, 23:20 #22 Poslednja Izmena: 13.11.2010, 14:06 od holodoc
>>> NASTAVAK IZ PRETHODNOG POSTA

Prvo da postavim kod kojim hoću da demonstriram sistem kojim bi se eliminisao problem koji sam opisao u prethodnom postu a koji je vezan za bezuslovne skokove i nedostatak apstrakcije. Kod jeste malo duži ali u principu mnogo realnije dočarava relan slučaj nego pseudo-kod koji je korišćen u originalnom članku koji sam komentarisao. Nativan SMF je bez odgovarajućih plaginova malko hendikepiran kad je u pitanju prikaz koda na stranicama pa tako ako imate neki editor sa sintaksnim bojenjem možda bi bilo dobro da ceo kod prekopirate tamo da bi mogli lakše da ga pratite.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define COUNT 100
#define CRITICAL_ERROR 1701
#define STATUS_OK 0
#define ID_ASSIGNMENT_FAILED 1
#define NAMING_FAILED 2

int processJobs();
int cleanupAndReport();
int cleanupRestoreAndReport();

typedef struct {
long jobId;
char name[24];
short error;
} Job;

int main(){
int finalStatus;

finalStatus = processJobs();
printf("Howdy! The system was about to report the following status: %d!\n", finalStatus);
(finalStatus == CRITICAL_ERROR) ? printf("Additionally there was a critical error while cleaning up!") : NULL;

getchar();
return EXIT_SUCCESS;
}

int processJobs(){
int i, status;
Job jobs[COUNT];
char *namePrefix = "Name";

srand((unsigned) time(NULL));

for(i = 0; i < COUNT; i++){
status = rand()%2;
// CHECKPOINT #1
jobs[i].jobId = rand();
if(!(rand()%2)){
jobs[i].error = 1;
return cleanupAndReport(&jobs);
}

// CHECKPOINT #2
sprintf(&jobs[i].name, "%s[%d]", namePrefix, i);
if(!(rand()%2)){
jobs[i].error = 2;
return cleanupAndReport(&jobs);
}

// CHECKPOINT #3
if(!(rand()%2)){
jobs[i].error = 3;
return cleanupRestoreAndReport(&jobs, i);
}
}

return 0;
}

int cleanupAndReport(Job *failedJob){
int status = STATUS_OK;

printf("Entered cleanupAndReport!\n");

switch(failedJob->error){
case 1 :
// CLEANING #1
break;
case 2 :
// CLEANING #2 - FATAL EXCEPTION!
status = CRITICAL_ERROR;
break;
default :
// DEFAULT
status = 1;
;
}
return status;
}

int cleanupRestoreAndReport(Job *failedJob, int failedAt){
// CLEANING AND RESTORING
printf("Entered cleanupRestoreAndReport and handling failure at %d!\n", failedAt);
return 0;
}

Cilj ovog koda je da demonstrira obradu potpuno proizvoljnih struktura i to tako da u slučaju da dođe do greške kompletna aplikacija sanira sve potencijalne probleme i operativnom sistemu vrati odgovarajući kodi rezultat.

Postoje tri funkcije:

  • processJobs
  • cleanupAndReport
  • cleanupRestoreAndReport
a main() je iskorišćena samo kao supervizor procesa i služi isključivo da operativnom sistemu vrati status obrade (mogao je i kompletan kod iz processJobs da se smesti u main() ali nije zbog jedne finese na kraju). Idem redom sa objašnjenjem koda.

Na početku koda se vrše standardna učitavanja zaglavlja i definisanje / deklarisanje konstantni u okviru preprocesorskih direktiva. Tu nema ničeg spornog.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define COUNT 100
#define CRITICAL_ERROR 1701
#define STATUS_OK 0
#define ID_ASSIGNMENT_FAILED 1
#define NAMING_FAILED 2

Zatim se definišu prototipovi funkcija
int processJobs();
int cleanupAndReport();
int cleanupRestoreAndReport();

i struktura koja ima za cilj da emulira realan slučaj strukturiranih podataka - nešto tipa objekta.
typedef struct {
long jobId;
char name[24];
short error;
} Job;

Naime, dve stvari su karakterističen za C kod:

  • većina podataka smeštena je u obliku struktura ili lista koje najbolje emuliraju objekte koje ne postoje u C-u
  • većina podataka se u funkcijama zbog performansi ne prenosi po vrednosti kao kopija već se radi prosleđivanje referenci / pokazivača na strukture podataka
Zato sam ovde izabrao strukturu da emulira objekat ali nisam hteo nepotrebno da komplikujem kod da koristim pokazivače na pokazivače i sl. C drangulije koje penziju znače :D

Main definiše neke početne stvari a zatim poziva processJobs funkciju čiji je zadatak da u okviru niza jobs smesti COUNT (u ovom slučaju 100) elemenata tipa Jobs strukture.

Funkcija kreće sa kreiranjem prvog elementa u nizu a zatim kreću operacije sa onim ešto bi bio ekvivalent onoj liniji "/* do some work */" u primeru od kojeg je diskusija počela. Tu se prvom elementu jednostavno postavlja vrednost jobId polja koja je nasumična.
for(i = 0; i < COUNT; i++){
// CHECKPOINT #1
jobs[i].jobId = rand();

U sledećoj liniji se proverava da kojim slučajem nije došlo do greške u toku prvog posla. Ovo je u suštini veštačka simulacija pojave greške jer bi u realnim uslovima detekcija greške direktno zavisila od rezultata prvog posla. Ovde se jednostavno koristi linija
if(!(rand()%2)){
da bi se simuliralo nasumično otkazivanje koda (kod će na toj lokaciji simulirati grešku za svaki nasumični broj koji je paran).

Ukoliko dođe do greške automatski se poziva funkcija cleanupAndrestore() kojoj se prosleđuje direktna referenca na ceo niz sa elementima struktura pri čemu ako je potrebno funkciji bez problema mogu da se proslede i reference na neku od lokalnih promenjljivih. Ono što je bitno kod ove strukture je da se poziv na funkciju cleanupAndReport() radi sa linije koja počinje sa return pa se tako obezbeđuje sistem kojim se rezultat čišćenja prosleđuje hipervizor funkciji (ovde je to main()) Znači rešili smo usput još jedan problem a to je da imamo sistem putem kojeg u slučaju da dođe do problema u samoj funkciji za čišćenje (da ga nazovemo "eksepš eksepšena" :whistle2:) možemo da obavestimo hipervizora koji nadgleda ceo proces da se nešto nije odigralo kako treba pa čak i da primenimo neku meru za rešavanje tog problama u samom hipervizoru, što je odlična stvar  :> "Eksepšn esepšena" je simuliran u switch petlji funkcije cleanupAndReport za slučaj greške 2 u processJob funkciji a kad se u tom slučaju pojavi neki kritičan izuzetak koji se simulira postavljanjem vrednosti promenjljive status na CRITICAL_ERROR.

Dakle čak i da se u potpuno apstraktnoj rutini za čišćenje koda pojavi problem postoji način da se ta informacija prosledi funkciji koja ima ultimativnu reč u rešavanju problema (pa makar to bilo i amputacijom nogu i ruku koda :D) Ako kompajlirate ovaj kod što sam dao videćete da se u određenim trenucima štampa kod 1701 koji indikuje baš to stanje pojave problema u rutini za čišćenje. Da ne bude zabune ovo sa prosleđivanjem koda nije osnovna poenta cele priče već apstrakcija tj. mogućnost da korisnik bude uvek u mogućnosti da bira kome će proslediti zadatak da reši čišćenje i sa kojim parametrima.

A kako se ovo tačno razlikuje od jednostavnog postavljanja gomile petlji pri dnu jedinstvene funkcije? Upravo u tome što kada šef dođe sutra i kaže da želi da funkcija processJobs bude u stanju da obradi i strukturu koja opisuje vanzemaljace koji još uvek čekaju na izdavanje pasoša u loklanoj opštini ne treba čupati kosu zbog toga što se kompletan proces regulisanja izuzetaka sveo na rutinu koja je do tada čistila đubre nakon obrade podataka jobs niza o kome sam pričao. Jednostavno kompletan proces obrade preuzima funkcija cleanupRestoreAndReport(). Na stranu to što apstrakcija obezbeđena na ovaj način omogućava da i spisak argumenata koji se prosleđuju funkciji za čišćenje bude potpuno proizvoljan i da ne mora da se koristi mali milion petlji za kontrolu tokova da bi se pre samog čišćenja prokontrolisalo šta treba da se čisti :) Po kojoj ceni? Ceni jednog dodatnog pozivanja funkcije koja se poziva samo jednom :)

Šta smo izgubili a šta smo dobili ovim pristupom?

1) Izgubili smo priliku da koristimo goto i zbog toga nam je jako žao :)
2) Izgubili smo priliku da veštačkim pokušajem simulacije sistema izuzetaka, kojim se kompletan blok za rešavanje izuzetka smešta na kraj funkcije, budemo prisiljeni da svakom krupnijom izmenom funkcije napišemo i  beskonačan broj linija za kontrolu uslova pri operaciji čišćenja funkcije ili da se igramo sa dodavanjem dodatnih labela i goto skokova.
3) Izgubili smo priliku da budemo u mogućnosti da definišemo astraktan kod koji će kasnije da nam omogući da mnogo lakše prilagođavamo funkciju i biramo koja će rutina da rešava naš problem (možemo tako da definišemo bezbroj rutina)

Šta smo dobili? Očigledno ništa :)

Za kraj da remiziram. Pravi sistem izuzetaka je u C-u nemoguće simulirati ali je ovaj princip sa vraćanjem povratnih vrednosti hipervizoru najpribližnije što postoji pravom sistemu jer simulira "custom exceptione" koji imaju sposobnost da uslovno vrše skokove na delove koda (u ovom slučaju funkciju) koja može na potpuno izolovan način da reši problem koji je nastao. Ono što je još važnije je da kod nije nužno pregledniji i čistiji ukoliko sve može da se opazi odmah krajičkom oka. Ponekad se pravi problemi tek vide kada se počne sa prilagođavanjem koda za sopstvene potrebe i tada se gotovo uvek ispravnim pokaže pravila da zarad proširivosti i prave čitljivosti koda treba preskočiti "teoretske preporuke" i poslušati praksu :) A praksa kaže da goto treba izbegavati kao đavo krst i da ako se i dogodi da se negde u kodu primeni da od tog koda kasnij ene treba mnogo očekivati pri proširenju već da se više isplati sve napisati iz početka pa čak i po ceni gubljenja vremena jer se na kraju ono uvek više isplati od koda koje koristi goto :)

Ja ovde stajem jesr sam postao i samom sebi dosadan a ako nastavim rizikujem da me poslodavci likvidiraju do ujutru :D
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

holodoc

12.11.2010, 23:39 #23 Poslednja Izmena: 13.11.2010, 00:13 od holodoc
Citat: marjan  11.11.2010, 23:30
-----

Hej, kako to da sam odmah po slanju poruke imao Utisak +1?? Mnogo pametan SMF, a? :))

Doduše, rasipa memoriju - pre neku poruku sam dobio "kilobajt" uz profil - pre sam bio bajt. LOL

goto sleep;
Izdresirali smo ga da svaki put kad neko postuje skraćenicu "K&R" ili sintagmu "Kuća pos'o, pos'o kuća" korisniku doda još jednu memorijsku pločicu :D Naravno pločicu možeš da dobiješ samo jednom u sto godina :)

Citat: gagi44  11.11.2010, 01:12Nije mi baš jasno šta je to klasičan softver a šta je to "ono ostalo". Pisao sam neke aplikacije koje su se izvršavale dva dana na izuzetno močnom serveru, probao sam i da pišem one koje se izvšavaju u deliću sekunde na sistemu sa par hiljada bajtova ram memorije a malo nešto baratam i sa ovim klasičnim softverom i ne mogu da kažem šta je lakše a šta teže.
Pa što koristiš termine koji ti nisu baš jasni  :P Šalim se naravno. Ja nisam nigde upotrebio sintagmu "klasičan softver" već "klasični razvoj sofver" koji za mene lično znači razvoj softvera u nekom od viših programskih jezika koji nemaju baš neke direktne veze sa programiranjem hardvera osim ako ne koriste neku vrstu API-ja za direktnu ili posrednu komunikaciju sa njim. Dakle sve što se generalno razvija u jezicima kao što su C++, C, C#, PHP, Java itd. itš.

Citat: gagi44  11.11.2010, 01:12Svaki ima svoju težinu, svaki nosi neke posebne izazove i svaki ima svoju posebnu draž.  Ja imam tezu da svako ko radi neku aplikaciju mora savršeno da poznaje alate koje koristi (programski jezici, tehnike programiranja, razvojna okruženja i slično) i  mora odlično da poznaje oblast kojoj je aplikacija namenjena (na primer ako radi obradu signala koja stiže od digitalnog stetoskopa mora da zna šta traži u tom signalu, što znači da mora da poznaje malo medicine)
Iako se u suštini generalno slažem sa ovim delom za alate i aplikacije ne mogu da se složim sa konstatacijom da neko ko je "klasičan programer" treba da poznaje oblast tipa medicine i slično. Ukoliko je u pitanju softversko inženjertsvo za izradu aplikacija specifične namene u kojem je potrebno napraviti istraživanja u pogledu nekih specifičnosti same aplikacije a koje su opet vezane za medicinu onda je u redu ali u svim ostalim slučajevima osnovni postulat kod rada u velikim softverskim kompanijama je da ti kao programer ne treba da znaš kompletne detalje o projektu :) Primera radi započeo si rad na web aplikaciji koja daljinski treba da osmatra i kontroliše pacijente za koje drugi tim izrađuje odgovarajuću mikroelektroniku ta ceo projekat. Kako ćete vi funkcionisati u tom slučaju? Tako što će projekt menadžer biti taj koji će svakome od vas dati odgovarajuća dnevna zaduženja i što ni tebe kao klasičnog programera a ni zaposlene u drugom timu neće opterećivati stvarima koje ne trebaju da znaju.

Tako elektroničar neće morati da vodi računa o tome da li ćeš ti u svom programu da koristiš bezsulovne skokove  :dzavo: ili ti o tome da li će elektroničar obezbediti dovoljnu temperaturnu stabilnost projektovane elektronike. Vi ćete biti organizovani tako da "elektroničar" svojim delom posla obezbedi tebi kao programeru odgovarajuće tehničke podatke i API putem kojeg ćeš ti moći da kontrolišeš datu elektroniku. Da stvar bude još interesantnija u toku razvoja tvog softverskog dela velika je verovatnoća da nećeš ni videti sam uređaj već da ćeš ispravnost svog koda i pridržavanje speicfikaciaj testirati sopstvenim aplikacijama kojima je to osnovni cilj. Dakle ne da ćeš pisati samu aplikaciju nego ćeš pisati i aplikacije za testiranje svoje aplikacije :)

To je budućnost (a kad malo bolje razmislim i sadašnjost) razvoja softvera. Potpuna apstrakcija elemenata u timu koji se bave istim projektom a imaju različita zaduženja.

Citat: gagi44  11.11.2010, 01:12Kod "mikroelektronike" moraš još da poznaješ i malo elektronike. Sve pojave u okruženju kod ovakvih sistema se odvijaju u realnom vremenu i ne smeš sebi dozvoliti da ih ispustiš u nekim situacijama a resursi su ti jako skromni. Kada nastane bug tokom testiranja na terenu teško je pronaći uzrok jer je teško reprodukovati tu situaciju sa terena u laboratoriji  a greška može da nastane kako zbog greške programera tako i zbog nekih uvrnutih razloga kao što je stalno uključivanje hidrofora u obližnjoj zgradi. Nema moćnih alata za ubijanje buba koje su ti na raspolaganja, ne možeš da zabodeš brejk. Dakle daleko više nepoznatih faktora je u igri što ti zagorčava život.
Upravo zbog toga se softver nakon objavljivanja stalno testira i ispravljaju njegove greške :) E sad ako klijent i dalje pored preporuke razvojnog tima dobija da dopusti dovoljno vremena za testiranje softvera tim tu zaista ne može mnogo da učini osim da na vreme instalira softver i moli se da su svi u timu bili raspoloženi kad su ga pisali :)

Citat: gagi44  11.11.2010, 01:12Verovatno su algoritmi koji su smešteni u jednu ploču ne veću od grafičke a koja obrađuje nekoliko telefonskih poziva daleko komplikovaniji od onih koje smo svi zajedno ikad pisali.
Današnji hardver je realno dostigao ograničenja koje postavlja fizika tako da se za razliku od rešenja koja su se razvijala ranije  danas za dobijanje boljih performansi koristi klasičan "brute force" pristup.  Nije algoritam za OpenGL transformacije toliko komplikovan (par trigonometrijskih funkcija ukombinovanih sa prvačkom matematikom) koliko su porasli zahtevi za dobijanjem boljih performansi u smislu broja obrađenih vertexa u jedinici vremena.

Citat: gagi44  11.11.2010, 01:12I podela na hardver i softver nije kruta i kao što neko reče "hardver je okamenjen softver". Ono što je softver današnjice može biti hardver sutrašnjice i obrnuto tako da je svako programiranje pomalo okrenuto ka hardveru.  :)
Nije baš tako :) Ja jesam radoznao po prirodi ali i dalje mislim da "klasičnog programera" ne treba uopšte da interesuje kako određeni kompajler funkcioniše ili kkao optimizuje kod. Jednostavno neke stvari su danas postale toliko opširne da bi letenje na sve strane samo značilo razvodnjavanje specifičnih sposobnosti a to u industriji nije baš najbolje jer kako kažu "majstor za sve nije sposoban nizašta" :)
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php