ugrás a tartalomhoz

Kal - A Clean Alternative to JavaScript Without Callbacks

Joó Ádám · 2013. Aug. 17. (Szo), 17.19
Egy JavaScriptre forduló aszinkron nyelv a callback hell nélkül
 
1

Pont be akartam küldeni én is

MadBence · 2013. Aug. 17. (Szo), 18.30
Pont be akartam küldeni én is :)
2

Legközelebb megtartóztatom

Joó Ádám · 2013. Aug. 18. (V), 00.36
Legközelebb megtartóztatom magam :)
3

Nem értem

Hidvégi Gábor · 2013. Aug. 18. (V), 20.52
Az aszinkron programozás bevezetésének pillanatában megjelent a callback hell problémája, amivel azóta küzd a fejlesztői közösség, és ezerféleképp próbálja áthidalni. MadBence egy hosszú cikkben keresi a megoldást, az ott található yield nyelvi elemre hasonlít a Kal szintaktikában a wait.

Ezekkel pontosan ekvivalens lenne, ha a futtatókörnyezet alapértelmezésben elrejtené előlünk az aszinkron hívásokat, és egy adatbázis-lekérdezésnél úgy viselkedne, mintha az szinkron lenne. Érdemes összehasonlítani a három módot:

Kal:
wait for user from db.users.findOne {name: userName}
Yield-del:
var user = yield db.users.findOne({name: userName});
Szinkron:
var user = db.users.findOne({name: userName});

Roppant hasonlítanak.

Minden a szinkron kód mellett szól, mert ehhez nem kell új szintaktikát (yield) vagy új nyelvet (Kal) bevezetni.
4

Az egyedüli ami ellene szól

MadBence · 2013. Aug. 18. (V), 22.05
Az egyedüli ami ellene szól, az az, hogy szinkron, azaz amíg a művelet eredményére vár, nem tud mást csinálni (a processzor passzívan várakozik). Kliens oldalon ez azt jelenti, hogy addig nem képes a böngésző a különböző eseményekre (kattintás, billentyűzetleütés, stb) reagálni, szerver oldalon pedig azt, hogy a folyamat nem képes más kapcsolatokat kiszolgálni. A szintaktikai elemek bevezetése nélkül nem lehet megoldani az aszinkron->szinkron transzformációt

A yield és a wait for jelentése nem teljesen azonos (utóbbi inkább a C# await kulcsszavának felel meg)
6

Szerintem ő arra gondolt,

janez · 2013. Aug. 18. (V), 22.17
Szerintem ő arra gondolt, hogy aszinkron legyen.
Csak a szintaktika által arról "ne tudjon". Valósítsa meg úgy mint ha szinkron lenne.

szerk: én se tartom elképzelhetőnek.
8

A háttérben minden maradna

Hidvégi Gábor · 2013. Aug. 19. (H), 07.27
A háttérben minden maradna aszinkron.
A yield és a wait for jelentése nem teljesen azonos
Értem én, mi a különbség köztük, de a mostani probléma szempontjából ez irreleváns, végeredményben mindkét esetben a függvénynek van visszatérési értéke.
9

Az aszinkronnak pont az a

BlaZe · 2013. Aug. 19. (H), 08.52
Az aszinkronnak pont az a lényege, hogy tudd, hogy aszinkron, illetve amíg a feldolgozás fut a háttérben, a hívó program tudjon mást csinálni. Ha szinkron vársz, a programod futtatása megakad. Ha kulturált a futtatókörnyezet, akkor a háttérben yieldel egyet, és addig fut egy MÁSIK program.

Az ilyen waites és egyéb megoldások értelme az alábbi:
callref = async_call();
// do something
callref.waitFor();
Ezt szerintem szinkron hívás mögé álcázva nem tudod elrejteni, mert a szegény fordító honnan tudná, hogy melyik ponton akarod feldolgozni az aszinkron hívás eredményét? Gyakorlatilag hogy hol kell bevárja annak a futását, ha esetleg még nincs kész.
13

Ezt szerintem szinkron hívás

Hidvégi Gábor · 2013. Aug. 19. (H), 10.27
Ezt szerintem szinkron hívás mögé álcázva nem tudod elrejteni, mert a szegény fordító honnan tudná, hogy melyik ponton akarod feldolgozni az aszinkron hívás eredményét?
Vegyük a C fread() függvényét. Ha elkezdesz beolvasni egy fájlt, akkor az operációs rendszer lefagy, az egeret nem tudod mozgatni, billentyűleütésre nem reagál a gép? Vagy csak ez is egy rejtett aszinkron hívás, aminek a végén visszakerül a vezérlés a függvényedbe? A fordító honnan tudja, melyik ponton akarod feldolgozni az eredményét?
14

Az alkalmazás

Poetro · 2013. Aug. 19. (H), 10.42
Az alkalmazásod fagy le, azaz nem tud semmi másra reagálni, amíg nem fejeződött be a művelet.
26

Vagy csak ez is egy rejtett

BlaZe · 2013. Aug. 19. (H), 12.58
Vagy csak ez is egy rejtett aszinkron hívás, aminek a végén visszakerül a vezérlés a függvényedbe?
Nem az a lényeg, hogy a háttérben mit csinál, hanem hogy a te programod hogyan dolgozza fel egy hívás eredményét. Ha a hívás befejeztéig nem csinál semmit, akkor az egy szinkron hívás, ha aközben is dolgozik, akkor az aszinkron hívás. És ha ezt az aszinkron hívást becsomagolod egy szinkron hívásba, akkor gyakorlatilag elvész aszinkronnak lenni.

A fordító honnan tudja, melyik ponton akarod feldolgozni az eredményét?
Sehonnan, de nem is kell tudja, mert a következő utasítás addig nem fut le, amíg a file be nem töltődött, hiszen ez egy szinkron hívás. Aszinkronnál ez nem igaz, mert van 2 párhuzamos folyamatod, és a hívónak valahol szinkronizálnia kell a hívott folyamathoz. Hogy ez egy adott nyelven hogyan van implementálva, az egy másik kérdés.

Szerintem érdemes kicsit az event-driven és a többszálú programozásnak is utánaolvasnod, hogy rendesen megértsd mi megy a háttérben, és milyen problémákra milyen megoldások vannak a különböző nyelvekben.
27

Nézem az erlangot, olvasgatok

Hidvégi Gábor · 2013. Aug. 19. (H), 13.37
Nézem az erlangot, olvasgatok az eseményes témában, eddig ezt találtam:
Although event systems have been used to obtain good performance in high concurrency systems, we have shown that similar or even higher performance can be achieved with threads. Moreover, the simpler programming model and wealth of compiler analyses that threaded systems afford gives threads an important advantage over events when writing highly concurrent servers.
28

Érdemes megnézni a

MadBence · 2013. Aug. 19. (H), 14.12
Érdemes megnézni a szálkezeléssel járó problémákat... Nem véletlenül nincsenek pl többszálú grafikus felületek manapság. (http://codeidol.com/java/java-concurrency/GUI-Applications/Why-are-GUIs-Single-threaded/)
29

Az alapján, amit eddig

Hidvégi Gábor · 2013. Aug. 19. (H), 14.29
Az alapján, amit eddig találtam, GUI-k vezérlésére jobb az eseményvezérelt modell, ezt nem is vitatom, viszont alkalmazásfejlesztésnél már nem ez a helyzet.
31

Az egyszálú környezet

MadBence · 2013. Aug. 19. (H), 15.08
Az egyszálú környezet JavaScript esetén ugye innen adódik (hiszen a DOM-ot lehet javascriptből manipulálni). Node.js-ben pedig azért jó ez az event-based modell, mert kicsit memory footprinttel lehet nagyon gyorsan nagyon sok eseményt (főleg http kérést) kiszolgálni. Ha szálakban gondolkodunk, akkor egy webszerver elindítana n szálat (thread pool), és azokkal szolgálná ki a kéréseket. Ha itt másodpercenként sok ezer kérésről van szó, akkor a szálak karbantartásának költsége nem elhanyagolható tényező, nem is beszélve arról, amikor két szálnak kommunikálnia kell (pl globális állapothoz férnek hozzá, vagy pl ha webszerverről van szó, azonos munkamenet-adatokkal kell dolgozniuk: ilyenkor meg kell valósítani a kölcsönös kizárást). És ne feledjük, hogy ilyenkor a szálak többsége nem csinál semmit, "csak" vár. Ez elég nagy pazarlás (memória kell a stacknek, stb). A szálaknak olyankor van előnye, amikor CPU-intenzív feladatokat kell végezni. Egy webszerver nem ilyen (leginkább IO-t kell végeznie).
61

"Egy webszerver nem ilyen

saxus · 2013. Aug. 22. (Cs), 22.21
"Egy webszerver nem ilyen (leginkább IO-t kell végeznie)."

Ha már itt tartunk, pont múltkor volt egy vitám egy tipikus PHP utálóval, akinek mindegy miről van szó, ha PHP, mert akkor már szar. (Jó, valljuk be, PHP-vel valóban vannak komoly bajok). Meg lassú. Nos, múltkor méricskéltem, átlag 80-85% adatbázis-lekérdezés a PHP kódhoz viszonyítva.
62

A PHP nem tökéletes, de ahogy

inf3rno · 2013. Aug. 22. (Cs), 22.28
A PHP nem tökéletes, de ahogy nézem a javascript sem, pedig nekem nagy reményeim fűződtek nodejs-hez. :-) A típusos nyelvek - mint a java - meg körülményesek, nem annyira ad-hoc jellegűek, mint a js, nincs anonim függvény, ami pedig nagyban megkönnyíti a munkát... Nehéz ebben a témában igazságot tenni. A php régebben tényleg nagyon gány volt, de az 5+ verziókban már tákoltak rajta annyit, hogy most egyre elfogadhatóbb...
5

... ha a futtatókörnyezet

janez · 2013. Aug. 18. (V), 22.10
... ha a futtatókörnyezet alapértelmezésben elrejtené előlünk az aszinkron hívásokat, ...


Én nem tudom, azért a wait for, vagy valami szerintem nem baj ha ott van. Szeretek tudni róla ha valami aszinkron módon történik, főleg ha épp ciklusban vagyok.

Mondjuk nekem tetszik a Kal megvalósítása. A ciklusoknál meg kifejezetten. Ezt eltudnám viselni a futtató környezetben.

Amire még kíváncsi lennék a jövőben, hogy az erőforrások elérésének korlátozására építenek-e be megoldásokat. Olyasmikre gondolok mint a Pool, hogy a párhuzamos mégis mennyire legyen párhuzamos.
7

Szeretek tudni róla ha valami

Hidvégi Gábor · 2013. Aug. 19. (H), 07.14
Szeretek tudni róla ha valami aszinkron módon történik, főleg ha épp ciklusban vagyok.
Pontosan milyen többletinformációt hordoz számodra az, ha tudod, szinkron vagy aszinkron egy függvényhívás? A lehető legrészletesebben fejtsd ki, légy szíves, hogy ezt a többletinformációt mire használod fel a ciklus futása közben!
10

Tegyük fel, hogy az aszinkron

BlaZe · 2013. Aug. 19. (H), 09.14
Tegyük fel, hogy az aszinkron hívás eredményére várakozást becsomagolod valamibe, ami kívülről szinkron. Pl így:
obj = async_call();
obj.getResult(); // itt van egy waitfor belül
Ezt felhasználva írsz egy kódot. Tudod, hogy ez belül egy aszinkron hívás. Ma. De mi lesz 1 év múlva? Mi lesz, ha valaki más nyúl bele később, aki ezt nem tudja, és előbb hívja meg a getResult()-ot, mint az valóban legutolsó lépésként indokolt lenne? Azt veszi észre, hogy rossz esetben rendesen alárúgott a válaszidőnek. Aztán elkezd nyomozni, és észreveszi, hogy elrejtetted a hívást. Aztán csuklasz, aztán a rokonság is... :)

