A dinamikusan típusos nyelvek (pl. JavaScript) szerintem...

Címkék

Tűzre való szemetek, sosem nyúlnék hozzá, csak statikusan típusos nyelvekhez (pl. Java, Scala, C#...)
15% (54 szavazat)
Bizonyos jól meghatározott helyeken megfelelő választás, pl. lehulló hópihék egy weboldalon
50% (173 szavazat)
Nem teszek különbséget a statikus típusossággal szemben, ugyanolyan jó
30% (106 szavazat)
Jobbak mint a statikusan típusos nyelvek
5% (16 szavazat)
Összes szavazat: 349

Hozzászólások

A C# alapvetően erősen típusos, statikus _ÉS_ dinamikus típusú nyelv. Bár tény, hogy alapvetően az első kettő jellemző rá.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

(érdekelnek a későbbi eszmecserék - köszönöm)

Vajon amikor a fél világ a JavaScriptet kiváltó, arra forduló nyelveket ír, akkor annak az elsődleges oka az, hogy a JS szar, vagy az, hogy épp az fut a böngészőkben...?

A másodikra szavaztam, de szerintem a hópihés példa kicsit bagatellizálja.

Eddig talán legproduktívabb webes projektben GWT-vel voltam, Java->JS fordítással. Mostanában nézelődöm PureScript, GHCJS, illetve ScalaJS vonalon, de lehet, hogy a következő projektemet egyszerűen TypeScriptben írnám.

Mi ExtGWT-ztünk, Smart annak idején nem volt elég "csinos", kicsit összeszedetlennek tűnt, ennek kb. 5 éve. Anno 2G rammal végigtoltam az egész projektet, superdev-ről még nem is hallottunk, a dev mode viszont meglepően jól és gyorsan működött - persze kb. 45percenként újra kellett indítani, mert leakelt :-)

Persze a Java miatt tényleg szerettük, de az is tény, hogy több, mint egy megányi JS-t generál. Intranetes, belső porjektekre tökéletes továbbra is, de valószínűleg public projektekre ma már kínos, ha nem fél másodperces a siteload :-)

Ami miatt szerettem, hogy az SQL+Java+JavaScript+HTML+CSS 5-öst kiválthattuk Java+Java+Java+Java+Javával :-) De ez főleg az ökoszisztémának volt köszönhető, nem csak a nyelvnek.

Egyébként, ha már JS-re forduló nyelvek...
múlthéten OpenAcademy-n volt egy kérdés, amire nem kaptunk kielégító választ az előadótól, de hátha itt valaki:
futás közben, ha logikai hiba van a kódban, akkor a fordult JS-t kezditek el debuggolni a browserben, vagy vannak erre már kifinomultabb megoldások? Ha előbbi, akkor nem nagyon gáz (értsd kényelmetlen, átláthatatlan) ezt csinálni?

> „JS szar, vagy az, hogy épp az fut a böngészőkben”
ez meg szerintem ellentmond egymásnak: azért csinálunk mást, mert a JS szar -> de a böngészőkben a JS fut, így kénytelenek vagyunk JS-re fordítani...
--
blogom

Sourcemap-ekkel. http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ A legtobb transpiler tamogatja.

GWT-ben epp az volt a mindblowing, ott megcsak sourcemap sem kellett. Netbeansben (!) a java kodban (!!!) beallitottad a breakpointot, es amikor odaert a futtatas a bongeszoben, felugrott a Netbeans ablaka es ment a step-by-step debugging.

Amugy meg vannak azok a hangok, akik arrol harsognak, hogy mivel Haskellben irod a kodot es GHCJS forditja neked JS-re, igy ha mar egyszer lefordult, akkor ugyis azt csinalja a kod, amit akarsz :-)

"az elsődleges oka az, hogy" a Js nem felel meg a modern körülményeknek, jó volt annó arra amire kitalálták, csak azóta eltelt 20 év. Az ECMAScript 6 hoz most sok jó újjítást, azokkal már használhatób lesz.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

A gyengén típusos nyelvek között az a szerencsés trend kezd kibontakozni, hogy mindegyik megy el az opcionálisan típusos (type hinting) irányba. Szerintem ez a legjobb megoldás. Lásd: TypeScript, Python PEP 484, PHP 7 type hinting.

mostanában hozzá sem tudok szagolni a szavazásokhoz :(

A JavaScript tuzre valo szemet, de nem asnam el ettol az osszes ilyen jellegu nyelvet.

+1

A JS-től a falhoz mennék, de ez
* részben attól van, hogy __nagyon__ más, mint amit megszoktam/megszoktunk,
* részben meg attól, hogy a böngészők közötti különbséggel szenvedni kell.

A Pythont szerettem, könnyen, gyorsan lehet benne dolgokat csinálni - ellenben az tuti, hogy kell egyfajta bizalom, hogy senki nem fogja elbaszni a kódot a gyenge típusossággal - s nem szívesen nyúlnék bele egy nagy, bonyolult, dinamikusan típusos nyelven írt alkalmazásba, bármennyire is le lett fedve tesztekkel...

A JS egy kulon dimenzio. Mar eleve az, ahogy osztalyt csinalsz benne: olvashatatlan. Meg ahogy selectort vadaszol szarul strukturalt async kodban: debuggolhatatlan. Anonym fuggvenyek minify-olt kod stack trace-eben, closure totalis abuse-olasa ("akkor itt most ki a this?"), raadasul altalaban egy es ugyanazon forrasfajlba teszi a fejlesztok nagy resze a listenereket, az uzleti logikat, a szerverrol jovo adatszerkezeteket es a html renderelest is, (ez mondjuk pont nem maganak a nyelvnek a hibaja, de) hanyinger!

Lehet szidni a PHP-t, hogy fractal of bad design, meg mekkora elvi hibakra epul, meg minden, de legalabb egy PHP kodban megtalalod aranylag gyorsan, hogy hol a hiba. Meg a PHP devek egy eleg turheto hanyada legalabb hallott mar MVC-rol, ami miatt eggyel konnyebben meg lehet talalni, hogy ugyan milyen hiba korulbelul honnan johet. (Hozzateszem, ez nem a PHP erdeme).

Szoval nalam a JS nem a tipusossaga miatt bukik meg elsosorban, de ettol fuggetlenul jobb szeretem az erosen tipusos nyelveket.

> Azt felróni a js-nek, hogy rosszul használják, szerintem nem a js hibája
Persze, bármit lehet "rosszul használni", csak vannak nyelvek, amikben ez kimerül abban, hogy max. nem idiomatikus kódot írsz (pl. haskell, java), és vannak olyan nyelvek, ahol nem is tudsz ilyet írni, mert túl sok concept keveredik, és túl sok lehetőséget ad a programozónak a nyelvi entitásokon való bűvészkedéssel. Ez utóbbi kategóriába tartozik a js is.

A sok oldalú != azzal, hogy máshol bevett módszerekre létezik mindenféle kerülőút, és ki melyiket preferálja! Tipikusan a JS, ahol van aki {}-et használ, van aki functionöket, van aki prototypinggal bűvészkedik (és JS kódot ír azért, hogy lehessen örököltetni), és a többi. Ez nem sokoldalúság, hanem katyvasz ugyanarra a problémára, név szerint egységbe zárás.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

Csak nekem jutott eszembe a "..." helyére egy magyarországi bizonyos rassz, aki utál dolgozni lop csal elősködik? (hint: cigányok).

Es kit erdekel, hogy hany rendes ciganyt ismersz?* (Elarulok egy titkot: en is, nem is veluk van a gond.) Azt kellene eszrevenni, hogy ez az orokos nacizas nem vezet sehova.

Nezd meg ezt a cikket: http://www.hir24.hu/poszt-itt-publi/2015/05/22/vasaroltam.-lebuziztak

Ez a cikk gyakorlatilag 100%-osan atirhato a szereplok kicserelesevel egy tetszoleges sotetborsodi tortenetre. Kulonbseg a ketto kozott, hogy egyik esetben ordas nagy nacizas lesz a vege, holott a cikk semmiben sem kulonbozik attol, amit pl. bohocmasni vagy gabucino lemuvel: egy csoport megbelyegzese, altalanositassal.

Egy fikarcnyit sem kulonbozol azoktol, akiket te lenacizol. Teljesen ugyanazt muveled, okokat, megoldast keresve megbelyegzed a masokat, ugyanugy altalanositasz is es ugyanugy sokkal kulonbnek probalod tartani magad.

Reszemrol itt befejeztem a vitat, foleg, ha a nacizmus fogalmat sem vagy kepes kulonvalasztani a rasszizmustol.

(Bar bonusz kerdeskent azert feltennem, hogy ki tartja magyarkent elfogadhatonak a nacizmust, amikor alapvetpen az akkori nemet erdekek menten szuletett az az ideologia es gyakorlatilag bealdoztak Magyarorszagot - es kivaltkepp Budapestet - a naci Nemetorszag vedelmeben. Az mas kerdes, hogy utana a derek "felszabadito" szovjet elvtarsak meginkabb vegigpusztitottak az orszagot.)

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

(erősen szubjektív)

A jobbikos cigányellenesség sokkal közelebb áll a nácizmushoz (ami egy pozitív eszme, a mi fajtánk védelme*) mint a rasszizmustól. Ami kb. by def. erősen értelmetlen, és kétségbe vonható hogy kik és miért lennének.

* : a magyarság szeretetéből illetve a jelenlegi helyzetből elég egyértelműen következik a "rasszizmus", azaz a cigányok-mélyszegények pozitív/negatív megkülönböztetése különböző célzott programok/pogromok által, a jelenlegi helyzet, magyarság számára előnyösebbé tételére

szerk: akinek fogalma nincs, az ne említsen engem ebben a témában. Ez már kezd durva lenni.

"a magyarság szeretetéből illetve a jelenlegi helyzetből elég egyértelműen következik a "rasszizmus", azaz a cigányok-mélyszegények pozitív/negatív megkülönböztetése [...], a jelenlegi helyzet, magyarság számára előnyösebbé tételére"

Most hogy van ez, mire gondolt a kolto? A magyarokat akarod megkulonboztetni a ciganyoktol, vagy a melyszegenysegben eloket vonod ossze a ciganyokkal, es mindezeket kulonited el a "magyarok"-tol (barmit is jelentsen ez ebben az ertelmezesben)?

Raadasul az sem vilagos, mit szeretnel jobba tenni a magyarok szamara? Jobban izolalodjanak el az emlitett embercsoportoktol? Meg kevesbe legyenek szem elott ezek a csoportok? Bocs, de rettentesen homalyosan fogalmaztal.

Amit en latok: jelen pillanatban pont, hogy a ciganyoknak es a melyszegenysegben eloknek volna szukseguk segitsegre, ami lehetoseg szerint nem tartalmazza a szeggregaciot, hanem - meg ha nem is integraljuk oket - megkonnyitjuk szamukra a velunk valo egyuttelest. Persze, ehhez mindket oldalon tenni kell, de addig, amig a donteshozo magyarok nem egy megoldando problemat, hanem egy elszeparalando csoportot latnak ezekben az emberekben, addig nem igazan lehet arrol vitatkozni, hogy hogyan lehetne jobb a magyarok szamara.
--
Blog | @hron84
Üzemeltető macik

a ciganyoknak es a melyszegenysegben eloknek volna szukseguk segitsegre

Egyrészt ne általánosíts. Másrészt nem szívesen segítek olyannak, aki a segítséggel nem él, hanem visszaél, illetve egyre többet kér, mert az neki jár, gyakorlatilag "alanyi jogon" - nagyon sokan vannak ilyenek.

Már most szólok, mert tudom, hogy milyen vagy: nem, nem feltétlen csak a cigányokról beszélek és nem, nem az összes romát értem ide.

"megkonnyitjuk szamukra a velunk valo egyuttelest"

Minek? A ciganyoknak mar igy is nagyon konnyu velunk egyuttelnie, meg dolgozniuk se kell. De bezzeg nekunk veluk: az mar nehezebb, mert engem nem ugy neveltek hogy normalis, hogy kirabolok embereket a nyilt utcan, bocs, hogy ehhez kulon hozza kell szoknom hogy ok igy szoktak, mert ez a kulturajuk.

Aki ilyeneket hadovál egy mondatba, mint "magyarság" és "nácizmus" egy mondatban, meg hogy pozitív, az hülye és/vagy nem ismeri a történelmet. Nácik aztán kurvára nem nézték a magyar érdekeket, hanem Erdélyt csaliként használva a románokkal együtt belerángattak minket egy számunkra teljesen szükségtelen háborúba, majd beáldozták Budapestet egy második Sztálingrádnak, csak, hogy védjék az elveszett háborújukat. Aki szerint ez pozitív az ostoba.

A jobbik cigányellenessége meg nem más, mint egy tünete egy kezeletlen problémának és önmagában messze nem a megoldása. (És nem is a liberális babusgatás.)

Az, hogy erre szerinted a nácizmus az egyetlen megoldás, az a te szűklátókörűséged. Hitler megpróbálta, Németország azóta is szop miatta.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Nácikat nyugodtan lehet "legtöbb"-özni. Hogy valaki náci, az az ő szabad döntése, csak rajta múlik. Azt viszont senki nem maga dönti el, hogy cigánynak születik-e vagy sem, így ennek alapján megítélni valakit hibás absztrakció (másképp fogalmazva visszataszító primitívség).

Hát ez így ebben a formában nem teljesen igaz. A cigányok esetén sem legtöbbször za a probléma, hogy az adott személy cigány, hanem az, amit otthonról hoz. Az egyén fejlődése során az otthon felszedett kultúrális hatások, egymás elismerésének módjai, stb nagy hatással vannak az egyén jellemére. Ebből következik, hogy egy náci családba született egyénnek, aki náci nevelést kapott, és náci mintát látott maga előtt, nem biztos jogosan felróható, hogy ő a szabad akaratából náci. Szóval nem olyan triviális ám, hogy mi az egyén szabad akarata, és mi az a jellemébe égetett minta, amit otthonról hoz, mint amilyennek most felvázoltad.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - harmadik rész

Egyrészt igazad van.
Másrészt nem gondolom, hogy célravezető lenne ez a szemléletmód. Ha úgy tekintjük, hogy az egyén nem felelős azokért a tetteiért, amelyek családi neveltetéséből következnek, akkor ennek továbbgondolásaként gyorsan oda jutunk, hogy senki nem felelős semmiért, aztán már mindjárt a világ determinisztikusságáról, a szabad akarat létezhetőségéről és hasonló homályos filozófiai témákról beszélünk. Ez nem célravezető megközelítés, még akkor sem, ha van benne igazság.

Jelentem Ön náci! :)

