» »

Kdaj uporabiti izjeme?

Kdaj uporabiti izjeme?

OwcA ::

Otroška radovednost - gonilo napredka.

Shinobi ::

Hm, gandolf nimas povsem prav. Kaj ce pise clovek parser? recimo da beres chunke in potem podatke. Kaj ce je kateri chunk napacno podan in potem preberes vec oz. izvedes file seek tja, kamor nebi smel? V takem primeru lahko imas miljavzent if stavkov, ali pa elegantno resis z exceptioni? Primer, ki si ga navedel glede New pa je dan danes prakticno nemogoce. Ne recem, da ni izjem, ampak da ti New nebi allociral vsaj pod Win32, se prakticno skoraj ne more zgoditi, razen ce hoces alocirati vec kot 4,2 GB podatkov (moras vzeti v zakup se Swap file in podobne stvari). Dan danes folk preverja, ko string alocira, char* pFileName = new char[256]; if (pFileName == NULL) to je skoraj da nesmiselno, ker 256 bytov bo vsak operacijski sistem vedno, ama cisto vedno od nekje napraksal - razen ce si v kaksni loop zanki ki miljavzent krat klice new. To pa je pol spet drug problem, ampak isti ko z datotekami.

Execptione zato odsvetujejo, ker kodo povecajo kar je res. In zakaj povecajo kodo? Ker nonstop precekirajo if/return variante. Ce to delas sam, si v bistvu kontraproduktiven. Je pa res, da kadar se gre za realno casovne aplikacije, pa si ponavadi ne mores privosciti exceptionov, ampak hej, Dot net to nonstop dela(managed okolje) pa prav nikogar ne moti.

Recimo za kak DirectX pa so exceptioni vsaj za render nesmiselni, ceprav ideja ni slaba: recimo beginscene render endscene. Nebi ti blo treba preverjat, ce je beginscene failal ali kaj podobnega. Pac vsakemu svoje.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

Gundolf ::

Ja Shinobi, vse lepo in prav, ampak poanta izogibanja exceptionom (recimo v primeru file copy funkcije) je ta, da uporabniku take funkcije, kadar se ne sekira za njen rezultat, funkcije ni treba obkrožat s try catch blokom. Naprimer, hočeš nekaj spravit v en fajl, a bi rad ta fajl, če že slučajno obstaja backupiral. Tako enostavno kličeš fileCopy(fajl) in te ne brigajo posledice. Če fajl ne obstaja se bo funkcija tiho pritožila, program bo laufal dalje. Če se fajla ne da odpret se bo funkcija pritožila (ne bo naredila backupa), ti boš pa še vedno napako lahjko ujel ko boš hotel prepisat ta fajl. Itd. To da fajla ni bilo mogoče skopirat ni neka nevarna zadeva v rang napak pri alokaciji memoryja. Poleg tega pa se lahko funkcijo uporablja tako, da imaš vedno pripravljeno reakcijo na njen rezultat. Spet isti scenarij, le da tokrat pogledaš, backupa ni bilo mogoče narediti kljub temu, da fajl obstaja in o tem obvestiš uporabnika. Tudi ta scenarij ni primeren za exceptione.

Exceptioni niso za preverjanje rezultatov določenih funkcij. Uporabiš jih tam, kjer si želiš nek blok kode popolnoma varen. Tako varen, da če pride do česarkoli (predvsem sem sodijo neprevdidljivi ali redki dogodki) imaš pripravljeno neko reakcijo. Koda, ki te sili v uporabo try catch blokov samo zato, da preveriš rezultat funkcije je slaba koda.

Še en primer slabe uporabe exceptionov: Borland ima nek class AnsiString (Borland hoče njihov C++ naredit podoben Delphiju), ki ima funkcijo za pretvarjanje stringa v float. Vse lepo in prav, dokler ti ta funkcija ne vrže exceptiona, če se stringa ne da pretvoriti v float. In če potem hočeš narest nek uporaben GUI (kjer se seveda v vsakem widgetu skrivajo AnsiStringi), moraš hočeš nočeš vsako pretvarjanje text -> float opremit s try catch blokom. Madona, da uporabnik narobe vpiše float je tako totalno pričakovana zadeva, da exceptioni tu nimajo kaj iskat. Niti v Borlandovih najhujših nočnih morah ne. To je stvar za en if stavek. Bad bad Borland.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

