Kiedy należy usunąć złożoność?

14

Przedwczesne wprowadzanie złożoności poprzez wdrażanie wzorców projektowych przed ich użyciem nie jest dobrą praktyką.

Ale jeśli zastosujesz się do wszystkich (lub nawet większości) zasad SOLID i zastosujesz wspólne wzorce projektowe, wprowadzisz trochę złożoności w miarę dodawania lub zmieniania funkcji i wymagań, aby zachować łatwość konserwacji i elastyczność w razie potrzeby.

Jednak kiedy ta złożoność zostanie wprowadzona i działa jak mistrz, kiedy ją usuniesz?

Przykład. Mam aplikację napisaną dla klienta. Pierwotnie stworzony tam, gdzie istnieje kilka sposobów na podwyżki dla pracowników. Użyłem wzorca strategii i fabryki, aby cały proces był ładny i czysty. Z biegiem czasu niektóre metody podnoszenia zostały dodane lub usunięte przez właściciela aplikacji.

Czas płynie, a nowy właściciel przejmuje kontrolę. Ten nowy właściciel ma twardy nos, wszystko jest proste i ma tylko jeden sposób na podbicie.

Złożoność wymagana przez wzorzec strategii nie jest już potrzebna. Gdybym wiedział, gdzie to kodować z obecnych wymagań, nie wprowadziłbym tej dodatkowej złożoności (ale upewnij się, że mógłbym wprowadzić ją przy niewielkiej lub żadnej pracy, jeśli zajdzie taka potrzeba).

Czy mogę teraz usunąć wdrożenie strategii? Nie sądzę, aby ten nowy właściciel kiedykolwiek zmienił sposób przyznawania podwyżek. Ale sama aplikacja wykazała, że ​​może się to zdarzyć.

Oczywiście jest to tylko jeden przykład w aplikacji, w której nowy właściciel przejmuje i upraszcza wiele procesów. Mogłem usunąć dziesiątki klas, interfejsów i fabryk i uprościć całą aplikację. Zauważ, że obecna implementacja działa dobrze, a właściciel jest z niej zadowolony (i zdziwiony, a nawet bardziej szczęśliwy, że mogłem tak szybko wprowadzić jej zmiany z powodu omawianej złożoności).

Przyznaję, że niewielka część tych wątpliwości wynika z tego, że jest wysoce prawdopodobne, że nowy właściciel już mnie nie wykorzysta. Nie obchodzi mnie to, że ktoś to przejmie, ponieważ nie był to duży generator dochodów.

Ale dbam o 2 (powiązane) rzeczy

  1. Obchodzi mnie trochę, że nowy opiekun będzie musiał przemyśleć nieco trudniej, próbując zrozumieć kod. Złożoność jest złożonością i nie chcę rozgniewać psycho-maniaka, który mnie ściga.

  2. Ale jeszcze bardziej martwię się o to, że konkurencja widzi tę złożoność i myślę, że po prostu wdrażam wzorce projektowe, aby wypełnić moje godziny pracy. Następnie rozpowszechniam tę pogłoskę, aby zaszkodzić mojej drugiej firmie. (Słyszałem o tym.)

Więc...

Ogólnie rzecz biorąc, czy wcześniej potrzebna złożoność powinna zostać usunięta, nawet jeśli działa, a historycznie wykazano potrzebę złożoności, ale nie masz żadnych wskazówek, że będzie ona potrzebna w przyszłości?

Nawet jeśli odpowiedź na powyższe pytanie brzmi „nie”, czy mądrze jest usunąć tę „niepotrzebną” złożoność, przekazując projekt konkurentowi (lub nieznajomemu)?

ElGringoGrande
źródło

Odpowiedzi:

7

Pod pewnymi względami myślę, że jest to w dużej mierze decyzja biznesowa i niekoniecznie oparta na samym kodzie. Kilka rzeczy do rozważenia:

  • Czy zarabiasz na wprowadzaniu zmian?
  • Czy kod działa obecnie zgodnie z oczekiwaniami?
  • Czy są jakieś problemy z bezpieczeństwem lub wydajnością w takim kodzie?
  • Czy kwota długu technicznego przewyższa koszt jego naprawienia?
  • Co realistycznie może się zdarzyć, jeśli pozostawisz kod bez zmian?
  • Jakie są przyszłe problemy, które mogą pojawić się z refaktoryzacją lub bez?
  • Jaką część odpowiedzialności stanowi kod dla Ciebie i Twojej firmy?

Jesteś w najlepszej pozycji, aby odpowiedzieć na te pytania. Jednak na podstawie twojego opisu nie wiem, czy zawracałbym sobie głowę refaktoryzacją i upraszczaniem, ponieważ nie brzmi to tak, jakby było warte twojego czasu. Jeśli obecnie działa, klient jest zadowolony, a Ty nie lubisz zarabiać za aktualizowanie wszystkiego, pozwól mu i pracuj nad działalnością generującą przychód.

