ugrás a tartalomhoz

Adatbázis és laza csatolás

inf · 2013. Feb. 17. (V), 07.31
Többször észrevettem már, hogy olyan dolgok mennek az adatbázisba, amik nagyon szorosan csatoltak az adott kóddal, amit írok. Általában olyanokról van szó, hogy 2-3 lehetőség között kell választani, és egy-egy lehetőség neve.

pl:

	access
		access_id
		user_id
		access_method
		access_hash
		access_expires
Itt bejelentkezési módokat listázok, ahol az access_method POST, COOKIE és GET értéket vehet fel attól függően, hogy jelszavas, permanent cookies vagy emailben kapott linkes a bejelentkezés. Ez egy a sok eset közül, ahol előfordult ilyesmi, és elég zavaró, hogy nincs laza csatolás a kód és az adatbázis között, és SET formájában megjelennek konkrét megvalósításhoz kapcsolódó értékek az adatbázisban.

Nincs valami bevett módszer ennek az elkerülésére?
 
1

Eltérő logikát kell

szjanihu · 2013. Feb. 17. (V), 12.37
Eltérő logikát kell alkalmazni az egyes access_method-ok esetén akár listázáskor, akár beszúráskor?
3

Nem értem a kérdést. A linkes

inf · 2013. Feb. 17. (V), 18.18
Nem értem a kérdést. A linkes és cookies bejelentkezés csak bizonyos ideig érvényes, a jelszavas meg nyilván örökre. Nem szeretném, ha a jelszavas bejelentkezést cookies-ként vagy linkesként lehetne kezelni, mert akkor brute force-al törhető lenne mindenki accountja különösebb erőfeszítés nélkül.
2

Lehet nem jött át teljesen a

BlaZe · 2013. Feb. 17. (V), 12.57
Lehet nem jött át teljesen a problémád, de itt elég szoros a kapcsolat az adatbázis tartalma és a kód működése között, ezért a szoros csatolás is.

Tovább gondolkozva valami olyasmi lehet az adott esetben, hogy logikailag különböző authorizációs módokat sorolsz fel (pl form,trusted,marketing), és a kódban transzformálod ezt a konkrét implementációra. Web esetében pl "post,cookie,get", desktop alkalmazás esetében meg pl "form,hwkey,marketingcode". Viszont így meg elveszted a lényeget, vagyis visszanézve nem fogod látni, hogy melyik bejelentkezés milyen konkrét módszerrel történt. Ebben az esetben pedig kimondott cél ennek letárolása. Illetve amennyiben csak webes a rendszered, akkor egy tök felesleges absztrakciós szintet hoztál be gyakorlati (pl karbantarthatóság, bővíthetőség) haszon nélkül (over-engineering). Ilyen absztrakciónak inkább visszafelé látom értelmét, amikor adott beállítás mellett adott, környezetfüggő implementációt kell kiválasztani és végrehajtani. Pl ha csak formos authentikáció engedélyezett a usernek, akkor a webes rendszer formot, a desktopos alkalmazás meg valami dialogot dob fel neki. De alapvetően az adatbázis a jellegéből adódóan szoros csatolást biztosít, és szerintem ez jól is van így, az absztrakciónak a kódban (üzleti logikában) van a helye.

De lehet a példád kicsit félrevitt :)
4

Van másik példa is. Van

inf · 2013. Feb. 17. (V), 18.28
Van másik példa is. Van olyan, hogy egy webshop-nál speciális kategóriák, fizetési módok, végösszegek vannak, és ezektől függően változnak az elérhető fizetési és szállítási módok. Pl: előrendelhető terméknél vagy 10k HUF feletti kosárnál csak előreutalással lehet fizetni, és házhozszállítással rendelni, vagy paypal-os fizetési módnál extra dolgok jelennek meg az oldalon, stb... Így az oldalnak tudnia kell, hogy melyik kategória a speckó, illetve melyik fizetési mód a speckó. Nyilván itt is be kell tennem SET-be a fizetési módokhoz, hogy paypal, stb... illetve a kategóriákhoz, hogy preorderable, stb... Ezt konkrétan úgy csináltam, hogy van egy special nevű tábla, meg kapcsolótáblák, de SET-el kevésbé lenne bonyolult. Szóval az üzleti logikához tartozó kapcsolókat kell beszórnom az adatbázisba, hogy rendesen működjön az alkalmazás. Ezeket meg az ember szívesebben rakná konfig fájlokba, viszont akkor az adatbázis meg a konfig fájlok között lenne szoros a kapcsolat, mert adatbázis id-k lennének letárolva a config fájlokban. (Ezt a config fájlos megoldás pl az előző példánál, a bejelentkezésnél nem lehet alkalmazni, mert ott nem csak 1-1 access sor lenne speciális, hanem az összes az.)
5

