ugrás a tartalomhoz

Már azt se tudom, melyik végén fogjam meg... (OOP "tervezés")

mind1 valami név · Jan. 15. (K), 23.32
Megint elővettem kedvenc gumicsontom, a router logok feldolgozásának problémáját.
Nem tudok vele még elindulni sem igazán. Procedurális megközelítéssel nem lenne gond, kismillió if-then-else, néhány regex, oszt jónapot.
De OOP használattal...

Amit kitaláltam, az eleve rossznak tűnik, mert nem tudom úgy megfogalmazni a dolgokat, hogy objektumok, amelyeknek vannak tulajdonságai és viselkedése, mert jelen esetben max. a log sorait tudom elképzelni efféle objektumként, amiből lehet n+1 féle, közös ősből származtatott osztályt gyártani, épp csak felesleges.
És a feldolgozás nem része a sorra épülő osztály viselkedésének, azt valahogy nem tudom összepárosítani vele.

Ha a másik végéről indulok neki, hogy
ggyártok egy osztálynak nevezett elemet, ami példányosításkor kap
1. egy iterátort (megnyitott input file leginkább), aminek az elemein végig lépked
2. meg egy feldolgozó objektumot, aminek a metódusait hívogatja minden egyes elemnél (1. válogat -> kell-e foglalkozni az iterátorból jövő elemmel, ha igen, akkor mondjon rá egy típust, 2. parse-olás - az előzőtől kapott érték alapján feldarabol, 3. filter - a feldarabolt sort a típusa alapján ellenőrzi, hogy kell-e egyáltalán, 4. kigyűjti belőle az adatokat és a típushoz tartozó tárolóba pakolja, 5. loop, 6. vége az iterátor adatainak, visszaadja a begyűjtött adatokat)

Akkor meg ott akadok el, hogy ezt tisztán procedurális megközelítésnek tartom, szinte kizárólag a szintaxis kedvéért használok OO eszközöket.

Ráadásul az adatok tárolásának a helye sem tűnik jól meghatározhatónak, mert ebben a felállásban kb. egy globális lista változóban kellene elhelyeznem sok dolgot úgy, hogy a lista elemei egy-egy komplexebb adatszerkezetet hordoznak - minden feldolgozandó sor típushoz egyet-egyet (persze látszólag DI-t használva adnám át a feldolgozó objektumoknak ezt a tároló objektumot, de ettől még úgy érzem, ez is csak egy globális változó marad)

Ennyiből érthető egyáltalán, hogy mi bajom vele és mit akarok?
Hogy kezdjek neki?


Update 1.: ami kimaradt a fentiekből, hogy (ahogy egy kommentben írtam) nem a programra van szükségem, csak "tanuló projekt" lenne. Viszont mindezt az újrahasznosíthatóság jegyében valahogy úgy képzelem, hogy több önálló modul/osztály, amibek a tényleges működtetéséhez szükség lesz egy user interface-re, ami lehet akár parancssori, akár egy webes vagy hagyományos GUI. Ami számomra különösen nehézzé teszi a dolgot, hogy OO elvekről olvastam viszonylag sokat régebben, amikre ezekből emlékszem, azt szeretném betartani, de pont az ilyen feladványok esetében nem működik a dolog.
 
1

Csináld meg procedurálisan,

inf3rno · Jan. 16. (Sze), 00.35
Csináld meg procedurálisan, ha csak úgy megy. Gondolom el akarsz készülni vele ahelyett, hogy hónapokig csak OOP-t tanulnál mindenféle gyakorlati haszon nélkül. Később refaktorálhatod és csinálhatsz ojjektumokat, ha mégis megmaradna ez a fétised.
2

Hét éve kezdtem neki először.

mind1 valami név · Jan. 16. (Sze), 00.43
Hét éve kezdtem neki először. Szerinted szükségem van rá? ;)
Ebből már csak az OOP lenne az érdekes.
3

Ja hogy ez ilyen betanulós

inf3rno · Jan. 16. (Sze), 03.19
Ja hogy ez ilyen betanulós projekt. Az más. :D
Ha nem valami egetverően bonyolult, akkor néhány osztállyal meg lehet oldani. Ha túl nagyra nő egy osztály, vagy nehezen nevezed el, mert több dolgot csinál, akkor szét kell bontani több kisebb osztályra. Felesleges túlbonyolítani. A Clean Code vagy Tiszta kód című könyvet érdemes elolvasni a témában, abból is a code smell részt. Az nagyjából leírja, hogy mikor gyanús, hogy gond van a kóddal.

Egyébként én még mindig azt mondom, hogy csináld meg függvényekkel a lehető legfapadosabban, pl hardcode-olt regex-ekkel, stb. Ha úgy megvan, utána meg írd át OOP-re, kezdj el gondolkodni, hogy melyik függvények tartoznak össze. Pl ha közös paraméterük van, akkor elképzelhető, hogy azzal közösen egy objektumot tudnának alkotni, stb. Igazából ezt fejben is meg lehet csinálni, ha tényleg nem célod a megvalósítás, csak tanulni szeretnél valamit. A megvalósításnál viszont általában előjönnek olyan dolgok, amire nem számítottál, pl bonyolultabb egy függvény/metódus, mint vártad, tovább kell bontani az egészet még több metódusra vagy osztályra, és így tovább. Amúgy el lehet indulni a másik irányból is, hogy csinálsz egy modelt, előre kigondolod az egészet, aztán a végén csak lekódolod. Úgy is meg lehet, hogy pár lényeges osztályt gondolsz ki, aztán a maradékot a TDD majd kidobja, stb. Kell hozzá némi tapasztalat.
4

