ugrás a tartalomhoz

Miért jó domain objecteket használni?

inf3rno · 2014. Már. 31. (H), 22.59
Hoztam egy példát domain objectek használatára egy cikkből. A cikk most nem igazán releváns a kérdés szempontjából, de azért belinkelem.

A kérdés annyi, hogy miért jobb domain objecteket használni a business logic layer-ben, mint egy az egyben átküldeni az adatot a data access layer-ből.

1.) - domain objectes példa
class MoneyTransfer
{
    private $accountDao;

    public function transferMoney(MoneyTransferRequest $transfer)
    {
        $source      = $this->accountDao->find($transfer->sourceId);
        $destination = $this->accountDao->find($transfer->destinationId);
        $money       = new Money($transfer->amount);

        $source->withdraw($money);
        $destination->deposit($money);

        return new MoneyTransferResponse();
    }
}
MoneyTransfer : Interactor
MoneyTransferRequest : DTO
MoneyTransferResponse : DTO
Money : Entity
Account : Entity
2.) - csak adat küldős példa
class MoneyTransfer
{
    private $accountDao;
	
    public function transferMoney(MoneyTransferRequest $transfer)
    {
        $source      = $this->accountDao->find($transfer->sourceId);
        $destination = $this->accountDao->find($transfer->destinationId);

        $source->balance = $source->balance - $transfer->amount;
        $destination->balance = $destination->balance + $transfer->amount;
		
		$this->accountDao->updateBalance($source);
		$this->accountDao->updateBalance($destination);

        return new MoneyTransferResponse();
    }
}

MoneyTransfer : Interactor
MoneyTransferRequest : DTO
MoneyTransferResponse : DTO
Money : -
Account : DTO
Amit nem értek, hogy miért éri meg az első (domain object-es) megoldást használni, és miért nem divat a második?

Felsoroltam néhány érvet, de szeretném, ha írnátok hozzá ti is, illetve megvitatnánk a meglátásaimat.








# 1. domain object 2. adat küldős
A A domain objectek esetében sima adatlekérdezésnél oda-vissza konverzió van a business logic réteg határán a DTO-k és Entity-k között. Ha csak adatot mozgatunk a rétegek határán, logikát nem viszünk át egyik rétegből a másikba, akkor a DTO-k újrafelhasználhatóak. Tehát ha pl a business logic kap egy DTO-t mentésre, akkor azt egyből továbbíthatja a data access-nek, illetve ha kiolvasás történik, akkor a kiolvasott adatokat egyből továbbíthatja a representation-nek. A business logic-nak tehát ilyen egyszerű műveletek esetén egyáltalán nem kell az adathoz nyúlnia.
B A domain objectek és az adatmentés módja között szoros a csatolás. Általában ezt annotációkkal próbálják lazítani, de attól még elég nehézkes egy az egyben lecserélni az adatmentés módját mondjuk adatbázisról fájlrendszerre vagy vissza. Ha csak simán DTO-k küldözgetése megy a rétegek között, akkor sokkal egyszerűbb lecserélni az adatmentés megvalósítását.
C A domain objectek esetében nem kell külön figyelni az adatok mentésére, ezt az aktuális ORM megcsinálja helyettünk. A DTO-k küldözgetésénél figyelni kell arra, hogy mentsük is a módosításokat a perzisztens tárolóba, de ez logikusan következik abból is, hogy csak az adatot használtuk fel. Ami aggasztó lehet, hogy nincs biztosíték arra, hogy a kiolvasás és a mentés között nem nyúl valaki az adatokhoz a perzisztens tárolóban. Úgy sejtem, hogy a PHP ORM-ek a domain object-es megoldás esetében valamilyen lock-al ezt megoldják, de ebben nem vagyok teljesen biztos. Pl egy nodejs esetében ilyen probléma nincsen, mert oda lehet adni teljesen ugyanazt az entity-t minden egyes rá vonatkozó lekérésnek. Szóval a konkurrencia kezelés a DTO-s megoldásnál úgy néz ki nehézkesebb, de erről várok véleményeket, tapasztalatokat.
 
1

Nekem az eddigiek alapján

inf3rno · 2014. Ápr. 1. (K), 01.56
Nekem az eddigiek alapján nagyon úgy tűnik, hogy ez a domain object használat legalább két problémából tevődik össze. Az egyik az adatbázis konkurrencia kezelés megoldása, a másik, hogy az entity-k a use case-ek számának növekedésével egyre nagyobbra nőttek, így muszáj volt valahogy kiszedni a use-case-ekhez tartozó logikát az osztályaikból, hogy könnyebben karbantartható legyen a kód. Én egyáltalán nem vagyok benne biztos, hogy ez a domain objectes legjobb megoldás, de még elolvasok legalább 20 cikket a témában mielőtt valami végkövetkeztetésre jutnék...

A legnagyobb problémám, hogy a domain objectek használata nem biztosít elég laza csatolást az adatbázishoz tartozó kód és a business logic között. Én sokkal inkább valami olyasmit képzelnék el, hogy az adatbázis beregisztrál eseménykezelőket az entity-khez, amit a business logic hoz létre, aztán úgy figyeli a változásokat, nem pedig ő maga példányosítja az entity-ket. Átnéztem pár architecture style-t, ami körül most nagy a felhajtás, clean, hexagonal, stb... és kb az jött át, hogy az a lényeg, hogy az részletkérdés, hogy az alkalmazás honnan kapja az adatokat, és hogy hogyan tárolja le. Az számít, hogy mi a belső logikája. Én arra gondoltam, hogy akkor a delivery method és a storage modulokat egy az egyben leválasztom egy-egy interface csomaggal, és így foglalkozhatok az alkalmazással magával. Ennek eléggé ellentmond az, hogy a domain objectek a storage modulban kell, hogy szülessenek, és nem pedig az alkalmazás hozza létre őket...

Olvasgatok, meg agyalok tovább...
2

Azért kell domain objecteket

szjanihu · 2014. Ápr. 1. (K), 08.17
Azért kell domain objecteket használni, mert máskülönben a logika stateless serviceben van, és könnyen megkerülhető: ezért is van egy olyan elv, hogy "always valid", vagyis ne engedd meg, hogy egy domain objected (DDD-ben aggregate-ről beszélünk) invalid állapotba kerüljön.

A laza csatolás az adatbázissal problémádat nem értem. Kell egy repository interfész, ami biztosítja a perzisztens tárolóból való hozzáférést és perzisztálást. Ezt pedig az infrastruktúra rétegben implementálod. Mindig használj explicit mentést repositoryn keresztül, ne hagyatkozz az éppen használt ORM szolgáltatásaira!

A domain objected meg inkább legyen nagy, mintsem elszórva legyen a business logic megannyi stateless application serviceben.

A konvertálással kapcsolatban pedig már leírtam, hogy CQRS esetén nincs rá szükség.

Még annyi, hogy az updateBalance megvalósításod nem tartja be az invariánst, mert ha csak az egyik objektumon hívod és elfelejted hívni a másikon, máris mehetsz pereskedni a bíróságra. Inkább passzold át a sourcenak a destination objektumot is (valamint nevezd át a metódust valami beszédesebbre).
3

Még annyi, hogy az

inf3rno · 2014. Ápr. 1. (K), 10.38
Még annyi, hogy az updateBalance megvalósításod nem tartja be az invariánst, mert ha csak az egyik objektumon hívod és elfelejted hívni a másikon, máris mehetsz pereskedni a bíróságra.


Azt én is látom, hogy 2x van a kódban, de az olyan eshetőségeket, hogy nem mentem, egy rendesen tesztelt kód eleve kizárja. A 2 paraméteres metódusokkal ugyanúgy probléma van, pl transferMoney(source, dest) vagy transferMoney(dest, source). Az ilyen jellegű problémákra egyedül az jelentene megoldást, ha config object-ben adom át, vagy csinálok neki fluent interface-t, pl createMoneyTransferFrom(source).to(destination).

Azért kell domain objecteket használni, mert máskülönben a logika stateless serviceben van, és könnyen megkerülhető: ezért is van egy olyan elv, hogy "always valid", vagyis ne engedd meg, hogy egy domain objected (DDD-ben aggregate-ről beszélünk) invalid állapotba kerüljön.


Hogyan lehet megakadályozni, hogy invalid állapotba kerüljön? A PHP-s ORM-ek, pl Doctrine esetén ez biztosítva van?
4

Azért jobb ezt a domain

szjanihu · 2014. Ápr. 1. (K), 11.14
Azért jobb ezt a domain objectre bízni, mert annak a felelőssége az invariánsok betartása és akárhonnan is hívod a transferMoney metódust, nem fog elveszni a pénz. Ezeknek a betartásáról neked kell gondoskodni("always valid"). Lehetnek aggregateken átívelő invariánsok (ez a példa pont olyan, mivel két aggregatet kell egyszerre módosítani), illetve olyan validációs szabályok is, amiket kénytelen vagy külső serviceben ellenőrizni (pl. ID megléte), de szabály az, hogy ami egy domain object belső magánügye, arról ő gondoskodjon és tegyen meg mindet azért, hogy az adott szabály be legyen tartva.

Ilyen szabály például az, hogy nem mehet negatívba az egyenleg. Ezt az aggregateben kell betartatni. Erre találsz példát a doctrine dokumentációban.
5

Miért van szükség arra, hogy

inf3rno · 2014. Ápr. 1. (K), 11.35
Miért van szükség arra, hogy a domain object tudjon az adatbázisról vagy az ORM-ről?
6

Nincs szükség, sőt, ne tudjon

szjanihu · 2014. Ápr. 1. (K), 12.40
Nincs szükség, sőt, ne tudjon róla! Melyik mondatomból következtettél erre?
8

Nem tudom, lehet, hogy csak

inf3rno · 2014. Ápr. 1. (K), 20.14
Nem tudom, lehet, hogy csak nekem volt egy hibás elgondolásom erről az egészről...