A válasz tehát az, hogy jó esetben beszélő programokat írunk, amik forrását olvasva x idő múlva is megérted, hogy mit csinál. Ha elrejted az aszinkron hívást, az információ óhatatlanul elveszik, és a jövőben ezt technical debt címszó alatt csúnyán meg fogod fizetni.
30

Pontosan milyen

janez · 2013. Aug. 19. (H), 15.00
Pontosan milyen többletinformációt hordoz számodra az, ha tudod, szinkron vagy aszinkron egy függvényhívás? A lehető legrészletesebben fejtsd ki, légy szíves, hogy ezt a többletinformációt mire használod fel a ciklus futása közben!


Ha ciklusban vagyok, és elkezdem pörgetni a ciklust akkor szinkron módon feltételezem, hogy a végrehajtandó feladatok egymásutániságát. Amíg ha aszinkron vagyok ezek párhuzamosak lesznek. NodeJS-ben nálam szinte mindig hamarabb lefut maga a ciklus, mint ahogy az első eredményt megkapnám. Főleg DB lekérdezésnél.

Egyszer ha a ciklusom 100-at fordul akkor az 100 konkurens lekérdezés DBMS felé per látogató.

Egy saját megvalósításban is elő példa:
A felhasználó elküld egy videó fájl feltöltő form-ot.
El kezdődik a feldolgozás. Amint feltöltötte a videót, én máris megjelenítem neki az eredmény oldalt. De ez előtt még elindítom a videó átkonvertálását. Ez aszinkron történik. A felhasználót már nem érinti. Nehezen tudok itt elképzelni szinkron kódot.

  • 1. fájl felötlés vége
  • 2. videó kódolás indítása [aszinkron] (4. és 5. párhuzamosak)
  • - 4. klaszterezés
  • - 5. mentés DB-be
  • 3. válasz a felhasználónak


Itt programozóként a szinkron kód engem jobban zavarna. (NodeJS)

app.post('/upload', function (req, res) { // 1.
  doConvert(req.files.video).success(function (path) { // 2.
     doClaster(path); // 4.
     doSaveDb(path, ..., function (err) { // 5.
        // awesome code ...
     });
  });
  res.render('uploaded'); // 3.
});
Szinkron elképzelés

app.post('/upload', function (req, res) { // 1.
  var path = doConvert(req.files.video); // 2.
  doClaster(path);  // 4.
  var result = doSaveDb(path); // 5.
  // awesome code ...

  res.render('uploaded'); // 3.
});
Itt kérdés, honnan is tudom, hogy most a doClaster és a doSaveDb az párhuzamosan mennek-e el.
Szerintem a wait for, yield, paralell, series kulcsszavak nagyon is hasznosak lennének egy szinkronnak tűnő kódban.

Szerk.: Azt belátom így is szervezhetem a kódot. Van egy fajta beidegződés már az aszinkron kódolás által.

app.post('/upload', function (req, res) { // 1.
  res.render('uploaded'); // 2.
  var path = doConvert(req.files.video); // 3.
  doClaster(path);  // 4.
  var result = doSaveDb(path); // 5.
  // awesome code ...

});
Bár hozzá teszem a valódi kódban a render még vár egy hívás eredményére. Ott a doConvert után tudnám berakni.
36

A példád nem a legjobb, mert

Hidvégi Gábor · 2013. Aug. 20. (K), 07.37
A példád nem a legjobb, mert a videókódolást még PHP-ban is másik processzként indítjuk, különben a feladat befejeztéig nem tudunk választ küldeni, és ez igaz a node.js-re is.

Egyszer ha a ciklusom 100-at fordul akkor az 100 konkurens lekérdezés DBMS felé per látogató.
És abban biztos vagy, hogy ez jó gyakorlat? Nagyobb táblákból való lekérdezésnél pillanatok alatt megtöltöd a processzor gyorstárát, és onnantól kezdve minden kontextusváltás akár százszor lassabb lesz a catche miss-ek miatt, és még jobb gépen is az ezredmásodperces kategóriába léphet, ami nagyjából ott van, mint egy lekérdezés feldolgozásának ideje.
37

Bár nem teljesen vagyok

MadBence · 2013. Aug. 20. (K), 12.35
Bár nem teljesen vagyok otthon az SQL ilyen jellegű lelki világában, de szerintem egy (SQL) kapcsolat egyszerre egy kérést tud feldolgozni, a többit egy várakozási sorba pakolja. A nyert idő pont annyi, hogy nem kell megvárni az előző kérés eredményének feldolgozását a következő kérés indításához.
38

Ha így van, akkor nem értem,

Hidvégi Gábor · 2013. Aug. 20. (K), 13.19
Ha így van, akkor nem értem, hol nyersz időt, hisz az előző kérés eredményét előbb-utóbb úgyis fel kell dolgozni, tehát ugyanannyi mindkét esetben az adatmozgás és az elvégzendő feladat.
39

Hát vannak speciális sql

inf3rno · 2013. Aug. 20. (K), 15.57
Hát vannak speciális sql kapcsolatok, amik mehetnek párhuzamosan, de a soros a jellemző.
40

Én is így tudom. Ha jól látom

janez · 2013. Aug. 20. (K), 16.24
Én is így tudom.
Ha jól látom bevett szokás párhuzamosan több kapcsolatot fenntartani és egy pool-ból kiszolgálni, ha nincs szabad kapcsolat akkor a kérések várakoznak.
(Bár én fenn DBMS alatt konkrétan a MongoDB-re gondoltam)
41

