full stack webfejlesztő - mihez kell értenie?
Csak úgy elgondolkodtam... ha valakinek olyan hülye ötlete jön, hogy egyszemélyes webfejlesztő akar lenni, annak milyen ismeretekkel kell rendelkeznie?
Szerver oldali programozás, adatbázisok, HTML, javascript, mindezek mellé keretrendszerek ismerete...
Jól látom, hogy ez nem kezdőknek való? :)
ui: nem, nem akarok belevágni ilyesmibe, csak játszadozás közben kezd kuszává válni a dolog, mert felszínes ismeretekkel elég macerásnak tűnik.
■ Szerver oldali programozás, adatbázisok, HTML, javascript, mindezek mellé keretrendszerek ismerete...
Jól látom, hogy ez nem kezdőknek való? :)
ui: nem, nem akarok belevágni ilyesmibe, csak játszadozás közben kezd kuszává válni a dolog, mert felszínes ismeretekkel elég macerásnak tűnik.
Off: Mindenhez IS.
Wow... ez szinte szóról-szóra
Igazából nem annyira nehéz
Nézem közben tovább a React-et. Ez a Flux és Redux nem rossz, gondolkodom már ebben a témában egy ideje, de nem tetszik, hogy a Flux teljesen kigyomlálta az aszinkron ciklusokat és hasonlókat. Egyelőre még nem érett meg a gondolat, hogy hogyan lehetne ezt jobban csinálni, úgyhogy valszeg használnám ezeket is a React-el együtt.
Valahogy így. :-) Én már egy
BE + FE
Én azt gondolom, hogy manapság sokkal többen kategorizálják magukat így, mint kellene. Egyetértek azzal, hogy ha valaki full stack, akkor egyszemélyes webfejlesztő tud lenni, vagyis egymaga végigvisz egy projektet.
És itt jön be a képbe a "csúnyaság": én még nem találkoztam olyan, magát full stack-ként kategorizáló fejlesztővel, akire nyugodt szívvel rá mernék bízni (egyedül) egy komolyabb projektet. Inkább az a tapasztalatom, hogy manapság az a full stack, aki hajlandó frontendhez és backendhez is nyúlni. De nem jelenti azt, hogy vérprofi akár csak az egyikben... :/
Egyszemélyes webfejlesztő meg van sok Vér Pistike, aki összekattintgat "bármit" wordpress-ben vagy más, hasonlóan profi "keretrendszerrel".
A CSS-t én mindig a html
Viszont kimaradt, hogy nem árt érteni az üzemeltetési dolgok egy részéhez is. :D
Hát én egyre inkább backend
Egyszerű
Ami megnehezíti az életet, az a fentiek újabb verzióiban behozott újdonságok, amelyek segítségével ugyanazt a feladatot többféleképp tudod elvégezni. Természetesen ezeket nyugodtan lehet használni, de számíts arra, hogy a featúrák számának a növelésével a hibázási lehetőségek négyzetesen nőnek a kombinációk miatt.
Ha ezt nem hiszed, kérdezd meg nyugodtan Pepitát, mekkora trágyadombot gyártottak a /censored/-nél, például hányfajta kliensoldali megjelenési technikával nehezítették meg a saját maguk életét. Gondolj bele, mennyi erőforrás elmegy a karbantartásra és az egységesítésre, valamint a különböző dolgok megtanulására.
A weboldalak és -szolgáltatások 99%-át a fentiekben leírt minimális követelményrendszer kielégíti, látszódjék az bármilyen összetettnek vagy csillogónak.
Elhinni elhiszem, csak ha nem
O.K., én egyébként is nehezen tanulok, de huszonegynehány éves pályám alatt talán négy embert ismertem, akiből kinézem, hogy képes lenne ilyesmire.
ha nem elégszem meg azzal,
Egyemberes projektről
És akkor még nem volt szó róla, hogy amilyen rendszereket láttam, ott a leendő felhasználók szakmájához sem ártott, ha ért valamit a fejlesztő, mert ennek hiányában elég komoly félreértések adódhatnak...
Persze, neki lehet menni úgy is, ahogy írtad, de... hát elég sok példa van rá, még céges, sok fejlesztős megvalósításban is. ;)
Mérce
Ha egyedül szeretnél pénzt keresni, akkor tényleg a Wordpress az egyik legjobb megoldás a problémára, szerintem még dizájnt is találhatsz ingyen.
Egyedül nagyon korlátozott minden erőforrás, így nagy projektet nem érdemes elvállalni, inkább csak kicsiket és hasonlókat, amit futószalagon tudsz gyártani. Így nem kell csillagrombolót tervezni, bonyolult adatbázisokat tervezni stb.
Direkt írtam, hogy ez rég nem
Csak csodálom azokat, akik minderre egymaguk is képesek, magas színvonalon.
Egyszerű
Ez a szakma nulla mondjuk egy orvoséhoz képest, ráadásul felelőssége sincs a művelőinek.
Akkor miért nem gyógyítasz? :-D
Lehet, hogy van sok felelőtlen művelője ennek a szakmának (Vér Pistikék), de ez távolról sem jelenti azt, hogy nincs felelőssége egy fejlesztőnek.
Ne vedd ennyire magadra (a
Más lapra tartozik, hogy manapság több IT-st ismerek, akiben meg tudok bízni, mint orvost, pedig orvosból (orvosként dolgozóból) sajnos már többet ismerek :(
Felelősség
Frontend: van körülbelül három böngészőmotor, amiket ismerned kell.
Orvoslás: minden ember más, ráadásul egy csomó szervünk vagy a lelkünk működését nem ismerjük pontosan, sem azt, hogy ezek hogyan hatnak egymásra. De ha valami elromlik, azonnal meg kell gyógyítani, és ha egy orvos hibázik, akár hosszú évekre is lecsukhatják, eltilthatják a szakmájától.
Ezzel szemben a fejlesztőt legfeljebb kirúgják, de pár napon belül új helyen dolgozhat minden probléma nélkül.
Te fizettél már az általad okozott hibákért?
a fejlesztőt legfeljebb kirúgják, de pár napon belül új helyen d
Érv
Az egészen más dolog, hogy milyen hozzáállással dolgozol.
Persze, máris :)
Egyébként a Mtk is előír alapvető felelősséget a munkádért (munkavállalóként), büntetőjogi felelősséged pedig külön szerződésbeli említés nélkül is van.
Olyat soha ne adj a számba, amit nem mondtam!
Egyébként a régióban legtöbb cég által használt ügyfélkezelő rendszer valószínűleg nem lenne az élvonalban sem, ha "trágyadomb" lenne, ehhez képest Magyar Brand díjat is kapott...
Gábor, nyomatékosan megkérlek, hogy ne vetíts rám / rólam olyan képet, amit nem mondtam, nem írtam, és legfőképpen egész másként gondolok.
Másrészt a webfejlesztés nem éppen "primitív munka", viszont ha valaki például PHP - ból 2018 - ban a 4.0 szintjén áll, akkor számára még primitívnek mondható backend feladatot sem ad önálló elvégzésre egy értelmes vezető fejlesztő vagy manager...
Tévedsz
Lehet itt mindenféle díjakat osztogatni, de az tulajdonképpen mit jelent? (Webes) szakmai szempontból díjazták? Az általad küldött lejárt tanúsítvánnyal rendelkező oldalon egy tárhelyszolgáltató marketingszövege jelenik meg. Mennyire egészséges az a szoftver, ahol egy felugró ablak megnyílásának az ideje másodpercekben mérhető?
Csak az utolsó sorra: pl. egy
Plusz
Igy is fel lehet fogni, meg
Felsoroltak
Nem tudom, pepita mit
Korrekt
Pl. nem járt le a
Félreértettem
kérdezd meg nyugodtan Pepitát
Viszont mint privátban is jeleztem: az, hogy mikor melyik cégnél mennyi ideig dolgoztam, az személyes adat, amit kizárólag az én döntési kompetenciám, hogy kivel osztok meg, és akkor itt, nyilvánosan is kérem, hogy haladéktalanul töröld illetve gondoskodj a törléséről, ha te nem tudod.
Baromira elszomorító, hogy ilyen szinten nem foglalkozol vele, hogy mit csinálsz!
Nem mondom azt, hogy fel se fogod ismerni a kódot, de az biztos, hogy amit pluszként teszel hozzá, annak 90%+ - ra kapsz code review-n change requestet.
De ebbe inkább nem megyek bele, mert előjön a "miért borzasztó dolog objektumorientáltan fejleszteni" lemez, amit enyhén szólva unok.
Ezzel egyenesen azt állítod,
De egy ingyenes regisztráció után bárki megnézheti a frontend forrását, és eldöntheti, mennyire jó, amit lát.
Inf3rnót megkértem, hogy moderálja ki a cégnevet. Más kérdés, hogy te azért csak beletetted a fenti linkbe : ) Ha már a privát szféráról van szó.
Kutyulod a dolgokat...
vs
Én leírtam, hogy azzal a tudással nem tud valódi 7.2-es kódot írni (gy.k.: vagyis kihasználni az új feature-ök előnyeit), mert azt kérdezted mit nem tud elvégezni. Erre most megváltozik a kérdés, hogy mit nem lehet megtanulni. :-D
Gábor, a Manyika néni, akinek a 8 általános is úgy van meg, hogy 6 x első + 2 x második, Ő is lehet profi full stack fejlesztő, ha eleget tud tanulni. Állítottad, hogy 2018 - ban elég a php 4.x tudás, ezt vitattam. Attól, hogy közben megpróbálod módosítani az eredeti kérdést, még nem lesz igazad.
Gábor, a Manyika néni, akinek
Gábor nem írta, hogy PHP 4.x-es tudással 7.2-es csapathoz/projekthez lehetne csatlakozni minden tanulás nélkül. Pusztán azt, hogy a weboldalak nagy százalékát el lehet készíteni PHP 4.x alatt is. Ez kétségkívül igaz. Az, hogy kinek melyik kényelmes, hasznos, produktív, az lehet szubjektív, vagy legalábbis nehéz/macerás objektív mérést végezni.
Szerintem nem gond, hogy mindenre nem csak egy megoldás van, hanem vannak alternatívák (feltéve, hogy ezek nem redundánsak, hanem bizonyos esetekben az egyiket, máskor meg a másikat érdemes használni).
Az, hogy kinek melyik
Ez talán akkor probléma, ha egy kezdő tanácsot kér, és megpróbálja eladni neki az elveit, amiket ha követ az illető, akkor mindene lesz, csak piacképes tudása nem.
Piacképes
A piacképes tudást úgy
Világos
Ha mondjuk XY Bt-knek készítesz WordPress oldalakat (mivel egyedül nagyjából ennyi fér bele), és nem feltétlenül garantálható a szerverkörnyezet, akkor célszerű lehet defenzíven dolgozni. Én például nemrég vettem részt egy önkéntes projektben, ahol statikus oldalakat kellett készíteni.
Hát akkor elkanyarodtunk a
Miről szól az egész?
A CMS-ben mit csinál az ember? Adatokat visz fel, módosít, megtekint. Az adatok az esetek túlnyomó részében adatbázisban vannak, a lekérdezések mezőnként karakterláncokat adnak vissza egy strukturált tömbben. Ezen a tömbön elvégzünk bizonyos műveleteket, majd az előző bekezdésben említett adatstruktúrát állítjuk elő belőle.
Tehát végeredményképp tömb-, szám- és karakterláncműveletek történnek az esetek túlnyomó többségében. Ezt a PHP mindig fogja tudni.
Fogalmi zavar
Továbbra is kérdés, hogy mi az, amit PHP 4.0 tudással nem lehet elvégezni? Erre várnék választ.
Ezek után várom a kifejtésed, mik a PHP 7.x előnyei, újdonságai, ami miatt egy egyszemélyes vállalkozásnak csak ebben érdemes dolgoznia.
Ha ez megvolt, akkor pedig azt, hogy mennyi rátanulás szükséges a 4.0-hoz képest, hogy ezeket az új dolgokat behozd.
Tehát a kérdésem nem változott.
csak hisztizel, mint egy óvodás
PHP 4.0 tudással továbbra sem fogsz tudni érdemben csatlakozni egy PHP 7.x tulajdonságait kihasználó projekthez. Nyilván újra tudod (valahogy) írni 4.0 alatt, de továbbfejleszteni csak akkor tudod, ha megtanulod és megszokod a különbségeket - akkor viszont már nem 4.0 a tudásod. :)
PHP 7.x előnyei (a teljesség igénye nélkül):
7.0:
- Type declarations
- Return type declarations, ezekkel jól tudod biztosítani, hogy mindig azt kapd, amit vársz (még procedurálisan is)
- Új operátorok -> rövidebb kód
- Generator Return Expressions és még pár generator feature
- Egész osztás
7.1:
- Nullable types
- Void functions - végre azt is deklarálhatom, hogy nincs visszatérési érték
- Class constant visibility - attól még, hogy Te ördögtől valónak tartod, ez egy fontos OOP feature
- Multi catch exception handling
7.2:
- New object type
- Abstract method overriding
- Password hashing with Argon2 - nyilván ez is tök haszontalan, hisz ott van a jó öreg md5 is... :-D
- Exif support updated
- Enhancements to the ZIP extension
Ezen kívül nem szabad elfelejteni, hogy van pár dolog, ami nem kompatibilis visszafelé, régi kódot 7.x-re téve ilyeneket is igen át kell nézni. Természetesen ha 4.0 rutinnal odaülsz a 7.x kód elé, indirect variables gondod rögtön lesz.
Valószínűleg ha valóban érdekelne téged, hogy mire jó egy - egy programnyelvnek (és fejlesztőnek) a fejlődése, vagy egyáltalán: érdekelne a fejlődés, akkor nem tőlem vagy mástól várnád azt az információt, hogy "mitől jobb", "mitől több", hanem utánajárnál, olvasnál róla és csak specifikáltabb kérdést tennél fel. Tessék, fentebb egy egyáltalán nem teljes lista, mondjuk inkább ízelítő, amiknek én örülök, hogy fejlődött.
Igazán boldog akkor leszek, ha majd lehet futtatni a PHP-t (mondjuk 8.x?) "szigorúan típusos módban".
Remélem ezt nem gondoltad komolyan, hogy én mondjam meg, hiszen nincs két egyforma tanuláskészségű ember.
Nekem egyébként úgy tűnik, hogy te "állítottál" előbb dolgokat, aminek egy része nettó butaság, csak a te rögeszméd.
2018 - ban ne sugalljuk már egy esetleges kezdő olvasónak, hogy elég PHP 4 - et feltenni valahogy, és indulhat a "webfejlesztés". Egy juniornak annál jobb, minél újabb verzión kezd el egy nyelvvel foglalkozni, annál kisebb az esélye, hogy lemarad, mire megszokja használni.
Remélem ezzel végre zárhatjuk ezt a dolgot, mert tök haszontalannak érzem.
(Inf3rno popcorn nem kell több. :) )
Szövegértés
Mi az a feladat, amit php 4.0 tudással nem lehet elvégezni?
Hol írtam én, hogy 4.0 verziót kell használni? Ez hülyeség lenne, hisz már sehol sem támogatott. Tudást említettem, ami teljesen mást jelent.
Tehát át kell gondolni, hogy mit tudott a php 4.x:
- típusok
- változók,
- konstansok,
- kifejezések,
- operátorok,
- kontroll struktúrák (if, for és társaik),
- függvények,
- objektumorientált programozás,
- hibakezelés,
- standard library,
- kiterjesztések.
Az általad felsorolt 7.x dolgok mind a meglévők csiszolása. Új dolog a php 5.x-ben a kivételkezelés, a névterek és a generátorok, továbbá ide sorolhatjuk a függvényparaméterek típusának megadását (5.0 és nem 7.x).
Tehát a kérdésre adott válasz részét képezi, hogy lehet-e kivételek, névterek és generátorok nélkül dolgozni. Szükségesek-e ezek ahhoz, hogy valaki elvégezze a feladatát, vagy csak bizonyos funkcionalitás alternatíváját jelentik, választási lehetőséget nyújtanak, hogy mindenki ízlése szerint dolgozhasson?
Mik a PHP 7.x előnyei, újdonságai, ami miatt egy egyszemélyes vállalkozásnak csak ebben érdemes dolgoznia?
Ha shared hoston van, akkor nincs választása, azt a PHP verziót kell használni, amit kap. Fel lehetett volna hozni, hogy a használt külső keretrendszereknek, rutinkönyvtáraknak is van verziókövetelménye.
A mondandódat sokszor hegyezed ki a típusdeklarációkra. Érdemes lenne kifejteni, hogy mit nyer ezekkel az ember. Mivel a kiértékelés futásidőben történik, ezért annyi a különbség típusdeklarációk használatakor, hogy a függvényhívás elején kapsz hibaüzenetet, míg ha nem használod őket, abban az esetben pedig akkor, amikor a kapott paramétert felhasználnád (például karakterláncot vársz, de tömböt kapsz helyette). Amit el tudok képzelni, hogy vannak kódelemző programok, amik segítségével a típuseltérésből adódó hibák egy részét még fejlesztés közben elkapd, de a működésből adódik, hogy nem lehet mindet.
Érdemes azt is kifejteni, hogy mi szól a magasabb php verziók ellen, mert ilyen problémába is lehet futni. Vagy azt, hogy milyen esetekben érdemes a legújabb (al)verzióra frissíteni, és mikor irreleváns.
(...)
Remélem ezt nem gondoltad komolyan, hogy én mondjam meg, hiszen nincs két egyforma tanuláskészségű ember.
2018 - ban ne sugalljuk már egy esetleges kezdő olvasónak, hogy elég PHP 4
Ismételten kioktatsz, amire nincs szükségem, köszönöm.
Ne már
Tényleg menj el politikusnak, mert tényleg nagy érzéked van hozzá, hogy lyukat beszélj az emberek hasába.. :)
Hogy a te szótáradban mit jelent a "dolog" és a "csiszolás", bocsi, de nem érdekel. Tőlem egy új feature-t is nyugodtan hívhatsz mezei nyúlnak is, ez nem fog változtatni az értékén.
Nem tudom, mi értelme van a tudást verzióhoz kötni, mert tutira nem úgy működik az emberi agy, hogy számok alapján külön-külön területekre "tároljon". Inkább a tapasztalat az, amit lehet konkrét verzió(k)hoz kötni, és itt jobban kijönnek a különbségek is..
De ha tudásnak hívod, és verzióhoz kötöd, akkor is ugyanúgy nem, vagy kényelmetlenül, lassan tudod felhasználni más verzió alatt.
De mind1, komolyan meguntam, nem fogok veled szélmalomharcosat játszani, hiába próbálsz sértegetni / bosszantani, legfeljebb egy másik fajta türelmem is elfogyasztod az ilyenekkel:
Nehéz
Miért az a helyes kérdés,
Az egy sokkal fontosabb kérdés, hogy milyen és hány céghez tudsz csatlakozni azzal a tudással. Illetve hogy ha 4.0 alapon készítesz egy projectet, akkor kit tudsz bevonni a fejlesztésbe, vagy kinek tudod továbbadni. Meg hogy mik azok a projectek, amik még támogatják a 4.0-t és tudsz rájuk épülni, ha kell valami. Mindkettő kb egy üreshalmaz. Az első (milyen céghez tudsz csatlakozni) talán nem olyan fontos, ha magányos farkasként dolgozol. Bár akinek ez nem szempont az kb bolond :) A másik viszont akkor is fontos, ha egyedül fejlesztesz. Senior ember ilyet nem csinál. Mekkora költséget okozunk azzal, ha PHP4 alapon írunk meg valamit, aztán kell valaki, aki átveszi, vagy beszáll? Borítékolható, hogy újra lesz írva az egész. Tehát még ha igaz is, hogy PHP4-ben mindent ugyanolyan jól meg lehet csinálni, ez akkor se egy vállalható alternatíva, amennyiben próbáljuk figyelembe venni az ügyfél pénztárcáját és mozgékonyságát (time to market).
Pl Java7-es projectre már igen nehéz fejlesztőt találni, pedig az egyrészt közel sem olyan régi, mint a PHP4, másrészt sokkal közelebb van a legfrissebb Java-hoz, mint a PHP4 az aktuális verzióhoz, és még sok lib által támogatott is.
+1 amugy hihetetlenul
amugy hihetetlenul vicces, hogy 2018-ban egy (elvileg) szakmai oldalon arrol megy a diskurzus, hogy tanuljon-e valaki PHP4-et, ha szeretne webfejlesztessel foglalkozni...
megkerestem a PHP4 hivatalos doksijat, ez all benne (vagyis inkabb helyette):
ertelmetlen arrol vitatkozni, hogy mi mindent lehet megcsinalni egy 2008 ota senki altal nem tamogatott nyelvben. nem csak hogy ertelmetlen, de egyenesen karos barkit arra buzditani, hogy hasznaljon PHP4-et.
Hát gondolom Gábor képviseli
Tudás
Nem mindenkinek célja, hogy cégekhez csatlakozzon, mert az mindenképp kötöttségekkel és bizonyos fokú rugalmatlansággal fog járni, ami nem biztos, hogy számára elfogadható.
De vegyük példaként mondjuk a típusosságot, ez hasznos lehet, ha csapatban dolgozik az ember, így van rá esély, hogy főleg nagyobb kódbázis esetén kontrolláltan derüljenek ki bizonyos hibák. De ha valaki egyedül dolgozik, és megvan hozzá a fegyelme, szükség van-e erre? Nem vagyok róla meggyőződve. Mi nem vagyunk sokan, nem használjuk ezt a lehetőséget, sőt, mind frontend, mind backend oldalon kihasználjuk a dinamikus típusok előnyeit. Mi tehát sok esetben vesztenénk, ha élnénk ezzel a lehetőséggel.
Ha a PHP 4 faék, akkor a PHP 7 jóval bonyolultabb. A featúrák számával azok kombinációja miatt a hibázás/félreértés/tévedés valószínűsége négyzetesen növekszik. Mi garantálja ezek után, hogy a 7-esben, teljes eszközkészlettel megírt program jobb lesz?
Mi garantálja ezek után, hogy
Gondolom ez a becsapós kérdés, mert már te is meg mások is leírták elég sokan, hogy ugyanaz megoldható mindkét verziónál.
Valószínűleg a fejlesztési idő alacsonyabb lesz PHP7-ben, mert az új feature-ök bizonyos dolgok automatizálását jelentik, amiket PHP4-ben újra és újra be kell gépelned. Nagyjából ennyi a különbség, meg az, hogy foltozzák a biztonsági réseket, készülnek hozzá kiterjesztések, keretrendszerek új technológiákhoz, szóval nem kell mindent magadnak megírni, ha esetleg valami új dolgot akarnál használni. Bár rólad tudom, hogy nem akarsz. :D
Teljesen mindegy, hogy kinek
Ami tény, hogy ha csak PHP4 tudásod van, akkor gyakorlatilag nullára csökkented az esélyét, hogy munkát találj. Legyen az egyszemélyes, vagy többszemélyes munka.
Ha PHP4+ libeket kell
A munkahelyemen összesen négy külső könyvtárat használunk, ebből kettő még PHP4-ben lett anno megírva (egy SQL daraboló és egy PDF nyomtató), és máig tökéletesen működnek. Ez hogyan lehetséges?
Minden bevezetett új featúra jár előnyökkel, de hátrányokkal is. Rengeteg példát lehetne felhozni, többek között rendszerprogramozásban miért ragaszkodnak a legtöbb helyen máig az ősi C-hez, miért lehet olvasni a neten olyan cikkeket, hogy C++ kódban nem használnak beépített "újdonságokat", például kivételkezelést. Magasabb szintű nyelveknél is akadnak problémák, ahol nem lehetséges a többszörös öröklés, a mixinekkel tudnak gondok lenni, a PHP típusajánlás sem tökéletes minden esetben, a példákat elég sokáig lehetne sorolni. És akkor ne is menjünk bele olyanokba, hogy a funkcionális programozás terjedésével az új PHP verziók featúráit nem is lehet kihasználni, mert nincs értelme.
Nincs olyan, hogy valami csak pozitív, és nincsenek árnyoldalai. A sütemények finomak, és nagyon könnyű belőlük energiához jutni, mert a szervezet az enegiát szállító cukrot közvetlenül tudja a sejtekhez szállítani belőle. Nemrég olvastam, hogy egy férfi csak süteményt adott a gyerekeinek, akiknek emiatt tönkrementek szépen a fogaik.
Érdekes lenne felmérni, hogy mennyi időt vesz igénybe ezeknek az új dolgoknak a megismerése, megtanulása, a tapasztalatgyűjtés, hogy mi mire jó és mire nem, mi mivel ütközik. Érdekes lenne felmérni, hogy mennyi idő a PHP4 eszköztárával (függvények, for ciklus, alap típusok: karakterlánc, egész szám, törtszám, tömb, null, és esetleg objektumok) elkészíteni egy projektet, és ugyanez mennyi idő az újabbakkal s azok újdonságaival. A nagyobb eszközkészlet mindenképp nagyobb szellemi erőfeszítést igényel, de a végeredmény ugyanaz lesz, karakterláncok bűvölése, hisz a böngészők azzal dolgoznak.
A featúrák számával azok
Szerintem ez is kinyilatkoztatás kategória. A legtöbb ilyen fejlesztés pont a hibázás elkerülésére készül, és azért automatizálnak, hogy ne kelljen ugyanazt kézzel bevinni, mert úgy könnyű hibázni. A feature csoportokat alkothatnak, és nem feltétlenül lehet tetszőlegesen kettőt összepárosítani. Szóval én nagyon meglepődnék, ha igaz lenne, amit írsz. Jó lenne, ha valamivel alátámasztanád. És itt valami referenciára, kutatásra, stb. gondolok, ahol ténylegesen ki is próbálták, és ez jött ki eredménynek.
Példa
class klassz {
function hehe(int $szam) {}
}
class orokolt extends klassz {
function hehe(float $szam) {}
}
function proba(klassz $klassz) {
}
proba(null);
?>
Ha egy metódus paraméterét egy bizonyos típussal deklarálod, akkor az örökölt osztály metódusában a paraméter típusa csak az vagy annak a leszármazottja lehet. PHP-ban a float nem az integerből származik, így egy szép figyelmeztetést fog generálni a futtatókörnyezet.
Csak nyalánkságnak tettem oda, hogy a
proba
függvényt nem lehetnull
paraméterrel hívni, ami szerintem elég nagy hiányosság, hisz az is egy információ, hogy egy paraméternek nincs értéke.Továbbá a paraméterek típusának ellenőrzése futásidőben történik, tehát az adott függvény vagy metódus meghívásánál a PHP megnézi, hogy az adott paraméter megfelel-e a kritériumnak, ha nem, akkor figyelmeztetést generál. Ha nem adod meg a paraméter típusát, és mondjuk egész számot vársz, de karakterláncot kapsz, akkor a program mindenképp hibát ad, amikor ezt a paramétert felhasználnád:
function osztas_tipus(int $szam) {
$eredmeny = 5 / $szam;
}
function osztas($szam) {
$eredmeny = 5 / $szam;
}
osztas_tipus("haha");
osztas("hehe");
?>
Futtatáskor az első egy fatal errort ad, a másik warningot, de mindenképp fog valamilyen hiba történni.
Ezek után a nagy kérdés, hogy mit nyertél az egész típusosdival: ellenőrizned ígyis-úgyis kell, akár használsz típusokat, akár nem, mert mindkét esetben hiba fog történni a programban. Emellett típusos paraméter esetében tudnod kell, hogy csak olyan típusú paramétert szabad átadnod,
null
-t nem (pedig adatbázisban lehet bármilyen mező értékenull
).Tehát az elvégzett munka ugyanannyi, de a program írásakor fejben kell tartanod az egyes típusokat, mi miből öröklődik, mit nem lehet átadni. Például ha egy publikus rutinkönyvtárat készítesz, akkor egyáltalán nem ildomos a paramétereknek típusokat adni, mert nagyon megkötöd vele a későbbi felhasználók kezét, akik nem feltétlenül ugyanazt a típust szeretnék használni, amit te elképzeltél.
A fenti egy konkrét példa volt, némi absztrakciót követel, ha általánosítani szeretnél belőle. Ha két hasonló dolog kerül be egy programnyelvben, akkor két featúránál kell fejben tartanod, hogy mit lehet vele csinálni és mit nem. Ezek kombinációja esetében pedig négyzetesen nő a hibázási lehetőségek száma.
Tehát az elvégzett munka
Vegyuk eszre, hogy a tipusok nelkuli vilagban is eszben kell tartani ugyanezeket dolgokat, raadasul mivel semmi sincs ledokumentalva, igy minden informacio implicit erheto csak el. Ez sokkal megterhelobb, es nehezebb fejben tartani. Tovabbra sincs rola semmilyen fogalmam, hogy honnan veszed ezt a negyzetesen no a hibak szama marhasagot.
Gondolom arra gondol, hogyha
Csak magamról tudom, hogy közepesen bonyolult főleg SQL-ekkel operáló kódot utólag tesztelve integrációs tesztekkel 25 hibát találtam, úgy, hogy én azért eléggé jól koncentrálok, és ritka, amikor hibázok. Ha valaki kicsit figyelmetlen, akkor dupla ennyit is simán összehoz, és általános használatnál annyira elő sem jöttek ezek, mert viszonylag ritka útvonalakon voltak. Egyébként ijesztő, hogy ez a TDD, BDD mennyire szitokszó egyeseknél. Annak idején prohardver programozós fórumba írtam egy kezdőnek, hogy érdemes lenne úgy elkezdenie programozni, hogy beletanul ilyenekbe, aztán egyből le lettem hurrogva, hogy ez mennyire felesleges, meg hogy csak csillagrombolók programozásához kell, kis projektekre kezdőknek szükségtelen, stb. Megvan ott is a színvonal...
Gondolom arra gondol, hogyha
for
t ésforeach
et, ami két feature ugye (ha már annak lett nevezve) és elég jelentős az átfedés a felhasználási területek között, akkor hogy tudom vele növelni a programomban a hibák számát. Úgy se tudom elképzelni, ha egymásba ágyazom őket. Legalábbis ekvivalens átalakítást feltételezve, tehát pl részhalmazon iterálást nem cserélek le teljes halmazon végigiterálásra. Ha nem ekvivalens átalakítást végzek, az pedig nem a feature kombináció hibája, hanem én vagyok hülye, és ugyanazt a hibát el tudom követnifor
használatával is.Továbbá azt se értem, hogy mivel a nyelvek fejlődése azt a célt szolgálja, hogy korábban is megvalósítható funkcionalitást tudj egyszerűbben leírni, hogy tud itt bármi hibanövekedés előfordulni. Jelentsen ez bármit. Ugyanis egymás alternatíváiról beszélünk, nem egymás kombinációiról. Az első mondatból kiindulva pedig, mivel tipikusan arról van szó, hogy rövidebben, kevesebb "featuret" használva írjuk le ugyanazt, kevesebb lesz a programban a "feature"-ök felhasználási száma. Ezért még ha lenne is értelme ennek az egész feature kombinálásnak, az új feature-ök használatával kisebb számokat "hatványozunk", bár nem tudom pontosan milyen hatványról is beszélünk itt, illetve hogy minek a megjelenésére számítunk a kitevőben.
Ha egy program 10
for
ciklusból áll, akkor az 10 potenciális hibázási lehetőség (amennyiben ignoráljuk a ciklusok magját, ami a választott példa miatt irreleváns). Ha ebből 5-öt lecserélünkforeach
-re, akkor hány hibázási lehetőségünk lett? Mivel 2 feature-t használtam 10^2=100? Vagy maradt az 5+5=10? Vagy 5+0=5, hiszen egyforeach
-et még egy újszülött se nagyon bír elrontani? Ha nem az első, azzal megcáfoltuk Gábor állítását. Ha az első, akkor viszont én elmegyek műkörmösnek...(Ezt nem kellett volna végiggongolnom, mert most az agyam kicsit matekosabb fele elkezdett visítva leolvadni :))
Paks 2
- for helyett használsz foreach-et vagy fordítva;
- for -t próbálsz meg foreach szintaktikával leírni és fordítva -> syntax error
- nem is iterálsz, hanem kitalálsz helyette valami rosszabbat.
Látható, hogy pusztán nézőpont kérdése, mennyire "hatványozottan nagyobb" a hibalehetőség, ha kényelmesen / elegendően nagy eszközkészlettel dolgozol.
Olyan ez, mint a szerelés: ha a szerszámos ládádban 12 féle csavarhúzó van, akkor sokkal nehezebben választod ki az adott csavarhoz a legjobbat, mint ha csak egy kalapácsod van. Ha ez elég nagy, akkor minden csavart be tudsz vele ütni, kifelé meg szedje ki az, aki akarja. :)
Persze ha van egy komolyabb szerszámkészleted, és már valamennyire megszoktad a szerszámokat, akkor sokkal rövidebb idő alatt sokkal szebben fogod összerakni ugyanazt a konyhaszekrényt, mint egy darab kalapáccsal - de hát az én szövegértésemmel baj van, úgyhogy nyilván nincs igazam. ;)
Mert 1 vezérlési szerkezetet használva 10 volt, akkor 2-t használva 2^2 = 4 lesz a szorzó, amivel a 10-et szorozni kell.
Szerintem pedig az egészben egy hiba van csak: a (z alapvető) vezérlési szerkezetek minden nyelvben meg vannak, így ez nemigazán feature.
Az egész lényege - amennyiben jól értem a szövegeket :-D - annyi, hogy felesleges a profi szerszámkészlet, mert kőbalta is van, és az ősember is el volt ezzel egy darabig, akkor meg minek bármi mást / többet használni.
Mert 1 vezérlési szerkezetet
használt_featureszám^2
formulával határozhatunk meg :)Egyébként komolyabbra fordítva, Gábor nem azt mondja (ha jól értem), hogy a programban fog négyzetesen nőni a hibák száma, hanem hogy exponenciálisan növekvő számú módon tudunk hibát vinni a rendszerbe. Ami oké, csak semmit nem jelent. A fű zöld, az ég meg kék :) Mondjuk azt is írta, hogy
Szóval összességében Gábor azt mondja, amit te is írtál: ne adjunk választási lehetőséget, mert az csak összezavarja a programozókat. És egyébként is meg kell tanulni használni a dolgokat, ami "kidobott idő", hisz a lefejlesztett funkcionalitás ugyanaz lesz, ezért a tanulással és a funkcionalitáshoz szükséges eszközök kiválasztásával eltöltött idő nettó veszteség. Ennek elsőre blikkre van értelme. Másodikra viszont nincs. Ugyanis ez ignorálja, hogy a fejlettebb feature-ök többnyire csökkentik a választások számát, emiatt csökkentik a fejlesztési időt, viszont cserébe növelik az olvashatóságot, karbantarthatóságot, ami szintén csökkenteni fogja a karbantartási időt, amikor legközelebb az adott részhet kell nyúlni. És akkor körbeértünk :) Erről ugyanis nem lehet meggyőzni, még olyan példákkal se, amik nyilvánvalóak és ő is elismeri (Assembly vs PHP). Úgy érzem Gábor úgy gondolja, hogy az absztrakciók szintjének növelése egy szintig hatékony, afölött kontraproduktív. Ami valószínűleg igaz, amíg a megoldandó feladat komplexitása konstans. Márpedig Gábor a leírása alapján olyan környezetben dolgozik, ahol ez igaz, ezért azt gondolja, hogy a többi webes rendszerben is így van. Valójában viszont a fejlesztők szemével nézve a feladatok komplexitása folyamatosan növekszik (pl skálázhatóság, magas rendelkezésre állás, vásárlói profil alapú termékajánló stb). Egyrészt az idővel, a technológiai fejlődéssel, másrészt jó eséllyel a senioritás szintjével is.
Innen már el lehet ugrani oda, hogy a rendszerben lévő hibák száma is nő, hiszen az a komplexitással, a futó kód méretével, az absztrakciók számával valóban jellemzően nő. De ezt nem a feature-ök száma határozza meg, hanem a feladat komplexitása. A feature-ök csak a növekvő komplexitás elérésében támogatnak. Na mindegy, továbbra is parttalan a vita, csak kijött :)
Úgy érzem Gábor úgy gondolja,
Persze, ez így van. Létezik overengineering. De ő messze nem arra a szintre tette a mércét, mint az átlag fejlesztő, hanem már az OOP alkalmazása is túl absztrakt neki.
A négyzetes micsodát szerintem sincs értelme tovább gondolni.
Igen
Az pedig nagyon jól látszik, hogy a segédeszközök és az absztrakciók számának a növelése nem segít a problémák megoldásában. Nem véletlenül nő a betörések száma a nagy informatikai és egyéb cégekhez: a feladatok komplexitása messze meghaladja a programozók intelligenciáját, azaz nem látják át a rendszer működését és az egyes komponensek interakcióit.
A feladat összetettsége lehet természetes és mesterséges, ez utóbbi pedig abból adódik, amikor programozók mindenféle best practice-re hivatkozva elbonyolítják a rendszert.
Szabadidőmben szeretek nyílt forráskódú szoftvereket vagy könnyen letölthető és visszafejthető frontend alkalmazásokat elemezni. Az a legegyszerűbb eset, hogy például a használt jQuery teljesen felesleges, vagy hogy OOP-t használnak ott, ahol egyszerű függvényekkel is meg lehetett volna oldani a problémát jóval kevesebb munkával, de az is általános, hogy a legtöbben nem értik az objektumorientált programozást. A programok nagy része feleslegesen overengineered.
Jól érted, amit írtam, de a
Leírtam, a komplexitás egy
Minden absztrakció egy hazugság, de legalábbis féligazság. NFS esetében csináljunk úgy, mintha helyi meghajtó lenne, ami mindaddig működik, amíg a hálózat elérhető és nem dugul be. Építsünk rá egy szolgáltatást! Az csak addig fog működni, amíg a hálózat is elérhető. Minél több ilyenből áll össze valami, annál nagyobb valószínűséggel fog kiesni belőle valami.
És annál nagyobb eséllyel fognak rá betörni, mert a készítői nem látják át, melyik absztrakció hol szivárog. Friss a Marriott hotel esete, de idén betörtek a Google-hoz, korábban a Microsofthoz, nagyon sok eset van, ahol tízmilliós nagyságrendben vitték az adatokat. Pedig ezeken a helyeken van pénz, vannak szakemberek, van tudás, és mégis.
Hozzátok hányszor törtek be eddig?
Én egyébként tizenkét éve egy cégnél dolgozom, és a felsoroltak nem céljaink, vagy másképp oldjuk meg. A microservice-ekben nem hiszek, továbbá az automata tesztekben sem.
Minden absztrakció egy
Érteni kell, amit csinálunk. Ehhez tanulni kell és tapasztalni. Ezért nem igaz, amit írtál, hogy a webfejlesztés egy egyszerű szakma. Nagyon nem az. Te csak a frontend részét látod. Attól még, hogy PHP-t is ismered, nem láttál még igazi backend rendszert, mert akkor nem írnál ilyet. A LAMP önmagában egy komolyabb rendszerben a frontend, nem a backend. Emiatt egy tényleg fullstack dev (ha létezik ilyen egyáltalán) egy nagyon komoly tudású ember lehet csak.
Sőt... emlékeim szerint tartottunk közösen prezentációt a smartyról, és hogy miért kéne beemeljük a stackünkbe ;) Ami ugye egy erősen absztrakciókkal dolgozik. Ez persze nem ma volt :)
Azzal egyetértek, hogy egyre komplexebb elemeket emelünk be a programjainkba, amikkel jönnek azok hibái is, nem csak a megoldásai. De enélkül sok feladatot nem lehetne megoldani. Neked ott van a PHP nyelv, a DB stb. Komplexebb rendszerekben ugyanez van, csak nagyobb volumenben. Pl amint az írást is skáláznod kéne, vagy multisite rendszert építeni, meg lennél lőve a stackeddel, és kénytelen lennél elmozdulni komplexebb megoldások irányába. Manapság pedig nagyon megnőtt az ilyen rendszerek száma.
Az automata tesztek hasznosságát vitatni pedig kb az a szint, mint a korong alakú Föld mellett kardoskodni. Ez egy teljesen meghaladott alapvetés. A mikéntjén lehet vitatkozni, a szükségességét kérdőre vonni viszont értelmetlen. Nekünk pl van a buildben kb 35k automata tesztünk, ami nélkül nem merge-ölhetünk. Emellett vannak egyéb release verifikációs tesztek, amik közel két napig futnak. Ezeket hogy oldanád meg kézzel?
»Minden absztrakció egy
Hát... ez egy érdekes mondat :)
Én biztos vagyok benne, hogy az állításaid nagy része igaz, és bizonyos szint felett szükségesek különféle eszközök és technikák a hatékony fejlesztéshez. De évekkel ezelőtt feltettem a kérdést, amire máig kíváncsi vagyok, hogy mi az a szint, ahol OOP-t érdemes használni? Mert az látszik a korábban hozott példákból, hogy az OOP bevezetésével a projekt komplexitása növekszik, azaz a hatékonyság csökkenni fog. És ugyanígy kérdés, hogy azok az emlegetett eszközök vajon mikor lesznek szükségesek.
Tudod cáfolni? Inkább neked
Inkább neked kéne bizonyítanod, hogy igaz.
Tudod cáfolni?Előbb definiáld
Én nem tudok ilyen szintet
Talán a legjobb példa erre, hogy még a js is oo nyelv, pedig annak idején csak arra hozták létre, hogy tudjad a menü háttérszínét változtatni mouseoverre. Nagyon alacsony a dolog belépési küszöbe, viszont ez is olyan, hogy én is tudok vésőt használni, mégsem lesz belőlem sosem fafaragó művész, mert ahhoz más kvalitások meg rengeteg gyakorlás kell. Az szerintem nem érv arra, hogy valamilyen eszköz haszontalan, hogy nem tudod egyből fél perc után mesteri szinten használni...
Absztrakció
Bizonyítás:
Vegyük a következő nagyon egyszerű programkódot:
print $valtozo;
$valtozo = 'ertek';
print $valtozo;
$valtozo = 'ertek';
print $valtozo;
A futás során az történik, hogy egy változónak értéket adunk, majd kinyomtatjuk a képernyőre.
$valtozo = 'ertek';
print $valtozo;
}
fuggveny();
fuggveny();
fuggveny();
Nem. A második programban egyrészt definiálunk egy függvényt, majd ezt háromszor meghívjuk. A függvény meghívásakor az történik, hogy a függvény címére ugrik a program, létrehoz egy ideiglenes memóriarekeszt, ahol a függvény változóit tárolhatjuk. Létrehozunk benne egy változót, annak értéket adunk, majd kinyomtatjuk. A függvény futásának befejezésekor a memóriarekesz tartalmát felszabadítjuk.
A második programnak tehát ugyanaz lesz a kimenete, mint az elsőé, de lassabban fog lefutni a plusz memóriaműveletek miatt, valamint több memóriát is foglal.
Az absztrakció azt jelenti, hogy elvonatkoztatok a valóságtól, és csak azt veszem figyelembe, amit fontosnak tartok. A valóságból kivonok egy kis részt, ezzel egyszerűsítem a problémát.
Esetünkben programozóként a következőképp gondolkodom: a függvény háromszori meghívásával a programom pontosan ugyanazt fogja csinálni és ugyanúgy fog működni, mintha a függvény tartalmát háromszor egymás után másolnám.
A valóság ezzel szemben az, hogy a függvény meghívásakor egyéb műveletek is történnek, ezért a program lassabb lesz.
A fenti gondolatmenetem tehát hamis, mert a második program nem ugyanúgy működik, mint az első. Az állításomat bizonyítottam.
Bizonyos szintig minden absztrakció szivárog. Ez nyilván ismerős kijelentés.
A számítástechnikában minden absztrakció teljesítményvesztéssel jár, bár ez a legtöbb esetben elhanyagolható. Emellett pedig magasabb logikai szinteken az absztrakciók nagyobb problémákat hoznak, egy jó példa erre az elosztott nyolc alapvető tévedése. Ezért hoztam fel az NFS-t.
Állítás: minden absztrakció
Nekem nem jött le, hogy a fenti hogy bizonyít ezzel kapcsolatban bármit. Mondjuk maga a kijelentés is elég fura. Azt eddig is tudtuk, hogy szivárognak az absztrakciók, de senkit nem érdekel, mert a gyakorlatban ennek nagyon ritkán van komoly hatása. És ha van, akkor foglalkozunk vele pl optimalizálásnál. Ha meg nincs, akkor meg bőven megéri őket használni. Gondolom te is hívsz függvényeket ahelyett, hogy lemásolnád az előző kódot csak hogy ugyanazt csinálja.
Ez is olyan dolog, amiben meg kell találni az egyensúlyt. Az egyik oldalról a DRY principle miatt érdemes szinte mindent újrahasznosítani, a másik oldalról meg a szivárgó absztrakciók miatt esetleg lehet sebességbeli veszteség, vagy hibák, vagy bármi egyéb. Általában az első szokott nyerni, de az sem örökérvényű szabály. Bár ritkán, de előfordulhat, hogy a DRY nem érvényesül, mert valami felülírja. Az meg hogy absztrakciókra van szükség egyértelműen következik abból, hogy újra kell hasznosítani a kódot.
Szintek
Nem az a kérdés, hogy kell-e őket használni vagy sem, hanem az, hogy hány szinten – minél kevesebb, annál jobb.
A spectre/meltdown továbbra
Spectre
Ha nem lenne a
És továbbra sem értem mi köze a distributed computing fallacies-nek ahhoz, hogy egy hálózati kommunikáció szét tud esni, illetve tulajdonságai vannak. Itt a hozott példádban pont direktben látszik, hogy hálózati kommunikációval érünk el tartalmat, tehát nincs absztrakció mögé bújtatva. Itt ha valaki ezeket figyelmen kívül hagyja, az nem absztrakció miatt van, hanem tudatlanság miatt.
Mellesleg ez a lista nem csak WAN hálózatokra igaz. Managed networkön ugyanígy van. Mégha a költségek és a valószínűség kisebb is. Simán lehet pl split brain LAN hálón is.
Ha elfogadom, hogy a Spectre
Ez így két szempontból is hibás elképzelés. Egyrészt minél jobban a minimális mennyiségű absztrakcióra törekszel, annál nagyobb része a kódnak nem lesz újrahasznosítva, és a kódismétlés lerontja a karbantarthatóságot. Másrészt az absztrakciókat azért használjuk, hogy javítsuk a kód érthetőségét. Ha nem teszünk bele kellő mennyiségű absztrakciót a kódba, akkor nehezen érthető lesz, ami szintén lerontja a karbantarthatóságot. Abban egyetértünk, hogy a túl sok absztrakció is rossz, viszont az optimális mennyiség nem a minimális, hanem inkább az a tartomány, amiben az átlag fejlesztő jól érzi magát, és a segítségével könnyebben boldogul a kód fejlesztésével és karbantartásával. A túl sok absztrakció is lerontja a karbantarthatóságot, mert annyi osztály és metódus lesz, hogy egy csomó plusz lépés megtalálni, hogy hol van a kód, amit módosítanod kell. Az overengineering is ugyanígy a karbantarthatóságot rontja le, és a kód érthetőségét nehezíti, hogy mesterségesen, gyakorlatilag jó ok nélkül iktatnak bele új absztrakciós szinteket, csak azért, hogy bizonyítsák, hogy ők olvastak erről vagy arról a tervezési mintáról.
Az, hogy kinek mi az optimális mennyiségű absztrakció, elég egyedi. Egyesek szerint minél kisebb és egyszerűbb egy metódus, annál jobb, legalábbis olvastam ilyet jó néhány könyvben. Én azért ezt fenntartásokkal kezelem, és jobban szeretem csak a lényeges dolgokat metódus nevekkel ellátni. Persze ha egy metódus túl nagyra hízik, akkor az erős jelzés, hogy érdemes szétbontani több apróbbra, és azoknak szintén külön nevet adni. Én inkább ilyen módon fejlesztek, és ha nagyjából körvonalazva van, hogy milyen modell szerint csinálom a kódot, akkor onnantól hagyom, hogy a kód beszéljen magáért, és feleslegesen nem tépem szét ezer darabra. Legtöbbször ha egy kódrész nehezen érhető az nem azt jelenti, hogy ki kell szervezni több külön metódusba, amik elmagyarázzák, hogy mit csinál, hanem hogy rosszak a változónevek. Érdekes, hogy olvastam olyan (egyébként elég népszerű) könyvet, ami pedig a fentit propagálja.
Az x86 architektúra
Tehát nem létezik olyan absztrakció, amiről HG beszél. Meg hát by definition az absztrakció erről nem mondhatna semmit, ha létezne is rá absztrakció. Ez teljesen az implementáció belügye. És ez a sebezhetőség rendre benne van az elmúlt jópár generációjú prociban.
Azt mondjuk nem tudom, hogy a valóságban valaha ezt kihasználta-e bárki bármilyen támadáshoz. Amikor olvasgattam róla, akkor még nem volt ilyenről információ. Illetve annyira lassú és bonyolult is az adatszivárogtatás, hogy a gyakorlati felhasználhatósága limitált. Ez nem a rootkites Pistikék szintje :)
Szóval a probléma létező, de semmi köze az absztrakciók témájához.
Ok. Max titkosszolgálatok
Lyukak
Korábban idéztem a Wikipédiából: absztrakción "a lényeges tulajdonságok kiemelését és a lényegtelen tulajdonságok figyelmen kívül hagyását értik"
Tegyük fel, hogy van száz kockád, nevezzük ezt az Igazság állapotának. Eljön az absztrakció ideje, kiveszel belőlük egyet. Még mindig nagyon jól lehet játszani, mert így is rengeteg maradt, de ritka esetben, amikor összeszámolnád őket, akkor kiderül, hogy már csak kilencvenkilenc van ott.
Megint jön egy absztrakció, megint kiveszel egyet. És így tovább. Tehát minden ilyen alkalommal egy picike információ eltűnik a rendszerből.
Tegyük fel, hogy van száz
Olvasgattam egy kicsit a
I disagree, however, with your statement that all abstractions are “failed” abstractions, mostly because you’ve not defined failure. You’ve even provided a pragmatic point-of-view where abstractions are not failures (usability, and ease of understanding).
Basically, if an abstraction hides the details that we are concerned with, then it is our job as developers to choose a different (less abstract) abstraction. If you are concerned with query timing and LINQ doesn’t give you fine-grained control over that, then LINQ is the wrong abstraction to use.
Abstractions only fail when they are wrong tool for the job, but in that case it’s the developer that has failed.
[1] Of course, it is possible to prove that any given abstraction has a one-to-one correlation with what it is abstracting, thus making it a “leakless” abstraction. For instance, one might be able to prove that the SQL grammar is fully covered by the LINQ grammar. But in Joel’s argument, I’ll assume he considers such an abstraction to fall into the “trivial” category.
https://discourse.codinghorror.com/t/all-abstractions-are-failed-abstractions/160/4
Mi volt a célod ezzel a hozzászólással?
Szerintem ez kínosan szakmaiatlan. Érvelni amellett, hogy ne használjunk függvénykiemelést? Fájt olvasni.
Ha a junior kolléga érvelne az első verzió mellett, akkor kapna egy rohadt nagy lecseszést. Ha esetleg egy senior kolléga érvelne e mellett, akkor azonnal jelezném a főnökömnek, hogy vagy ő vagy én távozok a cégtől.
Most komolyan, hozol egy példát, amivel te sem értesz egyet, csak azért, hogy cáfoljál valamit, amit senki nem állított? Ennek mi értelme?
Nem hiszek benne, hogy tőled valaha is kaphatunk érdemi kódot, de azért szeretnélek emlékeztetni, hogy évekkel ezelőtt, már sokszor ígértél olyat, hogy bemutatsz egy valós keretrendszert (?) vagy mit is, ahol megnézhető, hogy az általad preferált módszertan, rendszer, akármi nagy projektek esetén is működik. Üres ígéreteken kívül ebben a témában még semmit nem kaptunk tőled.
De, hogy érdemben is reagáljak a hozzászólásra. A refaktorálás lényege, hogy olvashatóbb, jobban kezelhetőbb kód szülessen ugyanolyan kimenettel. Ezt hasznosabbnak tekintjük azzal szemben, hogy egy függvény létrehozása, többszöri meghívása mekkora plusz terhet jelent a processzornak. Nem csak a gépeknek, hanem embereknek is írjuk a kódunkat, emiatt az olvashatóság kiemelten fontos. Így teljes egyértelmű, hogy a második programkód jobb, mint az első.
Nem
A leírtak nem arról szólnak, hogy melyik programkódot kell választani.
Szövegértés
Érdemes lenne picit gondolkodni rajta, hogy nem lehet-e, hogy fordítva van.
Amit itt "bebizonyítottál",
print 'ertek'
, amikor azt hirdeti magáról. De speciel itt az történik, amit a függvény ígér.Abba most ne menjünk bele, hogy normális futtatókörnyezetben nem az történik, amit írtál. De értem, amire céloztál.
kimondhassuk: ez egyáltalán nem egy szögegyszerű szakma...
Szóval ami a féligazság, az az, amit te közvetítesz itt, miszerint az absztrakció rossz. Ráadásul teszed ezt olyan környezetben dolgozva, ami gyakorlatilag az egyik legmagasabb absztrakciós szinten létezik, így még kicsit bort is iszol és vizet is prédikálsz. Ami a te dolgod, csak megint evidenciák puffogtatásával próbálsz meggyőzni nálad adott témában (OOP, automata tesztelés, elosztott rendszerek, futtatókörnyezet stb) tapasztaltabb kollégákat, hiszen ezekkel te bevallottan nem dolgoztál.
Szóval ami a féligazság, az
Az absztrakció wikipédiabeli megfogalmazása így hangzik: "a lényeges és lényegtelen tulajdonságok elválasztását, a lényeges tulajdonságok kiemelését és a lényegtelen tulajdonságok figyelmen kívül hagyását értik rajta"
Tehát nem a teljes igazsággal dolgozik, hanem az absztrakciót végző azt mondja, hogy a számára lényegtelen dolgokkal nem foglalkozik, úgy veszi, mintha azok nem lennének ott. Tehát az absztrakció féligazság vagy hazugság. A wikipédiás példát továbbgondolva ez olyan, mintha kijelentenéd, hogy minden madár magvakat eszik, de amikor találkozol a Darwin pintyek egy alfajával, hazaviszed kalitkában, de megdöglik, mert utólag kiderül, hogy épp vérrel táplálkozik. Hibás volt az absztrakciód.
Ez így ebben a formában nem igaz. Ezt az állításod már én is többször megcáfoltam.
Ez egyszerűen nem igaz, én
Amellett, hogy utóbbi egy értelmetlen kijelentés, nehéz belemagyarázni, hogy nem gondolod rossznak az egészet. Illetve mindig csak negatívan írsz a témáról. Emiatt alakul ki az a kép az emberben a véleményedről, amit fentebb írtam. És ezért frusztráló már a téma a többségnek.
Az egymásra épülő absztrakciós szintek meg sok esetben szükségesek. Nem ez a baj, hanem a céltalan halmozásuk. De akkor itt ezt a témát szerintem örökre lezárhatjuk, mert ebben mindenki egyetért.
1) Method inlining (csak a kódban létezik az absztrakció, runtimeban nem)
2) Többszintű öröklődés: több absztrakciós szintre bontottad le az osztályodat, de a típus ismert, ezért futásidőben ebből semmit nem veszel észre, statikus hívások vannak virtuális helyett.
3) A függvények/subrutinok nélküli spagetti kód memóriaigénye végtelen, hiszen minden egyes utasítás külön memória területet igényel, az ismétlődőek is.
4) CPU cache (és úgy általában a cache-ek): a CPU szemszögéből a memóriaművelet egy absztrakció, ami elfed egy nagyon komplex rendszert, tehát az állításod szerint ez teljesítményromláshoz kéne vezessen, de ennek az ellenkezője az igaz: jellemzően masszív teljesítménynövekedéshez vezet. És persze leakel, hiszen a "memóriaműveletek" nem garantálják a láthatóságot a CPU-k között, arról programozóként neked explicit módon kell gondoskodnod. (Ez az ára a jó teljesítménynek)
Az OOP-ről lehet hitvitát folytatni. Van ahol az kell, van ahol nem. Az automata tesztelés viszont egy annyira alapvető eleme a programozásnak, hogy ennek a hasznosságát kétségbe vonni - egy elvileg vezető programozó ember által - konkrétan az ijesztő kategória. Védőháló nélküli kötéltánc.
A futtatókörnyezeten a HW/OS/(VM/)stb-t értettem. Nyilván ez kell minden programozáshoz :) De amit ebből rendszeresen kiemelsz a példáidat alátámasztandó (lásd előző hozzászólásod), az már rég nem úgy működik, egy része meg régen sem úgy működött. Legalábbis amíg rendszerközeli dolgokról beszélünk. Afölött meg úgyis mindegy, hiszen egy PHP/JS amúgyis rémálom, ha teljesítményről van szó, a függvényhívás a legkevesebb... Bár a modern JS motorok ebben már elvileg elég jók.
Amellett, hogy utóbbi egy
Mint írtam korábban, az általam elemzett kódokból számomra egyértelmű, hogy rengeteg programozó túl sok absztrakciós szinttel dolgozik. Ennek a következménye a sok lassú program és az, hogy elképzelésük sincs, mi is történik igazából.
Példáid:
1, akkor ez nem is absztrakció,
2, izgalmas volna megnézni, hogy ha van egy programod procedurálisan megvalósítva, valamint egy másik OOP-vel, mekkora lesz a lefordított kód mérete, valamint a futásidő és memóriahasználat is érdekes,
3, ez egy érdekes felvetés, még gondolkodom rajta,
4, pont ezen gondolkodtam az este, hogy a hardverben a cache memória vagy a RAM az absztrakció; a tudásom itt némileg hiányos, mert ilyen mélyre még nem mentem le, úgyhogy itt tévedhetek.
A következőre jutottam: a modern processzorokban a RAM az absztrakció, mivel a CPU közvetlenül a cache-sel dolgozik. A memóriaalrendszer felelős a cache és a RAM közti másolásokért.
Emiatt ha egymás mellé teszel két processzort, az egyikben van cache, a másikban nincs, akkor a kettő nem egyezik meg, nem hasonlíthatod őket össze, mert az egyik alma, a másik körte.
Az absztrakciós szivárgás a cache-sel rendelkező CPU-kban akkor jelentkezik, amikor a gyorstárban nem található meg a szükséges adat, ezért a RAM-ból be kell olvasni a megfelelő lapot.
Emiatt a 4-es példád sem jó.
1, akkor ez nem is
Hogyne lenne. Ott a függvény. Csak ki van optimalizálva.
Amúgy ha már előkerült, nem az OOP vs nem OOP miatt lesz bármi különbség a méretben, vagy teljesítményben, hanem amiatt, ahogy használva van az OOP. Egy objektum nem más, mint egy struct és egy hozzárendelt procedurális kód. Ha hozzáveszed még a polimorfizmust, akkor megjelennek a virtuális hívások, vagyis a konkrét megvalósítás meghívásához fel kell oldani egy címet. Ilyen procedurális kódban is létezik, pl egy switch is hasonlóan működik (ha folytonos range-ből vannak az eseteid, egy jump table-lel 2 lépésből találja meg a konkrét lefuttatandó ágat). Szóval ez a struct+procedurális kód még kiegészülhet egyéb, implementáció specifikus dolgokkal, amik szükségesek pl szinkronizációhoz, GC-hez (bár a GC és az OOP nem jár kéz a kézben) stb. De ezek egyike se kötelező eleme az OOP-nek. Pl a 64 bites Oracle/OpenJDK JVM-ben 16 byte a minimális mérete egy objektumnak. Ennyi a sallang. Viszont nem (illetve nem mindenhol) kell menedzseljen free listeket a memory allocation miatt, abból kisebb waste keletkezik, mint egy default malloc implementációból. Szóval nehéz ezt összehasonlítani, mert implementációkat tudsz összehasonlítani az optimalizációjukkal és specifikumaikkal, nem pedig elméletet. És jellemzően managed envet nem managed envvel. Na mind1, a téma tulajdonképpen nem ez volt :)
Ha már a teljesítmény szóba kerül, itt van is egy trade-off. 2 fő ok miatt szoktak a compilerek inline-ozni. Az egyik, hogy megspórolják a minimális stack használatot tipikus esetben (mai procikon ez a return address és sok esetben a base pointer elmentése), a visszatéréskori ugrást és a hibás spekulációt. Ez utóbbi a komoly költség, nem a stack használata. A másik dolog pedig, hogy ha "egyenesen" folytatódik a program futása, vagyis ha az utasítások egymást követik szekvenciálisan a memóriában, akkor nem kell megfizetni annak a költségét, hogy esetleg a main memoryból elővarázsoljuk a következő utasítást egy random címre ugrás után. Erre nagyon durván optimalizálnak is a fordítók egyébként. A JVM JIT-je pl ha van egy nagyon magas százalékban végrehajtott ág (pl bimorphic, multimorphic hívás esetén), akkor a tipikus ágat "egyenesen" képes inline-ozni egy type check után. Vagyis ilyen esetekben a kód szekvenciálisan hajtódik végre tipikusan az L1 instruction cacheből. Ilyet csinálnak amúgy az AOT compilerek is. És mivel trade-off, itt számít egy metódus mérete pl, akármit nem fog a fordító inline-ozni, mert baromi nagyra növelné a lefordított natív kód méretét, ezáltal a memóriahasználatot. Illetve így gyakorlatilag akár az iCache-t is simán felülírná a szekvenciális inline-olt utasításokkal, ami adna egy nagy pofont az egésznek. Ezért a JVM-nek be tudsz állítani pl egy thresholdot, hogy mekkora (bytecode) méretű metódust inline-ozhat maximum. Ez pl egy érv a kisebb metódusok mellett, ha fastpathon vannak használva. Na, megint elkanyarodtam kicsit :) A lényeg, hogy a spagetti kód nem mindig nyerő teljesítmény szempontból, hiába látszik úgy.
Se nem a RAM, se nem a cache az absztrakció. A memóriaművelet az absztrakció. Amögött transzparansen meg van oldva, hogy cache, vagy main memory access (is) történik. A te programod erről semmit nem tud. Ezért írtam korábban, hogy nincs cache absztrakció az architektúrában. A procin belül persze van.
De nem csak CPU cache esetében van így. Az oprendszer disk cache ugyanez. Vagy az adatbázis előtti L1 és L2 cache ORM-ek esetében. Mind transzparens, mindhez szükséges absztrakció, és mind jellemzően komoly teljesítményjavuláshoz vezet.
Az egész cache by definition ugye azt jelenti, hogy javítjuk a data locality-t vagyis minél közelebb próbáljuk tartani az adatot a kódhoz. Hogy ne növeljük a kód komplexitását, absztrakció mögé rejtjük. Tehát az eredeti adatforrás (main memory, DB, disk) helyett először egy cache-ből próbáljuk elővenni az adatot, majd ha miss volt, egy következőből stb. Emiatt jó példa. Sosem cache-t címzel, csak onnan próbálja meg először feloldani.
Az absztrakció szükséges,
Mint írtam korábban, az általam elemzett kódokból számomra egyértelmű, hogy rengeteg programozó túl sok absztrakciós szinttel dolgozik. Ennek a következménye a sok lassú program és az, hogy elképzelésük sincs, mi is történik igazából.
Húha, sikerült idáig eljutni onnan, hogy az absztrakció rossz és tűzzel vassal irtani kell? :D
Jó lenne már eldönteni, hogy
Ha tényleg csak a túl sok absztrakciós szinttel van problémád, akkor jó lenne valami példát látni, hogy szerinted mi a túl kevés, túl sok és optimális. Mi sem szeretjük az overengineering-et, de részben stílus függő is, hogy mit tekintünk annak. Valaki a sok apró függvényt/metódust szereti beszélő nevekkel, én inkább valami közepes méretet preferálok, ahol nincs az "i = i + 1" is megmagyarázva. A helyesen használt absztrakció is ezt jelentené, hogy kiemeljük, hogy mit csinál az adott kód, mint lényeges részt, és beleírjuk az osztály, metódus, változó nevébe, hogy könnyebben legyen követhető. Azt, hogy hogyan csinálja, meg csak olyan szintig magyarázzuk meg, amennyire szükséges. Ebben is vannak egyéni dolgok, mert valaki csak úgy érti meg, ha szájbarágósan magyarázod, valaki meg elég jól tudja követni anélkül is.
+1
Én emiatt szoktam javasolni Gábornak, hogy politizáljon, mert azon a területen ez egy rendkívül hasznos tulajdonság manapság. ;)
Lehetetlen cáfolni, mert akkor csak az derül ki, hogy szövegértési problémáid vannak. :)
Te készítetted a popcorn-t, én már mind megettem...
Nem
Mi a konkluzió?
Viszont érdemes lenne
Illetve hogy egy random kódbázist tekintve simán lehet olyan absztrakció, amit te szükségtelennek találsz belepillantás után, de fontos oka van, hogy bekerült. Triviális példa a tesztelhetőség, amit csak a prod kódot böngészve nem biztos, hogy megtalálsz.
Triviális példa a
+1, én is nemrég tettem be egy külön metódust valahova, csak hogy jobban tesztelhető legyen a kód, és ne "uncaught exception"-ből kelljen előrántani, hogy mit dob bizonyos aszinkron hibáknál. A mocha fejlesztésénél sajnos nem gondoltak rá, hogy ilyesmire is lehessen tesztelni, és elég ocsmány lenne hozzátákolni.
Építsünk rá egy
Gondolom ezek szerint egy spagetti kódos oldal minden szempontból jobb, mert annál nincsenek absztrakciók. Vicc az egész. :D
Kombináció
Fentebb linkeltem, hogy PHP-ban a típusos paraméterek a bevezetésükkor gondot okoztak bizonyos esetekben, emiatt a programban új interface-eket kellett betenni, hogy működjön. Később javították ezt a hibát, de fejben kellett továbbra is tartani, hogy az adott program melyik verzión fut, mert ha régin is, akkor ott továbbra is interface-ezni kellett, ami bonyolítja a helyzetet.
Ha már olyan egyszerű példát hozol, mint a
for
ciklus, meg lehetett volna említeni a manapság divatos funkcionálisarray.forEach()
-et is, ami első ránézésre ekvivalens vele, másodikra pedig kiderül, hogy ha a futási környezet nincs rá optimalizálva, akkor lassabb jóval a natív alternatíváinál.Fentebb linkeltem, hogy
Szóval ez a hozott aspektus tök más, mint amiről szó volt. És ha csak ezt az aspektust vizsgálja az ember, az szűklátókörűség, ilyen alapokon nem lehet helyes döntéseket hozni. Erre lehet mondani, hogy akkor vegyük el az egyéb előnyökkel járó választás lehetőségét a fejlesztőtől, hiszen ő buta. De nem buta, max tanulnia kell.
Ha arra, hogy PHP-ban nem
Eleve, ha zavarnak a mellékhatások, akkor sima for ciklusból is lehet függvényeket hívni, tehát ott volt választási lehetőség, forEach esetében pedig nincs. Nem tudom, én sosem találkoztam mellékhatással (persze ez nem jelenti azt, hogy nincs, de húsz év alatt azért megír az ember pár for ciklust). Másrészt tíz éve nincs igazán fejlődés a processzorok sebességében, a memóriák elérési ideje és sebessége pedig jóval kisebb mértékben nőtt, mint a CPU-ké. Nyilván lehet optimalizálgatni a futtatórendszert (fordító, JS motor), akkor meg ott fizeted meg az árát. Ma, ha elindítasz egy böngészőt üres lappal, 150-200 megabájt memóriát kell hozzá lefoglalni, és egy átlag weboldal is megeszik száz körül. És mindezt (szimbolikusan) egy forEach ciklus kedvéért.
Ez félrebeszélés, teljesen
Most az eredeti kijelentésed ellen érvelsz, miszerint a webfejlesztés szög egyszerű. És hozod sorban az ellenpéldákat :)
Mert átgondolatlanul
inf3rno 51-es hozzászólása szerint igen.
A hibás nyelvi elemet valahol az 5.x-ben hozták be. De fog-e ezzel valaki találkozni, aki jóval egyszerűbb módon programozik? Lehet-e szögegyszerű eszközökkel fejleszteni? Feltétlenül jobb lesz-e az a kód, ami komplex eszközökkel készült?
Vicces dolog a chache-ekre meg a branch predictorokra hivatkozni, amikor havonta derülnek ki ezek hibái. Nemrég olvastam egy cikket, hogy hét új Spectre/Meltdown-jellegű hibát fedeztek fel, úgyhogy nagy kérdés, hogy vajon ezek a dolgok meddig maradnak a processzorokban a biztonság kárára.
inf3rno 51-es hozzászólása
Én továbbra is tartom, hogy lehet. Az már más kérdés, hogy érdemesnek érdemes e...
Te is hoztál fentebb Java-s
a bekezdésem eléjéből
+1
Nem rémlik, hogy lett volna
Az osztásos öröklődéses
OOP-nél vannak szabályok, amiket be kell tartani a minőségi kód írásánál, ilyen szabály a Liskov Substitution Principle (LSP), amit a fenti kód megsértene. Ezek mögött a szabályok mögött van néhány évtized gyakorlati tudás, és mindegyik jó okkal született. Ha a fenti módon akarod alkalmazni az OOP-t, akkor nyilvánvalóan nem ismered sem ezeket a szabályokat, sem az okokat, amiért használjuk őket.
Miért van az, hogy az OOP-vel kapcsolatos kritikáidat mindig hibás példákra alapozod? Miért gondolod azt, hogy az OOP az öröklődésről szól elsősorban, holott az esetek döntő többségében egyáltalán nem is használjuk? Tudsz esetleg olyan - nem egysoros - példát mutatni, ahol a fenti int -> float probléma megjelenik, és lenne valami gyakorlati haszna?
A null átadása nálam opcionális paraméter esetében fogadható csak el, egyébként ha olyan kód fut le null-al, ami számot várna, az egyértelműen hibás paraméter, és kivételt kellett volna dobni rá már az ellenőrzéskor. Ez azt hiszem ízlés kérdése, nekem ez vált be.
Ez így egyáltalán nem igaz. Ha valami általános paramétert akarsz, akkor interface-t kell megadni, aztán ahhoz esetleg elkészíthetsz néhány alap implementációt a könyvtáron belül. Ha valamiből örököltetni kell egy könyvtár használatánál, akkor az nálam hibás tervezésre utal. Keretrendszereknél esetleg bizonyos esetekben elfogadható ilyesmi, de szerintem minden megoldható könyvtárakkal, és nincs szükség rá, hogy valaki más mondja meg, hogy mi legyen pl. a könyvtár szerkezet, vagy ilyesmik, ami általában keretrendszereknél divat. Szóval én azokért sem vagyok oda.
Én nem szoktam fejben tartani. Ha valami ritka dologról van szó, akkor megnézem a dokumentációt, ha valami gyakran használtról, akkor esetleg megjegyzem. Ha mégsem, akkor a tesztek úgyis azonnal jelzik, hogy valami hiba van. Gondolom debuggolsz, ha ennyire félsz a hibázástól. A BDD vagy TDD elég sokat tud segíteni, hogy ne érdekeljen, mert ha van teszted az éppen fejlesztett kódra, akkor azonnal tudod, hogy nagyjából hol hibázik, mert éppen azokat a sorokat írtad le fél perce. A hibaüzenetet meg pár másodperc megfejteni. Ellenben ha debuggolsz, akkor órákat el tudsz tölteni a hiba okának a felderítésével.
Tesztek
Az integrációs tesztek viszont fontosak.
drágább a projekt elkészítése
Pl amit olvashatsz róla, hogy ha nem használod, az egy idealista elképzelés. Ha mereven ahhoz akarunk ragaszkodni, akkor az sok esetben tényleg hülyeség. Mindent előre tudsz, mindent előre értesz, mindent előre tud a product owner, mindenre jó interface-eket tudsz már előre kitalálni, ezért előre megvan minden teszted stb. A gyakorlatban ez azért így nem mindig kivitelezhető, így amit a valóságban csinálunk, hogy prod kódot megfelelő tesztek nélkül nem engedünk be a repoba. Hogy a megfelelő teszt unit, és/vagy magasabb szintű teszt, az már egy másik kérdés. Mindenre nem érdemes unit testet írni. Meg az is egy másik kérdés, hogy a tesztet előre írod-e meg, vagy a prod kóddal párhuzamosan.
Viszont tesztek nélkül fejleszteni vakrepülés és a valóságban sokkal több időt is igényel. Ez azt is jelenti, hogy a tesztek jelentős részét a fejlesztők fogják írni, viszont a funkcionális megfelelőséget más személynek kell vizsgálni. Ez viszont történhet teljesen, vagy részben a fejlesztő által írt tesztek alapján is, amennyiben van átfedés a teszt forgatókönyv és a tesztek között.
Pl amit olvashatsz róla, hogy
Én először mindig API-t tervezek, csak utána foglalkozok a tesztekkel, utána meg az implementációval, de azt már váltakozva. Azért általában lehet tudni előre, hogy mi az, amit elvárunk a kódtól, és csak a hogyan, ami kérdéses, szóval ha van egy jól megtervezett API, akkor nem jellemző, hogy az később változna. Esetleg akkor változhat, ha nem megvalósítható valamilyen logikai akadály miatt, amit nem láttunk előre. A teszteknél általában csak egy-egy feature-el kapcsolatos teszteket, esetleg egy-egy scenario-t írok meg előre, és utána implementálom azt a részt. Aztán jöhet a következő. Ha nem tetszik az implementáció, akkor is inkább nagyobb egységeket szoktam átírni úgy, hogy az API és a tesztek közben változatlanok, aztán egy idő után zöldbe megy újra az egész. Ritka az, amikor annyira félresikerül, hogy revertálni kell mindent, aztán nulláról újrakezdeni, általában akkor fordul elő ilyesmi, ha egyszerre túl nagy darabot akarok átírni. Ez is olyan, hogy ki kell tapasztalni. Nagyjából most ez az optimális nekem. Gondolom másnak más. Attól függ, hogy mennyire fontos a coverage, hogy mennyire könnyen találja meg valaki a hibát eltérő méretű kódrészletekben, mennyire érzi macerásnak karbantartani a teszteket és szabályosan minták alapján refaktorálni, mennyire érzi szükségét, hogy minden percben legalább egyszer zöldbe menjen a teszt, stb... A unit teszteknek én sem látom egyébként már annyira értelmét, nekem túl "fine grained" az a megközelítés. Viszont az olyan alapelveket, mint először a teszt, utána az implementáció, illetve váltogatjuk a teszt és a kód írását, stb. azóta is betartom, mert azok nagyon hasznosak.
Igen, ez jól működik addig,
Most pl amit csinálok, az egész jó példa erre. Van egy elég komplex XML konfigurációnk, amit sokezer sornyi kód dolgoz fel, és még sokezernyi tesztel. A feladat, hogy mostantól legyen YAML is :) Tegnap reggel még csak ötletem volt hogy kéne összeérjenek, de hogy pontosan hogy, és milyen sarok esetek vannak, az még nem volt világos. Így értelmes teszteket se tudtam írni. Szóval egész nap csak implementáltam, és most már nagyjából működik. Úgyhogy most el lehet majd kezdeni gondolkodni az API-n, a refaktoráláson, a teszteken. A lényeg, hogy vannak ilyen típusú munkák, hogy sailing in the fog, ahol a TDD nem segít. Persze masterbe semmi nem ment és fog bemenni teszt nélkül, és amikor már látszik mi az irány, akkor visszajönnek a keretek. De azt jó tudni, hogy a TDD - és úgy általában a szigorú processek - az early feedback ellen hat.
Még pár példa, ami eszembe jut:
- Integrálódni kell egy másik párhuzamosan fejlesztett service-zel. Itt még esetleg alakulhat az interface, legalábbis a közös. Változhat a protocol, bármi. A gyorsabb haladás eleinte itt is fontosabb tud lenni.
- Teljesítménykritikus részek. Itt is az API előtt néha azt jobb tudni, hogy az implementáció hogyan viselkedik (ez persze megint automata teszteket jelent :))
Szóval egész nap csak
Nyilván valamit megnéztél manuálisan rajta, amiből tudod, hogy nagyjából működik. Onnantól meg, amit megnéztél rajta, ugyanazt tudnád automatizálni is, és máris van egy teszted...
Persze, de én sem TDD-ről beszéltem feljebb. Nekem sok ilyen hobbi projektem van, amik ez a kategória, és azoknál is el lehet indulni magasabb szintről lefelé. Pl a te esetedben van valamilyen feldolgozód, ami eltérő formátumú adatokat dolgoz fel. Kapásból ott van, hogy "iDataProcessor.process(String data, MIME type) -> iResult result". Aztán amikor agyalsz, hogy mit kell tudnia a feldolgozónak, akkor le tudsz írni egy scenariot, aminél megnézed, hogy bizonyos data mellett bizonyos feltételek teljesülnek e a result-ra. Ha nincs még ilyen közös result adatstruktúra vagy objektum, esetleg maga a feldolgozó többféle eltérő metódust hívogat más objektumokon, nem adatstruktúrát állít elő, akkor érdemes lehet ezeket az objektumokat a processor-ba injektálni, és első körben azon keresztül meghívni a metódusaikat, később esetleg külön metódusokat csinálni a processor-on belül, amik majd meghívják őket, stb... Én nem tudok elképzelni olyan esetet, amikor a top-down megközelítés előre megírt tesztekkel ne lenne jobb megoldás a bottom-up megközelítésnél link és az utólagos tesztelésnél. Csináltam mindkettőt, és utólag tesztelni és debuggolni nagyon macerás. Nem is beszélve arról, hogy baromi lehangoló ha az ember egész nap csak tesztel egy késznek mondott kódot azzal összehasonlítva, amikor tesztel és fejleszt is egyszerre.
Persze macerás átírni a teszteket, viszont ha nincs sok belőlük, csak ilyen magasabb szintűek, akkor az implementáció az API alatt bármilyen mélységben szabadon változhat, mégis ha valami hiba van, akkor a tesztek azonnal jelezni fogják. Annyi hátrány van az alacsony szintű teszteléssel szemben, hogy nehezebb megtalálni a hibát, és valamennyi debuggolás is szükséges hozzá, illetve messze nincs minden lefedve tesztekkel, viszont nem kell minden változtatásnál átírni a teszteket, és azonnal jeleznek, ha valami komolyabb gond van a kóddal. Ha meg már kiforrott menet közben, hogy hogyan lesz megoldva a dolog, akkor egyrészt át lehet írni az API-t a véglegesre, másrészt meg fokozatosan kialakul fentről lefelé, hogy az alacsonyabb szintek hogyan épülnek fel, és lehet azokra is teszteket írni.
Na majd egyszer írok valami cikket vagy csinálok videot arról, hogy én hogyan tesztelek, mert lehet ez így nem nagyon érthető.
Nyilván valamit megnéztél
Amúgy normálisan valóban nem deployolt alkalmazással próbálunk ki kódot. Bár a jelenlegi munkámban a deploy mint olyan értelmezhetetlen :) De a lényeg, hogy van egy test harness, és azt használjuk a fejlesztéshez is. Szóval általában teszt alapú fejlesztést csinálunk és csinálok már sok éve. De nem a klasszikus, nagykönyvi TDD-t.
Szóval általában teszt alapú
Én is valahogy így vagyok vele, már nagyon régóta nem TDD-ztem. Nekem ez a megközelítés annak idején Liz Keogh valamelyik BDD videojával jött be. Utána elkezdtem rendesen BDD-zni cucumberrel. Aztán ráuntam, hogy egy csomó plusz munka volt a feature fájlokat írogatni komolyabb haszon nélkül, úgyhogy végül ott kötöttem ki, hogy a unit tesztekre kitalált keretrendszereket használom BDD stílusban, és szinte csak átfogó integrációs teszteket írok velük, amik azt mutatják meg, hogy a kód azt csinálja, amit elvárok tőle, nem azt, hogy az implementáció egy bizonyos módon van megoldva. Az utóbbi nekem alapból érdektelen legalábbis addig, amíg nem csinál valamilyen bottleneck-et vagy ilyesmi.
Egyébként nemrég volt egy olyan ötletem, hogy a kód benchmarkolását is automatizálni kellene, és pl e2e teszteknél megmondani előre, hogy mekkora a futási idő ami elvárt. Aztán akkor pirosba menne a teszt, ha ez az idő nem teljesül. Egy test accounttal akár ugyanazt az e2e tesztet lehetne használni dev környezetben a működés tesztelésére és production környezetben a betöltési idők tesztelésére. Egyelőre ennek az egésznek a hogyanját még nem találtam ki. Azt tudom, hogy vannak terheléses tesztek, de azok inkább arra mennek rá, hogy elbír e sok felhasználót a rendszer, nem arra, hogy milyen a felhasználói élmény vele egy adott pillanatban. Ami még érdekes lehet ezzel kapcsolatban, hogy akár folyamatosan is lehet monitorozni így a felhasználói élményt pl 10 percenként egy alap tesztsort végigtolva az éles szerveren. Valami hasonlót egyébként csinálnak most is, de inkább a rendes felhasználók kéréseit loggolják az időkkel együtt, aztán azt dolgozzák fel utólag, ami legtöbbször nem azonnali visszajelzést és riasztást jelent, hanem hetekre vagy hónapokra rá megnézik a logokat, meg hogy hol volt gond. Aztán ennyivel később már nem biztos, hogy rendelkezésre áll elég info arra, hogy kiderítsék mi okozta a problémát. Az ilyen jellegű tesztelés mondjuk szerintem még nagyon nincs benne a fejlesztői kultúrában, vagy csak a nagy projekteknél van jelen. Nyilván a kis projekteknél legtöbbször nem éri meg a ráfordított időt. Ez akár meg is változhatna, ha lenne valami szög egyszerű módszer ilyen tesztek írására.
A throughputra tesztelni
Latencynél viszont nem lehet átlagolni, mert azzal pont az értékes adatot veszíted el. Alertelés pedig azért nehéz, mert vannak outlierek, amik simán belenyalnak az alert zónádba. Pl ha microsec range-be vársz egy mérési eredményt, de pont belerúg egyet a scheduler, simán láthatsz millisec időket is emiatt. Laptopomon pl voltak ilyenek, amikor láttam, hogy a processem félre lett rakva, és emiatt jelent meg ms mérési eredmény. Webes rendszereknél talán ez kevésbé ennyire éles, de ott is megjelenik. Ami miatt ez érdekes, hogy a maximum és a nagyon magas (99.9%+) percentilis mérések fognak megjelenni a jelentős többségi user élményben. Az olyanokat, minthogy átlag response time el kell felejteni, az semmit nem jelent. Azon kívül, hogy elmondhatja az ember, hogy annál szinte biztosan csak rosszabb élménnyel fog találkozni a user :) Ez az egyik probléma, hogy a maximumokra nehéz thresholdot húzni. A másik probléma, hogy az emberek nem is értik amit mérnek. Ezért ha csinálnak is hasonló teszteket, azok rosszak. A toolok többsége is, amik léteznek, rosszul mérnek és rosszul reportálnak.
Illetve van még a coordinated omission problem, amibe nagyon komoly szakik is belefutottak. Ez gyakorlatilag annyit tesz, hogy ha már ki van nyomva a rendszer szeme és nem tud újabb kérést fogadni, vagy egy adott kérés várakoztatja másik kérések kiszolgálását, akkor ezek a mérések vagy el vannak dobva, vagy kozmetikázva vannak azzal, hogy csak a request rendszerben megjelenésétől a feldolgozás végéig mérjük. Ha csak a szerver oldalon töltött időt nézzük, nagyon klassz kis grafikonokat lehet kapni. Ha belevesszük azt is, hogy mikor indult a kérés, akkor viszont egyébként jól kinéző grafikonok fordulnak át horrorba és magyaráznak nagyon komoly teljesítményproblémákat. Ha érdekel a téma, ajánlom Gil Tene latency measurement pápa How NOT to Measure Latency előadását. Ez a fickó az egyik legnagyobb koponya a szakmában szerintem, ha low-level és performance kérdésekről van szó. Ez az előadása pedig kötelező darab :)
Amit mi használtunk előző helyemen load testing kiértékelésére és prodon mérésre, az pedig egy in-house Google Dapper implementáció volt. Ennek a distributed tracing megoldásnak az az előnye, hogy by design tartalmazza a várakozásokat is (az első mérési ponttól), így pontosan meg tudod mondani a main latency contributorokat. Azt tudja nagyvonalakban, hogy nyit egy mérést (span) egy bemenetnél és lezárja a kimenetnél, így kapsz minden bemenetre egy tree of spanst. Ehhez persze minden adatot meg kell tartani, ami nagyon komoly adatmennyiség, és ha magas request mennyiséggel dolgozol, akkor ez nem éppen egyszerű. De ha ilyen alapon futtatod a load tesztedet, és a load teszt nyitja a legkülső spant, akkor már tudsz értelmes grafikonokat rajzolni, és a grafikonról a minták alapján azonnal leordít, ha valami félrement. Ezt kiértékelni persze manuális munka, de nagyon hasznos.
Szóval vissza az elejéhez: lehet thresholdokat beállítani baseline-ok alapján, de az esélye, hogy alerted lesz arányos a baseline-hoz képesti toleranciáddal. Nehéz jól belőni. Ráadásul a tolerancia megengedi a regressziót...
Ezek miatt nem tipikus, hogy erre automatizálnának a fejlesztők. Ezeket a teszteket nagyon rendszerre kell szabni, érteni kell mit és hogy kell tesztelni és hogy mit csinál a rendszer. Ez pedig mind időigényes, komoly tapasztalatot igényel és ezért drága.
Szóval a latency mérés automatizálása egy rabbit hole :)
Köszi! Nekem is úgy tűnt
Idő és pénz
Te hány fölösleges tesztet írtál meg, mire rájöttél a ezekre? Mennyi idő ment el vele feleslegesen? Mindezért vállaltad a felelősséget? Hány juniornak kellett elmagyaráznod, hogy hol és mit szabad tesztelni és mit nem?
Pont erről szól az, amit fentebb állítok, hogy a komplexitás egy része mesterséges, azaz a programozók csinálják saját maguknak, és nem a feladatból következik. Érdemes lenne felmérni a projekteket, hány ilyennel vannak tele.
Te hány fölösleges tesztet
Szerintem meg keveri a
Pont ezért nem (sem) olyan egyszerű a fejlesztés
Ha egyedül dolgozik valaki, sokkal nagyobb az esélye, hogy ha más fogja olvasni / módosítani a kódját, annak nem fog tetszeni. Vagy "hosszabb", vagy "rövidebb" fv-eket szeretne látni, vagy több, vagy kevesebb osztályt, de biztosan lesz eltérés a saját szájízéhez képest.
Nem új, de szerintem jó támogató eszköz erre a PHP Mess Detector. Jól konfigurálható, használatával nagymértékben csökkenthető a codereview idő- és módosításigénye. Persze ez se 100% - os "védelem", és ugyanígy (szerintem se) gyakorlatban nem feltétlen jó szentírásnak venni clean code, solid, stb alapelveket. Iránynak nagyon jók, de valóban, ha tökéletesen meg akarsz nekik felelni, akkor a ló túlsó oldalán landolsz.
Hol?
Mert nem tudják. :)
Nincs az a logikai (összefüggés-) rendszer, amivel gondolkodva egyértelműen és kizárólagosan meg lehetne állapítani, hogy az adott kódot pontosan hogyan és milyen teszttel kell tesztelni.
Amikor olyan fejlesztők is vannak a világon, akik azt mondják, hogy "nem is kell automata teszt, felesleges", akkor mégis milyen szabályrendszer tudná meghatározni, hogy hol és hogyan? (Ha egyáltalán az sem mindenki által elfogadott, hogy kell-e.)
A saját szakmai véleményem az, hogy mindent kell tesztelni, de azt leginkább a megvalósítandó célok és az elvárt működési és minőségi elvárások határozzák meg, hogy mit mivel érdemes.
Unittesztelni olyan osztályokat érdemes, amik
- jól szervezettek (jól körülhatárolt, aránylag szűk működést valósítanak meg)
- emiatt könnyen "kiemelhetők" a környezetükből
- fontos, hogy önmagukban precízen működjenek (vagyis fontos, hogy pontosan és szigorúan azt csinálják, ami a specifikációban van)
- későbbi bármilyen módosításuk esetén azonnal (bőven élesítés előtt) tudni akarjuk, ha károsan módosult a működésük
Minél több feltétel igaz ezek közül az adott egységre, annál inkább érdemes egységtesztelni. Persze ha pl tele van (nem kívánatos) külső függőségekkel, akkor sokkal nehezebb / több munka utólag tesztet írni, mert köré kell építeni azt a (mock) "világot", amiben üzemszerűen működhet. De hát gagyi kódot gagyin lehet tesztelni is... (Ezért is vagyok TDD "párti", ha megtehetem.)
Soha nem írtam mindenre unit
Hogy mondjak példát is, amikre a közelmúltban írtam unit tesztet:
- tailored hashtable implementációra
- objektum szerializációja rollup/rolldown esetekre
- listener implementáció kontraktjaira
Amire nem készítettem, mert elegendő volt az IT:
- Egy globális szinkronizációs mechanizmus service szintű osztályára (de azokra igen, amin a logika függ)
De nincs polcról levehető okosság erre se. Gondolkodni kell.
Ez a kérdés olyan, hogy mennyi idő kellett ahhoz, hogy megtanuld mikor kell elöl és hátultesztelő ciklust írni? Mikor kell lefelé számláló ciklust írni? Mikor használunk fort, whilet, mikor foreachet? Ezek értelmetlen kérdések :)
A kérdések nem erre
Nem tudom pontosan mennyi idő, ami biztos, hogy több év volt. Szabadni mindenhol szabad tesztelni, csak pl egy todo listnél nincs értelme részletekbe menően e2e teszteket, integrációs teszteket, unit teszteket írni, mert a végén több lesz a teszt, mint maga a kód. Ha meg egy hiba átcsúszik valahogy a tesztelésen, akkor az egy kis kellemetlenség csak a felhasználóknak, és küldenek egy bug reportot róla, ha nagyon zavarja őket. Utána persze a report alapján máris lehet pótolni a hiányosságokat, és hozzácsapni egy új tesztet, ami azt a scenariot csinálja végig, aztán kijavítani a hibát. Ezzel szemben ha komplex a rendszer és/vagy kimondottan fontos, hogy tökéletesen működjön, akkor akár érdemes többféle mérettartományt átfogó tesztet is írni hozzá, pl e2e, integrációs és unit teszteket, illetve részletekbe menően kell tesztelni, pl minden egyes hiba típusra, ami előfordulhat, nem csak a gyakoriakra. Aztán még az is előfordulhat, hogy a projekt egyik része fontosabb, a másik meg kevésbé fontos, és ezért eltérő módon kell tesztelni a kettőt. Szóval szerintem nem olyan egyszerű erre valami általános tanácsot adni, hogy mikor hol és hogyan teszteljünk. Ez is egy eszköz, aminek meg kell szokni a használatát, aztán egy idő után az ember rájön, hogy neki hogyan fekszik a legjobban és milyen szituációban hogyan használja. Szerintem itt is igaz, hogy nincs golden hammer. Bár ez is csak egy vélemény a sok közül, mert Pepita láthatóan megoldja unit tesztekkel az összes projektjét.
Nem igazán
Ezen kívül pár éve megismertem a Seleniumot, és rögtön rá is kaptam olyan dolgok tesztelésére, amiknél nem igazán az a fontos, hogy hogyan és milyen logikával (részleteiben) jutott pl a user A - ból B - be, hanem az, hogy odajutott. Természetesen a kettő vegyítve jön be nekem igazán: ami önmagában tesztelhető backend, azt lehetőleg TDD fejleszteni, ha nem, akkor utólag unit tesztelni, ami viszont inkább működési és / vagy frontendet is érint, azt jobb "megnyomkodni".
Mondjuk a megtetszéshez az is hozzájárult, hogy első etupként a meglévő, élesítésenként kötelezően (tesztelő kolléga által) végrehajtott checklistet kódoltuk végig, és ami addig egy embernek min 1 óra volt, az Seleniummal 5 perc lett... Persze volt az elején rengeteg gondunk vele, de az mindig van, amikor újat tanulsz / vezetsz be.
Ez nem így van, jelenlegi
Ilyesmire jobb csinálni egy db fixturet ezzel: https://phpunit.de/manual/6.5/en/database.html, aztán arra lefuttatni a kódot és megnézni, hogy a kívánt eredményt adja e. Természetesen nem a táblában turkálva, hanem a kód metódusaival, amik az SQL-t gyártják. Úgy baromi lassú, ha minden testcasenél újra felépíted a táblákat meg hozzácsapod az adatot. Inkább úgy érdemes megoldani, hogy van egy fixture, amit az összes teszt használ, és amit az elején betöltesz. Utána tranzakcióba rakod, amit éppen tesztelsz a végén meg rollbackelsz, hogy ne változzon a fixture. Ehhez előfordulhat, hogy refaktorálni kell a kódodat, ha tranzakció kezelés van benne, de szerintem megéri, mert így elfogadható a teszt sebessége, és napi többször is simán le lehet tolni a teszteket. Esetleg még tovább lehet gyorsítani, ha verziózod a fixturet és pl a teszt adatbázisod nevébe beteszed a fixture verzióját. Igy nem kell minden teszt futtatásánál felépítened az adatbázist, ami az egyik bottleneck it.
Nekem is bejön az e2e, mert sokkal felhasználó közelibb. Aztán ha van user story, akkor az alapján kapásból lehet e2e teszteket írni és gyorsan el lehet indulni az egész projekttel top-down irányba. Utána ki lehet egészíteni integrációs tesztekkel, unit tesztekkel az egészet attól függően, hogy mennyire akarsz alapos lenni.
Ez tök jó cucc,
Illetve amit előzőleg nem írtam, és eleve megkérdőjelezi a PHPUnit használatát: van jónéhány külső függőség is, ami közvetlenül összefügg (id-k formájában) a saját és a szinkronizált db-adatokkal. Pl auth sem saját van, hanem webservice, és még néhány hasonló nyalánkság, amik miatt szintén tud bukni a mutatvány. Amire van teszt, annak van mögötte (mysql) db is *, amire nincs, arra többnyire a túl sok külső függőség miatt nincs (és itt a külső függőségek közé sorolom a hosszan összefüggő / nagy mennyiségű db rekordokat is).
Van, amit ezek közül sajnos e2e-vel sem lehet "végignyomkodni", mert a folyamatnak része pl egy mq üzenet elküldése, majd x idő után egy másik rendszer szintén mq-ban "válaszol", itt is van egy matek, majd ezután y naptári idő múlva, megint egy mutatvány. :)
Azért érdekes ez a projekt, mert több másik rendszerrel együtt kell működni, amik szintén nem önmagukban működő cuccok. Viszont ezek miatt bizonyos részek nagyon nehezen tesztelhetők.
SZERK: (*): Tudom, hogy ez is egy kvázi felesleges külső függőség (működik-e a teszt mysql szerver), de lényegesen egyszerűbb táblákat másolni így egyik db-ből a másikba.
Mock
Előző projecten készítettünk az ilyen külső függőségekből in-memory és deployolható mockokat, amiket a teszt fel tudott magának programozni, hogy milyen inputra milyen választ adjanak. Így gyakorlatilag ezeket használtuk fejlesztés közben, CI-ban, és a mockolt teszt környezetekben is.
Ami még előnye ennek a módszernek, hogy ezzel tudsz negatív eseteket is tesztelni (timeout, NACK, hibás válasz, bármi error), hisz nem kell elrontani egy szolgáltatást egy környezetben a teszteléshez, amin mások esetleg szintén függnek.
Én ilyesmi teszteket írok a pet projectemen is, és így egyáltalán nem kell a külső függőség a fejlesztéshez:
givenOrderFilled
paraméterei nem egyértelműek azonnal), de a lényeg látszik. És itt is több egyedi azonosító mozog a teszten belül, de az meg se jelenik a teszt kódjában, mert a fixture elfedi. DB-ben a rekordokat is fel tudod ugyanígy építeni, akár tesztből kapott azonosítókkal is.Meg csak akkor van értelme, ha a teszteket más írja, mint a prog
1. Kapsz egy feladatot
2. Megérted
3. Megtervezed (lebontod) egységekre, hogy mikből fog összeállni az egész
4. Az egyes egységeket is megtervezed, mi mit hol hogyan csináljon.
5. Elkezdesz tesztet írni, az első egységet (mondjuk) be kell tölteni (new valami)
6. Futtatod a tesztet -> elszáll hibával: class not exists.
7. Létrehozod a class-t.
8. Futtatod a tesztet: success.
9. Beírod a tesztbe a legelső dolgot, amit az egységnek kéne csinálnia.
10. futtatod: fail / error, mert nincs kód.
11. Így ismételgetve mész végig, apró lépésenként.
Miért is ér ez sokat?
Mert míg a tesztet írod, addig feladat-megértés / vizsgálódás szemszögből nézed a dolgot, olyan tesztet írsz, ami a specifikációt fedi le (illetve egy kis szeletét).
Elsőre persze failel a teszt, de utána lényegesen gyorsabban írod hozzá a sokkal jobb kódot, mert már egy másik szemszögből is átnézted / átgondoltad a problémát.
Emiatt (klasszikusan) TDD-ről akkor beszélünk, ha egyszerre készül a teszt és a kód, és ezt ugyanaz az ember csinálja.
Persze szokták a TDD-t egy kalap alá venni a PHPUnit-tal, de nem ugyanaz, sőt, unittesztelni is lehet utólag / másképp, nem csak "TDDézve".
Más kérdés, hogy ha "majd utólag megírom rá a teszteket" hozzáállás van, akkor könnyen előfordul, hogy elferdül a teszt, hogy lefedje, de egyrészt még így is nagyobb a valószínűsége, hogy észreveszi a fejlesztő a hibát, másrészt az ilyen utólagos teszt írás nem TDD.
Valódi (fizetett, nem hobby) munkában mennyit fejlesztettél TDD-ben? Mert én azt szoktam kritizálni, amivel már szereztem kellő mennyiségű tapasztalatot.
A ráfordítandó időről pedig annyit, hogy nekem már volt szerencsém csaknem ideális TDD - ben fejleszteni, és max 10% - al volt több idő, mint minden teszt nélkül ugyanezt lefejleszteni. Cserébe egy lényegesen tisztább kód született, 100% - os lefedettséggel. :)
Mondjuk ehhez hozzá tartozik az is, hogy sokkal több időt vitt el (az egészből) a teszt írása, de mire odajutottam, hogy egy - egy teszt mögé tehettem a kódot, akkor azon már alig kellett gondolkozni, hihetetlen gyorsan ment.
Sokan nem szeretik ezt, mert - főleg eleinte - sokáig "semmit nem csinálsz" (vagyis működő, üzleti kódot nem), de aztán a vége felé egyszer csak "kipottyan" a kész kód, nagyon rövid idő alatt.
Sokan nem szeretik ezt, mert
Ja nekem is ugyanez az életérzés szokott lenni a TDD-vel, hogy eleinte úgy érezm, hogy semmit nem csinálok, és csak visszafog, mert nem a lényegi, logikai résszel foglalkozom. Utána viszont azt is ugyanolyan egyszerű belefejleszteni, mint a new class-t kb. Szívesen használtam a TDD-t, de sosem szerettem karbantartani a unit teszteket.
Karbantartani én sem :)
Nehéz megmondani az alapján,
- "a programkód növekedésével arányosan nő a hibák száma". Ezek szerint nem szabad teszteket írni, mert azokban is hibázhatunk.
- "drágább a projekt elkészítése és karbantartása" - Szóval ne írjunk teszteket, mert az plusz idő és azokat is karban kell tartani. Tesztek nélkül viszont jóval nehezebb elkészülni és karbantartani, mert párszáz sor felett a debuggolásra jóval több idő megy el, mint az automatizált tesztelésre.
- "a rugalmasságot is csökkenti" - Ezért nem szeretem én sem a TDD-t annyira. Elég macerás minden kis módosításkor ezer helyen beleírni a tesztekbe.
- "csak akkor van értelme, ha a teszteket más írja, mint a programkódot" - Ez nem igaz. Ennyi erővel ha begépelsz egy szöveget, és újra olvasod, akkor nem fogod megtalálni a hibákat benne, mert ugyanúgy gondolkodsz, mint amikor elgépelted. Talán az egyetlen eset, amikor ez igaz lehet, amikor a user interface-t vizsgáljuk, hogy mennyire könnyen használható. Talán az egyedüli tesztekkel kapcsolatos dolog, aminél az ilyesfajta szűklátókörűség szóba jön, az az A/B testing.
- "az integrációs tesztek viszont fontosak" - Én is jobban szeretem őket, mint a unit test-eket, már egy ideje csak ezeket használom. Viszont ez inkább tapasztalat függő. Ha valaki nehezen látja át több osztály interakcióját, akkor jobb ha unit test-ekkel áll neki a dolognak. Én jobb szeretem az integrációs teszteket, mert bár nem teljes a coverage, de nagyjából azok is lefedik a projektet, és nagyobb lépésekben lehet haladni velük, illetve a karbantartásuk is egyszerűbb, mint a unit test-eknek.
Tesztek nélkül viszont jóval
Ezt alá tudnád valamivel
Ezért vannak a cikkekben
Vagy talán mert sosem olvassa vissza, amit leírt. Én van, hogy 2-3x is elolvasom, amit írok, aztán javítom a hibákat, vagy néha átírom az egészet, mert le tudom írni ugyanazt fele annyi sorban is, ha egyszer már átgondoltam.
Persze, csináltam már mindkettőt, és ezt tapasztaltam.
Egyébként a legnagyobb előnye az automatikus tesztelésnek a debuggolással szemben, hogy kevesebbet kell keresni, hogy hol a hiba. Már ha 5 perce még zöld volt a teszt, aztán pirosra vált, akkor nyilvánvalóan abban van a hiba, amivel az elmúlt 5 percben foglalkoztál. Ezzel szemben a kézi tesztelés sokkal időigényesebb, és emiatt nem csinálják kellő gyakorisággal, vagy ha igen, akkor csak a nagyon alapvető teszteket csinálják meg. Az első esetben nem az elmúlt 5 percben írt kódban kell keresni a hibát, hanem az elmúlt 1 hónapban írtban. A második esetben majd mondjuk 1 hónap múlva kiderül, hogy valami nem úgy működik, mint kéne, csak nem lett tesztelve, és ugyanúgy az elmúlt 1 hónap kódjában keresgélhetsz. Ezen kívül az is előny, hogy amíg futnak a tesztek (ha hosszúak), addig te csinálhatsz mást.
Amúgy az egész felvetés, hogy az automatizált tesztek rosszak lennének szembe megy a szakma lényegével. Azért programozunk, hogy automatizáljunk valamilyen ismétlődő folyamatot, és ne kelljen embereknek dolgozni rajta. A tesztelés is sűrűn ismétlődő folyamat, mert csak ezzel tudjuk biztosítani, hogy nem törtünk el valamit, amikor hozzányúltunk a kódhoz. Emiatt több, mint nyilvánvaló, hogy érdemes automatizálni a tesztelést is, és ha kellően gyorsak a tesztjeink, akkor napi többször lefuttatni őket, illetve legalább minden commit előtt.
Rossz példa
Az első "példa" amiatt (is) hibás, mert nem definiál semmiféle célt, hogy
- miért származik a második az elsőből,
- mi a művelet, amit szeretne a bemenő paraméteren végrehajtani,
- miért szükséges az eltérő input típus.
Ezen kívül nincs visszatérő érték, vagyis 2 void csinál két eltérő semmit két eltérő inputból kimenet nélkül, vajon szükség van egyáltalán öröklődésre?...
Tartok tőle, hogy az első "példa" egyetlen sorral leírható:
- Azért, mert nem csinálok vele semmit? Akkor mire ellenőrzök?
- Egyszerű fv-ek esetében legtöbbször elég, ha olyan típusú a paraméter, amit várok. OK, ha pont osztani kell vele, akkor ne legyen 0. De ilyen fv-t meg felesleges írni.
function osztas_tipus(int $szam)
fv - edre már a szerkesztőd is fogja jelezni, hogy oda egy egész számot várnak. Így kell a legkevesebbet fejben tartani.Szóval ha ráírom a rollerre (deklarálom), hogy csak ember jöhet, akkor azzal meg is kímélem "a későbbi felhasználókat" a kellemetlenségektől. Ha "nem azt a típust szeretné használni", akkor nem arra a függvényre van neki szüksége.
Ha lehet, a jövőben tényleg konkrét példa legyen, kissé szélesebb látószöggel.
Érdekes...
- Semmi sem tökéletes. :)
- A linkelt cikk 4 éves, és PHP 5.5 - nél megáll
- Hivatkozik egy másik "cikkre", miszerint TDD - vel felesleges a "típusozás". Ajjaj, a kettőnek kb semmi köze egymáshoz.
- PHP 7.x alatt típus deklaráció van már, ez több, mint ajánlás, és szerencsére return type-ra is van (vagyis ha egy fv eredményére pl foreach-elni akarsz, nem kell félned, hogy nem várt esetben null-t vagy egyéb noniterable értéket kapsz tőle)
Egyebekben egyetértek Inf3rnoval: mérd fel (és valódi mérés legyen), csinálj belőle tanulmányt (többedmagaddal, mert egy fecske nem csinál nyarat), támaszd alá megfelelően, és meglátjuk milyen hatással lesz.
Azt gondolom, hogy ha valamiről 5-10 ember nagyon hasonlóan gondolkodik (és mindannyian a saját tapasztalataik alapján), 1 pedig egész másképp, akkor nem feltétlenül a tíznek kell érvekkel meggyőznie az egyet, hanem fordítva.. Persze az is egy lehetséges megoldás, hogy meghagyják az egyet a saját tévhitében, "ő baja" gondolattal.
Abszolut egyetertek a
Miből vontad le a
Mi az az SQL daraboló amúgy? Tokenizer?
De tessék, mondok egy példát. Nem PHP, mert nem abban dolgozok. Java5 előtt nem volt concurrency package a Java API-ban, csak wait/notify stb. De nem volt még csak memory model sem. Java5-től van, és egyre fejlődő az eszközkészlet. Egyre bonyolultabb, és egyre hatékonyabb használni. És nem mellékesen nem a hozzá nem értő emberek írta kódok okozta bugokat kell vadászni, hanem expertek írták. Úgyhogy egyszerre lett komplexebb, hatékonyabb és biztonságosabb a többszálú programok készítése Javaban. Ez egy elég erős példa, ami cáfolja az általános állításodat.
Hajrá :)
De ugye most nem kezdesz el amellett érvelni, hogy felesleges képezni magunkat és újakat tanulni?
Kicsit olyan ez, mintha egy
Én csak azt nem értem továbbra sem, hogyha Gábor ennyire ellenzi az absztrakciókat, meg az általánosítást nyelvi eszközöknél, külsős könyvtáraknál, keretrendszereknél, akkor miért egy olyan szakmát választott, ami arról szól, hogy automatizálunk dolgokat, és az egészet absztrakciókkal fedjük el?! Vágom, hogy ennek van egy olyan vonala, hogy azt akarja, hogy a kódja ne függjön szinte semmitől, amit nem kontrollál, de akkor meg nem webfejlesztésben kellene részt vennie, hanem valami katonai vagy banki rendszereket írni, ahol ez valószínűleg követelmény, de talán még ott sem veszik ennyire szigorúan a dolgot... Az, hogy használunk egy keretrendszert arról szól, hogy más dolgozott helyettünk, ami jó, mert időt spórolunk, de lehet rossz is, ha nem megfelelő minőségben végezte el a munkát. Azért a nevesebb keretrendszereknél, könyvtáraknál általában nincs ilyen gond, illetve új nyelvi feature-ök bevezetésénél is szinte kizártnak tartom. Szerintem a programozók túlnyomó többsége megdöbbentőnek találná ezt a hozzáállást, alkalmazni valakit ilyen megközelítéssel meg biztosan nem alkalmaznának. A cégek többségénél a határidő, ami szent, és nem a hibátlan kód, és azzal, hogy valamit nulláról megírunk simán kicsúszhatunk többszörösen is a határidőből. Ezért van az, hogy gyakorlatilag minden cég inkább fizetne egy működő keretrendszerért az adott témában, mint hogy házon belül lefejlessze ugyanazt. És ez nem csak a szoftverfejlesztő cégekre igaz, pl itt egy helyi cégnek volt egyedi rendszere, ami teljesen jól működött, aztán olyan 5-10 éve lecserélték az egészet SAP-re. Az átállás nem volt annyira egyszerű, de végső soron most már csak az üzemeltetéssel kell foglalkozni, és már nem dolgoznak szoftverfejlesztők a cégnél, mint előtte. Nem tudom, hogy mi a mérlegük ezzel kapcsolatban, de úgy sejtem, hogy hosszú távon jobban megéri így, mint saját fejlesztőket fizetni havi bérben, különben nem lépték volna meg. Nem érdekes, hogy nekik jobban megérte függeni egy másik cégtől, mint hogy saját maguk csinálják meg azt a munkát, ami a cégnek egyébként abszolút nem profilja?
Ugyan a régi társaságból már
2000-ben jött a zseniális ötlet: picsába a fejlesztőkkel, majd a külsősök megoldják.
Tíz év elteltével ezeket a külsősöket is cserélték másik külsősre, de még mindig ugyanaz a helyzet, ha jól vagyok informálva: ugyan külsős a fejlesztő, de a cégnél dolgoznak helyileg, épp csak, mivel nem érdekük igazán a cég jóléte, mert ha ez nincs, lesz más ügyfél, a munka minősége is olyan, amilyen...
Amíg volt normális, saját munkaerő, addig kicsit más volt a hozzáállás mindenhez.
Csak egy példa: a 2000-es vadiúj rendszerrel úgy 3-4 évnyit esett vissza a szolgáltatások színvonala és közel két évbe tellett, mire a korábbi szintet hozta az új csoda...
Gondolom cége válogatja, hogy
Kicsit olyan ez, mintha egy
Katonaihoz nem volt
Én a külsős dolgoktól való függésre írtam, hogy szigorúan veszik, nem az absztrakció hiányára. Egyébként biztos vagyok benne, hogyha párszáz sornál hosszabb kódot ír a Gábor, és nem valami ocsmány spagetti az egész, akkor nála is ugyanúgy megjelennek legalább valami kezdetleges formában az absztrakciós szintek, pl. egymást hívogató függvények formájában. Az egész a DRY principle-ből egyenesen következik, mert ha újrahasznosítasz valamit és beteszed egy függvénybe, akkor máris lesz több hívó és egy hívott függvény, és az utóbbi szinte biztosan alacsonyabb szintre kerül, mint amik hívják. Ezért nem is értem, hogy miért szidja ennyire az absztrakciót. Talán olyasmire gondol, hogyha találsz egy általános mintát, és arra csinálsz valami általános könyvtárat, akkor az rossz, mert nem fed le minden ritka esetet. De ezt meg problémája válogatja.
Pedig linkeltem feljebb a
class klassz {
function klassz() {}
}
?>
Analógia: C-ben nagyon sok lehetőség nincs meg, ami C++-ban. Mégsem írnak át minden C-ben készült programot C++-ra. Miért nem? Sőt, fentebb hoztam példát arra, hogy egy projektet C++-ról írtak vissza C-re, bár persze ez nem általános.
PHP-ban egyébként nem volt ilyen jellegű újítás, mint amit leírtál.
A cégeteknél Java-ban dolgoztok?
Egy felmérés szerint a startupok 90%-a megbukik, azaz tíz esetből kilencszer minden erőfeszítésed, ami arra irányult, hogy future proof legyen a munkád, teljesen felesleges volt. Érdemes-e tehát nagy eszközkészlettel és bonyolult eszközökkel dolgozni? Tízből kilencszer senki sem fogja átvenni a munkát tőled.
PHP4 tudás, és azt, hogy ez
Amit a javas példára válaszoltál, az ékes bizonyítéka annak, hogy miért nincs értelme szakmai dolgokról vitatkozni veled. Egy általad teljesen ismeretlen példára is ráhúztad ezt az exponenciális költeményed. Azok után, hogy leírtam, hogy az mennyire erősen cáfolja az állításodat. Legalább megnézhetted volna, hogy miről van szó, akkor nem írtál volna le ilyet... Ha gonosz akarnék lenni, akkor azt mondanám mutasd meg, hogy a wait/notify párral, és egy elemi eszközkészlettel hogy implementálnál egy olyat, amivel egy (vagy több) szálat blockolni tudunk, amíg N másik szál el nem ér egy meghatározott pontra a feldolgozásban. De nem akarok gonosz lenni :) A lényeg, hogy 3 sornál többet kellene írnod, és szinte biztos lenne benne hiba.
Egyébként igen, javaban dolgozok már egy jó ideje, és már lassan 6 éve nem webes rendszereken.
Ha te nem tudsz modernebb eszközkészlettel hatékonyabban dolgozni, mint a limitáltabb régivel, az sajnálatos, de nem az eszközöket minősíti. Kiváltképp, ha a veled ellentétben azt ténylegesen használók ellentétes véleményen vannak.
»Ez valószínűleg így van, ha
És ugye pont ez volt az állításom, amibe belekötöttél...
Naná, hisz eleve ez a
Én értettem elsőre is, te nem
+1
Ugye? Jóval egyszerűbb úgy,
Pláne ha még
Az tuti. :D
Hát nem tudom, te milyen
ui: abba belegondoltatok már, hogy a magasszintű nyelvek végsősoron csak keretrendszerek az assembly-hez? :D
milyen assembly
A linkelt könyvben (vagy a 2. részében?) is van rá példa, hogy adott hosszúságú memóriaterületre másolgatod mondjuk a leütött billentyűk ASCII kódját, majd kiíráskor ezeket szép sorban másolod a képernyőmemória megfelelő részébe. A 0 byte jelenti a "string" végét. :)
Lehet olyat is, hogy ' - ok közé a kódodba (adatterületre) a szöveget írod, és a fordító az ASCII - vel fogja menteni, de ettől még a te programodnak kell kezelnie (kb byte-onként) a továbbiakban. Talán ez lehet a hasonló? :)
Nézzünk pár példát:
- PHP: nem jön létre hosszú távon újrahasznosítható byte kód, részben azért is, mert "futásidőben" dől el, hogy mi kerül fordításra (pl if - en belüli require). Így nincs is nagy jelentősége, hogy mennyire optimális a fordítás, gyakorlatilag annyi a cél, hogy egyszer le tudjon futni. -> tuti, hogy ha ugyanazt assembly-ben írnád meg, sokkal kevesebb lenne a byte kód és gyorsabb a futás (és egy webalkalmazást kb 30 évig fejlesztenél).
- JAVA: itt már van byte kód, de nem közvetlenül a processzor utasításkészletére, hanem egy köztes környezetre, aminek egyik fő feladata, hogy a nyelvben írt kód egyáltalán ne függjön a gépi kódú lehetőségektől. -> köze sincs a (forrás-) nyelvnek az assembly-hez.
- Delphi (Object Pascal): na ez már egy csöppet közelebb van, mert "ugyanolyan" exe-t is tud, mint egy assembly fordító, sőt, lehetőség van benne assembly-ben is megírni kódrészeket, ezeket közvetlenül fordítja. Annyiból viszont mégsem hívnám keretrendszernek, mert egyáltalán nem szerepel a céljai között az, hogy az assembly nyelvű programozást támogassa.
- C, C#, stb: szintén kicsit közelebb vannak a procihoz, de nincs tapasztalatom bennük, úgyhogy inkább kihagyom.
Összességében elmondható, hogy ma már kevés olyan magasszintű nyelv van, ami közvetlen futtatható gépi kódra fordít, de még ezek sem nevezhetők assembly-keretrendszernek szerintem. De a felvetés érdekes. :)
Assemybly string:
asm vs hlasm
Haladunk a korral, rendben van, de ezt azért nem hívnám hagyományos Assembly-nek, mint ahogy ők sem. :)
Viszont érdekes, jó a cucc.
De ebbe inkább nem megyek
Készítem a popcornt. :D
Bonyolultabb kódok, bonyolultabb feladatok
Nosztalgikus hangulatba kerültem a topik kapcsán. Ha visszaemlékszem, akkor 10-15 évvel ezelőtt meg voltam győződve arról, hogy amit mi csinálunk a cégnél az nagyon bonyolult, és igen összetett folyamatok vannak benne. És azt gondolom, hogy az adott környezetben ez még igaz is volt. Akkor még a PHP-t a világ legjobb nyelvének tartottam.
Megmosolyogtat, ha ma visszagondolok arra, hogy akkor extra ficsörnek tekintettük, hogy más cégektől kaptunk XML fájlokat, illetve adtunk nekik válasz XML-eket.
Ezzel szemben ma már nem is feltétlen kell tudnom, hogy kivel hogyan kommunikálok a „sok absztrakció miatt” el van ez előttem rejtve.
Sokkal bonyolultabb feladatokat oldunk meg ma, mint 10-15 évvel ezelőtt. Elsírnám magamat, ha ugyanabban a környezetben kellene megint mozognom, mint akkor. És remélem, hogy 15 év múlva még kényelmesebb lesz a környezet.
Biztos lesz valaki majd akkor is, aki elmondja, hogy Lambda-kalkulussal is mindent meg lehet oldani, és nincsen hasznuk a többség által hájpolt parasztvakításoknak… :)
Biztos lesz valaki majd akkor
Hát abban tutira nem lesz hiány. :D
Furcsa. Én örülnék, ha újra
Ezt a mostanit nem annyira.
Nem véletlen, hogy akkor net nélkül többet tanultam egy hét alatt, mint mostanában egy teljes év alatt.
A net a tanulás legnagyobb
Az egy más téma.
Ha az ember valamit kedvvel, lelkesedéssel csinál, azt csinálja nettől függetlenül.
Ha annyira érdekelne ma is a dolog, mint akkoriban, akkor a net egyéb rejtelmei nem vonnák el a figyelmem a tanulásról.
El tudod képzelni, hogy nulla orosz tudással, ruszki dokumentációkból bányásztam ki érdemi infókat? Nem sokat, de még ilyesmire is képes voltam, annyira érdekeltek a dolgok.
Volt egyfajta hangulata: fehér köpeny, légkondis, nyáron is hideg gépterem és a lyukkártyákból következően viszonylag lassú tempó... nem az eszetlen hajtás, a legyél kész tegnapra a holnapival, hiba nélkül. És hát nem volt jellemző a sok ezer-tízezer soros kód sem.
Ja vágom. Nézegettem
Hm?? Milyen kocsikban?
Gondolom az összesben. Bár
Van egy olyanom, hogy ez ma
Azért a lyukkártya az messze nem mechanikus dolog volt.
A nagyon régi olvasók úgy működtek, ha jól emlékszem, hogy drótszálakból készített kis kefék voltak a lyukkártya fölött és amikor lyukra futott a kefe, akkor rövidre zárt egy áramkört a kártya mögötti érintkezővel és ennek a jele ment tovább a gép felé.
Az újabbak, amikkel én is dolgoztam, már optikai alapon működtek: átvilágították a kártyát és ahol lyuk volt, azt a mögötte lévő fotodióda érzékelte.
Wikipedia szerint nem csak
Hát... igen, végül is az is
Szövőszékről valahogy egy Hollerith nevű úriember neve ugrott be, arról meg a Hollerith-konstans, de mi a fene lehet az? (Google nélkül tudja valaki? :D)
Passz. Wikipedian olvastam
FORTRAN-ban a szöveges
Ha még jól emlékszem, Hollerith készítette az első lyukkártyás szövőgépet.
Basszus... ha tudom, hogy
( :) )
Szerintem ne aggódj, nincs
:) nem olvastam végig, csak
Szeretnénk már végleg lezárni