Ile nadmiarowości / niezawodności powinno wdrożyć złożone oprogramowanie?

12

Głównym celem tego pytania: niektóre programy wykonują „dodatkową pracę” w celu zwiększenia szansy na „ostatecznie pomyślny / zadowalający” wynik, pomimo jednego lub więcej wewnętrznych błędów w oprogramowaniu, co wymaga dłuższego czasu wykonania, gdy te błędy wystąpią. Wszystko to dzieje się bez wiedzy użytkownika, jeśli wynik byłby udany.

Definicja złożonego oprogramowania:

  • Zawiera kod napisany przez (ponad 10 programistów) przez cały okres jego użytkowania, a nie napisany w tym samym przedziale czasowym
  • Zależy od ponad 10 bibliotek zewnętrznych, każda z zastrzeżeniami
  • Typowe zadanie programowe (do generowania pożądanego przez użytkownika wyniku) wymaga 10 lub więcej parametrów wejściowych, przy czym większość z nich ma wartości domyślne, ale można je konfigurować, jeśli użytkownik potrzebuje kontroli.
  • Co najważniejsze, oprogramowanie, które ma odpowiednią złożoność w stosunku do wykonywanego zadania, tj. Nie jest niepotrzebnie skomplikowane .

Edytowane: Co jest złożone? Proszę zobaczyć Istnieje duża różnica między złożonym a skomplikowanym . (link bezpośredni)

Definicja redundancji / odporności w ramach tego pytania :
(Dodano niezawodność na podstawie komentarzy)

  • Jeśli zadanie oprogramowania nie powiodło się, gdy użyto bieżącego zestawu parametrów, wypróbuj inne parametry.
    • Oczywiście musi istnieć wiedza wewnętrzna, że ​​te „różne” parametry używają innej ścieżki kodu, co może skutkować innym (miejmy nadzieję lepszym) wynikiem.
    • Czasami te różne ścieżki kodu są wybierane na podstawie obserwacji bibliotek zewnętrznych.
  • Na koniec, jeśli faktyczne wykonane zadanie różni się nieco od specyfikacji użytkownika, użytkownik otrzyma raport szczegółowo opisujący rozbieżność.
  • Wreszcie, podobnie jak 10 konfigurowalnych parametrów, nadmiarowość i raportowanie są również konfigurowalne.

Przykład takiego oprogramowania:

  • Migracja bazy danych
    • Baza danych biznesowych
    • Baza danych kontroli źródła itp.
  • Konwersja wsadowa między dokumentem Word a dokumentem OpenOffice, PowerPoint i OpenOffice Draw itp.
  • Automatyczne tłumaczenie całej strony internetowej
  • Automatyczna analiza pakietu oprogramowania, takiego jak Doxygen, ale tam, gdzie analiza musi być bardziej niezawodna (tj. Nie tylko narzędzie dokumentacji)
  • Komunikacja sieciowa, w której pakiety mogą zostać utracone i należy spodziewać się wielu ponownych prób

To pytanie zostało pierwotnie zainspirowane tym, jak radzisz sobie z celowo złym kodem?
ale teraz koncentruje się tylko na jednej z przyczyn wzdęć oprogramowania. To pytanie nie obejmuje żadnych innych przyczyn wzdęć oprogramowania, takich jak dodanie nowych funkcji.

Ewentualnie powiązane:

rwong
źródło
5
To nie jest redundancja, to jest wytrzymałość ...
5
Czy odpowiedź nie jest po prostu „tyle, ile potrzeba?”
Dean Harding
@Dean - absolutnie jest to wymóg jak każdy inny. Sztuką jest wyjaśnienie tego użytkownikom oraz konsekwencji i kosztów dla użytkowników, ale można to zrobić.
Jon Hopkins,
Dzięki @ Thorbjørn za opinię. Dodałem solidność do tytułu i definicji.
rwong
Trzymaj się z dala od starej bazy kodu, chyba że masz 5 dzieci do karmienia.
Job

Odpowiedzi:

7

To pytanie biznesowe, a nie techniczne.

Czasami koduję z badaczami lub na prototypie, więc zbudujemy coś o bardzo niskiej odporności. Jeśli się zepsuje, naprawimy to. Inwestowanie w dodatkową magię nie ma sensu, jeśli wkrótce wyrzucimy kod.