CCfly ::

V c++ je tudi std::exception, pa izpeljes svoje.

Še enkrat. Exception, kot pove ime, se uporablja ko pride do izjemne napake, ki jo mora razhroščiti in odpraviti programer. Ne uporabljajo se za napake, ki se skoraj zagotovo pojavijo med uporabo programa oz. so pričakovane.

FILE_OPEN_ERR,
FILE_DUPLICATE_ERR,
FILE_DEST_EXISTS_ERR
Vse te tri napake se pogosto pojavijo. Ne zaradi napačnega delovanja programa, temveč zaradi neveljavnega inputa. Namesto da vržeš izjemo raje shandlaš neprijetno situacijo v klicani funkciji.
"My goodness, we forgot generics!" -- Danny Kalev

Zgodovina sprememb…

  • premaknilo od: OwcA ()

64202 ::

> Exception, kot pove ime, se uporablja ko pride do izjemne napake, ki jo mora razhroščiti in odpraviti programer. Ne uporabljajo se za napake, ki se skoraj zagotovo pojavijo med uporabo programa oz. so pričakovane.

Jaz gledam na exceptione bolj kot na se eno orodje, da v dolocenih primerih kodo naredis elegantnejso/krajso. Se mi zdi popolnoma smiselno za operacije nad fajli uporabljati exceptione, ce so recimo del vecje transakcije.
I am NaN, I am a free man!

Zgodovina sprememb…

  • premaknilo od: OwcA ()

kopernik ::

Namesto da vržeš izjemo raje shandlaš neprijetno situacijo v klicani funkciji.


No, je tudi zelo odvisno od situacije. Zakaj bi se neka funkcija za kopiranje samovoljno odločila, kaj storiti v primeru, da kopiranje ni možno ? Klicatelj funkcije morda želi nekaj drugega, kot tisti, ki je funkcijo pisal.
Kako ravnati v takih primerih ? Ali vržeš napako ali pa vračaš nek rezultat. Mislim, da je bolje, da se se klicatelj ubada s tem, kaj storiti v primeru nezmožnosti kopiranja.
Isto zgoraj, ko je nekdo pisal o pretvorbi stringa v float. Kako na pisec take funkcije ve, kaj bi klicatelj želel v primeru, da je string napačen ? Nekdo bi imel za rezultat kar 0, drugi null, tretji pa recimo najmanjšo možno vrednost floata (ki je ponavadi kar konstanta). Če se funkcija samovoljno odloči, kaj storiti v takem primeru, ni v redu. Zato je bolje, da vrača napako, pa naj se klicatelj ubada s tem, kaj želi v primeru nepravilnega niza.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

Gundolf ::

Uf, so vam pa resno všeč teli exceptioni :D Sicer mi je prav žal, da se je tale tema malo izrodila v to smer, ampak očitno vas je treba še kakšno malenkost naučit.

Ja Kopernik, saj se mora tako ali tako vedno klicatelj funkcije odločiti kaj bo storil v primeru neprietne situacije, pa naj ta funkcija meče exceptione kot nora ali pa ne.
/* takole ... */
try {
   copyFile("a", "b");
} catch (...) {
   cout << "warning: copy failed";
}
/* ali takole ... */
if (copyFile("a", "b") != Copy_Ok) {
   cout << "warning: copy failed";
}

To je v primeru, da veš kaj storiti, če ti funkcija faila (razlog za fail ti ni pomemben). Spodaj pa v primeru, da se ti fučka ali funkcija uspe ali ne:
/* takole ... */
try {
   copyFile("a", "b");
} catch (copyFileEsception) {
   // guard copy file failures although we do not care about them
} catch (...) {
   // pass through non-kiddie stuff
   throw;
}
/* ali takole ... */
copyFile("a", "b"); 
// no need to check for copy file failures as they are irrelevant

Kaj je bolj elegantno, kaj je bolj pregledno, kaj je bolj varno, kaj je hitrejše in kaj je bolj pravilno? Če ti bo nek drug programer gledal kodo z exceptioni si bo mislil: "Zlomka, kakšen voodoo dela tale copyFile, da ga je treba zavarovat s try catch blokom?"

Zdej pa še enkrat vsi skupaj: Exceptioni so namenjeni izjemnim situacijam, ne handlanju običajnih potekov programa!
Ne uporabljat exceptionov tam, kjer za isto stvar obstajajo drugi (in niti ne bolj komplicirani) prijemi. Enostavno NE!

