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

0

Naszła mnie taka refleksja gdy przeglądam swój dobry (bu bu) słaby kod którego nie skończyłem.
Zrobiłem prototyp aby jakoś działało. Zostawiłem. Brak dokumentacji. Brak testów.

Naszło mnie takie przemyślenie
Skoro kod działa i na siebie zarabia to jeżeli nie ma testów, nie jest super czysty tylko był zrobiony na szybko aby jakoś działało to może testy, wzorce projektowe itd. których jestem takim zwolennikiem nie są takie super? Czy nie doprowadzanie do momentu gdy mamy tz. big ball of mud jest faktycznie takie ważne?

Oczywiście coś co mi się podoba i gadanie managerów:
ten projekt się przepisze, teraz to tylko szybko załatamy
Tylko że nigdy się tego nie przepisze bo nigdy nie będzie na to pieniędzy

Po co refaktoryzować jak można od razu pisać dobry kod?

27

Taki autentyk - kiedyś (daaaawno temu), w pierwszym januszsofcie jakim pracowałem, nie radziliśmy sobie z zarządzaniem błędami.
Zgłoszenia od testerów i klientów szły telefonicznie, mailem i na gębę - nie dało się w tym połapać, czasem naprawa jakiegoś błędu konfliktowała z innym zgłoszeniem (bo specyfikacja też była przekazywana ustnie, pokątnymi mailami z excelami w środku i wymyślana na poczekaniu).
Ogólnie, profesjonalizm pełną gębą.
Poszedłem do menadżera projektu - wytłumaczyłem na czym polega problem, dlaczego ciągle zapominamy o naprawach bugów i zaproponowałem, żeby wprowadzić Bugzillę (to było tak dawno temu). (Dla współczesnych - Bugzilla to taka jira, youtrack czy coś tam dla ogarniania zgłoszeń - można tym straszyć dzieci).

Na pytanie menadżera: "ile mi to instalowanie i wprowadzanie Bugzilli zajmie" odpowiedziałem, że 4 godziny...
Menadżer prawie zapowietrzył się z wściekłości, 4 godziny to czas, w którym w januszsofcie, zgodnie z typowym planem dnia, miałem napisać CMS, wdrożyć system intranetowy u klienta i jeszcze klepnąć stronę wizytówke dla dwóch innych.

Zamiast tego wydał zarządzenie:

  • Od teraz zakaz robienia błedów - pod groźbą kary finansowej

No i już nigdy więcej błędów nie było.
Elegancko.

2

Ach Jarek i jego opowieści których tak chętnie słucham. Już wiem czym jest problem dużego biustu.

No i już nigdy więcej błędów nie było.

My mamy dobrych programistów.
Po co pisać testy przecież nasi programiści piszą dobry kod.

2
Marcin Marcin napisał(a):

Po co refaktoryzować jak można od razu pisać dobry kod?

No ja też jestem za. Niestety masa ludzi uważa, że najpierw trzeba napisać spaghetti, potem dodać wzorce projektowe, a na końcu testy, czyli zasadniczo zupełnie odwrotnie niż należy.

8
Marcin Marcin napisał(a):

Skoro kod działa i na siebie zarabia to jeżeli nie ma testów, nie jest super czysty tylko był zrobiony na szybko aby jakoś działało to może testy, wzorce projektowe itd. których jestem takim zwolennikiem nie są takie super? Czy nie doprowadzanie do momentu gdy mamy tz. big ball of mud jest faktycznie takie ważne?

Chyba każdy inżynier w pewnym momencie uświadamia sobie, że jaranie się czystym kodem i innymi technicznymi rzeczami nie ma takiego znaczenia, jak zarabianie kasy przez produkt. Wzorce, dobre praktyki, konferencyjne gadki i reszta mają pomóc w rozwiązywaniu problemów biznesowych, a nie w pisaniu czystego kodu jako sztuka dla sztuki.

Tylko że nigdy się tego nie przepisze bo nigdy nie będzie na to pieniędzy

Kasa się znajdzie, jeżeli pokażesz wyliczenia, że przepisanie przyniesie zysk. Bo po co płacić masę kasy, jeżeli potem to się nie zwróci?

Po co refaktoryzować jak można od razu pisać dobry kod?