Nem teljesen... ez amolyan

mind1 valami név · Jan. 16. (Sze), 10.09
Nem teljesen... ez amolyan időmúlatós projekt, hogy legalább valami értelmesnek látszó dologgal töltsem el a maradék időmet, de a fény az alagút végén most épp egy száguldó TGV-nek tűnik. :D
5

Folyamatábra

Pepita · Jan. 16. (Sze), 11.53
Ha lerajzolod, hogy mit kell csinálni, akkor látni fogod, amit már most is jól sejtesz, hogy egy eléggé szekvenciális folyamatról van szó.
Van néhány elágazás, de gyakorlatilag egy belépési és egy kilépési pont van.
Egyetértek Inf3rnoval, az se baj, ha először procedurálisan csinálod meg, vagy "csúnya nagy" osztályokkal - majd refaktorálod, ha akarod.
Tervezés tekintetében azt javasolnám még, hogy bontsd fel a nagy feladatot sok kicsi, önmagában és belátható időn belül végrehajtható részekre.
Pl.:
1. Parancssorból indítható szkript, ami egy config alapján felnyal egy log fájlt (megnyitja olvasásra, majd lezárja), végül kiírja (stdout), hogy sikerült-e.
2. Adott egy lognyaló szkript, tanítsuk meg soronként olvasni, számolja meg a sorokat.
3. Kapott stringből config minták alapján (tömb) ki kell választani, hogy milyen típusú.
4. Típus alapján fel kell dolgozni a stringet.
Stb

Már az elején eldöntheted, hogy OOP vagy sem.
Ha elsőre procedurálisan csinálod is meg és később akarod OOP-ben, akkor is nagy valószínűséggel ugyanezek az issue-k lesznek újra aktuálisak, plusz hasznos lesz, amit időközben tapasztaltál (és kommenteltél). A fő lényeg az ember számára elfogadható méretekre bontás, hogy megoldáskor jól tudj fókuszálni. Az se baj, ha nem tervezed meg előre az egészet.
6

Procedurálisan megvan. Bash

mind1 valami név · Jan. 16. (Sze), 14.15
Procedurálisan megvan. Bash +perl szkriptek formájában. :)
Meg volt hozzá egy vázlatom pszeudokód jellegű kivitelben, azon rágódtam pár napig és ott jött elő kb annyi kérdéses dolog, amennyivel teleírhatnék két oldalt. Sajnos kukáztam, nem tudom megmutatni, de ha felébredtem, újra megcsinálom, aztán felteszem a githubra, hátha úgy már a részletekre is rá tudok kérdezni. Egyszerűen az objektum orientált szemléletet próbálnám megérteni ezen az egyszerűnek tűnő feladványon keresztül, de nem megy. Ahogy írtam, nem látom benne a klasszikus példákra hasonlító objektumokat. Klasszikus példa egy autó, aminek vannak tulajdonságai: szín, max. sebesség, gyorsulás, kerekek száma, tank mérete, fogyasztás; van viselkedése: motor indítás/leállítás, fordulás stb. és még szét is szedhető más objektumokra, a főbb alkatrészekre: motor, karosszéria, kerekek stb. - ezt a részét felfogtam az eddigi olvasmányoknak, épp csak képtelen vagyok ráhúzni a való élet legprimitívebb feladványaira us.
7

Igazából a klasszikus példák

inf3rno · Jan. 17. (Cs), 00.46
Igazából a klasszikus példák is nekem inkább adatstruktúrának tűnnek, mint ojjektumnak. Szerintem szórd fel githubra, aztán majd ránézünk, hátha tudjuk refaktorálni.
8

Képzelj köréjük egy rally

mind1 valami név · Jan. 17. (Cs), 00.59
Képzelj köréjük egy rally szimulátort! ;)
9

Úgy már egy fokkal jobb. :-)

inf3rno · Jan. 17. (Cs), 02.45
Úgy már egy fokkal jobb. :-)
10

Gondolkozz

Hidvégi Gábor · Jan. 17. (Cs), 10.16
Ha picit gondolkodsz, rájössz, hogy objektumorientáltan akkor lehet dolgozni, ha ugyanabból több hasonló van. Tehát autó egy Volkswagen, egy Skoda vagy egy Audi, akkor létre lehet hozni egy Autó osztályt, amit tudsz példányosítani.

A te feladatodra lefordítva ez azt jelenti, hogy ha többféle naplófájlt szeretnél ugyanazokkal a lépésekkel feldolgozni, akkor érdemes lehet elgondolkodni az OOP-n.

Szokták azt mondani, hogy az adott feladathoz mindig a legjobb eszközt kell választani. Az adatok transzformálására, amit te most szeretnél, a funkcionális megközelítés elvileg a leghatékonyabb. Nyilván elkészítheted a programot OOP is, de nemcsak hogy nem lesz optimális, hanem az OOP lényegét sem biztos, hogy meg fogod érteni.

Sajtreszerlővel is nekiállhatsz magadat kényeztetni, de nem biztos, hogy jó élményt fogsz vele elérni.

