Jak nie robić spaghetti

0

Witam,

Mam problem z kodem spaghetti. Niby już znam język programowania na tyle żeby coś tam małego naszkrobać w konsoli, ale zawsze wychodzi spaghetti. Pewnie dlatego że piszę od razu z głowy. I pytanie, jak nauczyć się dobrze pisać programy orientowane obiektowo? Czy to już etap na wzorce projektowe? Czy dobrze jeszcze jakąś książkę przerobić? Jak w ogóle wygląda u Was schemat pisanie prostej aplikacji, zawierającej kilka klas, ale tak by nie powstało spaghetti.
Dzięki za pomoc,
Pozdrawiam,

6

Jak coś napiszesz, to daj do oceny, opinii na forum, to Ci doradzą, pouczą, poprawią.

4
hansikkk napisał(a):

jak nauczyć się dobrze pisać programy orientowane obiektowo?

  1. Pisząc beznadziejne spaghetti
  2. Pisząc równie beznadziejny przekombinowany i najeżony wzorcami kod

I teraz najtrudniejsze

  1. Nauczyć się pośrodkowac i pisać kod dobrze zaprojektowany, ale jednak prosty, naiwny miejscami wręcz (wyciągając wnioski z dwóch poprzednich podejść)

Tylko, ze dojście do 3 to praca na lata, bo musisz nauczyc się pogardy zarówno do spaghetti jak i do wciskania wzorców gdzie popadnie. Wiele osob dochodzi do punktu 2 i tam sie zatrzymuje

Czyli spaghetti jest okej jako etap, problem w tym, ze zwykle ludzie uciekają ze spaghetti w overengineering (który tez jest ok jako ETAP, niestety wiele osób uważa go za ostateczny cel)

0

overengineering
Chodzi o to by na siłę nie udowadniać jakie to zaawansowane sztuczki znam, a iść czasem w prostotę kodu, a zarazem większą czytelność dla ogółu.

5

Musisz nauczyć się dzielić większy problem na pod problemy i zamykać je w klasy, które ukrywają tę złożoność. Gdy cały kod jest w jednej funkcji i wszystko wie o wszystkim to wiadomo, że wychodzi spagetti. A jak ładnie to podzielisz i wrzucisz w hermetyczne pudełka to o wiele łatwiej wtedy taki kod zrozumieć i rozwijać.

5

A piszesz testy? Jeśli zaczniesz (a najlepiej jeśli zaczniesz od pisania testów) to ciężej Ci będzie zrobić spaghetti.

0
lookacode1 napisał(a):

Musisz nauczyć się dzielić większy problem na pod problemy i zamykać je w klasy, które ukrywają tę złożoność. Gdy cały kod jest w jednej funkcji i wszystko wie o wszystkim to wiadomo, że wychodzi spagetti. A jak ładnie to podzielisz i wrzucisz w hermetyczne pudełka to o wiele łatwiej wtedy taki kod zrozumieć i rozwijać.

W teorii to wiem że tak się robi, masz jakieś materiały z których można się nauczyć?

Saalin napisał(a):

A piszesz testy? Jeśli zaczniesz (a najlepiej jeśli zaczniesz od pisania testów) to ciężej Ci będzie zrobić spaghetti.

Nie, nie piszę. Jakieś materiały do przerobienia?

0

Jak wyżej (@Saalin ), z czasem zaczniesz pisać kod pod testy, a to już krok w dobrym kierunku.

0
hansikkk napisał(a):

Nie, nie piszę. Jakieś materiały do przerobienia?

Nie napisałeś nic o technologii, więc najpierw dokumentacja (tutorial) do jakiejś polecanej biblioteki do testowania w danym języku, przykłady (jak robić asercje) i w sumie tyle na początek, później praktyka.

1

Pobaw się TDD, w ten sposób ciężko doprowadzić do spaghetti kodu.

A jeśli chodzi o zwykłe spaghetti to nigdy nie łam makaronu na pół; włóż go do garnka, poczekaj chwilę aż zmięknie i lekko przemieszaj.

1
hansikkk napisał(a):

Mam problem z kodem spaghetti. Niby już znam język programowania na tyle żeby coś tam małego naszkrobać w konsoli, ale zawsze wychodzi spaghetti.

Skoro tak oceniasz swoją znajomość języka programowania, to mi wydaje się, że spaghetti powinno być nawet trochę oczekiwane. W miarę nauki powinno zniknąć. Ale mogę źle interpretować Twoje słowa.

Czy to już etap na wzorce projektowe?

Hm… Pomijając na chwilę to, co @LukeJL napisał, co rozumiesz przez "etap na wzorce projektowe"?

