Powiedzmy, że mam encję, która ma atrybut „typ”. Może być ponad 20 możliwych typów.
Teraz jestem proszony o zaimplementowanie czegoś, co pozwoliłoby zmienić typ z A-> B, co jest jedynym przypadkiem użycia.
Czy powinienem więc wdrożyć coś, co pozwala na dowolne zmiany typu, o ile są to prawidłowe typy? A może powinienem pozwolić TYLKO na zmianę z A-> B zgodnie z wymaganiami i odrzucić wszelkie inne zmiany typu, takie jak B-> A lub A-> C?
Widzę zalety i wady z obu stron, gdzie ogólne rozwiązanie oznaczałoby mniej pracy w przypadku pojawienia się podobnych wymagań w przyszłości, ale oznaczałoby także większą szansę na błąd (chociaż w tym przypadku w 100% kontrolujemy osobę dzwoniącą punkt).
Konkretne rozwiązanie jest mniej podatne na błędy, ale wymaga więcej pracy w przyszłości, jeśli pojawią się podobne wymagania.
Ciągle słyszę, że dobry programista powinien starać się przewidzieć zmianę i zaprojektować system, aby można go było łatwo rozbudować w przyszłości, co wydaje się być rozwiązaniem ogólnym?
Edytować:
Dodanie więcej szczegółów do mojego nie tak specyficznego przykładu: Rozwiązanie „ogólne” w tym przypadku wymaga mniej pracy niż rozwiązanie „szczególne”, ponieważ konkretne rozwiązanie wymaga sprawdzania poprawności na starym i nowym typie, podczas gdy rozwiązanie ogólne wystarczy zweryfikować nowy typ.
źródło
Odpowiedzi:
Moja ogólna zasada:
Oczywiście jest to wytyczna, a nie twarda i szybka reguła: prawdziwą odpowiedzią jest skorzystanie z najlepszej oceny każdego przypadku z osobna.
źródło
thing1, thing2
, pomyśl o użyciu tablicy. Wthing1, thing2, thing3
prawie na pewno użyjthing[]
tablicy.” jest podobną ogólną zasadą przy podejmowaniu decyzji między wieloma zmiennymi lub pojedynczą tablicą.Słyszałem ten argument kilkadziesiąt razy i - z mojego doświadczenia - regularnie okazuje się on błędem. Jeśli uogólnisz teraz lub później, kiedy pojawi się drugi podobny wymóg, praca będzie prawie taka sama. Zatem nie ma absolutnie żadnego sensu inwestowanie w uogólnienie, jeśli nie wiesz, że wysiłek kiedykolwiek się opłaci.
(Oczywiście nie ma to zastosowania, gdy bardziej ogólne rozwiązanie jest mniej skomplikowane i wymaga mniej wysiłku niż konkretne, ale z mojego doświadczenia wynika, że są to rzadkie przypadki. Taki scenariusz został później zredagowany w pytaniu i nie jest to jeden dotyczy mojej odpowiedzi).
Kiedy pojawia się „drugi podobny przypadek”, czas zacząć myśleć o uogólnieniu. Znacznie łatwiej będzie wtedy uogólnić poprawnie , ponieważ ten drugi wymóg daje ci scenariusz, w którym możesz sprawdzić, czy właściwe rzeczy są ogólne. Próbując uogólnić tylko dla jednego przypadku, strzelasz w ciemności. Szanse są duże, nadmiernie uogólniasz pewne rzeczy, których nie trzeba uogólniać, i tęsknisz za innymi częściami, które powinny. A kiedy pojawia się drugi przypadek i zdajesz sobie sprawę, że uogólniłeś niewłaściwe rzeczy, masz dużo więcej pracy do zrobienia, aby to naprawić.
Polecam więc odłożyć pokusę na robienie rzeczy „na wszelki wypadek”. Takie podejście doprowadzi do zwiększenia nakładów pracy i konserwacji tylko wtedy, gdy przegapisz okazję do uogólnienia trzy, cztery lub więcej razy, a następnie będziesz miał stos podobnego (tak zduplikowanego) kodu do utrzymania.
źródło
TL; DR: zależy to od tego, co próbujesz rozwiązać.
Rozmawiałem na ten temat z moimi Grampami, kiedy rozmawialiśmy o tym, jak Func i Action w C # są niesamowite. My Gramps to bardzo stary programator czasowy, który był związany z kodami źródłowymi, odkąd oprogramowanie działało na komputerach, które zajmowały cały pokój.
Kilka razy zmieniał technologię w swoim życiu. Napisał kod w C, COBOL, Pascal, BASIC, Fortran, Smalltalk, Java i ostatecznie zaczął C # jako hobby. Nauczyłem się, jak programować z nim, siedząc na kolanach, gdy byłem diabłem, wycinając pierwsze wiersze kodu w niebieskim edytorze SideKick IBM. Kiedy miałem 20 lat, spędziłem już więcej czasu na kodowaniu niż granie na zewnątrz.
To trochę moje wspomnienia, więc przepraszam, jeśli nie jestem do końca praktyczny, gdy je powtarzam. Trochę mi się podobają te chwile.
Tak mi powiedział:
„Czy powinniśmy dążyć do uogólnienia problemu, czy rozwiązać go w określonym zakresie, pytasz? Cóż, to… pytanie”.
Gramps zatrzymał się na chwilę, aby pomyśleć o tym, jednocześnie ustalając położenie okularów na twarzy. Grał w grę match-3 na swoim komputerze, słuchając płyty Deep Purple na swoim starym systemie dźwiękowym.
„Cóż, to zależy od tego, jaki problem próbujesz rozwiązać”, powiedział mi. „Kuszące jest przekonanie, że istnieje jedno święte rozwiązanie dla wszystkich wyborów projektowych, ale nie ma jednego. Architektura oprogramowania jest jak ser, rozumiesz.”
„... Ser, Gramps?”
„Nie ważne, co myślisz o swoim ulubionym, zawsze znajdzie się ktoś, kto uważa, że śmierdzi”.
Przez chwilę mrugałam zmieszana, ale zanim zdążyłam cokolwiek powiedzieć, Gramps kontynuował.
„Jak budujesz samochód, jak wybierasz materiał na część?”
„Myślę… Myślę, że to zależy od kosztów i tego, co ta część powinna zrobić, jak sądzę.”
„To zależy od problemu, który stara się rozwiązać część. Nie zrobisz opony wykonanej ze stali lub przedniej szyby wykonanej ze skóry. Wybierasz materiał, który najlepiej rozwiązuje problem, który masz pod ręką. Teraz czym jest ogólne rozwiązanie? Albo konkretne? Na jaki problem, na jaki przypadek użycia? Czy powinieneś zastosować pełne funkcjonalne podejście, aby zapewnić maksymalną elastyczność kodowi, który będzie użyty tylko raz? Czy powinieneś napisać bardzo specjalistyczny, delikatny kod do część twojego systemu, która będzie miała wiele zastosowań i być może wiele zmian? Takie wybory projektowe są podobne do materiałów, które wybierasz do części w samochodzie lub kształtu klocków Lego, które wybierasz do budowy małego domu Jaka klocki Lego jest najlepsza? ”
Starszy programista sięgnął po mały model pociągu Lego, który ma na swoim stole, zanim kontynuował.
„Możesz odpowiedzieć tylko na to, jeśli wiesz, po co ci ta cegła. Skąd, do diabła, dowiesz się, czy konkretne rozwiązanie jest lepsze niż ogólne, i odwrotnie, jeśli nawet nie wiesz, na czym polega problem? próbujesz rozwiązać? Nie widzisz przeszłości, której nie rozumiesz ”.
„..Czy właśnie zacytowałeś Matrycę? ”
"Co?"
„Nic, mów dalej”.
„Załóżmy, że próbujesz zbudować coś w systemie faktur krajowych. Wiesz, jak wygląda ten piekielny interfejs API i jego plik XML zawierający trzydzieści tysięcy wierszy od wewnątrz. Jak wyglądałoby„ ogólne ”rozwiązanie do tworzenia tego pliku na przykład? Plik jest pełen opcjonalnych parametrów, pełen spraw, z których powinny korzystać tylko bardzo specyficzne gałęzie biznesu. W większości przypadków możesz je bezpiecznie zignorować. Nie musisz tworzyć ogólnego systemu faktur, jeśli jedyną rzeczą, którą „ Zawsze będę sprzedawać buty. Po prostu stwórz system sprzedaży obuwia i spraw, aby był to najlepszy system fakturowania butów, który istnieje na rynku. Teraz, gdybyś musiał stworzyć system faktur dla dowolnego rodzaju klienta, w szerszym zakresie - zostać odsprzedane jako niezależny, ogólny system sprzedaży,na przykład - teraz interesujące jest wdrożenie tych opcji, które są używane tylko w przypadku gazu, żywności lub alkoholu.Teraz są to możliwe przypadki użycia. Wcześniej były to tylko hipotetyczne przypadki Nie używaj przypadków, a nie chcesz wdrożyć Nie używaj przypadków. „Nie używaj” to młodszy brat „ Nie potrzebujesz ”.
Gramps umieścił pociąg lego z powrotem na swoim miejscu i wrócił do swojej gry polegającej na dopasowywaniu trzech elementów.
„Aby więc wybrać ogólne lub konkretne rozwiązanie danego problemu, musisz najpierw zrozumieć, na czym polega ten problem. W przeciwnym razie zgadujesz, a zgadywanie jest zadaniem menedżerów, a nie programistów. Jak prawie wszystko w IT, to zależy ”.
Więc masz to. "To zależy". To chyba najpotężniejsze wyrażenie dwuliterowe, gdy myśli się o projektowaniu oprogramowania.
źródło
Przede wszystkim powinieneś spróbować przewidzieć, czy prawdopodobne jest, że taka zmiana nastąpi - a nie tylko odległe możliwości gdzieś poniżej linii.
Jeśli nie, zwykle lepiej jest teraz przejść do prostego rozwiązania i rozszerzyć je później. Całkiem możliwe, że będziesz miał wyraźniejszy obraz tego, co jest wtedy potrzebne.
źródło
Jeśli pracujesz w domenie, która jest dla ciebie nowa, niż zasada trzech , o której wspomniał Daniel Pryden, zdecydowanie powinna być zastosowana. W końcu, jak masz budować przydatne abstrakty, jeśli jesteś nowicjuszem w tej dziedzinie? Ludzie często są pewni siebie, jeśli chodzi o zdolność do wyłapywania abstrakcji, choć rzadko tak jest. Z mojego doświadczenia wynika, że przedwczesna abstrakcja jest nie mniejszym złem niż powielanie kodu. Błędne abstrakcje są bardzo bolesne do zrozumienia. Czasami jeszcze bardziej bolesne dla refaktoryzacji.
Istnieje książka, w której poruszam moją uwagę na temat nieznanego obszaru, na którym pracuje programista. Składa się z określonych domen z wyodrębnionymi przydatnymi abstrakcjami.
źródło
Biorąc pod uwagę naturę twojego pytania, zakładając, że dobrze to zrozumiałem, faktycznie postrzegam to jako pytanie projektowe o cechach systemu centralnego, a nie pytanie o ogólne lub konkretne rozwiązania.
A jeśli chodzi o funkcje i możliwości centralnego systemu, najbardziej niezawodne są te, których nie ma. Opłaca się popierać minimalizm, zwłaszcza biorąc pod uwagę, że generalnie łatwiej jest centralnie dodać funkcjonalność, od dawna pożądaną, niż usunąć problematyczną funkcjonalność, długo niepożądaną, z licznymi zależnościami, ponieważ znacznie utrudniła pracę z systemem niż musi być przy zadawaniu niekończących się pytań projektowych przy każdej nowej funkcji.
W rzeczywistości, nie przewidując, czy będzie to często potrzebne w przyszłości, starałbym się unikać patrzenia na to jako zamiennik typu od A do B, jeśli to możliwe, a zamiast tego po prostu szukałem go jako sposobu na przekształcenie stanu A. Na przykład, ustaw niektóre pola w A, aby przekształciły się i wyglądały jak B dla użytkownika bez faktycznego zmieniania się w inny „typ” rzeczy - możesz potencjalnie stworzyć A sklep B prywatnie za pomocą funkcji kompozycji i wywoływania w B, gdy stan A jest ustawiony, aby wskazać, że powinien naśladować B, aby w miarę możliwości uprościć implementację. To powinno być bardzo proste i minimalnie inwazyjne rozwiązanie.
W każdym razie, powołując się na wiele innych, sugeruję pomyłkę po stronie unikania ogólnych rozwiązań w tym przypadku, ale tym bardziej, że zakładam, że rozważa się dodanie bardzo odważnych możliwości do systemu centralnego, i tam zasugeruj, że pomylę się z pominięciem tego, szczególnie na razie.
źródło
Trudno jest udzielić ogólnej odpowiedzi na ten konkretny problem ;-)
Im bardziej ogólny, tym więcej czasu zyskasz na przyszłe zmiany. Na przykład z tego powodu wiele programów do gier używa wzorca komponentu bytu zamiast budowania bardzo rozbudowanego, ale sztywnego systemu typów postaci i przedmiotów w grze.
Z drugiej strony, stworzenie czegoś ogólnego wymaga dużo czasu i wysiłku włożonego w projektowanie, które jest znacznie wyższe niż w przypadku czegoś bardzo konkretnego. Niesie to za sobą ryzyko nadmiernej inżynierii, a nawet zagubienia się w potencjalnych przyszłych wymaganiach.
Zawsze warto sprawdzić, czy istnieje naturalne uogólnienie, które zapewni ci przełom. Ostatecznie jednak chodzi o równowagę między wysiłkiem, który możesz teraz poświęcić, a wysiłkiem, którego możesz potrzebować w przyszłości.
źródło
Hybrydowy. To nie musi być ani pytanie, ani pytanie. Możesz zaprojektować interfejs API dla konwersji typu ogólnego, jednocześnie wdrażając tylko konkretną konwersję, której potrzebujesz teraz. (Upewnij się tylko, że jeśli ktoś zadzwoni do Twojego ogólnego interfejsu API z nieobsługiwaną konwersją, zakończy się niepowodzeniem ze statusem błędu „nieobsługiwany”).
Testowanie. W przypadku konwersji A-> B będę musiał napisać jeden (lub niewielką liczbę) testów. W przypadku ogólnej konwersji x-> y może być konieczne napisanie całej macierzy testów. To znacznie więcej pracy, nawet jeśli wszystkie konwersje korzystają z jednej ogólnej implementacji.
Jeśli z drugiej strony okaże się, że istnieje ogólny sposób na przetestowanie wszystkich możliwych konwersji, oznacza to, że nie ma dużo więcej pracy i być może skłaniam się do wcześniejszego rozwiązania ogólnego.
Sprzęganie. Konwerter z A na B może koniecznie znać szczegóły implementacji dotyczące A i B (ścisłe połączenie). Jeśli A i B wciąż ewoluują, oznacza to, że będę musiał ponownie przeglądać konwerter (i jego testy), co jest do bani, ale przynajmniej jest ograniczone do A i B.
Jeśli wybrałbym ogólne rozwiązanie, które wymaga dostępu do szczegółów wszystkich typów, to nawet w miarę ewolucji C i D, być może będę musiał ciągle ulepszać ogólny konwerter (i kilka testów), co może mnie spowolnić nawet chociaż nikt jeszcze trzeba przekonwertować do C lub D .
Jeśli zarówno konwersje ogólne, jak i specyficzne mogą być zaimplementowane w sposób, który jest luźno powiązany ze szczegółami typów, nie martwiłbym się tym. Jeśli jedno z nich można wykonać w luźny sposób, ale drugi wymaga ścisłego połączenia, to jest to mocny argument za podejściem luźno sprzężonym tuż za bramą.
źródło
To nie jest pytanie, na które można odpowiedzieć.
Najlepsze, co można racjonalnie uzyskać, to kilka heurystyk, które decydują o tym, jak ogólne lub szczegółowe jest wykonanie danego rozwiązania. Przepracowanie czegoś podobnego do poniższego procesu, zwykle przybliżenie pierwszego rzędu jest poprawne (lub wystarczająco dobre). Jeśli tak nie jest, przyczyna może być zbyt specyficzna dla domeny, aby można ją było szczegółowo omówić tutaj.
Przybliżenie pierwszego rzędu: zwykła reguła trzech YAGNI opisana przez Daniela Pryden, Doc Brown, i in .
Jest to ogólnie przydatna heurystyka, ponieważ jest to prawdopodobnie najlepsza możliwa metoda, która nie zależy od domeny i innych zmiennych.
Tak więc początkowe założenie brzmi: robimy najbardziej konkretną rzecz.
Przybliżenie drugiego rzędu: mówisz na podstawie swojej wiedzy eksperckiej w dziedzinie rozwiązań
więc może ponownie zinterpretować YAGNI jak polecając unikamy niepotrzebnego pracę , zamiast unikania niepotrzebnego ogólności. Możemy więc zmodyfikować nasze początkowe domniemanie i zamiast tego zrobić najłatwiejszą rzecz.
Jeśli jednak Twoja wiedza dotycząca domeny rozwiązania wskazuje, że najłatwiejsze rozwiązanie może spowodować wiele błędów lub być trudne do odpowiedniego przetestowania lub powodować inne problemy, łatwiejsze kodowanie niekoniecznie jest wystarczającym powodem do zmiany naszego oryginalny wybór.
Przybliżenie trzeciego rzędu: czy twoja wiedza w dziedzinie problemów sugeruje, że najłatwiejsze rozwiązanie jest w rzeczywistości poprawne, czy też dopuszczasz wiele przejść, o których wiesz, że są pozbawione znaczenia lub błędne?
Jeśli proste, ale ogólne rozwiązanie wydaje się problematyczne lub nie masz pewności, czy potrafisz ocenić te zagrożenia, wykonanie dodatkowej pracy i pozostanie przy początkowych przypuszczeniach jest prawdopodobnie lepsze.
Przybliżenie czwartego rzędu: czy twoja wiedza na temat zachowań klientów lub tego, w jaki sposób ta funkcja odnosi się do innych, priorytetów zarządzania projektem, lub ... jakieś inne nie ściśle techniczne względy modyfikują twoją obecną decyzję roboczą?
źródło
Odpowiedź na to pytanie nie jest łatwa. Wiele odpowiedzi dało heurystykę zbudowaną wokół reguły 3 lub czegoś podobnego. Wykraczanie poza takie zasady jest trudne.
Naprawdę naprawdę odpowiedzieć na to pytanie, trzeba wziąć pod uwagę, że twoja praca jest najbardziej prawdopodobne, aby nie realizować coś, co zmienia A-> B. Jeśli jesteś wykonawcą, być może jest to wymóg, ale jeśli jesteś pracownikiem, zatrudniono Cię do wykonywania wielu mniejszych zadań dla firmy. Zmiana A-> B to tylko jedno z tych zadań. Twoja firma będzie dbać o to, jak dobrze można wprowadzić przyszłe zmiany, nawet jeśli nie zostanie to określone w żądaniu. Aby znaleźć „TheBestImplementation (tm)”, musisz spojrzeć na większy obraz tego, o co tak naprawdę jesteś proszony, a następnie użyć go do interpretacji małej prośby o zmianę A-> B.
Jeśli jesteś niskopoziomowym programistą rozpoczynającym naukę po studiach, często wskazane jest zrobienie dokładnie tego, co ci kazano. Jeśli zostałeś zatrudniony jako architekt oprogramowania z 15-letnim doświadczeniem, zazwyczaj warto pomyśleć o dużych obrazach. Każda rzeczywista praca spadnie gdzieś pomiędzy „rób dokładnie to, co jest wąskie zadanie” i „pomyśl o dużym obrazie”. Przekonasz się, gdzie mieści się Twoja praca w tym spektrum, jeśli będziesz wystarczająco rozmawiać z ludźmi i wykonywać dla nich wystarczającą ilość pracy.
Mogę podać kilka konkretnych przykładów, w których twoje pytanie ma ostateczną odpowiedź na podstawie kontekstu. Rozważ przypadek, w którym piszesz oprogramowanie krytyczne dla bezpieczeństwa. Oznacza to, że zespół testowy wstał, aby upewnić się, że produkt działa zgodnie z obietnicą. Niektóre z tych zespołów testowych są zobowiązane do przetestowania każdej możliwej ścieżki w kodzie. Jeśli z nimi porozmawiasz, może się okazać, że jeśli uogólnisz to zachowanie, dodasz 30 000 USD do ich kosztów testowania, ponieważ będą musieli przetestować wszystkie te dodatkowe ścieżki. W takim przypadku nie dodawaj ogólnej funkcjonalności, nawet jeśli z tego powodu musisz powielić pracę 7 lub 8 razy. Zaoszczędź pieniądze firmy i rób dokładnie to, co podano w żądaniu.
Z drugiej strony rozważ, że tworzysz interfejs API, aby umożliwić klientom dostęp do danych w programie bazy danych utworzonym przez Twoją firmę. Klient prosi o zezwolenie na zmiany A-> B. Interfejsy API mają zazwyczaj aspekt złotych kajdanek: po dodaniu funkcji do interfejsu API zwykle nie należy usuwać tej funkcji (do następnego głównego numeru wersji). Wielu twoich klientów może nie być skłonnych zapłacić za aktualizację do następnego głównego numeru wersji, więc możesz utknąć w jakimkolwiek wybranym przez siebie rozwiązaniu przez długi czas. W takim przypadku zdecydowanie polecam utworzenie ogólnego rozwiązania od samego początku. Naprawdę nie chcesz tworzyć złego API pełnego jednorazowych zachowań.
źródło
Hmm ... mało kontekstu do odpowiedzi ... echo wcześniejszych odpowiedzi: „To zależy”.
W pewnym sensie musisz polegać na swoim doświadczeniu. Jeśli nie twoje, to ktoś starszy w domenie. Możesz spierać się o to, jakie są kryteria akceptacji. Jeśli jest to coś w stylu „użytkownik powinien mieć możliwość zmiany typu z„ A ”na„ B ”„ w porównaniu z ”użytkownik powinien mieć możliwość zmiany typu z bieżącej wartości na dowolną dozwoloną wartość alternatywną”.
Często kryteria akceptacji podlegają interpretacji, ale dobry personel QA może napisać kryteria odpowiednie do wykonywanego zadania, minimalizując niezbędną interpretację.
Czy istnieją ograniczenia domeny, które nie pozwalają na zmianę z „A” na „C” lub jakąkolwiek inną opcję, ale tylko „A” na „B”? Czy jest to tylko wąsko określony wymóg, który nie jest „myśleniem przyszłościowym”?
Gdyby ogólny przypadek był trudniejszy, zapytałbym go przed rozpoczęciem pracy, ale w twoim przypadku, gdybym mógł „przewidzieć”, że w przyszłości pojawią się inne wnioski o zmianę typu, byłbym skłonny: a) napisz coś wielokrotnego użytku dla ogólnego przypadku i b) zawiń w warunek, który na razie pozwala tylko A -> B.
Wystarczająco łatwe do zweryfikowania dla bieżącego przypadku w testach automatycznych i wystarczająco łatwe, aby później otworzyć inne opcje, jeśli / kiedy pojawią się różne przypadki użycia.
źródło
Dla mnie wytyczna, którą ustaliłem jakiś czas temu, brzmi: „Dla hipotetycznych wymagań pisz tylko hipotetyczny kod”. To znaczy - jeśli spodziewasz się dodatkowych wymagań, powinieneś pomyśleć trochę o tym, jak je zaimplementować i ustrukturyzować swój obecny kod, aby nie blokował w ten sposób.
Ale nie pisz teraz dla nich rzeczywistego kodu - pomyśl tylko, co byś zrobił. W przeciwnym razie zwykle będziesz robił rzeczy niepotrzebnie skomplikowanymi i prawdopodobnie zirytujesz się później, gdy pojawią się rzeczywiste wymagania, które różnią się od oczekiwanych.
Cztery twój przykład: jeśli masz pod kontrolą wszystkie zastosowania metody konwersji, możesz po prostu nazwać ją teraz convertAToB i planujesz użyć refaktoryzacji „metody zmiany nazwy” w IDE, aby zmienić jej nazwę, jeśli później potrzebujesz bardziej ogólnej funkcjonalności. Jeśli jednak metoda konwersji jest częścią publicznego interfejsu API, może być zupełnie inaczej: jej specyfikacja zablokowałaby później generalizację, ponieważ w takim przypadku trudno jest zmienić nazwę rzeczy.
źródło
Zasadniczo tak. Ale to nie nie musi prowadzić do rozwiązań generycznych.
Według mnie istnieją dwa rodzaje tematów związanych z tworzeniem oprogramowania, w których należy przewidzieć przyszłe zmiany:
Pierwszy przypadek rozwiązuje się obserwując spójność / sprzężenie, zastrzyk zależności lub cokolwiek innego. Drugi przypadek jest na bardziej abstrakcyjnym poziomie, na przykład wybranie architektury zorientowanej na usługi zamiast dużego monobotycznego obiektu typu blob dla dużej aplikacji.
W twoim przypadku prosisz o konkretne rozwiązanie konkretnego problemu, który nie ma żadnego przewidywalnego wpływu na przyszłość. W tym przypadku YAGNI i SUCHY to dobre motta do strzelania do:
W połączeniu z innymi nowoczesnymi praktykami (takimi jak dobre pokrycie testowe, aby móc bezpiecznie refaktoryzować) oznacza to, że otrzymujesz szybko napisany, oszczędny, średni kod, który rośnie w miarę potrzeb.
Nie, wygląda na to, że powinieneś mieć środowiska programistyczne, języki i narzędzia, dzięki którym refaktoryzacja w razie potrzeby jest łatwa i przyjemna. Ogólne rozwiązania tego nie zapewniają; oddzielają aplikację od rzeczywistej domeny.
Spójrz na nowoczesne frameworki ORM lub MVC, na przykład Ruby on Rails; na poziomie aplikacji wszystko koncentruje się na wykonywaniu pracy innej niż ogólna. Biblioteki same w sobie są oczywiście prawie w 100% ogólne, ale kod domeny (o co chodzi w twoim pytaniu) powinien w tym aspekcie robić minimalne shenanigany.
źródło
Innym sposobem myślenia o problemie jest rozważenie, co ma sens.
Na przykład opracowywałem aplikację, która zawierała sekcje, które działały prawie tak samo, ale miały niespójne reguły dotyczące zezwoleń. Ponieważ nie było powodu, aby je odróżniać, kiedy ponownie przebudowałem tę sekcję, kazałem im wszystkim robić uprawnienia w ten sam sposób. Dzięki temu cały kod był mniejszy, prostszy, a interfejs był bardziej spójny.
Kiedy zarząd postanowił zezwolić innym osobom na dostęp do funkcji, mogliśmy to zrobić, zmieniając tylko flagę.
Oczywiście sensowne jest dokonanie konwersji określonego typu. Czy sensowne jest także dokonywanie dodatkowych konwersji typu?
Należy pamiętać, że jeśli ogólne rozwiązanie jest szybsze do wdrożenia, to odpowiedni przypadek jest również łatwy, po prostu sprawdź, czy jest to jedyna dozwolona konwersja typu.
Jeśli aplikacja znajduje się w ściśle regulowanym obszarze (aplikacja medyczna lub finansowa), spróbuj zaangażować w projekt więcej osób.
źródło