2011-04-27 11 views
7

W językach OOP mogę napisać opakowanie bazy danych, które hermetyzuje połączenie z bazą danych, zarządza schematem i zapewnia kilka podstawowych operacji, takich jak exec, query, prepare_and_execute. Może nawet mam osobną klasę pomocniczą dla bazy danych, która obsługuje schemat bazy danych, pozostawiając abstrakcję bazy danych tylko do obsługi połączeń. Byłoby to następnie używane przez owinięcia modelu/fabryki, które używają klasy abstrakcji bazy danych do tworzenia wystąpień klas modeli. Coś wzdłuż linii, jak ten diagram UML: Identyfikator idiomatic do abstrakcji bazy danych

Jaki byłby preferowany sposób zaprojektowania takiego systemu w idiomatycznym haskell?

+1

Może warto odwiedzić http://blog.ezyang.com/2010/06/databases-are-categories/. –

+0

@Alexandre dzięki, dobra lektura, ale nie sądzę, że to było to, czego szukałem :) – Masse

+2

Twój diagram już nie istnieje. Czy możesz go ponownie przesłać? To pytanie zależy od tego. –

Odpowiedz

4

Najbardziej popularną biblioteką abstrakcji baz danych w Haskell jest HDBC. Oznacza to, że kwerendy są po prostu reprezentowane jako obiekty zastępcze. Mniej osób używa HaskellDB, co zapewnia bezpieczny sposób budowania zapytań. Nic nie zabrania posiadania typów danych użytkownika do reprezentowania typowych zapytań i niestandardowych funkcji do ich budowania.

Wartości w Haskell są niezmienne, co oznacza, że ​​nie jest użyteczne posiadanie zmiennego obiektu odpowiadającego rekordowi w bazie danych. Zamiast tego, wydaje mi się, że bardziej powszechne jest definiowanie typów danych użytkownika i funkcji, które przekazują i wypychają/wyciągają wartości tych typów do/z bazy danych.

Ilekroć aktualizacje bazy danych są konieczne, najprawdopodobniej będą one uruchamiane w niektórych stanach monadowych pod numerem IO. Pozwoli to zachować połączenie otwarte, na przykład, lub zrobić coś pomiędzy żądaniami.

Wreszcie, funkcje są pierwszej klasy, więc możliwe jest skonstruowanie wszystkich funkcji w locie. Zatem sama funkcja może zawierać dowolne informacje.

Tak, myślę, zwykle podejście Haskell składa

  • algebraicznych typów danych do reprezentowania rzeczywistych danych (jak niezmienne wartości)
  • reszty aplikacji do przekształcenia tych wartości
  • funkcje, które generują zapytania (zawierają szczegóły schematu, dane marszałkowskie do/z typów danych Haskella)
  • (opcjonalnie) monometr stateful do uruchamiania zapytań (ukrywanie szczegółów dostępu do bazy danych)
  • funkcje, które uruchomić zapytań (bez szczegółów dostępu do baz danych)
+0

Miałem coś podobnego na myśli. Czy mógłbyś omówić część z "monotematyczną monadą do prowadzenia zapytań"? Jakiś czas temu napisałem abstrakcję proof of concept nad HDBC, w której używałem Monada Reader, aby ukryć szczegóły połączenia (runDatabase ustanowi połączenie, uruchom czytnik z wartością połączenia, a następnie zamknie połączenie). Też miałem ADT reprezentujące Osobę i Lokację i coś w rodzaju "getLocation :: Int -> IO Location" i "getPerson :: Int -> IO Person". Do modyfikacji db miałem coś w stylu "savePerson :: Person -> IO()". Czy to właśnie miałeś na myśli? – Masse

+0

@Masse Miałem na myśli, że jeśli na przykład chcesz skompilować niektóre lub wszystkie instrukcje, uruchamiasz ['prepare'] (http://hackage.haskell.org/packages/archive/HDBC/latest/doc/html /Database-HDBC.html#v:prepare) na nich i potrzebujesz miejsca na kompilację instrukcji między zapytaniami. Więc możesz użyć 'type DB a = StateT [(Query, Statement)] IO a', aby je zapisać (przypuszczam, że instrukcja jest reprezentowana przez niestandardowy typ danych" Query ", który implementuje' Eq'). Na najwyższym poziomie miałbym coś takiego jak 'runDB :: FilePath -> DB a -> IO a',' withPerson :: Query -> Key -> (Person -> (a, Maybe Person)) -> DB a '... – sastanin

0

najbardziej idiomatyczne sposób korzystania Haskell dla baz danych i najskuteczniejszy jeden, moim skromnym zdaniem, jest buforować rekordy w pamięci i użyć STM w pamięci transakcje, aby korzystać z bazy danych do przechowywania. Następnie możesz użyć zmiennych transakcyjnych (TVAR) do zarządzania rekordami. Ale musisz zdefiniować własny język zapytań i potrzebujesz mechanizmu buforowania/buforowania i synchronizacji. To przecież, co robi java EJB3 i Hybernate.

Pakiet TCache definiuje DBRefs, które są trwałe STM variables with TVar semantics. Mogą być częścią rekordu i wskazywać na inny rekord i są lekkie, więc możesz rozwinąć własną abstrakcję. Ma również język zapytań SQL, w tym field search, joins i wyszukiwanie pełnotekstowe. Ma domyślną trwałość w plikach. Musisz tylko zdefiniować klucz do swojego rekordu Haskell i masz trwałość pliku. W przypadku trwałości bazy danych znajduje się klasa IResource, w której definiujesz operacje odczytu, zapisu i usuwania dla swoich rekordów.Każdy rekord może mieć własną trwałość. Tak więc cała interakcja z bazą danych znajduje się w jednym miejscu kodu źródłowego, a transakcje w pamięci są o kilka rzędów szybsze. TCache zapisuje spójny stan za każdym razem, gdy asynchronicznie zapisuje go w bazie danych. Może również pisać synchronicznie.

+0

Nie może pomóc odczuć, że istnieje ciężki przypadek zespołu NIF w pracy tutaj. – Masse

+0

Co ma znaczyć syndrom NIF? Jeśli nie rozumiesz, o co mi chodzi, poproś mnie o wyjaśnienia. Jeśli nie jesteś zainteresowany, wystarczy proste podziękowania lub nic nie mówiąc. Jeśli nie czujesz się dobrze z moją odpowiedzią, weź filiżankę herbaty. – agocorona

+0

* NIH. "Tutaj". Typo. Przepraszam – Masse

Powiązane problemy