Azt szerettem volna, ha csak data transfer objecteken keresztül kommunikáltak volna a moduljaim egymással. Úgy értem, hogy kölcsönösen tudnak egymásba adaptereket injektálni, és ezeknek az adaptereknek a metódusai szolgáltatják vagy várják a DTO-kat. Úgy néz ki, hogy a data access és a business logic között muszáj DTO-k helyett entity-ket átadnom, különben szinkront veszíthet az egész az adatbázissal. Ezt viszont szerettem volna elkerülni, mert valahogy nem tűnt helyesnek, hogy adaton kívül más is menjen a kettő között. Valószínűleg azért, mert vagy adat struktúrával dolgozok, vagy objektummal, viszont az tőlem teljesen idegen, hogy egy objektumnak vannak metódusai, de nincs adatrejtése... Legalábbis ezt gondoltam a domain objectekről. Most megnéztem ezt a konkrét példát, és pl az account-nál van adatrejtés a balance-ra...

Tudnál másik példát mondani erre a megoldásra?

Konkrétan egy szimpla CRUD-os példa érdekelne, mondjuk cikk listázást, létrehozást, olvasást, szerkesztést, törlést hogyan lehetne ilyen domain objectekkel leírni úgy, hogy közben rejtsék is az adataikat. Nekem régebbről java-s példákból az rémlett, hogy ilyenkor az entity nem rejti az adatokat, és simán le lehet róla másolni a property-ket egy DTO-ba... Na ez nem tetszene, mert vagy csak adatot tároljon az ojjektum, és legyen DTO vagy rejtse az adatait.
10

Miért van külön data access

szjanihu · 2014. Ápr. 1. (K), 22.57
Miért van külön data access és business logic? Nem azt mondom, hogy extrém esetben ez nem lehet jó/szükséges, de ne bonyolítsd túl.

Konkrét, viszonylag egyszerű és többnyire elégséges megoldás, amiben az írás/olvasás szét van választva (CQRS):

Írás
class DoctrineUserRepository implements UserRepository {
  public function save(User $user) {
    $this->entityManager->persist($user);
  }

  public find($userId) {
    return $this->entityManager->find('domain\user\User', $userId);
  }
}
class UserService implements UserServiceInterface {
  public function changePassword(ChangePasswordCommand $command) {
    $user = $this->userRepository->find($command->getUserId());
    $user->changePassword(
      $command->getCurrentRawPassword(),
      $this->passwordCreator->hash($command->getNewRawPassword())
    );
    $this->userRepository->save($user);
  }
}
/**
 * @ORM\Entity
 */
class User {
  public function changePassword($currentRawPassword, $newPassword) {
    if (!$this->password->createdFrom($currentRawPassword)) {
      throw new InvalidArgumentException('Invalid password');
    }
    $this->password = $newPassword;
  }
}
Olvasás
class DbalUserFinder implements UserFinder {
  
  /**
   * @return UserDto[]
   */
  public function getUsers($page) {
    $this->dbalConnection->...
  }
}
class UserDto {
  private $name;
  private $email;

  // constructor + getters
}
Ami a magasabb szintű modulokban láthatók: UserServiceInterface, ChangePasswordCommand, UserFinder, UserDto. Ha az ember pub/subbal játszik, akkor a serviceből handler lesz és azt már nem direktben használja a client, egyébként a többi marad hasonló.

Ha még konkrétabb példára vagy kíváncsi, javaslom a már korábban belinkelt blogomat, a predaddy-t, valamint a hozzá készített egyszerű példát (ez utóbbi event source-os példa, abból is az a fajta, amikor nincs explicit command handler és repository mivel ezek automatikusan működnek, de pl. a read oldal teljesen hasonló).
11

Már elkezdtem olvasni.

inf3rno · 2014. Ápr. 1. (K), 23.52
Már elkezdtem olvasni. :-)

Próbálok clean architecture szerint, legalábbis azon alapelve szerint eljárni, hogy a business logic-nak tök lényegtelen kell, hogy legyen, hogy milyen adattároló megoldás van alatta, vagy hogy milyen ORM-et használ (ha egyáltalán használ) ahhoz, hogy az adat tárolást elérje. Ez azért van így, mert a business logic-nak valami olyasminek kellene lennie, ami teljesen keretrendszer független, és ezért gyorsan tesztelhető. Az összes keretrendszer függő részt, mint pl a data access ezért le kell választani róla adapterekkel. Ez a része meglepően egyszerű, egyedül egy modul futtató környezetet kellett csinálnom hozzá, ami párszáz sorból megoldható.

Egyelőre csak kísérleti jelleggel, de próbálok valami olyat létrehozni, ahol nem csak vertikálisan (rétegekbe), de horizontálisan (témakörök szerint) is szét vannak választva egymástól a modulok. Most leginkább arra vagyok kíváncsi, hogy vajon javul vagy romlik e a kód olvashatósága és tesztelhetősége, meg hogy egyáltalán megvalósítható e mindez kellő rugalmassággal... A stateless - stateful kérdésnél, amit említettél, ütköztem akadályba jelenleg...
12

Nagyon le akarod választani

szjanihu · 2014. Ápr. 2. (Sze), 00.33
Nagyon le akarod választani az ORM-et a rendszerről, ami nagyon helyes, de a fenti példám hol függ az ORM-től? A repository implementáció nyilván függ tőle, ez nem kérdés, de ezzel nincs semmi baj. Ha viszont az annotáció zavar (ami mindössze inline konfiguráció), vidd ki konfigurációs fájlba.
13

Okés! Ha mondjuk ORM helyett

inf3rno · 2014. Ápr. 2. (Sze), 00.48
Okés!

Ha mondjuk ORM helyett kézzel írott SQL-ekkel nyúlnék az adatbázishoz, egy kis forgalmú oldalon, akkor szerinted mennyivel nőne meg annak az esélye, hogy eltörik a data integrity? Egyáltalán a PHP-s ORM-ek biztosítják, hogy a konkurrens kérések ne zavarják egymást? Vagy ha mondjuk egy domain object több tárolási módot használ, pl fájlrendszer és adatbázis is, akkor hogyan tudom biztosítani, hogy a kettő szinkronban maradjon?

Jó, túl sok lesz a kérdésből... :-) Valamiért nem vagyok kibékülve az ORM-ek használatával, mert nagy rendszerek, és nem értem, hogy olyan egyszerű dolgokhoz, mint egy-egy sql megírása miért kell egy ekkora keretrendszer... Nem elég szimplán mindent bepakolni tranzakcióba, aztán annyi?
14

Concurrency issuek

szjanihu · 2014. Ápr. 2. (Sze), 08.38
Concurrency issuek előjöhetnek akkor is, ha nem használsz ORM-et, csak nem akartam már ezzel is bekavarni a fenti példában. De ha már felhoztad, itt van egy JPA-s leírás a témában. A Doctrineban sajnos elég gányul lett implementálva a lockolás, nagyon nehéz új megoldásokkal bővíteni, pedig igény lenne rá pl. részemről is.

Nem, a tranzakció nem elég, és érdekes kérdés, hogy lehet szinkronban tartani két repositoryt. Ilyen problémába még nem ütköztem és szerintem nem is nagyon jön elő a való életben, így első látásra szerintem csak eventual consistency érhető el.

Ha nem tetszik az ORM, mondanám, hogy használj Event Sourcingot (ES), de nem mondom, mert - nem bántásból - előbb próbálj meg normálisan használni ORM-et, tudd, mi az a concurrency és hogy kezelhető, használj DDD-t, majd CQRS-t, és majd utána jöhet az ES, ha egyáltalán szükség van rá. Sok ember szidja az ORM-eket, de nagy részük rosszul használja. A DDD és egyáltalán az aggregatekben való gondolkodás sokat segít és eliminál nagyon sok problémát.
16

Én egy kicsit máshogy

inf3rno · 2014. Ápr. 2. (Sze), 12.15
Én egy kicsit máshogy működöm, úgy értem, szeretek tájékozott lenni azzal kapcsolatban, hogy mik a lehetőségeim, aztán utána választani közülük... Szerintem felesleges végigjárni a gyakorlatban is mindegyiket, elég csak az elméletben, abból már általában látom, hogy melyik jön be, és melyik nem.

Ilyen problémába még nem ütköztem és szerintem nem is nagyon jön elő a való életben, így első látásra szerintem csak eventual consistency érhető el.


Nekem ilyesmi akkor szokott előjönni, ha képeket csatolok valamihez. A képek másolásánál is lehet valamilyen fájlrendszer hiba... Ez a fajta probléma általában nem annyira bonyolult, először a fájlt teszem a helyére, utána küldöm el a tranzakciót, aztán ha valami nem stimmel, akkor törlöm a fájlt. Szóval egyelőre csak soros megoldást tudok, párhuzamosat nem, pedig az lenne az igazi...

Köszönöm a linkeket, azt hiszem már csak az olvasás van hátra... :-)
18

Concurrency issuek

inf3rno · 2014. Ápr. 2. (Sze), 16.58
Concurrency issuek előjöhetnek akkor is, ha nem használsz ORM-et, csak nem akartam már ezzel is bekavarni a fenti példában.

Persze, hogy előjöhetnek, az ORM egyik feladata (gondolom én) a lockok automatizálása, hogy ne kövess el ezzel kapcsolatban hibákat.

Próbáltam keresgélni concurrency test-el kapcsolatos cikkeket, megoldásokat, de az eddigiek alapján úgy néz ki, hogy extrém nehezen tesztelhető dologról van szó. Találtam C++-hoz meg visual studio-hoz egy chess nevű tool-t, ami jó ilyesmire, de ennyi, kifújt...
Amit még írtak, hogy google go alapból úgy lett tervezve, hogy kezelje a konkurrenciát, bármit is jelentsen ez... :-)

Kérdés az, hogy egy kis látogatottságú oldalnál megéri e egyáltalán foglalkozni concurrency management-el... A leggyorsabb megoldás ilyen szempontból tényleg az, hogy beszórsz egy ORM-et az oldal alá, aztán kész...