P.S. Kopernik, a misliš da bi bilo Borlandu res tako težko napisat funkcijo bool AnsiString::toFloat(float& f) const namesto float AnsiString::toFloat() const?

Zgodovina sprememb…

  • premaknilo od: OwcA ()

kopernik ::

Kar si podal za prvi primer je v bistvu popolnoma isto, samo da namesto if uporabiš try ... catch. Poleg tega je veriženje ifov precej grše in manj pregledno kot dodajanje catch blokov, še posebej glede na to, da imaš običajno v try bloku več raznovrstne kode, ki lahko povzroča različne napake. Kupi ifov, pri katerih je pri vsaki funkciji drugačen pogoj niso ravno nek zgled preglednosti.

Kar si podal za drugi primer, pa se ti tudi pri exception-u lahko fučka, če je le-ta exception definiran kot tak, da ga ni potrebno ujeti (ne vem, kako je s tem v delphiju). Npr. v Javi imaš celo skupino napak, ki jih ni potrebno ujeti, če jih nočeš (t.i. runtime napake).

Zakaj pa se je borland za neko določeno rešitev odločil, ne vem. Očitno so staknili glave skupaj in se odločili za tak pristop z exception-om.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

kopernik ::

P.S. Kopernik, a misliš da bi bilo Borlandu res tako težko napisat funkcijo bool AnsiString::toFloat(float& f) const namesto float AnsiString::toFloat() const?


To bi bilo pa skrajno neintuitivno in tak API bi bil zgled, kako se funkcij NE poimenuje. Mislim, toFloat(), ki vrne boolean. Kvečjemu canConvert() ... drugače pa sem že zgoraj rekel, napaka ali rezultat, ko sem repliciral na to, da se funkcija sama odloči kaj storiti v primeru nezmožnosti kopiranja.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

Vesoljc ::

precej stvari se da "izrodit", sej exception recimo lahko vrzes tudi on success.
so le tool, in nic vec. ce se ti s kladivom usekas po prstih si si sam kriv...
Abnormal behavior of abnormal brain makes me normal...

Zgodovina sprememb…

  • premaknilo od: OwcA ()

CCfly ::

Jaz gledam na exceptione bolj kot na se eno orodje, da v dolocenih primerih kodo naredis elegantnejso/krajso. Se mi zdi popolnoma smiselno za operacije nad fajli uporabljati exceptione, ce so recimo del vecje transakcije.
Sem sicer odprt za diskusijo, kje gre za pravilno uporabo izjem in kje gre za abuse, vendar sem svoje pravilo palca že navedel (zdaj že več kot enkrat). Lahko prediskutiramo error handling v širšem kontekstu če odpremo drugo temo.

Kar si podal za prvi primer je v bistvu popolnoma isto, samo da namesto if uporabiš try ... catch.
Ne popolnoma. Prvič manjši overhead, drugič možnost ignoriranja napake pri čemer se code flow nadaljuje v klicatelju copyFile (ne da bi ga obdajal v try catch pri vsakem klicu posebej). Če je tvoj cilj prenesti handlanje napake v katero od parent funkcij (se pravi prekiniti normalni flow programa in ga prenesti v catch), potem lahko pa še vedno v klicatelju copyFile vržeš izjemo.
Moja poanta pa je ravno v tem, da želiš prenesti code flow v catch le, ko pride do nepričakovane napake.
BTW: Kakor se spomnim RuntimeError še vedno "zmoti" normalni flow programa. Je preprosto exception, ki ga poznamo v C++, oz. ne zahteva eksplicitne deklaracije.
"My goodness, we forgot generics!" -- Danny Kalev

Zgodovina sprememb…

  • premaknilo od: OwcA ()

kopernik ::

Kaj je pravzaprav mehanizem izjem ? Deep down je to pravzaprav en nabildan if. So plusi in so minusi, tema o tem je že bila tudi tu na slo-techu, kolikor se spomnim. Moja original replika se je pravzaprav nanašala na tisto, da se funkcija sama odloči in pohendla izjemne situacije, kar se mi zdi narobe. Debato o izjemah zato lahko mirne duše končamo.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

CCfly ::

Res je tisto da funkcija sama shandla napako je slaba ideja. Moj kiks.
"My goodness, we forgot generics!" -- Danny Kalev

