Teoria a praktyka

3

@Riddle bardzo często przedstawiał piękne teorie jak może wyglądać inżynieria oprogramowania, jednak jego działania na forum pokazują, że jego podejście może zawierać usterki jak np. wprowadzanie bugów itd. Jakie znacie przykłady teorii, które w praktyce okazują się nie właściwe lub nie tak dobre jak to opisuje teoria?

Moim zdaniem np. dziedziczenie w OOP, jest często nadużywane i w praktyce lepiej z niego nie korzystać wcale niż nadużywać. Kilka poziomów dziedziczenia (lub dziedziczenie jednocześnie z kilku ale nie wiem czy w każdym języku się tak da [problem diamentu(?)]) wprowadza to wiele zamieszania i bardzo ciężko się połapać w kodzie, ciężko debugować itd.

1

Książki książkami, życie życiem.
Ja zdania jestem, że dobrze wiedzieć, czyli mieć zaplecze teoretyczne i dobrze robić, żeby tą teorie mieć gdzie wykorzystać.

Jednak w projektach bywa różnie i czasami jest tak, że każde rozwiązanie jest lepsze niż to perfekcyjne teoretycznie.

Balans jest ważny, ale jak Ci biznes z dnia na dzień wymyśli kosmos na kółkach w kształcie owalnego trójkąta rozwartokatnego, który ma być niebinarny to trzeba zrobić tak, żeby działało i lykneli że to to.

Zależy czym się zajmujesz, nie wiem też jak wyglądają projekty niskopoziomowe, czy też takie spaghetti czasami jak w web devie, ale generalnie to są 3 typy:

  • thinkers,
  • doers (lepiej),
  • thinking-doers (najlepiej i najmniej chodzących przypadków)
1
anonimowy napisał(a):

Moim zdaniem np. dziedziczenie w OOP, jest często nadużywane i w praktyce lepiej z niego nie korzystać wcale niż nadużywać.

Moim zdaniem usecasem do dziedziczenia może być to, jeśli klasa bazowa zawiera pewne funkcje, ale jest niepełna. Być może nie wszystkie funkcje są zaimplementowane, być może sam musisz zaimplementować funkcje w klasie, żeby to miało sens (ponieważ reszta kodu będzie się opierać na polimorfizmie i będzie wywoływać metody twojego obiektu).

Czyli jakby
klasa abstrakcyjna -> klasa potomna
Albo
interfejs z niektórymi domyślnymi metodami - implementacja interfejsu (np. w Rust tak można zrobić. Tylko tam to się trait nazywa)

Jednak to, że może być usecasem, nie znaczy, że trzeba tak robić.

Zastanawiam się, czy nie lepiej wtedy oddzielić wspólny kod gdzieś indziej, żeby mieć oddzielnie helpery (używane przez każdą z konkretnych implementacji) oraz oddzielnie interfejs (który będzie implementowany przez każdą konkretną implementację).

1

Dużo tego jest. Często teorie są z d**y, bo sukces danej teorii to głównie marketing a nie wieloletnie badania, które w jakiś usystematyzowany sposób pokazują, że faktycznie może być coś na rzeczy.

Najczęściej IMO wynika to z tego, że dana teoria zakłada pewien szczególny przypadek jako ogólny, gdzie w praktyce wychodzi na to, że tak nie jest. Przykłady:

  • piramida testów jest z d**y, bo zakłada pewien szczególny przypadek tj. długo rozwijana aplikacja z dużą ilością logiki biznesowej. W praktyce dużo częściej klepiemy CRUDa i testy wysokopoziomowe to coś co powinno stanowić większość
  • abstrakcja everywhere. Brak brania pod uwagę faktu, że błędna abstrakcja jest szkodliwa i utrudnia znalezienie tej prawidłowej
  • frameworki robiące konfigurację pod spodem są super. Fajnie to wygląda w tutorialach, na żywo rozwiązujesz głupi problem 2 dni zamiast w 5 min
0
anonimowy napisał(a):

Jakie znacie przykłady teorii, które w praktyce okazują się nie właściwe lub nie tak dobre jak to opisuje teoria?

Wszystko co ukazuje się pod zbiorczą nazwą Inżynieria oprogramowania. Tyle teorii, tyle podejść i analiz a w praktyce wychodzi na to że koszta rosną, jakość spada, skomplikowanie rośnie i tyle dobrze że wydajność hardware rośnie szybciej i potrafi to wszystko skompensować więc nikt głośno nie mówi że król jest nagi.

Ale tworzenie nowych algorytmów na uczelniach jest trudne. Lepiej tworzyć teorie na temat rozwoju oprogramowania, bezpieczniejsze i daje lepszy scoring.