Ahogy nézem doctrine sem valami jól tesztelt concurrency témakörben. Én legalábbis egyáltalán nem találtam ezzel kapcsolatos teszteket, de lehet nekem maradt ki valami... Közben találtam olyat sto-n, hogy doctrine-ben kézzel kell megadni, hogy milyen típusú lock-ot akarsz, de ez mondjuk 1 éves topic volt. Szóval a doctrine sem csodaszer ezzel kapcsolatban...

Összességében nekem az jött le, hogy a concurrency-vel kapcsolatban jobban járok PHP esetében, ha végigolvasom a pgsql dokumentációban a transaction isolation-al és a lock-al kapcsolatos részeket. Már így is jó ideje hiányosságom ez a témakör, csak nagy vonalakban vagyok tisztában azzal, hogy mennyi szopás van vele...
19

google go alapból úgy lett

Hidvégi Gábor · 2014. Ápr. 2. (Sze), 17.10
google go alapból úgy lett tervezve, hogy kezelje a konkurrenciát, bármit is jelentsen ez
A go natívan kezeli a konkurens feldolgozást, alapvető nyelvi elemeket ad hozzá (csatornák), eleve úgy lett megtervezve és elkészítve, nem pedig addícionális dologként, mint a legtöbb nyelvben, ahol egy libraryt kell hozzá betölteni.

Ettől függetlenül mindenképp több figyelmet igényel, mint egy átlagos, szinkron kód megírása, és csak nagyobb projekteknél lehet rá szükség, egy Apache vagy nginx nagyon sokáig elég.
20

Ettől függetlenül mindenképp

inf3rno · 2014. Ápr. 2. (Sze), 17.16
Ettől függetlenül mindenképp több figyelmet igényel, mint egy átlagos, szinkron kód megírása, és csak nagyobb projekteknél lehet rá szükség, egy Apache vagy nginx nagyon sokáig elég.


Én is úgy látom, hogy kis terhelésnél nincs szükség rá, mert nem valószínű, hogy ilyen jellegű problémák jelentkeznek. Majd akkor esek pofára, amikor kiderül, hogy mégis... :-)
21

A Doctrine-ban az API

szjanihu · 2014. Ápr. 2. (Sze), 17.31
A Doctrine-ban az API hasonló, mint a JPA-ban, csak kevesebb választási lehetőség van. Szóval teljesen jól működik az optimistic lock. PHP-szinten meg - sajnos - nincs concurrency issue, mivel nem multithreaded (tekintsünk el most a pthreadtől)

De szerintem ez már nagyon offtopic, lévén a domain objectek ORM függetlenek.
22

Ok, szóval doctrine-ben

inf3rno · 2014. Ápr. 2. (Sze), 17.59
Ok, szóval doctrine-ben alapból optimistic lock van. De concurrency test-ek nélkül nincs rá garancia, hogy a doctrine azt be is állítja a megfelelő helyen, és tényleg minden flottul megy...

Senki nem mondta, hogy nem lehet elkanyarodni az eredeti témától. Én speciel pont ezt szeretem a weblaboros fórumban...
23

Nem, nem csak optimistic lock

szjanihu · 2014. Ápr. 2. (Sze), 19.14
Nem, nem csak optimistic lock van, de ennek utána tudsz nézni a dokumentációban. Biztos vagyok benne, hogy van rá legalább unit teszt.
24

Félreértetted, az

inf3rno · 2014. Ápr. 2. (Sze), 20.34
Félreértetted, az alapbeállításra mondtam, hogy optimistic lock. Amúgy minden entity-nél be lehet állítani, hogy milyen típusú lock legyen hozzá, meg gondolom be lehet konfigolni más alapbeállításra is a rendszert.

Ha már így szóba került, akkor elolvasom az ezzel kapcsolatos részt is.
http://docs.doctrine-project.org/en/2.0.x/reference/transactions-and-concurrency.html

Arra gondoltam, hogy domain objectek helyett át lehetne adni egy task listet is a db-nek, hogy ezeket hajtsa végre ilyen és ilyen callback-ekkel, így atomi lenne a két réteg között az információ átadás, de valószínűleg könnyebben karbantartható a domain objectes megoldás.
68

Olvasgatok ezekben a

inf3rno · 2014. Ápr. 18. (P), 00.47
Olvasgatok ezekben a témákban, ha jól értem a CQRS kb annyit tesz, hogy kettéválasztják a kódot írásra és olvasásra, és az olvasást leegyszerűsítik, az írásnál meg a domain model alatt sokszor event sourcing-ot használnak.

introduction-to-domain-driven-design-cqrs-and-event-sourcing

Egyelőre minden világosnak tűnik, bár vannak kérdéseim. A legfontosabb, hogy az ES-nél hogyan akadályozzátok meg, hogy kifussatok a tárhelyből (ha pl a képeket fájlokban tároljátok, és sosem törlitek azokat sem), vagy hogy a túl sok record miatt totál belassuljon az adatbázis?

Egyelőre csak arra tudok gondolni, hogy bizonyos időközönként archiválni kell a dolgokat valamilyen más tárolóba, egyesíteni a régi event-ek hatásait, és törölni a régieket, illetve a fájlokat. Gondolom a nagy rendszerek, mint pl fb is valami hasonló módon működnek, ezért lehet egy-egy képet még évek után is elérni, holott már elméletileg régen törölve lettek. Ők valszeg sosem archiválnak, hanem inkább bővítik a tárhelyet. Bár újabban azt vettem észre fb-nál, hogy pár hét vagy hónap után már nincsenek a history-mban a megosztásaim.

A másik érdekes probléma, hogy a cqrs és a ddd hogyan jön össze?

Ha jól értem a cqrs arról szól, hogy elválasztjuk az írást az olvasástól azért, hogy az olvasás jóval gyorsabb legyen, ne kelljen egy csomó mapping-en keresztül mennie, hanem azonnal be tudjuk szórni az adatot a viewmodel-be. Szóval az olvasás egy csomó réteget átugrik, amik az írásban benne vannak, és ebbe akár a domain layer is beletartozhat, vagy nem?
70

A másodikat meg tudom

inf3rno · 2014. Ápr. 18. (P), 14.12
A másodikat meg tudom válaszolni, ott elég csak az írás részében a DDD-t követni, az olvasásnál meg talán lehet csalni.

Az ES-ről még olvasok, határozottan tetszik a hagyományos adattárolási megoldásokhoz képest, sokkal egyszerűbb megoldás, és határozottan hasznát tudom venni. Használtam már ugyanezt a megoldást, amikor az árazásnak kellett nyomonkövetni a történetét egy webshopban, szóval ez csak annak a kiterjesztése. Gondolom fölé lehet szórni egy jó csomó view-ot, és végeredményben ugyanazt kapjuk olvasás szempontból, mintha rendes tábláink lennének. Írás szempontból viszont sokkal könnyebb dolgunk van, plusz még sokkal több adatot le tudunk kérni, tudunk szép grafikonokat rajzolni, szóval a menedzsment is el lesz ragadtatva...
71

ES-nél szerintem a megfelelő

inf3rno · 2014. Ápr. 21. (H), 00.56
ES-nél szerintem a megfelelő archiválási megoldással a belassulás és a tárhely elfogyása is megakadályozható. Nem tűnik bonyolultnak olyan algoritmust írni, ami megkeresi a már nem használt eseményeket, kimenti őket fájlba, majd törli őket. A fájlrendszerrel való szinkronizálás is hasonló elvek mentén egyszerűen megoldható. Szóval összességében ES-ben nem látok semmi kivetni valót, valószínűleg használni is fogom, mert jóval fejlettebb, mint a hagyományos megoldások adatbázissal kapcsolatban.

Lehet úgy is rendszert építeni cqrs-el kombinálva, hogy külön adatbázist használunk a domain event-ekhez, és külön adatbázist az olvasásra. Az event-eket pedig egy bus-ra rakva egyesével végre lehet hajtani az olvasásra szolgáló adatbázison, és így szinkronba hozni a kettőt egymással konkurrencia vagy hibalehetőség nélkül. Annyi hátránya van ennek a megoldásnak, hogy az olvasásra szolgáló adatbázis nem feltétlen lesz szinkronban az event-eket tárolóval, főleg ha nő az írással kapcsolatos terhelés. Én szerintem kisebb terhelésnél nincs szükség ilyesmire, és elég csak view-okat építeni az event-ek fölé (ha relációs adatbázisban tároljuk őket), vagy bármi mást, ami aggregálja a bennük tárolt adatot, és kesseli az aktuális állapot lekérését.
72

Event Sourcing

Hidvégi Gábor · 2014. Ápr. 21. (H), 08.24
Idézet a cikkből:
How do you know that in few months time this data is not going to be important?
És ha sosem lesz szükség azokra az adatokra? Csak fölöslegesen bonyolódik a programkód. Ráadásul, mivel az eltéréseket tárolja az elmélet szerint, minél régebbi egy adat, annál lassabb lesz előhozni.

Mivel a tárhely manapság olcsó, ennél szerintem egyszerűbb és gyorsabb, ha a teljes sorról készítesz másolatot, ad absurdum a napi mentésből nyered vissza az adatokat.
73

Abban látok valamennyi

inf3rno · 2014. Ápr. 21. (H), 20.49
Abban látok valamennyi logikát, hogy ugyanabba az adatbázisba mentsem az event-eket és ugyanonnan olvassam ki mondjuk view-okon keresztül az aktuális adatot. Annyira nem bonyolult megoldani, de egyelőre én sem érzem fontosnak, hogy feleslegesen bonyolítva legyen az adatbázis szerkezete.
A külön read db-s és event storage-es megoldás egyáltalán nem jön be. Websocket-el el tudom képzelni, ahol event formájában kapnám meg a választ, viszont HTTP-vel nem értem, hogy hogyan lehet összeegyeztetni. A szinkronizálás a read db és az event storage között teljesen független az aktuális kéréstől, így nincs mód visszaküldeni bármilyen választ php esetében. Esetleg nodejs-nél be lehet tenni ugyanabba a daemon-ba, és lehet hozzácsapni eseménykezelőt, de így is egyrészt bonyolult, másrészt meg lehet, hogy időben annyira el lesz tolva a frissítés, hogy simán timeout-ol a böngésző vagy a webszerver. Egyáltalán nem tűnik nekem PHP-re szabott megoldásnak.