Még pár gondolat: ha figyeled a programozási trendeket, a világ most eléggé elmegy a funkcionális irányba, valószínűleg nem véletlenül. Talán az OOP nem váltotta be a hozzá fűzött reményeket. Hogy a funkcionális jobb-e, arról nem vagyok meggyőződve, mert sok helyen nem az általános emberi gondolkodás szerint működik.

Jómagam bő huszonöt éve programozok, ebből tizenhét éve professzionálisan, azaz elég sok mindent láttam már a szakmában, a legegyszerűbb weboldaltól a vállalatirányítási rendszerig készítettem jópár rendszert. Foglalkoztam OOP-vel, de ennyi idő alatt csak összesen két alkalommal merült fel bennem, hogy egy bizonyos feladatot objektumorientáltan kéne megvalósítani, mert a nyelv által nyújtott eszközökkel a program egyszerűbb lesz. Minden más esetben a procedurális változat sokkal jobbnak bizonyult.
11

Nem csak többféle napló

mind1 valami név · Jan. 17. (Cs), 11.42
Nem csak többféle napló fájlt, hanem azon belül is többféle sor típust kellene feldolgozni. Szóval valamilyen szinten rá lehet erőszakolni(?) az objektum orientált felállást.

Kiindulhatok abból, hogy TextInput (mert legalábbis pythonban a text fájl is iterátor) -> LogInput
A LogInput-ból lehet
kern
daemon
journal (systemd)
user
stb.

A különböző log típusokban vannak mindenféle eredetű és formájú sorok, amiből momentán egy az, amit fejből tudok: az iptables csomagokra vonatkozó bejegyzései, amik szintén tovább bonthatóak pl. protokoll szerint, mert kicsit más a TCP, mint az UDP és totál eltérő az ICMP (előbbiekben vannak portok is, utóbbiban port nincs, van helyette type=) stb.

Csakhát ez így több száz, esetleg több ezer sornyi kód, ha kulturáltan, a S.O.L.I.D. elvekhez ragaszkodva próbálom megírni, míg procedurálisan, esetleg nem is pythonban...

Pl. port scant folytató IP címek kiszűrése:
log_common.sh - közös rész a többi, hasonló scripthez
port-scan-list.sh - cli interface az eredeti perl programhoz
log1.pl - ebben van a lényeg: a stdin-ről érkező kernel logból kigyűjti azokat az IP-ket, ahonnan vélhetőleg scannelték a címem.

Ez az egész, csicsázással, kommentekkel stb. együtt sincs száz sor. Szóval az egésznek csak annyi értelme van, hogy játsszak, ismerkedjek ezekkel a dolgokkal...

Vagy... a párja, ami megvan pythonban is:
A log-common.sh a fenti,
unusual_log_entries.sh - egy .txt-ben megadott regex lista alapján kiválogatja a megszokott sorokat, amiket csak akkor érdemes átnézni, ha "esemény van", egyébként érdektelenek.

Ugyanez szólóban, pythonban (csak ennek másik .txt kell, mert a python kicsit másképp kezeli ezeket): grep_v_f.py
Épp csak itt kb. hótt felesleges osztályt létrehozni, mert ettől még ugyanúgy procedurális az egész.
14

Sorok

Pepita · Jan. 17. (Cs), 11.59
Egy - egy sor is olyan, mint Gábor példájában az autó. Az is érdekes, hogy többféle log file van, meg kell vizsgálni, hogy van-e a sorok típusai között közös. Tehát "A.log" - nak lehet-e ugyanolyan "logsortípus" típusú sora, mint "B.log" - nak?
Ha igen: a log-sor-típusok nem függnek a log-típustól.
Ha nem: a log-sor-típusok alá vannak rendelve a log-típusnak.
Most nincs időm átnézni a meglévő szkripteket, de ha így, sorban építkezel, jó eséllyel felszedsz némi OOP-t.
Nem lesz sokezer sor (sokezer class), ha jól húzod meg a határokat. Szépek a SOLID, clean code, stb elvek, de a gyakorlatban inkább törekedni kell rájuk, mint foggal - körömmel ragaszkodni. Utóbbi esetben lehet annyira túltolni, hogy már attól lesz nehezebben átlátható + lassú + stb.
12

Trend?

Pepita · Jan. 17. (Cs), 11.48
ha figyeled a programozási trendeket, a világ most eléggé elmegy a funkcionális irányba
Ezt miből gondolod? Én inkább azt látom, hogy még az is OOP (-nek hívják), ami nem. :)

Az viszont való igaz, hogy ha túltoljuk az elveket - elméletet, akkor könnyen lehet belőle gigászi osztályhalmaz hatalmas öröklődési lánccal - pársoros classokkal.
13

Pythonban pl. alapállás, hogy

mind1 valami név · Jan. 17. (Cs), 11.55
Pythonban pl. alapállás, hogy minden objektum. :)
15

széles körben támogatott/fejlesztett eszközök

EL Tebe · Feb. 11. (H), 14.49
Tudom, hogy egy saját megoldásban gondolkodsz és hogy az alábbi nem megoldás a kérdésedre, de már kismillió naplófájlt gyűjtő, tároló, analizáló, szétválogató, osztályozó, monitorozó stbstb. eszköz érhető el, pláne, amióta a virtuális megoldások elterjedtek.