Ale jeśli użytkownicy twojego systemu potrzebują go jako solidnego, powinieneś go zbudować w ten sposób. I powinieneś uczynić go solidnym w sposób, w jaki Ty i oni potrzebujemy, aby zmaksymalizować długoterminowy sukces, ignorując przy tym rodzaje redundancji / niezawodności, których nie potrzebują.

Ogólnie rzecz biorąc, zaczynam od zera, a następnie dodaje solidności z czasem. Często zadaję takie pytania, jak ta część normalnego procesu planowania. Ogólnie pracuję w stylu programowania ekstremalnego, w którym tworzymy długą listę pożądanych funkcji, a także umieszczam tam funkcje niezawodności. Np. „System przetrwa awarię pojedynczego pudełka”, miesza się z takimi rzeczami jak „Użytkownik może dołączyć przy użyciu poświadczeń Facebooka”. Cokolwiek powstanie pierwsze, najpierw buduję.

William Pietri
źródło
5

Złożone oprogramowanie zwykle jest redundantne, jak zapewne wiesz, ale oczywiście nie dlatego, że jest to najlepszy sposób, ale dlatego, że programiści zwykle „przyczepiają się” do istniejącego kodu, zamiast starać się zrozumieć szczegółowo, jak działa oprogramowanie.

Jednak gdybyś zapytał mnie, ile zwolnień powinno być do przyjęcia, nie powiedziałbym nic. Redundancja jest jednym z wielu skutków ubocznych złożoności, archemezą prostoty. Prawdopodobnie prostota powinna zająć miejsce z tyłu, jeśli czas ma większe znaczenie, choć podkreślam, że ci, którzy twierdzą, że czas jest najważniejszy, rzadko ci, którzy faktycznie dbają o rozwój oprogramowania. Zazwyczaj kierownik projektu zachęca cię do jak najszybszego wykonania zadania, abyś mógł wrócić do bardziej palących problemów, jednak Twoim obowiązkiem jako programisty jest wiedzieć, kiedy zadanie zostanie wykonane. Myślę, że zadanie nie zostanie wykonane, dopóki nie uda się go zintegrować z programem, tak jak powinno być. Być może program jest skomplikowany,

Należy jednak powiedzieć, że w ten sposób może być konieczne wygenerowanie zbędnego kodu. Jeśli projekt jest już bardzo redundantny, kontynuacja może być łatwiejsza, zakładając, że szef nie ma kilku tygodni na zabicie, co pozwala na restrukturyzację całego projektu.

Edycja: W związku z przeredagowaniem pytania dodam trochę o solidności. Moim zdaniem sprawdzanie parametrów powinno odbywać się tylko wtedy, gdy A) akceptujesz bardzo konkretny format, taki jak wartość daty jako ciąg lub B) różne parametry mogą potencjalnie powodować konflikty lub wykluczać się wzajemnie.

W przypadku A) wymagania dotyczące zgodności parametrów z określonym formatem są zwykle kluczowe dla konieczności zastosowania metody (np. Konwersja daty z ciągu). Technicznie rzecz biorąc, może się to zdarzyć w twoim programie bez konieczności, ale zdecydowanie zachęcam do wyeliminowania tych możliwości i zaakceptowania tylko tych parametrów, o których wiesz, że reprezentują typ danych, których szukasz (Zaakceptuj datę, a nie ciąg znaków, jeśli nie można na przykład konwertować. Jeśli konwersja musi być również wykonana, użyj metody narzędzia do konwersji ciągu przed przekazaniem go do metody).

Jeśli chodzi o B), wzajemnie wykluczające się parametry reprezentują złą strukturę. Powinny istnieć dwie klasy, jedna, która obsługuje jedną skrzynkę, a druga, która obsługuje ją w inny sposób. Wszystkie typowe operacje można wykonywać w jednej klasie bazowej, aby uniknąć nadmiarowości.

W sytuacjach, w których liczba parametrów metody wynosi 10+, zaczynam rozważać plik właściwości zawierający wszystkie te parametry, które najprawdopodobniej nie będą się często zmieniać. Jeśli się zmienią, możesz zapisać wartość domyślną w pliku właściwości i dodać metodę „setPropertyName ()”, która pozwala zastąpić wartość domyślną w czasie wykonywania.

Neil
źródło
4
Myślę, że źle rozumiesz pytanie. Ma na myśli „redundancję” jak w „nie ginąć w płomieniach, gdy wystąpi błąd”, a nie jak w „pisaniu duplikatu kodu”. Solidność jest lepszym terminem na to, jak zauważyli inni.
Adam Lear
redundancja ma pozytywny wpływ na kluczowe zadania. ludzkie ciało jest tutaj doskonałym przykładem.
Claudiu Creanga
3