Ahol szerintem kifejezetten hasznos lehet az a kliens oldal. Ott le lehet tárolni js-ben, vagy bármi másban a lépéseket, aztán be lehet tenni a végére egy apply gombot, hogy tényleg menteni akarom, és egy kérésben elküldeni mindent a szervernek. Ritkán fordul elő azért ott is olyan probléma, hogy egy ilyen megoldást kellene alkalmazni.
79

Kicsit utánajártam azóta

inf3rno · 2014. Ápr. 23. (Sze), 04.16
Kicsit utánajártam azóta ennek a témának:

event sourcing előnyei:
- high availability (nagyon sok felhasználót ki tudsz szolgálni egyszerre, mert nem kell a concurrency kezeléssel foglalkoznod) vagy realtime visszaadnod az eredményt
- bármikor visszaállíthatod az adatbázist egy korábbi állapotba
- bármikor készíthetsz backup-ot különösebb erőlködés nélkül, elég az event-eket lemásolni
- bármikor módosíthatod a read adatbázisod szerkezetét, elég utána újra lefuttatni az event-eket és feltölteni a read adatbázist az új szinkronizációs kód segítségével (így pl a deploy-t is lehet teljesen automatizálni, nem kell kézzel hozzáigazítani az új szerkezethez a tárolt adatokat)

event sourcing hátrányai:
- általában eventual consistency-vel használjuk, legalábbis általában a high availability miatt szokták választani. emiatt eleve úgy kell tervezni az UI-t meg minden mást, hogy ennek megfeleljen. sok esetben ez működőképes, sok esetben viszont azonnali eredményt várunk... vannak megoldások, amikkel lehet tákolni a rendszeren, hogy növeljük a user experience-t. ezekhez általában a session-ben kell letárolni az elküldött kéréseket...
- szükség van konfliktus feloldó kód írására a szinkronizációhoz, bár ez lehet skip és hibaüzenet küldés ugyanúgy, mint egy normál rendszernél
- be kell lőni a cron-t vagy daemonokat kell használni a szinkronizációhoz, mert az nem azonnali
- kétféle aggregate kódot kell karbantartani, az egyik a write model-ben a lekérdezések (általában csak id szerinti lekérések), a másik meg a read model lekérései, vagy inkább a read model cache-ének a feltöltése, ha olyan a rendszer

Összességében szerintem csak akkor éri meg használni, ha nagy terhelésű a rendszer, egyébként nincs értelme foglalkozni vele.

És ha sosem lesz szükség azokra az adatokra? Csak fölöslegesen bonyolódik a programkód. Ráadásul, mivel az eltéréseket tárolja az elmélet szerint, minél régebbi egy adat, annál lassabb lesz előhozni.


Ez nincs így, mert általában külön adatbázist használnak a cacheléshez, szóval az olvasás mindig baromi gyors, az írásra viszont várni kell terheléstől függően, és nem kapsz azonnali választ, hogy sikerült e vagy nem (legalábbis ha eventual consistency-vel használják).
80

Ha egy processen belül oldod

szjanihu · 2014. Ápr. 23. (Sze), 10.52
Ha egy processen belül oldod meg a szinkronizációt, akkor bár külön tranzakció(ka)t használsz, végeredményben a válasz visszaküldésekor már ott vannak az adatok a read storageban. Feleslegesen ne bonyolítsd el, message queuet elég csak indokolt esetben használni.

Még mindig azt mondom, hogy a read storageba ne rakj semmiféle constraint.

Az unique email érdekes kérdés. Viszonylag kevés esetben van ilyen probléma egy rendszerben, de két lehetséges megoldás:
- Az aggregate ID-jét az emailből képzett hashből állítod elő, így írásnál hiba lesz ütközés esetén. Ez nyilván akkor nem elégséges, ha egy aggregateben több unique adat van.
- Használhatsz hibrid rendszert, pl. az ilyen típusú aggregatekhez csinálhatsz explicit táblákat, ahová már rakhatsz unique contraint.

A második megoldást javaslom: authentikáció során nem ID alapján keresed meg az aggregatet, hanem email és jelszó hash alapján. Az authentikációs/authorizációs feladatok külön bounded contextet képeznek, ahol eldöntheted, érdemes-e ES-t használni. Úgy tűnik nem. Viszont a felhasználó más jellegű adatai - amelyek függetlenek az említett feladatoktól - már más BC-be tartoz(hat)nak, ahol használhatsz ES-t.
81

Nagyon sok esetben a

inf3rno · 2014. Ápr. 23. (Sze), 13.09
Nagyon sok esetben a validációt a read model alapján csinálják. Ha elég gyors a rendszer, akkor nagyjából szinkronban lesz a kettő, és nagyon keveset téved csak. Az auth részét szinte mindenki kiteszi táblákba, mert egyszerűbb úgy, de még ez sem feltétlen muszáj, pl REST-nél elég egyszer ellenőrizni rendesen, utána úgyis külön cache-be teszed, mert baromi lassú. Szóval szinte mindegy, hogy hol és hogyan ellenőrzöd a cache alatt, ha az megvan 1-2 másodpercen belül...

Általában szétkapják modulokra a kódot, és bounded contextet használnak, akár teljesen eltérő jellegű read database-ekkel. Ahol key-value vagy column a jó, ott nosql-t, ahol meg relációs ott sql-t... Na jó ez mondjuk már tényleg a nagy rendszerekre vonatkozik, azt hiszem amazonról láttam egy videot (talán ezt), hogy ott így csinál(hat)ják. A szépsége az a dolognak, hogy a domain eventek miatt laza a csatolás, az event sourcing miatt meg nem igazán kell tartani adatvesztéstől, vagy bármi egyébtől, szóval gyakorlatilag azt és annyit teszel az event storage elé vagy mögé read model-nek, amit nem szégyellsz. Gyakorlatilag query cache-nek van, semmi többnek...

off:
Nagyjából megint összeszedtem egy cikkre való anyagot DDD, CQRS, event sourcing témában.
74

Annyi hátránya van ennek a

szjanihu · 2014. Ápr. 22. (K), 00.19
Annyi hátránya van ennek a megoldásnak, hogy az olvasásra szolgáló adatbázis nem feltétlen lesz szinkronban az event-eket tárolóval, főleg ha nő az írással kapcsolatos terhelés.

Így van, ez az eventually consistency. A legtöbb esetben valójában bőven elégséges megoldás az, ha nem azonnal jelenik meg az adat a képernyőn. Ha kevés az írás, akkor szinte azonnal megjelenik az adat, ha meg sok, akkor hagyományos módon megoldva belassulna a rendszer és sokáig tartana egy-egy write request.

Korábbiakra válaszolva:
Lehet DDD-t használni CQRS nélkül, lehet CQRS-t használni ES nélkül, sőt ezt kb. fordított sorrendbe is le lehetne írni. Nincs éles tapasztalatom ES-sel, és azzal, hogy viselkedik egy nagy DB-n, de ha snapshottolsz, akkor elég korlátos mennyiségű eventet kell betölteni, amelyekre az indexelt aggregate ID alapján szűrsz, és amelyeket version alapján rendezel. Egyébként a snapshotok előtti eventeket törölheted a DB-ből, nincs szükség rájuk (ha csak később neked nem lesz rájuk szükséged).

A külön read db-s és event storage-es megoldás egyáltalán nem jön be. Websocket-el el tudom képzelni, ahol event formájában kapnám meg a választ, viszont HTTP-vel nem értem, hogy hogyan lehet összeegyeztetni. A szinkronizálás a read db és az event storage között teljesen független az aktuális kéréstől, így nincs mód visszaküldeni bármilyen választ php esetében.

Mennyivel más ez, mintha ugyanabban a DB a read storage is? A szinkronizációt ugyanúgy PHP-ben, programozottan oldod meg. Bár csak POC, kb. ennyiből áll két event lekezelése és a read storage frissítése.

Ha egy command/event, szóval bármilyen message feldolgozása közben hiba van, érdemes azt és a kivételt egy error queue-ba irányítani, így egyrészt azt lehet monitorozni, másrészt később egy esetleges hibajavítást követően újra fel lehet azt használni.

A másodikat meg tudom válaszolni, ott elég csak az írás részében a DDD-t követni, az olvasásnál meg talán lehet csalni.

Így van, olvasásnál nem kell a domain, nem kell az üzleti logika, ott pusztán adatokra van szükség, amelyek a megfelelő formában, lehetőleg minél gyorsabban rendelkezésünkre állnak.

Nem tudom, linkeltem-e már, itt egy általam elkövetett ES-es példa projekt, csak hogy látni lehessen, mégis eszik-e vagy isszák, meg hogy néz ki minden predaddyvel.
75

Nem tudom linkelted e már,

inf3rno · 2014. Ápr. 22. (K), 01.25
Nem tudom linkelted e már, megtaláltam én anélkül is. Predaddy jónak tűnik CQRS témában, valószínűleg használni is fogom.

Mennyivel más ez, mintha ugyanabban a DB a read storage is? A szinkronizációt ugyanúgy PHP-ben, programozottan oldod meg. Bár csak POC, kb. ennyiből áll két event lekezelése és a read storage frissítése.


Nem a szinkronizációval van bajom, azt egyszerűen meg lehet oldani. A probléma az, hogy kérés-válasz alapú megoldásoknál nem működik az event sourcing, mert teljesen eltérő consistency model-t használ. Egy REST-hez immediate consistency kell, hogy azonnal vissza lehessen küldeni a válaszban, hogy mi történt, pl egy erőforrás létrehozásánál automatikusan át lehet irányítani az erőforrás url-jére, stb... Az event sourcing viszont eventual consistency-t használ, szóval a kettő teljesen üti egymást. Olyan delivery megoldásoknál, ahol elégséges az eventual consistency, az event sourcing egy jó megoldás lehet. Ahol immediate consistency kell, ott is le lehet menteni az adatok mellett az event-eket is, és fel lehet használni őket backup vagy migrációs célokra, esetleg történeti áttekintést nyújtó funkciók fejlesztésére. Szóval az alap ötlet, hogy mentsük a domain event-eket, a REST esetében sem teljesen értelmetlen...