Pisanie dobrego kodu jest najprostszą częścią inżynierii oprogramowania. Trudne jest ustalanie, które problemy rozwiązywać i w jaki sposób. Złożone projekty są kijowe niekoniecznie dlatego, że zostały napisane syfiasto, często jest to połączenie wielu czynników, jak bardzo krótki termin na wdrożenie (czyli na produkcję leci prototyp), architektura wspierająca rozwiązania, które ostatecznie nie są potrzebne (i nikt ich nie używa), rotacje w projekcie (bo każdy ma inną wizję czystości kodu, więc jak pierwotny autor odchodzi, to następny chce przerabiać na swoją modłę i robi niespójnie), zmiana wymagań na każdym kroku, haki wynikające z niedojrzałości platformy czy tam bibliotek i wiele innych rzeczy. Programowanie jest proste, inżyniera oprogramowania jest trudna, a najtrudniejsze (i najbardziej wartościowe) jest dostarczenie rozwiązania, które działa i spełnia potrzebę biznesową, ale w ogóle nie wymaga programowania.

0

Chyba każdy inżynier w pewnym momencie uświadamia sobie, że jaranie się czystym kodem i innymi technicznymi rzeczami nie ma takiego znaczenia, jak zarabianie kasy przez produkt. Wzorce, dobre praktyki, konferencyjne gadki i reszta mają pomóc w rozwiązywaniu problemów biznesowych, a nie w pisaniu czystego kodu jako sztuka dla sztuki.

Celem pracy jest zysk

9
Marcin Marcin napisał(a):

Po co refaktoryzować jak można od razu pisać dobry kod?

Pytanie trochę w stylu: "Po co chybiać strzelając, skoro można zawszę trafiać w 10?"

4

wzorce projektowe itd.

Wzorce projektowe to zwykle po prostu obejścia ograniczeń języka. Czyli im więcej trzeba wzorców projektowych napakować, tym gorszy język (a przynajmniej mniej ekspresywny), bo zamiast pisać to, co chcesz, żeby komputer zrobił, to musisz pisać dużo kodu, który nic nie robi, a jest "wzorcem".

Po co refaktoryzować jak można od razu pisać dobry kod?

Jak umiesz, to pisz.

Skoro kod działa i na siebie zarabia to jeżeli nie ma testów, nie jest super czysty tylko był zrobiony na szybko aby jakoś działało to może testy, wzorce projektowe itd. których jestem takim zwolennikiem nie są takie super?

Jak coś jest małego, co nie wiadomo jak działa, ale działa, coś, czego nigdy już nie ruszysz - to niech sobie będzie nawet ze słabym kodem. Co innego, jak będziesz musiał to utrzymywać.

Czy nie doprowadzanie do momentu gdy mamy tz. big ball of mud jest faktycznie takie ważne?

Big ball of mud czy kod spaghetti spowalnia programistów. Bo trzeba bardziej myśleć nad tym, co jakiś kawałek kodu robi. Też ciężko dodać nowe ficzery, bo się okazuje, że dana architektura nie pozwala na łatwe zmiany itp. Wrzucając śmieciowy kod do projektu zaciąga się dług techniczny, który kiedyś trzeba będzie spłacić. Nawet jak nic nie zrobisz z tym kodem, to i tak potem będzie cię spowalniał, więc i tak trzeba będzie spłacić ten dług, czyli albo zrobić od czasu do czasu refaktoring albo przyjąć na klatę postępujący spadek produktywności.

3
LukeJL napisał(a):

wzorce projektowe itd.

Wzorce projektowe to zwykle po prostu obejścia ograniczeń języka. Czyli im więcej trzeba wzorców projektowych napakować, tym gorszy język (a przynajmniej mniej ekspresywny), bo zamiast pisać to, co chcesz, żeby komputer zrobił, to musisz pisać dużo kodu, który nic nie robi, a jest "wzorcem".

Nie za bardzo.
Wzorce nie (zawsze/rzadko) zastępują słabości języka, ale są na innym poziomie abstrakcji. Olbrzymia większośc wzorców jest cięciem w zakresie odpowiedzialności (separacją) i język niewiele ma do tego.

Oczywiście, stosując wzorce w C tzreba się opisac więcej linii itd niż w języku wyższego poziomu, ale to inna opowieść.

3