Ezekben a legtöbb ismert napló formátum támogatott (és nyilván folyton frissítik programok és különböző verzióváltozatokra is), ráadásul a tárolási/visszakeresési lekérdezésekben, sőt, vizualizációban, vagy értesíőrendszerek támogatásában is komoly megoldásokat/kompatibilitást nyújtanak. Sok API-n keresztül is vezérelhető, némelyik jól skálázható, akár kiszervezhető külső tárolókra (s3, stb) és még a magas rendelkezésreállás is elérhető velük.

A saját igényeket pedig sztem egyszerűbb ezekkel megvalósítani, mint 0-ról mindent megírni.. Igaz, ez utóbbi esetén tanulsz, előbbi esetén meg hatékony vagy :)

(Nézz rá pl az "ELK" kulcsszóra)
17

Ez az egész játék nálam arról

mind1 valami név · Feb. 11. (H), 18.05
Ez az egész játék nálam arról szól(t volna), hogy át tudjam tenni a gyakorlatba azt, amit az OOP tutorialokban olvastam.
Mert szép és jó, hogy ezekben hozzák példának mondjuk az autót, de azokat a példákat nem igazán tudom ráhúzni a való életben előforduló problémákra, például erre, a viszonylag egyszerűnek tűnő dologra, hogy statisztikát gyártani primitív logokból.
Egyébként ami logelemzőt néztem, az konkrétan egy sem tudta azt, amit látni akartam.
18

Amit szeretnél, hogy magától

inf3rno · Feb. 11. (H), 18.37
Amit szeretnél, hogy magától kitalálja, hogy milyen minta illik a logra, arra nem fogsz triviális algoritmust találni. Szóval ennek a munkának egyáltalán nem az OOP a nehézsége. Szerintem ha gyakorolni akarsz, de nem nagyon akarod beleásni magad a pattern mining algoritmusokba, akkor csinálj egyesével feldolgozót az előforduló log formátumokra, akár regex alapon, aztán előbb utóbb célba érsz. Sok árukeresős, utazásos, repjegyes, stb. site ugyanígy külön botot ír a felkeresett oldalakhoz, ahelyett, hogy valami általánosat fejlesztene, mert az utóbbi jóval nehezebb.
19

Az már rég a múlté, azon

mind1 valami név · Feb. 11. (H), 19.19
Az már rég a múlté, azon rágódtam pár napot, készítettem egy pár soros programot, ami kigyűjtötte a hasonlónak tűnő sorokat és abból megállapítottam, hogy az kiindulási alapnak sem jó, mert olyanokat is összevonna, amiknek közük nincs egymáshoz, máskor meg több ezer sorra állította, hogy egyediek, amik valójában egyformák voltak csak bizonyos címek cserélődtek bennük. :) De ott nem is a leprogramozás volt a kérdéses, hanem az algoritmus, de azt már kukáztam.

Ami megmaradt, az tképp évek óta megvan, mint feladat, de évek óta nem jutok tovább annál, hogy a beolvasó ciklus megvan. :)
Illetve ami kellett, azt itt linkeltem is valahol, pár rövid perl és shell szkript, néhány linuxos toollal összekapcsolva. Csak néha rámjön a roham és nincs kéznél Haloperidol (vagy valami ilyesmi ami kiüti az embert pár napra :D), hogy félretoljam és akkor egy ideig rágódok rajta. Aztán félredobom, találok más szórakozást és napok, hetek múltán újabb roham és goto 1 ;)


Most két napja pl. azon töröm a fejem, hogy egy sor feldarabolása az a sorhoz, mint objektumhoz tartozó metódus kellene, hogy legyen vagy annak az objektumnak a metódusa, aki a sorból adatot gyűjt? Mert mindkettőt jogosnak is érzem, meg hülyeségnek is. Csak az a baj, hogy ezeket már nem tudom úgy megfogalmazni, hogy más is értse.
23

ötletelés

EL Tebe · Feb. 12. (K), 17.12
Esetedben egy log sor is csak egy adathalmaz (sima string), az, hogy milyen típusú adatot tartalmaz, milyen formátumban, sorrendben, értékkel ésatöbbi, az változó.

1) Egyik része a programodnak maga a log fájlok elkérése, hatékony beolvasása és a lehetséges változatok/hibák kezelése lesz.

2) A másik, amit be kell lőnöd, hogy pontosan mit szeretnél megtudni a naplókból (és mikor, egyszerre mennyit (és minek? :) )).

Az összes ilyet össze kell gyűjtened és állj meg még azelőtt, hogy az összegyűjtöttekkel bármiféle műveletsort terveznél: mivel a konkrét info kiolvasása, sőt, ezek saját használatra történő átstruktúrálása, formázása is teljesen külön probléma. (kereshetővé tétel, rendezés, indexelés és még bőven sorolhatnám, meg aztán pláne...)

Ezekből máris következik, hogy egy csomó dolgot eleve nem is kell beletervezned. Gyakorlatilag beraksz egy bemenetet és dob egy eredményt, amit majd tovább adhatsz. Ami a bemenetet felbontja, az ne csináljon mást, neki csak egyetlen feladata legyen. Olyannyira, hogy a fájl kiolvasása, a sorvég karakterek érzékelése, stb sem az ő dolga.
(Így eseélyes hogy máris igaz lesz hogy az osztály kizárólag csak azzal foglalkozik, ami a dolga)