Magát a szinkronizációt személy szerint nem tartom egy jó ötletnek, mert können sérülhet a data integrity. Ha több domain event van egy tranzakción belül, akkor a tranzakciós határokat az event storage nem fogja tárolni, és előfordulhat, hogy az egyik event gond nélkül bekerül a read db-be, míg a másik valamilyen constraint megsértése miatt nem. Ezzel a megoldással gyakorlatilag a tranzakciók semmit sem érnek. Ez nyilván azért van, mert megpróbáljuk kézzel lekezelni őket késleltetve, ahelyett, hogy az adatbázisra bíznánk...
76

Az eventually consistency

szjanihu · 2014. Ápr. 22. (K), 12.37
Az eventually consistency csupán annyit jelent, hogy több, egymást követő tranzakció után lesz konzisztens az adatbázis. A read model frissítését megoldhatod ugyanabban a PHP processben, még mielőtt visszaküldenéd a kliensnek a választ. Szóval az, hogy szinkron, vagy aszinkron végzed el a szinkronizációt, teljesen rajtad múlik. PHP-ben az aszinkron feldolgozáshoz nem kicsit kell trükközni (külön process és/vagy messaging queue). Alapesetben nyugodtan dolgozd fel az eventeket szinkron módon és csak indokolt esetben válassz aszinkron (nem blokkoló) megoldást.

előfordulhat, hogy az egyik event gond nélkül bekerül a read db-be, míg a másik valamilyen constraint megsértése miatt nem

A read storageben felesleges bármiféle constraint rakni, lévén a domain eventek validált business folyamat eredményeképp keletkeznek, vagyis nem kell őket újra validálni - ami megtörtént az megtörtént. Ha szinkronizáció során egy event feldolgozása sikertelen, az valamilyen "egyszerű" hiba miatt lehet, mivel itt nem szabad komplex logikának lennie. Épp ezért talán elégséges az előző bejegyzésemben írt error queue-s megoldást alkalmazni.
77

Jó, de hogyan tudok egy

inf3rno · 2014. Ápr. 22. (K), 16.25
Jó, de hogyan tudok egy unique name constraint-et érvényesíteni? Tegyük fel, hogy van egy olyan forgatókönyv, hogy az event storage-be bekerült egy felhasználó, de még vár a szinkronizációra. Ekkor egy másik felhasználó regisztrál ugyanolyan néven. Hogyan tudom ellenőrizni, hogy az a név már foglalt? A read db-ben még nem az, mert nem került sor a szinkronizációra, az event storage meg nem arra való, hogy kibontsunk minden event-et, és ellenőrizzük benne a neveket (gondolom én). Szóval a végeredmény valszeg az lesz, hogyha van constraint a read db-n, akkor nem engedi lejátszódni a második regisztrációt szinkronizációnál, ha meg nincs, akkor meg két felhasználó lesz ugyanolyan néven. Ez persze csak arra az esetre vonatkozik, amikor a szinkronizáció nem egy tranzakcióban megy az event-ek mentésével, hanem teljesen külön játszódik le... Általában ez utóbbit szokták event sourcing-on érteni.
78

Ez egy baromi jó előadás a

inf3rno · 2014. Ápr. 22. (K), 22.42
Ez egy baromi jó előadás a témában: Command-Query Responsibility Segregation by Udi Dahan

Nekem az jött le, hogy az eventual consistency a legtöbb esetben elfogadható, mármint nagyon sok esetben, ha belegondolunk. Általában elég az új állapotot csak az azt létrehozó kliensében jelezni, és a szerveren nyugodtan tárolhatjuk esemény formájában a módosítást, amit valamikor a jövőben végrehajtunk, vagy elvetünk... A gond itt az egymásra épülő command-eknél van. Ezeknél megkerülhető az azonnali válasz, ha a kliens-ben tároljuk a módosításokat, és folyamatosan küldjük el azt a szervernek a háttérben. Így a kliens által megjelenített adat folyamatosan up to date. Viszont így belefuthat a felhasználó olyan helyzetekbe, hogy dolgozott a módosításon egy csomót, és egy konkurrens módosítás miatt az egész munkája elveszett, holott végig azt hitte, hogy sínen van minden. Ez ami nagyon nem jó ES-el kapcsolatban, meg ezzel az aszinkron read-write szinkronizációval kapcsolatban. Ha ezt sikerülne megoldani valamilyen módon, akkor leválthatná a most elterjedt ORM-es, relációs megoldásokat.

Eventual consistency in REST APIs
Ez is azt írja, hogy feladat függő a dolog, szóval hogyha immediate consistency-re van szükség, akkor azt kell használni, ha meg nincs rá szükség, akkor visszatérhetünk egy 202 accepted header-el REST-nél, aztán később feldolgozzuk a kérést.

Ahogy nézem vannak alternatívái az event sourcing-nak. Eventual consistency a read modelnél elérhető úgy is, hogy erre felkészített adatbázist választunk:
Choosing Consistency By Werner Vogels (Amazon SimpleDB)


Ami még érdekes lehet, hogy kis terhelésű rendszereknél lehet szerver oldali read model nélkül használni, ha csak id alapú lekérések vannak, és nincsen keresés... Bizonyos időközönként a szerver csinálhat snapshot-okat, ha lassú lenne, de maga a kliens is megteheti ezt mondjuk localstorage segítségével... Na meg persze lehet takarítani az event-et sorát, hogyha pl egy created és egy deleted kioltja egymást, akkor sokszor nincs sok értelme bennhagyni... Ezeket az event alapú megoldásokat pl el tudnám úgy képzelni, hogy minden user bizonyos event-eket figyel, aztán ha olyan event érkezik a domain model-től a kérések validálása után, akkor megkapja azt... Egy chat-et pl baromi egyszerűen meg lehet valósítani ilyen elven, de szerintem azon kívül még baromi sok dolgot is...

off:
Én pl most azt tervezem, hogy robotoknál a sampling rate-et befolyásolom az alapján, hogy a feldolgozási sorban mennyi event van, illetve hogy ezeknek a száma időben nő vagy csökken... Na jó ez a része egyelőre csak fejben van meg, még nem kezdtem el komolyabban foglalkozni a robotozás témájával, de kapásból egy érdekes kérdés, hogy socket-ekkel event alapon csináljam e vagy rest-el kérés-válasz alapon... Az egyik arról szól, hogy folyamatosan kapom az adatokat a szenzor hálózatról, aztán figyelem őket, és reagálok, a másik meg arról szól, hogy csak akkor kapok adatot, ha kérek... Nekem az első megoldás ami szimpatikusabb, de valószínűleg gyorsabban fogja meríteni az aksit, mint csak akkor kérni adatot, ha tényleg kell. Na most már tényleg nagyon elkalandoztam :P
7

Csatolás

vbence · 2014. Ápr. 1. (K), 15.35
A domain objectek és az adatmentés módja között szoros a csatolás.

Jó esetben ez nem igaz. Nem PHP-s példa, de a JPA például pont standard annotációkat is definiál, ami alatt elvileg kicserélhető az ORM. - Természetesen ilyenkor le kell mondjunk a finomabb hangolás lehetőségeiről ami eszközfüggő.

Azonban enélkül sincs nehéz dolgunk. Ha egy XML alapú konfigot használunk (annotációk helyett), akkor mondjuk egy XSLT segítségével konvertálhatunk a két ORM konfigurációja között.

Egy másik lehetőség, hogy saját annotációkat vezetünk be, és ehhez írunk egy konfig-generálót (én pl Doctrine-hoz megtettem), ekkor az ORM lecserélésekor (a konfig-generátort kell megírni az újabb eszközhöz).

Ha a réteget amivel kapcsolatban vagyunk lecseréljük (legyen az ORM, vagy adatbázis API), mindenképpen megrázkódtatással jár hacsak nem a lehető legminimálisabb funkcionalitást használtuk.
9

Engem inkább olyan jellegű

inf3rno · 2014. Ápr. 1. (K), 20.23
Engem inkább olyan jellegű dolgok aggasztanak, hogy mi van, ha több adatbázist szeretnék használni egyszerre, mondjuk egy pgql, egy dokumentum, meg egy gráf adatbázist, mert polyglot persistence-hez van éppen kedvem. Így létezhetnek olyan domain objectek, amelyek egyszerre több eltérő adatbázishoz tartozhatnak. Ha tényleg laza a csatolás az adatmentés módja és a domain objectek között, akkor nem okozhat semmilyen problémát lekódolni egy ilyen projektet. Ez valóban így van?
15

Limitációk

vbence · 2014. Ápr. 2. (Sze), 09.46
Egyelőre nem látok olyat, hogy több perzisztencia eszköz "összedolgozna". Vagyis használhatsz egyszerre több különböző konfigurációt, de akkor le kell mondanod olyan kényelmi funkciókról, mint a lazy loading, ahol az eszköz tud az objektum gráfról, és szükség esetén betölti az adatokat, ha letévedsz a gráf éppen kiSELECTelt részéről.

Heterogén perzisztencia esetén ha egy objektum rendelkezik olyan mezővel, amit egy másik eszköz felügyel, azt kénytelen vagy tranzient-nek jelölni, és manuálisan (vagy talán egy köztes rétegben) gondoskodni arról, hogyan kell betölteni a gráf azon részét.

Ez utóbbit el tudom képzelni AOP segítségével, ahol az illető getterre rákapcsolsz egy advice-t ami elvégzi a betöltést a másik eszközzel. Így nem szennyezed be a business objektumodat adateléréssel és megmarad a kényelem. (Ez nem különbözik sokban attól, ahogy az ORM egyébként is végzi a lazy loadingot, azaz hogy eltéríti a gettereket egy proxy objektum segítségével). - Erre nem hizsem, hogy sok esetben szükség lesz, vagyis viszonylag kevés kapcsolódási pontot képzelek el a gráf egyik helyen tárolt részéről a másik felé.