2

W programowaniu mieliśmy dużo świetnie zapowiadających się rozwiązań, które ostateczbnie spadły z rowerka. Teoria, jak sama nazwa wskazuje, zaczyna się od teorii. Ktoś sobie wymyślił, że takie dziedziczenie w OOP, to dobry sposób na odzwierciedlenie rzeczywistości, narysował parę wykresów, ktoś inny zrobił z tego doktorat, a jakiś przedsiębiorczy guru zaczął organizować szkolenia, warsztaty i certyfikację z tego, czy ktoś tam dobrze opanował konkretną technikę. Następnie przez 10-20 lat branża szuka w tym sensu, nie odnajduje i piękna w założeniach koncepcja leci do kosza.
Samo OOP, jako koncepcja opiera się na fałszywym przekonaniu, że świat (a ściślej modelowana rzeczywistość) jest zorganizowana hierarchicznie. No i mamy jakieś przykłady, które niby mają to pokazywać, że istota żywa<-ssak <-małpa<-szympans. I wszystko gra, do momentu, kiedy ktoś nie ma potrzeby zderzenia tego z rzeczywistością i np. nie potrzebuje klasy obrazującej wszystkie istoty w zależności od temperatury środowiska w którym zyją.
Z drugiej strony, jest tak, że jakaś koncepcja powstaje, robi się modna, a na koniec każdy musi ją stosować, bo to "best industry practices". No i mamy jakieś tam mikroserwisy, które nie są mikroserwisami, TDD, które sprowadza się do "mamy testy, ale one niczego nie testują" itd.

2

@anonimowy podaj może przykład wprowadzenia buga przez @Riddle będzie można rozpocząć konkretną dyskusję

8

Nie wiem czy o takie coś pytasz i czy to można zaliczyć do teorii, ale bardzo mnie drażni cargo kult i ogólnie fetysz nowych technologii.

Ok, czasem pisanie czegoś w jakimś nowym nurcie jest dobre, ale pchanie na siłę do projektu technologii X tylko dlatego, że teraz jest modna i fajnie będzie wyglądać w CV jest słabe.

No i potem powstają potworki, gdzie jakaś prosta nakładka na bazę, taki ordynarny CRUD ogarnia 20 osób i jest do niego zaangażowany docker, k8s, 4 VPSy, 7 bibliotek, 5 frameworków, do tego jeszcze rozbicie na mikroserwisy i ogólnie zamiast projektu do ogarnięcia dla studenta w tydzień, robi się projekt do ciągłej pracy przy utrzymaniu dla kilkunastu osób.

A co do OOP - to jest technologia, która sama w sobie nie jest ani zła, ani dobra. Tak samo jak młotek - do wbijania gwoździ jest super, ale do uszczelnienia rury od kibla to już średnio się nadaje. Tak samo tutaj - obiektówka używana z głową jest fajna, ale pchanie na siłę wszędzie "bo tak" jest błędem. Tylko to nie znaczy że młotek jest zły, tylko że ktoś nie umie z niego korzystać.

3

Docker akurat prawie zawsze jest uproszczeniem. Zeby to byla faktycznie zbedna abstrakcja, to to by musial byc jakis prosty skrypt

11
anonimowy napisał(a):

@Riddle bardzo często przedstawiał piękne teorie jak może wyglądać inżynieria oprogramowania, jednak jego działania na forum pokazują, że jego podejście może zawierać usterki jak np. wprowadzanie bugów itd. Jakie znacie przykłady teorii, które w praktyce okazują się nie właściwe lub nie tak dobre jak to opisuje teoria?

Tak po prawdzie, to to, co nazywasz teoriami, to nie są żadne teorie, tylko bardziej wierzenia czy inne zabobony, a więc pytanie jest błędnie skonstruowane.
Jeśli chcielibyśmy odpowiedzieć na pytanie, "które zabobony nie działają w praktyce", to odpowiedź brzmi "żadne", i można zamknąć wątek. ;)

piotrpo napisał(a):

Samo OOP, jako koncepcja opiera się na fałszywym przekonaniu, że świat (a ściślej modelowana rzeczywistość) jest zorganizowana hierarchicznie. No i mamy jakieś przykłady, które niby mają to pokazywać, że istota żywa<-ssak <-małpa<-szympans. I wszystko gra, do momentu, kiedy ktoś nie ma potrzeby zderzenia tego z rzeczywistością i np. nie potrzebuje klasy obrazującej wszystkie istoty w zależności od temperatury środowiska w którym zyją.

