Czy wykrywalność dla programistów stanowi problem przy stosowaniu zasad SOLID?

10

Zajmuję się aplikacjami biznesowymi, w których wszyscy inni programiści są przyzwyczajeni do robienia podstawowych aplikacji CRUD lub koncentrują się wyłącznie na tworzeniu ładnych / funkcjonalnych interfejsów.

„W sposób, w jaki to robimy, pracownik miałby wszystko, co mógłbyś zrobić z pracownikiem”. I to była prawda. Ta jedna „klasa” zawierała tysiące linii kodu i było tam wszystko, co można zrobić z pracownikiem. Lub, co gorsza, była tabela danych pracowników i każdy programista wymyślił, jak zrobić to, co chciał zrobić w module obsługi zdarzeń.

Wszystkie złe rzeczy związane z tym podejściem były prawdziwe, ale przynajmniej deweloper korzystający z pracownika mógł, bez przechodzenia do innych dokumentów, dowiedzieć się, jak zapisać pracownika do planu opieki zdrowotnej, podwyższyć wynagrodzenie, zwolnić, zatrudnić, przenieść itp. To samo dotyczy dla Managera i wszystkich innych głównych pomysłów. Lub, jeśli korzystali z pracownika inne potrzebne tabele danych, mogą po prostu zrobić, co chcieli.

Tak, był dużo zduplikowanego kodu. Tak, to był bardzo kruchy kod. Tak, testowanie było znacznie trudniejsze niż to konieczne. Tak zmieniającą się funkcjonalnością było wywoływanie strachu, a Kopiowanie Wklej było naturalne ze względu na to podejście.

Ale mogli przynajmniej odkryć, co było dostępne, tworząc jedną klasę lub mogli zrobić to, co trzeba, bez konieczności rozumienia różnicy między interfejsami, klasami abstrakcyjnymi, konkretnymi klasami itp. I nie musieli szukać niczego innego niż metody zwrócone przez intellisense lub znają tabele, w których znajdowały się dane.

Mam googled / binged, a nawet yahoo! D, ale nie znalazłem potwierdzenia tego problemu.

Więc może nie ma problemu i czegoś mi brakuje. Zanurzyłem mózg, próbując znaleźć rozwiązanie, w którym programiści, którzy nie działają w rzeczywistości, mogą łatwo odkryć, jak coś zrobić, bez konieczności odwoływania się do jakichkolwiek zewnętrznych dokumentów lub skanowania nazw klas w różnych komponentach / projekty, aby znaleźć ten, który brzmi jak to będzie działać.

Jedyną rzeczą, jaką udało mi się wymyślić, jest to, że z powodu braku lepszej nazwy, „Tabela treści” nie robi nic więcej, niż zwraca rzeczywiste klasy (a tak naprawdę większość z nich to interfejsy, ale nie mają znać różnicę, a nawet ostrożność), którą inni programiści mogą wykorzystać do wykonania pożądanych zadań. Wciąż kończą się naprawdę dużymi klasami, ale nie ma w nich prawie żadnego zachowania.

Czy istnieje lepszy sposób, który nie wymaga dogłębnej znajomości środkowego poziomu, na którym ma miejsce faktyczna implementacja SOLID?

Zasadniczo pytam, czy istnieje sposób, aby pozwolić programistom typu CRUD nadal być programistami CRUD w bardzo złożonym systemie

ElGringoGrande
źródło
8
Być może programiści nie mogą całkowicie polegać na IntelliSense (lub odpowiedniku) pod względem wykrywalności. Nazwij wszystko dobrze. Dokumentuj dobrze. Jest to problem z komunikacją, a nie problem techniczny.
Rein Henrichs,
Hmmm. Trochę Im więcej o tym myślę, tym bardziej wierzę, że czai się okazja biznesowa.
ElGringoGrande 10.10.11
2
@ReinHenrichs: Jeśli programista będzie musiał przeczytać dokumentację, zajmie im to trochę czasu, a wydajność spadnie. Dlatego ważne jest, aby szybko dowiedzieli się, czego potrzebują do danego zadania. Nie musi polegać na inteligencji, ale lepiej być łatwym. Ułatwienie to z pewnością problem techniczny.
Jan Hudec
@JanHudec: Nie, to nie jest problem techniczny, ale organizacyjny przy użyciu odpowiednich konwencji nazewnictwa, układu i białych znaków. Bez konwencji nazewnictwa nie wiedziałbyś, czego szukać. Bez spójnego nazewnictwa nie znalazłbyś wszystkiego i / lub znacznie trudniej byłoby namierzyć wszystko. Bez spójnego układu i użycia białych znaków (szczególnie w deklaracjach typów) nie znajdziesz połowy potrzebnych instancji. Tak, lepsze wyrażenie regularne mogłoby pomóc, ale nie chcę się uczyć wyrażenia regularnego tylko po to, aby dowiedzieć się, gdzie jest używana klasa.
Marjan Venema
@JanHudec To nie jest „jeśli”, ale „kiedy”. Programiści będą musieli przeczytać dokumentację. Jeśli chcesz, aby „szybko dowiedzieli się, czego potrzebują do danego zadania”, najlepiej jest skoncentrować się na zwiększeniu skuteczności dokumentacji. Nie próbuj rozwiązywać problemu ludzi (np. Komunikacji) za pomocą rozwiązania technicznego. To. Robi. Nie. Praca.
Rein Henrichs,