Oczywiście, stosując wzorce w C tzreba się opisac więcej linii itd niż w języku wyższego poziomu, ale to inna opowieść.

Zależy jak postrzegamy wzorzec. Jeśli uznamy, że to pewna koncepcja programistyczna, rodzaj abstrakcji, to nawet jeśli jesteśmy w stanie zaimplementować w kilku linijkach dany wzorzec (albo czasem wręcz w jednej), wtedy faktycznie możemy uznać, że język nie ma nic do tego. Abstrakcja jest abstrakcją, niezależnie czy się namęczyliśmy przy jej implementacji, czy nie.

Ale jeśli uznamy wzorzec tak, jak często się to przedstawia, czyli coś, co wymaga naprodukowania dużej ilości kodu i stworzenia iluś klas, żeby zaimplementować banalne zachowanie, to może to wskazywać na to, że piszemy w języku małoekspresyjnym, że do implementacji prostych zachowań trzeba się nakodzić. A wtedy wzorce jawią się jako coś kosztownego w implementacji, co aż należy podkreślić, że się ich używa (mimo, że w innym języku implementacja danego wzorca to będzie tylko kilka linijek zamiast kilkudziesięciu).

Może też ludzie gdzie indziej kładą nacisk, niż trzeba. Zamiast stosować ogólne zasady typu SOLID, to szukają gotowych recept typu "magiczne wzorce, które poprawią jakość kodu". A potem wychodzi overengineering.

2

Prowizorka jest najtrwalszą konstrukcją znaną człowiekowi.

Nie trzeba później prowizorki często zmieniać, dostosowywać, nadążać za nowymi wymaganiami otoczenia, to prowizorka, patrząc biznesowo, jest dobrym rozwiązaniem. Optymalnym pod względem kosztów, czasu racy, zaangażowania i wydatków na ewentualne przyszłe (niewielkie) poprawki.

4
LukeJL napisał(a):

Oczywiście, stosując wzorce w C tzreba się opisac więcej linii itd niż w języku wyższego poziomu, ale to inna opowieść.

Ale jeśli uznamy wzorzec tak, jak często się to przedstawia, czyli coś, co wymaga naprodukowania dużej ilości kodu i stworzenia iluś klas, żeby zaimplementować banalne zachowanie, to może to wskazywać na to, że piszemy w języku małoekspresyjnym, że do implementacji prostych zachowań trzeba się nakodzić. A wtedy wzorce jawią się jako coś kosztownego w implementacji, co aż należy podkreślić, że się ich używa (mimo, że w innym języku implementacja danego wzorca to będzie tylko kilka linijek zamiast kilkudziesięciu).

Może też ludzie gdzie indziej kładą nacisk, niż trzeba. Zamiast stosować ogólne zasady typu SOLID, to szukają gotowych recept typu "magiczne wzorce, które poprawią jakość kodu". A potem wychodzi overengineering.

Psychologicznie MOŻE być jak piszesz.
Wg mnie MOCNO się to łączy z "religią wzorcową", wtedy wzorce są narzucane (przez atmosferę w zespole), produkowane na ilość (pod CV) itd.

Ja ZAWSZE wracam do stwierdzenia, co to jest wzorzec: uznanie i nadanie nazwy na coś, co od dawna jest w branży,
NA PRZYKŁAD STOLARZE nazwali jeden ze sposobów połączenia desek "na pióro", i w ten sposób się szybko i skutecznie rozumieją.
Ale zarazem ci prości stolarze są (w odróżnieniu od programistów) nigdy nie użyją złącza "na pióro" gdy nie jest potrzebne / zbędne / głupie.
Żaden stolarz nie jest zmuszany do nauczenia się I UŻYWANIA wzorców, które ktoś inny wymyślił, aby napisać doktorat albo wydać książkę

3

IMO to trochę wina podejścia agilowego.
Robimy wymagania A i B towrzymy ładny kod i sprawdzający się w tamtych warunkach. Potem przychodzi wymagania C które strasznie miesza w A i B robi jakiś dziwny bypass itd. No ale okazuje się, że od strony użytkownika to tylko input i checkbox więc programisci estymuja jak dodanie inputu i checkboxa i troche zapasu i nie stracza czasu albo nie ma chęci u dewelopera zeby sie narobic i tamto przerobic. Bo co jeśli nie daj boże zrobi bład w starym kodzie. Potem mija troche czasu ludzie się zmieniają przychodzi wymaganie D i okazuje się, że już nie ma programistów którzy biznesowo rozumieja co się dzieje w kodzie i bojąc się, że coś zepsują dospawuja wymaganie D które pasuje jak pięść do oka w tamtym miejscu. Ba dum tss mamy gówniany kod.