Oprogramowanie powinno wybaczać błędy użytkownika i całkowicie nie tolerować błędów programistów.

Oznacza to, że oprogramowanie powinno być bardzo solidne i umożliwiać bezproblemowe odzyskiwanie w przypadku błędów wprowadzania danych przez użytkownika i błędów konfiguracji systemu. Przynajmniej przyjazny komunikat o błędzie informujący, gdzie wystąpił błąd (pole wejściowe, plik konfiguracyjny, argument wiersza poleceń itp.) I jakie ograniczenie zostało naruszone („musi być mniejszy niż X znaków”), prawidłowe opcje to [X , Y, Z] ”itp.). Dla dodatkowej niezawodności oprogramowanie może zasugerować alternatywę lub zastosować rozsądną wartość domyślną (ale zawsze powinno wskazywać, że nie używa dokładnie tego, co podał użytkownik).

Nie mogę wymyślić wielu sytuacji, w których uzasadnione jest automatyczne ponawianie z różnymi ustawieniami domyślnymi, ale są pewne (automatyczne ponawianie w celu ustanowienia łącza komunikacyjnego wydaje się rozsądne). Zgadzam się z @William, że ten poziom „redundancji” jest decyzją biznesową.

Z drugiej strony nie powinna istnieć odporność na błędy programistyczne w czasie wykonywania. Jeśli istnieją warunki wstępne dla parametrów funkcji, należy je sprawdzić za pomocą stwierdzeń, a nie kontroli w czasie wykonywania. To mój wielki wkurzający zwierzak, aby zobaczyć zbędne sprawdzanie błędów i zgłaszanie tego samego parametru na trzy lub cztery poziomy w stosie wywołań:

 int A(int x)
 {
   if (x==0) return -1
   ...
 }
 int B(int x)
 {
   if (x==0) return -1
   err = A(x)
   if (err) return err;
   ...
 }
 // and so on and so on....

To tylko dodatkowa niepotrzebna złożoność. Nie powinieneś tracić czasu na zastanawianie się, jak jedna funkcja powinna obsłużyć błąd wprowadzony przez niewłaściwe użycie innej. Jeśli mówisz o „solidności”, to nie potrzebujesz jej. Zastąp go twierdzeniami i dokładnymi testami integracji.

AShelly
źródło
3

To kwestia wymagań.

Czy istnieje wymóg dotyczący solidności?

„Gdy łącze komunikacyjne ulegnie awarii, błędne pakiety są odrzucane” „Gdy łącze wznawia działanie, żadna transakcja nie jest przetwarzana dwukrotnie”

powinny istnieć przypadki użycia do odzyskiwania po błędzie (w przeciwnym razie skąd wiesz, jak to się stanie?)

Pozostawienie programistom wynalezienia niezawodności na bieżąco (w razie potrzeby) skutkuje „magicznymi” systemami.

Z czasem wszystkie magiczne systemy stają się magią. Korekcja błędów w tle ukrywa występowanie błędów, dzięki czemu nie będą one korygowane, więc system ostatecznie ulegnie degradacji do stanu większej entropii; i działa jak bzdura, ponieważ cały czas poprawia błędy. Musisz mieć limit, aby zatrzymać system w stanie trwale zdegradowanym.

Tim Williscroft
źródło
2

Niektóre operacje prawdopodobnie wymagają podejścia „spróbuj ponownie”, zwłaszcza jeśli zależą od zasobów zewnętrznych, takich jak baza danych. Na przykład, jeśli nie można połączyć się z bazą danych lub zapytanie nie powiedzie się, operację można powtórzyć pewną liczbę razy, zanim zrezygnuje i wyśle ​​błąd na wyższy poziom. Jednak, zgodnie z pewną logiką, wielokrotne próbowanie tego samego jest często objawem złego kodu i magicznego myślenia, które kryje prawdziwe problemy.

Matt H.
źródło
Jeśli ponowna próba nastąpi bez zliczenia i zgłoszenia / widoczności, twoje systemy ulegną degradacji i będą działać nieprawidłowo z powodu ich magicznej samokorekty. Zawsze używaj nieszczelnych liczników kubełkowych (PLOPD4) do zgłaszania prób i błędów. W ten sposób niski poziom jest ignorowany, ale problemy stają się widoczne dla użytkowników.
Tim Williscroft,