pragmatyczne programowanie i piękny kod

6

Od pewnego czasu dochodzę do myśli, że dobre praktyki na temat czystego kodu wraz z konstrukcjami języków wysokopoziomowych coraz częściej są sprzeczne z pragmatycznym programowaniem.

1. DRY

Ciągle uważałem, że w kodzie nie należy łamać reguły DRY, że jeśli coś się powtarza to znak, żeby reagować i przeciwdziałać temu. Kod w takich wypadkach poddaje się grupowaniu i uogólnianiu na tyle ile to konieczne. Dlatego też po przejściach z C++ i Java, skakałem z radości na widok Pythona.

Mimo wszystko, im więcej uczyłem się na temat właściwych praktyk programowania tym coraz wolniej tworzyłem kod, a jego przejrzystość i tak pozostawiała wiele do życzenia. Link do kolejnego wątku jest idealnym przykładem rosnącej złożoności w próbie ochrony DRY: http://4programmers.net/Forum/Inzynieria_oprogramowania/201041-o_utrudnianiu_sobie_zycia_w_c++_za_pomoca_wektorow_metod_i_szablonow

2. Programista != Prorok aplikacji

W takcie moich przygód z programowaniem od czasu do czasu miałem styczność z kilkoma nietypowymi tekstami na temat porzucenia wysokiego poziomu abstrakcji i skupieniu się wyłącznie na kodzie faktycznym. Pierwotnie to zignorowałem, bo jak to tak programować bez uwzględnienia przyszłych jakże prawdopodobnych modyfikacji!

Pułapki programowania obiektowego: http://www.slideshare.net/Reg1773/puapki-programowania-obiektowego

Najbardziej uderzył mnie argument odnośnie uogólniania, bo fakt faktem kodując, nie wiem co przyjdzie dokładnie dodać za 3 miesiące tak więc uogólniam każdą możliwą opcję. W każdym razie to myślenie, a także kodowanie z myślą ponownego wykorzystania kodu w moich oczach jest coraz większą ściemą.

W odniesieniu do tego slajdu bardzo podobała mi się odpowiedź @Azariena w wątku: Projekt Szachów

Ujął aplikacje w proste koncepcje. Oczywiście, zaraz po jego wypowiedzi padło kilka tekstów, że rozbudowa pod wieloma kątami będzie mieć dużo bolączek.

W trakcie czytania wątku spodziewać się można było takich odpowiedzi skoro zwykle chce się opancerzyć kod tak, żeby był przygotowany na każdą ewentualność. W praktyce takie działanie wydaje mi się przerostem formy nad treścią.

Ciekawym momentem była próba patrzenia na projekt nie z perspektywy fragmentów aplikacji, a samej aplikacji. Wtedy interesowałem się metodykami tworzenia oprogramowania i przeczytałem "Zwinny samuraj. Jak programują mistrzowie zwinności" i "Zrozumieć Agile Project Management Równowaga kontroli i elastyczności". Głównie podobała mi się podstawa tych metodyk agile czyli Lean Software Development.

W kontekście odchudzania bardzo przypadła mi do gustu informacja, że wartością dla klienta w aplikacji nie jest wystrzałowa architektura, a konkretna funkcjonalność.

To też bardzo podobał mi się przykład z książki "Czysty Kod". Chętnie przepisałbym fragment z książki, ale nie mam jej przy sobie.

Został podany tam przykład, że kod to miasto, które z czasem się rozwija. Główną myślą było to, że nie ma idealnego kodu na czas całego systemu. Jako przykład została przedstawiona wieś i nieopłacalność budowy w niej autostrady. Dopiero gdy to wieś się porządnie rozwinie wtedy pojawi się sens budowy tej autostrady.

Innym przykładem na to, że próba wyprzedzenia potrzeb w projekcie jest daremna ukazuje ta notka na temat astronautów platformowych: http://www.devblogi.pl/2012/04/kiedy-wielcy-mysliciele-analizuja.html

3. Podsumowanie

Osobiście myślę, że języki oferują za wiele wygody programiście. Wcześniej gdy był C to ludzie też tworzyli duże systemy i dawali sobie z nimi radę, a teraz mimo licznych wygód to programowanie staje się coraz bardziej chore.

Na koniec TAO programisty o którym sobie przypomniałem.

3.2