Kicsit komolyabban: tényleg náciztak már le amiatt, mert kijelentettem, hogy nehogy már az legyen a mentség a megélhetési bűnözésre, mert valaki szegény és egyszerűbb neki lopni, mint kicsit megerőltetni magát és elmenni dolgozni.

Igen, tudom, nem túl sok hendikeppel indulnak a pozitív példák terén, de...

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

"csak rajta múlik" nem, nem csak rajta múlik. Természetesen hiszem, hogy minden egyén aki egy közösségbe tartozik, az felelős a tetteiért a közösség szabályainak megfelelően, ha ez nem felel meg neki, akkor közösséget kell váltani. Akinek nem tetszik, hogy magyarországon nem lehet lopni meg ölni, az keressen magának másik országot, ahol megengedik, ez nem is kérdés.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - harmadik rész

Akkor még egyszer. Aki náci az náci. Bár általában mára maximum fotelnácik maradtak.

Probléma az, hogy:
- felemlegeti, hogy 10:1-es arányok mellett 1:1 a börtönökben a cigányok, magyarok aránya? -> náci.
- nem tetszik neki a kettős mérce? -> náci.
- nem tetszik neki a szivárvány színű cipő? -> náci.
- kopasz? -> náci.
- bakancs van rajta? -> náci.
- Tigris tankot épít legóból kisgyerek korában? -> náci.

És még folytathatnám. Ugyanolyan halál lazán megbélyegeztek ti is embereket, mint a (fotel)nácik.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Én tűzre dobnám minden lelkiismeretfurdalás nélkül. Csak nevetek magamban azon, hogy mindenki megpróbál JS interpreteren futtatni minden mást. Persze a fura hibákat megtriplázva, mert úgy olcsóbb a fejlesztés. De ne kelljen telepíteni, menjen böngészőben!!!! Hahaha! Akkor megérdemled a 10-szeres költségen kapott gyenge végeredményt. Meg hogy néha bebizonyítják, hogy ha C programot fordítunk rá extrabrutálbutított módban, akkor már majdnem olyan gyors mintha elfelejtenénk a JS-t és rendesen gépi kódra fordítanánk. A jövő akkor kezdődik, amikor a JS-t sikerül elfelejteni. Addig vegetálunk csak.

Python megvan, es az, hogy Javanal 5-10x gyorsabban lehet vele haladni?

Szerencsetlen statikus agyak!
:)

Hát igen... az a jó a python-ban, hogy nagyon gyorsan lehet prototípust készíteni... aztán vége is az előnyöknek. :)

Éveken át karbantartani a kódot viszont kínszenvedés python/perl/scala/stb nyelvek esetén... "szerencsére" az ötletgazda addigra már egy másik cégnél és/vagy egy másik projekten fossa a python/perl/scala/stb forráskódot, mint a hasmenéses elefánt... :)

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Nem nemszeretés, hanem tapasztalat... :)

Iszonyú kevés mature kódbázis van ezekből a divatnyelvekből és azok nagyon nagy része abadoned... ami meg van, azok általában one man show alapúak, ha az eredeti alkotó abbahagyja, akkor inkább írnak egy újabbat, mintsem a régit foltozzák.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Nem tudom mikor nézted a toolokat, de egyre több, egyre jobb.
Pl. az IDE-kkel már szinte semmi gond nincs.

Én egyébként nem vagyok oda általában a "tool"-okért, leginkább egy-egy nyelvi vagy módszertani hiányosságot próbálnak pótolni velük, amivel még rontanak a karbantarthatóságon.

Hm... "egyre jobb", "szinte már semmi gond nincs"... aham. :)

Scala is olyan, hogy az ember gyorsan halad, a projektmenedzserek szeretik, mert gyorsan megy a projekt, az üzlet szereti, mert hamar kapnak megoldásokat, tulajdonképpen mindenki szereti, aztán amint a projekt egy kicsit is kinövi magát feladatban vagy időben, akkor jönnek elő a különféle problémák, amelyek spagetti kódot eredményeznek, aminek az egyik leggyakoribb megoldása, hogy a fejlesztők átmennek egy másik céghez egy újabb zöldmezős projektre... :)

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Az utolso ket Java projektemen pontosan ugyanez tortent. Aztan fel evig hibakeresessel teptem a hajam Pythonban. Pontosan ugyanolyan szar kodot lehet irni barmilyen nyelven, legyen az dinamikusan vagy statikusan tipusos.

Ket kivetelt ismerek: az egyik az ML tipusu nyelvek es a Haskell, a masik pedig a LISP alapuak (Racket, Clojure). Mindketto gyakorlatilag kikenyszeriti, hogy jol es tomoren megfogalmazd a mondanivalodat. Masik kozos jellemzojuk, hogy tobbet gondolkozol, mint amennyit gepelsz. A Scala ebbol a szempontbol sajnos tul nyitott, dehat ez kell az iparnak.

"Az utolso ket Java projektemen pontosan ugyanez tortent."

Nem azt mondom, hogy Java esetén nincs ilyen, mert láttam én már ilyen projekteket...

"Pontosan ugyanolyan szar kodot lehet irni barmilyen nyelven, legyen az dinamikusan vagy statikusan tipusos."

Azért vannak platformok, amelyekben sokkal könnyebb szar kódot írni.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

"Azért vannak platformok, amelyekben sokkal könnyebb szar kódot írni."

A Java és a Scala ebből a szempontból kb. egyformák, kb. ugyanaz a nehézségi szintje a szar kód írásának.

Viszont, ha megfordítjuk (, azaz vannak platformok, amelyekben sokkal könnyebb jó kódot írni.) akkor egyértelmű a Scala előnye a Javahoz képest.

"A Java és a Scala ebből a szempontból kb. egyformák, kb. ugyanaz a nehézségi szintje a szar kód írásának."

Hát...

"Viszont, ha megfordítjuk (, azaz vannak platformok, amelyekben sokkal könnyebb jó kódot írni.) akkor egyértelmű a Scala előnye a Javahoz képest."

Írtam, hogy az ember tényleg hamar halad. Az elején. Meg amíg tart a lendület és a jó hangulat.

Aztán amikor Scala-s stacktrace-t kell elemezni vagy szimplán hibát keresni; vagy kell egy viszonylag nagyobb refactor; esetleg stateful kell horizontálisan skálázni vagy szimplán csak evolválni kell a kódot olyan embernek, aki nem dolgozott a projekten és nem ismeri a helyi Scala dialektust (ugye bőséges syntactic sugar), akkor jön az őszülés, majd az "én nem ilyen lovat akartam", és a csendes kilépés a projektből.

Értem én, hogy újdonság, meg izgalmas, meg divatos, meg nagyon jó és különben is, csak amikor feloszlik a rózsaszín köd, akkor jönnek a meglepetések.

Kérdés: mennyi év volt a legtöbb, amit egy Scala projekten eltöltöttél?

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Úgy látom csak ilyen gányolós Scala-s projektekben vettél részt.
Sajnos nekem is vannak ilyen tapasztalataim Java-s projektek kapcsán, biztosan lennének Scala-sak is, de olyanokban még nem dolgoztam élesben sajnos. (és itt válaszoltam a kérdésedre is)
Pont ilyenekre gondolok, amiket írsz is. Olyan embereket raknak be a projektbe, akik alig ismerik a nyelvet, projektet, mindent block copy-val oldanak meg, ráadásul nincs is ellenőrzés, hogy miket és hogyan csinálnak, abból ilyen frankó (már bocs:) projektek kerekednek.
Ez viszont nem a nyelv hibája, hanem a metodikáé és az egyéneké.

Kérés: mutass egy olyan kódrészt az egyik ilyen projektből, ami mutatja, hogy mire is gondolsz, amiért ilyen rossz véleménnyel vagy a Scala-ról!

"Úgy látom csak ilyen gányolós Scala-s projektekben vettél részt."

Nem vettem részt a projektben, az utóéletében vettem részt, amikor már mindenki máshol dolgozott és kellett valamit kezdeni a helyzettel.

"biztosan lennének Scala-sak is, de olyanokban még nem dolgoztam élesben sajnos"

Hmm... jól értem, hogy akkor a Scala csak hobbiprojekt volt eddig?

"mutass egy olyan kódrészt az egyik ilyen projektből"

Nem kódrészleten múlik, hanem azon, ami körüllengi ezeket a projekteket. Amikor kapsz egy stacktrace-t, ami vég nélkül "anonfun" és "apply" sorokat tartalmaz és egyszerűen fogalmad nincs, hogy mivel van baj, csak találgatsz még akkor is, amikor elvileg jól értesz hozzá.

"Ez viszont nem a nyelv hibája, hanem a metodikáé és az egyéneké."