Odpowiedzi:

4

Wygląda na to, że to, co opisałeś (tj. Klasa pracowników z WSZYSTKIM możliwym kodem, który możesz zrobić z pracownikiem) jest niezwykle powszechnym wzorcem, który osobiście widziałem dość często. Część tego kodu napisałem sam, zanim poznałem coś lepszego.

To, co zaczyna się jako klasa, która ma reprezentować pojedynczy byt z możliwym do zarządzania zestawem metod, przekształca się w coś, co jest koszmarem do utrzymania, ponieważ każda funkcja i każde wydanie dodaje coraz więcej do tej samej klasy. Jest to sprzeczne z zasadami SOLID, które mówią, że powinieneś napisać klasę raz i oprzeć się pokusie jej ciągłego modyfikowania.

Jakiś czas temu (zanim odkryłem wzorce projektowe lub SOLID jako promowane przez innych), postanowiłem, że mój następny projekt trochę zmieni. Pracowałem na serwerze, który służył jako interfejs między dwiema bardzo dużymi platformami. Początkowo wymagana była tylko synchronizacja konfiguracji, ale widziałem, że byłoby to logiczne miejsce dla wielu innych funkcji.

Zamiast pisać klasę, która ujawniała metody, napisałem klasy reprezentujące metody (okazało się, że jest to wzorzec „Command” z GoF). Zamiast wykonywać pracę dla klienta, wszystkie moje główne klasy aplikacji stały się trwałymi właścicielami stanów i stały się znacznie krótsze. Za każdym razem, gdy musiałem dodawać nową metodę interfejsu do samej usługi, po prostu tworzyłem nową klasę, która miała metodę Execute (), która wszystko zaczynała. Jeśli wiele poleceń ma coś wspólnego, pochodzą one ze wspólnej klasy podstawowej. W końcu rzecz miała ponad 70 różnych klas dowodzenia, a cały projekt był nadal bardzo łatwy do zarządzania i praca z nim była przyjemnością.

Twoja „klasa TOC” nie jest zbyt daleka od tego, co zrobiłem. Miałem fabrykę abstrakcyjną (GoF), która była odpowiedzialna za tworzenie komend. Wewnątrz klasy fabrycznej ukryłem większość szczegółów za klasą bazową i makrami w stylu ATL, więc gdy programista musiał dodać lub wyszukać zapytanie, wszedł tam i zobaczył tylko:

BEGIN_COMMAND_MAP()
    COMMAND_ENTRY( CChangeDeviceState )
    COMMAND_ENTRY( CSetConfiguration )
    ....
END_COMMAND_MAP()

Alternatywnie (lub oprócz) możesz umieścić wszystkie swoje rzeczywiste klasy poleceń w osobnej przestrzeni nazw, więc gdy ludzie kodują i muszą coś uruchomić, po prostu wpisują nazwę przestrzeni nazw, a Intellisense wyświetla listę wszystkich zdefiniowanych przez ciebie poleceń. Następnie każde polecenie zawiera wszystkie metody get / set, które dokładnie określają, jakie parametry wejściowe i wyjściowe.

Możesz także zbadać użycie wzoru Fasada (GoF). Zamiast wystawiać ponad 1000 klas inżynierom CRUD. Ukryj je wszystkie za jedną klasą, która odsłania tylko to, co jest potrzebne. Nadal trzymałbym się, aby każda „akcja” była własną klasą, ale twoja klasa Fasady może mieć metody, które inicjują każdą z twoich akcji i ponownie, dzięki Intellisense natychmiast zobaczą, co jest dostępne. Lub niech Facade ma rzeczywiste metody, ale wewnętrznie każ im tworzyć polecenia, ustawiać je w kolejce i czekać na odpowiedzi. Następnie powróć, jakby wykonano zwykłe wywołanie metody.