Ha nem elvárt módon dob eredményt valami (ahogy fent írtad), akkor nem - vagy hibás minta alapján - készítetted fel a feldolgozáshoz.
(És persze itt máris be fog jönni a képbe egy halom probléma, mint például Windows és Linux különbségek, mint a sorvég karakterek, vagy a fájl karakterkódolása, a felhasznált függvények erre vonatkozó képességei, ésatöbbi..)

Próbálj meg ne sorokban gondolkodni, hanem egy, egy "oszlopban":
Ki kell gyűjtened az összes lehetséges adattípus mintát (pl dátum+idő formátumok, ip címek, stb).
Ha egy sort nem egy egésznek veszel, hanem inkább csak egy feldolgozandó adathalmaznak, amit még kisebb darabokra kell bontani, akkor közelebb kerülsz a célodhoz.
Pláne, hogy így a beolvasott elemhez adattípusokat is tudsz majd definiálni, amivel már ténylegesen lehet műveleteket végezni. Például két dátum közt eltelt idő.
Itt is fel fog majd olyan probléma merülni, hogy ami területi beállításokból, vagy egyedi konfigból adódódnak, lásd az egyik időpont timestamp-ben van, a másik ISO formátumban, a harmadik meg csak egy integer lesz, stb.stb..

Én "kézzel" egy txt-be kigyűjteném a már meglévő log fájlokból, a leggyakoribb, egyedi log sort - tehát a legjellemzőbbeket.
Ha ezekre lesz kész mintád, akkor minden más esetet, amit nem ismer fel a programod, azt külön naplózhatsz egy fájlba és ha pl megváltozik valami, akkor azt is látni fogod, meg azt is, hogy milyen mintákat kell még gyártanod, amivel bővítheted a programod. Ebben benne van az, hogy a mintákat felhasználó, adatot vizsgáló osztályod a mintákat bővíthető módon kapja.

Ha már lesz egy komplett készleted, hogy melyik adatra milyen minta illik, akkor tovább is fejleszthető a dolog: ismerje fel automatikusan egy log (vagy sor) elrendezését: oszlopait, azok típusait, számát, sorrendjét, stb.
Persze ez annyira nem egyszerű, mert mi van, ha egy sor pl három dátum+idő adatot tartalmaz? Melyik, mit jelent?
Ekkor lesz az, hogy miután az adatok típusát meghatároztad egy sorban, akkor kezded csak a "sor"-t nézni: egy sorra is gyártasz mintát: azaz: milyen sorrend jellemző, milyen log-ra (pl dátum, dátum, ip, http-head-txt error_code = apache2).
De ezt már nem lesz nehéz megcsinálni, ha szépen szét van bontva apró részekre a progid.

3) A harmadik, legnagyobb rész az, amikor már túl vagy a kiolvasáson, parse-on, ergo a változóba pakolás is rendben van - következhetnek az ezekkel való műveletek - tehát az, amiért az egésszet elkezdted.

Akár struktúrálás, csoportosítás, számlálás, rendezés, szűrés, tárolás?, továbbítás? Event-ek indítása esmény hatására, ésatöbbi. Ez lesz a legnagyobb része a melónak és erről lehet a legkevesebbet általánosan írni.

Nem tudom, hogy mi a célod a log fájlok elemzésével, indítani valami progit, vagy statisztikát készíteni?

Azon elgondolkodnék, hogy mindenképpen egy vegyes tartalmú, X MB / GB logfájlt (vagy többet) szeretnék-e állandóan egy progi időről időre történő futtatásával újra és újra beolvasni, átnyálazni, elejétől a végéig (vagy tól-ig blokkokat) stb és ahhoz hozzádrótozni valamilyen batch jellegű "figyelést". Vagy sokkal inkább egy folyamatosan futó kis progiba beküldeném a tail (vagy multitail) parancs kimenetét és így az újonnan létrejövő sorokat kellene csak piszkálnom.. Ha egy figyelmeztetés lenne a cél, akkor konkrétan arra írnék egy mintákat: ha szerepel benne pl. hogy alert/warning/vagy ilyesmi, csak akkor történjen vmi, minden más kuka (figyelmen kívül hagyás=nem illeszkedik a minta).

"Most két napja pl. azon töröm a fejem, hogy egy sor feldarabolása az a sorhoz, mint objektumhoz tartozó metódus kellene, hogy legyen vagy annak az objektumnak a metódusa, aki a sorból adatot gyűjt?"

1. Egy sor (elvileg) = egy esemény. A tartalmát simán tovább kell majd adni az erre írt résznek (lásd alább) - plussz még egy fontos jelentése van, nyilván hogyha egy új sor kerül a naplóba, akkor az adott időpontban történt vmi.

2. Egy sor felbontása = jellemzően whitespace-enként kapsz majd adatoszlopokat, amik egyesével vizsgálhatóak és definiálhatók: oszlopok száma, az oszlopban szereplő adat típusa, stb.
Ergo: kell egy külön osztály +metódusok, amibe beküldöd a sort (sztringként) és ami majd lebontja "oszlopok"-ra (mintáid alapján), amik meg olyan objektumok, amik képesek tárolni, visszaadni az értéket.

Erre írtam tegnap, hogy kétféleképpen gondolj az osztályokra: az adatok "eltárolása" és az azokkal végzendő "műveletek" két különböző dolog.

Nah, már így is kicsit túltoltam, de majd írj azért, hogy sikerült összehozni vmit :)