No nie, w OOP chodzi o łączenie ze sobą stanu i zachowania. To o czym piszesz, to dziedziczenie - i to jest tylko jedna, nieobowiązkowa technika z OOP.

Z drugiej strony, jest tak, że jakaś koncepcja powstaje, robi się modna, a na koniec każdy musi ją stosować, bo to "best industry practices". No i mamy jakieś tam mikroserwisy, które nie są mikroserwisami, TDD, które sprowadza się do "mamy testy, ale one niczego nie testują" itd.

No i to jest clue sprawy.
Ktoś miał problem - rozwiązał go - opowiedział innym (np. na konferencji).
No i potem ci inni stwierdzają, że zrobią tak samo, no bo skoro komuś to pomogło, to im też pomoże. Problem w tym, że zazwyczaj umyka im ten szczegół, że nie mają takiego samego wejściowego problemu, tylko zupełnie inny.

1

No nie, w OOP chodzi o łączenie ze sobą stanu i zachowania. To o czym piszesz, to dziedziczenie - i to jest tylko jedna, nieobowiązkowa technika z OOP.

Zgadza się, jednak to właśnie w językach obiektowych wymyślono sobie dziedziczenie, stworzono z niego fetysz, opracowano wzorce projektowe, jak z tego dziedziczenia "prawidłowo" korzystać. Coś jak w starym dowcipie o tym jak to socjalizm dzielnie rozwiązuje samodzielnie stworzone problemy.

3

No nie, w OOP chodzi o łączenie ze sobą stanu i zachowania. To też jest zabobon.

To o czym piszesz, to dziedziczenie - i to jest tylko jedna, nieobowiązkowa technika z OOP. True.

No i potem ci inni stwierdzają, że zrobią tak samo, no bo skoro komuś to pomogło, to im też pomoże. Problem w tym, że zazwyczaj umyka im ten szczegół, że nie mają takiego samego wejściowego problemu, tylko zupełnie inny. True. Ale możliwe że jest jeszcze drugi problem. Wejściowy problem może i mają ten sam, ale nie potrafią z tej konferencji/książki wydobyć faktycznej praktyki. Większość osób po prostu słyszy jakieś słowo, zakłada że rozumie co ono znaczy, i dokleja do niego swoje pomysły, często wynik jest słaby; i często osoba krytykuje to słowo.

Jak np. ktoś słyszy słowo "TDD" i zakłada że wystarczy pisać testy. Słyszą "microserwisy" i zakładają żę wystarczy mieć apki co gadają po http. Słyszą "devops" i zakładają że wystarczy postawić k8s. Słyszą "CI" i zakładają że wystarczy mieć jenkinsa w chmurze. Praktycznie każdy termin jest w taki sposób wypaczany. Ktoś słyszy "agile" i myśli że chodzi o scruma. Ktoś słyszy "continuous delivery" i zakłada o to żeby robić często deploye. Ktoś słyszy "code review" i automatycznie myśli "PR".

2

Moze to w takim razie nie jest wypaczenie znaczenia, a ewolucja, dostosowanie do realiow i praktyki?

6

@Riddle Masz rację. Tylko wspólnym mianownikiem tych problemów jest to, że OOP, CI/CD, code review, TDD, agile i cała masa innych narzędzi staje się celem samym w sobie. Taka bardzo częsta patologia, która sprowadza się do tego, że zamiast zastanawiać się jak zrobić wydajnie, dobre oprogramowanie zastanawiamy się "jak wdrożyć CI". Oczywiście to CI może być pożytecznym narzędziem, ale nadal jest wyłącznie narzędziem. Jeżeli staje się celem samym w sobie to zapomina się o prawdziwym celu, którym jest dostarczenie klientowi porządnego oprogramowania, które robi to czego klient od niego oczekuje, tylko zaczynamy się zajmować pierdołami. W dużych firmach kończy się to często karykaturalnymi sytuacjami, w których od kilkudziesięciu, do kilu tysięcy ludzi "robi" produkt do ogarnięcia przez 10 sensownych inżynierów. Wszystkie kejpiaje na zielono, wskaźniki jakości kodu na 99%, testy się świecą, roadmapy przygotowane, a na koniec przychodzi dzień sądu (release) i się okazuje, że udało się zrobić wszystko, poza produktem.

3

@Riddle Masz rację. Tylko wspólnym mianownikiem tych problemów jest to, że OOP, CI/CD, code review, TDD, agile i cała masa innych narzędzi staje się celem samym w sobie.

No, a nie powinny. To tylko narzędzia do osiągniecia celu. TDD, CI, Agile, DevOps nie są wartością samą w sobie; one pomagają dostarczyć wartość, jeśli się umie z nich korzystać.