A példád nem a legjobb, mert

janez · 2013. Aug. 20. (K), 16.24
A példád nem a legjobb, mert a videókódolást még PHP-ban is másik processzként indítjuk, különben a feladat befejeztéig nem tudunk választ küldeni, és ez igaz a node.js-re is.


Igen, itt is külön processz de az csak egy feladat. Ott kilép egy másik szálra, de oda is tér vissza ha megvan vele (callback) és megy tovább a feldolgozás. Én addigra már a választ rég vissza küldtem a felhasználónak.

És abban biztos vagy, hogy ez jó gyakorlat? Nagyobb táblákból való lekérdezésnél pillanatok alatt megtöltöd a processzor gyorstárát, és onnantól kezdve minden kontextusváltás akár százszor lassabb lesz a catche miss-ek miatt, és még jobb gépen is az ezredmásodperces kategóriába léphet, ami nagyjából ott van, mint egy lekérdezés feldolgozásának ideje.


Konkrétan a MongoDB-ről van szó. Amúgy nem rontok neki párhuzamosan 100 lekérdezéssel. Csak azért írtam, hogy na különbség adódhat már 100 lekérdezésnél ha az párhuzamos vagy szinkron.

Itt pool-t építek be és tudom szabályozni a lekérdezésekből, hogy mennyit küldjek egyszerre párhuzamosan. Pl.: 5-8 párhuzamos kérés, ha egy végez mehet a következő. (Bár mondjuk néhány driver megoldja)
43

Cache miss vs scriptnyelvek

BlaZe · 2013. Aug. 20. (K), 17.49
És abban biztos vagy, hogy ez jó gyakorlat? Nagyobb táblákból való lekérdezésnél pillanatok alatt megtöltöd a processzor gyorstárát, és onnantól kezdve minden kontextusváltás akár százszor lassabb lesz a catche miss-ek miatt, és még jobb gépen is az ezredmásodperces kategóriába léphet, ami nagyjából ott van, mint egy lekérdezés feldolgozásának ideje.
Ezzel mit akarsz mondani? Hogy ne kérdezzünk le nagy táblákból, mert az sok adatot húz be? Ha van párszáz processed (pl jó sok apache a php miatt), akkor a context switchek úgyis baromi drágák, és a cache hit/miss arányod se feltétlenül lesz optimális. Ezek a scriptnyelvek amúgy se jók arra, hogy cachebarát kódot írjunk bennük, túl messze vagyunk a vastól. Történik, ami történik, nem sok ráhatásod van.

Mondjuk hogy ciklusban általánosságban nem feltétlenül éri meg adatbázishoz fordulni, azzal egyetértek. Meg azzal is, hogy drága a cache miss. De itt nem a cache miss ideje lesz a sok úgyse. Akkora cache misst úgyse tudsz produkálni, hogy össze lehessen vetni az adat hálón átrángatásával :) De szerintem ez a téma elég nagy ugrás a scriptnyelvektől. A vasat kihajtó kód készítése egy külön szakma, amit nagyon kevesen értenek jól, és teljesen más architektúra kell hozzá, mint pl egy átlagos weboldalhoz. De ha már, akkor a node.js architektúrája ehhez kicsit közelebb áll, mint pl a php.
44

Ezzel mit akarsz mondani?

Hidvégi Gábor · 2013. Aug. 20. (K), 18.39
Ezzel mit akarsz mondani? Hogy ne kérdezzünk le nagy táblákból, mert az sok adatot húz be?
Nem, hanem azt, hogy nem éri meg egyszerre sok lekérdezéssel bombázni az adatbáziskezelőt, ha az külön processzt indít minden lekérdezésnek.

Ha viszont valóban úgy működik, hogy a lekéréseket sorban, egymás után szolgálja ki, akkor ez nem gond. Ez valószínűleg így van, mert eszembe jutott, hogy pl. MySQL-ben van a thread_concurrency nevű beállítás, amit a magok számának kétszeresére célszerű állítani, azaz valószínű ennyi szálon mehet egyszerre lekérdezés párhuzamosan. Ebben az esetben viszont érdemes elgondolkozni azon, van-e értelme sok kérést egyszerre indítani, és hogy mit is nyerünk vele, főleg akkor, ha olyan adatbázisból kérdezünk le, ahol az adatok fizikailag egy tárolón vannak.
45

Nem, hanem azt, hogy nem éri

BlaZe · 2013. Aug. 20. (K), 19.47
Nem, hanem azt, hogy nem éri meg egyszerre sok lekérdezéssel bombázni az adatbáziskezelőt, ha az külön processzt indít minden lekérdezésnek.
Baj lenne, ha így lenne, mert egy nagyobb terhelésre hamar felzabálná a gép erőforrásait az adatbázisszerver.

Ebben az esetben viszont érdemes elgondolkozni azon, van-e értelme sok kérést egyszerre indítani, és hogy mit is nyerünk vele, főleg akkor, ha olyan adatbázisból kérdezünk le, ahol az adatok fizikailag egy tárolón vannak.
Gondolom azt, hogy minél előbb elindítasz egy kérést, annál hamarabb lesz meg a válasza :)
49

minél előbb elindítasz egy

Hidvégi Gábor · 2013. Aug. 21. (Sze), 06.41
minél előbb elindítasz egy kérést, annál hamarabb lesz meg a válasza
Akkor alternatívaként használható a mysqli_multi_query(), és akkor a kódnak sem kell széttöredeznie.
46

Na ez pont ideális téma lenne

inf3rno · 2013. Aug. 20. (K), 21.05
Na ez pont ideális téma lenne egy cikknek ;-)
11

Minden nyelv

Poetro · 2013. Aug. 19. (H), 09.43
Szinte minden nyelv képes aszinkron események feldolgozására. Gondolj csak bele a C-ben, vagy Assembly-ben a különböző megszakításokra, legyenek azok szoftveresek, vagy hardveresek. Azok aszinkron események, amikre te feliratkozol egy függvénnyel vagy kódrészlettel, és az a függvény akkor fog lefutni, amikor valami kiváltja azt az eseményt. De ugyanez a helyzet bármilyen UI programozáskor is bármilyen nyelven. Kirakunk egy gombot, és le akarunk futtatni egy kódsort amikor azt a gombot valaki megnyomta. Ez minden nyelven aszinkron fog lefutni, bár van olyan nyelv / API, ami ezt például egy végtelen ciklusba burkolja, amiben az eseményt figyeli, van amiben konkrétan megadod, hogy mi fusson le.

Az olyan nyelvekben, amik nem tudnak szálakat kezelni, vagy az nagyon bonyolult lenne, egy tökéletes megoldás. Szerintem nem szabad ezt elrejteni ezt a viselkedést a programozó elől, mert nem fogja tudni, hogy mire számítson, amikor először meglátja a kódot, és megpróbál benne mondjuk egy hibát felderíteni. Inkább legyünk beszédesek a működéssel kapcsolatban, mint elrejtsünk fontos részleteket. Főleg igaz ez akkor, ha a nyelvtől idegen ez a fajta működés (és valószínűleg a nyelvek jelentős részétől ez nagyon idegen).

Szerintem egy kicsit bele kéne ásnod magad az esemény vezérelt programozásba, és akkor megváltozna a véleményed, hogy miért is jó ez a megközelítés.
12

Aszinkron

Hidvégi Gábor · 2013. Aug. 19. (H), 10.23
A node.js nagyjából így működik:
- indítasz egy IO eseményt
- feliratkozol az onEseményComplete vezérlőre egy callback függvénnyel
- a függvényed futása leáll, a programod elalszik
- a vezérlés átkerül a node-hoz, amely futtatja a többi szálat
- az IO esemény befejeződik, kiváltódik az onEseményComplete
- a rendszer meghívja a callback-et

Az általam felvázolt rejtett aszinkron így működik:
- indítasz egy IO eseményt
- a függvényed futása leáll, a programod elalszik
- a vezérlés átkerül a node-hoz, amely futtatja a többi szálat
- az IO esemény befejeződik
- a vezérlés visszakerül az eredeti függvénybe

Ez utóbbi kísértetiesen hasonlít a yield-es megoldásra, csak nem kell hozzá yield.

Ha elindítok egy adatbáziskérést, azt azért teszem, mert szükségem van az adatokra. A programom addig nem tud továbblépni, amíg ezeket az adatokat meg nem kapom, mert ezek szükségesek a futáshoz.

A kérdésem számodra is adott: mi az a plusz információ, amit az hordoz számomra, hogy tudom: a rendszer aszinkron módon kéri le az adatbázisból az adatokat? Továbbá ezt az információt hogyan tudom felhasználni?
15