De ez azért valahol

BlaZe · 2013. Feb. 17. (V), 19.23
De ez azért valahol természetes, hiszen egy megrendelésről tudnod kell, hogy milyen fizetési módot választott a user (vagy mit írtál elő neki). Illetve a preorderable is kell az üzleti logikának, valamint ezek szoros és fontos paraméterei egy megrendelésnek, illetve kategóriának.

Hogy pl 10kHUF feletti rendelésre speciális eset van, azt én is configba raknám (hogy ez file, vagy db config, az most mindegy), hiszen ez egy globális paramétere az üzleti logikának. Az, hogy az aktuális megrendelés paypal-es, vagy nem, az már megrendelés szintű információ, a megrendelés egy tulajdonsága, ezért ennek a megrendelésben van a helye.

Vagy az a bajod, hogy az üzleti logikában le kell írnod, hogy
if ( $cart->getSumPrice() > $this->prePayLimit ) {...}
meg
if ( $cart->getPaymentMode() == PAYPAL ) {...}
?

Azt hiszem nem igazán értem még mindig a problémád.
7

Annyi a bajom, hogy

inf · 2013. Feb. 17. (V), 21.06
Annyi a bajom, hogy konstansokat kell felvinnem az adatbázis sémába, aminek elvileg általános dolgokról kellene szólnia. Pl fel kell vinnem string konstanst, hogy az alkalmazásom tudja, hogy melyik id-hez melyik beléptetési mód tartozik. Persze lehet külön táblákat csinálni, amikben felsorolom ezeket a konstansokat, de az még tovább rontja a helyzetet, mert még bonyolultabb SQL-eket kell írnom...
9

Enumokkal mi a baj? Az tény,

BlaZe · 2013. Feb. 17. (V), 22.51
Enumokkal mi a baj? Az tény, hogy szinkronban kell tartani a db és a kód oldali enumokat, de hát ezt máshogy nem nagyon lehet, mivel 2 külön rendszer.

Persze lehet külön táblákat csinálni, amikben felsorolom ezeket a konstansokat, de az még tovább rontja a helyzetet, mert még bonyolultabb SQL-eket kell írnom...

Ez szerintem nem feltétlenül igaz, mert csinálhatsz konstansokat php oldalon az id-val, és akkor már eleve az id-t tolod le, viszont a kódodban a konstans neve szerepel. A kapcsolótábla meg csak ahhoz kell, hogy ha db oldalon selectet írsz, akkor lásd, hogy melyik érték mit jelent, de az alkalmazásod nem használja azt a táblát egyáltalán. Plusz megvan az az előnye, mint az enumnak is, hogy csak valid értéket tolhatsz le a táblába a constraint miatt.
11

A fenti hozzászólásban épp

szjanihu · 2013. Feb. 18. (H), 00.10
A fenti hozzászólásban épp erre kérdeztem rá. Tehát pl. fizetési típusok esetén vannak-e eltérések az üzleti logikában.

Adatbázis nélkül, tisztán OOP-vel hogy oldanád meg mindezt? Példánál maradva lenne egy abstract fizetési típus osztályod, illetve ebből származtatnád a többit és azokban az egyedi, specializálni kívánt logikát megírnád. Csak azért, mert ezeket adatbázisba mented, ne gondolkodj másképp. Csináld meg úgy, hogy működjön DB nélkül, aztán majd megcsinálod a perzisztálást/visszaolvasást.