Errefelé találsz annyi megoldást, mint égen a csillag: https://www.google.com/search?client=firefox-b-d&q=log+parsing
És ha pl github-on ránézel egy ilyen megoldás forrására, talán még egy adag mintát is találsz a feldolgozáshoz.
24

Köszi, de...

mind1 valami név · Feb. 12. (K), 21.59
Még1x: ez nem egy szükséges cucc, amit meg kell írnom, egyszerűen próbálom (sajnos már évek óta, szóval reménytelenül :D) megérteni, hogy hogyan lehet egy gyakorlati problémát valahogy OOP-re fordítani, mert a tutorialokat látszólag értem, de amint valami másra próbálnám átültetni, mindig elveszek a részletekben.

Amit ki akarok szedni a logokból (mind megvan scriptekben):
1. Ritkán előforduló bejegyzések. Ennek van gyakorlati értelme is, hogy észrevegyem, ha valami szokatlan történt. Ez most úgy megy (bőven elég), hogy kézzel kigyűjtöttem a gyakori mintákat, amik rendszeresen előfordulnak és nem érdemes foglalkozni velük úgy, mint eseménnyel. Pl. a tűzfal által eldobált csomagok. Konkrétan erre van egy ilyesmi regex: "^.* DROP IN=ppp0 .*$", ehhez hasonlóan össze van szedve az összes érdektelen sor és egyszerűen egy "grep -f patterns.txt -v kernel.log" paranccsal érem el.
2. Eldobált csomagok /óra/IP cím. Változó a publikus IP-m, ezért kellett bele az IP is. Ez gyakorlatilag ennyi:
cat kernel.log | perl -nle '/^(... .. ..):.*DROP.*DST=(\S+)/ && do { print $1,"\t",$2 }' | uniq -c
3. Port scanek. Erre meg van egy pici perl scriptem, ami számolja az azonos IP-ről, eltérő portokra érkező, eldobált csomagokat. (https://github.com/haa-zee/shell-scripts/blob/master/log1.pl)

Szóval itt most tényleg csak arról van szó, hogy unatkoztam, szerettem volna megérteni pár dolgot. Na, akkor most átolvasom újra amit írtál, mert így elsőre csak addig jutottam, hogy te ezt egy valódi, "éles" problémának gondolod. ;)

A különböző log parserekkel olyan gondjaim voltak, hogy vagy túl sokat kellett volna olvasni a használatukhoz, vagy pont azt nem tudták, amit én akartam. :)

Ja, meg az maradt ki az egészből, hogy viszonylag általános kialakításúra szeretném/szerettem volna összehozni, hogy ha egyszer eszembe jut, hogy ne a router logjából szemezgessek, hanem mondjuk egy systemd journalból, akkor az se okozzon gondot. Vagy ha mondjuk kitalálok, hogy kíváncsi vagyok a leggyakrabban megszólított portokra (csak mint példa), akkor is elég legyen egy konfig file-t módosítani és megírni azt a plusz osztályt, ami az újabb statisztikát legyártja.
Egyébként kétévnyi log feldolgozása a szerveren, ami egy n3150-es celeron a 8GB RAM-mal, max 10-20mp, a laptopomon, wifin, NFS-t használva 5-6mp, ha jól emlékszem :)
25

ilyen esetben

EL Tebe · Feb. 12. (K), 23.26
Egy "éles" és működő megoldás esetében - ami ráadásul nem is nagyon változik - sokszor nem javasolják, hogy csak a módszertan miatt az ember hozzányúljon és szinte alapoktól (újra)írja.

Ha meg csak úgy próbálkozol, ahogy írtad, akkor meg elég ha csupán egy apró részt próbálsz megírni OOP szerint.
26

hogyan lehet egy gyakorlati

inf3rno · Feb. 13. (Sze), 06.05
hogyan lehet egy gyakorlati problémát valahogy OOP-re fordítani, mert a tutorialokat látszólag értem, de amint valami másra próbálnám átültetni, mindig elveszek a részletekben


Szerintem az a baj, hogy az alapokat sem érted és úgy próbálsz nekifutni. Igazából a legtöbben, amikor elindulnak OOP-vel, megnéznek néhány mintát, és úgy gondolják, hogy van fogalmuk arról, hogy mit jelent az, hogy osztály, és hogyan kell használni. Én is csak 20 év után most gondolkodtam el rajta NLP kapcsán.

Általában egy fogalmat többféle osztállyal leírhatsz. Ezek közül kell kiválasztani a számodra relevánsokat, és megpróbálni valamilyen kompozíciót összehozni belőlük, amivel megoldod a feladatot. Mondjuk a szöveges feladat az, hogy "becsüld meg egy 81mm átmérőjű alma felületét".

Alma =
    Gömb (nagyjából) +
    Tárgy(3d) +
    Gyümölcs(rózsaféle) +
    Piros +
    ...


Ha egy gömb felületet akarsz számolni, akkor:

class Sphere {
    constructor(diameter){this.diameter = diameter;}
    surfaceArea(){return this.diameter * this.diameter * Math.PI;}
}
Mivel itt az almádnál csak a forma a releváns, ezért eldöntheted, hogy milyen irányba haladsz tovább.

1. átírod a nevet gömbről almára