(*) Nie chciałem wchodzić w zbyt wiele szczegółów, ale tak naprawdę miałem zestaw klas „Command” i „CommandHandler”. To oddzielało odpowiedzialność za zarządzanie / kolejkowanie / serializowanie parametrów wejścia / wyjścia od klas, które faktycznie „obsługiwały” te polecenia.

DXM
źródło
Tak. Dzisiaj zdałem sobie sprawę, że tym, co ostatecznie zakończyliśmy, jest źle zaimplementowany wzór fasady. Nie sądzę, aby można było zrobić coś więcej niż rozbicie dużej fasady na mniejsze. Podoba mi się twój pomysł włączenia niektórych klas dowodzenia za kulisy.
ElGringoGrande
0

To może być problem. Zwłaszcza jeśli źle nazywasz rzeczy. Ale istnieje wiele rozwiązań bez uciekania się do skomplikowanych klas. Heck, klasa ze zbyt wieloma metodami może być równie trudna w nawigacji dzięki Intellisense.

Spróbuj użyć przestrzeni nazw (C #) lub pakietów (Java), lub jakiejkolwiek podobnej koncepcji, jaką ma Twój język (nazywam je wszystkie przestrzeniami nazw), aby uprościć problem.

Zacznij od nazwy firmy. To ogranicza Intellisense tylko do nazw pisanych przez ciebie. Następnie, jeśli masz wiele aplikacji, użyj drugiej części przestrzeni nazw, aby je podzielić. Uwzględnij przestrzeń nazw Core dla rzeczy istniejących w różnych aplikacjach. Następnie podziel elementy na rodzaje funkcji. I tak dalej.

Jeśli zrobisz to dobrze, skończysz z bardzo wykrywalnymi przedmiotami.

Na przykład, jeśli chcę weryfikacji użytkownika, wpisuję „MyCo”. i daje mi listę przestrzeni nazw aplikacji. Wiem, że baza danych użytkowników jest używana we wszystkich naszych aplikacjach, dlatego wpisuję „Core”. wtedy dostaję listę rodzajów funkcjonalności. Jednym z nich jest „Walidacja”, więc wydaje się to oczywistym wyborem. I tam, w ramach sprawdzania poprawności, znajduje się „UserValidator” ze wszystkimi jego funkcjami.

Tak się składa, że ​​w przypadku rzeczy, których często używam, szybko zapamiętam nazwy, a przynajmniej konwencje. Ponieważ wprowadzam wiele zmian w regułach sprawdzania poprawności, będę wiedział, że wszystkie moje klasy sprawdzania poprawności nazywane są FooValidator, gdzie Foo jest nazwą tabeli. Więc właściwie nie będę musiał przechodzić przez przestrzenie nazw. Po prostu napiszę UserValidator i pozwolę IDE wykonać resztę pracy.

Ale dla rzeczy, których nie pamiętam, wciąż jest dość łatwo je znaleźć. A kiedy to zrobię, mogę usunąć prefiks przestrzeni nazw.

pdr
źródło
Częściowo jest to przeze mnie złe nazewnictwo. Nazwy nie są okropne, ale często myślę o lepszym miesiąc po fakcie. Ale nawet przy dobrych imionach, jeśli masz tysiące klas, nazwy nie zawsze są łatwe do wykrycia. Próbuję to przezwyciężyć. Pomyślałem, że może być znany sposób.
ElGringoGrande 10.10.11
0

Ponieważ określasz ich jako programistów „CRUD”, zakładamy, że nie uważasz ich za bardzo dobrych. Nie wiemy, czy to oznacza, że ​​nie rozumieją także Twojej domeny biznesowej. Jeśli rozumieją domenę, klasy powinny mieć dla nich sens. Wiedząc, że zbudowano kilka klas, powinni najpierw spojrzeć, zapytać drugi, rozważyć budowę od zera jako trzecią opcję.

O ile wiedza na temat tego, jak automatycznie wiedzieć, jak używać / ponownie wykorzystywać klasę, patrząc na nią, nie powinna być oczekiwana za pierwszym razem. Będziesz musiał udokumentować i ewentualnie podać dodatkowe wyjaśnienia poprzez szkolenie lub ewentualnie podczas przeglądu kodu.

Wiele API i projektów open source dostarcza dokumentację, przykłady kodu i inne wyjaśnienia. Twoja może nie musi być tak przyjazna dla użytkownika, ale nie można tego obejść. Naucz ich dobrze.

JeffO
źródło
Nie. CRUD nie oznacza, że ​​nie są dobre. Są to programiści, którzy zawsze zajmowali się podstawowymi aplikacjami danych. CRUD = utwórz, przeczytaj, zaktualizuj i usuń. Nie widzę, jak to czyni ich złymi programistami.
ElGringoGrande
W brytyjskim angielskim slangu „crud” == „cholera”.
Michael Shaw