Jak poradzisz sobie ze skokiem złożoności?

13

Wydaje się to rzadkie, ale powszechne doświadczenie, że czasami pracujesz nad projektem i nagle coś niespodziewanie się pojawia, rzuca ogromny klucz w prace i bardzo zwiększa złożoność.

Na przykład pracowałem nad aplikacją, która rozmawiała z usługami SOAP na różnych innych komputerach. Wymyśliłem prototyp, który działał dobrze, a następnie opracowałem regularny interfejs i ogólnie wszystko działało w przyjemny, dość prosty i łatwy do naśladowania sposób. Działało świetnie, dopóki nie rozpoczęliśmy testowania w szerszej sieci i nagle strony zaczęły przekraczać limit czasu, ponieważ opóźnienie połączeń i czas wymagany do wykonania obliczeń na zdalnych komputerach spowodowały przekroczenie limitu czasu żądań do usług mydlanych. Okazało się, że musimy zmienić architekturę, aby rozdzielić żądania na ich własne wątki i buforować zwrócone dane, aby można je było stopniowo aktualizować w tle, zamiast wykonywać obliczenia na podstawie żądania na żądanie.

Szczegóły tego scenariusza nie są zbyt ważne - w rzeczywistości nie jest to świetny przykład, ponieważ był dość przewidywalny, a ludzie, którzy napisali wiele aplikacji tego typu dla tego rodzaju środowiska, mogli go przewidzieć - z tym wyjątkiem, że ilustruje sposób, w jaki można zacząć od prostej przesłanki i modelu i nagle do eskalacji projektu dochodzi do eskalacji złożoności.

Jakie masz strategie radzenia sobie z tego rodzaju zmianami funkcjonalnymi, których potrzeba pojawia się - często w wyniku czynników środowiskowych, a nie zmian specyfikacji - później w procesie rozwoju lub w wyniku testowania? Jak zachować równowagę między unikaniem przedwczesnego ryzyka optymalizacji / YAGNI / nadmiernej inżynierii projektowania rozwiązania, które łagodzi potencjalne, ale niekoniecznie prawdopodobne problemy, w przeciwieństwie do opracowywania prostszego i łatwiejszego rozwiązania, które może być tak samo skuteczne, ale nie obejmuje gotowości do każda możliwa ewentualność?

Edycja: odpowiedź Szalonego Eddiego zawiera: „wysysasz to i znajdujesz najtańszy sposób na wdrożenie nowej złożoności”. To sprawiło, że pomyślałem o czymś ukrytym w pytaniu, ale nie podniosłem się specjalnie.

Po uderzeniu w ten guz i wprowadzeniu niezbędnych zmian. Czy robisz coś, co utrzyma projekt tak blisko harmonogramu, jak to możliwe, ale może wpłynąć na łatwość konserwacji, czy wrócisz do swojej architektury i przerobisz ją na bardziej szczegółowym poziomie, który może być łatwiejszy do utrzymania, ale odepchnie wszystko podczas rozwoju?

glenatron
źródło

Odpowiedzi:

8

Co przychodzi mi do głowy, czytając to, zwinne powiedzenie: najpierw stawiaj czoła najbardziej ryzykownym i / lub najmniej zrozumiałym zadaniom w całym cyklu życia projektu . Staram się jak najszybciej stworzyć działający szkielet projektu, aby udowodnić, że koncepcja działa. To z kolei pozwala również na przeprowadzenie okrutnych testów w celu wykrycia, czy architektura rzeczywiście spełnia obietnicę w rzeczywistych okolicznościach. Ponadto, jeśli w rozwiązaniu znajduje się jakaś nowa, nieznana technologia / platforma / narzędzie, weź to również wcześnie.

Jeśli podstawowa architektura jest w porządku, poszczególne funkcje można dodawać i testować przyrostowo, a także w razie potrzeby refaktoryzować, przy relatywnie niższych kosztach. Konieczność zmiany architektury to duże ryzyko, z którym należy sobie radzić z góry. Daje to szybką informację zwrotną: w najgorszym przypadku, jeśli cała koncepcja się rozpadnie, wiemy o tym wcześnie i możemy przerwać projekt przy minimalnej stracie.

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

Twój przykład dotyczył niektórych z najtrudniejszych aspektów programowania, a mianowicie obliczeń rozproszonych i programowania współbieżnego , które są coraz szerzej stosowane i utrudniają programistom pracę.