2

@Afish: oczywiście, tyle że jaranie się czystym kodem pozwala na napisanie systemu który daje się utrzymać i rozwijać - to jest czysty zysk w przypadku kiedy firma pracuje przez kilka lat nad swoim produktem. Cel jest oczywiście jasny, ale jesteśmy nie tylko od tego żeby kodować jak zwierzęta a zrobić to w sposób nie urągający godności człowieka.

Wielokrotnie niestety spotykałem i wciąż spotykam się z sytuacją, kiedy takie pójście na skróty w przeszłości ma swoje konsekwencje w tym, że praca nad całkiem prostym zadaniem wymaga ogromnego nakładu czasu i pracy.
Jeśli w tym o czym piszesz zawarłeś również aspekty na pograniczu biznesu i technologii to się w pełni zgadzam, jeśli tylko biznesowe to nie.

2

Po co chirurg ma myć ręce przed operacją jak ma płacone za operację a nie za mycie rąk?
Jakość kodu jest ważna, przy czym należy zachować umiar. Ani zastanawianie się godzinamk nad nazwa jednej zmiennej ani konstruktor z 20 argumentami nie są sensowne. A Ty @Marcin Marcin pracowałeś kiedyś w utrzymaniu? Kojarzysz co to godziny SLA na przykład?

5

Czy nie doprowadzanie do momentu gdy mamy tz. big ball of mud jest faktycznie takie ważne?

Jeśli piszesz coś co można "porzucić" to pewnie nie. Ale dług techniczny rośnie z czasem. Jak dziś zrobić coś "na szybko" to jutro kolejny ficzer będzie zbudowany na tym i nagle poprawka stanie się bardzo kosztowna. Co gorsza kilka ficzerów później może okazać się, że zrobienie czegoś prostego wymaga strasznie dużo pracy.
Widziałem takie projekty w stylu pole minowe - żaden developer nie chciał dotykać kodu, bo dowolna zmiana powodowała kaskasowe błędy w różnych miejscach.

Po co refaktoryzować jak można od razu pisać dobry kod?

Problem nie jest w tym, że ludzie od nowosci piszą zły kod tylko kod się zmienia w czasie. Zmieniające się wymagania, nowe funkcje, poprawki innych błędów itd. Może napisałeś funkcje X i było ładnie, ale teraz trzeba zrobić funkcje Y i może to wymagać zrefaktorowania X.

2

To jest w ogóle ciekawe w kontekście tego kiedy do firmy przychodzi junior, który trafia na smutnych, zmęczonych albo niedouczonych "seniorów" których jedyną metryką "seniority" jest ilość dupogodzin - młody zamiast uczyć się tego jak robić żeby było dobrze i mieć w przyszłości mniej pracy łyka najlepsze smaczki od bardziej doświadczonych kolegów. Jedyne czego się uczy to jak zrobić żeby działało i się nie narobić. A co najważniejsze - nigdy nie myśleć w perspektywie dalszej niż kilka dni.

0
var napisał(a):

@Afish: oczywiście, tyle że jaranie się czystym kodem pozwala na napisanie systemu który daje się utrzymać i rozwijać - to jest czysty zysk w przypadku kiedy firma pracuje przez kilka lat nad swoim produktem. Cel jest oczywiście jasny, ale jesteśmy nie tylko od tego żeby kodować jak zwierzęta a zrobić to w sposób nie urągający godności człowieka.

Z mojego doświadczenia więcej problemów powstaje ze zmieniających się wymagań i budowania złych rzeczy, niż ze zrobienia ich niepoprawnie. Mówisz, że to jest „czysty zysk” i masz rację, ale zysk trzeba maksymalizować, a często bardziej opłaca się zrobić więcej badziewia, niż polerować miej dobrych rozwiązań.

3
LukeJL napisał(a):

Zależy jak postrzegamy wzorzec.

