Moim zdaniem absolutnie nie tak to oznacza. I to jest naruszenie SUCHEGO.
Chodzi o to, że obiekt / domena w środku jest modelowany tak, aby reprezentował domenę tak dobrą i wygodną, jak to możliwe. Jest w centrum wszystkiego i wszystko może od tego zależeć, ponieważ sama domena nie zmienia się przez większość czasu.
Jeśli baza danych na zewnątrz może przechowywać te obiekty bezpośrednio, wówczas mapowanie ich do innego formatu w celu oddzielenia warstw jest nie tylko bezcelowe, ale tworzy duplikaty modelu i nie jest to intencją.
Na początek czysta architektura została stworzona z myślą o innym typowym środowisku / scenariuszu. Aplikacje serwera biznesowego z gigantycznymi warstwami zewnętrznymi, które potrzebują własnych typów specjalnych obiektów. Na przykład bazy danych, które produkują SQLRow
obiekty i wymagają SQLTransactions
w zamian aktualizacji elementów. Jeśli chcesz użyć tych w centrum, musisz naruszyć kierunek zależności, ponieważ twój rdzeń będzie zależał od bazy danych.
W przypadku lekkich ORM, które ładują i przechowują obiekty encji, tak nie jest. Dokonują mapowania między SQLRow
domeną wewnętrzną a domeną. Nawet jeśli potrzebujesz wstawić @Entitiy
adnotację ORM do obiektu domeny, argumentowałbym, że nie ustanawia to „wzmianki” o zewnętrznej warstwie. Ponieważ adnotacje są tylko metadanymi, żaden kod, który ich specjalnie nie szuka, nie zobaczy ich. Co ważniejsze, nic nie musi się zmienić, jeśli je usuniesz lub zastąpisz adnotacją innej bazy danych.
W przeciwieństwie do tego, jeśli zmienisz domenę i stworzyłeś wszystkich twórców map, musisz bardzo zmienić.
Poprawka: Powyższe jest nieco uproszczone i może się nawet mylić. Ponieważ jest część w czystej architekturze, która chce, abyś tworzył reprezentację dla każdej warstwy. Ale należy to rozpatrywać w kontekście aplikacji.
Mianowicie następujące tutaj https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
Ważne jest to, że izolowane, proste struktury danych są przekraczane przez granice. Nie chcemy oszukiwać i przekazywać wierszy jednostek ani baz danych. Nie chcemy, aby struktury danych miały jakąkolwiek zależność, która narusza zasadę zależności.
Przenoszenie bytów z centrum w kierunku warstw zewnętrznych nie narusza zasady zależności, ale są one wspomniane. Ma to jednak uzasadnienie w kontekście przewidywanej aplikacji. Przekazywanie jednostek przesuwałoby logikę aplikacji na zewnątrz. Zewnętrzne warstwy musiałyby wiedzieć, jak interpretować obiekty wewnętrzne, musiałyby skutecznie robić to, co powinny robić warstwy wewnętrzne, takie jak warstwa „przypadku użycia”.
Poza tym oddziela warstwy, więc zmiany w rdzeniu niekoniecznie wymagają zmian w warstwach zewnętrznych (patrz komentarz SteveCallendera). W tym kontekście łatwo jest zobaczyć, jak obiekty powinny reprezentować konkretny cel, do którego są używane. Również warstwy powinny ze sobą rozmawiać w odniesieniu do obiektów wykonanych specjalnie na potrzeby tej komunikacji. Może to nawet oznaczać, że istnieją 3 reprezentacje, po 1 w każdej warstwie, 1 do transportu między warstwami.
I jest https://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html, który porusza się powyżej:
Inni ludzie obawiają się, że wynikiem mojej porady będzie dużo zdublowanego kodu i dużo rutynowego kopiowania danych z jednej struktury danych do drugiej w różnych warstwach systemu. Z pewnością też tego nie chcę; i nic, co zasugerowałem, nieuchronnie doprowadziłoby do powtórzenia struktur danych i nadmiernego kopiowania w terenie.
To IMO implikuje, że zwykłe kopiowanie obiektów 1: 1 to zapach w architekturze, ponieważ tak naprawdę nie używasz odpowiednich warstw i / lub abstrakcji.
Później wyjaśnia, jak wyobraża sobie wszystkie „kopiowanie”
Interfejs użytkownika oddziela się od reguł biznesowych, przekazując między nimi proste struktury danych. Nie pozwalasz swoim kontrolerom nic wiedzieć o regułach biznesowych. Zamiast tego kontrolery rozpakowują obiekt HttpRequest do prostej waniliowej struktury danych, a następnie przekazują tę strukturę danych do obiektu interaktora, który implementuje przypadek użycia, wywołując obiekty biznesowe. Następnie interaktor zbiera dane odpowiedzi do innej struktury danych waniliowych i przekazuje je z powrotem do interfejsu użytkownika. Widoki nie wiedzą o obiektach biznesowych. Po prostu patrzą w tę strukturę danych i przedstawiają odpowiedź.
W tej aplikacji istnieje duża różnica między reprezentacjami. Przepływające dane to nie tylko byty. A to gwarantuje i wymaga różnych klas.
Jednak zastosowany do prostej aplikacji na Androida, takiej jak przeglądarka zdjęć, w której Photo
podmiot ma około 0 reguł biznesowych, a „przypadek użycia”, który się nimi zajmuje, prawie nie istnieje i jest bardziej zaniepokojony buforowaniem i pobieraniem (proces ten powinien być IMO reprezentowane bardziej precyzyjnie), punkt, w którym oddzielne przedstawienia zdjęcia zaczynają zanikać. Mam nawet wrażenie, że samo zdjęcie jest obiektem do przesyłania danych, podczas gdy brakuje prawdziwej warstwy rdzenia logiki biznesowej.
Istnieje różnica między „oddzielaniem interfejsu użytkownika od reguł biznesowych poprzez przekazywanie prostych struktur danych między nimi” a „gdy chcesz wyświetlić zdjęcie, zmień jego nazwę 3 razy po drodze” .
Poza tym, widzę, że te aplikacje demonstracyjne zawodzą w reprezentowaniu czystej architektury, ponieważ kładą ogromny nacisk na rozdzielanie warstw w celu oddzielenia warstw, ale skutecznie ukrywają to, co robi aplikacja. Jest to w przeciwieństwie do tego, co zostało powiedziane w https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html - a mianowicie
architektura aplikacji krzyczy o przypadkach użycia aplikacji
Nie widzę takiego nacisku na rozdzielanie warstw w czystej architekturze. Chodzi o kierunek zależności i skupienie się na reprezentowaniu rdzenia aplikacji - encji i przypadków użycia - w idealnie prostej Javie bez zależności na zewnątrz. Nie chodzi tak bardzo o zależności od tego rdzenia.
Jeśli więc aplikacja ma rdzeń reprezentujący reguły biznesowe i przypadki użycia i / lub różne osoby pracują na różnych warstwach, należy je rozdzielić w zamierzony sposób. Jeśli natomiast piszesz prostą aplikację samodzielnie, nie przesadzaj. 2 warstwy z płynnymi granicami mogą być więcej niż wystarczające. Warstwy można również dodać później.
BankAccount
ale z regułami specyficznymi dla aplikacji, co możesz zrobić z tym kontem.@SerializedName
adnotacje Gsona w modelu domeny? Czy stworzyłbyś nowy obiekt odpowiedzialny za mapowanie odpowiedzi sieciowej na model domeny?Właściwie to masz rację. I nie ma naruszenia DRY, ponieważ akceptujesz SRP.
Na przykład: masz metodę biznesową createX (nazwa ciągu), a następnie możesz mieć metodę createX (nazwa ciągu) w warstwie DAO, wywoływaną w ramach metody biznesowej. Mogą mieć ten sam podpis i być może jest tylko delegacja, ale mają różne cele. Możesz także mieć createX (nazwa ciągu) na UseCase. Nawet wtedy nie jest to zbędne. Mam na myśli to: te same podpisy nie oznaczają tej samej semantyki. Wybierz inne nazwy, aby wyczyścić semantykę. Samo nazywanie to wcale nie wpływa na SRP.
UseCase odpowiada za logikę specyficzną dla aplikacji, obiekt biznesowy odpowiada za logikę niezależną od aplikacji, a DAO jest odpowiedzialne za przechowywanie.
Ze względu na różną semantykę wszystkie warstwy mogą mieć własne modele reprezentacji i komunikacji. Często widzisz „byty” jako „obiekty biznesowe” i często nie widzisz konieczności ich oddzielania. Ale w „dużych” projektach należy dołożyć starań, aby odpowiednio rozdzielić warstwy. Im większy projekt, tym większa możliwość, że potrzebna będzie inna semantyka reprezentowana na różnych warstwach i klasach.
Możesz pomyśleć o różnych aspektach tego samego semantycznego. Obiekt użytkownika musi być wyświetlany na ekranie, ma pewne wewnętrzne zasady spójności i musi być gdzieś przechowywany. Każdy aspekt powinien być reprezentowany w innej klasie (SRP). Tworzenie twórców map może być uciążliwe, więc w większości projektów, w których pracowałem, te aspekty zostały połączone w jedną klasę. Jest to wyraźnie naruszenie SRP, ale tak naprawdę nikogo to nie obchodzi.
Zastosowanie czystej architektury i SOLID nazywam „nieakceptowalnym społecznie”. Pracowałbym z tym, gdyby mi wolno. Obecnie nie wolno mi tego robić. Czekam na moment, w którym będziemy musieli poważnie potraktować SOLID.
źródło
Nie, nie musisz tworzyć klas modeli w każdej warstwie.
Entity (
DATA_LAYER
) - to pełna lub częściowa reprezentacja obiektu Database.DATA_LAYER
Mapper (
DOMAIN_LAYER
) - w rzeczywistości jest klasą, która konwertuje Entity na ModelClass, na której będzie używanaDOMAIN_LAYER
Spójrz: https://github.com/lifedemons/photoviewer
źródło