Byl raz programista, ktory pisal niestrukturalne programy. Nowicjusz,
probujacy go nasladowac, takze zaczal pisac niestrukturalne programy.
Gdy nowicjusz poprosil mistrza o ocene postepow, mistrz skarcil go
za pisanie niestrukturalnych programow, mowiac: "Co jest odpowiednie
dla mistrza, nie jest odpowiednie dla ucznia. Musisz zrozumiec
Tao zanim przenikniesz strukture."

Myślę, że już wreszcie pojąłem o w tym tekście chodzi.

Jestem ciekaw waszych opinii, a szczególnie tego, czy jako programiści C++, C# czy Java doszukujecie się potrzeb łamania dobrych reguł?

5

Link do kolejnego wątku jest idealnym przykładem rosnącej złożoności w próbie ochrony DRY: http://4programmers.net/Forum/[...]oca_wektorow_metod_i_szablonow

O, mój wątek. Ale dość daleko, tamten wątek/kod to był przykład chorego zastosowania szablonów do tworzenia ciekawych, ale zupełnie niepraktycznych konstrukcji :].

Nie do końca się ze wszystkim zgadzam (trochę za ostre podejście), ale ten link powinien Cię zainteresować - http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html .

Zasadniczo przesadzanie zarówno w stronę za niskiego i za wysokiego poziomu abstrakcji jest złe. I łatwe. Trudne jest znalezienie złotego środka, i po tym IMO można poznać wybitnego programistę (mi do tego jeszcze sporo brakuje...) ;).

Ja poczekam na wypowiedzi innych, ale jeszcze jedna, luźno cytowana sentencja:

Najczytelniejszy, najłatwiejszy w debugowaniu i mający najmniej błędów, najtańszy w utrzymaniu i pisaniu, nie wymagający poprawek, najszybciej działający, zużywający najmniej zasobów... najlepszy kod to brak kodu w ogóle

Warto powiesić w ramce nad łóżkiem :].

edit: http://www.codinghorror.com/blog/2007/05/the-best-code-is-no-code-at-all.html

3

Jeśli chodzi o "Pułapki programowania obiektowego" to autor nie czytał lub nie pamięta o GoF.
Krytykuje agregację zamiast zastosować fabrykę.

Ale ogólnie wiem o co mu chodziło. Niestety mania programowania uniwersalnego może dopaść każdego doświadczonego programistę.
Wtedy czas jest na chwilę się zatrzymać i stwierdzić - czy naprawdę potrzebuję tej setki linii żeby zrobić "hello world"?
A może na początek wystarczy coś prostego?

Wg mnie program powinien się rozwijać tak jak ten fraktal - w miarę napływania nowych wymagań (a nie wyprzedzając je):
http://fractalenlightenment.com/wp/wp-content/uploads/image-import/_Z8mwJp4iSOo/RxT5JjRtcdI/AAAAAAAADnI/le_YlI6PCHo/s1600-h/Koch%2BSnowflake.JPG

3

Ja myśle że po prostu nie można zapominać o zasadach YAGNI i KISS. DRY to nie wszystko.
Jeśli wiemy że jakaś funkcja czy klasa powinny być uogólnione to możemy to faktycznie zrobić, ale do pewnego poziomu. Nie ma sensu bawić się w pisanie 10 warstw abstrakcji, genericów i innych cudów dla klasy o której wiemy że będzie przechowywać bardzo konkretną strukturę która się nie zmieni i wiemy że powstanie tylko jedna implementacja tego wszystkiego. Zresztą wiadomo że przedwczesna optymalizacja to źródło wszelkiego zła. I tyczy się to czasem nie tylko optymalności i szybkości kodu, ale też jego struktury. Refaktorowanie, wydzielanie nadklas / metod etc wykonuje się wtedy kiedy pojawia się taka potrzeba.
To nie znaczy że nalezy pisać gówniany kod a potem go przerabiać, nie! Podkreślam że refaktorować trzeba kiedy pojawia się potrzeba, to znaczy że refaktorujemy od razu kiedy chcielibyśmy coś skopiować, albo od razu kiedy piszemy nową klasę która jest bardzo podobna do innej.

0

Jeśli chodzi o "Pułapki programowania obiektowego" to autor nie czytał lub nie pamięta o GoF.
Krytykuje agregację zamiast zastosować fabrykę.

Ale ogólnie wiem o co mu chodziło. Niestety mania programowania uniwersalnego może dopaść każdego doświadczonego programistę.
Wtedy czas jest na chwilę się zatrzymać i stwierdzić - czy naprawdę potrzebuję tej setki linii żeby zrobić "hello world"?
A może na początek wystarczy coś prostego?

