Monadic ACID
Happstack zawiera ciekawą propozycję trwałości danych nazwaną Monadic ACID. Nie jest to ani RDMS, ani noSQL. Myślę, że MACID to ciekawa propozycja w dziedzinie trwałości danych. Poniżej króta instrukcja, jak korzystać z MACID w Happstack.
Zadeklaruj dane:
> $(deriveAll [''Show, ''Eq, ''Ord, ''Default] > [d| > -- |GuestBookEntry: simple guest book entry > data GuestBookEntry = GuestBookEntry > { author :: String > , message :: String > , date :: ClockTime > } > > -- |GuestBook: a list of GuestBookEntry > newtype GuestBook = GuestBook { guestBookEntries :: [GuestBookEntry] } > |])
Zapewnij trwałość i wersjonowanie obiektów:
> $(deriveSerialize ''GuestBookEntry) > instance Version GuestBookEntry > > $(deriveSerialize ''GuestBook) > instance Version GuestBook
Przykładowa funkcja zapytania do bazy danych:
> readGuestBook :: Query GuestBook GuestBook > readGuestBook = ask
Przykładowa procedura modyfikacji bazy danych:
> addGuestBookEntry :: GuestBookEntry -> Update GuestBook () > addGuestBookEntry e = modify $ \(GuestBook gb) -> (GuestBook (e:gb))
Co ciekawe powyższe dwie funkcje mogą być dowolnie skomplikowane i używać pełnej gamy możliwości Haskella, co czyni z nich potężne procedury składowane.
Teraz stwórz listę metod, których będziesz używać do interakcji z bazą danych. Na tej liście muszą się znaleźć wszystkie przewidziane zapytania oraz modyfikacje.
> $(mkMethods ''GuestBook ['readGuestBook, 'addGuestBookEntry])
Rekord GuestBook zadeklaruj jako komponent aplikacji:
> -- |make Guestbook its own Component > instance Component GuestBook where > type Dependencies GuestBook = End > initialValue = defaultValue
Modyfikacje bazy danych wykonuje się przy użyciu konstrukcji update:
> let entry = GuestBookEntry {...} > update $ AddGuestBookEntry entry
A zapytania przy użyciu query:
> guestBook <- query $ ReadGuestBook > showAsHtml guestBook
Różnica między query a update jest prosta: query nie modyfikuje zawartości bazy danych, natomiast update ma taką możliwość. Obie funkcje są synchronizowane na bazie danych, jednak update jest również trwałe (ale przez to wolniejsze).
Moje doświadczenie z MACID sugerują następującą listę zalet i wad:
Zalety:
- nie trzeba ustawiać bazy SQL
- dane są statycznie typowane
- językiem zapytań jest Haskell
- językiem procedur składowanych jest również Haskell
Wady:
- rozmiar danych ograniczony wielkością dostępnej pamięci
- nie jest to architektura rozproszona
Z praktyki wiem, że MACID w wydaniu Happstack jest idealny do rozpoczęcia pracy nad aplikacją internetową. Odpada problem administracji zewnętrznej bazy danych!
Zaś gdy ilość danych urośnie, będzie można z pełną świadomością wybrać architekturę: czy standardowa relacyjna baza danych, czy coś z dziedziny noSQL, a może jakaś hybryda?