Zgodovina sprememb…

  • premaknilo od: OwcA ()

Gundolf ::

Ok Kopernik, tole je C++ in v C++u je vse exceptione treba ujeti, drugače bye bye program. Ko smo pa pri neintuitivnosti toFloat - neintuitivno ni dejstvo, da kličeš funkcijo myString.toFloat(myFloat) namesto myFloat = myString.toFloat(). To je tako daleč od neintuitivnosti, da se niti najmanj ne more primerjat z neintuitivnim try {myFloat = myString.toFloat();} catch (SomeKindOfException e) {/*..*/} Zakaj je to drugo neintuitivno? Zato ker se uporablja exception v normalnem poteku programa.

Ja sintaksa to vsekakor dopušča zlorabe exceptionov, ampak C++ ni jezik, kjer bi te sintaksa silila v lepo programiranje (kvečjemu te zavede v grdo). In mešanje resnih napak s pričakovanimi je le v redkih primerih lepo programiranje.

Kako Java razume exceptione je že druga zgodba. Sem že slišal od ne ravno slabih programerjev, da so v Javi uporabili exceptione kot orodje za končanje zanke...

P.S. Mehanizem izjem ni le nabildan if. Zraven sodi najbolj neka stvar, na katero je treba močno računat - stack unwinding. Poleg tega pretirana uporaba izjem povečuje možnost da pride do kakšne grde izjeme (recimo v konstruktorju, destruktorju ali v izjemi). Sicer bolj slab izgovor ampak če malo gledaš na to, da svojega programa ne kompliciraš za brezveze, potem ne uporabljaš izjem prepogosto oz. kadar jih ni treba.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

CCfly ::

Še stara tema Coding Style.
"My goodness, we forgot generics!" -- Danny Kalev

Zgodovina sprememb…

  • premaknilo od: OwcA ()

64202 ::

> Kaj je bolj elegantno, kaj je bolj pregledno, kaj je bolj varno, kaj je hitrejše in kaj je bolj pravilno? Če ti bo nek drug programer gledal kodo z exceptioni si bo mislil: "Zlomka, kakšen voodoo dela tale copyFile, da ga je treba zavarovat s try catch blokom?"

Spustil si tale primer (transakcije):
// exceptioni
copyFile(...);
...
...

// if z gnezdenjem
if(copyFile(...)) {
   ...
   if(...) {
      ret = true;
   }
}
return ret;


Ocitno to ustreza nekim pravilom o pravilnosti, je hitreje, ampak ne ustreza mojemu pojmovanju "elegantno, kaj je bolj pregledno, kaj je bolj varno" :).

> Kako Java razume exceptione je že druga zgodba. Sem že slišal od ne ravno slabih programerjev, da so v Javi uporabili exceptione kot orodje za končanje zanke...

No, jaz sem exceptione uporabljal za shranitev trenutnega stanja izvajanja. Torej, nekje naredis "throw freeze();" in ta "signal" potuje gor po stacku do handlerja za zamrznitev trenutnega stanja na heap. Potem ko je trenutek primerem, se pa koda se enkrat izvede, je pa seveda napisana tako, da se pravilno izvede nazaj do tocke, kjer sem izbljunil "freeze". Pac, moral sem sparat s sistemskimi threadi in nisem bil pri volji kolovratit z user-space threadi. Zdaj me pa krizajte :D
I am NaN, I am a free man!

Zgodovina sprememb…

  • premaknilo od: OwcA ()

64202 ::

Ah ja, da me ne bo kdo razumel kot exception fanatika. Kadar programiram gui kodo v qt ali wxwidgets sploh ne uporabljam izjem, ker je itak vecino kode v raznih callback handlerjih (= slotih), tam pa izjeme ne delujejo ravno najbolje. Pa se prevedes s -fno-exception pa je binary na koncu se toliko manjsi.
I am NaN, I am a free man!

Zgodovina sprememb…

  • premaknilo od: OwcA ()

Gundolf ::

Ne razumem tvojega primera 64202. Že če začnem pri prvem delu, uporabljaš exceptione in ne pogledaš ali ti je copyFile kaj vrgel? To pomeni potovanje do najbližjega catch bloka (ki je lahko šele v main funkciji ali pa ga sploh ni), kar večinoma pomeni, da je tak exception dokončen (se pravi, če ne morem skopirati fajla, bom pa kar končal program).