Tu nie ma żadnego "zależy". Wzorce mają definicję: general, reusable solution to a commonly occurring problem within a given context. Nie ma nic o liczbie linijek kodu, ani o tym, że się trzeba napracować.

Jeżeli komuś implementacja wzorców sprawia wysiłek; jeżeli zamiast wiedząc, że np. jakieś dane mają być przetwarzane za pomocą różnych algorytmów w zależności od parametru woli walnąć wielką metodę z drabinką ifów zamiast kilka małych klas w strategii, to jest po prostu niesprawnym programistą.

Schadoow napisał(a):

IMO to trochę wina podejścia agilowego.

Robimy wymagania A i B towrzymy ładny kod i sprawdzający się w tamtych warunkach. Potem przychodzi wymagania C które strasznie miesza w A i B robi jakiś dziwny bypass itd. No ale okazuje się, że od strony użytkownika to tylko input i checkbox więc programisci estymuja jak dodanie inputu i checkboxa i troche zapasu i nie stracza czasu albo nie ma chęci u dewelopera zeby sie narobic i tamto przerobic. Bo co jeśli nie daj boże zrobi bład w starym kodzie. Potem mija troche czasu ludzie się zmieniają przychodzi wymaganie D i okazuje się, że już nie ma programistów którzy biznesowo rozumieja co się dzieje w kodzie i bojąc się, że coś zepsują dospawuja wymaganie D które pasuje jak pięść do oka w tamtym miejscu. Ba dum tss mamy gówniany kod.

Wydaje mi się, że jest na to w miarę proste rozwiązanie - nowe wymaganie, to nowy kod. Jeśli starego nie ruszamy, to nie mamy go jak zepsuć.
Niestety ludzie preferują "reużywanie" kodu przez dodawanie ifologii, i wtedy właśnie powstają pola minowe.

2

Kod ma być zamknięty na zmiany i otwarty na rozszerzenia

6

@somekind:

Jeżeli komuś implementacja wzorców sprawia wysiłek; jeżeli zamiast wiedząc, że np. jakieś dane mają być przetwarzane za pomocą różnych algorytmów w zależności od parametru woli walnąć wielką metodę z drabinką ifów zamiast kilka małych klas w strategii, to jest po prostu niesprawnym programistą.

Idealny przykład jak braki w doświadczeniu i jezykach powodują brandzlowanie się wzorcami. Drabinka ifów nie jest alternatywą dla wzorca strategii.
Strategia to bardzo szczególny przypadek higher order function. Walenie jakichkolwiek klas, żeby zrobić coś co jest naturalnym rozwiązaniem w każdym współczesym języku (który dorobił się lambd) to troszkę patologia. W przypadku programowania fp w prawie każdej linijce kodu znajdzie się coś co na siłę można nazwać strategią, ale podkreślanie tego nie ma sensu. Tak, jak nie ma sensu fascynowanie się w każdym zdaniu, że piszemy prozą.

2
jarekr000000 napisał(a):

Tak, jak nie ma sensu fascynowanie się w każdym zdaniu, że piszemy prozą.

Uważam że podejście nie koduj pisz prozę ma jakiś sens

5

no właśnmie jest se wielka metoda to zamieniamy ja na ...małe kl;asy? a dlaczego nie na małe metody na początek?

Prawie nikt nie robi od razu wiekich klas i metod (no chyba że patrzymy do hinduskiego kodu). Klasa ma 8000 linii, a metoda 16 parametrów, ale to narastało zwykle latami.
Weź fiksnij to na szybko, tam jest taki wielki warunek, trzeba dorobić nowy case. No i mamy ten nieszczęsny warunek.

  • jak ma dwa case to ok.
  • Cztery - robi się trochę przykro.
  • Osiem - programiści zaczynają mówić, że trzeba by to zrefaktoryzować, bo nie mieści się na ekranie, ale managment nie rozumie czemu dodanie siódmego case'a było proste, a osmego już jest trudne.
  • Szesnaście case'ów w ifie - programiści zaczynają się zwalniać, bo poziom szamba jest taki że nie da się oddychać.

Przy którym poziomie szamba/case'ów w ifie należy zacząć sprzątać? Pewnie przy trzecim, a może nawet przy drugim. Jakby od razu było wiadomo że tam będzie 16 różnych algorytmów to by to lepiej zaprojektowano :(

3
jarekr000000 napisał(a):