Krótko mówiąc, dokonaj analizy kosztów i korzyści oraz oceny ryzyka obu ścieżek i zastosuj najbezpieczniejszy, najbardziej wydajny i najbardziej opłacalny sposób działania.

VirtuosiMedia
źródło
6

Czy usunięcie tego kodu i zastąpienie go czymś prostym dla przyszłej łatwości kodowania funkcji, którą klient musi wziąć pod uwagę i za którą zapłacić?

Możesz mieć coś przydatnego, z czego mógłby się nauczyć inny programista, ale prawdopodobieństwo znalezienia aplikacji innego klienta do podłączenia jest mało prawdopodobne.

Plotki na temat kodu konkurencji nie są czymś, czemu można zapobiec. Będą wyglądać głupio, próbując negatywnie rekrutować klientów.

JeffO
źródło
+1 za „i zapłać za”. Jeśli chcesz poprosić klienta o zapłatę za zmianę, musisz pozwolić klientowi zdecydować, czy dokonać zmiany. Zauważ, że pozostawienie systemu elastycznego zwiększa pewną wartość odsprzedaży firmy, ponieważ pozwoli właścicielowi NASTĘPNIE łatwiej wprowadzać zmiany.
John R. Strohm,
3

Często mówi się: „Jeśli się nie zepsuło, nie naprawiaj go”.

Za tą regułą kryje się kilka uzasadnień. Niektóre z nich mogą polegać na tym, że „uproszczenie” grozi wprowadzeniem nowych, różnych i być może większych błędów, może zająć coraz więcej czasu na rozwój od innych cenniejszych przedsięwzięć i może być całkowicie niewłaściwą zmianą w przypadku nieoczekiwanej przyszłej okazji biznesowej, która powstaje.

Jeśli istnieje wystarczająca wartość biznesowa, aby ten kod był przenośny i łatwiejszy w utrzymaniu, zdecyduj, czy ta wartość jest naprawdę wystarczająca, aby uznać obecny kod za „uszkodzony”. Może tak być, jeśli planowana jest duża ekspansja biznesowa lub podejrzewasz ukryty błąd ukryty w złożoności, który może doprowadzić do upadku firmy.

hotpaw2
źródło
2

Przede wszystkim, jeśli aplikacja została już raz przejęta przez nowego właściciela, może się to powtórzyć. I kolejny właściciel może znów zacząć korzystać ze złożoności, z której obecnie nie korzysta.

Poza tym nietrywialne zmiany w działającym kodzie zawsze pociągają za sobą ryzyko, dlatego (jak zauważyli inni) klient powinien się z nimi zgodzić (i za nie zapłacić). Jeśli obecna „dodatkowa” złożoność nie powoduje zauważalnej, mierzalnej wady (takiej jak problemy z wydajnością), nie ma silnego powodu, aby ją usunąć.

(Potencjalni) klienci, którzy (nie) zatrudniają cię wyłącznie na podstawie plotek konkurencji, i tak nie są tego warte, chyba że desperacko potrzebujesz dochodu. Masz dobre i logiczne powody, dla których wdrożyłeś aplikację tak, jak to zrobiłeś, i każdy poważny klient może to zrozumieć. Ktoś, kto nie zadaje ci pytania - lub nawet nie zadaje sobie trudu - prawdopodobnie sprawi ci po drodze więcej kłopotów niż praca.

Péter Török
źródło
1

Ogólnie rzecz biorąc, czy wcześniej potrzebna złożoność powinna zostać usunięta, nawet jeśli działa, a historycznie wykazano potrzebę złożoności, ale nie masz żadnych wskazówek, że będzie ona potrzebna w przyszłości?

Nie.

Nawet jeśli odpowiedź na powyższe pytanie brzmi „nie”, czy rozsądnie jest usunąć tę „niepotrzebną” złożoność, przekazując projekt konkurentowi (lub nieznajomemu)

Nie. Po co marnować czas na naprawę niskiego priorytetu? Brak szkody dla kodu tam pozostającego.

Co do pytania: kiedy należy usunąć złożoność?

Uważam, że jeśli się nie zepsuło, nie naprawiaj tego .

Pizza Pan
źródło
0

Aby móc usunąć złożoność, muszą być spełnione następujące warunki:

  1. Usunięty element musi być niezależny od programu. Jeśli istnieją jakieś zależności od otaczającego programu do danego kodu, samo usunięcie złożoności nie będzie działać
  2. Niestety, jeśli wygląda to na złożoność, jest bardzo prawdopodobne, że elementy nie są niezależne i zależności spowodują uszkodzenie programu po usunięciu elementu
  3. Usunięcie wszystkich zależności zajmie trochę czasu, dlatego należy wziąć pod uwagę czas, gdy oceniasz, czy operacja jest warta wysiłku
  4. Przez większość czasu nie jest to warte wysiłku, ale po prostu zdecydujesz, że żaden nowy kod nie będzie używał starego