Nawet „normalne” programowanie (pojedynczy wątek na jednej maszynie) jest tak skomplikowane dla każdego nietrwialnego programu, że potrzeba wielkich umiejętności i wieloletniego doświadczenia, aby uzyskać w tym dobry użytek - ale wciąż daleko od „rozwiązania”. Nawet na tym poziomie złożoności, głównie z powodu wybuchu kombinatorycznego , znacznie przekraczają zdolność ludzkiego mózgu do pełnego zrozumienia i zrozumienia. Myślenie inaczej jest głupotą.

Przetwarzanie rozproszone i programowanie współbieżne dodają jeszcze dwa wymiary do wielkości przestrzeni „złożoności”, która rośnie co najmniej w sześciennych (sp?) (N ^ 3) w porównaniu do programowania „normalnego”. Pomyślmy na przykład o nowych zestawach problemów i błędów, z którymi musimy sobie poradzić. Zabawne jest nawet granie z pomysłem, że w tej skali można pojąć wzajemne połączenia i skutki uboczne.

Najwyraźniej nie mam srebrnych kul, ale jestem pewien, że największym błędem, jaki można popełnić, jest myślenie, że wszystko rozumiesz i rozwiązałeś.

Kilka pomysłów, jak sobie z tym wszystkim poradzić, oprócz innych odpowiedzi, które już zawierały:

  • Wielka pokora
  • Zaakceptuj, że twój system / program jest niedoskonały, nietrwały i niekompletny .
  • Przygotuj się na błędy
  • Obejmuj zmianę
  • Zaplanuj zwolnienie
  • Pomyśl o sprawdzeniu przyszłości
  • Spójrz na (lub przestudiuj) biologię lub socjologię, jak zachowują się złożone systemy
  • Staraj się, aby uniknąć stanu zmiennego. Przejdź do protokołów bezstanowych (takich jak REST i HTTP).
  • Programowanie funkcjonalne może złagodzić ból

Chyba mógłbym to kontynuować. Bardzo ciekawy temat :)

Maglob
źródło
Spójrz na (lub przestudiuj) biologię lub socjologię, jak zachowują się złożone systemy - Dalej. Reszta twojej odpowiedzi była solidna, ale ma to tak peryferyjne zastosowanie do opisanego problemu.
Jim G.
1
@Jim G. Może. Biologia nie pomoże zoptymalizować twoich pętli, ale jeśli chcesz wymyślić nowe perspektywy, spostrzeżenia lub skuteczne abstrakty (dotyczące rozwoju oprogramowania), pomaga wyjść z piaskownicy. Argumentując, że biologia (lub socjologia) nie ma nic wspólnego z programowaniem, zaledwie kilka kroków od argumentowania, że OOP lub wzorce projektowe nie mają nic wspólnego z programowaniem. Na przykład: OOP : biologia -> Alan Kay -> OOP / Smalltalk. Lub Wzory projektowe : socjologia -> projektowanie urbanistyczne -> Christopher Alexander -> Język wzorców -> Wzory projektowe.
Maglob
@Jim G. Cont. Niektóre cytaty, Alan Kay: „Myślałem, że obiekty są jak komórki biologiczne i / lub pojedyncze komputery w sieci, zdolne tylko do komunikowania się z wiadomościami” oraz Wikipedia: „[Wzorzec projektu] Idea została wprowadzona przez architekta Christophera Alexandra w dziedzina architektury [1] i została dostosowana do różnych innych dyscyplin, w tym informatyki ”
Maglob
W porządku. Daję Ci +1 za Spróbuj, aby uniknąć stanu zmienności i innych samorodków. Chodzi mi o to, że jeśli twój menedżer zlecił ci zmniejszenie złożoności, z pewnością zastosowałbyś brzytwę Occama do problemu i zabrałeś się do pracy. Nie sądzę, że ty lub ktokolwiek inny „spojrzałby na biologię” po pomoc w bezpośrednim problemie.
Jim G.
2

Nie zgadzam się z duchem odpowiedzi @ Pétera Töröka, ponieważ zakłada ona, że ​​zespół (lub osoba indywidualna) może koniecznie przewidzieć najbardziej ryzykowne elementy na wczesnym etapie cyklu życia projektu. Na przykład w przypadku PO zespół nie mógł przewidzieć rosnącej złożoności związanej z rozwiązaniem wielowątkowym, dopóki ich plecy nie oprą się o ścianę.

Pytanie PO jest dobre i mówi o problemie wielu sklepów z oprogramowaniem.