Lefagy

Poetro · 2013. Aug. 19. (H), 10.43
Az a probléma, hogy az alkalmazásod addig lefagy, és nem tud semmi mást feldolgozni, kiszolgálni, amíg várakozik. Pedig ha párhuzamosan tudna kéréseket kilőni az oprendszer felé, akkor hatékonyabban tudna működni.
16

Ha elindítok egy

Hidvégi Gábor · 2013. Aug. 19. (H), 10.46
Ha elindítok egy adatbáziskérést, azt azért teszem, mert szükségem van az adatokra. A programom addig nem tud továbblépni, amíg ezeket az adatokat meg nem kapom, mert ezek szükségesek a futáshoz.
17

Amíg te az #1-es user

MadBence · 2013. Aug. 19. (H), 10.51
Amíg te az #1-es user lekérdezésének eredményére vársz, addig a node ki tudna szolgálni másik 1000 usert, de így ez a lehetőség ki van lőve.
19

Nem értem, mit nem lehet

Hidvégi Gábor · 2013. Aug. 19. (H), 11.01
Nem értem, mit nem lehet érteni azon, amit leírtam. Idézem a 12-es hozzászólásban az általam vázolt rejtett aszinkron módot, kiemelés tőlem:

- indítasz egy IO eseményt
- a függvényed futása leáll, a programod elalszik
- a vezérlés átkerül a node-hoz, amely futtatja a többi szálat

Tehát hol állítom pontosan, hogy a node rejtett aszinkron módban nem tud tovább futni, és további ezer felhasználót kiszolgálni, vagy akár az alkalmazásom további párhuzamos szálait továbbfuttatni?
20

többi szálat

Poetro · 2013. Aug. 19. (H), 11.08
De milyen többi szálat? Összesen egy alkalmazás fut (egyetlen szálon) egy Node alkalmazásban, a Node által vezérelt szálak nem az alkalmazásod részei, ergo az alkalmazásodhoz, ha megállt, nem fut be több vezérlés, és nem tud több felhasználót kiszolgálni, mert áll.
21

Lényegtelen. Amit eddig írtam

Hidvégi Gábor · 2013. Aug. 19. (H), 11.13
Lényegtelen. Amit eddig írtam a szálakkal kapcsolatban, transzformáld át a következőre: és a node tovább lép az event loop-ban.
25

Erlang

Poetro · 2013. Aug. 19. (H), 12.18
Akkor lehet érdemes lenne megismerkedned az Erlang nyelvvel, ahol a dolgok ehhez elég hasonlóan működnek.
66

Go

Poetro · 2013. Aug. 28. (Sze), 17.14
Most találtam egy nagyszerű blogbejegyzést a Go nyelvről. Szerintem ez áll legközelebb ahhoz, amit szeretnél.
67

Igen, ez egy fokkal jobb,

Hidvégi Gábor · 2013. Aug. 28. (Sze), 17.49
Igen, ez egy fokkal jobb, valami hasonlót kéne csinálniuk, csak JS-sel. Azt viszont sosem értettem, miért szeretik sokan annyira a statikus típusosságot, nekem eddig nem volt bajom/nem származott hátrányom a dinamizmusból JS-ben vagy PHP-ban, inkább úgy gondolom, hogy sokkal gyorsabban lehet fejleszteni így, de a kód (talán) nem lesz annyival lassabb.
68

Típusosság

Poetro · 2013. Aug. 28. (Sze), 18.13
Én az utóbbi időben megszerettem a típusosságot JS-ben is (Google Closure Library), és elég sok haszna van, ha több 10.000 sornyi JS kódot kell karbantartanod. A fordító figyelmeztet, ha valami furát csinálnál, tud a típus alapján optimalizálni stb. És természetesen az IDE-ben is megfelelő kiegészítéseket ajánlja fel a típus és az öröklődés alapján.
70

Egy típusrendszer majd minden

Joó Ádám · 2013. Aug. 28. (Sze), 20.49
Egy típusrendszer majd minden hibádat elkapja fordítási időben. Nem tudom, hogy vagy vele, de én se a kivételeket, se a validáló if-ek képernyőit nem szeretem.
69

A go-ra azt mondják, hogy

inf3rno · 2013. Aug. 28. (Sze), 18.44
A go-ra azt mondják, hogy nagyon jó, érdemes használni.
71

Leszámítva, hogy azt ígérte,

Joó Ádám · 2013. Aug. 28. (Sze), 20.57
Leszámítva, hogy azt ígérte, hogy nem lesznek kivételek, és mégis vannak. Ezért kezdtem el tanulni, és ezért hagytam aztán a francba.

Ugyanitt szívesen veszem, ha valaki tud olyan modern, magasszintű, erősen statikusan tipizált, fordított nyelvet, amiben nincsenek kivételek, ellenben lehetőleg több értékkel is vissza lehet térni, vagy legalábbis vannak kimenő paraméterek vagy mutatók.
72

mi a baj a kivételekkel? mit

inf3rno · 2013. Aug. 30. (P), 04.08
mi a baj a kivételekkel? mit használnál helyette?
73

Az a baj velük, hogy egy

Joó Ádám · 2013. Aug. 31. (Szo), 02.30
Az a baj velük, hogy egy kivételeket használó nyelvben – lévén egyetlen sincs, amelyiknél a lehetséges kivételek részét képeznék a függvény kézjegyének – bármikor, bármelyik függvényhívás hatására összeomolhat a program.

A Java ellenőrzött kivételei egy jó kezdeményezés volt, de a kivitelezés csapnivaló: egyrészt nem kizárólagos, másrészt a szabványos könyvtár tele van olyan semmitmondó kivételekkel (IOException), amikkel semmit nem lehet kezdeni, harmadrészt a kivételkezelés szintakszisa áttekinthetetlenné teszi a kódot, miközben a gyakorlatban a kivételek rég nem kivételes helyzetek jelzésére szolgálnak, pusztán csak másodlagos visszatérési értékek (lásd Integer.parseInt()).

Hogy mit használnék helyette? Thompsonék is rájöttek arra, amire én, és pont ugyanúgy oldották meg, ahogy én szeretném: több értékkel való visszatéréssel, ahol az egyik egy státuszkód. A Goban ez így is működik, kivéve, hogy utólag mégis került bele egy panic()-recover() páros, ami effektív egy throw-catch, és így megint semmi garanciád nincs arra, hogy idegen kód hívásakor nem pukkad ki a lufi.
74

Nem teljesen értem, mondjuk

inf3rno · 2013. Aug. 31. (Szo), 09.31
Nem teljesen értem, mondjuk egy ilyet hogyan oldanál meg vele:

try {
    $data = $file->read();
    status(200);
    echo $data;
}
catch (IOException $e){
    status(404);
    echo 'cannot read file';
}
catch (Exception $e){
    status(500);
    echo 'unknown error';
}
77

$data, $error =

Joó Ádám · 2013. Aug. 31. (Szo), 14.33
$data, $error = $file->read();

switch ($error.getclass()) {
    case 'NoError':
        status(200);
        echo $data;
        break;

    case 'IOException':
        status(404);
        echo 'cannot read file';
        break;

    default:
        status(500);
        echo 'unknown error';
}
Nyilván egy komolyabb nyelv esetén a switch helyén mondjuk mintaillesztés állna.
78

Nekem a kettő tök egyformának

inf3rno · 2013. Aug. 31. (Szo), 16.23
Nekem a kettő tök egyformának tűnik.
79

Mert egyformák is. A

Joó Ádám · 2013. Aug. 31. (Szo), 16.37
Mert egyformák is. A különbség az, hogy része a függvény szignatúrának a hibatípus, és nem attól függ a programod helyessége, hogy ledokumentálták-e a kivételeket; és hogy nem kell minden függvényhívást körülvenned egy blokkal, mert ha nem kezelsz egy hibát, akkor legfeljebb valótlan adat kerül valahova, de normális és kiszámítható marad a vezérlés, nem kerülnek inkonzisztens állapotba külső erőforrások stb.
80

Java esetében - ha jól tudom

inf3rno · 2013. Aug. 31. (Szo), 18.35
Java esetében - ha jól tudom - ott van a metódus mellett egy felsorolás, hogy mit dobhat. A többi nyelvről nem tudok nyilatkozni, a php és a js nincs rendben, annyit tudok. Engem nem zavarnak ezek a kivételek abban az esetben, ha tesztelve vannak. Néha könnyebb megtalálni velük a hibát.
81

Java esetében - ha jól tudom