Jeśli chodzi o pisanie kodu, to już jakiś czas tego nie robiłem. Niemniej może poradzę coś ogólnie…

Jak pisać czytelny kod? Pisząc, miej w głowie, że kod piszesz dla odbiorcy.

Ten, kto ten kod odbiera, ma go zrozumieć. Chodzi przecież o komunikację między Tobą a tym kimś… lub komputerem. I tak: zawsze odbiorcą jesteś Ty (już podczas pisania), prawie zawsze komputer, czasem drugi programista. To moja prywatna klasyfikacja, mogę się mylić. Jestem świadom, że jest tu pewien kontrast z cytatem p. Dolanda Kuntha (https://www.goodreads.com/quotes/6086714-programs-are-meant-to-be-read-by-humans-and-only).

Co oznacza kod czytelny dla Ciebie samego? Nie polegaj tylko na pamięci. Niestandardowych rozwiązań unikaj, a jeśli nie możesz, to notuj je gdzieś, na przykład w komentarzach. Wszelkie standardy bardzo pomagają. Mówią: "y" zawsze w tym kontekście oznacza to i to, "z" to i to, a "y+z" to i to. Nie trzeba się zastanawiać i szukać w głowie, "co mogłem mieć na myśli miesiąc temu, jak to pisałem". Szukaj najbardziej intuicyjnych rozwiązań dla Ciebie samego w dłuższej perspektywie (tj. "łatwo przypominalnych" i "łatwo rozumialnych"). Myślę, że w miarę kodowania będziesz zerkać do standardu coraz mniej, przynajmniej część rzeczy z niego pewnie będziesz mieć w pamięci. Czy będziesz w stanie zrozumieć swoje intencje i decyzje w tym kodzie za rok? To może trudne do przewidzenia, może pomoże zastanowienie się, czy jesteś w stanie teraz zrozumieć swoje decyzje, jak czytasz swój kod sprzed roku (niekoniecznie w tym nowym języku).

Co oznacza kod czytelny dla komputera? Wiedz, co dzieje się z kodem między jego pisaniem a wdrożeniem. Czy jest kompilowany? Interpretowany? Jest jakiś bytecode? Jaki program będzie ostatecznie wykonywał Twój kod? Czy to wszystko wpływa jakoś na wydajność kodu? Czy kompilator połowę Twojego kodu usuwa, a drugą połowę zamienia na "swój"? Generalnie chodzi mi tutaj o to, że w idealnym przypadku komputer zinterpretuje czy skompiluje Twój kod dokładnie tak, jak myślisz, że to zrobi. Tutaj znów napiszę: unikaj niestandardowych rozwiązań i haków. Unikaj opcji kompilatora, których przeznaczenie będziesz znał tylko Ty albo które przydają się w jednym pliku na sto. Stosuj się do standardów, najlepiej tych najszerzej znanych. Znaj oficjalną dokumentację. Czy wspominałem już o unikaniu niestandardowych rozwiązań (nawet tych, które są opisane w oficjalnej dokumentacji)?

Co oznacza kod czytelny dla drugiego programisty? …Tak, standardy i konwencje po raz trzeci, między innymi te związane z formatowaniem kodu. Zauważ, że w wypadku komunikacji człowiek-człowiek standardy nie zawsze muszą być formalnie określone: mam na myśli intuicję. Druga osoba może mieć całkiem inną intuicję niż Ty. Przykładowo nazwa klasy "ABC" może dla niej znaczyć coś innego niż dla Ciebie. Nie chodzi mi o to, żeby polegać lub nie na intuicji, po prostu pamiętaj, że ona tam gdzieś zawsze jest. Inne ważne pojęcia tutaj, moim zdaniem, to kontekst oraz abstrakcje. Kontekst najlepiej by był oczywisty. Przykładowo druga osoba nie powinna musieć się zastanawiać, czy identyfikator "x" w danym pliku ma jakiś związek z identyfikatorem "_x" w innym pliku, ich znaczenie powinno jasno wynikać ze standardów, konwencji, nazw plików, klas i tym podobnych. Poziom abstrakcji staraj się wypośrodkować. Za dużo abstrakcji to wspomniane przez Ciebie overengineering, za mało to właśnie spaghetti (przynajmniej ja bym tak to sklasyfikował). Po co tworzyć dany interfejs, jeśli żadna z przewidywanych klas nie będzie go implementować (overengineering)? Z drugiej strony być może w danym przypadku nie ma sensu robić copy-paste i potem modyfikować tylko niektóre miejsca we wklejonym kodzie (spaghetti). To działanie podatne na przeoczenia, może lepiej wydzielić nową metodę, albo nawet całą klasę.

Te trzy punkty nie są koniecznie rozłączne. Być może porady z jednego da się zastosować w pozostałych. Jak masz pytania, to pisz, może o czymś zapomniałem, a może źle napisałem.


PS W sumie to nie wiem, co masz na myśli przez ową "konsolę".

0

Znajdź jakieś popularne programy które mają udostępnione źródło w necie ( napisane w języku Twojego wyboru ).. Poprzeglądaj.

1

IMHO najlepsze jest review robione przez kogos kto pod wzgledem umiejetnosci jest poziom wyzej (nie mylic z nazwa stanowiska). Chociaz ta metoda bywa nieprzyjemna, zwlaszcza jak sie w nowy temat/jezyk wchodzi.

0

PS W sumie to nie wiem, co masz na myśli przez ową "konsolę".

Bez trybu okienkowego. Mam 5 klas napisanych i strasznie to wychodzi...
Zresztą możecie zobaczyć jaki mi tam bigos wyszedł.
W książce Gręboasz Opus Magnum w rozdziale Projektowanie programów orientowanych obiektowo jest opisane jak niby podejść do tematu. Chciałbym może więcej podobnych materiałów.
Wydaje mi się. że zanim zacznę pisać kod, muszę to dobrze zaplanować. Dlatego poczytałbym jakieś konkretne książki, jak w ogóle do tematu przysiąść.
kod.zip

0
ksh napisał(a):

Znajdź jakieś popularne programy które mają udostępnione źródło w necie ( napisane w języku Twojego wyboru ).. Poprzeglądaj.

Skąd brać te programy? Np. z https://sourceforge.net/ ?

3

pisać w tym języku w którym piszesz, nie brać zasad z javy do C++ a zasad z C do R

1

klasyki:

  • Fowler refaktoryzacja kodu link

    • Martin clean code link

    Kurde że ktos w tych czasach bierze grębosza i opus magnum jak jest tyle książek(dyskusje o tym były już).

4
hansikkk napisał(a):

Bez trybu okienkowego. Mam 5 klas napisanych i strasznie to wychodzi...

  1. jak nie chcesz mieć spaghetti, to nie pisz kodu po polsku. Bo inaczej będziesz miał potworki typu setStan

  2. po co klasa mają metodę setID? Wygląda jak antypattern. id nie powinno się w ogóle zmieniać, bo jeśli się zmienia, to przestaje pełnić swoją funkcję identyfikatora. Tj. to powinno wyglądać tak, że tworzysz w pamięci obiekt z danym ID i on ma już to ID do końca.

  3. Ogólnie settery/gettery są strasznie nadużywane i zwykle niepotrzebne. Sam ich używasz w jednym zaledwie miejscu w klasie DB. Jak rozumiem - masz jedną zmienną konto wielokrotnego użytku, do której ładujesz dane z kolejnych rekordów w bazie. Można i tak, ale w takim razie po co w ogóle robić jakieś settery? Robisz zwykłą strukturę i zapisujesz do niej dane. Jak chcesz użyć tej samej struktury do zapisywania kilku rekordów, to po prostu podmieniasz pola i tyle.

  4. bardziej elegancko byłoby tworzyć nową strukturę/obiekt do każdego użytkownika, a nie używać tej samej (chyba, że robisz jakąś optymalizację wydajności, ale w twoim wypadku to prędzej sam kontakt z bazą danych będzie uderzał w wydajność, a nie to, że sobie utworzysz kilka obiektów w pamięci)

  5. literówka w nazwie metody: queryExcec

Dlatego poczytałbym jakieś konkretne książki,

Książki mogą też zaszkodzić, jeżeli będziesz stosować się bezmyślnie do wyczytanych rad. Fajnie jest brać inspiracje z wzorców czy książek, ale zrozumieć też "dlaczego" pewne porady są w książkach (i zrozumieć, że kontekst autora książki może być trochę inny) i po każdej poradzie z książki warto przeczytać jakąś odtrutkę (np. artykuł w necie krytykujący dane podejście z książki) albo samemu dokonać krytycznej refleksji, żeby faktycznie zrozumieć, a nie naśladować.

Np. pomysłu, żeby robić gettery/settery do wszystkiego też pewnie sam nie wymyśliłeś, tylko wyczytałeś gdzieś. To teraz wypadałoby poczytać coś, co krytykuje settery/gettery (ogólnie to zaciemnia proceduralny kod jak w twoim przypadku, oraz ułatwia łamanie zasad OOP w przypadku kodu OOP (którego u ciebie nie widzę w ogóle))

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