Igen, írtam, hogy ez nem a nyelvnek a hibája, hanem az egész platform, az ökoszisztéma és a fejlesztők így egyben alkalmatlanok még arra, hogy Scala éles üzemben bizonyítson. Majd talán fog. Vagy nem.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

"Hmm... jól értem, hogy akkor a Scala csak hobbiprojekt volt eddig?"

Jól, de abból egész sok. :)

"Igen, írtam, hogy ez nem a nyelvnek a hibája, hanem az egész platform, az ökoszisztéma és a fejlesztők így egyben alkalmatlanok még arra, hogy Scala éles üzemben bizonyítson. Majd talán fog. Vagy nem."

Akkor ebben részben egyetértünk. A platformot én már nem gondolom annak. Az ökoszisztéma lehet gond, nem tudom azon projekteknél miket választottatok, de vannak olyanok, amiket nem ajánlanék. A Scala-nak nagyobb a tanulási ideje, ezért bárkit nem szabad engedni szabadon garázdálkodni, a kevésbé hozzáértőknél le kell szűkíteni, hogy miket használhatnak, és kell a felügyelet (ez egyébként se rossz). Arról nem is beszélve, hogy kell a sok automata teszt.

Azért Javanál (meg a többi, fordított, statikusan, erősen típusos nyelvnél) nagy előny, hogy a refaktorálásokból jövő elbaszások egy részéért a fordító nyakoncsap.
Pl, ha egy függvénynek a valamelyik paraméterét átírom más tipusúra, a compiler szól, ha az IDE nem húzta utána minden helyen. Pythonnál velem előfordult, hogy a PyCharm ki-kihagyott függvényhívásokat, pl.
--
blogom

Vajon melyiket könnyebb karban tartani?



private
  iFoo : integer;

published
  property Foo : integer read iFoo write iFoo;


/**
 * @var int 
 */
private $foo;

/**
 * @return int 
 */
public function getFoo() {
  return $this->foo;
}

/** 
 * @param $value int
 */
public function setFoo($value) {
  if ($value != (integer)$value)
    throw new InvalidArgumentException('$value is not an integer!');

  $this->value = $value;
}

Magic methodos "alternatíva": (Mgj.: szerintem amit az IT-ben "magic" névvel illetnek, azt helyből kerülni kell messziről.)


private $props = array(
  'foo' => null,
);

public function __get($prop)
{
  if (!array_key_exists($this->props, $prop))
    thorw new InvalidArgumentException('Invalid property name: '.$prop);

  return $this->props[$prop];
}

public function __set($prop, $value)
{
  if (!array_key_exists($this->props, $prop))
    thorw new InvalidArgumentException('Invalid property name: '.$prop);

   switch ($prop)
   {
      case 'foo': 
        if ($value != (integer)$value)
          throw new InvalidArgumentException('$value is not an integer!');
        break;
      // ...
   }

  $this->props[$prop] = $value;
}


// bar.h:

class Bar
{
  private:
    int _foo;
  public:
    int get_foo();
    void set_foo(int value);
}

// bar.cpp

#include <bar.h>

Bar::get_foo() 
{
  return _foo;
}

Bar::set_foo(int value)
{
   _foo = value;
}


Oké, valóban lehet rövidebben is:


class Bar
{
  private:
    int _foo;
  public:
    inline int get_foo() { return _foo; }
    inline void set_foo(int value) { _foo = value; }
}



private int foo;

public int getFoo() {
  return this.foo;
}

public void setFoo(int value) {
  this.foo = value;
}

def __init__(self,foo):
  self.foo = foo

public int Foo { get; set; }

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Egészen addig, ameddig rá nem jössz, hogy az egyik setterre kell egy ellenőrzés és írhatod át 500 helyen a kódot.

Ezért jó a C#-os auto property. Arról nem tehetek, hogy a Java devek ilyen fogyi megoldást tudtak csak kitalálni.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

"Ezért jó a C#-os auto property. Arról nem tehetek, hogy a Java devek ilyen fogyi megoldást tudtak csak kitalálni."

Ahham... most komolyan egy pár kattintással generálható kódon kell rágódni? :)

Egyébként a C# (Delphi) megoldással az a baj, hogy nem tudod előre, hogy mi lesz az eredménye egy

v.Valami = 2;

utasításnak, mert fogalmad nincs arról, hogy ez egy sima értékadás vagy kijöhet belőle egy validációs hiba vagy bármiféle egyéb hiba.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Normal esetben egy lofasz.setValami(2) sem dob instant validacios hibat, mert erre semmi nincsen felkeszitve, hanem vagy a lofasz.save() dobja el magat, vagy pedig van egy lofasz.validate() metodus publikalva, ahol le lehet kerni a validacios hibakat.
--
Blog | @hron84
Üzemeltető macik

Nem vagyok benne biztos, hogy immutable objektumoknál indokolt a deep copy. Elég csak azokat az objektumokat másolni, amiken van módosítás. Persze lehet, hogy van olyan usecase, ahol ez az állítás nem igaz, de - tapasztalataim alapján* - életképes az a megközelítés, hogy a nem módosított részgráfokat referencia szerint "másoljuk" be az új másolatba.

* nemrég összejött egy újraírható de immutable AST reprezentáció ennek alapján, nagyon büszke voltam rá :D

Ilyesmi, de pont fordítva. A módosultat és a felettieket kell másolni.
pl. A objektumban van A1, A2; A1-ben A11, A12; A2-ben A21, A22. Ha módosul A22, akkor kell fölé egy új B2 (A2 másolata) és egy új B objektum. Tehát az A marad ugyanaz, a B-ben lesz A1, B2; A1-ben A11, A12; B2-ben A21, B22.

Ezzel a következő a probléma: az objektumok nem csak fák, hanem gráfok, ha nem végzel deep copy-t.
Jelenleg A21 két objektumban szerepel, de nem tudhatod, hogy van-e rá máshol referencia.
Ha módosítod a B2-ben A21-et, akkor az azt jelenti, hogy A2-ben is módosulni fog.
Honnan tudja B2, vagy A21, hogy ő melyik objektumokban van benne? Ehhez minden referenciának tárolni kellene az inverzét is.
Egy objektum nem tud, és nem szabad, hogy tudjon arról, hogy ki hivatkozik rá. Csak arról szabad tudni, hogy ő kire hivatkozik.

Nem kell, az immutabilitással pont azt a problémát lehet elkerülni, hogy egy objektum módosítása hasson a rá hivatkozó objektumokra. Pl. átadom egy függvénynek A21-et, aminek emiatt fogalma sincs, melyik objektumok hivatkoznak rá, és módosítanám az objektumot, az kihatna A2-re, ami kihatna A-ra. Immutable objektumokkal ez a veszély nem áll fenn, cserébe ha A21-ből szeretnék B21-et csinálni, és szeretném ha ez A-ban reflektálódna (tehát ismerem A referenciáját), akkor ahhoz A-ból kell csinálnom B-t és rekurzívan módosítanom kell az objektumokat B21-ig. Cserébe a nem változtatott objektumok esetén nincs szükségem deep copyra.

Egy példa többet ér ezer szónál:


case class Name(first: String, last: String)
case class Address(city: String, street: String)
case class Person(name: Name, address: Address)

val p1 = Person(Name("John", "Doe"), Address("London", "Trafalgar square 2"))
val p2 = p1.copy(address = p1.address.copy(street = "Trafalgar square 3"))

ahol

A = p1, A1 = p1.name, A2 = p1.address, A11 = p1.name.first, A12 = p1.name.last, A21 = p1.address.city, A22 = p1.address.street
B = p2, B2 = p2.address, B22 = p2.address.street

p1.name = p2.name, p1.address.city = p2.address.city


data Name    = Name String String
data Address = Address { city :: String, street  :: String }
data Person  = Person  { name :: Name,   address :: Address }

p1 = Person (Name "John" "Doe") (Address "London" "Trafalgar square 2")
p2 = p1 { address = (address p1) { street = "Trafalgar square 3" } }

Vagy még egyszerűbben és szebben lencsékkel (p2 = p1.address.street~="Trafalgar square 3" azt hiszem, de nem értek hozzá). Amúgy nem konkrétan ez a példa hozta ki belőlem az undort, csak megint eszembe jutott, hogy ADT-t definiálni milyen szar Scalaban; Trait, meg case class / object, stb. stb. Itt is .copy, etc.

Ohh, pedig azt hittem, beideztem a lereagalt mondatot.

"Pl. egész szép DSL-ek készíthetők vele viszonylag egyszerűen."

A Groovy-rol sok rosszat el lehet mondani, de azt nem, hogy kimondottan funkcionalis nyelv lenne, legalabbis a LISP-hez kepest eleg messze van tole, nagyon erosen objektumorientalt, es igazabol csak a closure-k azok, amik funprogra utalnak benne - de ez mar boven eleg ahhoz, hogy nagyon szep DSL-ek legyenek benne leirhatok, konkret pelda a Gradle build eszkoz.
--
Blog | @hron84
Üzemeltető macik

A-ha! Kezdőként én is itt akadtam el :-)

Nem a létrehozással van a gond, hanem a GC-vel. Ha nem hasznosítasz újra, akkor a GC megeszi az erőforrásaidat. Javaban ha most csinálsz egy deepcopyt, csak azért, hogy pure functional megközelítésben programozhass, akkor bizony az eredeti objektumaid mennek a GC-nek. Bár a generational GC-k világában ez nem _akkora_ nagy probléma (funkcionális nyelveknél pedig gyakori a sok, de rövid életű objektum), mégis van egy mérhető overheadje.

Mindig is lesz, nem véletlenül vannak a funprog nyelvekben mutable adatstuktúrák is (legalábbis Array, Matrix, Vector, stb.)

"funkcionális nyelveknél pedig gyakori a sok, de rövid életű objektum"

Java-nál is erősen optimalizálva van erre, így nem számottevő az overhead.

"nem véletlenül vannak a funprog nyelvekben mutable adatstuktúrák is"

A pure funkcionális nyelveknél nincsenek mutable adatstruktúrák.

Szerintem is van rájuk szükség, ha nem is gyakran.
A pure funkcionális nyelvek készítői és kedvelői szerint viszont nincs szükség rájuk.
Ha van ilyen benne, akkor nem pure (és egyesek szerint, akkor nem is funkcionális, ha nem pure; szerintem funkcionális úgy is, ha nem pure)

Az két külön fogalom ahogy tudom/értem a dolgot. A tisztán pure kb lehetetlen. Hogyan kezelnek tisztán pure nyelvben dátumot, vagy véletlen számokat, vagy hogyan írnak IO eszközre?? Ez nettó baromság. Lehet rá törekedni, de végül mindig lesznek elemek, amiket nem lehet kikerültni. Céleszközre célnyelvet el tudok képzelni, ha a cél is engedni, de valós életben használható univerzális programozási nyelvbe képtelenség a tisztán pure szemlélet.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

Ezek közül a Haskellt ismerem valamennyire, és lényegében az sem teljesen pure.

"átadják inputként azt az infót is, ami alapján kell a következő számot generálni" de ha mindig ugyanazt adják át, akkor mitől lesz véletlen, ha meg mást adnak át, akkor mitől lesz pure.

szóval, amit írtam, azt tartom még most is.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

Ugyanattól lesz véletlen, mint bármely más nyelvben, csak itt explicite átadod a randomgenerátor állapotát (amely ugye egyszer egy seeddel lett inicializálva). Ettől Pseudorandom. De ez inkább általános programozási koncept, mintsem funprog. Szóval jó tudni.

Ha nem pszeudorandomot akarsz, az a tudomány jelen állása szerint csak úgy érhető el, hogy információt szerzel a külvilágtól (lásd még: /dev/random és /dev/urandom közti különbség), azaz megintcsak IO monádhoz nyúlsz (egyszerűsítve újfent: valamilyen "computational context"-ből nyered az infót ~ a randomgenerátor (=világ) állapotából)

