2017-02-01 55 views
5

Używam Realm w kilku małych projektach i bardzo mi się podoba. Mam nadzieję, że wykorzystam go w większych projektach i szukam lepszej struktury mojej warstwy dostępu do danych.Jak napisać lepszą warstwę dostępu do danych z Realmem

Natknąłem się na podobne question i próbowałem zebrać informacje, które tam znalazłem. Podejście omówione tutaj jest wzorem DAO, więc dałem temu szansę.

To jest moja klasa modelu.

class Chat: Object { 
    dynamic var id: String = "" 
    dynamic var createdAt: Date = Date() 
    dynamic var creatorId: String = "" 
    dynamic var title: String? 
    let chatMessages = List<ChatMessage>() 

    override static func primaryKey() -> String? { 
     return "id" 
    } 

    convenience init(fromJSON json: JSON) { 
     self.init() 
     // ... 
    } 
} 

Następnie stworzyłem ChatDAOProtocol, aby zachować wszystkie metody pomocnika wygody.

protocol ChatDAOProtocol { 
    func addMessage(_ message: ChatMessage) 
    func getChatThumbnail() -> UIImage 
    func getParticipants(includingMe: Bool) -> [Participant]? 
    static func getChat(fromId id: String) -> Chat? 
    static func getChat(fromCreatorId id: String) -> Chat? 
} 

Wreszcie stworzyłem inną klasę o nazwie ChatHelper że wdrożone wszystkie te metody protokołu.

class ChatHelper: ChatDAOProtocol { 
    func addMessage(_ message: ChatMessage) { 

    } 

    func getChatThumbnail() -> UIImage { 
     return UIImage() 
    } 

    func getParticipants(includingMe: Bool) -> [Participant]? { 
     return nil 
    } 

    static func getChat(fromId id: String) -> Chat? { 
     return nil 
    } 

    static func getChat(fromCreatorId id: String) -> Chat? { 
     return nil 
    } 

} 

Wydaje się, że to już lepsze niż zraszanie całego kodu związanego z bazą danych w całym VC i tym podobnych. Ale wciąż mam pewne wątpliwości.

Powiedzmy na przykład, czy muszę zebrać wszystkich uczestników czatu, teraz muszę zadzwonić do tej metody na klasie ChatHelper. A jeśli chcę uzyskać po prostu tytuł czatu, nazywam właściwością samego obiektu Chat. Nie wygląda na bardzo zunifikowany interfejs. Czy powinienem dołączyć także obiekty pobierające i ustawiające dla wszystkich właściwości pomocnika. Tak więc obiekt Chat nigdy nie jest wywoływany bezpośrednio (z wyjątkiem możliwości utworzenia instancji).

Albo

powinienem zrobić sam obiekt Chat zgodne z protokołem ChatDAOProtocol? Więc wszystkie metody wygody, jak również właściwości są bezpośrednio dostępne z obiektu Chat prosto w górę?

A może jest lepszy sposób niż oba te sposoby?

Odpowiedz

2

Jest to dość podchwytliwe pytanie, ponieważ tak naprawdę zależy to od tego, jak bardzo chcesz się oderwać od bezpośredniej interakcji z Królestwem i jak bardzo chcesz pójść na kompromis z wydajnością Królestwa.

Osobiście uważam, że jest w porządku, jeśli oddziela się zapytanie i pisze logikę, ale nadal czyta bezpośrednio z obiektów modelu Realm. Jeśli przeniosłeś się do innej opartej na obiektach bazie danych (podobnie jak dane podstawowe), wówczas gdy chciałbyś refaktoryzować klasę nadrzędną, obiekty te należałyby do czegoś innego (np. RLMObject do NSManagedObject), sposób, w jaki logika biznesowa odczytana z tych obiektów nie ulegnie zmianie .

Jedną z rzeczy, na które należy uważać, jest jednak abstrakcja logiki w taki sposób, aby wykorzystać Sferę bardzo nieefektywnie.

Głównym przykładem tego, jak widzę, jest twoja metoda getParticipants, zwracasz standardową tablicę Swift. Konwersja obiektu do takiego obiektu spowodowałaby stronicowanie każdego obiektu w pamięci (w przeciwieństwie do leniwego ładowania na żądanie), co spowodowałoby utratę wielu korzyści wynikających z wydajności Realm. Ale ponieważ obiekty Results zachowują się jak standardowe tablice, nie musisz zmieniać logiki biznesowej, jeśli bezpośrednio je zwróciłeś.

Kolejna uwaga: jeśli aktualizujesz pojedynczą właściwość wsadu obiektów, lepiej byłoby, gdyby wszystkie obiekty były aktualizowane w pojedynczej transakcji zapisu, zamiast w klasie pomocnika, wewnętrznie otwierającej transakcję zapisu za każdym razem, gdy wywoływana jest metoda pomocnicza.

+0

Dzięki za odpowiedź. Wziąłbym pod uwagę wymienione punkty i przerobiłem mój kod. Czy uważasz, że preferowane jest posiadanie metod pomocniczych w tej samej klasie "Czat" lub stworzenie osobnej klasy "ChatHelper" dla tych metod pomocniczych jest lepsze? – Isuru