Odnośnie pułapek programowania obiektowego trzeba jeszcze pamiętać że prezentacja się odnosi mocno do gamedevu.

Faktycznie, gamedev (i nie tylko on zresztą) rządzi się swoimi prawami, ma swoje własne specyficzne problemy i ma swoje własne wzorce.

Typowy błąd to np. modelowanie obiektów w grze za pomocą naiwnego dziedziczenia.
Na papierze wygląda ładnie, po czym szybko okazuje się że dziedziczenie osiąga szósty poziom zagnieżdżenia, ilość klas mnoży a i tak kod się duplikuje bo hierarchia i własności obiektów nie tworzą naturalnie drzewa tylko splątany graf (więcej np. http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/)

Podejść do tego problemu jest wiele:

Pisanie gier jak aplikacji biznesowych się kończy źle... i odwrotnie. Co nie znaczy że podejście obiektowe zawsze jest złe - tylko trzeba do obiektowości podejść inaczej, nie kopiować wzorce na ślepo :].

To tak na boku, żeby nie było że obiektowość jest zawsze zła i brzydka.

0
py_ninja napisał(a):

Od pewnego czasu dochodzę do myśli, że dobre praktyki na temat czystego kodu wraz z konstrukcjami języków wysokopoziomowych coraz częściej są sprzeczne z pragmatycznym programowaniem.

To programista i jego kod może być sprzeczny z pragmatycznym programowaniem, zwłaszcza jeśli źle używa tych dobrych praktyk i konstrukcji.

Link do kolejnego wątku jest idealnym przykładem rosnącej złożoności w próbie ochrony DRY: http://4programmers.net/Forum/Inzynieria_oprogramowania/201041-o_utrudnianiu_sobie_zycia_w_c++_za_pomoca_wektorow_metod_i_szablonow

Nie no, przygody @msm w krainie templatów nie mają zbyt wiele wspólnego z DRY.
A samo stosowanie DRY nigdy nie prowadzi do wzrostu złożoności, jest dokładnie odwrotnie.

Pułapki programowania obiektowego: http://www.slideshare.net/Reg1773/puapki-programowania-obiektowego

Jeśli ten gość stosował manię wraperów i uogólniania, to faktycznie zły kod pisał, i dobrze, że przestał. Ale nikt nigdy, w żadnych zasadach OOP nie twierdził, żeby tak robić. Zawsze było wręcz przeciwnie.
Ta prezentacja wygląda na własnoręczne odkrycie KISS i YAGNI, tylko brak jeszcze umiejętności nazwania tych zasad. :)
I kto powiedział, że obiekty w programie muszą modelować rzeczywiste obiekty? :|

Ujął aplikacje w proste koncepcje. Oczywiście, zaraz po jego wypowiedzi padło kilka tekstów, że rozbudowa pod wieloma kątami będzie mieć dużo bolączek.

Tyle, że według pomysłu @Azarien nie tylko rozbudowa, ale budowa i testowanie będą koszmarem. Podział aplikacji na mniejsze elementy wspomaga proces jej powstawania. Dzięki podziałowi problemu na abstrakcje, można je implementować etapami, każdy element oddzielnie testując.
Postulowane szachy w jednej funkcji, to byłoby lekko ponad tysiąc linii kodu, czyli czysta patologia. (Żeby nie było, ja w swoim projekcie w tamtym wątku też przesadziłem, głównie z metaobiektami opisującymi możliwości ruchu. To byłoby komplikacją.)

W kontekście odchudzania bardzo przypadła mi do gustu informacja, że wartością dla klienta w aplikacji nie jest wystrzałowa architektura, a konkretna funkcjonalność.

Owszem, architektura jest wartością tylko dla programisty.

Osobiście myślę, że języki oferują za wiele wygody programiście. Wcześniej gdy był C to ludzie też tworzyli duże systemy i dawali sobie z nimi radę, a teraz mimo licznych wygód to programowanie staje się coraz bardziej chore.

Zatem pisz w C. ;)

3

Mimo wszystko, im więcej uczyłem się na temat właściwych praktyk programowania tym coraz wolniej tworzyłem kod, a jego przejrzystość i tak pozostawiała wiele do życzenia. Link do kolejnego wątku jest idealnym przykładem rosnącej złożoności w próbie ochrony DRY:

