Po co refaktoryzować? Nie można od razu napisać dobrze? Czy słaby kod to zawsze zły kod?

4

Był taki film "Dzień Świstaka", w którym gość przeżywał ciągle ten sam dzień 2 lutego. Najpierw przydarzało mu się wiele pechów, np. szedł ulicą i samochód go ochlapywał itp. A później, ponieważ już ten sam dzień przeżył ileś razy, to wiedział, co się stanie i bawił się tym. Wiedział, w którym miejscu przejedzie samochód, wiedział, kogo spotka, co powiedzieć, czego nie mówić itp.

Tak samo z programistami - przy pierwszej implementacji ilość niewiadomych jest zbyt wielka, żeby od razu napisać prosty jasny kod - dlatego wychodzi spaghetti. Ew. jak ktoś jest "bojący się", to będzie stawiał na elastyczność i wzorce i doprowadzi do overengineeringu, co mu niewiele da (bo problem nie jest z jakością kodu, tylko z brakiem doświadczenia programisty w rozwiązywaniu danego typu problemów).

A jak już się rozwiązywało wcześniej jakiś problem ileś razy, to można pisać od razu lepiej, bo się wie, co się sprawdza, co się nie sprawdza. Łatwiej można przewidzieć różne problemy na długo, zanim wystąpią (bo widzieliśmy je już ileś razy). Jeśli jakichś wzorców warto użyć, to wiemy, jakich, a jakich lepiej nie - bo mamy know-how.

Być może software lepiej by wyglądał, gdyby na wczesnym etapie projektu programiści zamiast pisać produkcję, to robili masę PoCy i przepisywali od nowa po ileś razy, nabywając know how. Na późniejszym etapie ciężko przepisywać wszystko, jednak taką taktykę można by zastosować do nowych ficzerów. Zamiast wrzucać brzydki kod, robić implementację po kilka razy i wrzucić coś dopracowanego.

0
jarekr000000 napisał(a):

Patrząc z punktu widzenia Java i C# to te języki nie są już od dawna czysto obiektowe.

To prawda. Nie wiem jak Java, ale C# już od dawna jest brudnooobiektowy.
Funkcyjne wstawki w językach obiektowych mają na celu usunięcie proceduralnych fragmentów (takich jaki pętle z ifami), a nie zmianę ogólnej charakterystyki języka. To się po prostu nie uda.

C# chyba od więcej niż 10 lat. Co oznacza, że nie trzeba się gimnastykować i używać pokrętnych rozwiązań na klasach na proste problemy.

Klasy w języku obiektowym to nie jest pokrętne rozwiązanie, to jest podstawowa struktura organizacji kodu.

Jeśli problemem jest if na 500 linii kodu, to nie naprawi się go hasłem "lambdy" czy "FP". Kod trzeba ogarnąć, a trzymanie 500 linii lambd/funkcji w jednym pliku niekoniecznie będzie lepsze pod względem czytelności. Zwłaszcza nie w języku, który wymaga klamerek i returnów, więc funkcje wewnętrzne wyglądają chyba jeszcze gorzej niż ify.

LukeJL napisał(a):

Tak samo z programistami - przy pierwszej implementacji ilość niewiadomych jest zbyt wielka, żeby od razu napisać prosty jasny kod

Jeżeli się nie komplikuje od razu, to czemu kod ma nie wyjść prosty i jasny?

3

@somekind
To się po prostu nie uda. a próbowałeś, czy to jest założenie które pozwala na zracjonalizowanie sobie nie podejmowania wysiłku nauki nowych/innych paradygmatów programowania tym samym zachowując status quo nie wychodząc ze swojej strefy komfortu?
500 linii lambd/funkcji w jednym pliku nikt chyba nie namawiał do trzymania wszystkiego w jednym pliku.

Wydaje mi się że tutaj jest konflikt starego i nowego podejścia do programowania.
@jarekr000000 uważa FP jako by był kolejnym krokiem naprzód jeśli chodzi o rozwiązywanie problemów związanych z pisaniem oprogramowania,
a takie OOP to archaizm który już powinien odejść do lamusa jak kiedyś np. goto,
a @somekind jest apologetą tego co już zna, potrafi i rozumie, a do nowych/odkrytych na nowo rozwiązań podchodzi sceptycznie/ostrożnie/(niechętnie?)
Poprawcie mnie jeśli się mylę :P

1

Najpierw odpowiedzialbym na inne pytanie - kto jest odbiorca tego kodu i w jakim celu on powstaje. Ewentualnie zapytałbym analogicznie dlaczego piłkarz czasami pudłuje przy strzale na bramkę.

Jeżeli piszesz coś dla siebie i masz nieograniczony budżet czasowy, można zaryzykować stwierdzenie, że od razu piszesz docelowe rozwiązanie najwyższej jakości. Jeżeli grasz sam na pusta bramkę, prawdopodobnie zawsze strzelisz gola. Jednak świat nie jest idealny:

  • czasami trzeba iść na skróty, aby dowieźć określony zakres na nienegocjowalny termin
  • czasami robimy MVP, które być może po teście pójdzie do /dev/null
  • czasami eksperymentujemy z nową technologia, której nie znamy
  • zwykle zamiast spuszczać się nad pięknem kodu opłaca się iść dalej z kolejnym tematem - skupiamy się na celu, a taskow jest zawsze więcej niż rąk do pracy
  • zwykle brak pełnej wiedzy aby zaprojektować docelowe rozwiązanie, wiec implicite zaciagamy dług techniczny. Lepsze to niż overengineering
    (...)