Oto jak poradziłbym sobie z problemem:

  1. Postępuj zgodnie z radami Freda Brooksa i organizuj programistów jak zespół chirurgów .
  2. Wybierz mądrego i „życzliwego” mistrza-chirurga, który może zarówno: A) zyskać zaufanie i szacunek swoich rówieśników; oraz B) Podejmuj trudne decyzje w odpowiednim czasie.
  3. Spodziewaj się, że mistrz chirurg ograniczy złożoność na początku i na końcu procesu programowania.

Więcej na temat punktu 3:

  1. Master-chirurg powinien podjąć świadomy wysiłek, aby zaproponować najprostsze rozwiązanie, które będzie działać. Lata znaczącego doświadczenia powinny dać mistrzowi chirurgowi taką możliwość.
  2. Szersza organizacja, czyli przełożeni kapitana chirurga, powinna dać zespołowi wystarczająco dużo czasu i zasobów, aby zmniejszyć złożoność po dacie wysyłki. Umożliwi to zespołowi programistów zarówno terminowe wysyłanie kodu, jak i wykonywanie kaizen, aby na bieżąco zmniejszać złożoność.
Jim G.
źródło
IMHO w przypadku PO powinni byli zacząć testować wcześniej, aby odkryć, jak (i ​​czy) ich architektura działa w rzeczywistych okolicznościach. Przy okazji sugerując, że masz „chirurga głównego”, wydaje się, że zasadniczo sugerujesz, że ludzie, którzy mogą przewidzieć techniczne ryzyko związane z projektem - dokładnie to, z czym twierdzisz, że się nie zgadzasz.
Péter Török,
@ Péter Török: ... Sugerując, aby mieć „głównego chirurga”, wydaje się, że w zasadzie sugerujesz, że są ludzie, którzy mogą przewidzieć techniczne ryzyko związane z projektem : Nie, nie jestem. Mówię, że ci ludzie są oboje: A) Najlepsi, aby przede wszystkim całkowicie unikać złożoności; oraz B) Najlepiej nadaje się do wykopania zespołu ze złożoności po wysłaniu kodu.
Jim G.
IMHO mówimy o tym samym. Doświadczenie, które pomaga twojemu „chirurgowi” wybrać najprostsze rozwiązanie, które może działać, jest oparte na wspomnieniach z poprzednich projektów i rozwiązań oraz wiedzy, które rozwiązanie zadziałało (lub nie) w danym przypadku. Innymi słowy, przegląda mające zastosowanie rozwiązania konkretnych problemów i ocenia potencjalne korzyści i ryzyko każdego z nich. To pomaga mu wybrać odpowiedni dla bieżącej sytuacji, unikając w ten sposób bardziej ryzykownych ścieżek .
Péter Török
1
Przypomina mi to cytat nieżyjącego, świetnego trenera koni Raya Hunta: „Jak uzyskać dobry osąd? Doświadczenie. Jak zdobyć doświadczenie? Zły osąd”.
glenatron
1

Kod do interfejsów

Pisząc nową funkcjonalność powiązaną z inną funkcjonalnością, stwórz granicę w postaci interfejsu (rodzaju Java), przez który wszystkie przechodzą. To będzie

  1. upewnij się, że masz pełną kontrolę nad używanymi funkcjami
  2. pozwalają mieć wiele implementacji tej samej funkcjonalności.
  3. zmniejsz ogólną złożoność, ponieważ moduły są tylko cienko połączone, a nie w pełni powiązane.

źródło
0

można zacząć od prostej przesłanki i modelu i nagle do eskalacji projektu dochodzi do eskalacji złożoności

Nie zaskakujący.

To jest tworzenie oprogramowania. Jeśli nie wymyślasz czegoś nowego, pobierasz istniejące, sprawdzone rozwiązanie.

Jest mało miejsca na środku.

Jeśli wymyślasz coś nowego, musi istnieć co najmniej jedna funkcja, której nie w pełni rozumiesz. (Aby to w pełni zrozumieć, musisz mieć działającą implementację, której byś po prostu użył).

Jak sobie z tym poradzić?

  1. Miej realistyczne oczekiwania. Wymyślasz coś nowego. Tam musi być częściami nie rozumieją.

  2. Miej realistyczne oczekiwania. Jeśli wydaje się, że działa poprawnie za pierwszym razem, coś przeoczyłeś.

  3. Miej realistyczne oczekiwania. Gdyby to było proste, ktoś inny zrobiłby to pierwszy, a ty po prostu mógłbyś pobrać to rozwiązanie.

  4. Miej realistyczne oczekiwania. Nie można bardzo dobrze przewidzieć przyszłości.

S.Lott
źródło
2
Czekaj, więc mówisz: masz realistyczne oczekiwania?
glenatron
0