Valami sejtésem van azért a véletlengánerálásról ;)

Idézném a wiki-t, tudom nem szentírás, de hátha jó kiinduló pont:

- The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices (usually—see below).
- Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices (usually—see below).

Csűrhatjük meg csavarhatjuk, de a

func getRandom() { return xyImplementationOfRandomGenerator.next() } meg func getDate() { return new Date() } meg func storeToFs() { writeToFs("asd") } funkciók nem pure-ok, tehát "A pure funkcionális nyelvek készítői és kedvelői szerint viszont nincs szükség rájuk" - amire reagáltam - egy szép elmélet, de végül a gyakorlatban nem állja meg a helyét, mert ezen nyelvek kedvelői mindenféle trükkökkel próbálják a legkissebb szkópra redukálni a dolgot, de ha feketén meg fehéren nézzük, akkor bukó. Lehet tisztán pure programot írni pl. akadémiai fejlesztéseknél, és "verhetjük rá a nyálunk", de amint tárolni, vagy megjeleníteni is akarjuk az adatokat, ne adj isten külső forrásból beszerezni, akkor helló van.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

Meglepődnél, hogy akár a te mindennapi ügyeid folyásában is mennyire nem bukó a pure functional szemlélet; a banki rendszerek miatt már ma, a proteinfolding miatt pedig a jövőben lehetsz hálás annak, hogy valaki vette a fáradságot a "scope minimalizálására" :-)

Megállja a gyakorlatban az a helyét, csak azt kell megérteni, hogy a purefunc nyelvben pont, hogy nem hívsz getDate()-et abból a függvényből, amiben a bonyolult dátummatató logikádat írod, hanem annak egy bemenetként adod át a getDate eredményét. Olcsó trükk a szétválasztásra, mégis nagyon, NAGYON sok programozónak nem megy (lásd még printf-ek meg IO-ba logolások a businesslogic közepén), holott ehhez még funprog paradigma sem kell, elég lenne érteni az _igazi_ unit testinghez, ahol ez szintén nemkívánatos.

ne legyen IO unit tesztben

pont pár hete olvastam a könyv vonatkozó részét, és ezt így ebben a formában ezt pont nem olvastam ki belőle :)
Azt írta a szerző, hogy a unitteszteknek gyorsan kell futni, és a gyors az max. 10ms-t jelentsen. Azt pedig csak javasolta, hogy IO ne legyen benne.
Például ha egy unitteszt az inputot akármilyen markuppal leírt fájlból olvassa ki, ami hozzá van csomagolva a teszthez (szóval getResourceAsStream() hívásra gondolok), akkor az IO, de nem jelent releváns overheadet, így teljesen jó megoldás (ez pl. akkor jó, ha az inputnak az akármilyenmarkup leírása olvashatóbb, mint az akármennyire is fluent internal dsl-lel tesztből összelegózott java adatszerkezet).

> ezt így ebben a formában ezt pont nem olvastam ki belőle :)
Akkor olvasd el még egyszer :-)

A test is not a unit test if:
* It talks to the database
* It touches the file system
* It can't run at the same time as any of your other unit tests
* You have to do special things to your environment (such as editing config files) to run it.

(forrás: http://www.artima.com/weblogs/viewpost.jsp?thread=126923)

Nem, ha jól akarod használni, nem fér bele. Kettő fő oka van:
1) a unit test nagy vonalakban azt nézi, hogy adott inputra megfelelő outputot kapsz-e. Fájlolvasás esetén már elég nehéz garantálni, hogy az az input megy be, amit a teszt vár.
2) így nem a kódodat fogod tesztelni, hanem azt, hogy létezik-e a fájl, olvasható-e - tehát úgy általában a csak az adott környezetre/pillanatra érvényes IO-t. Ennek nem sok értelme van.

ahol IO van, az az esetek 9x%-ban olyan kód, ami egy dekóder. Persze bele lehet b@szni byte tömbben is az adatokat, de ez mennyivel szebb, mintha egy fileból olvasnánk be? Főleg úgy, hogy pl.java-ban nincs unsigned byte, viszont van nagyon kényelmes getClass().getResourceAsStream("test001.dat")

Egyes emberek arról is könyveket írtak, hogy milyen jó a Jackson diagram ... sőt, mindig van valami szent grál, amit nagyon okos emberek megmondanak, hogy ez öcsém, ez a tuti, aztán pár év múlva kiderül, hogy ami akkor jó ötletnek tűnt, azért annyira mégsem volt jó ötlet, vagy mégsem ez a tuti MINDENRE JÓ megoldás... szóval ez nem igazán jó érv.

Mi pedig, akik 1x-2y éve programozunk, had mondjuk már el a véleményünket, ami esetleg rámutat egy másik aspektusrra, amivel lehet, hogy a blog írójának mondjuk soha nem kellett találkoznia.

És innen már csak egy lépés választ el minket attól, hogy azért legyen valakinek igaza, mert ő mondta...

Az én fogalmaim szerint a unit teszt az olyan kódokat kellene, hogy teszteljen, aminek a bemenetét a programozó adja meg a kódjában. Ez kb. az int add(int x, int y) { return x+y; )
jellegű kódok. Ezt szépen bepakoljuk a JUnit/TestNG/stb. tesztrendszerbe, és gyakran lefuttatjuk (pl. minden SVN commitnál, Jenkins-ből). Amennyiben csak ilyen fajta kódokat tesztelünk, akkor persze teljesen igazak a feltételek: nem kell hozzá sem adatbázis, sem file rendszer, sem tesztesetek egymástól való függősége.

Ettől függetlenül szükség van olyan tesztekre, amik mondjuk egy bináris fileformátum dekódolásnál különböző bemeneteket tesztelnek. Itt lehetne azzal játszani, hogy a bináris adatokat belefordítom a class-ba (pl. byte[] formában). Ez a fenti definició szerint is unit teszt lesz, bár iszonyat ronda kódot fog eredményezni. Egy másik megoldás, hogy file-ból olvasom fel (getClass().getResourceAsStream("test001.dat")) ezeket az adatokat. Ez lehet hogy nem felel meg a definiciónak, de ettől még szerintem ugyanúgy unit teszt, egy kódot tesztel, bármikor lehet indítani, stb. Az esetleg egy hivatkozási alap lehet, hogy de hát az input adat, és a tesztkód nincs egy "helyen", viszont cserébe sokkal olvashatóbb lesz az egész kód, ami szerintem egy teljesen jogos érv. Sebességkülönbség lényegében nem lesz.

Na, a másik eset az, amikor a tesztelendő funkció adatbázis hozzáférést tartalmaz. Ilyenkor igazából feltételezzük, hogy van egy adott állapota az adatbázisnak, és abban az adott állapotban az adott funkció egy adott eredményt ad. Itt két fő helyzetet látok: az egyik, amikor a funkció lényegében egy SQL parancs. Itt nem igazán látom mockolási lehetőséget, illetve ezt nem hívnám igazából unit tesztnek. A másik, amikor a függvény egy adatbázis eredménnyel csinál valamit, ilyenkor esetleg lenne értelme mockolásra. Ezeket viszont már nem hívnám klasszikusan unit tesztnek, de ettől még futhatnak ugyanabban a junit környezetben, mint a fenti tesztek.

Nektek mi a véleményetek?

Elméleti szinten igen, gyakorlatilag viszont... oprendszert is odagenerálsz, ami futtatja a unit tesztet, vagy azt azért be lehet tölteni a teszt futtatása előtt? Hol van az a szint, aminél még engeded az I/O-t? Mert nem tudja saját magát a környezettel együtt generálni a unit teszt... :)

Mi a lényeges különbség aközött, hogy fordítási időben belegenerálod a unit tesztedbe a (forrás)fájlból való olvasás után a szükséges adatokat és azt betöltöd a unit teszt futtatása előtt (mert nyilván fájlból fogod felolvasni a fordított unit tesztet), vagy a teszt futási ideje előtt vagy alatt betöltöd azt?

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

"Elméleti szinten igen, gyakorlatilag viszont..."
Elméletről beszélek. Ennek az elméletnek az van a hátterében, hogy akár minden mentésre is gyorsan lefusson a unit test, és közben ne kelljen homokóráznom, amíg be nem fejeződik.

"Mi a lényeges különbség aközött, hogy fordítási időben belegenerálod a unit tesztedbe a (forrás)fájlból való olvasás után a szükséges adatokat és azt betöltöd a unit teszt futtatása előtt (mert nyilván fájlból fogod felolvasni a fordított unit tesztet), vagy a teszt futási ideje előtt vagy alatt betöltöd azt?"

E között valóban nem sok. Én nem is beszéltem ilyenről. Én a unit teszt futása során való generálásról beszéltem.
Pl. ez egy egyszerű xml elem generátor js-ben: '<test size="' + size + '">' + content + '</test>', és máris tudom az adott elemmel tesztelni a kódomat akár több ezer esetre is.

"Elméletről beszélek. Ennek az elméletnek az van a hátterében, hogy akár minden mentésre is gyorsan lefusson a unit test, és közben ne kelljen homokóráznom, amíg be nem fejeződik."

Óóó... de a mentés I/O művelet, nem? Dobjuk ki. :)

"E között valóban nem sok. Én nem is beszéltem ilyenről."

Ebben a szálban pedig erről van szó. :)

"Én a unit teszt futása során való generálásról beszéltem."

Az egy másik szál.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

"Mi a lényeges különbség aközött, hogy fordítási időben belegenerálod a unit tesztedbe a (forrás)fájlból való olvasás után a szükséges adatokat és azt betöltöd a unit teszt futtatása előtt (mert nyilván fájlból fogod felolvasni a fordított unit tesztet), vagy a teszt futási ideje előtt vagy alatt betöltöd azt?"

Lehet, hogy félreértettelek, azt hittem, hogy "generálás" alatt arra próbálsz utalni, amiről a szál egy másik ágában is szó van.
Ha nem arra gondolsz, akkor ennek a hozzászólásodnak sem látom semmi értelmét, mint ahogy a viccesnek szánt sok másiknak sem.

"Ha nem arra gondolsz, akkor ennek a hozzászólásodnak sem látom semmi értelmét, mint ahogy a viccesnek szánt sok másiknak sem."

Nem vicces. Csak szeretném látni, hogy hol húzod meg a határt.

Mert már csak pusztán ahhoz több tucat I/O művelet kell, hogy a unit teszted egyáltalán elinduljon majd az eredményét megkapd és mindez egy viszonylag komplex operációs rendszer tetején történik, szóval simán elképzelhető, hogy virtualizált környezetben fut a teljes unit teszt, plusz még a swap-en is van egy része és onnan kell betölteni majd újra kiírni... ezekről a gyakorlatias dolgokról elegánsan elvonatkoztattok, majd azon megy a késhegyig menő pusztán elméleti vita, hogy egyel több vagy kevesebb I/O művelet mekkora problémát okoz.

"Leírtuk, miért nem elméleti. Hivatkozásokkal alátámasztottuk."

Ahja... és ha Michael Feathers 10 évvel ezelőtt különösen szerette a zöldbabfőzeléket omlós fehér kenyérrel enni, akkor Te ma most a zöldbabfőzelék apostola lennél és kikelnél mindenki ellen, aki rozskenyérrel eszi a főzelékét. Ennél már a "csak" is jobb indok...

"Ezután sajnáljuk, hogy nem érted meg, de én több időt sem szánok már rá."

Ahja... gondolkodni kellene és érveket ütköztetni... nyilván egyszerűbb egy 10 éves blogposzt körbehordozása véres kardként. Hát hajrá, a tekintélyelv vitte mindig is előre a világot... ja nem. :)

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Az elv az, hogy a "unit teszten belülre ne tegyünk IO műveletet"!
Ez a határ. Arra, hogy előtte vagy utána mi történik, arra nem nagyon tudunk hatással lenni.