class Apple {
    constructor(diameter){this.diameter = diameter;}
    surfaceArea(){return this.diameter * this.diameter * Math.PI;}
}
var apple = new Apple(81);
console.log(apple.surfaceArea());
2. példányosítod a gömböt és a példányt almának nevezed el

var apple = new Sphere(81);
console.log(apple.surfaceArea());
3. átörökíted a gömb tulajdonságait, metódusait

class Apple extends Sphere {}
var apple = new Apple(81);
console.log(apple.surfaceArea());
4. kompozíciót használsz

class Apple {
    constructor(diameter){this.shape = new Sphere(diameter);}
    surfaceArea(){return this.shape.surfaceArea();}
}
var apple = new Apple(81);
console.log(apple.surfaceArea());
Mindegyik jó megoldás ebben az esetben. Ha általánosítasz, akkor jobb, ha van külön Alma osztály, így legtöbbször a 2. kiesik. Ha többféle osztály tulajdonságait vonod össze és csak egyszeres öröklést támogat a nyelv, akkor a 3. biztosan kiesik, az 1. is általában kiesik, kivéve ha külön névtér alá teszed be, és nem akarsz a DRY-nak megfelelni valami miatt. Ilyen pl ha DDD-ben több BC alatt is megjelenik ugyanaz a fogalom, de mindenhol más osztály kompozícióa fontos a BC szempontjából, pl raktározásnál a súly és a térfogat a fontos, számlázásnál meg a súly, az egységár és az élelmiszer ÁFA. A 4. ami biztosan mindig használható, de ebben a konkrét esetben overengineering lenne. Nagyjából ezek az alapok.

A bonyolult problémák ennél jóval bonyolultabb szöveges feladatoknak felelnek meg. Azoknál már nem feltétlen jön ennyire természetesen, hogy melyik fogalmat milyen osztályok kompozíciójával kellene leírnod, vagy sokszor az sem világos, hogy pontosan milyen fogalmakat használsz a domain modelledben. Általában csak az van, hogy valamit el kell végezni a kódnak, aztán az alapján megpróbálod kitalálni, hogy milyen modellt lenne jó használni rá.

Ezt lehet agyalással, vagy el lehet indulni TDD-vel, és az szétvágja neked valamilyen módon osztályokra a problémát. Ez a modell bizonyítottan működik, mert átmegy a tesztjeiden, általában egy elég nyers szokott lenni, ami SRP szerint alakul ki. Ezen érdemes utómunkát végezni refaktorálással, pl beszélőbb neveket adni az osztályoknak, ami a modelledet jobban tükrözi, vagy ha nem akarsz mindent általánosítani, hogy cserélhető legyen, akkor akár apróbb osztályokat egyesíthetsz is és felülbírálhatod az SRP-t, hogy ne legyen annyira overengineering érzésed. A BDD valahol az agyalás és a TDD között van. Ott refaktorálás helyett már menet közben gondolkodsz el a jó szóhasználaton és azon, hogy szétvágsz e egy nagyobb osztályt vagy egyben hagyod. A BDD-hez szerintem jóval több tapasztalat kell, hogy jól csináld, úgyhogy érdemes először a TDD-t begyakorolni.

Ezen kívül úgy is meg lehet közelíteni a problémát, hogy először adat struktúrákkal és függvényekkel oldod meg, aztán elkezdesz azon agyalni, hogy melyik adatstruktúrához melyik függvényt társítanád, és így osztályokat alakítasz ki. Esetleg a kialakult osztályok hasonlósága alapján elkezdhetsz általánosításon, ilyesmiken gondolkodni, kialakulhatnak közös felületek, stb. Ezzel jóval nehezebb eredményre jutni, mint a TDD-vel, de ha szeretsz kísérletezni, akkor ezzel is célba érhetsz. Egyébként TDD-hez hasonló megközelítést használhatsz így is, tehát a függvényeket és adat struktúrákat létrehozhatod a már megírt tesztjeid alapján anélkül, hogy nagyon agyalnál a felelősségi körökön, adat- és implementáció rejtésen, stb.

Nyilván ez az egész gyakorlati tudás, és nem jön csak így zsigerből. Úgyhogy hiába várod, hogy pár tutorial után csak úgy magától menni fog.

Én egyébként a hobbi projektjeim egy részénél odáig jutottam, hogy már teszteket se tudok írni, úgyhogy a TDD tök esélytelen. Van olyan probléma, amit két évbe telt egy tucat osztályra szétcsapni, de ezeknek a nagy része sem tesztelhető még, mert csak körvonalakban van meg, hogy mit csinálnak, és valószínűleg mindegyik alá még többezer másik osztály fog később tartozni. Ezek ilyen több évtizedes projektek lesznek, dehát ezért hívjuk hobbinak őket. Amivel napi szinten találkozol munkaként azokon legtöbbször nem kell ennyit agyalni, mert van egy cég és egy a problémához tartozó folyamat, amit automatizálni akarnak. Ha elég alaposan megvizsgálod a folyamatot, akkor gyakorlatilag megvan a modelled. A DDD nagyjából így dolgozik, vannak domain expertek, akik elmagyarázzák neked a folyamatot, és akikkel egy jó modelt tudsz csinálni. Hasonló elven tudsz te is fejleszteni domain expert nélkül is, de jóval macerásabb úgy mindent végiggondolni, mint kérdezni, és azt mondják, hogy nem is éri meg a DDD-t használni, ha nincs domain expert. Én ezzel azért nem értek egyet, szeretem, ha van domain model egy projekthez, bármilyen egyszerű is legyen az. Egyedül a CRUD alkalmazások, amiknél üresen lehet hagyni. Nekem az jött le, hogy legtöbbször alulbecsli az ember, hogy egy probléma mennyire bonyolult. Ha már szóba került, amiről eddig szó volt, mint OOP, az csak a domain model. Ehhez még azért tartozik egy körítés, pl hogy honnan jön az input, hol tárolod az adatot milyen formában, és így tovább. Egy komoly alkalmazásnál ezek külön rétegek, amik jól elválnak egymástól. Ez igazából a dolog másik része, tisztában kell lenni az architektúrákkal is egy kicsit, különben nem fog menni. A te projekted azért még nem feltétlen ez a méret, de ha sikerül végre lemodellezned, akkor utána ebbe az irányba is érdemes képezni magad.
16