To, iż kod nie był przejrzysty wynikało zapewne z innego powodu. Nie wynikało to z powodu stosowania się do zasad DRY tylko przez łamanie innych zasad, o których być może nie wiesz. Powielanie kodu to zło, które należy omijać szerokim łukiem z prostego pwoodu - modyfikacje i poprawki. Jeśli w kodzie masz powielające się fragmenty kodu to za pół roku nie będziesz o tym pamiętał i po wprowadzeniu poprawek w jednym fragmencie, nie stworzysz tego samego w innych fragmentach.

Poza tym nie stosowanie się do zasad DRY powoduje wyolbżymianie kodu. W moim aktualnym projekcie moja każda formatka posiada nie więcej jak 250 linijek kodu, a jest to projekt bardzo złożony, który w całości zajmie około 50k linijek kodu. Osiągnąłem to właśnie dizęki temu, że stosuję się do zasad DRY i tworzę ten sam kod ylko w jednym miejscu. Oczywiście nie tylko dizęki temu uzyskałem taką jakość, no ale zobaczmy co tam dalej napisałeś to może omówię kolejne praktyki programowania :)

W takcie moich przygód z programowaniem od czasu do czasu miałem styczność z kilkoma nietypowymi tekstami na temat porzucenia wysokiego poziomu abstrakcji i skupieniu się wyłącznie na kodzie faktycznym. Pierwotnie to zignorowałem, bo jak to tak programować bez uwzględnienia przyszłych jakże prawdopodobnych modyfikacji!

Takie podejście mieli programiści w latach 90, gdyż nie wiedzieli oni powodu, by przejmować się sytuacjami nieprzewidywalnymi. nie było w tym specjalnie nic złego biorąc pod uwagę, że programowali wtedy strukturalnie.

Innym przykładem, gdzie poziom abstrakcji jest mniej ważny, niż faktyczny działający kod, są aplikacje, które posiadają dużo wąskim gardeł i wymagają szybkości. Np programy do konwersji wideo, obróbki grafiki, obróbki dźwięku.
Programy tego typu powinny skupić się w najważniejszych fragmentach kodu, na szybkości działania. Aczkolwiek nie oznacza to, że programista powinien odpuścić kompletnie jakość kodu.

Najbardziej uderzył mnie argument odnośnie uogólniania, bo fakt faktem kodując, nie wiem co przyjdzie dokładnie dodać za 3 miesiące tak więc uogólniam każdą możliwą opcję. W każdym razie to myślenie, a także kodowanie z myślą ponownego wykorzystania kodu w moich oczach jest coraz większą ściemą.

To zależy. Podczas programowania potrzebne jest świeże i logiczne myślenie, a nie uparte chodzenie według pewnych zasad. Sztywne zasady są dla humanistów, a programowanie dla ludzi myślących, więc trzeba myśleć, czy faktycznie dany kod wykorzystamy kiedyś w innym projekcie. Kolejny przykład z życia wzięty:

  • testy jednostkowe - kiedyś napisałem sobie klasę obsługującą testy jednostkowe w moich projektach. Do dziś tę klase wykorzystuję , a jej jakość jest raczej wysoka biorąc pod uwagę fakt, że ilość linijek kodu to zaledwie 150 :)
    W każdym moim projekcie wykorzystuję t klasę i sprowadza isę ona świetnie w tym co robię. Jestem z niej naprawdę dumny.
  • modele barw - kiedyś pisałem program, który wykorzystywał między innymi modele barw. Modele te napisałęm w taki sposó, że mogę je teraz wykorzystać w dowolnym projekcie co też często robię. Zaimplementowane są tam konwersje itd.
    Również świetny projekt, a wykorzystany był w trzech innych projektach, takzę chyba warto jednak pisać uniwersalnie.

W trakcie czytania wątku spodziewać się można było takich odpowiedzi skoro zwykle chce się opancerzyć kod tak, żeby był przygotowany na każdą ewentualność. W praktyce takie działanie wydaje mi się przerostem formy nad treścią.

Dokładnie, ale tylko wtedy, gdy faktycznie nie ma potrzeby pisać czegoś uniwersalnie. Tak jak napisałem wcześniej - najważniejsze to myślenie logiczne i wiedza, czy faktycznie dany kod będzie wykorzystany w innych projektach.

W kontekście odchudzania bardzo przypadła mi do gustu informacja, że wartością dla klienta w aplikacji nie jest wystrzałowa architektura, a konkretna funkcjonalność.