tp1
źródło
Są niezależne i faktycznie je usunąłem i przeszły wszystkie testy jednostkowe / integracyjne / regresyjne. Złożoność polega po prostu na wdrożeniu strategii wymagającej przynajmniej interfejsu i konkretnej implementacji tego interfejsu. W dwóch lub kilkudziesięciu miejscach, w których nowy właściciel uprościł wszystko, można to zrobić za pomocą jednej klasy.
ElGringoGrande
0

Myślę, że działa tu coś większego ... Skalowalność

To, o czym mówisz, nazywa się skalowalnością . Nie ma znaczenia, czy kodowanie jest skomplikowane, ma znaczenie, czy aplikacja może ewoluować w oparciu o nowe reguły biznesowe lub zmienione reguły biznesowe. Co się stanie, jeśli następny właściciel chce czegoś zupełnie innego.

Mówię więc: zachowaj kod i udokumentuj go. Jest to funkcja, z której można korzystać z aplikacji.

Michael Riley - AKA Gunny
źródło
0

Ogólnie rzecz biorąc, czy wcześniej potrzebna złożoność powinna zostać usunięta, nawet jeśli działa, a historycznie wykazano potrzebę złożoności, ale nie masz żadnych wskazówek, że będzie ona potrzebna w przyszłości?

Usunięcie złożoności wymaga wysiłku i ryzyka. Jeśli jest to więcej niż dodatkowy wysiłek i ryzyko związane z utrzymaniem zbyt złożonego kodu, należy go zachować. W przeciwnym razie usuniesz go. Trudno jednak oszacować te ryzyko.

Dodam, że można zmniejszyć ryzyko trudniejszej konserwacji, dokumentując, dlaczego w kodzie użyto strategii wzorca projektowego. Osobiście uważam, że każdy wzorzec projektowy powinien być identyfikowalny z wyraźnym wymogiem (funkcjonalnym lub niefunkcjonalnym).

Nawet jeśli odpowiedź na powyższe pytanie brzmi „nie”, czy mądrze jest usunąć tę „niepotrzebną” złożoność, przekazując projekt konkurentowi (lub nieznajomemu)?

Twój scenariusz rezygnacji z rywalizacji o godziny wypełnienia jest właśnie powodem, dla którego powinieneś udokumentować złożoność. Jeśli udokumentujesz i uzasadnisz (z konkretnymi wymaganiami klienta) użycie dowolnego wzoru, jesteś objęty ubezpieczeniem. Jeśli nie możesz usprawiedliwić wzoru wymaganiem klienta, wygląda to na nadprojekt lub zapalenie wzoru.

Jeśli wymagania się zmienią, możesz uzasadnić pozostawienie go ze względu na ryzyko złamania kodu (lub nakładu pracy, aby chirurgicznie usunąć wzór).


Myślę, że dobrze jest rozróżnić przypadkową złożoność od zasadniczej złożoności , ponieważ wzorce często obejmują oba.

Oznacza to, że wymóg obsługi różnych algorytmów przy podejmowaniu decyzji o podwyżce jest istotną złożonością (część problemu do rozwiązania). Utrzymanie swojego kodu jest ułatwione przez wzorzec strategii, ale zakodowane jeśli / wtedy alternatywą dla strategii nadal będzie działać. Przeprowadziłem ćwiczenia na kursach magisterskich, w których studenci znajdują możliwości zastosowania strategii w projektach typu open source. Złożoność niekoniecznie jest lepsza / gorsza przy stosowaniu strategii (ponieważ jest to niezbędna złożoność). Czasami może być jeszcze trudniej zrozumieć strategię, ponieważ kod dzieli się na wiele klas z polimorfizmem, a nie na jeden duży blok if / then / else.

Idealnie wzór działa, gdy korzyści, które zapewnia, przewyższają koszty jego wad. Ponownie, ilościowe określenie tych rzeczy jest trudne. Często wzorzec uszczęśliwia dewelopera (nie tylko dlatego, że ułatwia dodawanie nowej strategii przebijania, ale także pozwala deweloperom na ciepłe kłótnie, aby wiedzieć, że wzór został zastosowany). Trudno jest pokazać klientom, w jaki sposób przynoszą im korzyści.

Klient nie dba o szczegóły, a nawet go nie rozumie. W przypadku nowej właścicielki stosującej KISS w swoich procesach, to redukuje istotną złożoność, która powinna mieć również wpływ na oprogramowanie.

Fuhrmanator
źródło