Épp a másik oldalnak kellene megmondani, hogy szerintük hol van a határ. Van-e ilyen határ egyáltalán, vagy bátran rakjunk bele bármennyit?

Analógia: Van egy poharad, benne valamennyi víz (alap IO). Mennyi vizet lehet még beletenni, hogy ne csorduljon túl?
Itt ugye az a probléma, hogy
1. változik a pohár (más-más rendszereken futtatják a unit teszteket, illetve egy rendszeren belül is változik)
2. többen is töltögetik a poharat egymástól függetlenül

Akkor legyél egy kicsit konstruktív és válaszold meg a kérdéseimet:
Mennyi IO lehet egy unit tesztben?
Egy projektnél összesen mennyi lehet benne?
Egy projektnél ki mondja meg, hogy mennyi lehet benne?
Szerinted lehet-e benne annyi, ami gondot okoz?
Mitől függ, hogy mennyi lehet benne?
Szerinted az gond-e, hogy egy unit teszt egyik fejlesztőnél 5 mp alatt fut le, a másiknál 2 perc alatt?
Szerinted mennyi idő alatt kell, hogy egy unit teszt lefusson?
Szerinted mennyi idő alatt kell, hogy a projekt összes unit tesztje lefusson?

Próbálom kicsit közös nevezőre hozni a vitatkozókat. Szerintem az a gond, hogy nem válik szét a fejekben a szigorú unit teszt, és az integrációs teszt. Ez különösen
úgy necces, hogy sokszor ugyanabban a keretrendszerben (junit, nunit, stb.) futnak a unit (mondjuk függvénytesztek) és integrációs (pl. adatbázist is használó) tesztek.
A saját kis bináris dekóder példámat most hagyjuk, értem, hogy bele lehet b@szni mindent a java osztályba, aztán akkor nincs IO (bár ótvar ronda lesz a kód).

Az nyilvánvaló, hogy az IO mennyiségét a lehetőség szerint próbáljuk minimalizálni. Ez rendben van. A unit teszteknek egyébként is az a dolga, hogy viszonylag gyorsan
tudjon lefutni. Hogy mennyire kell, hogy gyorsan lefusson? Nyilván az ideális eset az azonnal. Ha egy rendszerben mondjuk több tízezer unit teszt van, akkor ez lassan
fog lefutni, akármilyen erős gépen is dolgozunk. A kérdés az, hogy mi a csodának kell mondjuk több 10 ezer unit tesztet futtatni? Ha irok egy kódot, ami esélyesen nem
core funkciót érint, akkor csak a saját kódomat tesztelő unit tesztet kell majd lefuttatnom, tehát az esélyesen gyors lesz (mert csak 1-1 osztályt tesztelek). Miután becommitálom a branchembe, akkor a jenkins szépen lefut, végigtekeri a unit teszteket, és küld egy email-t, ha sikerült elqrni valamit. És őszintén, nem tök mindegy, hogy 3 másodperc, vagy fél perc múlva küld emailt? Úgysem reintegrálom addig a kódomat, amíg az összes unit teszt hibátlanul le nem fut rajta. Persze ez nagyban függ attól is, hogy ki milyen gyakran commitál. Én szeretek viszonylag gyakran, amikor 1-1 stabilabb állapotot elérek, más viszont sokkal ritkábban, mondjuk naponta, 2 naponta szokott.

Tehát:

Mennyi IO lehet: amennyire szükség van.
Összesen mennyi lehet: amennyire szükség van.
Ki mondja meg hogy mennyi lehet: a fejlesztők
Lehet benne annyi: ha gondot okoz, akkor szét kell szeparálni a unit teszteket (aminek egy része valójában integrációs teszt) gyors és lassú tesztekre
Mitől függ, hogy mennyi lehet benne: az előbb már volt
Egy unit teszt az egyik fejlesztőnél 5 mp alatt fut le: akkor a másik fejlesztőnél valami gond van, meg kell nézni, ki kell javítani.
Mennyi idő kell amíg egy unit teszt lefut: annyi idő alatt, ami még nem zavarja a fejlesztőt
Mennyi idő alatt fusson le az összes teszt: tök mindegy, mert nem a fejlesztőnek, hanem a háttérben futó jenkinsnek a dolga. Azért nem baj, ha mondjuk 15 perc alatt lefut minden, de nagy rendszernél nyilván sok idő lesz, kis rendszernél meg kevés.

"Az elv az, hogy a "unit teszten belülre ne tegyünk IO műveletet"! Ez a határ. Arra, hogy előtte vagy utána mi történik, arra nem nagyon tudunk hatással lenni."

Arra sincs hatásod, hogy alatta mi történik... lásd például virtualizált környezetek. :)

"Épp a másik oldalnak kellene megmondani, hogy szerintük hol van a határ. Van-e ilyen határ egyáltalán, vagy bátran rakjunk bele bármennyit?"

Annyit tegyél bele, amennyivel értéket tudsz teremteni az ügyfél számára...

"Analógia: Van egy poharad, benne valamennyi víz (alap IO)."

Csak I/O? Miért nincs CPU vagy memória poharad? A CPU vagy a memória végtelen? Unit tesztbe tehetek végtelen mennyiségű CPU vagy memória igényt, de I/O-t véletlenül sem? Akkor se, ha ezzel gyorsabb lesz a unit teszt? Akkor se, ha ezzel öt perc alatt kész a unit teszt, ha pedig eliminálom az I/O-t, akkor két hétig szüttyögök és trükközök, mert akkor nyerek mondjuk 2ms időt ennél a tesztnél? Persze, megtérül, ha a unit teszt futtatások meghaladják a 144 milliót, de ez nem igazán reális. Szóval mi a cél? :)

"Szerinted az gond-e, hogy egy unit teszt egyik fejlesztőnél 5 mp alatt fut le, a másiknál 2 perc alatt?"

Ezt csak az I/O befolyásolja? Hm... mik nem vannak.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

"Arra sincs hatásod, hogy alatta mi történik... lásd például virtualizált környezetek. :)"

Van hatásom, hogy alatta mi történik, amit belerakok a forrásba, annak mind van hatása. Ha belerakok egy IO hívást, ami nem válaszol, annak szerinted nem lesz hatása? Ha arra gondolsz, hogy nem csak annak van hatása, akkor így igaz, de minél több egyéb hatás van kívül, annál rosszabb még nekem is tetézni ezt a hatást.

A kérdéseimre amelyikre írtál valamit, azok egyike se érdemi válasz.

"Annyit tegyél bele, amennyivel értéket tudsz teremteni az ügyfél számára..."
Ezt hogy kell elképzelni? A fejlesztőknek mondod: "Srácok mindenki tehet IO-t a tesztelendő kódjába, de csak annyit, amennyi az ügyfél számára értéket teremt!"?
Itt egy adatbázis olvasás, ez értéket teremt, akkor ezt belerakom, itt egy írás, ezt is. Így?

"Csak I/O? Miért nincs CPU vagy memória poharad?"
Van CPU és memória poharam is, csak azok sokkal kiszámíthatóbbak. Illetve, ahol gond lehet, azokat se rakom be a unit test-ekbe, hanem a stress illetve performancia tesztekbe teszem be.

"Ezt csak az I/O befolyásolja? Hm... mik nem vannak."
Állított valaki ilyesmit? A kérdésre a válasz?
Van egy adatbázis hívásod a kódban, ami lefut 1ms alatt. Leáll a külső adatbázis, 2 óra alatt tudják a rendszergazdák megjavítani, vagy elmegy a net, akkor addig nem tudsz unit tesztet futtatni.
Ha jól értelek, akkor ez sem gond, mivel majd kijavítják és onnantól majd tudom futtatni a unit tesztjeimet, általában 1mp alatt, néha 5 perc, nagy ritkán 2 óra.

"ha ezzel öt perc alatt kész a unit teszt, ha pedig eliminálom az I/O-t, akkor két hétig szüttyögök és trükközök"
Igen, nem feltétlen egyszerű, sok esetben programozási paradigmát és/vagy módszertant kell hozzá váltani. (Hülyeség, mert nekem nehéz?)

Akkor még egy pár kérdés az előbbiekhez (bár nagy reményeim nincsenek):
Ha IO van a kódban, akkor elvileg le kell-e tesztelni az esetlegesen előforduló IO hibákra (lassan válaszol, nem válaszol, többször válaszol, ...)?
Ha le kellene tesztelni, akkor hogyan?
Származik-e abból előny, hogy párhuzamosan futtathatók a tesztek?
Ha IO-t tesztelsz, akkor származhat-e abból gond, hogy párhuzamosan futnak a tesztek?

Rá lehet mondani erre az elvre, hogy baromság, de ha be tudod tartani, akkor számtalan előny keletkezik, ha meg nem, akkor hátrány.

"(Hülyeség, mert nekem nehéz?)"

Ha nem ad effektíve értéket, akkor igen, hülyeség.

"Van CPU és memória poharam is, csak azok sokkal kiszámíthatóbbak."

Annyira démonizálod itt az IO-t, hogy jajúristen, mennyire szörnyű, hogy lassan félek lemezhez nyúlni. De most komolyan, gyakorlatban mennyire mutatkozik meg annak a hátránya, hogy egy adatot, amit a teszteléshez használok, az unit teszt kód olvassa be és nem a programkóddal együtt előre? (Mert ugye valahogy annak be kell kerülni a csodás, kiszámítható memóriába, CPU-ba.)

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

"Ha belerakok egy IO hívást, ami nem válaszol, annak szerinted nem lesz hatása?"

Ha berakok egy memória foglalást és nincs annyi szabad memória, annak mi lesz a hatása? Az I/O is olyan erőforrás, mint a többi... továbbra se értem, miért épp ez az egyetlen az, amit üldözni kell... :/

"Ezt hogy kell elképzelni? Itt egy adatbázis olvasás, ez értéket teremt, akkor ezt belerakom, itt egy írás, ezt is. Így?"

Úgy, hogy ha ez a sok szakmai maszturbálás túlsúlyba kerül, akkor az ügyfél azt látja, hogy hétről hétre nem kap semmit...

"Van CPU és memória poharam is, csak azok sokkal kiszámíthatóbbak."

Miért lennének kiszámíthatóbbak? Pont annyira kiszámíthatóak és stabilak, mint az I/O: vagyis semennyire.

"Van egy adatbázis hívásod a kódban, ami lefut 1ms alatt."

Hamar eljutottunk az adatbázis hívásig (=integrációs teszt) a szimpla tesztadat-beolvasástól (=egyszerű I/O)... veszélyben az elmélet, túlozni kell, vagy mi van?

"Igen, nem feltétlen egyszerű, sok esetben programozási paradigmát és/vagy módszertant kell hozzá váltani. (Hülyeség, mert nekem nehéz?)"

Nem azt írtam, hogy nehéz, hanem azt, hogy idő, amíg a tesztadatokat beleilleszted inline a teszt forráskódba, majd írsz rá teszteket, hogy a tesztadatot jól illesztetted-e be... mert nehogy fel kelljen olvasni (például) a @BeforeMethod/@BeforeClass szakaszban fájlból (amit még támogat is egy csomó unit teszt eszköz), mert az tiltott I/O művelet.

"Ha IO van a kódban, akkor elvileg le kell-e tesztelni az esetlegesen előforduló IO hibákra (lassan válaszol, nem válaszol, többször válaszol, ...)? Ha le kellene tesztelni, akkor hogyan?"

Ha memória használat van a kódban, akkor elvileg le kell-e tesztelni az esetlegesen előforduló memória hibákra (lassan allokálódik, mert fragmentált a memória vagy swap-et kell használni; OutOfMemory a válasz, mert nincs elég memória; ...)? Ha le kellene tesztelni, akkor hogyan? Hm?