(Tipikusan olyan feladatotra gondolok, mint egy GoogleDocs-szerű dokumentumszerkesztő, ahol a metaadatok lehetnek RDBMSben, a dokumentum tartalma meg mondjuk MongoDBben. - Két jól elkülöníthető gráf, itt konkrétan egy darab kapcsolódási ponttal).
17

Egyelőre nem látok olyat,

inf3rno · 2014. Ápr. 2. (Sze), 12.29
Egyelőre nem látok olyat, hogy több perzisztencia eszköz "összedolgozna". Vagyis használhatsz egyszerre több különböző konfigurációt, de akkor le kell mondanod olyan kényelmi funkciókról, mint a lazy loading, ahol az eszköz tud az objektum gráfról, és szükség esetén betölti az adatokat, ha letévedsz a gráf éppen kiSELECTelt részéről.


Érdekes, megpróbálok keresni, szerintem biztosan vannak ilyen eszközök is.
25

Hallgass az eszedre!

Hidvégi Gábor · 2014. Ápr. 2. (Sze), 21.17
interactor, entity, DTO, domain object, ORM, perzisztens, annotáció, use case, business logic, architecture style, hexagonal, delivery method, interface csomag, storage modul, stateless service, always valid, application service, CQRS, destination objektum, fluent interface, aggregateken átívelő invariánsok, validációs szabályok, data transfer object, itt untam meg

Buzzword Driven Development Isn't Gonna Help You
26

Már vártam valami hasonló

szjanihu · 2014. Ápr. 3. (Cs), 09.33
Már vártam valami hasonló linket tőled. Amíg vannak ilyenek, mint te, nekem addig biztosítva van a munkám. Örök hála.
27

Maga a cikk nem hülyeség,

MadBence · 2014. Ápr. 3. (Cs), 10.24
Maga a cikk nem hülyeség, csak egy kicsit túl nyilvánvaló dolgokat ír le. Ha ráböksz véletlenszerűen egy buzzwördre, hogy na akkor most így fogunk fejleszteni, az nem biztos, hogy célravezető.
28

Pontosan. Mert mi van akkor,

Hidvégi Gábor · 2014. Ápr. 3. (Cs), 10.39
Pontosan. Mert mi van akkor, ha egy egyszerűbb munkánál nincs szükség ilyen mértékű absztrakcióra? Én inkább fordítva közelítem meg a dolgot, és a refaktorálások után derül ki, hogy na, ez a projekt megfelel a DDD elveinek.
32

Nem veszel figyelembe egy

inf3rno · 2014. Ápr. 3. (Cs), 12.18
Nem veszel figyelembe egy fontos tényezőt: Egy rosszul elkezdett projektet DDD-re refaktorálni akár sokszor hosszabb idő is lehet, mint újra megírni nulláról az egészet. Ezért van az, hogy előbb gondolkodunk, aztán meg kódolunk...

Nem igazán tudok mérőszámokat arra, hogy mikortól éri meg kézzel írt SQL-ek meg spagetti kód helyett DDD-re váltani, de én úgy vagyok vele, hogy nekem már 1 sor kód után jobb érzés oo kódot írni, mert az szép, a másik meg ronda. A szépség persze relatív... :-)
35

Gondolkodhatsz akármennyit,

Hidvégi Gábor · 2014. Ápr. 3. (Cs), 12.55
Gondolkodhatsz akármennyit, rengeteg probléma akkor derül ki, amikor a rendszer már előrehaladott állapotban van/már használják, vagy akár közben is változhat a specifikáció. Ennek előfordulási valószínűsége egyenes arányosságban van a projekt nagyságával.

A szépségről pedig neked is linkelek egy nagyon jó bejegyzést: Beyond clean code.
There are only two types of code, code that delivers business value, and code that doesn't.

As an industry, we have come to value code that looks pretty. We have come to value readability and correctness. But for some reason, we never really talk about the fact that said code needs to deliver business value. The cleanest code that doesn't deliver value is still crap.
36

Ezt az idézetet nem értem

BlaZe · 2014. Ápr. 3. (Cs), 20.03
Ezt az idézetet nem értem hogy jön ide. Ha haszontalan kódot írsz, annak nincsen haszna, akkor se, ha szép. Ok, de ezzel a felfedezéssel még senki nem lesz híres :) Ezzel arra szeretnél rámutatni, hogy a szép (értsd: olvasható, karbantartható) kód öncélú és nincs business értéke? Pont azért kell ilyen kódot írni, és megfelelő absztrakciókat beletenni, amit az első bekezdésben írsz.
44

+1

bamegakapa · 2014. Ápr. 4. (P), 00.36
Pont azért kell ilyen kódot írni, és megfelelő absztrakciókat beletenni, amit az első bekezdésben írsz.

Bennem is ez merült fel.
45

1nf3rn0 következő mondatára

Hidvégi Gábor · 2014. Ápr. 4. (P), 08.58
1nf3rn0 következő mondatára reagáltam vele:
Nem igazán tudok mérőszámokat arra, hogy mikortól éri meg kézzel írt SQL-ek meg spagetti kód helyett DDD-re váltani, de én úgy vagyok vele, hogy nekem már 1 sor kód után jobb érzés oo kódot írni, mert az szép, a másik meg ronda.
És itt most épp nem az OO-val van baj vagy az absztrakcióval, hanem amiért a 25-ös hozzászólásban lévő linken is rámutatok, hogy a megfelelő eszközt célszerű használni, de sokan már előre eldöntik, hogy a problémákat egy bizonyos módszerrel oldják meg.
50

a megfelelő eszközt célszerű

inf3rno · 2014. Ápr. 4. (P), 13.24
a megfelelő eszközt célszerű használni, de sokan már előre eldöntik, hogy a problémákat egy bizonyos módszerrel oldják meg


Én úgy gondolom, hogy az én megoldásom a megfelelő eszköz, te meg úgy gondolod, hogy a tiéd, 1:1, hozz bizonyítékot!
53

1:1

Hidvégi Gábor · 2014. Ápr. 4. (P), 14.34
Kétféle projekt létezik:

1, Egy újabb CMS-t kell írni, azaz semmi újat nem kell kitalálni, már csináltál ilyet, így pontosan tudod, hogy milyen eszközöket (jelen esetben paradigmákat, például tervezési mintákat, absztrakciókat) fogsz felhasználni. Ilyen esetben a te megoldásod a megfelelő eszköz.

Ezen eszközök használatával gyorsan lehet hatékony kódot írni.

2, Egy új ügyfél egyedi problémáját kell megoldani. Ilyenkor elsőre csak egy célt tudsz kitűzni, amit el kell érni, de még a legalaposabb tervezés után is egy csomó minden fejlesztés/használat közben derül ki. Nagyjából amikor elkészül az első változat, akkor látod át, hogy mire is volt szüksége az ügyfélnek, és ekkor kezdheted el igazából refaktorálni a kódot, előtte mindenképp spagetti lesz. Ekkor kerülnek bele a különböző minták, ekkor ismered fel, hogy mit lehet/kell absztrakcióval megoldani.

Amennyiben előre definiáltad volna, milyen eszközöket használsz, akkor előre meg is kötötted volna a kezed, ami valami módon mindenképp a munka kárára válik.


Létezik egy harmadik lehetőségi is: amennyiben a birtokodban van a Bölcsek Köve, úgy olyan módszert alkalmazol, ami csak tetszik.
54

2, Egy új ügyfél egyedi

inf3rno · 2014. Ápr. 4. (P), 15.12
2, Egy új ügyfél egyedi problémáját kell megoldani. Ilyenkor elsőre csak egy célt tudsz kitűzni, amit el kell érni, de még a legalaposabb tervezés után is egy csomó minden fejlesztés/használat közben derül ki. Nagyjából amikor elkészül az első változat, akkor látod át, hogy mire is volt szüksége az ügyfélnek, és ekkor kezdheted el igazából refaktorálni a kódot, előtte mindenképp spagetti lesz. Ekkor kerülnek bele a különböző minták, ekkor ismered fel, hogy mit lehet/kell absztrakcióval megoldani.

Amennyiben előre definiáltad volna, milyen eszközöket használsz, akkor előre meg is kötötted volna a kezed, ami valami módon mindenképp a munka kárára válik.


Ez így egyáltalán nem igaz. Le kell ülni az ügyféllel, megbeszélni mit akar leírni a user story-t, csinálni belőle use case-eket, és azok alapján már lehet TDD-vel megvalósítani. Abban igazad van, hogy az eszköz választást jobb minél későbbre hagyni, de a hexagonal architecture, clean architecture, DDD, stb... pont ilyen célból lett kitalálva, hogy ne kelljen azonnal eszközt választani, csak meghatározni felületeket, amiket használni fogsz a projektedhez. Pl adatbázis helyett simán betehetsz minden repository-t egy-egy json fájlba és csinálhatsz egy fájlrendszeres modult. Később meg ha úgy gondolod, akkor hozzácsaphatsz egy mysql-es modult, ha a relációs adatbázis mellett döntenél... A projekt többi részének teljesen mindegy, hogy milyen eszközöket használsz a perzisztens adat tárolásra. Ugyanígy tökmindegy kell, hogy legyen nekik a delivery method, szóval hogy mondjuk REST Api-n keresztül, vagy hagyományos webes felületen kapják e a kéréseket. Persze lehet úgy is fejleszteni, ahogy te mondod, hogy később refaktorálod, csak sokkal kevésbé hatékony, és nem feltétlen kapsz egy átgondolt szerkezetet a végén...
59

egy csomó minden