Na koniec zaryzykuję stwierdzenie, że jeśli kod jest mega wypieszczony, odbija się to negatywnie na performance większego kawałka. Przykładem mogą być przeciągające się w nieskończoność CR, bo team reviewujący jest „strażnikiem jakości”. Jakość nie jest binarna, trzeba chodzić na kompromisy.

0

Byłem świadkiem tego jak powstawała mała aplikacja, dość prosta w samych założeniach przez całe 4 miesiące. Pisała to jedna osoba, która miała wywalone na jakieś dzielenie odpowiedzialności a podstawowy zakres dobrych praktyk i testów znała chyba tylko ze słyszenia.
Kiedy aplikacja poszła do testów to sam autor nie był w stanie ogarnąć tego co się tam dzieje.
Połowa rzeczy nie działała, debugowanie było wyjątkowo ciężkie.

Oczywiście, wina całego zespołu - ale to był swojego rodzaju eksperyment.

Tak, czasem (a nawet często) trzeba iść na kompromisy. Nie ma kodu idealnego i trzeba wypracować jakieś akceptowalne standardy.
Tyle że bez przesady. W tym przypadku po 4 miesiącach padła decyzja o przepisaniu tego od zera. A co dopiero gdy przychodzi do pisania softu który rozwija się latami...

1

Po co refaktoryzować? Nie można od razu napisać dobrze? Czy słaby kod to zawsze zły kod?

Pracowałem z kilkoma osobami, co do których mam prawie pewność, że celowo piszą brzydki kod, żeby inni nie rozumieli tego kodu. Kod powinien odwzorowywać biznes, którego problem rozwiązujemy. Czytasz kod co najmniej 10 razy częściej niż go piszesz więc poświęć chwilę i nazwij zmienną tak, żeby ona była zrozumiała dla czytelnika. Ciężko mi policzyć ile błędów spotkałem lub uniknąłem dzięki przypominaniu ludziom, że nie są sami w projekcie i żeby celowo nie komplikowali kodu. Jeżeli kod wygląda na skomplikowany to znaczy, że jest po prostu źle napisany i prawdopodobnie też źle działa.

Bo jak niby ma działać dobrze kod, którego nie da się otestować bo ktoś tworzy klasę Bóg z milionem zależności. Dobra klasa to taka gdzie mogę sobie podmienić zależności i ją otestować bez stawiania miliona frameworków. I to samo tyczy się całych modułów. Jeżeli kontrakt między serwisami jest zrozumiały to łatwo jest te serwisy otestować. Jeżeli jest niezrozumiały to może biznes nie potrzebuje takiego produktu skoro nie da się łatwo wytłumaczyć jego potrzeby.

1

Celowe działanie jest jak najbardziej możliwe - przy skomplikowanym oprogramowaniu można sobie zapewnić "dożywocie" i dostatek ;)

1

Byłem świadkiem tego jak powstawała mała aplikacja, dość prosta w samych założeniach przez całe 4 miesiące. (...)
Kiedy aplikacja poszła do testów

Czyli klasyczny waterfall - najpierw piszemy całą aplikację, a potem "idzie do testów". No to jest właśnie przykład na to, czemu waterfall jest dość ryzykowny.

Tyle że bez przesady. W tym przypadku po 4 miesiącach padła decyzja o przepisaniu tego od zera. A co dopiero gdy przychodzi do pisania softu który rozwija się latami...

Czyli jednak skręcenie z waterfalla w model zwinny, gdzie są kolejne iteracje. I jaki był tego efekt? Przepisali to dobrze? Czy programista, który pisał pierwszą wersję, uczestniczył w pisaniu kolejnej?

3
twoj_stary_pijany napisał(a):

Pracowałem z kilkoma osobami, co do których mam prawie pewność, że celowo piszą brzydki kod, żeby inni nie rozumieli tego kodu.

var napisał(a):

Celowe działanie jest jak najbardziej możliwe - przy skomplikowanym oprogramowaniu można sobie zapewnić "dożywocie" i dostatek ;)

Takie sytuacje występują najczęściej przy zamówieniach publicznych. Osobny przetarg na utrzymanie systemu jeszcze bardziej zwiększa prawdopodobieństwo tego procederu. Na szczęście jest to miecz obosieczny.

1

@LukeJL: nie do końca - wstępne testy robił autor do spółki z osobą z którą się integrował. Oczywiście sam happy path, jak coś nie działało to doprawiał kod curry i jazda dalej. Po 3 miesiącach poszło do QA dlatego, że w tym przypadku ciężko było testować ten kawałek systemu w tak ograniczonym zakresie. Nie było to zbyt mądre podejście no ale też temat nie do końca dotyczy samego podejścia do zarządzania.

Nie zostało to przepisane wcale. Ze względu na koronawirusa firma prawie upadła, pozbyła się prawie całego zespołu i nie było jak tego przepisywać. Jakoś działa, błędy zostały połatane dodatkowym spaghetti i sam projekt już nie jest rozwijany. Nie mniej jednak jeśli ktoś wpadnie na pomysł pracy z tym to świeć panie nad jego duszą

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0