Ugyanez igaz bármilyen más erőforrásra, ami kell a teszt futtatásához. Vagy bízzuk a tesztet futtató környezetre, hogy lefoglalja és/vagy biztosítsa szükséges erőforrásokat? Á, nem... az hülyeség.

"Származik-e abból előny, hogy párhuzamosan futtathatók a tesztek? Ha IO-t tesztelsz, akkor származhat-e abból gond, hogy párhuzamosan futnak a tesztek?"

Mi köze az I/O használatnak ahhoz, hogy párhuzamosan futtathatóak-e a tesztek? Ha a memória fogy el, akkor mi a helyzet? Ha a CPU fogy el, akkor mi a helyzet? :)

"Rá lehet mondani erre az elvre, hogy baromság, de ha be tudod tartani, akkor számtalan előny keletkezik, ha meg nem, akkor hátrány."

Hát... bizonyítani semmit nem bizonyítottál... hacsak nem azt, hogy a CPU és a memória használata is tiltott kell legyen a unit tesztek futtatásánál. De hát azt csak nem szeretnéd. :)

"Hát... bizonyítani semmit nem bizonyítottál... hacsak nem azt, hogy a CPU és a memória használata is tiltott kell legyen a unit tesztek futtatásánál. De hát azt csak nem szeretnéd. :)"

De, de, nagyon szeretnenk! Udvozlettel, Uzemelteto csapat. :D

Komolyra forditva.

En azt gondolom, hogy vannak azert esszeru hatarok, amikor az IO megengedett egy Unit tesztnel, de abban valamennyire igazat adok a kolleganak, hogy az eszetlen lemeztekeres senkinek se jo. Ahogy a Java kodokat optimalizaljuk, hogy minel hatekonyabban hasznaljak fel a memoriat es a processzort, arra is optimalizalni kell, hogy hatekonyan hasznaljak fel a lemezt. Nekem peldaul eszembe nem jutna egy minta XML outputot beleturni a kodba csak azert, hogy a File osztaly szent konstruktorat meg ne kelljen hivni unit tesztbol. Ugyanakkor 2-3-5 soros igazsagtablakat szerintem ostobasag CSV-bol olvasni, mert azert azok boven elfernek a kodban is.

Szoval hol az igazsag mostanaban? Baratsagos, meleg huvos szobaban.
--
Blog | @hron84
Üzemeltető macik

"Hát... bizonyítani semmit nem bizonyítottál"
Nem is akarok semmit se bizonyítani.
Próbáltam konstruktívan leírni, hogy milyen előnyei vannak ha nincs IO a teszt futása során.

"Hamar eljutottunk az adatbázis hívásig (=integrációs teszt) a szimpla tesztadat-beolvasástól (=egyszerű I/O)... veszélyben az elmélet, túlozni kell, vagy mi van?"
Én sehol sem írtam, hogy milyen IO, minden IO-ról szó van, fájl IO, lokális adatbázis IO, hálózati IO, ... Leírtam azt is, hogy nyilván 1 lokális fájl IO kevésbé rossz. Te akarod arra alapozni az érvelésed, hogy 1 lokális fájl IO az semmi, akkor X-szer semmi is az. Ráadásul előhozakodtál a virtualizációval, aminek köszönhetően az se biztos, hogy mindig lokális, amit annak hiszel.

Azt hiszem én is kiszállok.

"Én sehol sem írtam, hogy milyen IO, minden IO-ról szó van, fájl IO, lokális adatbázis IO, hálózati IO, ... "

De ezek erősen különböző I/O erőforrások, nem lehet egy kalap alá venni ezeket...

"Leírtam azt is, hogy nyilván 1 lokális fájl IO kevésbé rossz."

Ahham... akkor a totális I/O tiltástól eljutottunk oda, hogy egy lokális fájl felolvasása kevésbé rossz? Alakul. :)

"Te akarod arra alapozni az érvelésed, hogy 1 lokális fájl IO az semmi, akkor X-szer semmi is az."

Nem, én arra alapozok, hogy ha olcsóbb/gyorsabb/egyszerűbb/átláthatóbb lesz egy unit teszt az I/O használatától (= ezáltal értéket teremtünk), akkor használjuk és ne hivatkozzunk egy tíz éves blogbejegyzésre, amely a lassú HDD-k korában íródott és általános érvényű tiltást ír egyetlen egy fajta erőforrásra, ami akkor tényleg szűk keresztmetszet volt.

"Azt hiszem én is kiszállok."

Ok, pedig pont kezdett értelme lenni a vitának. :)

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Abban más, hogy egy külső erőforráshoz fordulsz.

Szerk.:
Azért, hogy kicsit érthetőbb legyen:
- A unit tesztet fejlesztés során számtalanszor futtatod, hogy lásd, helyes-e az általad megírt kód.
- Az integritás tesztet azokkal a külső rendszerekkel teszteled, amikkel mennie kell. Pl. fájl IO-nál azt szeretnéd tesztelni, hogy Windows-on, Linux-on, read only fájl rendszeren, ... fut-e.

...és? Miben kell máshogy tesztelni? Logikailag miért nem a Foo osztályhoz tartozik, hiszen a Foo egységről akarom eldönteni, hogy jó-e.

Memóriát miért nem kezeled potenciálisan külső erőforrásnak? Virtuális memória mellett nem tudhatod, hogy az adott címzett memória az nem-e ram, mappelt fájl, swap, valami periferianak a regisztere, vagy egy masik számítógép memoriajanak egy darabkája halozaton at elérve. Erről szól az absztrakció, hogy ezekkel nem foglalkozok.

Ha a LoadFromStreamet tesztelek mi van? Lehet MemoryStream es FileStream is.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Unit tesztnél az a cél, hogy minden fejlesztőnél ugyanúgy, jól és gyorsan fusson, mindegy, hogy Ő pl. Linux-ot használ, pedig a Linux nem is támogatott.
Ezért célszerű az IO-t leválasztani amennyire csak lehet, és unit tesztnél ezeket mock, stub, ... -val helyettesíteni.
Integritás tesztnél pedig a tényleges külső rendszerekkel teszteljük.

Szerk.
Ha a kódodban általános stream kezelés van, akkor a unit tesztnél használhatod a MemoryStream-et, integritás tesztnél a FileStream-et.

És a nem támogatott oprendszeren csak a unit teszt nem fog menni? Hogy próbálja ki a fejlesztő, hogy mit fejlesztett? Hogy keres hibát? :O

"Ezért célszerű az IO-t leválasztani amennyire csak lehet, és unit tesztnél ezeket mock, stub, ... -val helyettesíteni. Integritás tesztnél pedig a tényleges külső rendszerekkel teszteljük."

Ööö... izé... a fájlrendszer nem külső rendszer... ha külső rendszer, akkor a memória és a CPU is külső rendszer...

"Ezért célszerű az IO-t leválasztani amennyire csak lehet, és unit tesztnél ezeket mock, stub"

Most akkor (én értelmezésemben: a legtöbb esetben) célszerű leválasztani (ha nem indokolt) vagy ősbűn?

(Kezdem úgy érezni magam, mitn egy goto vitában.)

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

"Pl. fájl IO-nál azt szeretnéd tesztelni, hogy Windows-on, Linux-on, read only fájl rendszeren, ... fut-e."

Nem. Unit teszt szinten azt szeretnéd tesztelni, hogy a bemenő paramétereknek megfelelő tartalom és metaadat keletkezik-e.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Attól, hogy Te nem tartod külső egységnek az IO egységeket, attól az még így van. Próbáld megismerni a számítógép alapjait!
Részletek a Wikipedia-ról:
"In computing, input/output or I/O (or informally, io or IO) is the communication between an information processing system (such as a computer) and the outside world"
"In computer architecture, the combination of the CPU and main memory, to which the CPU can read or write directly using individual instructions, is considered the brain of a computer. Any transfer of information to or from the CPU/memory combo, for example by reading data from a disk drive, is considered I/O."

Ha Te a külső rendszereket unit tesztelni akarod, tedd! Engem most már kicsit hagyhatnál. Legalább ebben a szálban ne válaszolj a hozzászólásaimra. Ígérem én se fogok a Tieidre!

Bocsánatot kívánok, de ne keverjük már ide a hardveres architektúrát, amikor lényegesen magasabb szinten futnak a programjaink... leginkább egy virtualizált hardveren futó absztrakt driver rendszeren át érik el a perifériákat, miközben egy újabb virtuális gépen futnak, itt-ott natívra fordított részletekkel... :)

...értem én, hogy van egy fehér cérnakesztyűs sznob elméleti hozzáállásotok, de azért az ember általában tökig olajos lesz, ha úgy dolgozik, hogy közben azért halad is.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Ahja, de kesztyűs kézzel csak K+F munkát lehet végezni (vagy hobbi programozni), dolgozni és haladni nem... :)

...az ügyfél pedig nem a szakmai maszturbációdat fogja és/vagy akarja megfizetni, hanem a megtermelt értéket, mindig lesz kompromisszum az elvek és a gyakorlat között.

Mutatnál példát egy tetszőleges éles üzemben lévő termékedről, amelyikben minden itt leírt elvet betartottál?

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Valaki árulja már el, hogy mi az a mágikus különbség egy unit teszt és egy integrációs teszt között gyakorlatban.

Tehát, nem azon leakadva, hogy IO-t használ-e vagy sem, hanem (keretét tekintve) ugyanolyan teszt lesz-e belőle, mint az unit teszt, vagy valami mágikus, eddig előlem eltitkolt keretrendszer fogja-e futtatni és csak szimplán oda lesz íva, hogy Foo cucc integrációs tesztje...?

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Szerintem az a mágikus különbség, hogy mást tesztel. A unit teszt azt teszteli, hogy a kódod üzleti szempontból helyes-e, valóban azt csinálja, amit kell, helyes bemenetre helyes kimenetet adnak a kód részei (metódusok, függvények), helytelenre pedig jó hibajelzéseket. Aka szegény ember verifikációja. Az, hogy az üzleti logika helyesen van-e implementálva, nem érdekli, hogy mi az adatod forrása. Lehet az memória, lehet az filerendszer, hálózat stb. A kódnak ettől függetlenül kell helyesen működnie.
Egy példa: az n-edik Fibonacci-számot akkor is helyesen kell tudni kiszámolni, ha az n értéke konzolról, hálózatról, vagy file-ból jön. Lényegtelen, hogy a paraméter honnan jön, a logikának kell jónak lennie.

Az integrációs teszt pedig azt teszteli, hogy a helyesen működő programod jól ágyazódik-e be abba a környezetbe, ahol futni fog: helyesen kezeli az I/O-t más programokkal (az OS is egy másik program), rendszerekkel. Az egy teljesen másik felelősségi kör tesztelése, mint az üzleti logikáé. Teszteli, hogy a program akkor is az elvártak szerint működik, ha nincs meg a megfelelő futtatókörnyezet: nincs meg a bemeneti file, nem lehet írni a kimenetre, timeoutol az egyik hálózati szolgáltatás stb. Ez nem tisztán üzleti logikai dolog, erre nem való unit test.
A példánkra visszatekintve: az integrációs teszt ellenőrzi azt, hogy az n értéke jól kerül be az üzleti logikába, valamint a helyes kimeneti eszközön és a helyes formátumban szerepel a válasz. Ez viszont nem üzleti logika, hanem integráció.