Ha no baa :) Problem jest jednak inny. Załóżmy taką sytuację: piszesz program dla klienta, on Ci mówi co chce, Ty to akceptujesz.
Przechodzisz do realizacji i tworzysz produkt taki jakim chciał go klient. Dodajesz nawet kilka dodatków by pdonieść jakość produktu, a przy tym ocenę Twojej pracy. Kod jednak pisałem niedbale bez żadnej wcześniejszej przemyślanej architektury. Klient otrzymałprodukt był zadowolony, czasami coś się wysypało, ale ogólnie nie było tragedii. Po 2 miesiąchc klient przychodzi i prosi byś dopisał modyfikację i dodatki do np. ewidencji pracowników. Chcesz się zabrać do roboty , aż tu nagle... z powodu głupiej i nieprzemyślanej architektury dałeś sobie pat-a i nie możesz dodać nowych funkcjonalności z "tego i tego powodu". Owa sytuacja ma trzy wyjścia:

  • Mówisz, że tego nie da się zrobić
  • Tworzysz obejścia problemów, co pwooduje kolejne dziwaczne konstrukcje i kod zaczyna przypominać spaghetii, które leżało w kącie przez rok :)
  • Refaktoryzujesz kod, ale z racji, iż cały projekt wygląda praktycznie źle pod względem kodu, nie jesteś w stanie w szybkim tempie niczego zdziałać.

Ogólnie kicha jak widzisz. Klient w tym przypadku NIE jest zadowolony z funkcjonalności.

Jeśli jednak pisałbyś ten sam projekt przemyślanie, tworząc konkretną i logiczną architekturę, kolejne modyfikacje byłyby błahostką. I wtedy klient JEST zadowolony.

Klienta nie obchodzi jakość kodu, ale faktyczny rezultat, jednak źle napisany kod blokuje w pewnym momecnie nowe funkcjonalności lub modyfikacje. Zazwyczaj trzeba pisać obejścia a te powodują frustrację u programisty.

Został podany tam przykład, że kod to miasto, które z czasem się rozwija. Główną myślą było to, że nie ma idealnego kodu na czas całego systemu. Jako przykład została przedstawiona wieś i nieopłacalność budowy w niej autostrady. Dopiero gdy to wieś się porządnie rozwinie wtedy pojawi się sens budowy tej autostrady.

Pamiętam ten fragment i dokładnie tak powinno być. Piszesz małą klasę i nie obudujesz jej specjalnie gigantycznymi powiązaniami z innymi klasami tylko dlatego, że "być może kiedyś to się przyda".
Tylko, że chyba nie bardzo rozumiesz o co chodziło autorowi z tego też powodu poczytaj o YAGNI (You Ain’t Gonna Need It) zaleca, aby nie planować funkcjonalności, o których uważamy, że „kiedyś mogą się przydać”.
Autor właśnie tę zasadę miał na myśli pisząc słowa przytoczone wcześniej. Nie twórzmy ze wsi, metropolii :)

Osobiście myślę, że języki oferują za wiele wygody programiście. Wcześniej gdy był C to ludzie też tworzyli duże systemy i dawali sobie z nimi radę, a teraz mimo licznych wygód to programowanie staje się coraz bardziej chore.

Zauważ ilu programistów teraz chce utrzymywać te duże systemy pisane w "C" :) Z czegoś to wyniak prawda? No właśnie z jakości kodu i czytelności.

Jestem ciekaw waszych opinii, a szczególnie tego, czy jako programiści C++, C# czy Java doszukujecie się potrzeb łamania dobrych reguł?

hmmm... trudne pytanie. Zazwyczaj gdy mam jakiś problem w domu z moim projektem (zaraz powiem o pracy w pracy :)) to potrafię przez godzinę, a nawet dwie myśleć o tym jak powinno rozwiązać się dany problem stosując się do dobrych praktyk programowania. Co jednak najważniejsze jak napisać kod tak, by w przyszłości był fajny do wykorzystania.
Nie pisze kodu byle jak tylko staram isę go umieszczać tam gdzie powinien być (bardzo ważne zagadnienie), a także napisać go tak by kod był króki (kolejne ważne zagadnienie). czy funkcja powinna być uniwersalna? Z tym akurat tak bardzo nie szaleję. Funkcja powinna być uniwersalna jeśli sa ku temu jakieś powody.

