![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 78 Pomógł: 5 Dołączył: 15.04.2006 Ostrzeżenie: (10%) ![]() ![]() |
Mam taki kod:
dostaje blad: Cytat Catchable fatal error: Object of class naglowki could not be converted to string in C:\xampplite\htdocs\gra\index.php on line 33 Probowalem na rozne sposoby, ale nie mam pojecia dlaczego taki blad (IMG:http://forum.php.pl/style_emoticons/default/sad.gif) |
|
|
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 304 Pomógł: 51 Dołączył: 4.02.2005 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
zamień to:
na to:
|
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 78 Pomógł: 5 Dołączył: 15.04.2006 Ostrzeżenie: (10%) ![]() ![]() |
Dzieki, rzeczywiscie bledu juz nie ma (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) ale nie wiem dlaczego to co jest zakomentowane powoduje ze strona ladnie wczytuje szablon zamienia miejsca w ktorych sa te teksty i wrzuca tam swoje strony html, a jak dalem wersje swoja to juz jest tylko biale tlo (IMG:http://forum.php.pl/style_emoticons/default/sad.gif) ktos wie gdzie moze byc blad ?
|
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 793 Pomógł: 32 Dołączył: 23.11.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
@shine
Ogólnie to powiem, że nie wiem co chciałeś osiągnąć, ale to co tu jest to jest jakaś papka. Czy to co tu napisałeś w czymś coś ułatwia? Bo mi się wydaje że nie. Jak chcesz pisać obiektowo, to umieszczaj cały kod w obiektach, podziel funkcjonalnie, niech one coś robią, a nie są tylko pojemnikiem na dane. Doradzam poczytać, bo to co tu prezentujesz lepiej nie mówić. Kup dobrą książkę przerób od deski do deski, a potem samemu kombinuj. Bo inaczej nauczysz się czegoś co potem będzie ciężko wyplenić. |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 78 Pomógł: 5 Dołączył: 15.04.2006 Ostrzeżenie: (10%) ![]() ![]() |
Wiem, ze moj kod jest brzydki i niepraktyczny, ale juz go pozmienialem tak, ze robi to co sobie zalozylem, podzielony na funkcjonalne kawalki. Jesli chodzi o czytanie to akurat mi tego nie musisz mowic jestem po solidnym teoretycznym przejsciu przez Inzynierie Oprogramowania i jezyki obiektowe, ksiazki o OOP, teraz zaczynam praktykowac wiec niektore rzeczy pisze troche bez sensu dla samej wprawy, a nie dlatego nie wiem ze najpierw powinienem sobie zrobic specyfikacje wymagan pozniej use case'y i diagramy klas itp, ale wszystko powoli
|
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 793 Pomógł: 32 Dołączył: 23.11.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Nie wiem czemu przyjąłeś pozycję obronną, ale jak masz takie zaplecze wiedzowe, to ono Ci nic nie daje w praktyce, skoro produkujesz taki kod. Nie chodzi nawet o próbowanie, masz wiele "błędów" z samym kodem obiektów. Właściwości publiczne, nie używanie get'erów i set'erów, nazewnictwo, metody które tak na prawdę nic nie robią, a jak są inne to bez sensu jest to że ich nie umieszczasz, no i wspomniany brak enkapsulacji dla funkcjonalności.
Więc dlatego mówię abyś poczytał, a jak czytasz, to chyba bez zrozumienia. Do tego powinno raczej się zacząć od samej budowy obiektów, a potem przejść na wyższy poziom, bo jak nie zrozumiesz jak działają, jak nimi możesz się posłużyć. |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 149 Pomógł: 12 Dołączył: 3.03.2008 Skąd: łódzkie Ostrzeżenie: (0%) ![]() ![]() |
... nie używanie get'erów i set'erów... Czytałem w jednej książce, chyba w tej: http://helion.pl/ksiazki/wzopro.htm że stosowanie getterów i setterów nie jest oznaką podejścia obiektowego. Nie mam książki przed sobą teraz, ale wieczorem w domu przejrze ją jeszcze raz i dokładniej napiszę co autor miał na myśli (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 793 Pomógł: 32 Dołączył: 23.11.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Czytałem w jednej książce, chyba w tej: http://helion.pl/ksiazki/wzopro.htm że stosowanie getterów i setterów nie jest oznaką podejścia obiektowego. Nie mam książki przed sobą teraz, ale wieczorem w domu przejrze ją jeszcze raz i dokładniej napiszę co autor miał na myśli (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Brak nie oznacza, ale odnoszenie się do zmiennych obiektu bezpośrednio już jest złym nawykiem. (Coś o tym wiem, bo już widziałem takie kody, jak kolega próbował jedną właściwość ukryć bo "coś muz mieniało" to nie mógł, bo nie dało się (sprawdź gdzie to używane jest w większej aplikacji, życzę powodzenia) i nie mógł dojść co ją zmieniało, więc jak dla mnie operacje na czystych właściwościach to porażka. Więc chętnie posłucham co autor miał do powiedzenia, tylko oby nie wyszła czysto filozoficzna gadka. |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 149 Pomógł: 12 Dołączył: 3.03.2008 Skąd: łódzkie Ostrzeżenie: (0%) ![]() ![]() |
Zapodam cały rozdział, bo ciekawy i najlepiej odda o co chodzi z tymi getterami i setterami.
Metody zwracające i ustawiające są złe Jak już wspomniałem, fundamentalną regułą rządzącą systemami obiektowymi jest ukrywanie przez obiekty ich szczegółów implementacyjnych. Stosowanie tej zasady umożliwia modyfikowanie implementacji obiektów bez konieczności wprowadzania zmian w kodzie, który te obiekty wykorzystuje. Oznacza to, że powinieneś unikać stosowania funkcji zwracających i ustawiających, które z jednej strony niczego nie ułatwiają, a jednocześnie zapewniają dostęp do szczegółów implementacyjnych (pól) w systemach obiektowych. Warto zwrócić uwagę na fakt, iż ani przykład systemu terminali ATM, ani przykład modelu ruchu ulicznego nie wykorzystywał metod zwracających i ustawiających pola obiektów. Nie twierdzę przy tym, że Twoje funkcje nigdy nie powinny zwracać wartości, lub że funkcji get i set nigdy nie należy stosować. Obiekty czasami po prostu muszą przekazywać swoje dane, aby cały system mógł funkcjonować prawidłowo. Tak czy inaczej, funkcje get i set często są wykorzystywane w sposób niewłaściwy, a więc w roli środków zapewniających dostęp do pól, które w przeciwnym razie byłyby prywatne, zatem ich używanie może prowadzić do poważnych utrudnień. To, co rozumiem przez właściwe zastosowania tych metod omówię na końcu tego podrozdziału. Obecność metod zwracających i ustawiających (nazywanych często akcesorami i mutatorami, choć zdarza się, że słowo akcesor jest używane w odniesieniu do obu tych metod) zwykle oznacza brak jasności oraz niewłaściwe podejście do rozwiązywanego problemu. Programiści często umieszczają te metody w definicjach klas, ponieważ najzwyczajniej w świecie chcą uniknąć myślenia o sposobie komunikowania się obiektów klas w czasie wykonywania systemu. Użycie metod zwracających pozwala odwlec moment analizy technik komunikacji do czasu właściwego kodowania. Takie podejście jest przejawem czystego lenistwa; z pewnością nie jest to oznaka „programowania dla elastyczności”. Przeanalizujmy banalny przykład, który dobrze pokazuje, dlaczego należy unikać metod zwracających. W Twoim programie może występować tysiąc wywołań metody getX(), z których każde zakłada, że wartość zwracana przez tę metodę należy do określonego typu. Wartość zwracana przez metodę getX() może być składowana np. w zmiennej lokalnej, zatem typ tej zmiennej musi odpowiadać typowi zwracanej wartości. Jeśli będziesz musiał zmienić implementację obiektu w taki sposób, że zmieni się typ zmiennej X, popadniesz w poważne tarapaty. Jeśli dotychczasowym typem zmiennej X był int, a nowym typem jest long, po wprowadzeniu odpowiedniej zmiany otrzymasz tysiąc błędów kompilacji. Jeśli rozwiążesz ten problem w sposób niewłaściwy, a więc zastosujesz operację rzutowania typu zwracanej wartości na typ int, kod będzie co prawda kompilowany, ale z pewnością nie będzie działał prawidłowo (zwracana wartość będzie obcinana). Aby uniknąć negatywnych skutków tej zmiany, będziesz musiał zmodyfikować kod otaczający każde z tysiąca wywołań metody getX(). Zdecydowanie nie chciałbym się znaleźć w podobnej sytuacji. Przyjrzyjmy się teraz klasie Money. Ponieważ klasa ta była początkowo pisana wyłącznie z myślą o obsłudze dolarów amerykańskich, zdefiniowano w niej metodę getValue(), która zwraca liczbę zmiennoprzecinkową typu double, oraz setValue(), która ustawia nową wartość. Pierwszy problem polega na tym, że takie rozwiązanie umożliwia zupełnie nonsensowne działania na reprezentowanych kwotach pieniężnych, co ilustruje poniższy fragment kodu: Kod Money a, b, c; // … a.setValue( b.getValue() * c.getValue() ); Co właściwie oznacza pomnożenie dwóch dolarów przez pięć dolarów? Drugi problem jest jeszcze poważniejszy: może zaistnieć konieczność wprowadzenia do aplikacji rozwiązań międzynarodowych, a więc umożliwiających między innymi obsługę wielu różnych walut. Taka zmiana będzie wymagała dodania pola nazwanego currency, które będzie miało wewnętrznie przypisywane takie wartości jak US_DOLLAR, YEN, LEU, ZLOTY czy HRYVNA. Stosunkowo drobna zmiana — wielkie problemy. Co w tej sytuacji będzie zwracała metoda getValue()? Metoda ta nie może po prostu zwracać wartości typu double, ponieważ sama wartość niewiele Ci mówi. Musisz przecież wiedzieć, z jaką walutą masz do czynienia. Nie jest też możliwe normalizowanie zwracanej wartości, np. do dolarów, ponieważ przeliczniki stosowane na rynku walutowym zmieniają się co minutę. Warto się też zastanowić, co należałoby zrobić z otrzymaną wartością. Nie można ich przecież tak po prostu wyświetlić, ponieważ wymagałoby to opatrzenia ich symbolem odpowiedniej waluty. Możesz oczywiście do istniejącej metody getValue() dołączyć nową metodę getCurrency(), ale od tej chwili cały kod wykorzystujący tę wartość będzie musiał dodatkowo pobierać informację o walucie i lokalnie normalizować uzyskiwane wartości do standardowej waluty. Powielenie tego rozwiązania w tysiącu miejsc istniejącego kodu źródłowego wymagałoby mnóstwa pracy. Musiałbyś też znaleźć wszystkie okna swojego systemu, w których wyświetlane są kwoty pieniężne — logika odpowiednich elementów graficznych musiałaby zostać przebudowana do postaci obsługującej różne waluty. Ta „prosta” zmiana błyskawicznie staje się źródłem ogromnych komplikacji. Oto kolejny przykład: przeanalizuj wszystkie problemy związane z polami System.in, System.out oraz System.err po wprowadzeniu do Javy klas Reader i Writer. Wszystkie trzy pola były publiczne, co samo w sobie było przekleństwem tego rozwiązania. Samo zastosowanie odpowiednich otoczek (np. metody System.getOut(), która zwracała pole System.out) oczywiście nie rozwiązywało problemu — pola System.out i System.err musiały być (opartymi na formacie Unicode) obiektami klasy Writer, nie (opartymi na formatowaniu bajtowym) obiektami klasy PrintStream. To samo dotyczyło pola System.in i klasy Reader. Zmiana zadeklarowanych typów obiektów zawierających pola System.out nie jest rozwiązaniem wystarczającym. Obiekty klasy Writer są wykorzystywane w nieco inny sposób niż strumienie wyjściowe. Oba mechanizmy różnią się przecież semantyką i udostępniają różne metody. W efekcie musisz więc zmienić (lub przynajmniej sprawdzić) cały kod otaczający, wykorzystujący pole System.out do wyświetlania na konsoli danych wyjściowych. Jeśli Twój program np. stosował formatowanie Unicode dla danych tekstowych wyświetlanych za pośrednictwem pola System. out, będziesz musiał użyć aż dwóch wywołań metody write() do zapisania na konsoli pojedynczego znaku. Co więcej, będziesz zmuszony do wprowadzenia do swojego programu dodatkowego kodu wyciągającego bardziej i mniej znaczące bajty znaków i wyświetlającego je osobno. Cały ten kod będzie jednak trzeba usunąć w wersji opartej na klasie Writer. Opisany problem jest efektem siły przyzwyczajenia. Kiedy programiści proceduralni zaczynają korzystać z Javy, próbują budować kod, który będzie choć trochę przypominał ich dotychczasowe dokonania. Języki proceduralne nie oferują możliwości 50 Wzorce projektowe. Analiza kodu sposobem na ich poznanie wykorzystywania klas, ale zawierają zwykle rozwiązania podobne do struktur języka C (czyli w praktyce klasy bez metod i z samymi polami publicznymi). Dla takich programistów naśladowanie struktur języka C jest zupełnie naturalne — próbują budować definicje klas pozbawionych metod i udostępniających wyłącznie publiczne pola. Kiedy taki programista proceduralny usłyszy gdzieś, że należy stosować pola prywatne, odpowiednio zmienia ich deklaracje i tworzy publiczne metody get i set. Takie rozwiązanie nie jest jednak niczym więcej niż niepotrzebnym komplikowaniem publicznego dostępu do danych. Programiści stosujący tego typu działania z pewnością nie tworzą systemów obiektowych. Programiści proceduralni będą argumentowali, że publiczne akcesory otaczające pola prywatne są o tyle „lepsze” od dostępnych bezpośrednio pól publicznych, że dają znacznie większą kontrolę nad operacjami modyfikowania wartości pól. Programista obiektowy stwierdzi natomiast, że każdy dostęp — kontrolowany czy nie — jest źródłem potencjalnych problemów konserwacyjnych. Dostęp kontrolowany może być co prawda lepszy od dostępu swobodnego, ale nie zmienia to faktu, że takie rozwiązanie jest z wielu względów niewłaściwe. Argument o wyższości akcesorów nad bezpośrednim dostępem w ogóle nie uwzględnia najważniejszej słabości obu rozwiązań — zdecydowana większość klas i tak nie potrzebuje metod akcesorów (ani mutatorów). Oznacza to, że dobrze zaprojektowany system przesyłania komunikatów (o sposobach jego projektowania za chwilę) w większości przypadków pozwala całkowicie wyeliminować metody get i set oraz w konsekwencji tworzyć klasy, których konserwacja będzie dużo łatwiejsza. Cd. w następnym poście. Nie twierdzę, że zwracanie wartości jest złe, lub że powinieneś wyeliminować ze swojego programu wszystkie metody get — to po prostu niemożliwe. Minimalizowanie udziału tego typu funkcji w definicjach klas spowoduje jednak znaczne ułatwienia w konserwacji kodu. Z czysto praktycznej perspektywy, częste stosowanie metod get i set sprawia, że kod jest nie tylko bardziej skomplikowany, ale także mniej elastyczny. Przeanalizuj typową „wszechmogącą” klasę proceduralną, która z innych obiektów zbiera informacje niezbędne do wykonania jakiegoś zadania. Implementacja tej klasy pełna jest wywołań zewnętrznych metod get. Co jednak powinieneś zrobić, kiedy okaże się, że odpowiednie zadania są już wykonywane przez jeden z obiektów udostępniających swoje dane tą drogą? Czy można przenieść kod wykonujący właściwe zadania z jednej, „wszechmogącej” klasy w miejsca, w których składowane są niezbędne dane? Wywołania akcesorów przestają być potrzebne, a cały kod jest dużo prostszy. Stosowanie metod get i set powoduje też, że program staje się nieelastyczny (nie można w jego ramach łatwo implementować nowych wymagań biznesowych) i wyjątkowo trudny w konserwacji. Prawdopodobnie najważniejszą zasadą systemów obiektowych jest abstrakcja danych, a więc ścisłe ukrywanie implementacji mechanizmów obsługi komunikatów przed innymi obiektami. To tylko jeden z powodów, dla których wszystkie Twoje zmienne klasowe (pola klasy niebędące stałymi) powinny być prywatne (deklarowane ze słowem kluczowym private). Jeśli stworzysz publiczną zmienną klasową, nie będziesz mógł zmieniać tego pola wraz z ewolucją całej klasy, ponieważ w ten sposób uniemożliwiłbyś prawidłowe funkcjonowanie kodu zewnętrznego, który z tego pola korzysta. Z pewnością nie masz ochoty na przeszukiwanie tysiąca zastosowań jakiejś klasy tylko dlatego, że wprowadziłeś drobną zmianę w jej definicji. Bezmyślne stosowanie metod zwracających i ustawiających jest niebezpieczne z tych samych względów, które decydują o zagrożeniach związanych z używaniem pól publicznych — także metody get i set zapewniają zewnętrzny dostęp do szczegółów implementacyjnych. Co będzie, jeśli zostaniesz zmuszony do zmiany typu udostępnianego w ten sposób pola? Przecież będziesz wówczas musiał zmienić także typ zwracany przez metodę akcesora. Jeśli wartość ta jest używana w wielu miejscach, będziesz musiał zmienić odpowiednie fragmenty w całym kodzie. Ja wolałbym jednak ograniczyć zakres koniecznych zmian do definicji pojedynczej klasy. Nie chcę, by prosta modyfikacja przenosiła się na cały program. Na podstawie reguły ukrywania szczegółów implementacji można stworzyć wiarygodny test systemów obiektowych. Czy możesz dokonywać istotnych zmian w definicji pojedynczej klasy (włącznie z wyrzuceniem całych fragmentów kodu i wstawieniem w ich miejsce zupełnie nowej implementacji) bez konieczności modyfikowania kodu wykorzystującego obiekty tej klasy? Tak głęboka modularyzacja oprogramowania bardzo ułatwia konserwację oprogramowania i pełni zasadniczą funkcję w ocenie jego obiektowości. Nieprzestrzeganie zasady ukrywania szczegółów implementacji bardzo ogranicza możliwość stosowania pozostałych mechanizmów obiektowych. Ponieważ metody akcesorów naruszają regułę hermetyzacji, można bez trudu wykazać, że systemy, w których często lub niewłaściwie stosuje się tego typu rozwiązania po prostu nie są systemami obiektowymi. Co więcej, jeśli skrupulatnie przeprowadzisz proces projektowania (w przeciwieństwie do kodowania ad hoc), szybko stwierdzisz, że Twój program nie musi zawierać niemal żadnych metod akcesorów. Proces ten jest więc bardzo ważny. Zapewne zauważyłeś, że w przedstawionym przykładzie modelowania ruchu ulicznego w ogóle nie stosowano metod zwracających i ustawiających. Obiekty klasy Car nie udostępniają metody getSpeed(), także obiekty klasy Road nie definiują metody getAverageSpeed(). Nie potrzebujemy metod getLocation() czy setLocation() w obiektach klasy Car, ponieważ składujemy informacje o lokalizacji pojazdów w obiektach klasy Road reprezentujących odcinki dróg, na których te pojazdy aktualnie przebywają. Nie potrzebujemy też metody setAverageSpeed() w obiektach klasy Road, ponieważ obiekty te same obliczają średnią prędkość pojazdów. Brak metod zwracających i ustawiających nie oznacza, że jakieś potrzebne dane nie mogą być przekazywane pomiędzy poszczególnymi modułami tego systemu — przykładowo, obiekt Road przekazuje informacje o lokalizacji do obiektów klasy Car. Tak czy inaczej, podczas projektowania systemów obiektowych należy możliwie głęboko minimalizować przepływy danych. Doskonałym papierkiem lakmusowym wskazującym na „słuszność” zastosowanych mechanizmów jest następująca reguła: Nie proś obiektu o informacje, których potrzebujesz do wykonania jakiejś czynności; zamiast tego proś obiekt zawierający te informacje o wykonanie tych czynności za Ciebie. Przykładowo, nie powinieneś stosować przedstawionego wcześniej wyrażenia: Kod Money a, b, c; // … a.setValue( b.getValue() * c.getValue() ); Zamiast tego zażądaj od obiektu klasy Money wykonania odpowiednich działań za Ciebie: Kod Money a, b, c; // … a.increaseBy( b ); Nie mówisz już: „daj mi ten atrybut, abym mógł go wyświetlić”. Teraz żądasz czegoś zupełnie innego: „daj mi możliwą do wyświetlenia wizualizację tego atrybutu” lub „wyświetl swoją zawartość”. Kolejnym wyznacznikiem realizacji tej reguły jest szczegółowość operacji. Operacje obszerne sprowadzają się do jednorazowego żądania od obiektów wykonania dużych zadań. Szczegółowe operacje żądają od obiektów realizacji stosunkowo niewielkich zadań. Ogólnie, wolę obszerne metody, ponieważ ich stosowanie upraszcza kod i w wielu przypadkach eliminuje konieczność stosowania metod zwracających i ustawiających. Metody akcesorów i mutatorów można eliminować dopiero na etapie budowy modelu systemu, ponieważ bez dobrze przemyślanego modelu dynamicznego wiarygodne przewidywanie przyszłych mechanizmów komunikacji obiektów klas jest po prostu niemożliwe. Oznacza to, że w przypadku braku tego modelu musisz zapewniać jak najwięcej technik udostępniania danych, ponieważ nie jesteś w stanie przewidzieć, które z tych technik faktycznie będą konieczne. Taka strategia projektowania przez zgadywanie jest w najlepszym przypadku nieefektywna, ponieważ w praktyce oznacza stratę czasu na pisanie niepotrzebnych metod (lub dodawanie zbędnych mechanizmów do implementowanych klas). Jeśli postępujesz w myśl zasady, że w pierwszej kolejności należy budować model statyczny, musisz być przygotowany na to, że stracisz mnóstwo czasu na tworzenie nieprzydatnych lub zbyt elastycznych metod. Co więcej, jeśli niewłaściwy model statyczny wymusi zbyt duże nakłady na tworzenie niepotrzebnych rozwiązań, cały projekt może się zakończyć niepowodzeniem; a jeśli mimo to zdecydujesz się na jego kontynuowanie, koszt konserwacji kodu będzie przewyższał koszt jego ponownego napisania. Wróćmy teraz do przykładu modelowania ruchu ulicznego, w którym użyłem modelu statycznego do analizy relacji odkrytych w fazie planowania systemu przesyłania komunikatów. Nie projektowałem modelu statycznego, by później próbować na jego podstawie budować model dynamiczny (z uwzględnieniem ograniczeń narzuconych przez przygotowany wcześniej model statyczny). Uważne projektując i skupiając się na tym, co chcesz osiągnąć (nie na tym, jak to zrobić), możesz wyeliminować ze swojego programu znaczną część metod zwracających i ustawiających. Treść znajduje się w pierwszym rozdziale książki, a ten jest dostępny jako przykładowy na stronie Heliona (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) |
|
|
![]()
Post
#10
|
|
Grupa: Moderatorzy Postów: 4 465 Pomógł: 137 Dołączył: 26.03.2004 Skąd: Gorzów Wlkp. ![]() |
Myślę, że ma trochę racji. Nie do końca oczywiście, bo zakłada, że każdy kod pisany oop jest aplikacją., To nie prawda, bo spora część to biblioteki, które po prostu muszą posiadać settery i gettery, aby mogły pełnić swoje funkcje. Samo podejście jak poniżej:
Cytat Zamiast tego zażądaj od obiektu klasy Money wykonania odpowiednich działań za Ciebie: To po prostu pewien styl pisania. Trzeba przy nim bardzo uważać, aby obiekty nie rozrosły się i nie stały obiektami-śmietnikami. Osobiście preferuję wydzielenie osobnych obiektów do wykonania zadań, które zupełnie nie pasują do żadnego dotychczasowego obiektu. Niestety nie bardzo rozumiem też, dlaczego miałbym zepsuć obiekt odsłaniając jego składowe - autor jest w tym bardzo, ale to bardzo mało przekonywujący. Dziwi mnie twierdzenie, że (konkludując) program uważa się za obiektowy, gdy używa setterów i getterów. To nie prawda, bo musi spełnić szereg innych założeń. Mam też obiekcje co do rozumienia pojęcia hermetyzacja przez niego. On ją rozumie (albo jak tak to odebrałem) na jakimś bardzo wysokim poziomie - nie widzi tego, że obiekt powinien dostarczać interfejs i ukrywać swoje flaki, bo może ktoś zechce zmienić np. nazwę składowej. Pozdrawiam |
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 793 Pomógł: 32 Dołączył: 23.11.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Z jednej strony autor krytykuje akcesory, a z drugiej sam robi coś czego nie powinno się robić. Co już wspomniał Cysiaczek, za dużo chce ładować w obiekt, jak napisał
Cytat Teraz żądasz czegoś zupełnie innego: „daj mi możliwą do wyświetlenia wizualizację tego atrybutu” lub „wyświetl swoją zawartość”. Po co obiekt ma się sam wyświetlać? Walamy mnóstwo kodu, obiekt puchnie i rośnie, staje się nieczytelny, bo już nie wiemy co tak na prawdę robi... bo i robi co musi, jak i wyświetla się, zapisuje i bug wie co jeszcze, cokolwiek chce się dodać nowego związanego z obiektem, trzeba to napisać w nim, nie można tego hermetyzować, bo już jest się zależnym od tego co jest w obiekcie, nie od jego interfejsu. Do tego Cytat Ogólnie, wolę obszerne metody, ponieważ ich stosowanie upraszcza kod Ja nie wiem, ale to wygląda właśnie na pozostałość po proceduralnym sposobie pisania, metody powinny być proste, dlatego nawet powstał Compose Method, aby właśnie kod metod był krótki i treściwy.Jeszcze jedna rzecz, autor nie mówi aby nie stosować akcesorów, ale aby tego nie robić bezmyślnie, i właściwie zastępować dostęp do właściwości które stały się niewidoczne na zewnątrz. Więc autor bardziej krzyczy, a nie mówi coś ciekawego, bo na początku mówi że to źle money przez akcesory, ale nie podał alternatywnego rozwiązania, a jest nim dla niego aby obiekt money sam się wyświetlał, co jest głupie, do tego coś co wyświetla taki obiekt, niezależnie gdzie się to znajduje musi wiedzieć, że zostały dodana waluta, a jak się dobrze napisze to będzie jedno miejsce. Do tego to jest poważna zmiana w aplikacji, a więc jak się jej nie planowało, to nic dziwnego że będzie trochę roboty przy zmianach, można oczywiście dawać od razu "wszystko, na wszelki wypadek" ale sam autor mówił o przeroście ilości niepotrzebnych elementów, więc jakby sam sobie zaprzeczył. Ogólnie wizja autora, to obiekty które robią wszystko, z olbrzymią ilością kodu, każda nowa funkcjonalność z nimi związana wymaga zmiany ich samych. Brak podziału funkcjonalnego, na to co dany obiekt robi, tak aby móc opisać to w jednym dwóch zdaniach. Czyli robi się nam tak na prawdę nie obiekt, a moduł jakby i nie ważne że jest obiektem, bo i tak jest do wszystkiego. Wydaje mi się że to mu zostało jako zaszłość po proceduralnym sposobie pisania. Ale też są pewne elementy z którymi się zgadzam, jak planowanie aplikacji, przed pisaniem, co spowoduje że nie będzie jak to zwykle bywa dodawanie get'era bo muszę coś dostać z obiektu... bo nikt nie planował jak to zrobić, czy da się lepiej. Czyli podsumowując, autor nie mówi aby nie stosować akcesorów, tylko aby dobrze przemyśleć projekt, bo to zmniejszy ich liczbę. Bo często da się osiągnąć tą samą funkcjonalność w inny lepszy sposób. |
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 149 Pomógł: 12 Dołączył: 3.03.2008 Skąd: łódzkie Ostrzeżenie: (0%) ![]() ![]() |
Czyli konkluzja taka, że w programowaniu obiektowym można coś zrobić sposobem nr1, a kiedyś indziej można zrobić sposobem nr2 bo bardziej pasuje. I żeby było trudniej to oba sposoby mogą być niedobrą praktyką, oba mogą być dobrą praktyką i oba mogą sobie przeczyć (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Wiwat programowanie obiektowe (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) Za dużo tutaj dowolności i abstrakcji, przez to jest to takie trudne. Ale dobry programista powiedział mi kiedyś, że z programowaniem obiektowym to musi Ci coś "zaskoczyć", "kliknąć" w głowie. Zanim to nastąpi to czytasz i czytasz i mało rozumiesz, a po zaskoczeniu objawienie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Co do tych getterów i setterów to trzeba pamiętać, że książka z której rozdział zacytowałem jest pod języki kompilowane i z typowaniem zmiennych oraz metod. W PHP nie mamy tego problemu/dobrodziejstwa (zależy jak patrzeć na to), więc i restrykcje co do getterów i setterów z powyższej książki nie są takie restrykcyjne dla PHP. Ten post edytował jarek_bolo 2.04.2008, 16:36:37 |
|
|
![]()
Post
#13
|
|
Grupa: Zarejestrowani Postów: 793 Pomógł: 32 Dołączył: 23.11.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Co do tych getterów i setterów to trzeba pamiętać, że książka z której rozdział zacytowałem jest pod języki kompilowane i z typowaniem zmiennych oraz metod. W PHP nie mamy tego problemu/dobrodziejstwa (zależy jak patrzeć na to), więc i restrykcje co do getterów i setterów z powyższej książki nie są takie restrykcyjne dla PHP. Tu akurat się mylisz, bo jak zamiast string wyplujesz obiekt, to i tak musisz pozmieniać, bo nawet dynamiczne typowanie nie pomoże. Ogólnie z te "dobrodziejstwa" raczej sprzyjają złemu programowaniu, gdzie nie wiadomo co się dzieje. A OOP ma za zadanie aby kod był czytelniejszy i łatwiej modyfikowalny (tam między innymi). |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 149 Pomógł: 12 Dołączył: 3.03.2008 Skąd: łódzkie Ostrzeżenie: (0%) ![]() ![]() |
Ale ja nie napisałem, że w ogóle nie trzeba się przejmować tylko napisałem, że mniej restrykcyjne co znaczy, że wciąż różne reguły obowiązują.
Ale już np. jak inta na stringa (pod warunkiem, że string liczbowy) sobie możesz wachlować wedle potrzeb. Dobrodziejstwem również tego nie nazywam, bo wolał bym, żeby była ścisła kontrola typów w PHP. |
|
|
![]() ![]() |
![]() |
Aktualny czas: 5.10.2025 - 09:11 |