Persze meg lehet kérdezni, hogy na de a gyakorlatban ezt mit jelent? Más keretrendszert? Más eszközöket?
Nem feltétlenül. Lehet xUnit keretekkel is futtatni olyan teszteket, amik *integrációs funkcionalitást* tesztelnek. A lényeg itt azon van, hogy a rendszered mely funkcionalitását teszteled. Magát a logikát (unit test) vagy a környezetbe való beágyazást (integration test). Az eszközkészlete lehet mind a kettőnek ugyanaz, ez az eszközkészlet sokoldalúságát mutatja csak meg.
Ettől függetlenül jó dolog elkülöníteni a kettőt, mert: eleve jó dolog elkülöníteni a más rendszerekkel, külvilággal való interfészt a belső működéstől. Más szabályok vonatkoznak a külső rendszerekkel való interfészelésre és más a belső logikára.
Épp ezért, ha el vannak különítve az integrációs kódok, meg a belső logikai kódok, akkor a tesztek is legyenek elkülönítve: a belső logikát tesztelő kód ne végezzen olyan műveletet, ami azt tesztelné, ami nem a feladata a belső logikának.
Azért ne, mert akkor kaphatsz másodfajú hibát, vagy éppen a "két hiba kioltja egymást" side effect miatt kaphatsz elsőfajú hibát. Pedig egyiket sem szeretnél, mert nem ezt teszteled.

Ugyanígy, amikor integrációt végzel, nem érdekel, hogy a belső logika helyes-e már, de érdekel, hogy jók-e a konfigurációk, a külső rendszerekkel való kommunikációs rétegek jól működnek-e. Ezeknek a teszteléséhez meg pont nem szükséges belső logika - előre kiszámított adatokkal lehet dolgozni szépen.

És ez nem elmélet, nincs mögötte matematika, meg bizonyítás: ezek csak elvek arra vonatkozóan, hogy amikor tesztelsz, pontosan tudd, mit tesztelsz, mi az, ami hibát okozhat, és ki felelős érte. Integrációs tesztben tudhatod, hogy vagy a te interfészed a világ felé hibás, vagy az ellenoldali fél hibás. A belső logika hibája itt senkit nem érdekel. A belső logika tesztjénél meg nem érdekel, hogy éppen áll az internet vagy a fileserver (aminek élesben mennie kell).

Ez szerintem nem igazán érv. Ha mondjuk egy dekóder algoritmust tesztelünk (mondjuk png dekódolás) akkor mennyi pluszt jelent a file io, főleg ha mondjuk SSD
van a gép alatt? Kb. semmit. Úgyis pár tucat bináris file-ra lesz megcsinálva a unit teszt, tehát ez igazából se nem oszt, se nem szoroz.

Akkor vedd úgy, hogy egy jó programozó képes különválasztani az IO-t minden mástól, mert felfogja, hogy esetleg párhuzamosan is lehet így tesztelni, és továbbra is két-három nagyságrenddel gyorsabb Lx cacheből kiszedni, mint a hiperszuper ssd-ből. Továbbá azt is felfogja, hogy IO != diszk, hanem lehet hálózat is, vagy terminálkiírás, atyaég: beolvasás, ami esetén meg is állna a tesztje. Ehelyett absztrahál.

Igen, jelent ott is gondot, mert az IO megbízhatatlan. Ha az a fájl valamiért épp elérhetetlen, vagy nagyon nagy a latency más IO műveletek miatt, akkor pl. az automatikus build rendszered is hibára futhat.
Ha kevés dolgot tesztelsz egyszerre, ráadásul csak szekvenciálisan tesztelsz, a fájl része a projektnek akkor nagyon kicsi az esélye , hogy problémával találkozol.
Ellenben ha nagyon sok teszt eset fut (pl. property based testing-et használsz), párhuzamosan futnak a tesztek, a fájl külső részen van, akkor már sokkal nagyobb esélye van a problémákra.

"Igen, jelent ott is gondot, mert az IO megbízhatatlan."

Mi garantálja, hogy a programod alatt is mindig ott lesz minden? Pl. Java esetén eltűnik egy .class fájl félúton, mert nem .jar-ban volt, PHP esetén szintén nem töltődik be minden indításkor, csak első használatkor, stb.

Plusz, hogyan tesztelsz olyan dolgokat, amikor kifejezetten azt akarod tesztelni, hogy egy adatbázisban a megfelelő módosulások hajtódnak végre?

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Ez ugye most ilyen elméleti síkú víta? Mi a csodáért nem lenne elérhetetlen az SVN-ben lévő teszt file, amit aztán a build rendszer rak össze. Az mindig ott van,
nem fogja a kismanó kitörölni. Ha pedig igen, akkor a unit teszt dob egy hibát, és meg lehet nézni, hogy ki volt az a kismanó, akinek egy baszott nagyot kell vágni
a kezére. Megjegyzem, ilyen a pályafutásomban még nem fordult elő.

Igen, elméleti síkú vita, a hogyan lenne célszerű nézőpontból.
Ezt írtam én is, ha a fájl része a projektnek, akkor az elérhetetlenségére kicsi az esély, ha nem része, akkor bizony nagyobb.

Nem csak az elérhetetlenségéről van szó, hanem a beolvasás idejéről is, ami az IO terheltségtől függően elég nagy is lehet, főleg, ha több száz, ezer esetre akarod tesztelni az adott részeket, így ennél a megoldásnál több száz, ezer fájlt kell felolvasni. Nem is beszélve arról, ha nagy méretű adatokkal is tesztelni akarod, pl. 1GB-os méretre is menjen.

"Ezt írtam én is, ha a fájl része a projektnek, akkor az elérhetetlenségére kicsi az esély, ha nem része, akkor bizony nagyobb."

Az unit teszthez tartozó adatfájl, amit valami megkap paraméterül, miért ne lenne a (teszt)projekt része, ami a build során a megfelelő helyre kell, hogy kerüljön, különbben már a build elhasal?

Egyáltalán, a dinamikusan betöltött kóddal (mert mondjuk az éppen unit tesztelt kód használ ilyet, vagy akár egyenesen pont azt akarod tesztelni) mi a helyzet? Az is IO.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

És ha az adat picit komplexebb, minthogy simán paraméterekben átadd? Vagy mittom, arról szól a teszt, hogy egy adott adatot jól parseol-e be a cucc? És ha mondjuk az bináris, beleraksz egy nagy byte[] { ... } -t a kódba?

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Miért kellene, hogy szorosan kapcsolódjanak? Átlag havi egy-két integrációs munkám simán szokott lenni, ahol a partnertől kapott adatot valamilyen úton-módon be kell dolgozni a mi rendszerünkbe, mindezt hosszú távon automatizáltan. (A formátum és a transzport módja teljesen egyedi.)

Hogyan írsz akkor unit tesztet arra, amikor az a feladat, hogy egy weboldalra be kell jelentkezni (leszimulálva a böngészőnek kb. az összes lépését), és ott letölteni egy XML fájlt majd azt átkonvertálni a saját ERP-d formátumára. (Igen, van, hogy ennyire szarik bele a partner és egyszerűbb módot nem ad rá.) Nincs semmiféle "enkóder" vagy generátor, csak az adatot kapjuk. És gondolom eléggé adja magát, hogy miért nem akarok generátort írni.

De ugyanez ezer csillió más esetre elképzelhető, amikor neked megvan az adat, meg hogy mi az és csak be kell parseolni.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

"Miért kellene, hogy szorosan kapcsolódjanak?"
Azért, mert valaminek elő kell állítani azt, amit be kell parsol-ni.

"És gondolom eléggé adja magát, hogy miért nem akarok generátort írni."
Nem igazán adja magát. Általában egy generátort sokkal egyszerűbb és gyorsabb, mint parse-olót írni. A való életben sajnos nem feltétlen az elmélet teljesül, nem írunk mindenhez tesztet, sőt talán semmihez sem írunk, a kódunk is olyan, amihez nehéz írni. Én most legalábbis az elméletről beszélek, nem a gyakorlatról, a "hogyan kellene"-ről és nem a "hogyan van"-ról.

"Hogyan írsz akkor unit tesztet arra ..."
Sehogy, erre integrációs tesztet írok, illetve egy-egy lépésére (unit) írok unit tesztet.

Tehát ha jól értem, amiről vitatkoztok: A azt mondja hogy az IO az rossz, kerüljük el. B azt mondja, hogy de hát a programok 99%-a IO-t tartalmaz (képernyőre kiirás, egérre, gombnyomásra, file-ra, socket adatra, stb. várás). Erre A azt mondja, hogy ez igaz, viszont fontos lenne, hogy a programban szeparáljuk el az IO-t tartalmazó, és az IO-t nem tartalmazó részeket, mert az IO-t nem tartalmazó részeket így akkor lehet normálisan tesztelni?

Értem, köszi. Még egy kérdés: a probléma azzal van, hogy a loggolás blokkol, vagy azzal, hogy egyáltalán loggolunk ezekből a kódokból? Ha viszont blokkol, akkor azt
nem úgy kellene megoldani, hogy a logger az egy interface, aztán az azt megvalósító könyvtár majd megoldja az aszinkron kiírást?

Az IO-s részek tesztélésénél is van kétféle módszer:
1. Integrációs teszt, amikor valódi IO-n küldünk, fogadunk dolgokat, és az egyes rendszerek integrált viselkedését teszteljük.
2. Funkcionális teszt, amikor nem valódi IO-n, hanem pl. egy Mock IO-n keresztül végzünk küldést, fogadást és közben a Mock IO-n szimuláljuk a normális választ, a késleltetett választ, vagy, hogy egyáltalán nem válaszol, vagy csak némely esetben nem válaszol. A valódi IO-n keresztül ezeket az eseteket nagyon nehéz tesztelni.

Szerk.: Unit teszten csak a normális válasz-os részt érdemes tesztelni, mert a többi mind "lassan" működik.

A dátum pure. A rendszeridő már nem. Természetesen a random, és IO sem.

Nem nettó baromság, csak sokaknak túl nehéz megérteni. Konyhanyelven arról van szó, hogy - ahogy te is írtad - a gyakorlati haszna nem sok egy kizárólag pure nyelvnek, mivel a felhasználója soha nem fog tudni értesülni a végrehajtás eredményéről. A kizárólag pure nyelvet tehát tekintheted teoretikusnak, kutatási területnek, csak épp nettó baromságnak nem.

Nyilván valahogy be kell hozni a való világba ezeket az eredményeket, erre tökéletes lehetőséget biztosít egy ún. computational context, amit a Haskell esetén épp a kategóriaelméletből kölcsönvett monádnak neveznek; ki nem találnánk melyik monád kell az IO-műveletekhez: az IO Monad.

Tévedsz azonban, mert a kizárólag pure szemlélet továbbra sem képtelenség a gyakorlati problémáknál. Egy jól szervezett programkódban elkülönítheted a pure, mellékhatásoktól mentes kódot - ami ugyanarra a bementere mindig ugyanazt a kimenetet fogja produkálni, és az eredmény _csak_ a bemenetektől függ - az IO kódtól. Gondolom a tesztelés fontosságát egy komplex szoftverben nem kell kiemelnem. Képzeld csak el, ha van a pure kódjaidra teszt x%-os coverage-dzsel, akkor az tényleg x%, és nem szólhat közben ja egy random(), ja egy readLine(), ja egy egyéb. (Zárójelben megjegyezném, hogy a (code line) coverage egy szoftver tesztelésekor kimondottan félrevezető, mert nem az állapottér lehetséges összetételét vizsgálja, hanem a fájl sorait. Improvementért lásd QuickCheck és tsai).

Szerencsém van a haskell-atyaúristen Simon Meier mellett dolgozni, tőle tanultam egy jó tippet szoftverkarbantarthatóságról. A függvényeid legkisebb része legyen impure, a többi pure, és minél több pedig total (azaz az értelmezési tartomány minden eleméhez rendel kimenetet; ez utóbbit egyszerű - a compiler általában kényszerít rá - megvalósítani).