Natomiast zupełnie inaczej wygląda programowanie w pracy - w firmie. Tam pisze się kod tak bydziałał. Przechodził testy i zadowalał klienta. Z obrymi praktykami programownaia nie ma to jednak znaczenia, co pwooduje, że kod w pracy zazwyczaj jest brzydki i trudny w utrzymaniu. Często musimy wymyślać nowe obejścia dla problemów które powstają.

Oba podejścia dają możliwość tworzenia dobrych programów, ale tylko jeden z tych sposobów daje satysfakcję z utworzonego projektu :)
Dobry kod daje profity w przyszłości. Kod tworzy się szybciej a dodatki, modyfikacje etc. tworzone są od ręki.

0

Osobiście nie rozumiem ludzi którzy piszą w pracy kod którego powstydziłby się nawet student, bo brak czasu, bo napięte terminy, bo zbliża się asteroida...

Może to brak kontroli jakości, a może niechlujstwo, nie wiem.

1

Aż dziwne, że nikt nie wspomniał o http://en.wikipedia.org/wiki/Principle_of_least_astonishment
Co mi z kodu, który ma X warstw abstrakcji, N zastosowanych wzorców, itp itd jeśli nie wiadomo gdzie czego szukać.

0

Tu macie fajny artykul na temat: http://www.asawicki.info/news_1438_igk_conference_-_our_slides.html Po prostu trzeba dobrac narzedzia do tego co chcemy zrobic. Mysle ze autorzy nie bez powodu lapia sie na podium praktycznie na kazdym Compo na IGK. Jesli pracujemy przy molochu ktory jest tworzony przez kilkaset osob, przez lata, nie obejdziemy sie bez "dobrych praktyk". Jesli robimy male, proste rzeczy, ew. zalezy nam najbardziej na wydajnosci, warto rozwazyc inne podejscia.

Przyklad ode mnie, potrzebowalem napisac prosciutki timer do zarzadzania czasem (Java), moglem robic caly projekt, testy, rozbijac na klasy, uzywac wzorcow itp. tylko po co, jesli w 15 minut mialem cos co w 100% spelnilo moje wymagania?

Nie mozna sie fixowac na jednym podejsciu.

0

Tyle, że według pomysłu @Azarien nie tylko rozbudowa, ale budowa i testowanie będą koszmarem. Podział aplikacji na mniejsze elementy wspomaga proces jej powstawania.
Nigdy nie napisałem, żeby szachy zrobić w jednej funkcji. Ale zauważ, że na problem spojrzałem od góry: klasa Chessboard, klasa Player itp. Każda z tych klas czy funkcji miałaby się zajmować czymś zupełnie odrębnym.
Inni zaś zaczynali od dziedziczenia bierek czy wręcz od pola - Field, które na 99% później okazałyby się zbędne.
(pole czy bierka mogłyby mieć sens dopiero w warstwie graficznej, ale na jej temat nie zabierałem głosu)

0

dziedziczenie figur jak chcemy zrobić np warcaby nie jest złe. Załóżmy ,że później chcielibyśmy zrobić z tego programu szachy to dodanie nowych figur nie stanowiło by problemu Możemy np zrobić funkcję czysto wirtualną o nazwie "ruch" i dopiero obiekty podrzędne od "figury" by ją implementowały. Każda figura przecież inaczej się rusza np pionek i konik. Chociaż w sumie jak już wiemy ile będzie występować figur to po co w ogóle używać dziedziczenia. Możemy stworzyć po prostu klasę Figura odnoszącą się do wszystkich typów figur, ale jeśli by tak zrobiliśmy byłoby w sumie dużo sprawdzeń. Jeśli jest to taka figura zrób to zaś jeśli inna zrób coś innego(inaczej wykonaj ruch). Ja mam tak ,że im bardziej kombinuje,staram się go przygotować na wszystkie możliwe przypadki to mi program gorzej wychodzi.

0

że im bardziej kombinuje,staram się go przygotować na wszystkie możliwe przypadki to mi program gorzej wychodzi.

Bo masz za mało doświadczenia jeszcze.
Pisząc program należy dużo kombinować. Jeśli tworzymy coś w domu to 1/3 czasu (niektórzy twierdzą, że nawet więcej) powinniśmy poświęcić na rozplanowanie aplikacji (np. w UML-u). I to rozplanowanie powinno być jak najlepsze - zgodne z zasadami dobrego kodu.
Pisząc program bez poprzedniego procesu analizy i projektowania, nic dziwnego, że program gorzej Ci wychodzi. Nie da się napisać dobrego programu pod względem kodu, bez procesu analizy i projektowania.

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