Piszę nowy projekt strony internetowej od zera. Projekt jest w języku C#, ale moje tło jest w PHP (pseudo-kod poniżej jest nieco, jeśli mieszanina, starając się być zwięzła i deklaratywna).Jak zaimplementować wzorce odwzorowania danych/repozytorium dla różnych źródeł danych?
Problem
muszę pobrać dane konfiguracyjne z jednego z dwóch miejsc - czasem z lokalnej bazy danych, a czasami z usługi SOAP. Powinienem móc stworzyć ten sam zestaw obiektów modelu z dowolnego źródła.
Dane są przechowywane w zupełnie różnych strukturach w różnych źródłach danych - kilka różnych odpowiedzi na Soap musi być połączonych ze sobą od końca Soap, podczas gdy struktura DB jest znacznie bliższa temu, jak strukturyzuję moje obiekty Modelu w kod.
konfiguracja składa się z drzewem obiektów: Produkty zawierać Właściwości które zawierają Opcje które mają Umowy dla gdy mają one zastosowanie.
Cele
Chcę oddzielić obawy jak najwięcej (miejmy nadzieję ułatwić zarówno test-/Podtrzymy-/Extend-umiejętności):
- mojego modelu obiektów powinien wiedzieć nic o Data Persistence or retrieval
- Obiekt Persistence danych powinien w miarę możliwości być agnostyczny o dokładnym typie źródła danych
- Chcę oddzielić tworzenie obiektu jako m uch, jak to możliwe.
Pytania
Jestem świadomy różnych wzorców projektowych wokół tego (choć nie jestem do końca pewien, czy rozumiem je w całości). I asked a question on Programmers podobne do tego i otrzymałem odpowiedź na temat Persistence Ignorance (more here) oraz wzoru Repository, które wydają się być koncepcjami ze świata Microsoft.
O ile mogę powiedzieć "Nieprzetworzona trwałość" jest po prostu koncepcją posiadania obiektów Modelowych, które nic nie wiedzą o twoim mechanizmie przechowywania danych, a wzór repozytorium wydaje się bardzo podobny do wzorca mapowania danych, z tym że ukrywa on may be more of a facade, więcej o tym, co się właściwie dzieje.
Więc moje pytania to:
w strukturze danych Mapper powinienem mieć jeden Mapper od modelu obiektu? Zamiast posiadania jednego dla całego drzewa konfiguracji?
A zatem, czy powinienem mieć obiekt drzewa konfiguracji, który używa wszystkich obiektów Mapper?
class ConfigBuilder() {
public ConfigBuilder (productMapper, propertyMapper, optionMapper, conditionMapper) {
// save them into local properties
}
public Products() {
var products = productMapper.FetchAll();
foreach (var product in products) {
AddProperties(product);
}
return products;
}
private AddProperties(products) { /* ... */ }
private AddOptions(property) { /* ... */ }
private AddConditions(option) { /* ... */ }
}
Czy wydaje się to dobrym rozwiązaniem?
Gdzie powinna znajdować się logika do budowy obiektów?
W pewnym momencie musi istnieć znaczna ilość logiki, aby zbudować moje obiekty konfiguracyjne z losowej tablicy danych XML, które otrzymuję z usługi Soap, oraz mniejszą logikę, aby zrobić to samo z Baza danych.
Czy powinienem wstawiać logikę do budowania obiektów w oddzielnych instancjach obiektów Mapper?
interface IProductMapper { FetchAll; FetchByCode; Create; Delete; Update }
class ProductMapperXml implements IProductMapper {
public ProductMapperXml(xmlDataSource) {}
public FetchAll() { /* A whole bunch of logic to create the Product objects from XML data source */ }
}
class ProductMapperDatabase implements IProductMapper {
public ProductMapperDatabase(databaseConnection) {}
public FetchAll() { /* Select and build products from the database */ }
}
Czy to w porządku? Czy ta logika powinna być dalej rozwijana? Jeśli tak, dlaczego? Ponadto, jestem nieco zaniepokojony, że obiekt ProductMapperXml
ma znaczną logikę i jest odpowiedzialny za tworzenie obiektów wewnętrznie. Czy powinienem podać go w pewnym sensie ProductFactory
? Lub po prostu użyć metody fabrycznej?
Proszę dać mi znać, czy istnieją bardziej eleganckie sposoby rozwiązania tego niż moje sugestie? Również, jeśli są jakieś warstwy abstrakcji lub Wzorców projektu, mógłbym skorzystać z tego, że tęskniłem?