OOP tervezés

EL Tebe · Feb. 11. (H), 15.26
A tervezés nekem is mindig nehéz, gondot okoz:

1) vagy általánosságban nézed - és akkor nem a konkét megoldásban gondokodsz hanem csak az elveket vizsgálod - vagy pedig 2) pontosan specifikálva haladsz, viszont az már konkrét megvalósítás, tehát általánosságban nem lehet beszélni/írni róla..

Ezért sem igazán jók az ezzel kapcsolatos tutorial-ok.

Sajnos megtanulni, ismerni és követni kell az elején az alapelveket, aztán később rájön az ember, hogy ez mennyire hasznos.

Én megpróbálnék helyedben minden részt szétbontani, minél apróbb, elemi darabokra.

Van amire adat(halmaz)ként kell tekinteni, van amire funkcióként/műveletként.

(Attól, hogy az ember oda írja az elejére, hogy "class" attól még ezek különböző dolgok, de ezt nyilván tudod Te is)

Ha ez megvan, meg a fenti elemekre bontás, akkor már tisztábban is látsz, ráadásul azt is tudni fogod, hogy elérhető-e az adott feladatra külső megoldás/lib, amit már nem kell neked 0-ról megírnod.

Pl, létezik az "egy felelősség elve", azaz egy osztály egy és csak egy felelősséggel rendelkezzen. Ez kicsit bonyolult, de ha figyelsz rá, akkor idővel nagy segítség lesz, pláne, ha régi kódokat kell megérteni, használni/meghívni. Interface-eket hozol létre, az sem épp bonyolítás, bár munkával jár és meg kell tanulni szintén.

Megnézném az adathalmazokat: amiből kigyűjteném az összes ismétlődő és változó elemet, forrást és azt is, hogy mik az ezekkel végzendő műveletek és azok szintén csoportosíthatóak-e, definiálhatóak-e általánosítva?
Ez már gyakorlatilag az, amiről feljebb írtam.

Amit írtál Te is: pl egy műveletet elvégezhetsz valamilyen esemény alapján, vagy egy user interface-en keresztül meghívva, stb. Eleve ezt is többfelé kell szedned, ne legyen egy megvalósítás külön a UI-hoz, külön egy event-nél, stb..

Az is kérdés, hogy pl időnként kell elvégezned egy feladatot "batch" jelleggel, vagy "realtime". Mivel itt már kapásból az is felmerül, hogy jó lesz-e egyáltalán a fejlesztéshez használt nyelv..
20

Jó ötlet

Pepita · Feb. 12. (K), 10.48
Én megpróbálnék helyedben minden részt szétbontani, minél apróbb, elemi darabokra.
Ezt mindig célszerű (el)követni, egyetértek.

Mondjuk kimondani / leírni sokkal könnyebb, mint betartani olyankor, amikor tetszik a feladat, rá akarok ugrani és / vagy szűk határidő van. :-D
Ezzel együtt a saját tapasztalatom az, hogy összességében jóval hatékonyabb és gyorsabb a fejlesztés, ha "emészthető" részekre van bontva a feladat.
21

kimondani / leírni sokkal könnyebb, mint betartani

EL Tebe · Feb. 12. (K), 15.39
Ez így van, részletekbe belemenni idegőrlő tud lenni, hogyha az ember nyakába liheg az idő és azonnal kell működnie vminek.

Sokszor türelmetlen vagyok és egyből mindent szeretnék :) ez sem igazán jó, Ugyanez a helyzet a teszt esetek írásával..

Mindig akkor bántam meg a kapkodást, amikor x idő múlva vissza kell térjek egy "sos legyen meg, nem számít hogyan" feladathoz. Tipikusan a kérdező példája, amikor x éves projecthez kell hozzányúlni, vagy ilyeesmi.

Aztán amióta én döntöm el, hogy hogyan oldok meg valamit, és hogy egyáltalán elvállalom-e az adott feltételekkel/körülményekkel, azóta más a helyzet, jó eséllyel nem futok bele ilyesmibe.
22

Nem éri meg elvállalni az

inf3rno · Feb. 12. (K), 16.20
Nem éri meg elvállalni az ilyen tákoljunk bele dolgokat, vagy ha mégis, akkor dupla, tripla órabérért, mint általában. Ha a projekt számodra idegen eszközökkel dolgozik, akkor a beletanulás legalább annyi időt elvisz, mint az, hogy megoldd a feladatot. A zöld mezős projektek sokkal jobbak, mert te mondod meg, hogy mivel dolgozol.