Kar se pa tiče tvojega primera v Javi te pa ne bom kritiziral. Java niti približno ni moje področje, vem le toliko, da so njeni exceptioni precej drugačni od teh v C++ - zaradi samega designa jezika.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

64202 ::

Ne, exception ni dokoncen, ampak je koda "transakcijska", torej imas 10 nivojev ali vec, in vse akcije na vseh nivojih morajo uspeti. Potem se pa kot zadnja akcija izvede nekam zapis o uspehu. Try/catch je pa samo en in to cisto na vrhu transakcije, ki v catchu rece "transakcija ni uspela". Najlazje je, da kar vse akcije sprozijo izjemo, ko gre karkoli narobe, kot pa da notri mesas if-e.

Tisto s throw freeze sem pa pocel v c++-su. V javi bi verjetno lahko vklopil green-threads...
I am NaN, I am a free man!

Zgodovina sprememb…

  • premaknilo od: OwcA ()

kopernik ::

Ja, gundolf, z ignoriranjem napake sem mislil v smislu, da te compiler ne sili, da jo ujameš. Itak je logično, da ko se sproži in se je ne ujame, ni variante da zadeva preživi.

Exception-i so, vsaj zame, precej uporabna zadeva. Je pa res, da vidim tudi jaz skrajno neokusno napisane programe, kjer se meče izjeme kar podolgem in počez.

In še nekaj, izjem ni potrebno razumeti zgolj kot napake, usodne za pravilno delovanje programa, temveč se jih lahko uporablja tudi za druge situacije. Običajno je itak tako, da se try ... catch bloki pojavljajo na višjih nivojih (na mejah našega programa/sistema), zato niti ni potrebe, da bi jih nametal po celotni kodi. Pač izjemo delegiraš naprej na klicatelja.

Zgodovina sprememb…

  • premaknilo od: OwcA ()

sid_dabster ::

Exceptioni so, ce se jih uporablja premisljeno, se kar uporabno orodje.Pri pretirani uporabi pa koda postane spaghetti, ravno tako kot pri (pretirani) uporabi goto.
Npr. koda , v kateri se exception lovi, kot je v zadnjem postu napisal 64202, sele na cisto na koncu stacka, je zaradi uporabe exceptionov preglednejsa.
Ce pa bos za vsako funkcijo (ki je znotraj zakljucena celota, morda celo implementirana v kaksni loceni knjiznici) pisal try-catch blok, pa se z vidika preglednosti bolj splaca, da enostavno evaluiras error kodo, ki jo funkcija vrne.

Videl sem pa tudi ze kodo, ko so ljudje iz loopov skakali tako z goto-ji kot z exceptioni. Oboje je (vsaj za moj okus) strasno grdo. In nevarno.

In mnogo dodatnih tezav nastopi pri multithreaded programih.

V embedded programski opremi pa exceptioni v principu prav ne pridejo, ker tam nepredvidenih situacij NE SME BITI, ker jih moramo poloviti ze z assertioni med razvojem programske opreme; za resevanje nepredvidenih situacij uporabljamo druge mehanizme (good old watchdog timer etc.).
Fallen beyond all grace deeper and deeper
The sound of her own blood dripping
Like sacred tears from a bleeding rose...( Embraced, Within)

Gundolf ::

Aja kopernik, sem te narobe razumel. Sem že pozabil, da Java omogoča take exceptione, za katere moraš nujno try catch blok postavit (vsaj tako se zdaj medle spominjam). V c++ tega na srečo ni, moja poanta je pa, da ravno zato ker jih ni treba ujeti (iz stališča sintakse), ni lepa koda, ki bi jih veliko metala takrat ko to ni treba. Bolje od mene je povedal sid_dabster, da niso za to, da ti varujejo eno samo funkcijo pred dokaj predvidljivimi dogodki.

64202, se strinjam, transakcijski primer je tudi lahko dober za uporabo exceptionov. O freeze pa iz moje strani le - svašta! No vsekakor ni nastala lepa in pregledna koda.

Pa da iz moje stvari naredim majhen zaključek (zdaj ko tema ni več off-topic tudi ni več tako zanimiva ;)). Vse kar sem govoril velja za stališče lepega programiranja. Kdor se (morda bolje rečeno kadar se kdo) ne sekira za lepo kodo, lahko uporablja vsa orodja kakor mu trenutno paše. In pa tudi v lepi kodi se najdejo izjeme, ki dopuščajo bolj liberalno uporabo uporaba exceptionov.