Származtatott objektumok adatbázisba mentésére van egy pár megoldás: Single Table Inheritance, Class Table Inheritance, stb. Ezt a kettőt általában támogatják az ORM-ek, de ha nem használsz ORM-et, akkor is megoldható az implementálásuk.
12

Okés, köszi, utánaolvasok

inf · 2013. Feb. 18. (H), 00.50
Okés, köszi, utánaolvasok ezeknek... Idorm & paris-t fogom majd megnézni orm terén.
13

Ezt nem ismertem, de

szjanihu · 2013. Feb. 18. (H), 01.00
Ezt nem ismertem, de ránézésre ez nem fogja tudni :)
Látom PHP-ben gondolkozol, úgyhogy azt mondom, Doctrine, esetleg Propel. Én hanyagolnám az Active Recordot, de az már más téma.
14

Igazából szinte tökmindegy,

inf · 2013. Feb. 18. (H), 01.12
Igazából szinte tökmindegy, nem akkora projekt, hogy számítana, akár sima SQL-ben is megírhatnám... Van összesen 18 tábla benne, és ezzel azt hiszem vége, hacsak nem lesznek extra igények.
6

Bár őszintén szólva fogalmam

MadBence · 2013. Feb. 17. (V), 20.33
Bár őszintén szólva fogalmam sincs, mit szeretnél, de ha az a gond, hogy az egyes access_method-ok bele vannak hardkódolva az egyes rekordokba (ezzel különböző anomáliákat okozva), akkor egyszerűen vedd ki az access_method-od egy új táblába (normalizálás).

Ha azzal van a gond, hogy az eltérő access_method-ok eltérő implementációt takarnak (tehát pl egy más típusú objektum reprezentálja őket), és ezt az osztályhieararchiát szeretnéd valahogy reprezentálni az adatbázisban, akkor az a helyzet, hogy a relációs adatbázisok nem igazán alkalmasak erre (meg lehet oldani minden további nélkül, csak ezek elég csúnya megoldások)
8

A normalizálás csak ront a

inf · 2013. Feb. 17. (V), 21.10
A normalizálás csak ront a helyzeten, csak tovább bonyolódnak tőle az sql-ek... Egyébként ja, az a gondom, hogy bele kell hardkódolnom, és ezt nem tartom valami szépnek, de ha muszáj, akkor muszáj...

Ahogy nézem az öröklődős megoldás még bonyolultabbá tenné az egészet, akkor már jobb így flagekkel csinálni.
10

Szerintem az alapvető gond

MadBence · 2013. Feb. 17. (V), 23.03
Szerintem az alapvető gond az, hogy te a konkrét adatbázist, és az adatbázis modelljének kódbeli reprezentációját megpróbálod két külön rendszerként kezelni. Szerintem ez nem jó hozzáállás. Lásd Entity Framework. Ott kiválasztod, mit szeretnél karbantartani (kód/db/modell), és a keretrendszer onnantól kezdve mindent elvégez helyetted, nem kell tudnod, hogy a maradék két komponens hogyan néz ki.
15

Azt hiszem rájöttem, hogy hol

inf · 2013. Feb. 18. (H), 02.16
Azt hiszem rájöttem, hogy hol rontottam el. Abból indultam ki, hogy a php-vel csinálom az sql selectet az access-hez, és hozatom létre a session bejegyzést, és ezért össze kell kötnöm a mysql-es konstansokat a php-s konstansokkal. A valóság meg az lesz, hogy mysql-ben lesznek ezek a dolgok tárolt eljárásban. Így rendesen kettéválik az adatbázis réteg és a felette lévő business logic, ami majd használja. A webshopos példára ugyanez igaz.

Egyébként abban igazatok volt, hogy egy ORM-el szintén ugyanúgy ki lehet alakítani egy réteget php-ben, és onnan küldözgetni a query-ket, viszont az szorosan csatolt lesz az adatbázissal. Szóval ez is egy lehetséges megoldás.

Na hát ilyen az, amikor érzi az ember, hogy hiba van a gépezetben, de nem jön rá, hogy hol. :D

Köszönöm mindenkinek az építő hozzászólásokat!