Remélem sikerült árnyalnom a pure szemléletről alkotott véleményed.

Amúgy csak kötözködöm, ahogy az imént is írtam feketén meg fehéren. Nem kell kiemelned a tesztelés fontosságát, és ötletesnek tartom, hogy már a funkció definiciójából kitalálható, hogy lesz-e side effect vagy sem. Aranyos. De szerintem egy program, ami fix bemenettel dolgozik, megold egy problémát, és a "felhasználója soha nem fog tudni értesülni a végrehajtás eredményéről" nettó hülyeség :) arra jó, hogy a szerzője megveregesse a saját vállát, mások meg elismerően hümmögjenek rá, mikor a kódot nézik, mert kimenet ugye nincs. Még azt sem tudja meg, hogy jó lett-e az eredmény :D:D = nettó baromság. Tudom a világ nem fekete meg fehér, és innentő pure sem.

"Szerencsém van" az király ;)

"Remélem sikerült árnyalnom a pure szemléletről alkotott véleményed." mindeféleképpen jó és hasznos dolog másokkal beszélgetni, és remélem nekem sikerült átadnom, mit gondolok a !tisztán! pure, eye candy programozási elméletekről. Én is azt vallom, hogy immutable és pure as possible (gyönyörű mondat), és ha még non-blocking is, akkor van öröm és boldogság.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

> egy program, ami fix bemenettel dolgozik, megold egy problémát, és a "felhasználója soha nem fog tudni értesülni a végrehajtás eredményéről" nettó hülyeség
Azt a két fogalmat kevered, hogy "a felhasználó értesül" és "van visszatérési értéke". Ez a "program": public static int add(int a, int b) { return a+b; } pure, van visszatérési értéke, de jelen formájában nem értesül a felhasználó arról. Tedd egy printLn-be a kimenetet, és máris praktikus.

Innentől kezdve - gondolom - te is hasznosnak tekinted ezt a - és akkor pontosítsunk - szubrutint, még régiesebben: szubprogramot. Tudsz a helyességéről, a komplexitásáról érvelni, a compiler által generált kód optimalizálásának is utánajársz, stb. Összefoglalva: a compsci pontosan ezzel foglalkozik, egy modellen vizsgálódik, kutat, és az eredmények alapján fejleszti a jövőben a te praktikus compileredet. Nettó hülyeség? Nem hinném.

Nincs itt semmi eyecandy. Mivel - tudtommal - minden tisztán pure nyelven van arra framework (pl. az említett IO Monad), hogy a számítás eredményével vissza lehessen térni a való világba _egy_ interfész segítségével.

Nem hinném, hogy keverem. A-t elindítja a felhasználó, ami hív B-be, ami C-be, és mindnek van viszatérési értéke. Mire megy vele a felhasználó, ha nem értesül róla? Mi volt az értelme? "Tedd egy printLn-be a kimenetet, és máris praktikus" és máris nem pure a dolog. Vannak neki pure része, amik remekül tesztelhetők. "A pure funkcionális nyelvek készítői és kedvelői szerint viszont nincs szükség rájuk", szerintem meg van, én csak ennyit próbálok mondani.

"minden tisztán pure nyelven van arra framework" ez egy ellentmondás, ha van rá mód, akkor az nem tisztán pure. Vannak pure szemléletű nyelvek, amik igyekeznek minimalizálni meg elkülöníteni a változékony világot amennyire csak lehetséges.

lazán kapcsolódik, most én vagyok a matematikus

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

Attol, hogy letezik az IO monad, meg azt mondanam, hogy a Haskell pure functional (ahogy a vilag ~100% is igy teszi). Ha mindenaron ra akarod valamire eroltetni a "tisztan" pure-t, akkor termeszetesen a felhasznalo ertesitese miatti ellentmondasba fogsz keveredni. Ez is tiszta sor.

Viszont akkor kerdeznem, milyen (a te fogalmaid szerinti) "tisztan" pure nyelveket ismersz?

> mert fogalmad nincs arról, hogy ez egy sima értékadás vagy kijöhet belőle egy validációs hiba vagy bármiféle egyéb hiba

Eh, igen, ahhoz, hogy ez működjön, szükséges feltétel, hogy rendesen legyen dokumentálva a kód. Ha ez adott, akkor jó tud lenni, egyébként tényleg egyenes út a gányoláshoz.

...egy tudatos döntés volt a Java nyelvben, hogy megkülönböztessék az értékadást és az érték kiolvasását a függvényhívástól... szóval a properties támogatásnak nem csak előnyei vannak, de ezt szeretik elfelejteni.

Ha generálod a Java Bean-t, akkor úgyis ott lesz a megfelelő "setter/getter/equals/hashCode/toString", ha kézzel létrehozod, akkor plusz egy egérkattintás a "generate getter/setter/equals/hashCode/toString". A lényeg egyébként se ezekben az osztályokban szokott lenni, néhány másodperc plusz munka és/vagy ott Lombok.

A hívásnál pedig egy

v.Valami = 2;
v.setValami(2);

nem olyan nagyon nagy különbség, hogy ezen múljon bármi is, viszont egyértelmű, hogy az ott egy függvényhívás és nem szimpla értékadás.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

Nyilvan a public API-dra epito 3rd party kodokat is refactoralni tudod konnyen es gyorsan. Foleg, ha nem te fejleszted. Nem minden kodot az ir, aki felhasznalja.
A getter/setter bevezetese public field helyett visszafele nem kompatibilis API valtoztas, a verziozasnal igy is kell banni vele.

Nyilvan nem csak ezen mulik. De latom, egy-két apróság elkerülte a figyelmed:
- C++: Ket fájlt kell karban tartani.
- PHP: Ha garantálni akarod, hogy csak szam legyen, plusz kódokat kell irni.
- Nem mindegy, hogy hol, mit milyen tömören tudsz megfogalmazni.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Ha olyan szintu dolgokon mulna a forraskodok karbantarthatosagat, amiket itt felsoroltal, akkor ez egy boldogabb vilag lenne.

Edit: belatom, hogy ettol nem lett vilagosabb a felvetesem. Egy trivialis peldaval elve: mar egy kozepesen bonyolult, OOP nyelven irt webalkalmazasnal is mindennapos problemat jelent az MVC/MVVM/MVP/stb architektura megsertese (ki nem latott meg controllerben implementalt uzleti logikat?), SOLID alapelvek megsertese, OOP alapelvek megsertese (eleve, a getterek/setterek letezese onmagaban ide tartozik) vagy a ido elotti optimalizalasbol fakado karok.

"Elég fiatal lehetsz, ha tényleg azt hiszed, hogy a kód karbantarthatósága a választott nyelven múlik."

Az, hogy egy refaktorálásnál nem futásidőben jönnek elő a nyavalyák, az elég sokat segít a karbantarthatóság tekintetében. Nem a nyelven múlik, hanem a platformon, a fejlesztőkön és az ökoszisztémán.

--
http://wiki.javaforum.hu/display/~auth.gabor/Home

ja, csak az ökoszisztéma meg részben a nyelvtől függ :)
dinamikusan típusos nyelven írt kódból sokkal kevesebb információt tud kihámozni az IDE statikus kódelemzéssel, így a refactoring eszközök, kódminőség-ellenőrzők (->ökoszisztéma) se lesznek annyira erősek.
Szerintem a kódminőség függ a nyelvtől, a fejlesztőktől, a platformtól és az ökoszisztémtól is, mindegyiknek van relevanciája.

Rossz a kiírás, mindenki tudja, hogy a lehulló hópihéket a weboldalon Javaban kell programozni! :))

--
Debian - The "What?!" starts not!
http://nyizsa.blogspot.com

A feladathoz kell a szerszámot megválasztani! Egy fog betöméséhez nem való a fejsze, de a körömreszelővel sem lehet olajat bányászni.
Viszont ezeket azért lehet kreatívan használni, mert láttam én már viszonylag finoman megmunkált faszoborportrét amit teljesen és kizárólag szekercével faragtak.
Szóval egy jó programozó bármilyen nyelven tud Fortan programot írni! :D
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba!; DropBox

Egyik opciót sem jelöltem.
Erőteljesen favorizálom a statikusan típusosságot, de ezzel együtt a JavaScriptet pl. (sokkal) jobb nyelvnek tartom, mint a Javat. Vannak más szempontok is.

:)
Számomra a funkcionális paradigma a legkézenfekvőbb, ezért fontos szempont, hogy mennyire lehet hatékonyan funkcionális programozást mívelni adott nyelven. Ez Javaban elég nyögvenyelősen lehetséges, míg pl. c++ -ban, javascriptben sokkal inkább kivitelezhető. Persze más bajom is van a Javaval, de ez az elsődleges.
Kedvenc nyelvem amúgy a Haskell, ami statikusan típusos.

Van pár nyavajája a típusok meg kivételek körül, de teljesen jól használható cucc. Lehet olvasni egy csomó cikket, hogy teljesítmény problémák lehetnek vele, de nagy részük az ide-oda boxolás miatt van. Nem a szent grál, de hát mi az a programozásban (meg úgy általában a világban).

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

Az esetek többségében azért ezek a megoldások nem funkciók, hanem closure-k. És bár nem vagyok Haskelles, de el tudom képzelni mi a véleménye egy tisztán pure programozási nyelv hívőnek :D a klózsörökről: semmi jó.

-
Konténerezett Hadoop és Cassandra cluster konfigurálása - második rész

magam reszerol en folyamatosan hasznalok Java, Python, PHP nyelveket (pl JavaScript-et messzirol kerulom, mert megtehetem.... de ismerem).

Az en velemenyem, tapasztalatom, es persze ezzel lehet nem egyet erteni.
Nagyon primitiv fejlesztesekhez (vagy ahol a JVM tul nagy, remelhetoleg a JigSaw projekt megoldja ezt) en PHP-t (web-es) vagy Python-t (system service) valasztok. Minden mas esetben (kiveve az egeszen specialisaktol) a Java-t preferalom, meghozza azert mert tipusos nyelv. Termeszetesen teljes mertekben egyet ertek azzal a hozzaszolassal, hogy a programozasi nyelv csak egy eszkoz.... a feladathoz kell valasztani a legmegfelelobbet es nem raeroltetni a feladatra azt amit szoktunk hasznalni.
A tipusos nyelvek legnagyobb elonye az
- staikus kod elemzes
- IDE funkcio tamogatas
Nagyon jol latszik (pl az Eclipse-ben) a kulonbseg a Java es Script (PHP v Python) fejlesztes tamogatasa kozott. Mig a Javahoz fantasztikus kod manipulalo eszkozok (pl refactor es source menu) es kivallo statikus kodelemzes (a hulye hibak es teljesitmenyvesztes elkerulesere) addig a script nyelvek eseten ennek csak egy nagyon kicsi resze erheto el, mert a mukodesbol/tipus nelkulisegbol adodoan nem lehet jobb tamogatast kihozni belole (persze valoszinuleg mindket esetben van meg hova fejlodni).
Termeszetesen a teszt/automatizalt teszt eszkozoket mindket esetben hasznalni kell (bar valahogy a megrendelok ezt nem szeretik finanszirozni, a tulajdonosok megerteni.... tisztelet a kivetelnek, azert a komolyabb cegek ezt felfogtak), lehet jo minosegu kodot irni. De magam reszerol az a tapasztalatom, hogy a tipusos nyelvekkel egyszerubb hibamentes kodot irni.

peace!

Egyéb: nem rosszabb, nem jobb, hanem más. Kicsit másképp kell használni. Más célra jó a kettő.

De mindkettővel meg lehet oldani egyszerű és bonyolult feladatokat is.

Ha egy feladatra nyelvet kéne választani, nem a típusosság lenne a legfontosabb szempont.