Joó Ádám · 2013. Aug. 31. (Szo), 19.03
Java esetében - ha jól tudom - ott van a metódus mellett egy felsorolás, hogy mit dobhat.


Ezek volnának az ellenőrzött kivételek, de vannak ellenőrizetlenek is, előbbieknek pedig elég rossz a megítélése a közösségben, így aztán semmit nem javítanak a helyzeten.

Engem nem zavarnak ezek a kivételek abban az esetben, ha tesztelve vannak.


Hogy érted, hogy tesztelve vannak? Egy ilyen függvényhívás lehet, hogy teliholdkor dob csak kivételt. Nem tudsz teljeskörűen tesztelni.
82

Ha nem lehet teljeskörűen

inf3rno · 2013. Aug. 31. (Szo), 19.11
Ha nem lehet teljeskörűen tesztelni, akkor a külső libet el lehet fedni egy adapterrel, ami elfog minden kivételt, és sajátot dob tovább helyette. Ha jól értem a problémád, akkor az elfogatlan kivételekkel van gondod, azok viszont már a te hatáskörödbe tartoznak, mert te írod a try-catch blokkot a külső libhez...
83

Annyira nem reális mondjuk a

Joó Ádám · 2013. Aug. 31. (Szo), 19.32
Annyira nem reális mondjuk a Java sztenderd könyvtár köré wrappert írni. Meg azért jó volna tudni, hogy mit kezdj azzal a hibával, márpedig egy ismeretlen kivételről nem fogod tudni.
84

A külső könyvtárakat

inf3rno · 2013. Aug. 31. (Szo), 20.09
A külső könyvtárakat általában jól meghatározott céllal használod. Ha kivételt dobnak, akkor nyilván a cél nem teljesült. Pl nem sikerült beolvasni a fájlt, stb... Le lehet loggolni, és később utánanézni. Ha asztali alkalmazásról van szó, az már gondolom macerásabb, ott max a felhasználót lehet megkérni, hogy ugyanmár küldje el neked a logot.
87

Checked vs unchecked

BlaZe · 2013. Aug. 31. (Szo), 20.29
Ezek volnának az ellenőrzött kivételek, de vannak ellenőrizetlenek is, előbbieknek pedig elég rossz a megítélése a közösségben, így aztán semmit nem javítanak a helyzeten.
Ez mit jelent pontosan? Vagy mire alapozod? Az tény, hogy sokan nem tudják melyik típusú exception mire való. Mint ahogy általában sokan nem tudnak helyesen exceptiont se kezelni.

Itt van egy leírás a két típus közötti különbségről.

A lényeg:
Unchecked exceptions: Represent defects in the program (bugs) - often invalid arguments passed to a non-private method.

Checked exceptions: Represent invalid conditions in areas outside the immediate control of the program (invalid user input, database problems, network outages, absent files)
88

Ha keresel a témában, a

Joó Ádám · 2013. Aug. 31. (Szo), 20.52
Ha keresel a témában, a legtöbb hang azt mondja, hogy ne használj ellenőrzött kivételt. Mindemellett a sztenderd könyvtárban sem tűnik igazán következetesnek. De egyébként én pont azért használok egy statikus analízis eszközt (fordító), hogy elkapja a hibáimat, ezért nem tudok mit kezdeni az első meghatározással.
89

Na ez a téma már tényleg

BlaZe · 2013. Aug. 31. (Szo), 23.27
Na ez a téma már tényleg nagyon messzire visz :)

Röviden: Én nem hiszek a fekete-fehérben, szerintem a checked exception nem buta dolog, de találkoztam én is olyan kóddal, ahol kicsit átestek a ló túloldalára. De szerintem az jó dolog, ha egy API meg tudja mondani milyen hibákra kell a hívójának felkészüljön, és ezek lekezelése ki is van kényszerítve a fordító által. Hogy mást ne mondjak, így reviewn pl könnyen el lehet kapni egy rossz hibakezelést, míg ha unchecked, akkor a reviewer adott esetben nem is tudja, hogy milyen exception jöhet az adott helyen, csak ha jól ismeri a hívott APIt. Na ez tényleg messzire visz :)

De egyébként én pont azért használok egy statikus analízis eszközt (fordító), hogy elkapja a hibáimat, ezért nem tudok mit kezdeni az első meghatározással.

A fordító jó, de mindent nem tud. Például az NPE és egyéb szintaktikailag helyes, mégis hibásan működő kódot nem tud kiszűrni.
91

Nem azért, nem kötöszködni akarok, de ha

Pepita · 2013. Szep. 1. (V), 23.32
Én nem hiszek a fekete-fehérben
, akkor éppen a mindennapi életemet élem, számítógép nélkül, abban ugyanis csak 0 és 1 van. Minél inkább tudunk fekete-fehérben programozni, annál jobb a végeredmény, kevesebb a hiba(lehetőség).
A típusosság, és az ezt maradéktalanul ellenőrző fordítók nagyon jó alternatíva.
92

Ez egy jó nagy butaság, már

BlaZe · 2013. Szep. 2. (H), 07.19
Ez egy jó nagy butaság, már ne haragudj :) Azért vannak programozók, hogy gondolkodjanak, és az optimális megoldást válasszák ki, nem azért, hogy buta szabályok, vagy szokások mögé beállva tolják a mindigúgyanúgyt. Az üzleti logika, a software architektúra és a 0/1 végtelenül messze vannak egymástól.

A típusosság és a fordítók ellen meg senki nem érvelt.
94

Nem haragszom, félreértettük egymást

Pepita · 2013. Szep. 3. (K), 19.45
A 0-1-re lebontási képesség pont nem megy "mindigugyanúgy", csakis és kizárólag teljesen azonos feladatnál. Arra meg minek írnál új progit, ha egyszer ott van.
Azt a végtelenül messzi távolságot bizony át kell tudni hidalni, az üzleti logikából kell tudni készíteni minél kevesebb 0-1-et.
Szóval szerintem (is) tényleg itt hagyjuk, mert túl messzire visz.
75

Exception vs hibakód

BlaZe · 2013. Aug. 31. (Szo), 13.12
Arra soha nem lehet garanciád, hogy idegen kód hívásakor nem pukkad ki a lufi, lévén, hogy nem te írtad, és nem sok kontrollod van felette. Az exception a hibakódnál erre egy modernebb szerkezet, és én személy szerint nem is értek egyet azzal, hogy a hibakódnál nehezebben olvasható kódot eredményez, mert az ifhalomnál semmi nem olvashatatlanabb. Vagy nem jött át hogy mire gondolsz pontosan.

Exceptionnel definiálhatsz olyan pontokat a programodban (pl global exception handlerek), ahol bármilyen hibát elkaphatsz mélyebbről, mégis be tudod azonosítani pontosan, hogy a program melyik pontján történt a hiba, ami infót egy hibakód már nem tud szolgáltatni.

A javas hivatkozásokkal kapcsolatosan:
Az Integer.parseInt() egyébként ugye nem is checked exceptiont dob, jogosan. És szerintem az kivételes eset, hogy egy nem valid szám stringet adsz oda neki. Ez nem validációra való.

Ami az IOException-t illeti, ahol van értelme tovább ragozni, ott tovább is van (pl FileNotFoundException)

Azzal viszont nagyon egyetértek, hogy nem ész nélkül kell exceptiont dobálni (pl azért, mert exceptiont dobni drága muri). Általános érvényű szabályként elmondható, hogy ha egy metódus olyan választ akar szolgáltatni, ami kizárólag a hívója számára hordoz információt, az ne exception legyen. Tehát a
validator.validate(input) throws ValidationException
valóban butaság. Az exception (egyik) lényege, hogy a kivételt ne csak a közvetlen hívó kód, hanem bárki feljebb le tudja kezelni.
76

Arra soha nem lehet

Joó Ádám · 2013. Aug. 31. (Szo), 13.55
Arra soha nem lehet garanciád, hogy idegen kód hívásakor nem pukkad ki a lufi, lévén, hogy nem te írtad, és nem sok kontrollod van felette.


De arra lehet garanciám, hogy ha a program nem is helyesen, de kiszámíthatóan viselkedik, és ezt a függvény felülete és a fordító garantálja, ha nincsenek kivételek. Ha vannak kivételek, akkor bármelyik könyvtári függvény hívásakor összeomolhat a programom, illetve bármikor átadhatja a vezérlést valahova a hívási fában feljebb, az én szándékom nélkül.

a hibakódnál nehezebben olvasható kódot eredményez, mert az ifhalomnál semmi nem olvashatatlanabb


