Pracuję nad projektem oprogramowania, w którym musimy zbudować trzy interfejsy API. Jeden dla kanału bankowości domowej , jeden dla kanału agencji i trzeci dla kanału mobilnego .
Interfejs API agencji jest najbardziej kompletny, ponieważ ma wszystkie funkcje .. następnie nieco mniej Home API, a następnie API mobilne.
Architekci tutaj stworzyli wspólną warstwę (międzykanałowe usługi EJB wspólne dla wszystkich interfejsów API). Ale interfejsy API są różne.
Na razie nie ma dużej różnicy między interfejsami API. Duży zespół zaczął od kanału agencji, a my dostosowujemy go teraz do kanału domowego. Po prostu wzbogacamy obiekty specjalnie do naszej aplikacji domowej. W przeciwnym razie kod jest 95% podobny między interfejsami API. Interfejsy API są oparte na Spring MVC i mają (kontrolery, modele i niektóre narzędzia).
Zasadniczo kontrolery wykonują mapowanie BO do ChannelObject (wydaje mi się, że nie jest to właściwe miejsce do zrobienia tego), a także dodatkowe narzędzia i serializatory. Na razie wszystko jest zduplikowane. Mówią, że powodem duplikacji jest to, że chcą niezależnych interfejsów API. „Jeśli jutro chcemy innego zachowania dla domu niż agencji czy telefonu komórkowego, nie będziemy walczyć !!”
Czy istnieje przypadek, w którym powinniśmy zaakceptować duplikat kodu?
Odpowiedzi:
Powielanie może być właściwe, ale nie z tego powodu.
Powiedzenie „możemy chcieć, aby te trzy miejsca w bazie kodu zachowywały się inaczej, chociaż w tej chwili są identyczne”, nie jest dobrym powodem do powielania na dużą skalę. Pojęcie to może mieć zastosowanie do każdego systemu i może być wykorzystane do uzasadnienia jakiegokolwiek powielania, co oczywiście nie jest uzasadnione.
Powielanie powinny być tolerowane tylko przy usuwaniu byłoby ogólnie bardziej kosztowne teraz z jakiegoś innego powodu (nie mogę myśleć o dobry teraz, ale mieć pewność, że mogą być one - praktycznie wszystko w programowaniu to raczej kompromis niż prawo).
W przypadku tego, co robisz, właściwym rozwiązaniem może być np. Wyodrębnienie zachowania, które jest teraz duplikowane, do Strategii lub innego wzorca modelującego zachowanie jako klasy, a następnie użycie trzech wystąpień tej samej klasy. W ten sposób, jeśli nie chcesz, aby zmienić zachowanie w jednym z trzech miejsc, trzeba tylko stworzyć nową strategię i instancji, że w jednym miejscu. W ten sposób musisz tylko dodać niektóre klasy i pozostawić resztę bazy kodu prawie całkowicie nietkniętą.
źródło
Sandi Metz, uznana inżynierka oprogramowania i autorka ekosystemu Ruby, ma świetny post na blogu i przemówienie, w którym mówi także o związku między powielaniem a abstrakcją. Dochodzi do następującego wniosku
I całkowicie się z nią zgadzam. Pozwól, że dam ci więcej kontekstu do tego cytatu. Czasami znalezienie właściwej abstrakcji jest bardzo trudne. W takich przypadkach kuszące jest po prostu skorzystanie z jakiejkolwiek abstrakcji w celu ograniczenia powielania. Ale później może się okazać, że twoja abstrakcja nie dotyczy wszystkich przypadków. Jednak ponowna zmiana wszystkiego i wybranie innej drogi jest kosztowne (dla lepszego wyjaśnienia obserwuj, jak mówi!).
Tak więc dla mnie istnieją wyjątkowe przypadki, w których akceptacja duplikacji jest właściwą decyzją, szczególnie gdy nie jesteś pewien, co ma nadejść i wymagania mogą się zmienić. Z twojego postu zakładam, że jest teraz wiele powielania, ale twoi koledzy sugerują, że może się to zmienić i nie łączyć obu aplikacji ze sobą. Moim zdaniem jest to uzasadniony argument i nie można go zlekceważyć.
źródło
Jeśli ludzie zaczną rozumować na temat projektu słowami „jeśli jutro” , to często jest to dla mnie duży znak ostrzegawczy, zwłaszcza gdy argument ten jest uzasadniany decyzją obejmującą dodatkową pracę i wysiłek, o której nikt tak naprawdę nie wie, czy to się kiedykolwiek wydarzy spłacić, a trudniejsze do zmiany lub cofnięcia niż decyzja przeciwna.
Powielanie kodu zmniejsza wysiłek tylko na krótki czas, ale zwiększy wysiłki związane z utrzymaniem prawie natychmiast, proporcjonalnie do liczby zduplikowanych linii kodu. Zauważ też, że gdy kod zostanie zduplikowany, trudno będzie usunąć duplikację, gdy okaże się, że była to zła decyzja, podczas gdy jeśli nie powiela się teraz kodu, nadal łatwo jest wprowadzić duplikację później, jeśli okaże się, że trzymasz się DRY była zła decyzja.
Mówi się, że w większych organizacjach czasem korzystne jest faworyzowanie niezależności różnych zespołów w stosunku do zasady DRY. Jeśli usunięcie duplikacji poprzez wyodrębnienie 95% wspólnych części interfejsów API dwa nowe komponenty prowadzą do połączenia dwóch niezależnych zespołów, może to nie być najmądrzejsza decyzja. Z drugiej strony, jeśli masz ograniczone zasoby i będzie tylko jeden zespół utrzymujący oba interfejsy API, jestem pewien, że w ich własnym interesie nie będzie tworzenie podwójnego wysiłku i unikanie niepotrzebnego powielania kodu.
Zauważ też, że robi to różnicę, jeśli interfejsy API „Strona główna” i „Agencja” są używane wyłącznie przez całkowicie różne aplikacje, lub jeśli ktoś może spróbować napisać kompilację komponentu na podstawie tych interfejsów API, których można również użyć w kontekście „Strona główna” jak w kontekście „Agencji”. W tej sytuacji posiadanie dokładnie identycznych części wspólnych interfejsów API (co można zagwarantować tylko wtedy, gdy części wspólne nie są powielone), znacznie ułatwi opracowanie takiego komponentu.
Jeśli więc okaże się, że naprawdę będą istniały różne podgrupy, każda odpowiedzialna za każdy z interfejsów API, każda z innym harmonogramem i zasobami, nadszedł czas na skopiowanie kodu, ale nie „na wszelki wypadek”.
źródło
Powielanie w celu uniknięcia sprzężenia . Powiedzmy, że masz dwa duże systemy i zmuszasz je do korzystania z tej samej biblioteki. Być może łączysz cykl uwalniania obu systemów. Może nie jest tak źle, ale powiedzmy, że jeden system musi wprowadzić zmianę. Druga musi przeanalizować zmianę i może to mieć wpływ. Czasami może to popsuć. Nawet jeśli obie strony są w stanie koordynować zmiany, może to być wiele spotkań, przez menedżerów, testowanie, zależności i koniec małego autonomicznego zespołu.
Więc płacisz cenę za powielony kod, aby uzyskać autonomię i niezależność.
źródło