Idealny przykład jak braki w doświadczeniu i jezykach powodują brandzlowanie się wzorcami.

To nie było brandzlowanie, po prostu podałem przykład częstej patologii o banalnym rozwiązaniu.

Drabinka ifów nie jest alternatywą dla wzorca strategii.

Oczywiście, że nie. Ale niektórzy tak to piszą, bo się nie brandzlują. Albo może uważają, że programowanie funkcyjne polega na długich funkcjach, nie wiem. :)

Strategia to bardzo szczególny przypadek higher order function. Walenie jakichkolwiek klas, żeby zrobić coś co jest naturalnym rozwiązaniem w każdym współczesym języku (który dorobił się lambd) to troszkę patologia.

Dobrze, i gdzie umieścisz 20 lambd po 30 linijek kodu każda?

W krótszych przypadkach można klas nie robić, ale nadal - przyczepiłeś się nie do tego, co trzeba. No chyba, że chcesz tu i teraz tutaj przyznać, ze pisanie najeżonej ifami metody na 600 linii kodu jest w porządku?
Bo jeśli krytykujesz krytykowanie ifologii i przerośniętych metod, to tak jakbyś to popierał.

3

@somekind:

Dobrze, i gdzie umieścisz 20 lambd po 30 linijek kodu każda?

W przypdadku dłuższego kodu zamiast lambd można użyć funkcji, a te funkcje można rozbić na mniejsze.
A wszystko to można trzymac w plikach - równiez w wielu małych. Można też w klasach jak mamy jakiś ułomny język co nie umie w funkcje.

1

@jarekr000000: oczywiście zgodzę się że niektóre języki lepiej wspierają dobre nawyki ale jak dla mnie to czepiasz się teraz szczegółów. Chodzi o to że jak masz eksport do pliku to nie trzeba za kazdym razem robić ifa, tylko możesz mieć funkcje albo klasy które spełniają odpowiedni kontrakt i mieć łatwe rozszerzenie kodu o kolejne formaty. Czy to zrobisz lambda czy nie - idea jest podobna.

1
Marcin Marcin napisał(a):

Kod ma być zamknięty na zmiany i otwarty na rozszerzenia

A co to oznacza? Bo całkiem niedawno był tu taki poradnik wg. którego oznacza to, że każda publiczna metoda powinna być wirtualna, żeby dało się ja nadpisać ;)

7
jarekr000000 napisał(a):

W przypdadku dłuższego kodu zamiast lambd można użyć funkcji, a te funkcje można rozbić na mniejsze.
A wszystko to można trzymac w plikach - równiez w wielu małych. Można też w klasach jak mamy jakiś ułomny język co nie umie w funkcje.

No, więc chyba można stwierdzić, że w różnych językach wzorce mogą wyglądać różnie.
A to że w językach obiektowych wzorce używają obiektów, to nie jest efekt mojego brandzlowania i braku doświadczenia, tylko specyfiki tych języków.

Saalin napisał(a):

A co to oznacza? Bo całkiem niedawno był tu taki poradnik wg. którego oznacza to, że każda publiczna metoda powinna być wirtualna, żeby dało się ja nadpisać ;)

No jak dla mnie, to wzorce typu strategia, metoda szablonowa, łańcuch odpowiedzialności są właśnie rozwiązaniami OCP, bo dla nowego przypadku nie trzeba ruszać starego kodu, tylko stworzyć nowy.

1
KamilAdam napisał(a):

Jakby od razu było wiadomo że tam będzie 16 różnych algorytmów to by to lepiej zaprojektowano :(

Gdyby każde wpisanie 'git init' było analizowane, z pomocą wróżki, czy urośnie z tego coś wielkiego to może inaczej by się od początku szkicowało, sorry: świadomie pisało.

2

@somekind:

A to że w językach obiektowych wzorce używają obiektów, to nie jest efekt mojego brandzlowania i braku doświadczenia, tylko specyfiki tych języków.

Patrząc z punktu widzenia Java i C# to te języki nie są już od dawna czysto obiektowe. 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. Zresztą C# ma też zresztą goto i unsafe i też nie trzeba tego wcale używać i robić z C# Basica.
(btw. metoda szablonowa - też higher order function (jak większość wzorców behavioralnych), chain of responsibility - function composition).

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