Ezt sosem értem, mire alapozzák az emberek. Az if szinte minden nyelvben egy egyszerűbb szerkezet, mint a try-catch. Ha felkészülsz minden hibalehetőségre, akkor még ha ugyanolyan komplex szintakszis is mindkettő, pont ugyanannyi if-et kell írnod, mint try-t. El kell fogadni, hogy a hibakezelés bizony kódba kerül.

A dolog nyitja valószínűleg az, hogy a kivételek rászoktatták a fejlesztőket arra, hogy írunk egy nagy try-t a program tetején, aztán hadd szóljon. Csak ez nem hibakezelés.

Exceptionnel definiálhatsz olyan pontokat a programodban (pl global exception handlerek), ahol bármilyen hibát elkaphatsz mélyebbről, mégis be tudod azonosítani pontosan, hogy a program melyik pontján történt a hiba, ami infót egy hibakód már nem tud szolgáltatni.


Az ilyen handlerek már semmit nem tudnak kezdeni a hibával azon kívül, hogy naplózzák. Azonosítani pedig a hibakód helyét is lehetne, attól, hogy visszatérési értékként, a stack visszapörgetése nélkül adod át a hibaobjektumot, pont ugyanazt tárolhatod benne, mint egy kivételben.

Az Integer.parseInt() egyébként ugye nem is checked exceptiont dob, jogosan. És szerintem az kivételes eset, hogy egy nem valid szám stringet adsz oda neki. Ez nem validációra való.


Pedig itt épp hogy ellenőrzött kivételt kellene dobnia. Az, hogy a külső forrásból érkező adatban szám helyett egyéb karakter van, a legkevésbé sem különleges eset. Külön validáló függvény pedig nincs, és erőforráspazarló is volna kétszer megcsinálni ugyanazt (először validálni, aztán parsolni).

Ami az IOException-t illeti, ahol van értelme tovább ragozni, ott tovább is van


A baj az, hogy az IOException-nek nincs közlésértéke. Be akarsz zárni egy socketet, kapsz egy IOException-t. Mégis mi a bánatos tücsköt kellene vele csinálni?

Az exception (egyik) lényege, hogy a kivételt ne csak a közvetlen hívó kód, hanem bárki feljebb le tudja kezelni.


Hány példát tudsz erre összeszedni? Már azon kívül, hogy naplózol vagy hibaüzenetet jelenítesz meg a felhasználónak?
85

Ha vannak kivételek, akkor

BlaZe · 2013. Aug. 31. (Szo), 20.17
Ha vannak kivételek, akkor bármelyik könyvtári függvény hívásakor összeomolhat a programom, illetve bármikor átadhatja a vezérlést valahova a hívási fában feljebb, az én szándékom nélkül.

Ez igaz az unchecked exceptionökre, de nem igaz a checked exceptionökre, mert az része a szignatúrának. Az unchecked exceptionök tipikusan runtime (jellemzően programozói) hibákra valók, mint pl az említett NumberFormatException.

Ezt sosem értem, mire alapozzák az emberek. Az if szinte minden nyelvben egy egyszerűbb szerkezet, mint a try-catch. Ha felkészülsz minden hibalehetőségre, akkor még ha ugyanolyan komplex szintakszis is mindkettő, pont ugyanannyi if-et kell írnod, mint try-t. El kell fogadni, hogy a hibakezelés bizony kódba kerül.
Kód ifekkel:
ret1 = call1();
if ( -1 != ret1 ) {
  ret2 = call2()
  if ( -1 == ret2 ){
    handleError2();
  }
} else {
  handleError1();
}
Szemben ezzel:
try{
  call1();
  call2();
} catch (Exception1 ex){
  handleError1();
} catch (Exception2 ex){
  handleError2();
}
A második lényegesen áttekinthetőbb, a hibakezelés teljesen elkülönül az üzleti logikától, míg a rengeteg if eléggé töredezett kódot eredményez. Sőt, a try block teljesen ki is emelhető metódusba, és akkor egyáltalán nincs a logika körül exception kezelés. Ez azt gondolom nem összehasonlítható az ifes megoldással áttekinthetőségben.

A dolog nyitja valószínűleg az, hogy a kivételek rászoktatták a fejlesztőket arra, hogy írunk egy nagy try-t a program tetején, aztán hadd szóljon. Csak ez nem hibakezelés.
Ebben egyetértünk :) De én ilyet azért nem sokat láttam pályafutásom alatt...

Az ilyen handlerek már semmit nem tudnak kezdeni a hibával azon kívül, hogy naplózzák.
Dehogynem. Ez nem feltétlenül a main()-ben lévő try-catchet jelenti. De még ilyen helyzetben is sokat tudhatnak csinálni. Gondolj pl egy web service-re, ami az elkapott exception típusától függően más result code-ot ad visza. A hívónak nagyon nem mindegy, mégis egy try-catch blokkból jön az egész.

Azonosítani pedig a hibakód helyét is lehetne, attól, hogy visszatérési értékként, a stack visszapörgetése nélkül adod át a hibaobjektumot, pont ugyanazt tárolhatod benne, mint egy kivételben.
Akkor mi a különbség eközött és az exception között?

Pedig itt épp hogy ellenőrzött kivételt kellene dobnia. Az, hogy a külső forrásból érkező adatban szám helyett egyéb karakter van, a legkevésbé sem különleges eset. Külön validáló függvény pedig nincs, és erőforráspazarló is volna kétszer megcsinálni ugyanazt (először validálni, aztán parsolni).
Exceptiont dobni drágább, mint validálni, és csak akkor exceptiont dobni, ha rossz volt a validáció. Ami egy programozói hiba, ezért az unchecked exception.

A baj az, hogy az IOException-nek nincs közlésértéke. Be akarsz zárni egy socketet, kapsz egy IOException-t. Mégis mi a bánatos tücsköt kellene vele csinálni?
Pl jelezni, hogy nem sikerült a teljes adatcsomagot átküldeni. És dönteni, hogy újra megpróbáljuk, vagy beidőzítjük későbbre, akármit... Ez ugye jellemzően akkor dobódik, ha a close() miatt kikényszerített flush() nem sikerült.

Hány példát tudsz erre összeszedni? Már azon kívül, hogy naplózol vagy hibaüzenetet jelenítesz meg a felhasználónak?
Bármennyit :) Gondolj egy olyan objektumra, aminek van egy nagyon bonyolult metódusa, ami több metódusra van bontva, és akár azok is. Adott esetben elég a publikus metódusban lekezelni az exceptiont.
86

Az ilyen handlerek már semmit

tgr · 2013. Aug. 31. (Szo), 20.23
Az ilyen handlerek már semmit nem tudnak kezdeni a hibával azon kívül, hogy naplózzák.

Ennek éppen a fordítottja igaz: a legtöbb olyan hibát, amivel tudsz mást is kezdeni azon kívül, hogy naplózod, jóval magasabb szinten tudod csak lekezelni. A hibás user inputból származó problémákat (pl. nem létező id) azon a ponton tudod csak értelmesen lekezelni, ahol az inputot beolvastad (egy MVC webalkalmazásnál ez tipikusan a kontroller), nem azon a ponton, ahol megpróbálsz kezdeni valamit az adatbázisból kiolvasott tömbbel, csakhogy az üres. A súlyos hibáknál meg (pl. nem elérhető egy service) az egész aktuális műveletből ki kell hátrálni, ami szintén jellemzően sok absztrakciós szinttel feljebb ugrást jelent.

Másrészt meg nem árt, ha sok kitépni való haj áll rendelkezésre, hogyha minden egyes tömbhivatkozásnál státuszokat kell majd kiolvasgatnod, hogy hátha nem is volt olyan elem. Nem véletlen, hogy még az egyébként igen compile-time-ellenőrzés-barát Java is lényegében kihátrált a checked exceptionok mögül.
18

Több adat

Poetro · 2013. Aug. 19. (H), 10.52
De neked több adatra is szükséged lehet a futáshoz, amiket te párhuzamosan le tudsz kérni, és amikor megjönnek egyből fel is dolgozni, és csak amikor minden adatod megvan a felhasználónak szóló kimenet legenerálásához, akkor teszed meg. Például kell neked több adatbázis lekérdezés, egy HTTP kérés, egy kis log írkálás, és ezeket te párhuzamosan el tudod indítani, és amikor végül majd mind visszaért, akkor adsz választ a felhasználónak, de addig is folynak a háttérben dolgok. Ráadásul Node esetén ha több felhasználót akarsz kiszolgálni, akkor nem is szabad blokkolni, és az alkalmazást felfüggeszteni, mert akkor egyszerre csak egy felhasználót tudsz kiszolgálni.

Ha neked nem tetszik ez a szemlélet, nem kell használni, létezik annyi más nyelv és rendszer, ami elrejti előled ezt.
23

Például kell neked több