BlaZe · 2014. Ápr. 4. (P), 20.04
egy csomó minden fejlesztés/használat közben derül ki. Nagyjából amikor elkészül az első változat, akkor látod át, hogy mire is volt szüksége az ügyfélnek, és ekkor kezdheted el igazából refaktorálni a kódot, előtte mindenképp spagetti lesz.
Pont ez az, amiért azokat a módszereket kell használni, amikről itt többnyire szó van. Nagyon nem mindegy, hogy egy spagetti kódot kell refaktorálni, vagy egy normálisan felépítettet.

Egy tapasztaltabb fejlesztő tudja, hogy milyen rétegei lesznek annak az alkalmazásnak, amit le kell fejleszteni. Akkor is, ha esetleg a speckó változik közben. Nemkülönben ha betartasz bizonyos szabályokat, laza csatolást használsz stb, akkor viszonylag fájdalommentesen tudsz leválasztani/hozzárakni/átírni dolgokat, hiszen egy viszonylag jól izolált részen dolgozol, bármihez is kell nyúljál. Míg ez nagyon nem igaz annál a megközelítésnél, amit felhoztál ellenpéldának.
37

Az én világomban a szépség és

inf3rno · 2014. Ápr. 3. (Cs), 20.17
Az én világomban a szépség és a minőségi kód nem zárja ki egymást.
33

Hohó, azért az, hogy csak úgy

MadBence · 2014. Ápr. 3. (Cs), 12.29
Hohó, azért az, hogy csak úgy hűbelebalázs módjára nekiállunk kódolni, az megint csak nem megy. Az a kerék feltalálásának az esete. Használjunk a best practice módszereket, azért hívják őket így, mert nem hülyeségek (időt, tehát pénz takarítunk meg velük).
Viszont ne azért használjuk őket, mert csak, hanem mert az adott problémát hatékonyan megoldják (ez feltételezi, hogy ismerjük az adott buzzwörd mögött lévő tényleges dolgot), hatékonyabban, mint a másik XYZ buzzwörd (tehát össze is tudjuk őket hasonlítani).
34

Praktikák

Hidvégi Gábor · 2014. Ápr. 3. (Cs), 12.46
Természetesen vannak ilyenek, például a külön adatbázisosztály, a programlogika és megjelenítés szétválasztása stb.

Cserébe itt egy ellenvélemény, és ennek is van komoly alapja: Reinvent the wheel!.
39

Más dolog éles projektet

inf3rno · 2014. Ápr. 3. (Cs), 20.28
Más dolog éles projektet kódolni, és megint más dolog kísérleti jelleggel kódolgatni... A cikk, amit linkeltél a második esetre illik csak, mi meg az első esetről beszélünk.
29

Ahhoz, hogy szakmabeliek

bamegakapa · 2014. Ápr. 3. (Cs), 11.28
Ahhoz, hogy szakmabeliek beszélgetni tudjanak, csak kellenek elnevezések, nem?
30

Hány

Hidvégi Gábor · 2014. Ápr. 3. (Cs), 11.53
Hát persze, csak nem mindegy, mennyi. Vajon ugyanarról beszélnek? A fenti szöveg fele angol kifejezésekből áll, ugyanazt értik mindketten alatta? Ha valamiről ennyit kell magyarázni, ennyi elnevezés kell hozzá, hogy érthető legyen, az elfogadható?
31

És a helyzetet még az is

inf3rno · 2014. Ápr. 3. (Cs), 12.16
És a helyzetet még az is bonyolítja, hogy sokszor különböző szavakat használunk ugyanazokra a dolgokra, mert nekem az elején még elég homályos képem volt csak a dologról. Most már egy fokkal tisztább, de még most is van mit tanulnom...
38

A szakma nyelve az angol.

szjanihu · 2014. Ápr. 3. (Cs), 20.19
A szakma nyelve az angol. Arról pedig az egyén tehet, ha nem ismeri, vagy rosszul használja a kifejezéseket. Szeretünk nevet adni a dolgoknak, mozaikszavakat kitalálni, ilyen "hülye" világban élünk. Rád is hivatkozhatnék úgy, hogy
a weblabor tag, aki szeret 'programozópukkasztó' blogmarkokat beküldözgetni és alapvető dolgok értelmét megkérdőjelezni úgy, hogy látszólag fogalma sincs a témákról

Ehelyett csak annyit mondok:
a Hidvégi megint alkotott
40

Bocsi :D

inf3rno · 2014. Ápr. 3. (Cs), 20.36
Bocsi :D
41

Miért ORM?

Vilmos · 2014. Ápr. 3. (Cs), 22.05
Kezdőre jellemző kérdés, de azért felteszem. Eddig adatbázis ügyben a PDO-t javasoltátok. Megnéztem a korábban linkelt Doctrine leírást, batch feldolgozás címszó (11.2.2. Iterating results). Pont úgy néz ki mint a "prepared statement". Ez valami köztes nyelv mint a Smarty, vagy valahol előnye is van a PDO-val szemben?
$batchSize = 20;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach($iterableResult AS $row) {
    $user = $row[0];
    $user->increaseCredit();
    $user->calculateNewBonuses();
    if (($i % $batchSize) == 0) {
        $em->flush(); // Executes all updates.
        $em->clear(); // Detaches all objects from Doctrine!
    }
    ++$i;
}
42

Off

vbence · 2014. Ápr. 3. (Cs), 22.36
Ez itt elég offtopic. Új témában szivesen válaszolok.
43

A PDO egységes felületet ad

inf3rno · 2014. Ápr. 3. (Cs), 23.20
A PDO egységes felületet ad ahhoz, hogy adatbázishoz tudjál csatlakozni, és annak kéréseket küldeni. A kéréseket a PDO-val az adatbázisod nyelvén pl MySQL vagy PostgreSQL küldöd. Az ORM-ek egy további absztrakciós réteget jelenetenek efelett, ezek az általad megadott kéréseket átfordítják az aktuális adatbázis nyelvére, így bármikor legyerélheted mondjuk a MySQL adatbázisodat PostgreSQL adatbázisra, nem kell változtatnod a kódodon. Az SQL nyelv, ami a példában van az DQL (gondolom doctrine query language), amit a doctrine nevű ORM fordít át az aktuális adatbázis nyelvére. De persze nem muszáj lekérdező nyelvet használni, mert ahogy az ORM nevében is benne van, tud object relation mapping-et csinálni. Szóval az adatbázis tartalmából tud neked automatikusan objektum gráfot csinálni, ha megmondod neki, hogy hogyan tegye. Így gyakorlatilag egy deka SQL-t nem kell megírnod ahhoz, hogy a relációs adatbázist csatolj a rendszeredhez, plusz a doctrine kezeli a lockokat is helyetted, szóval a konkurrens kérések által okozott esetleges hibákkal sem kell megküzdened... Összességében sokkal egyszerűbben lehet egy ilyen rendszerrel használni az adatbázist, mintha PDO-ból kézzel írt SQL-eket küldözgetnél.

Az eredeti kérdés a domain objectekre vonatkozott, az ORM-ek csak úgy kerültek be a témába, hogy ők képesek automatizált módon létrehozni ilyeneket. De meg lehet csinálni a domain objecteket kézzel is, ugyanúgy SQL-t kell írni, meg lockokat beállítani, meg anyámkínja... Adat struktúrákkal is ugyanúgy meg lehet csinálni ugyanazt, csak ugyanannak a kódnak kell lefutnia, mint amit a domain object csinál. A domain object-ek használata abban segít, hogy leválaszd az adatelérést az üzleti logikájáról az alkalmazásodnak. Ezt általában elég nehéz megtenni, mert sokszor nem tudod eldönteni, hogy mi tartozzon egyik, és mi a másik rétegbe, illetve mi legyen a határfelületükön. Ennek az az oka, hogy SQL-ben sok olyan dolgot meg lehet csinálni az adatbázis szerveren, amit amúgy a PHP-re vagy más HTTP szerveren futó nyelvre bíznál. Ha úgy döntesz, hogy valamit SQL-re bízol, akkor az a data access-be vándorol, ha meg úgy, hogy PHP-re bízod, akkor meg dönthetsz, hogy a data access-ben vagy a business logic-ban legyen. Én jelenleg nem tudok az ilyen jellegű döntésekre biztos receptet, de kíváncsi vagyok, hogy a nálam tapasztaltabbak hogy szokták megoldani, az ilyen jellegű problémákat...
47

Objektum gráf, perzisztencia

Vilmos · 2014. Ápr. 4. (P), 11.20
Kösz a magyarázatot, így nem kell új topic-ot nyitnom.
A DQL érthető, PDO jellegű szerkezet. Inkább ez mint a QueryBuilder. Az egy vicc.

Szóval az adatbázis tartalmából tud neked automatikusan objektum gráfot csinálni, ha megmondod neki, hogy hogyan tegye.

Mondjuk YAML formában tárolom a tábla-mező szerkezetet. A mezőnkénti adatbázis-objektum megfeleltetéshez nekem kell kódot írnom, amit az ORM meghív szükség esetén, vagy végrehajt valami varázslatot?

Perzisztencia

Van róla magyarázat emberi nyelven?
( Találkoztam jó pár angol szóval, melyekről kiderült nem újak csak máshogy ismertem őket, például: hash array - asszociatív tömb, callback function - amit a szoftveres megszakítás végrehajt, serialíze - memória változók mentése sztringe/fájlba.
Aztán vannak értelmezési problémáim, egyik kedvencem a dependency injection. Oké, lefordítható magyarra is, de mire való? Tévedés joga fenntartva - úgy hiszem, az objektumok elérését teszi lehetővé, pont úgy mint a normál függvények. Az objektumok egyetlen példányváltozóba vannak összevonva, a teljes szerkezet globálissá van téve. )
48

Dependency Injection

Hidvégi Gábor · 2014. Ápr. 4. (P), 11.35
Tegyük fel, hogy van egy osztályod, ami a felhasználók menedzsmentjét végzi, beolvassa őket, ha megváltozik az adatuk, elmenti. Ezt úgy is megoldhatod, hogy az adatbáziscsatolót magában a kódban példányosítod, lefuttatod a lekérdezéseket, visszaadod az eredményt, viszont ekkor a felhasználómenedzsment modul függeni fog az adatbáziscsatolótól.