Ktoś kto wprowadza TDD, CI albo OOP do projektu dla samego wprowadzenia to trochę taki cargo cult.

1

TDD bym w cargo cult nie wrzucał, imo, to będzie wartość dodana sama w sobie, zmusi do nauczenia się testowania:)

5
lion137 napisał(a):

TDD bym w cargo cult nie wrzucał

Jak w jakiejś firmie usłyszysz "robimy TDD, bo to zajebiste narzędzie, dlatego od dzisiaj wprowadzamy wymaganie, żeby Sonar pokazywał 95% pokrycia kodu testami, to zmienisz zdanie. Czy to będzie TDD? Oczywiście nie. Czy będzie rubryczka "wdrożenie TDD w projekcie X"? Oczywiście tak.
OOP, DevOps, CI/CD, konteneryzacja, czy nawet podejście agile to nie są złe koncepcje. Problem zaczyna być jak zaczyna się je "wdrażać", bo to "best industry standards", a skoro wdrożyć się nie da, to wyciąga się z nich jakieś mało znaczące bebechy, instaluje Jenkinsa, czy uruchamianą z łapy pipeline, albo urządza dokładnie 15 minutowe daily tudzież wciska jakiegoś starego klamota w kontener na k8s, podmienia bazę na zarządzalną w chumrze i już jesteśmy DevOps, Cloud Native, agile. To, że wszystko działa gorzej niż wcześniej - mało znaczący szczegół.

0

Tak kocham TDD, które testuje tylko mocki xd Wszystko da się zepsuć

3

@anonimowy Nie wiem, czy to ironia, czy skrót myślowy, na 100% dobry przykład. TDD nie polega na tym, że ma się testy, nie polega nawet na tym, że ma się właściwe testy. To jest sposób w jaki ktoś tam zalecił te testy pisać, tak żeby na koniec osiągnąć satysfakcjonujący rezultat w postaci dobrych, znaczących testów.
Pokrycie kodu testami jest jakimś tam wskaźnikiem, który może czasami coś mówić. Jakości testów nie da się łatwo mierzyć. Dlatego jeżeli organizacja naciska na wskaźniki, to dostaje to na co naciska, czyli wskaźniki. W efekcie masz to pokrycie na poziomie >90%, excele się świecą na zielono, ale sytuacja jest gorsza niż zanim te testy napisano. Bo o ile stanem wyjściowym było pokrycie kodu w 5% sensownymi testami, to na końcu ćwiczenia mamy pokrycie kodu w 90%, ale testami, które nie mają żadnego sensu. W dodatku tracisz nawet możliwość rozróżnienia komponentów, które są przetestowane od tych, które przetestowane nie są. Jako bonus oczywiście leci zabetonowanie implementacji.
Klasyczne "Operacja się udała, pacjent nie przeżył".

3

@piotrpo ja właśnie wyśmiewam testy, które są tylko po to żeby były a nie testują nic sensownego. Niestety w wielu zastanych projektach napotkałem się na coś takiego i jest to koszmar

0

Możesz zamienić klasy, na struktury ze wskaźnikami na funkcje. Dałem przykład użycia takich rozwiązań ale został cały wpis usunięty. GPT Ci to wyjaśni. Masz szybkość C i funkcjonalność klas, bez tych chorych zabezpieczeń (w JS to zostało użyte prawidłowo uważam) i bez dziedziczenia które rozumiem ale nie stosuję.

2
piotrpo napisał(a):

@anonimowy Nie wiem, czy to ironia, czy skrót myślowy, na 100% dobry przykład. TDD nie polega na tym, że ma się testy, nie polega nawet na tym, że ma się właściwe testy. To jest sposób w jaki ktoś tam zalecił te testy pisać, tak żeby na koniec osiągnąć satysfakcjonujący rezultat w postaci dobrych, znaczących testów.

To jest prawda, ale nie jest całą historią.

Prawdą jest że TDD nie polega na posiadaniu testów ani nawet właściwych testów. Prawdą jest też że polega na sposobie ich pisania. Dokładniejsze chodzi o pisanie ich przed kodem, jako sposób wytworzenia kodu.

Ale dodatkowo:

  • Jak powiedział @piotrpo to jest technika testowa (sposób pisania testów)
  • jest to również technika projektowa - jaknajbardziej jeśli naszym celem jest dobry design, TDD jest dobrym sposobem żeby to osiągnąć
  • jest to technika specyfikacyjna - pozwala określić nasze cele w postaci wykonywanych testów
  • technika komunikacyjna - pozwala zakomunikować innym programistom dużo wartościowych informacji które w kodzie mogłyby się zatracić