Projektowanie i kodowanie z myślą o przestarzałości. Załóż, że to, co dziś kodujesz, będzie musiało zostać wycięte i zastąpione jutro.

Ian
źródło
0

Środowisko powinno być częścią specyfikacji. Zatem zmiana środowiska JEST zmianą specyfikacji. Jeśli natomiast oparłeś swój prototyp i projekt na środowisku innym niż to, co było w specyfikacji, popełniłeś głupi błąd. Tak czy inaczej, wysysasz go i znajdujesz najtańszy sposób na wdrożenie nowej złożoności.

Edward Strange
źródło
0

Podobnie jak w przypadku większości problemów programistycznych, to zależy moim zdaniem. Ten problem jest tak nieodłączny w twórczej pracy, że nie należy zapominać, że wystąpią awarie, i to jest w porządku . Programowanie jest nikczemnym problemem i zwykle nie znasz właściwego rozwiązania problemu, dopóki go nie rozwiążesz.

Istnieje jednak szereg lokalnych, specyficznych czynników, które mogą się tutaj znaleźć, takich jak:

  • Cele tego systemu. Czy to jednorazowa sprawa? Czy zamierzasz utrzymać ten system w perspektywie średnio- i długoterminowej?

Krótko mówiąc, może nie warto zastanowić się nad tym więcej niż wystarczy, aby uruchomić. Refaktoryzacja jest droga i nie tworzy natychmiastowej wartości końcowej dla użytkownika. jednak, nie ma prawie żadnego przypadku, który mógłby wymyślić inne niż absolutnie odrzucone oprogramowanie, w którym jest ono tak krótkotrwałe, że nie warto ulepszać projektu. O wiele ważniejsze jest, aby móc zrozumieć, co zrobiłeś i szybko to naprawić, niż zakończyć teraz. Jeśli będzie to na dłuższą metę, najprawdopodobniej w końcu się spłaci (i być może znacznie wcześniej, niż myśli każdy zaangażowany), lub odwrotnie (nie zrobienie tego spowoduje ból wkrótce zamiast „kiedy musimy go naprawić”). Prawie kusi mnie, by powiedzieć „zawsze znajdź czas, aby to poprawić”, ale są przypadki, w których nie jest to możliwe.

  • Cele zespołu. Czy jest to coś w rodzaju „zrób to teraz za wszelką cenę”, czy może „zróbmy to dobrze”?

Powinno to mieć ogromny wpływ na twoje decyzje. Twój zespół albo poprze tę decyzję, albo przekaże zasoby do przeprojektowania, albo zażąda szybkiego rozwiązania. Moim zdaniem, jeśli zauważysz, że zespół konsekwentnie popycha cię w złym kierunku, jest to ogromna czerwona flaga. Widziałem takie rzeczy w scenariuszu, w którym trwa ciągłe gaszenie ognia, w którym nigdy nie ma czasu na przeprojektowanie, ponieważ zawsze naprawiasz problemy, które tworzy zły projekt. Może jednak istnieć również środek masy: teraz „duct-tape”, napraw jak najszybciej (ale w rzeczywistości to zrób).

  • Twoje zrozumienie problemu. Dlaczego poprzednie rozwiązanie nie działało?

Naprawdę ważne. Zastanów się, jaki jest błąd lub problem i dlaczego tak się dzieje. Tego rodzaju sytuacja jest doskonałą okazją do znalezienia wadliwych (lub brakujących) założeń, ograniczeń i interakcji. Ogólnie rzecz biorąc, zawsze faworyzuj lepsze rozumienie problemu zamiast rozwiązywania obecnego problemu. To prawdopodobnie Twoja największa obrona przed YAGNI / nadinżynierią. Jeśli wystarczająco dobrze zrozumiesz swój problem, rozwiążesz go, a nie inne problemy.

Na koniec spróbuj zbudować rzeczy we właściwy sposób . Nie mówię o błędach i problemach, które napotykasz, gdy albo lepiej rozumiesz problem, albo wrodzony ludzki błąd. Nie mam na myśli: „nie popełniaj błędów i popraw je za pierwszym razem” - to niemożliwe. Mam na myśli, staraj się dobrze zarządzać złożonością w codziennej pracy, naprawiaj uszkodzone okna, staraj się, aby to było tak proste, jak to tylko możliwe, ulepszaj kod i myślenie przez cały czas. W ten sposób, gdy (nie jeśli) zmiana puka do twoich drzwi, możesz powitać je otwartymi ramionami zamiast strzelby.

Juan Carlos Coto
źródło