Hidvégi Gábor · 2013. Aug. 19. (H), 11.43
Például kell neked több adatbázis lekérdezés, egy HTTP kérés, egy kis log írkálás, és ezeket te párhuzamosan el tudod indítani
A kérdés a párhuzamosítható és nem párhuzamosítható kérések aránya. Sokkal inkább látom értelmét annak, hogy alapból legyen minden rejtett aszinkron, és külön jelöljük meg azokat a hívásokat, amelyeknek tényleg aszinkron kell lefutniuk.
24

Ha neked nem tetszik ez a

Hidvégi Gábor · 2013. Aug. 19. (H), 12.13
Ha neked nem tetszik ez a szemlélet, nem kell használni, létezik annyi más nyelv és rendszer, ami elrejti előled ezt.
Nem csak nekem nem tetszik, hanem a Kal alkotóinak sem, de még MadBence is egy hosszú cikket szentelt a problémának. Viszont, ha a Kal készítőinek sikerült egy új nyelvet alkotni, ami aszinkron javascriptté fordul, akkor logikusan következik a kérdés: nem lehetett volna eleve a (node)js-t olyanra csinálni, mint ahogy a Kal működik (wait/yield használatával vagy rejtett aszinkron működéssel)?
32

Ha elindítok egy

janez · 2013. Aug. 19. (H), 15.08
Ha elindítok egy adatbáziskérést, azt azért teszem, mert szükségem van az adatokra ...


Kivéve ha te szúrod be vagy frissíted őket. Abban az esetben nem szükséges megvárni.
Amúgy a lekérdezésnél is mehetsz tovább, mert jöhet az adat több forrásból is. Tipikus példa erre a MongoDB ahol kell egy plusz lekérdezés a join-hoz. Illetve rendelkezésedre állhat még ez előző lekérdezés megérkezte előtt is az az adat ami a második lekérdezéshez kell. (Nálam eléggé sok az ilyen)
90

Speciel en nem banom, ha

city99 · 2013. Szep. 1. (V), 18.23
Speciel en nem banom, ha kapok egy true-t a sikeres beszuras eseten ;) szoval az nem feltetlen igaz hogy nincs szuksegem "adatokra" vagyis inkabb valaszra, de meg az is lehet hogy a logika szempontjabol kritikus hogy sikerult vagy sem beszuras vagy frissites igy akar meg meg is varnam azt.
93

Ettől függetlenül én is

janez · 2013. Szep. 2. (H), 09.51
Ettől függetlenül én is kiértékelem a választ :)
,csak példát írtam arra, hogy van olyan eset amikor nem feltétlen van rá szükség. Logolás, stb.
22

A probléma ott van, hogy csak

MadBence · 2013. Aug. 19. (H), 11.16
A probléma ott van, hogy csak egy szál van, hiszen azért programozunk event looppal, mert nem tudunk szálakkal (nagyon leegyszerűsítve).
Plusz az általad vázolt megoldásban honnan tudja a program, hogy neki most el kell engednie a vezérlést (várakoznia kell)? Ezzel ugyanott vagyunk, mintha szálakkal bohóckodnánk:

console.log(i); //1
foo();
console.log(i); //csak a joisten tudja :(
Hiszen a foo most vagy aszinkron, és akkor bármi történhetett, vagy szinkron, és akkor nyilván nem változott semmi.

Lehet, hogy a probléma figyelmen kívül hagyása nagyon kényelmes (mert tényleg sokkal egyszerűbb lenne, ha szinkronnak álcázva működne minden!), de valójában sok egyéb olyan problémát generál, ami miatt nem érdemes ebbe az irányba mozdulni. Én még nem találkoztam ilyen jellegű ES kezdeményezéssel (pedig figyelemmel kísérem az ES6-7 feature-öket).
33

Nem foglalkoztam túl sokat

inf3rno · 2013. Aug. 19. (H), 23.11
Nem foglalkoztam túl sokat aszinkron js-el, de engem ez a problémamegoldás erősen emlékeztet arra az agyrémre, amit php-ban csináltak a sablonozással (smarty és társai). Teljesen felesleges egy új nyelvet kitalálni, amikor van egy létező, jól működő nyelvünk. Biztos vagyok benne, hogy ezek a problémák mind megoldhatóak javascripttel. A példákból nekem az jött csak le, hogy fogalmuk sincs arról a kal készítőinek, hogy hogyan kell átlátható kódot írni. Pl nem teszünk 5 szint mély behúzásokat egy függvénybe, a függvényeket lehetőleg beszórjuk egy-egy osztály alá, az eltérő rétegeket külön osztályokba szervezzük, az ismétlődő részeket meg a megfelelő absztrakciós szintre tesszük, ahol nem ismétlődnek. Nyilván ezeknek az elveknek az alkalmazása gondot jelent a szomszéd pistikének, de akkor ő ne álljon neki nodejs alkalmazást készíteni, maradjon csak a php-nél...
34

Lehet, hogy Istvánra kell

Joó Ádám · 2013. Aug. 20. (K), 00.29
Lehet, hogy Istvánra kell változtatnom, de nekem sem sikerült kézben tartanom a Node.js kódom a triviális méret fölött.
35

Okés, akkor majd beszélünk

inf3rno · 2013. Aug. 20. (K), 00.53
Okés, akkor majd beszélünk róla, ha több tapasztalatom lesz vele. Az még szerintem jó sok idő, mert most php-zek még legalább egy hónapig.
42

Az a gond, hogy a JavaScript

janez · 2013. Aug. 20. (K), 16.35
Az a gond, hogy a JavaScript nyelvi elemei még eléggé kiforratlanok és eléggé nehéz a nagy méretű kódot karbantartani, illetve eleve szép kódot írni.

Itt gondolok csak arra, hogy miket kell művelni egy osztály elkészítéséhez, annak örökléséhez, annak buktatói stb. Akkor még a callback-ek egymásba ágyazásáról nem beszéltünk. Valójában nagyon nehéz szétszedni a kódot rendeltetése szerint.

Vannak már törekvések ezek kijavítására ES6, de én személy szerint úgy érzem a JavaScript még gyerekcipőben jár, de jó úton jár ahhoz, hogy PHP dicsőségeire törjön rövid időn belül.

Hozzá teszem ez saját szubjektív véleményem.
47

Hát nem tudom, én egyelőre js

inf3rno · 2013. Aug. 20. (K), 21.10
Hát nem tudom, én egyelőre js klienssel foglalkoztam, és nem volt gondom a kód karbantartásával. Tesztelni meg ugye klienst nem éri meg, úgyhogy az kimaradt. Lehet, hogy jól tesztelhető kódot nehezebb írni...

Js-nél a core-ban vannak hátrányos dolgok, de ezeket nagyon kevés kóddal át lehet hidalni. Requirejs/commonjs és osztály örököltetős kód kell. Aszinkronra is van jópár áthidalós megoldás, majd lehet, hogy én is csinálok sajátot, ha jobban belefolyok. Elképzelésem már van a témáról, de most más foglalkoztat. Időt csináltam, töröltem a játékot, amivel tolni szoktam. :D
48

engem ez a problémamegoldás

Hidvégi Gábor · 2013. Aug. 21. (Sze), 06.39
engem ez a problémamegoldás erősen emlékeztet arra az agyrémre, amit php-ban csináltak a sablonozással (smarty és társai)
A smartynak az a szerepe, mint az OOP-nek, azaz hogy az ember ne csináljon túl nagy hülyeséget. Akkor van igazán értelme, ha csapatban dolgozol, egyedül csak hátráltat, mert akkor valóban nincs értelme egy új szintaktikát megtanulni. Egyrészt teljesen szétválasztja a programlogikát a megjelenítéstől, így akár verziókezelésre sem lesz feltétlenül szükség, másrészt a korlátozott elemkészlete miatt tényleg csak adatok megjelenítésére jó.
50

A smartynak az a szerepe,

inf3rno · 2013. Aug. 21. (Sze), 13.43
A smartynak az a szerepe, mint az OOP-nek, azaz hogy az ember ne csináljon túl nagy hülyeséget. Akkor van igazán értelme, ha csapatban dolgozol, egyedül csak hátráltat, mert akkor valóban nincs értelme egy új szintaktikát megtanulni.


Nekem ez a bizalom teljes hiányát jelenti a sitebuilder felé, aki a sablonokat készíti, ha meg nem bízol meg más munkájában, akkor miért dolgozol vele csapatban?
51

Nincs mindig lehetőséged