TDD to jest takie 4in1. Szkoda że większość ludzi myśli o tym, ze to jest tylko technika testowa 😕

4
Riddle napisał(a):

TDD to jest takie 4in1. Szkoda że większość ludzi myśli o tym, ze to jest tylko technika testowa 😕

Pozwoliłem sobie na uproszczenie. A w szerszym kontekście - szkoda, że wielu ludzi sprowadza tworzenie oprogramowania do napisania kodu z pominięciem analizy, upewnienie się, że ten kod działa, wdrożenia, utrzymania i zmian.
Odchodząc od tematu testów, to wiele tych modnych terminów z obszaru inżynierii programowania, takie jak DDD, DevOps, TDD, Agile w większości przypadków opisują kulturę pracy, a nie narzędzia i techniki. Jeżeli ktoś z tego wyciągnie "mamy mieć event storming, admina nazwiemy DevOpsem, napiszemy tonę bezużytecznych testów i zatrudnimy Scrum Mastera", to po chwili będzie miał bagno większe niż miał, ale za to będzie uważać je za nowoczesne bagno.

2

"W teorii nie ma różnicy między teorią i praktyką, a w praktyce jest..."

1

W teorii wiesz co i jak, każdy powtarza tą teorię, jesteś pewny wszystkiego, w praktyce się okazuje, że ta teoria to był wierzchołek góry lodowej i są problemy i błędy, których nikt w tej teorii nie uwzględnił.
Praktyka to jednak użycie teorii, zweryfikowanie i stworzenie planu, która przy próbie opisu w sposób uproszczony będzie teorią, a w sposób bardzo precyzyjnym z wielką precyzją praktyką.

0
.GodOfCode. napisał(a):

Praktyka to jednak użycie teorii, zweryfikowanie i stworzenie planu, która przy próbie opisu w sposób uproszczony będzie teorią, a w sposób bardzo precyzyjnym z wielką precyzją praktyką.

Czyli praktyka jest jak TDD dla teorii?

0
loza_prowizoryczna napisał(a):
.GodOfCode. napisał(a):

Praktyka to jednak użycie teorii, zweryfikowanie i stworzenie planu, która przy próbie opisu w sposób uproszczony będzie teorią, a w sposób bardzo precyzyjnym z wielką precyzją praktyką.

Czyli praktyka jest jak TDD dla teorii?

Nie, TDD to narzędzie, mi chodziło o problem, projekt, masz jakiś problem rozwiązujesz go możesz robić te tdd, ale naczytasz się jak coś działa, ktoś ci to wyjaśni, potem sam tworzysz sobie w domu/garażu te rozwiązanie i wychodzi, że o 80% rzeczy nikt nie powiedział dali tylko 20%.

0
.GodOfCode. napisał(a):

Nie, TDD to narzędzie, mi chodziło o problem, projekt, masz jakiś problem rozwiązujesz go możesz robić te tdd, ale naczytasz się jak coś działa, ktoś ci to wyjaśni, potem sam tworzysz sobie w domu/garażu te rozwiązanie i wychodzi, że o 80% rzeczy nikt nie powiedział dali tylko 20%.

Metoda naukowa to też jest narzędzie. Najpierw praktycznie badasz interesujący cię fragment rzeczywistości a później dopasowujesz do niego teorię. To co ty opisujesz to matematyka ale tam nie używają TDD.

0
loza_prowizoryczna napisał(a):

Metoda naukowa to też jest narzędzie. Najpierw praktycznie badasz interesujący cię fragment rzeczywistości a później dopasowujesz do niego teorię. To co ty opisujesz to matematyka ale tam nie używają TDD.

Cały świat jest matematyczny jak ubierzesz jakiś problem we wzór, to teraz możesz go rozwiązać matematycznymi narzędziami, jak dobrze go ubierzesz to problem będzie piękny do rozwiązania.

Nawet taki głupi przykład utrzymywania równowagi możesz stworzyć parametry, które dają jakąś wagę danemu sygnałowi na wejściu coś jak x*a jak w funkcji liniowej, czyli też podstawie neurona w mózgu, perceptrona i okazuje się że takie proste równanie rozwiążesz to rozwiązaniem jest stabilność układu czyli gdzie w problemie się nigdy nie przewraca twój układ który stabilizujesz.

0
.GodOfCode. napisał(a):

Cały świat jest matematyczny jak ubierzesz jakiś problem we wzór, to teraz możesz go rozwiązać matematycznymi narzędziami, jak dobrze go ubierzesz to problem będzie piękny do rozwiązania.

Świat może być podzbiorem rozwiązań matematycznych ale twierdzenia że świat == matematyka jest błędny.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.