Tegyük fel, hogy függetleníteni szeretnéd tőle, például teszteléshez vagy lehetővé szeretnéd tenni, hogy más adatforrásokkal dolgozhasson egyszerűen a programod. Ilyenkor nem közvetlenül példányosítod a csatolót a kódban, hanem átadod paraméterként (beinjektálod).
56

Függetlenség

Vilmos · 2014. Ápr. 4. (P), 18.24
Ahogy a nyelvet figyelem lassan mindennek van/lesz objektumos felülete. (mysqli-nek már van) Az objektum példánya injektálható és mégsem lesz cserélhető az adatforrás, mivel az akármilyen változó mögött a konkrét interfész függvényei állnak. Más nem is állhat.
Látszólag helyesen jártunk el. Nem találtuk fel újra a kereket, szabványosan dolgoztunk, követtük a nyájat és kudarc.
Úgy gondolom a függetlenséget a "wrapper" (burkoló osztály?) biztosítja. Az a belsejében persze függ valamitől, de számos hívásában már nem.

A DI-vel kapcsolatban az az érzésem, más területen futott be karriert mint amiről beszélnek. (a viagra is szívgyógyszer lett volna) Ki lehet próbálni, használsz egy szerény objektum könyvtárat, mondjuk 20 különböző osztályt. Nincs a fő objektumba belegyógyítva a többi példánya, mindet külön adjuk át a függvényeknek ... ellentétben az egyetlen példányváltozóval. Nem jellemző.

Nekem elég volt ennyi agyalás.
57

Az adatbáziscsatoló ebben a

Hidvégi Gábor · 2014. Ápr. 4. (P), 18.39
Az adatbáziscsatoló ebben a formában rossz példa volt, amit beinjektálsz, a lehető legáltalánosabbnak kell lennie. Persze ez újabb problémákat vet fel, de szerintem biztosan van haszna ennek az eljárásnak.
62

A DI-vel kapcsolatban az az

BlaZe · 2014. Ápr. 4. (P), 20.28
A DI-vel kapcsolatban az az érzésem, más területen futott be karriert mint amiről beszélnek. (a viagra is szívgyógyszer lett volna) Ki lehet próbálni, használsz egy szerény objektum könyvtárat, mondjuk 20 különböző osztályt. Nincs a fő objektumba belegyógyítva a többi példánya, mindet külön adjuk át a függvényeknek ... ellentétben az egyetlen példányváltozóval. Nem jellemző.
Nekem nem jön át, hogy ezzel mit szeretnél mondani. Az elég csúnya lenne, ha a hívónak kéne definiálnia a hívott objektum függőségeit. Az azt jelentené, hogy ő is kívülről kéne kapja a függőségeit. Azokat is, amiket csak arra használ, hogy átadja a másik objektumnak...
65

Függőség neve, teljes neve

Vilmos · 2014. Ápr. 5. (Szo), 14.00
Függőség neve, teljes neve kb. csomagfüggőség. Valaminek a rövidítése, önmagában a szenvedélybetegséget juttatja eszembe. Sokáig nem is értelmeztem, bár ez valamiért nem zavart. Szóval a használt modulok leltárát értik alatta.

Procedurális programozásban is van függőségi probléma, de nem kell ilyen gondossággal körbeprogramozni a használatot. A szükséges függvény meghívható bárhol. Objektumnál előbb példányosítás, ami változót generál. Azt a változót muszály elérni. Paraméteres átadással körbehordozni nemcsak egyszerűen ronda. Ahogy említettétek, a példányokat "objektum gráfba" szervezik, ennek egyik módja a DI. Ez a szervezkedés mint tervezési lépés még nem jött át semmiféle leíráson, pedig alapvető.
( Maga a DI technikailag közel áll a procedurális függvény használathoz, mivel szándék szerint egymás közti függőség nincs az egymás mellé halmozott készleten. A függvény külön előkészítés nélkül meghívható ott ahol állok.)
66

Függőség neve, teljes neve

BlaZe · 2014. Ápr. 5. (Szo), 22.48
Függőség neve, teljes neve kb. csomagfüggőség. Valaminek a rövidítése, önmagában a szenvedélybetegséget juttatja eszembe. Sokáig nem is értelmeztem, bár ez valamiért nem zavart. Szóval a használt modulok leltárát értik alatta.
Bocs, de ??? :) Ezzel mit szeretnél mondani?

Lehet tévedek, de mintha keveredne benned a dependency injection és a dependency injection container fogalma. És továbbra sem értem mit szeretnél ebből az egészből kihozni. A procedurális kód szoros és statikus függőséggel dolgozik, amit a programkód definiál. A DI pedig laza csatolással dolgozik, gyakorlatilag egy runtime függőségi gráf felépítése, amit tehetünk programkódból, konfigurációból, DIC-cel... Nem értem sem az összehasonlítást, sem annak okát. Valamint 2 kör után azt sem, hogy valójában mi bajod a DI-nel :)
67

Jobb mintával magyarázni.

Vilmos · 2014. Ápr. 6. (V), 14.56
Jobb mintával magyarázni. Szóval, akárhogy hozzuk létre az objektum láncolást az eredmény ilyen lesz:
oMain->oImport->oHelper("what?")->oWork("item")+1
Van némi ellenérzésem a fentivel kapcsolatban. A DI-t csak azért írtam mert az sokat emlegetett. Ezt tudom használni: o->Work() és ezt is Work(), ez elsőt nem igazán. A gyakorlatban mire jó a runtime gráf? ( Az implementációs függőség, függetlenség ebből nem derül ki például.)
51

A perzisztens azt jelenti

inf3rno · 2014. Ápr. 4. (P), 13.27
A perzisztens azt jelenti kitartó. Ebben a kontextusban, az ideiglenes ellentéte, kb azt jelenti, hogy a szerver újraindításakor nem vesznek el az adataid, mert lemented őket az adatbázisban, fájlrendszerben, vagy bármi más helyen...
55

így nem kell

vbence · 2014. Ápr. 4. (P), 18.06
így nem kell új topic-ot nyitnom


Attól még kellett volna...
58

Jobb így, hidd el!

inf3rno · 2014. Ápr. 4. (P), 19.54
Jobb így, hidd el!
69

Nem győztél meg...

vbence · 2014. Ápr. 18. (P), 09.05
Nem győztél meg...
46

Önellentmondás

Hidvégi Gábor · 2014. Ápr. 4. (P), 09.28
a Hidvégi megint alkotott
vs
Amíg vannak ilyenek, mint te, nekem addig biztosítva van a munkám.
Akkor tanúsíthatnál egy kicsivel több tiszteletet, nem harapunk abba a kézbe, amelyik etet!
49

Nyelv

Hidvégi Gábor · 2014. Ápr. 4. (P), 11.56
Szerinted:
A szakma nyelve az angol. Arról pedig az egyén tehet, ha nem ismeri, vagy rosszul használja a kifejezéseket.


Ezt írta inf3rno:
És a helyzetet még az is bonyolítja, hogy sokszor különböző szavakat használunk ugyanazokra a dolgokra

És Vilmos:
Találkoztam jó pár angol szóval, melyekről kiderült nem újak csak máshogy ismertem őket


Szóval mindenképp hasznos lenne egy közös pont, egy szótárszerűség, ahol vagy angolul vagy magyarul le van minden definiálva, különben csak elbeszélnek az emberek egymás mellett.
52

Szóval mindenképp hasznos

inf3rno · 2014. Ápr. 4. (P), 13.29
Szóval mindenképp hasznos lenne egy közös pont, egy szótárszerűség, ahol vagy angolul vagy magyarul le van minden definiálva, különben csak elbeszélnek az emberek egymás mellett.

Persze, én már szorgalmazom egy ideje, hogy hozzunk létre ilyen szótárat, de érdeklődés hiányában elmaradt...
60

Ezt a szótárat úgy hívják,

BlaZe · 2014. Ápr. 4. (P), 20.14
Ezt a szótárat úgy hívják, hogy self-development :) Meg tapasztalat. Más megoldás nincs. El lehet olvasni a wikipedián mindent, amiről itt szó van. Könyvek is vannak róluk, rengeteg cikk. Én nem hiszek abban, hogy ezeket meg lehet spórolni, vagy a téma megfelelő mélységű körbejárása és gyakorlása nélkül képbe lehet kerülni valaminek a jelentésével. Ezek nem olyan dolgok, hogy egy rövid definíciót lehessen rájuk adni. Nem véletlenül lett ilyen hosszú ez a szál is itt. És ráadásul egy ilyenből (különböző vélemények, látásmód, tudás és tapasztalat anyag ütköztetése) sokat tanulni, úgyhogy szerintem jobb is így :)
61

Bennem ez akkor merült fel,

inf3rno · 2014. Ápr. 4. (P), 20.18
Bennem ez akkor merült fel, amikor alapvető dolgokon mást értettünk Ádámmal, úgy, mint polimorfizmus, encapsulation, stb... Persze érdekes vita volt, de attól még jó lenne, ha lenne valami standard szókészlet, hogy ne beszéljek baromságot. :D Wikipedia-n persze utánanéztem utána, de van, hogy ott sem tiszta a kép...
63

Szótár

T.G · 2014. Ápr. 4. (P), 22.12
Van már egy szótár, ami szerintem egészen jó lett:
http://oktatlak.hu/kislexikon/szotar.pdf (931 oldal)
64

Az a baja, hogy csak egy

inf3rno · 2014. Ápr. 5. (Szo), 01.26
Az a baja, hogy csak egy szószedet... Fordítások készítéséhez, meg könyv íráshoz mondjuk nagyon jó, de ott ki is merül. Én olyasmire gondoltam, mint a wikipedia, csak annál részletesebben, ha lehet komolyabb példakódokkal, stb... Egy ilyen rendszer mondjuk nem hiszem, hogy megéri a fáradozást, mert kicsi a magyar piac hozzá, angol nyelvű meg már biztosan létezik nem is egy...