Hidvégi Gábor · 2013. Aug. 21. (Sze), 14.28
Nincs mindig lehetőséged megválogatni a munkatársaidat. Nagyon sok motiválatlan/kiégett ember van, vagy akiknek egyszerűen más a preferenciájuk, mint mondjuk neked. Őket nem érdekli annyira, mit csinálnak, nem céljuk a szükséges minimumnál többet nyújtani, és jóval többet hibáznak egy jó programozónál.
52

Hát ezeknek a kódját utólag

inf3rno · 2013. Aug. 21. (Sze), 15.06
Hát ezeknek a kódját utólag át lehet nézni, és javíttatni az esetleges hibákat. Ha meg képtelenek tanulni, akkor nincs helyük a csapatban. Persze erre sok helyen egyszerűen nincs kapacitás, ott valóban jobb ilyen biztonsági intézkedéseket bevezetni, de akkor sem kellene emiatt új nyelvet bevezetni, vannak olyan sablon rendszerek, ahol php-t használnak ugyanúgy erre a célra, és csak szűrik a forráskódból a használható paramétereket és függvényeket. A php sablonnyelv, tökéletesen alkalmas ilyen célra...

A js-el kapcsolatban nekem kifejezetten nem tetszik az, hogy ugyanígy új nyelveket próbálnak csinálni, amik js-re fordulnak, ahelyett, hogy az aktuális problémákat js-ben oldanák meg. Elég sok tisztán js alapú megoldás van erre az aszinkron kód formázási problémára, de ha ezt valaki nem tartja elégnek, akkor nyugodtan javasolhat a nyelv fejlesztőinek új nyelvi elemet. Szerintem nem véletlen, hogy ezek az új nyelvek, mint pl coffeescript, typescript, stb... annyira nem terjedtek el. A script nyelveknek az az előnye, hogy nem kell őket befordítani, ezek a nyelvek pedig pont ezt az előnyt veszik el, cserébe viszont nem sokkal nyújtanak többet, debuggolni viszont sokkal nehezebb őket.
53

Egy közepesnél nagyobb

MadBence · 2013. Aug. 21. (Sze), 15.11
Egy közepesnél nagyobb projectnél a JS fájlokat is ugyanúgy buildelni kell, szóval nem a buildeléssel van a baj, hanem azzal, hogy egy komplett új nyelv, ami fél év múlva vagy eltűnik (support, stb), vagy nem.
54

Ott a pont :-P Úgy látszik én

inf3rno · 2013. Aug. 21. (Sze), 15.24
Ott a pont :-P Úgy látszik én csak zsigerből érzem, hogy gond van ezekkel :D
55

Hát ezeknek a kódját utólag

Hidvégi Gábor · 2013. Aug. 21. (Sze), 16.06
Hát ezeknek a kódját utólag át lehet nézni, és javíttatni az esetleges hibákat. Ha meg képtelenek tanulni, akkor nincs helyük a csapatban.
Szerintem ez az átlag, és a cégeknek egyszerűen nem éri meg több időt és pénzt belefeccölni abba, hogy jobbat találjanak.

Az adatokat a megjelenésüktől külön kell választani, erre a smarty kezdetnek jó, de úgy általában a php mint sablonnyelv rossz választás, mert csak szerveroldalon fut.
63

így akár verziókezelésre sem

saxus · 2013. Aug. 22. (Cs), 22.36
így akár verziókezelésre sem lesz feltétlenül szükség


Már hogy ne volna szükség???

másrészt a korlátozott elemkészlete miatt tényleg csak adatok megjelenítésére jó.


Sajnos nem, viszont amikor meg kellene 1-2 dolog, akkor inkább hátráltat, mintsem segít. Teljesen felesleges plusz réteg a smarty.
65

Jó, hát verziókezelésre

inf3rno · 2013. Aug. 22. (Cs), 23.12
Jó, hát verziókezelésre szükség van, meg az OOP sem arra lett kitalálva, hogy ne csináljanak "túl nagy hülyeséget" az emberek, de szerintem felesleges szőrszálhasogatni, mert nagyon elmegyünk off irányba.

Én is úgy gondolom, hogy felesleges plusz réteg. Sosem tetszett, ha valaki új nyelvet akart építeni egy létező fölé, teljesen feleslegesnek érzem. Kicsit olyan ez, mint a bábeli zűrzavar... (Régebben én is elkövettem ugyanezt a hibát.)
56

A smartynak az is előnye,

Hidvégi Gábor · 2013. Aug. 21. (Sze), 17.40
A smartynak az is előnye, hogy a php-hoz képest jóval egyszerűbb szintaktikája van, és szebb, átláthatóbb sablonokat lehet vele létrehozni. PHP-val könnyű csúnya kódot gyártani, ami tele van például karakterláncok egymáshoz ragasztgatásával.

A php igazából alkalmatlan a hatékony sablonozásra.
57

Én nem igazán vagyok sablon

inf3rno · 2013. Aug. 21. (Sze), 20.03
Én nem igazán vagyok sablon párti, weblapokat le lehet írni szépen sablonnal, interaktívabb dolgoknál egy bizonyos szint felett már inkább nyűgnek érzem. A js kliensnél is inkább dom fát építek, mint sablonozok.
58

A php igazából alkalmatlan a

tgr · 2013. Aug. 22. (Cs), 05.42
A php igazából alkalmatlan a hatékony sablonozásra.

Bizony. A PHP lehet, hogy sablonnyelvnek indult húsz éve (abban az időben, amikor a C még egy jó alkalmazásfejlesztési nyelvnek számított), de a mai sablonnyelvek kritériumaitól messze elmarad. Nincsenek benne blokk függvények, nincs olvasható filter szintaxis, nincs autoescape, nem lehet sablonokat leszármaztatni egymásból, a legtipikusabb sablonos feladatokat (mint pl. iteráció az első és az utolsó sor speciális kezelésével, üres lista esetén default értékkel) nem támogatja normálisan; messze elmarad használhatóságban a Smarty, Twig, Moustache és társaitól.
59

Hát ennyire nem folytam bele.

inf3rno · 2013. Aug. 22. (Cs), 14.40
Hát ennyire nem folytam bele. Szerintem ezeket ugyanúgy meg lehet oldani php-ben is, különben nem lenne teljes értékű nyelv. Mondjuk akkor már nem feltétlen sablonról beszélnénk. Pl az első és utolsó sor problémáját egy saját Iterator-ral simán meg lehet csinálni. Én mondjuk nem szoktam sablonozni, nincs rá automatikus kiegészítés, legalábbis én még nem találkoztam vele. Felesleges plusz egy rétegnek érzem, amikor a View-al úgyis leválasztom a megjelenítést az üzleti logikáról...
60

Nyilván meg lehet oldani

tgr · 2013. Aug. 22. (Cs), 17.33
Nyilván meg lehet oldani PHP-ben is, a Smarty-t is PHP-ben írták. De nem feltétlenül akarod minden projektben magad megoldani, mint ahogy mondjuk a memcached klienst is meg tudnád írni magad PHP-ben, de valószínűleg nem érdemes :) És vannak dolgok, amikre a PHP szintaxisa egyszerűen nem túl barátságos, pl. függvénykonkatenáció (hogy a <?php echo dolgot ne említsük).
64

És vannak dolgok, amikre a

inf3rno · 2013. Aug. 22. (Cs), 23.07
És vannak dolgok, amikre a PHP szintaxisa egyszerűen nem túl barátságos, pl. függvénykonkatenáció (hogy a <?php echo dolgot ne említsük).


Hát vannak nyelvek, amik még barátságtalanabbak, nem tartom vészesnek azt az echo-t. Én mondjuk inkább dom fa szerűen szoktam html-t építeni, és nem sablonozok, de ez ízlés kérdése. Valahogy nem szeretem, ha a logika egy része adatfájlokban van csak azért, hogy sablonok legyenek.

De nem feltétlenül akarod minden projektben magad megoldani, mint ahogy mondjuk a memcached klienst is meg tudnád írni magad PHP-ben, de valószínűleg nem érdemes :)


Nyilván nem szeretném én megoldani, ha nem az én feladatom. Én úgy gondolom, hogyha egy sitebuilder képes megtanulni a smarty-t, akkor a php sem lehet olyan nagy falat neki, de lehet, hogy tévedek.

További hátránya ezeknek a nyelveknek, hogy egyik napról a másikra eltűnhet a support, bár azért ez már kevésbé valószínű, mint js esetében. Szintén hátránya, hogy ami van support, az sem teljes körű, pl egy automatikus kiegészítést kicsikarni belőlük gondolom nem egyszerű. Talán bizonyos IDE-k esetében már ezt is megoldották, nem nyomoztam utána. Én mindenesetre maradok a php-s view rétegnél, és azon belül a php kóddal épített html-nél, mert nekem az "tisztább szárazabb érzés".