[edit: typoti...]

Zgodovina sprememb…

  • spremenil: Gundolf ()

rokpok ::

Bom še jaz postavil eno konkretno vprašanje. Sicer ne zadeva ne c++ in ne jave, ampak PHP. Primer funkcije:
public function __construct ($configuration) {
	if (!is_array ($configuration)) {
		throw new Exception ('$Configuration parameter must be array.');
	}
	if (!$this -> validateConfigurationSchema ($configuration, $this -> configurationSchema)) {
		throw new Exception ('Given configuration does not validate configuration schema.');
	}
	$this -> connect ($configuration);	
}

Ali je to dober način (z uporabo exceptionov)? Konkretna funkcija je iz razreda, ki se uporablja za delo z zbirkami podatkov. Parameter, ki je podan, mora biti polje in mora imeti določene ključe v polju (ključi se preverijo s funkcijo validateConfigurationSchema()). Ali sploh obstaja kakšen drugi način (v PHP-ju), s katerim bi preveril ali podani parametri ustrezajo določenemu tipu podatkov? Ker ko moraš funkciji podati tri parametre, nastane kar velik šmorn, če preverjaš vsak parameter.
Rad bi bil pingvin.

64202 ::

> O freeze pa iz moje strani le - svašta! No vsekakor ni nastala lepa in pregledna koda.

Hja, ta konstrukt je v c++ gotovo obskuren. Ce se bralec kode poglobi v zadevo, mu bo kaj hitro jasno, da je to kljub vsemu dokaj elegantna resitev za razliko od klasicnih state masin. Najlepse bi bilo s threadi resit zadevo, ker je koda transakcijska*, samo pricakovana obremenitev je stotine ali tisoce vzporednih zahtev, torej to s sistemskimi threadi ne gre. Druga resitev so user-space threadi, mislim da se to da pod unixom narest z ucontexti, pod winsi pa s fibri. Samo to prinese svoje tezave zraven, pa se treba je razmislit kako to vpliva na samo izvajanje c++-sa (destruktorji ipd.). Sicer za navdih pri "throw freeze()" mi je sluzil tale programski konstrukt: class Continuation

Kasneje sem sicer sprogramiral knjiznico (implementirano priznam z res morilsko template kodo), ki popolnoma loci konkreten mehanizem za paralelno izvajanje (threadi) in samo kodo. Torej lahko brez sprememb kode dolocis za n odsekov kode, ki se izvajajo v m threadih. n in m sta seveda parametra, ki jih lahko sproti v izvajanju dolocis. MS je zdaj cisto isto zadevo spravil v CCR (Concurrency and Coordination Runtime). Tole je vse skupaj ze offtopic, ampak sem hotel samo pokazat, da zavoljo "lepe kode" ne mores dati razvoja softvera za par let na hladno in razviti celoten CCR, ker je to lepo[tm].

* state masine so dokaj neprimerne za take zadeve
I am NaN, I am a free man!

Gundolf ::

Ja uporabnosti ne gre preveč trejdat za lepo kodo. Ampak za večino probemov obstaja elegantna rešitev (ne bom trdil da za tvojega tudi). Če pa že ne, je pa povsem sprejemljivo uporabit eno zelo grdo kodo, jo zapakirat v knjižnico, jo dodobra pretestirat in vse, njeno uporabo pa naredit elegantno. V najboljših knjižnicah je najbolj ogabna koda. In prav je tako. Knjižnice naj so tisto, kar skrije grde stvari a kar naj čimbolj učinkovito dela in naj ponuja uporabniku čim bolj enostavno uporabo.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[c#] try/catch, v katerem gradniku je napaka

Oddelek: Programiranje
101028 (766) japol
»

Vprašanji glede napak pri programiranu

Oddelek: Programiranje
171844 (1276) noraguta
»

null reference exception na čudnem mestu C#

Oddelek: Programiranje
51312 (1249) krho
»

[JAVA] Simpl problem z IF - ELSE stavkom :)

Oddelek: Programiranje
151775 (1518) morbo
»

[c++] goto,jump

Oddelek: Programiranje
181653 (1436) 64202

Več podobnih tem