Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Kod doskonały vs rzeczywistość
Omenomn
post
Post #1





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Cześć, programuję w php, js, html, css, czyli taki standard jeżeli chodzi o strony www, frameworki to: laravel, vue.js, materializecss, może niektórzy mnie kojarzą po nicku.

Spotykam się czasem podczas pisania aplikacji z tym, że w pewnym momencie np. w połowie prac, uświadamiam sobie, że kod jest bardziej zawile napisany niż mógłbym być.
Załóżmy, że chciałem zastosować do kilku funkcjonalności tą samą część kodu i teraz okazuje się, że, aby tą część wykorzystać, komplikuję sobie świeżo pisane rzeczy, żeby je dostosować do tego co już mam. Teraz przyszło mi na myśl, czy aż tak ważne jest to, aby nie powielać kodu, bo w sumie kierując się taką genezą, wszystko mam (tak mi się wydaje) napisane bardziej zawile, ostatecznie tylko po to, żeby wykorzystać istniejące elementy i dostosować do nich nowe.
Przeważnie znajdują się jakieś mini różnice w poszczególnych funkcjonalnościach, które po zsumowaniu robią o wiele większy bałagan niż jakby napisać dla każdej funkcjonalności oddzielnie ten "uniwersalny kod".
Dodatkowo, jeśli teraz chciałbym zmienić rzeczy, które są używane w kilkunastu miejscach, to te kilkanaście miejsc przestaje działać z automatu i muszę je wszystkie poprawiać.
Nie wiem, czy przedstawienie sprawy w tak ogólny i teoretyczny sposób pozwoli Wam się odnieść do tematu, jeśli nie to podam jakiś przykład.

Druga rzecz, to np. 5 lub więcej rozwiązań jednego problemu, gdzie większość wydaje się być niezła.
Jak podejmujecie decyzje, czy na szybko, czy jakoś bardziej analizujecie, bo mi schodzi trochę czasu na takie analizy i jest to dość irytujące?

Mam w sobie jakąś taką cechę, że strasznie drażni mnie jak zaczyna się robić bałagan i zależy mi bardzo na prostocie i przejrzystości tego co piszę, zarówno od strony użytkownika jak i programisty, chciałbym, żeby to co piszę było idealne i jak mi się nie udaje to mam nerwy.

Czy macie podobne problemy, jeśli tak, jak sobie z nimi radzicie?

Może to kwestia doświadczenia, programuję zawodowo już praktycznie 2 lata, więc trochę doświadczenia nabrałem, ale to jednak nie 10 lat:p
Próbuję sobie wytworzyć jakieś standardy i rozwiązania powtarzalnych problemów, czyli np. stosować jeden lub dwa typy formularzy we froncie, na upload filmów mieć jeden sprawdzony sposób po stronie użytkownika i serwera, usuwanie zasobów też działające w konkretny sposób do wielokrotnego stosowania.

Tylko teraz pytanie się pojawia, czy chcąc budować taką swoją bazę rozwiązań nie zostanę w tyle, przez to, że nie zapoznaję się z innymi narzędziami, a pracuję cały czas na tych samych, oczywiście aktualnych wersjach.

Co sądzicie?

Go to the top of the page
+Quote Post
10 Stron V   1 2 3 > »   
Start new topic
Odpowiedzi (1 - 99)
mrc
post
Post #2





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Stosuj dziedziczenie, kompozycję, SOLID i wzorce projektowe. Pisz małe funkcje, zamykaj je w klasach które mają pojedynczą odpowiedzialność. Pisz testy jednostkowe/integracyjne.

Polecam Ci przeczytać (i podumać nad) Clean Code. Jak zaczniesz ogarniać wzorce, i zobaczysz po co tak na prawdę jest singleton czy factory, oraz jakie niebezpieczeństwa się z tym niosą, to zaczniesz pisać ładniej.
Go to the top of the page
+Quote Post
Omenomn
post
Post #3





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Mrc, używam frameworka (Laravel), tam pewna stylistyka pisania jest już narzucona i pewne wzorce są wykorzystywane.
Czytałem kiedyś o różnych wzorcach i robiłem różne przykłady, ale korzystając z frameworka, mam to gotowe, więc się zapomina siłą rzeczy.
Na jakich frameworkah pracowałeś i ile czasu, jeśli można wiedzieć?

Mam na swoim koncie kilka większych aplikacji.
Półtora roku doświadczenia w pracy z Laravel, więc to nie tego typu problemy, żeby stosować obiektowe programowanie (IMG:style_emoticons/default/tongue.gif)

Mimo to dzięki za odpowiedź.

Może na przykładzie:
Mam multiformularze w większości widoków zasobów.
Formularz jest generowany vue.jsem.
Lista zasobów tak samo, więc dane dla listy muszą być w jsonie.
Natomiast dane z formularza mogę przesłać w jednym polu w jsonie, albo normalnie, albo połączyć obie metody, wszystko zależy od rodzaju zasobu.
Jeśli mam dane tekstowe tylko, to json jest okej, nawet kiedy mam obraz do przesłania to html 5 również umożliwia przesłanie go jsonem, ale co np. kiedy chcę przesłać pdf, lub film, wtedy muszę przy wybraniu pliku, przesłać go do tymczasowego folderu ajaxem, najlepiej wyświetlić go w formularzu i jeszcze dodać opcję usunięcia i wybrania ponownie pliku, tak dla każdej pozycji w formularzu, bo jak wspomniałem są to multiformularze.
Już w tym momencie jest kilka możliwości rozwiązania tych zagadnień i załóżmy, że upload jest wykorzystywany w kilku miejscach. Zgodnie z zasadą niepowielania kodu dobrze byłoby stworzyć narzędzie (metody, widok w vue.js) do uploadu filmików i obrazów, ale później przychodzi kolejna funkcjonalność: upload kilku obrazów na raz i to po przez upuszczenie, a nie tylko wybór plików standardowy i co, modyfikować to co mamy, pod następną funkcjonalność komplikując sobie jeszcze bardziej to co i tak już dość zawiłe przez to, że obsługuje i filmy i obrazy?

Cytat
pojedyncza odpowiedzialność
to jest chyba słowo klucz



Ten post edytował Omenomn 4.01.2017, 22:43:40
Go to the top of the page
+Quote Post
mrc
post
Post #4





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


2 lata Zend (edit), 2 lata Kohana, rok Symfony i 3 miesiące Laravel. Framework nie jest tak ważny. Własną logikę biznesową budujesz w każdym fw. Jeżeli jej nie budujesz, to znaczy że robisz to źle. Co do wzorców, pamiętaj że np. samo stworzenie jednolinijkowej statycznej funkcji factory() nie powoduje jeszcze, że tworzysz fabrykę (dobrą fabrykę). Niestety, nawet popularne frameworki czy biblioteki mają sporo takich udziwnień.


--Edit--

Przepatrzyłem swój profil na LinkedIn. Dwa lata zenda poproszę.

Ten post edytował mrc 4.01.2017, 22:21:38
Go to the top of the page
+Quote Post
Omenomn
post
Post #5





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Zenda nie znam, na Kohanie niestety, albo stety dane mi było pracować chwilę, przynajmniej wiem jaka jest kiepska (IMG:style_emoticons/default/tongue.gif) , jak CodeIgniter lub gorzej (IMG:style_emoticons/default/tongue.gif)
Rok Symfony i 3 miesiące Laravel można porównać do mojego półtora roku na Laravel.

Odnośnie tego, że framework nie jest tak ważny nie zgodzę się, wystarczy porównać Kohanę lub CodeIgnitera z Laravelem, albo Symfony - zupełnie inny poziom pisania, choćby przez composera i artisana w laravel, ale to inny temat.

Ten post edytował Omenomn 4.01.2017, 22:52:02
Go to the top of the page
+Quote Post
mrc
post
Post #6





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Nie ma co porównywać doświadczeń. Moje doświadczenia są takie, że wszędzie jest jakaś logika biznesowa, o którą trzeba dbać - pisać testy, refactorować itp. Jeżeli rozmieszczasz wszystko w akcjach i klasach modelowych, to współczuję. Wtedy nie masz logiki.
Go to the top of the page
+Quote Post
Omenomn
post
Post #7





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Umieszczam kod w miejscach uzależnionych od potrzeb, ale w ogromnej przewadze są to jednak kontrolery i modele, używam zdarzeń, middlewarów, jobsów praktycznie nigdy, bo są rzadko potrzebne, walidacji w requestach, jednak request nie zwróci mi obiektu z danymi jakie dostał plus z tablicą z errorami, dlatego mam to w kontrolerach w ostatnich projektach.
Oprócz tego są przecież widoki, tłumaczenia, są configi, migracje, seedy, to wszystko też się składa na logikę aplikacji, jest storage ogarniający pliki, composer, artisan...

Moje rozterki nie są raczej banalne, ale rzeczywiście ta pojedyncza odpowiedzialność w metodach u mnie rzeczywiście trochę na bakier, muszę nad tym popracować.

Go to the top of the page
+Quote Post
mrc
post
Post #8





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Stosuj wyżej podane techniki, a na pewno polepszy się Twój ogólny proces programowania. Do tego staraj się nazywać zmienne lepiej, nie komentuj rzeczy, które w oczywisty sposób wychodzą z kodu. W ogóle, to wszystko co mówię - to jest napisane w Clean Code. Ta książka zmieniła moje postrzeganie kodu, odkąd ją zrozumiałem (!= przeczytałem) nie mam problemów z czytelnością kodu.
Go to the top of the page
+Quote Post
ZenekN
post
Post #9





Grupa: Zarejestrowani
Postów: 419
Pomógł: 5
Dołączył: 7.08.2012

Ostrzeżenie: (0%)
-----


dzięki za informację
Cytat


dochodzi do tego jeszcze odpoczynek (dużo odpoczynku)
Go to the top of the page
+Quote Post
mrc
post
Post #10





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


+1 ZenekN

Do odpoczynku dochodzi uprawianie sportu, życie poza komputerem, wychodzenie z domu i wiele innych, które sprawiają że jesteś świeży.
Go to the top of the page
+Quote Post
Omenomn
post
Post #11





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Okej mrc, zastanawia mnie tylko dlaczego wychodzisz z założenia, że ich nie stosuję, przynajmniej zdecydowanej większości.
Go to the top of the page
+Quote Post
mrc
post
Post #12





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Bo te techniki zapobiegają problemom z nieczytelnym i skomplikowanym kodem - a Ty z tym masz problem. Ok, może źle mówię, może stosujesz (tego nie wiem) - ale coś w takim razie idzie Ci z tym nie tak jak potrzeba.
Go to the top of the page
+Quote Post
Omenomn
post
Post #13





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Sądzę, że większość programistów ma z tym problem nie tylko Ja, są tego może mniej świadomi, miałem do czynienia z kodem różnych ludzi, nawet z większym doświadczeniem od siebie i to chyba oczywiste, nie był idealny.

Dobra ogarnę książkę o czystym kodzie, ale wątpię, że będzie do zastosowania z niej wiele rzeczy na frameworku, obym się mylił, zobaczymy.

Ten post edytował Omenomn 5.01.2017, 11:07:40
Go to the top of the page
+Quote Post
ZenekN
post
Post #14





Grupa: Zarejestrowani
Postów: 419
Pomógł: 5
Dołączył: 7.08.2012

Ostrzeżenie: (0%)
-----


Ogólnie mam podobny problem ale chyba dlatego że jestem dość roztargniony i nie podchodzę do tematu tak jak potrzeba.

Prosta odpowiedź
Cytat
Doświadczenie + nauka = doskonałość kodu


Miałem problem o którym pisałem na forum (jestem samoukiem) zleciłem projekt dobremu programiście na początku byłem zachwycony tym człowiekiem myślałem że jest świetnym programistą.
Tylko pamiętam ciągle słowa "Nie będę ciągle wprowadzał poprawek" czyli że coś było ciągle ze mną nie tak,

Po kilku latach nauki z mojej strony kiedy już znacznie rozumiem wzorce

A wystarczyło wprowadzić prawidłowo relacje w bazie danych np.(n:n) i voila problem rozwiązany.


Czyli tak jak autor wyżej napisał wracajmy do wzorców i analizujmy je krok po kroku

Ten post edytował ZenekN 5.01.2017, 11:52:15
Go to the top of the page
+Quote Post
nospor
post
Post #15





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




@mrc mowisz o tej ksiazce?
http://ricardogeek.com/docs/clean_code.pdf
Go to the top of the page
+Quote Post
mrc
post
Post #16





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


@nospor

Tak, ta książka. Osobiście, wolę drukowaną wersję (IMG:style_emoticons/default/smile.gif) I niebiesko-czarną okładkę (IMG:style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
Omenomn
post
Post #17





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Teraz mam np. problem tego typu, że w systemie, nad którym pracuję, jest kilka zasobów wykorzystujących obrazy i filmy.
Przykładowo:
1. Slider
- upload filmów z wyborem miniaturki z filmu,
- obrazy również z miniaturkami.
2. Galeria
- obrazy z miniaturkami.
3. Klipy
- upload filmów z wyborem miniaturki z filmu,

Zrobiłem to na zasadzie takiej, że każdy zasób, nazwy swoich plików przechowuje we wlasnej tabeli i teraz zastanawiam się, czy nie było by lepiej zrobić dla każdego rodzaju pliku oddzielną tabelę, a w tabelach zasobów przechowywać tylko referencje, wtedy miałbym tylko jeden model od filmów i nie musiałbym ogarniać obsługi plików filmów w sensie uploadu, czy usuwania w kilku miejscach.
Natomiast minus jest taki, że przy wprowadzeniu np. 10 slidów jednocześnie, najpierw muszę dodać filmy do tabeli z filmami, obrazy do tabeli z obrazami, później dopiero wprowadzać same slidy z odpowiednimi referencjami.

(IMG:style_emoticons/default/questionmark.gif)

Ten post edytował Omenomn 5.01.2017, 17:42:39
Go to the top of the page
+Quote Post
vokiel
post
Post #18





Grupa: Zarejestrowani
Postów: 2 592
Pomógł: 445
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Nie jest trochę tak, że szukasz rozwiązania na problemy implementacyjne?

Przykłady, które podałeś nie są raczej przypadkami natury warsztatu, architektury etc. Tylko bardziej szukanie rozwiązań konkretnych zagadnień, a tych w programowaniu może być bardzo dużo. Przy tym wiele z nich będzie poprawnych, nie będzie jednego najlepszego.

Ten post edytował vokiel 5.01.2017, 23:06:59
Go to the top of the page
+Quote Post
Omenomn
post
Post #19





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Właśnie o to mi chodzi, że to moje problemy nie dotyczą tylko warsztatu, a sięgają trochę głębiej, niemniej jednak pozycja http://helion.pl/ksiazki/czysty-kod-podrec...rtin,czykov.htm sądzę, że się przyda i odświeżenie sobie wzorców też.

Pracując na frameworku całą strukturę mam gotową praktycznie. Korzystam z wzorców, nie tworząc ich, przez co zapominam jak działają.
Kiedyś uczyłem się o wzorcach analizując dokładnie przykłady z książki, a na dzień dzisiejszy ta wiedza jakby wyparowała (IMG:style_emoticons/default/ohmy.gif) .
Wychodzi na to, że ta na nauka, była stylu, zakuć, zdać, zapomnieć, a nie cierpię się tak uczyć.
Wiele bardziej wolę zapamiętywać w trakcie używania.

http://helion.pl/ksiazki/php-wzorce-projek...ders,phpwzo.htm

Ten tytuł sobie również przestudiuję, zobaczymy co przyniesie.

Ten post edytował Omenomn 6.01.2017, 10:09:01
Go to the top of the page
+Quote Post
mrc
post
Post #20





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Omenomn może ucz się tak: dowiedz się, czym jest fasada, i zacznij w swoim projekcie (projektach) szukać miejsca, gdzie fasadę można wstawić. Rób refactory i wstawiaj fasady. Później poczytaj czym są fabryki i zastanów się, gdzie u siebie możesz takie fabryki wstawiać.

Oczywiście, do tego trzeba mieć logikę biznesową - zestawy klas które realizują algorytmy, połączenia z bazą czy innymi elementami jak np. curl, guzzle, websockety, systemy kolejkowe.
Go to the top of the page
+Quote Post
zegarek84
post
Post #21





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


z góry przepraszam za lekki spam, ale z tematu pod KOD zajebiście podchodzi ;D
zabrakło mi doświadczenia i ostrożności - oby i Tobie nie zabrakło doświadczenia i ostrożności ;D
Go to the top of the page
+Quote Post
Pyton_000
post
Post #22





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Nie ma idealnego kodu, ale za to jest Refaktoryzacja. Magiczne i jakże przydatne słowo. Polecam. I nie na uraaaa za wszystko się brać, tylko małymi kroczkami powoli, do przodu.
Go to the top of the page
+Quote Post
com
post
Post #23





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Omenomn

Pierwsze co zrób to zapomnij o frameworku. Nie ważne czy używasz Laravela, Zenda, Symfony, to tylko baza dla resposne i request i tam się sprawdza, ale nie jako logika biznesowa. Twój model biznesowy, który powinieneś poznać zanim tak naprawdę zabierzesz się za tworzenie czegokolwiek, nie zależy od języka programowania, a tym bardziej o jakieś wymyślonej w nim implementacji w postaci Frameworka. Myślenie skoro gość X od fw y robi to tak to ja tez mogę, jest bardzo zgubne. Nie da się stworzyć gotowca na tyle uniwersalnego, żeby dla każdego problemu jaki istnieje dało się w nim stworzyć najlepsze rozwiązanie. Uniwersalne są tylko wzorce projektowe. Dlatego analizując Twój przypadek z dużym prawdopodobieństwem mogę stwierdzić, że zacząłeś typowo, mam do zrobienia projekt X, no to stawiam nowa instancje Laravela, potem co, pewnie baza danych. Po tygodniu/ miesiącu, okazuje się ze czegoś zapomniałeś nie uwzględniłeś, bazę trzeba zmienić i pól kodu. No i pojawiają się takie problemy jak tym masz, a wszystko przez to, że zacząłeś od złej strony. Zanim napisałeś pierwsza linijkę kodu powinieneś poznać swój model domenowy, jak już go poznasz to dopiero wtedy do niego dobierać odpowiednie narzędzia które pozwolą Ci go stworzyć łatwiej, a nie na odwrót. Wtedy dostrzeżesz znacznie więcej, kod będzie dużo bardziej czysty i reuzywalny niż wcześniej.
Go to the top of the page
+Quote Post
Omenomn
post
Post #24





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Sądzę, że umniejszasz trochę frameworkom jednak.

Już wymyśliłem jak ogarnąć to uploadowanie, żeby miało sens i wykorzystałem wzorzec dekorator do tego.
Przykładowe przesłanie pliku wygląda tak:

  1. $thumbnail = new Property(new ContentImage(new Thumbnail(new Encoder(new File())));
  2. $thumbnail->make($request->file);


1. Property - pobieranie właściwości pliku (nazwa, path, rozszerzenie).
2. ContentImage - pobiera treść pliku.
3. Thumbnail - pomniejsza treść.
4. Encode - określa rozszerzenie.
5. File - tworzy plik.

Tylko mam teraz taki problem, że chciałbym w każdym z tych obiektów mieć dostęp do właściwości pobranych w obiekcie Property i nie mam pomysłu dobrego jak to zrobić.
Encode potrzebuje rozszerzenie, File potrzebuje nazwę pliku, ContentImage wymaga ścieżkę.

Mógłbym przekazywać właściwości dalej w każdym wywołanym obiekcie:
  1. $this->maker->properties = $this->properties

jednak to trochę powielanie kodu, mam parę pomysłów, ale żaden jakiś specjalny, a Wy?

Spróbuję się wspomóc obserwatorem.

Ten post edytował Omenomn 9.01.2017, 19:04:35
Go to the top of the page
+Quote Post
com
post
Post #25





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Sądzę, że umniejszasz trochę frameworkom jednak.


Nie, framework to tylko narzędzie coś jak IDE, i tak samo jak one może być lepsze lub gorsze, ale to tylko narzędzie ułatwiające prace, nie sprawi, że kod się sam napisze i będzie dobrej jakości.

Cytat
wykorzystałem wzorzec dekorator


Jesteś pewny, że dobrze go zrozumiałeś?

https://github.com/domnikl/DesignPatternsPH...tural/Decorator
Go to the top of the page
+Quote Post
Omenomn
post
Post #26





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Cytat
Jesteś pewny, że dobrze go zrozumiałeś?


Tak, a według Ciebie nie?

http://blogophp.com/2009/08/16/dekorator/#more-40
http://stackoverflow.com/questions/1234554...e-re-sizing-etc

Cytat
Nie, framework to tylko narzędzie coś jak IDE, i tak samo jak one może być lepsze lub gorsze, ale to tylko narzędzie ułatwiające prace, nie sprawi, że kod się sam napisze i będzie dobrej jakości.


Tylko, żeby nauczyć się dobrych praktyk na frameworku potrzeba kupę czasu. Jak ktoś jest oblatany w jednym to nie siądzie na inny i po dwóch miesiącach nie będzie w nim wymiatał, na poznanie frameworka i różnych w nim patentów trzeba czasu.
Framework to nie tylko narzędzie, to w pewnym stopniu narzucona struktura i pewne podejście do programowania.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #27





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Dekotator tutaj jest definitywnie złym rozwiązaniem skoro obiekty potrzebują zależności z innych dekoratorów.

Dekoratorem może być tutaj tylko Thumbnail bo on faktycznie coś tam robi na źródłowych danych.
Go to the top of the page
+Quote Post
Omenomn
post
Post #28





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Dobrym rozwiązaniem jest, do przekazywania atrybutów wykorzystałem obserwator, więc mam kombo dekorator-obserwator i jestem Hardkorem (IMG:style_emoticons/default/biggrin.gif)
Go to the top of the page
+Quote Post
mrc
post
Post #29





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


Omenomn, skoro coś Ci w decoratorze nie pasuje, to znaczy że nie jest to dobre rozwiązanie.

Co do frameworków. Możesz być specjalistą w Laravel i 5 lat tłuc jego dobre praktyki. W pomiędzy czasie świat się zmieni. Laravel przestanie mieć większość udziałów na rynku. Będziesz miał problemy w znalezieniu pracy, bo umiesz pisać tylko tak jak uczył Laravel. Moim zdaniem programista to osoba, która nie przyzwyczaja się do rozwiązań, ma otwarty umysł na nowe/inne technologie, języki.

Tak jak wyżej koledzy pisali, fw to tylko fw. Request-Response + MVC. Tak samo, jak PHP to tylko PHP i może się okazać, że za kilka lat będzie trzeba się przebranżowić, albo chociażby zmienić języki. Co wtedy?
Go to the top of the page
+Quote Post
Tomplus
post
Post #30





Grupa: Zarejestrowani
Postów: 1 885
Pomógł: 231
Dołączył: 20.03.2005
Skąd: Będzin

Ostrzeżenie: (0%)
-----


10 lat temu ktoś powiedział, że trzeba porzucić PHP, bo z tego języka już nic nie będzie.
Go to the top of the page
+Quote Post
Omenomn
post
Post #31





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Dekorator to dobre rozwiązanie, ale nie wystarczające, więc musiałem je połączyć z innym.
Swoją drogą zadanie dla Was.
Jak we wzorcu dekorator przekazywać pomiędzy obiektami atrybuty elementu dekorowanego, tak, żeby każda klasa miała do nich dostęp i mogła je modyfikować i, żeby każdy obiekt widział te zmiany.

  1. Co do frameworków. Możesz być specjalistą w Laravel i 5 lat tłuc jego dobre praktyki. W pomiędzy czasie świat się zmieni. Laravel przestanie mieć większość udziałów na rynku. Będziesz miał problemy w znalezieniu pracy, bo umiesz pisać tylko tak jak uczył Laravel. Moim zdaniem programista to osoba, która nie przyzwyczaja się do rozwiązań, ma otwarty umysł na nowe/inne technologie, języki.
  2.  
  3. Tak jak wyżej koledzy pisali, fw to tylko fw. Request-Response + MVC. Tak samo, jak PHP to tylko PHP i może się okazać, że za kilka lat będzie trzeba się przebranżowić, albo chociażby zmienić języki. Co wtedy?


Powiem Ci tak, jeśli pracujesz na Symfony, albo Laravel, przesiądź się na CodeIgnitera, albo Kochane i zacznij pisać takie same systemy.
Jeżeli nie sprawia Ci to różnicy, to okej, nie wszystkim musi zależeć na jakości pracy, ale jeśli komuś zależy to rękami i nogami będzie się bronił przed taką przesiadką, więc to nie tylko narzędzie request-response + mvc, bo configi, routing, seedy, migracje, storage, env, blade, eventy, jobsy, composer, paczki, artisan, helpery, walidacja, translatory itd.

Więc zdecydowanie uproszczacie, CodeIgniter i Kochana nie ma nawet połowy z tego.
Framework to owszem narzędzie, ale można używać samego młotka, albo wielu wyspecjalizowanych narzędzi, jakich dostarczają dobre frameworki.

  1. W pomiędzy czasie świat się zmieni. Laravel przestanie mieć większość udziałów na rynku. Będziesz miał problemy w znalezieniu pracy, bo umiesz pisać tylko tak jak uczył Laravel.


To jest właśnie myślenie ludzi, którzy uczą się miliona rzeczy, a w żadnej nie są specjalistami.
Każdy z osobna ma wpływ na rynek, jeśli zmieniasz to co lubisz na coś czego nie chcesz robić, tylko po, żeby znaleźć pracę, to dostaniesz pracę, ale się nie rozwijasz i w dłuższym czasie jesteś na minus.

Ja np. nienawidzę wordpressa, bo jest zaprzeczeniem obiektowego programowania i ukazuje hipokryzję ludzką, ponieważ wszyscy mówią o obiektowym pisaniu kodu, a później jadą na wordpressie, który jest funkcyjny. Jednak jeśli lubiłbym worpressa, to śmiało mógłbym się w nim rozwijać i cisnąć cały czas, a zmienianie co 4 miesiące cmsa na joomlę, albo drupala, albo jeszcze coś innego, byłoby staniem w miejscu, bo w żadnym z tych narzędzi nie byłbym specjalistą.

Jeżeli siedzi się w czymś np. 2 lata i uzna się, że już osiągnęło się poziom mastera, wtedy można zmienić framework lub narzędzie i można o sobie powiedzieć np. "jestem specjalistą w Laravel, robiłem na nim mnóstwo rzeczy i znam wiele rozwiązań", a nie mówić: "znam Laravela, pracowałem na nim 3 miesiące, zrobiłem jeden mały projekt" - nie znasz, liznąłeś.

Jest takie powiedzenie: "jak coś jest do wszystkiego, to jest do niczego".

Ten post edytował Omenomn 10.01.2017, 09:34:46
Go to the top of the page
+Quote Post
daro0
post
Post #32





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Pracuję w Kohana 3.2/3.3 od 2 lat. A nie starszej wersji na linii 2.x. W standardzie pobierając to z githuba Kohana 3.3 ma tylko to co jest potrzebne do realizacji w miarę prostych aplikacji, resztę trzeba albo pobrać z innych repo na githubie (a są ciekawe moduły), albo po prostu napisać samemu. Wymagana jest tu jednak gruntowna znajomość tego jak działa ten FW. Bardzo przyjemnie się z tym frameworkiem pracuje. Na pewno nie tylko ja mam taką przyjemność. Jest jeszcze na pewno jakaś wąska grupa programistów PHP która się tym zajmuje.

Ale do czego zmierzam. Dobry kod? Rzecz w tym że KO3 ma dość specyficzne założenia, między innymi CFS, inny styl nazewnictwa (oparty o underline a nie camelCase), jest inaczej niż w Laravelu czy tam Symfony. Jest to dość prosty, lekki i szybki FW. Ale wystarczy przejrzeć inne oprócz Symfony i Laravela, np. Yii, FuelPHP i jeszcze parę innych. I co każdy inny to i inna filozofia i przyjęte założenia w architekturze.

Jakim to trzeba być ekspertem żeby (i tu bardzo istotna sprawa) we właściwy i praktyczny sposób stosować te różne wzorce typu dekorator czy tam inne? A pytam o to dlatego, że po roku jak się spojrzy na to co się pisało wcześniej (i tu nie ważne na jakim FW czy też bez niego) to można mieć wrażenie, że wcześniejszy kod można było napisać inaczej. I najprawdopodobniej lepiej albo bardziej praktycznie, bo człowiek się uczy.

Ten post edytował daro0 10.01.2017, 11:45:22
Go to the top of the page
+Quote Post
Omenomn
post
Post #33





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Dokładnie, a jakim trzeba być ekspertem, żeby traktować framework jako młotek, że mogę się z jednego przesiąść na drugi i zrobić w nim miazgę.

Trzeba by na każdym jednym z tych młotków pracować po minimum dwa lata i mieć je ogarnięte do maksimum możliwości.
Go to the top of the page
+Quote Post
mrc
post
Post #34





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


@Omenomn

To co mówisz, składa się na to, co już wcześniej pisałem (inny wątek): Ja uczę się programować, a Ty uczysz się używać czegoś, co ktoś zaprogramował.
Go to the top of the page
+Quote Post
com
post
Post #35





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Dekorator to dobre rozwiązanie, ale nie wystarczające, więc musiałem je połączyć z innym.


No to oznacza, że coś jest nie tak z użyciem jego w tym miejscu, skoro zamiast rozwiązać problem pojawił się nowy wynikający z użycia tego wzorca, a dekorowanie dekoratorów, można ale to raczej mija się z celem.

Cytat
Ja uczę się programować, a Ty uczysz się używać czegoś, co ktoś zaprogramował.


I to jest dobre podsumowanie. Bo tu wcale nie chodzi o to czy się przesiadasz z jednego na drugi, napisałem są lepsze i gorsze narzędzia(frameworki). Po jakimś czasie stawianie projektu opanujesz do perfekcji, ale fw za Ciebie dobrego, czystego kodu nie napisze. Jasne masz masę helperów, które dostarcza w pudełku, ale one są uniwersalne, a nie stworzone dla Twoich potrzeb. Skupiając się tylko wokoło nich, produkt który powstanie będzie dostosowany do narzędzia które użyłeś i automatycznie przestanie być uniwersalny. Używasz Laravela, wiec jeśli znasz trochę jego historii tam zdarzały się BC Breaki co wersje, wiec automatycznie w krótkim czasie rośnie w projekcie dług technologiczny, bo nie wielu stać na to, żeby co nowe wydanie zmieniać projekt i dostosowywać pod nowsze jego wersje. Dlatego u nas na forum znajdziesz osoby pracujące np w Zend 1 chociaż mamy już 3, podobnie jest z innymi tego typu narzędziami.
Go to the top of the page
+Quote Post
daro0
post
Post #36





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Cytat(Omenomn @ 9.01.2017, 17:48:48 ) *
  1. $thumbnail = new Property(new ContentImage(new Thumbnail(new Encoder(new File())));
  2. $thumbnail->make($request->file);


Nie potrafię zrozumieć po co tyle zachodu. No ale spoko, to Twoje podejście.
Ale np. KO3 daje coś takiego:
https://kohanaframework.org/3.2/guide/api/Upload

no i jeszcze do obrazków (i np. zmiany rozmiaru)
https://kohanaframework.org/3.2/guide/api/Image

W tym sensie framework ma swoje helpery do tych operacji. Laravel i inne pewnie też.

Bardzo chciałbym wiedzieć jak tego typu rozwiązania (i wzorce jakich użyjesz) przekładają się na praktykę
i czy nie będzie problemów z kodami.
Go to the top of the page
+Quote Post
Omenomn
post
Post #37





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Chodzi o to, że kod ma rozwiązywać między innymi takie problemy:
- upload jakiegokolwiek pliku
- upload obrazka
- upload minaturki
- upload obrazka z minaturką
- upload wideo
- upload wideo z miniaturką
- upload wideo z trzema miniaturkami
- plus mogą wystąpić dodatkowe rodzaje plików lub inne konfiguracje

Teraz:
- do operacji na plikach mam bibliotekę
- do operacji na obrazach mam bibliotekę
- i do operacji na filmach mam bibliotekę

Wszystkie wykorzystuję w obu rozwiązanich.

Zwyczajne podejście to:
- Robię kontroler do uploadu plików z metodami np.: uploadVideo, uploadVideoWithThumbnail, uploadImage, uploadImageWithThumbnail i to jest okej, ale:
- muszę pobierać za każdym razem atrybuty pliku:
'name' => $file->getClientOriginalName(),
'extension' => $file->getClientOriginalExtension(),
'path' => $file->getRealPath(),
- muszę za każdym razem ustawiać kontent:
$content = GrImage::make($path); lub $content = \File::get($file); w zależności od typu pliku
- muszę kodować:
$content->encode($extension); lub nie, jeżeli to video
- i wreszcie wrzucić plik:
if ($disk->exists($name))
$disk->delete($name);

$disk->put($name, $content);

Opisałem najprostszą konfigurację.
Standardowym podejściem mogę wszystkie metody przechowywać w kontrolerze i w zależności od potrzeb dopisywać następne (co już jest złym podejściem, bo kod powinno się nadbudowywać, a nie zmieniać już napisany).

- function putFile()
- function getProperties()
- function resizeToThumbnail()
- function makeThumbnail()
- function makeVideo()
- function getThumbnailFromVideo()
itd. itd...

Przez to mam milion metod w kontrolerze i robi się mega bałagan.

Natomiast podejście dekoracyjne wygląda tak:
- zwykły obraz:
$image = new Property(
new ContentImage(
new Image(
new Encoder(
new File))));
$image->make($request->file);
- miniaturka:
$thumbnail = new Property(
new ContentImage(
new Thumbnail(
new Encoder(
new File))));
$image->make($request->file);
- video:
$video = new Property(
new Content(
new Video(
new File)));
$video->make($request->file);
- video z miniaturką
$video = new Property(
new ThumbnailFromVideo(
new Content(
new Video(
new File))));
$video->make($request->file);
- video z trzema miniaturką
$video = new Property(
new ThumbnailFromVideo(
new GetThumbnail(
new ThumbnailFromVideo(
new GetThumbnail(
new ThumbnailFromVideo(
new GetThumbnail(
new Content(
new Video(
new File))));

lub
$video = new ThreeThumbnailsFromVideo(
new Content(
new Video(
new File))));
$video->make($request->file);

Mogę to nadbudowywać jak mi się żywnie podoba. Dodatkowo wszystkie te klasy są obserwatorami obiektu przechowującego konfigurację pliku, więc jeśli będę chciał dodać obiekt zmieniający nazwę Renamer

$video = new ThreeThumbnailsFromVideo(
new Content(
new Video(
new Renamer(
new File)))));
$video->make($request->file);

Wtedy wszystkie obiekty dostają o tym informację (Obserwator).

Ostatecznie dekorator wywołuję przez klienta, więc stworzenie miniaturki będzie wyglądało tak:
use Acme\MakerClients\Thumbnail;

$thumbnail = new Thumbnail;
$thumbnail->make($request->file);

i tak z każdą zawartością.

Chyba macie zbyt sztywne podejście do wzorców, czemu mam stosować jeden, skoro mogę połączyć dwa, to jest o wiele bardziej konstruktywne i ciekawe niż trzymanie się konkretnego wzorca jak sztywnych zasad 10-ciu przykazań.

Ten post edytował Omenomn 10.01.2017, 19:11:09
Go to the top of the page
+Quote Post
Pyton_000
post
Post #38





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Skoro chcesz obsługiwać upload po typie pliku to Factory będzie lepszym rozwiązaniem lub Strategia.
Go to the top of the page
+Quote Post
daro0
post
Post #39





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Też mi się wydaje że coś na wzór tego mogło by był dobrym rozwiązaniem. Np. tak:

  1. $files = $_FILES['attachment'];
  2.  
  3. //upload zdjęć
  4. $result = Uploader::factory('Image')
  5. ->data($files)
  6. ->execute();
  7.  
  8. //upload filmów
  9. $result = Uploader::factory('Video')
  10. ->data($files)
  11. ->execute();
  12.  
  13. //upload muzyki
  14. $result = Uploader::factory('Music')
  15. ->data($files)
  16. ->execute();
  17.  


W tym założeniu (tylko że ja biorę pod uwagę KO3) musiałbym mieć w katalogu application/classes podkatalog Uploader a w nim odpowiednio:
Image.php
Video.php
Music.php

i wszystkie te klasy musiałyby rozszerzać:

  1. abstract class Uploader {
  2.  
  3. public static function factory($name)
  4. {
  5. $class = 'Uploader_'.$name;
  6. return new $class;
  7. }
  8.  
  9. }


która to klasa musiałaby być w katalogu classes

Odrębna sprawa to identyfikacja co i czym jest bo po rozszerzeniu pliku to dość prosta sprawa.
Go to the top of the page
+Quote Post
Omenomn
post
Post #40





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Po typie pliku jest tylko jeden upload, który ma zdecydować po rozszerzeniu, czy uploadować wideo z thumbnailem, czy obraz z thumbnailem dla sliderów, ale rzeczywiście, może do decyzji o tym użyję innego wzorca.

Jednak to co pokazałeś daro0 w jaki sposób wykorzystuje kod klas poniższych, jak w dekoratorze?

Czyli, że upload obrazu wykorzystuje ten sam kod do uploadu pliku co wideo:

if ($disk->exists($name))
$disk->delete($name);

$disk->put($name, $content);

i jak w jednym miejscu ogarniesz metodę do pobrania atrybutów pliku, żeby zrobić z nim później co się chce?

Jak to rozwiążesz strategią lub factory?
Go to the top of the page
+Quote Post
Pyton_000
post
Post #41





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Przede wszystkim obsługa zapisu/usuwania pliku powinna być oddelegowana do oddzielnej klasy np. StorageHandler(new LocalStorage());
I tam sobie dajesz np.

$storage->store((File)$file);

Czyli defacto masz 2 fabryki: 1 do obsługi pliku samego w sobie a 2 do zapisu/odczytu/usuwania.

Wynikiem 1-szej powinien byc obiekt z którego pobierzesz sobie jakieś tam atrybuty. Wew. niego możesz mieć obiekt np. miniaturki itd itd.
Go to the top of the page
+Quote Post
daro0
post
Post #42





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Zakładam że są trzy klasy: Uploader_Image, Uploader_Video oraz Uploader_Music, trzy osobne pliki PHP. Zakładam że rozszerzenie będzie w jakiś sposób ustalane na podstawie tego co jest w $_FILES['attachment']['name'] i jest wyciągane i na podstawie np tego:

  1. $files = $_FILES['attachment'];
  2. $path = $_FILES['attachment']['name'];
  3. $ext = pathinfo($path, PATHINFO_EXTENSION);
  4.  
  5. $uploaders = array(
  6. 'jpg' => 'Image',
  7. 'png' => 'Image',
  8. 'gig' => 'Image',
  9. 'bmp' => 'Image',
  10. 'avi' => 'Video',
  11. 'mp4' => 'Video',
  12. 'mp3' => 'Music',
  13. );
  14.  
  15. if (array_key_exists($ext, $uploaders))
  16. {
  17. $uploader = $uploaders[$ext];
  18. $result = Uploader::factory($uploader)
  19. ->data($files)
  20. ->execute();
  21. }
  22. else
  23. {
  24. // jakis komunikat
  25. }
  26.  


To tylko jeden z możliwych sposobów.
Go to the top of the page
+Quote Post
Omenomn
post
Post #43





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


ale Wy się cały czas rozszerzeniem zajmujecie, a to jest tylko jeden z problemów i to nie aż tak istotny, nie kumacie, czy nie wiem co...

Opisałem to wcześniej.

Jak daro0 chciałbyś utworzyć tym rozwiązaniem sam obraz, albo obraz z miniaturką?
albo samo wideo, albo wideo z miniaturką, albo wideo z trzema miniaturkami?

Czy dekoracja, sama w sobie nie nasuwa się na myśl?

Masz plik i go dekorujesz, "tu mu zmienię rozmiar, tu mu zmienię rozszerzenie, tu mu zmienię nazwę, tu jeszcze coś innego mu zmienię" (IMG:style_emoticons/default/biggrin.gif)

i tak sobie zmieniam jak mi się podoba.

Tak w ogóle jak czytam te tutoriale z nazwami klas, metod i zmiennych po polsku, to od razu wiem, że taki tutorial to śmieć.
Jaki dobry programista używa polskich nazw w programowaniu.

Ten post edytował Omenomn 10.01.2017, 21:48:42
Go to the top of the page
+Quote Post
Dejmien_85
post
Post #44





Grupa: Zarejestrowani
Postów: 251
Pomógł: 23
Dołączył: 23.04.2013

Ostrzeżenie: (0%)
-----


Sądzę, że każdy ma podobne rozterki do Twoich. (IMG:style_emoticons/default/wink.gif)

Pisząc prywatne projekty zawsze biorę pod uwagę "czystość kodu" do "czasu pracy".

Każdy ma jakieś wyobrażenie o tym jaki powinien być kod, a także każdy ma swoje nawyki. Wydaje mi się, że większość z nas ma lepsze wyobrażenie o swojej pracy, niż ona w rzeczywistości wygląda - a widać to najlepiej przy prywatnych projektach. ; )

Uczymy się wzorców, mówimy sobie, że testy i czystość kodu (znana książka "Czysty Kod") są ważne, ale gdy zaczynamy pracę nad jakimś projektem, to nie zawsze trzymamy się idealnie swoich teorii.

Ja osobiście ciągle podejmuję decyzje typu: "zostawić tutaj drobny bałaganik do posprzątania na później czy posprzątać już teraz?".

Najważniejsze to najpierw nauczyć się pokory - pamiętam doskonale czas, kiedy uczyłem się bardzo dużo nt. programowania, wzorców, czystego kodu, testowania. Sam siebie uważałem za wybitnego programistę.
Jednak podczas pewnego projektu śpieszyłem się z dostarczeniem pewnego oprogramowania. Po dwóch miesiącach pisania kodu nagle zdałem sobie sprawę, że złamałem prawie wszystkie zasady, w jakie głęboko
wierzyłem - dostrzegłem wtedy jaką byłem żałosną istotą... ; )

Pomyślałem sobie - Damianie, Ty tępy ch#&$^, uważasz się za tak dobrego programatora, a tutaj tworzysz takie g$%#$, że smród rozchodzi się po całości.

Pamiętam także jedną aplikację, dość dużą. Pisałem ją przez jakiś rok (prywatny projekt). Po długiej przerwie bylem zmuszony do pewnych modyfikacji, zajrzałem więc do starego kodu i...
ni cholery nie mogłem się połapać w jednej części kodu. Po prostu stworzyłem tak cholernie skomplikowany kawałek kodu, że musiałem przez prawie dwie godziny go analizować, aby połapać się
o co w nim chodziło.

Jaka jest moja rada? Nie ma kodu doskonałego. Goni nasz wszystkich czas. Nawet jeśli masz dobre zamiary, to często robisz małe grzeszki. Małe grzeszki nie są złe, o ile się nie rozrastają.

Ze swojej strony powiem tylko tyle, że wszystko zależy od nastroju i nastawienia.

Pisałem prywatne projekty, w których naprawdę działałem według swoich zasad, tj. pełne skupienie na "czystości" i "otestowaniu".
Wielbię Wujka Boba, więc tworzyłem soft otestowany w 90-kilku procentach. Siedziałem nad nim długo, starałem się go ciągle refaktoryzować, nawet gdy
niektóre rozwiązania zabierały dużo czasu. Widziałem tego efekty. Widziałem, że warto mieć testy.

Ale... nawet teraz po latach doświadczenia potrafię się śpieszyć i tworzyć oprogramowanie "na szybko", bez testów, z "małymi grzeszkami".

Ważne, aby mieć jakieś standardy.

Gdy łamię zasady, wtedy coś za uchem mówi mi "grzeszysz". Popełniam grzeszki. Ale mam jednak pewne "standardy grzeszenia".
Mogę pisać kod, który nie jest otestowany. Mogę czasem wprowadzić jakąś mała zawiłość. Ale jesli widzę, że coś staje się zbyt
skomplikowane, albo zbyt nieczytelne, wtedy włącza się alarm i wprowadzam porawki.

W końcu większość z nas wie jakie problemy wiążą się z nieczystym kodem. Doświadczyliśmy tego.
Wiemy co robić, aby nie kopać pod sobą dołków. Czasem grzeszymy. To normalne.

Ważne, aby mieć jakieś normy.
Go to the top of the page
+Quote Post
sazian
post
Post #45





Grupa: Zarejestrowani
Postów: 1 045
Pomógł: 141
Dołączył: 19.09.2006
Skąd: B-tów

Ostrzeżenie: (0%)
-----


Cytat(Omenomn @ 10.01.2017, 21:38:41 ) *
Tak w ogóle jak czytam te tutoriale z nazwami klas, metod i zmiennych po polsku, to od razu wiem, że taki tutorial to śmieć.
Jaki dobry programista używa polskich nazw w programowaniu.


Zajrzy do baz danych takich programów jak optima lub xl od comarch-a, subiekt od insert-tu czy wf-mag od wapro.
W ich bazach nie znajdziesz słowa po angielsku, a nie ukrywajmy są to jedne z większych firm w Polsce.
Idąc Twoim tokiem rozumowania ich produkty które zarabiają pewnie niezłe melony to śmieci....
Ale to temat na nieco inną rozmowę (IMG:style_emoticons/default/wink.gif)
Go to the top of the page
+Quote Post
Omenomn
post
Post #46





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Chcesz mi wmówić, że stosowanie polskiego nazewnictwa jest okej?

Zarabianie oprogramowania, nie jest równe z tym, że jest dobrze napisane.
Strony na wordpressie też zarabiają (IMG:style_emoticons/default/biggrin.gif)

Ten post edytował Omenomn 10.01.2017, 22:49:31
Go to the top of the page
+Quote Post
com
post
Post #47





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Jak daro0 chciałbyś utworzyć tym rozwiązaniem sam obraz, albo obraz z miniaturką?
albo samo wideo, albo wideo z miniaturką, albo wideo z trzema miniaturkami?

Omenomn
A Twoim gdzie niby stwierdzę, że mam wybrać te a nie inne rozwiązanie.

Cytat
Czy dekoracja, sama w sobie nie nasuwa się na myśl?

Nie, za to strategia już tak (IMG:style_emoticons/default/wink.gif)

Przyjrzyjmy się definicji:
Dekorator, pozwala na dynamicznie dodawanie nowych funkcjonalności do istniejących klas podczas działania programu.

Strategia, tworzy wspólny interfejs z dozwolonymi operacjami oraz listę klas implementujących dany interfejs dostarczających konkretne algorytmy.

Factory, dostarcza interfejs do tworzenia obiektów nieokreślonych typów, pozwala podklasom zdecydować, jakiego typu będzie obiekt

I powiedz mi gdzie tu pasuje Twój kod. Co z tego że udekorujesz sobie jakaś klasę jak nie stwierdzisz, że w tym konkretnym miejscu ona ma być tak udekorowana. Pomijając fakt, że zamieniłeś znaczenie modelu w Twoim rozwiązaniu, bo teraz dekorujesz obiekt własnościowi a to miał być podobno upload.
Go to the top of the page
+Quote Post
Omenomn
post
Post #48





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


upload, a przed uploadem odpowiednio się plik, a teraz uwaga ------ dekoruje.

Cytat
Dekorator, pozwala na dynamicznie dodawanie nowych funkcjonalności do istniejących klas podczas działania programu.


Własności też, nie tylko funkcjonalności.

Cytat
I powiedz mi gdzie tu pasuje Twój kod. Co z tego że udekorujesz sobie jakaś klasę jak nie stwierdzisz, że w tym konkretnym miejscu ona ma być tak udekorowana. Pomijając fakt, że zamieniłeś znaczenie modelu w Twoim rozwiązaniu, bo teraz dekorujesz obiekt własnościowi a to miał być podobno upload.


Stwierdzę. Kontroler ma metodę przypisaną do routingu, więc jak wyślę coś postem na strona.com/image, to mam w kontrolerze metodę image(), w której wywołuję $image = new PropertyGeter(
new ContentImageGeter(
new ImageNoResizer(
new Encoder(
new FilePuter))));
$image->make($request->file);
i mam upload obrazu,

jak chcę obraz z jego miniaturką to strona.com/image-with-thumbnail, metoda imageWithThumbnail()
$image = new PropertyGeter(
new ContentImageGeter(
new ThumbnailResizer(
new Encoder(
new FilePuter))));
$image->make($request->file);

itd.

Nie potrzebuję wzorca decydującego o tym jaki plik ma zostać stworzony, bo doskonale wiadomo jaki.

http://stackoverflow.com/questions/1234554...e-re-sizing-etc

Ten post edytował Omenomn 10.01.2017, 23:15:07
Go to the top of the page
+Quote Post
com
post
Post #49





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Własności też, nie tylko funkcjonalności.

To nie moja definicja, ok własności tez mogą być. Ale nie to jest ważne a słowo nowe własności/funkcjonalności.

Spójrz na swój kod i co można tam zauważyć


$image = new PropertyGeter(
new ContentImageGeter(

new ImageNoResizer(
new Encoder(
new FilePuter))));



$image = new PropertyGeter(
new ContentImageGeter(

new ThumbnailResizer(
new Encoder(
new FilePuter))));


95% tego kodu to tak naprawdę spójny interfejs, który mógłby tworzyć jedna całość, a reszta to już tylko odpowiedni wybór ścieżki dla algorytmu.
Cytat
Stwierdzę. Kontroler ma metodę przypisaną do routingu, więc jak wyślę coś postem na strona.com/image

No czyli masz jakaś strategie o niespójnym interfejsie do obsługi i daj to komuś żeby zrozumiał taki kod, a potem użył z nowym schematem bo klient wymyślił sobie że teraz nie 3 miniaturki a 4.

Załóżmy, że piszesz testy, jak taki kod przetestować skoro nie wiesz co tak naprawdę uzyskasz, bo w zależności od tego jak go wywołasz otrzymasz inny wynik, i co jeśli o czymś po drodze zapomnisz, bo dodałes nowe funkcjonalności i zamiast tych 5 dekoratorów masz już ich 20/30/100.

Ten post edytował com 10.01.2017, 23:27:17
Go to the top of the page
+Quote Post
Omenomn
post
Post #50





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


No to wtedy robi się nakładkę.

Cytat
Spójrz na swój kod i co można tam zauważyć


  1. $image = new PropertyGeter(
  2. new ContentImageGeter(
  3. new ImageNoResizer(
  4. new Encoder(
  5. new FilePuter))));
  6.  
  7.  
  8. $image = new PropertyGeter(
  9. new ContentImageGeter(
  10. new ThumbnailResizer(
  11. new Encoder(
  12. new FilePuter))));


Co można zauważyć? że za każdym razem jest pobierana właśność do pliku i ustalany content, kodowanie i zapis?

Sprawdź sobie jak wygląda upload video z miniaturką:
  1. $video = new PropertyGeter(
  2. new ThumbnailFromVideoCuter(
  3. new ContentGeter(
  4. new FilePuter)));
  5. $video->make($request->file);

lub samo video. czy inny plik:
  1. $file = new PropertyGeter(
  2. new ContentGeter(
  3. new FilePuter));
  4. $file->make($request->file);


i jakie teraz własności kodu wywnioskowałeś?

Cytat
No czyli masz jakaś strategie o niespójnym interfejsie do obsługi i daj to komuś żeby zrozumiał taki kod, a potem użył z nowym schematem bo klient wymyślił sobie że teraz nie 3 miniaturki a 4.


Każdy framework tak ma, nie wiesz?

Ten post edytował Omenomn 10.01.2017, 23:40:04
Go to the top of the page
+Quote Post
com
post
Post #51





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


No dokładnie te same dla tej grupy wideo, tak samo będzie dla audio i czego sobie tam jeszcze nie wymyślisz.

Każda grupa to jakiś schemat, który dodatkowo rozbudowujesz i zależnie od tego jak skomponujesz te obiekty taki uzyskasz context, ale dla każdej operacji będzie on inny choć operujesz dalej na tym samym obiekcie, wiec oczekujesz dostać ten obiekt, a nie cokolwiek.

Cytat
Każdy framework tak ma, nie wiesz?


Wskaż mi gdzie framework ma coś nie udokumentowane i nie wiesz co uzyskasz jak wykonasz dany fragment jego kodu.

To trochę tak jakbyś z kota chciał zrobić mysz

To jak się uparłeś już na te twoje "dekoratory" to zrób chociaż Fasade, żeby to można było produktywnie wykorzystać. Tylko to jest trochę bez sensu.

Bo ile teraz ktoś kto chce dodać głupi obrazek musi pamiętać, żeby taki plik dodać. A wzorce maja dawać te możliwość, że jedno rozwiązanie możesz wprost wyjąc z tego projektu i dodać do innego i tam też będzie działać i teraz zamiast kod się sam dokumentować, piszesz how to use.

Dekorator jest rozwiązaniem które można tu zastosować ale tak jak już zostało napisane:
Cytat
Dekoratorem może być tutaj tylko Thumbnail bo on faktycznie coś tam robi na źródłowych danych.


czy jak na tym stacku który podrzucałeś:
  1. process = new Upload(myImage); // concrete component
  2. process = new Resize(process); // decorator
  3. process = new Clip(process); // decorator
  4. process->run();


Cytat
Jak we wzorcu dekorator przekazywać pomiędzy obiektami atrybuty elementu dekorowanego, tak, żeby każda klasa miała do nich dostęp i mogła je modyfikować i, żeby każdy obiekt widział te zmiany.
Tak:

http://blogophp.com/2009/08/16/dekorator/#more-40

Pierwsze co powinno To Cie właśnie zastanowić, że coś jest tutaj nie tak, skoro tak nie jest. Jak już używamy wzorców to trzeba ich używać dobrze, bo inaczej zamiast kod rozjaśnić zaciemniamy go.

Podsumowując, właściwości nie powinny wędrować miedzy dekoratorami, bo wtedy już to nie jest dekorator! Dekorujesz konkrety obiekt bazę która rozszerzasz, a nie budujesz nad obiektem bazy nowego obiektu do rozszerzeń. Każdy dekorator to niezależny byt, który możesz wywołać bezpośrednio na obiekcie bazowym zawsze i nie potrzebujesz do tego więcej dekoratorów po drodze.

To:
  1. $video = new PropertyGeter(
  2. new ThumbnailFromVideoCuter(
  3. new ContentGeter(
  4. new FilePuter)));
  5.  

i to:
  1. $video = new ThumbnailFromVideoCuter(
  2. new PropertyGeter(
  3. new ContentGeter(
  4. new FilePuter)));
  5.  


Ma dać ten sam efekt, daje, zapewne nie bo ThumbnailFromVideoCuter() zależy pewnie od obiektu PropertyGeter(), skoro potrzebny był Ci obserwator.

Ten post edytował com 11.01.2017, 00:52:22
Go to the top of the page
+Quote Post
Omenomn
post
Post #52





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Cytat
Wskaż mi gdzie framework ma coś nie udokumentowane i nie wiesz co uzyskasz jak wykonasz dany fragment jego kodu.

To trochę tak jakbyś z kota chciał zrobić mysz


Mówię o routingu. Dziwnie Cię zdziwiło, że są metody przypisane do konkretnej akcji z urla.

Cytat
Podsumowując, właściwości nie powinny wędrować miedzy dekoratorami, bo wtedy już to nie jest dekorator! Dekorujesz konkrety obiekt bazę która rozszerzasz, a nie budujesz nad obiektem bazy nowego obiektu do rozszerzeń. Każdy dekorator to niezależny byt, który możesz wywołać bezpośrednio na obiekcie bazowym zawsze i nie potrzebujesz do tego więcej dekoratorów po drodze.


Miedzy dokoratorami będę przekazywał obiekt, w którym będzie się znajdował kontent pliku plus inne atrybuty, które można modyfikować, a nie jak do tej pory sam kontent. Dlatego musiałem rozwiązać problem przekazywania właściwości, ale z obiektem będzie prościej o wiele.

Cytat
To:
  1. $video = new PropertyGeter(
  2. new ThumbnailFromVideoCuter(
  3. new ContentGeter(
  4. new FilePuter)));


i to:
  1. $video = new ThumbnailFromVideoCuter(
  2. new PropertyGeter(
  3. new ContentGeter(
  4. new FilePuter)));




Ma dać ten sam efekt, daje, zapewne nie bo ThumbnailFromVideoCuter() zależy pewnie od obiektu PropertyGeter(), skoro potrzebny był Ci obserwator.


Nieprawda, znajdź mi informację, że w dekoratorze kolejność dekoratorów ma nie mieć znaczenia.
Choćby zawsze musi istnieć końcowy dekorator, który nie przyjmuje wartości do konstrukora, więc jeżeli musi istnieć końcowy, to może istnieć początkowy i może istnieć ustalona kolejność.
Go to the top of the page
+Quote Post
daro0
post
Post #53





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Prawda jest taka, że gdybym miał się tak zastanawiać nad tym wszystkim to bym nigdy nie skończył w terminie żadnego projektu a wymagania są określone przez klienta. Owszem czasem trzeba coś dodać, coś nie było przewidziane, jednak na ogół nie jest to problemem. Tak na szybko (pierwsze co mi przychodzi na myśl). Zakładam że jest formularz typu Multipart/Formdata w widoku a w nim daje się jakiś opis w pole tekstowe, jest pole do wybierania obrazka do uploadu oraz opcja checkbox, czy ma być miniaturka czy też nie a rozmiary są określone w konfiguracji frameworka.

application/classes/Request.php

  1. <?php defined('SYSPATH') OR die('No direct script access.');
  2.  
  3. class Request extends Kohana_Request
  4. {
  5. public function files($key = NULL)
  6. {
  7. if ($key === NULL)
  8. {
  9. return $_FILES;
  10. }
  11. else
  12. {
  13. return Arr::path($_FILES, $key);
  14. }
  15. }
  16. }
  17.  


i metoda kontrolera

  1. public function action_upload()
  2. {
  3. if ($this->request->method() == HTTP_Request::POST)
  4. {
  5. if ($this->request->files('attachment'))
  6. {
  7. $config = Kohana::$config->load('app.uploads.images');
  8. $options = array(
  9. 'image' => array(
  10. 'width' => Arr::path($config, 'image.width'),
  11. 'height' => Arr::path($config, 'image.height'),
  12. ),
  13. 'thumbnail' => array(
  14. 'width' => Arr::path($config, 'thumbnail.width'),
  15. 'height' => Arr::path($config, 'thumbnail.height'),
  16. ),
  17. 'use_thumbnail' => $this->request->post('chk_use_thumbnail') ? TRUE : FALSE,
  18. );
  19.  
  20. $result = Uploader::factory('Image')
  21. ->options($options)
  22. ->data($this->request->files('attachment'))
  23. ->execute();
  24. }
  25. }
  26. // do something
  27. }


To jest tylko jedno z możliwych podejść. Tutaj to czy jest miniaturka czy nie to jest określone na podstawie tego co zwraca $_POST a ten helper musiałby na podstawie tego wykonywać pewne operacje. Zakładam użycie helperów Image oraz Upload z tego frameworka.

Nie wiem jak by to wyglądało w Laravelu a już tym bardziej gdyby pisać całkowicie od zera.

Ten post edytował daro0 11.01.2017, 09:51:16
Go to the top of the page
+Quote Post
Omenomn
post
Post #54





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Jak się poświęci więcej czasu przy jednym projekcie na dobre rozwiązanie problemu, to później tego rozwiązania można używać w kolejnych, i czas wykonania skraca się o wiele.
Piszą o tym w książkach o wzorcach i dobrych praktykach.
Problem jest rozwiązany i działa meeega!!
Teraz mam bibliotekę rozszerzalną na miliony sposobów, gotową do użycia w innych projektach.
Go to the top of the page
+Quote Post
ohm
post
Post #55





Grupa: Zarejestrowani
Postów: 623
Pomógł: 144
Dołączył: 22.12.2010

Ostrzeżenie: (0%)
-----


Cytat(Omenomn @ 11.01.2017, 11:32:25 ) *
Teraz mam bibliotekę rozszerzalną na miliony sposobów, gotową do użycia w innych projektach.


Tylko pytanie czy inni też będą wiedzieli jak tę bibliotekę szybko i łatwo użyć?
Go to the top of the page
+Quote Post
nospor
post
Post #56





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
Tylko pytanie czy inni też będą wiedzieli jak tę bibliotekę szybko i łatwo użyć?
Soryy, ale nie bede sobie "nieulatwial" pracy tylko dlatego ze ktos moze kiedys nie wiedziec jak tego uzyc... Ja tez mam wlasne liby w Symfony ktore generalizuje mi rozne rzeczy, np Grid, edycja, usuwanie, w sume caly CRUD. Na napisanie tego poswiecilem chwilke czasu ale teraz kazdy kolejny CRUD to 15 minut robotyi wiem ze wszystko bedzie dzialac tak samo.

Wracajac do twojego pytania:
Po pierwsze, skoro klasa byla uzywana w projekcie, to sa przyklady uzycia
Po drugie, zazwyczaj jak potrzeba pisze sie komentarz.
Go to the top of the page
+Quote Post
Omenomn
post
Post #57





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Zgadzam się z nospor
Go to the top of the page
+Quote Post
com
post
Post #58





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Mówię o routingu. Dziwnie Cię zdziwiło, że są metody przypisane do konkretnej akcji z urla.


Nie napisałem że coś w tym dziwnego, napisałem, że masz tu strategie o której ja i inni mówiliśmy.

Cytat
Nieprawda, znajdź mi informację, że w dekoratorze kolejność dekoratorów ma nie mieć znaczenia.
Choćby zawsze musi istnieć końcowy dekorator, który nie przyjmuje wartości do konstrukora, więc jeżeli musi istnieć końcowy, to może istnieć początkowy i może istnieć ustalona kolejność.


Wgl nie zrozumiałeś dekoratorów.

Jedyne co musi istnieć to klasa która rozszerzasz, ona ma jakaś funkcjonalność w Twoim przypadku bazą jest Upload. I kiedy podczas tego uploadu zależy Ci żeby powstała miniaturka, wiec dodajesz do istniejącego obiektu Uploadu zrób mi miniaturkę. Dlatego tworzysz dekorator, którego jedynym zadaniem jest zmienić obiekt bazowy tak żeby zamiast pełnego obrazu zwrócona została miniaturka w jego miejscu.
Dla innego route chcesz miniaturkę obrócona o 180 stopni. Wiec bierzesz klase Upload bierzesz dekorator Thumbnail i dekorator Rotate i masz miniaturkę i obrócony. Ale nie ma znaczenia czy najpierw obrócisz potem zmniejszysz czy na odwrót i tak i tak efekt zawsze jest taki sam i tak powinno być u Ciebie, a tak nie jest bo u Ciebie każda klasa zależy od innej. W przypadku prawdziwego dekoratora nadawane ograniczenia/zmiany na obiekcie są od siebie nie zależne, wiec mogę mięć: miniaturkę; miniaturkę i obrócony == obrócony i miniaturka; obrócony, a wszystko to bez jakiejkolwiek zmiany w kodzie. Twoje początkowe założenie było blednę, czyli:
Cytat
Choćby zawsze musi istnieć końcowy dekorator

Nie ma czegoś takiego jak początkowy czy końcowy dekorator, jest obiekt który dekorujesz i jeśli dekoratory maja ten sam interface co ten obiekt, to można je ze sobą składać tak jak było opisane w przykładach, ale tylko i wyłącznie wtedy.

Cytat
Soryy, ale nie bede sobie "nieulatwial" pracy tylko dlatego ze ktos moze kiedys nie wiedziec jak tego uzyc...

Tu wcale nie chodzi o nie ułatwianie pracy, bo po to zaproponowane zostało użycie wzorców, żeby te rozwiązanie było jak najbardziej elastyczne i można było wykorzystać je w wielu projektach, ale wzorce zostały zdefiniowane w taki sposób, żeby każdy kto sporzy na kod, znając je wie jaki będzie efekt. A kiedy kolega Omenomn po roku czy dwóch latach wróci do tego kodu coś zmienić, najpierw znów będzie musiał wdrożyć sam siebie jak to działa i czemu tak to zrobiłem wtedy a nie inaczej.

Przeczytaj jeszcze raz uważnie co tam zostało napisane
http://blogophp.com/2009/08/16/dekorator/#more-40
Najistotniejsze fragmenty
Cytat
// obiekty tej klasy beda dekorowane
class SimpleText extends Information

Cytat
Proszę zwrócić uwagę na fakt, iż gdy obiekt dekorowany jest tego samego typu co dekoratory jesteśmy w stanie ?dekorować? również dekoratory


obiekt dekorowany !== dekorator i nie możesz go nazwać dekoratorem końcowym.

Pomijając już sam fakt, że tak jak tam było:
new FirstLetter(new TextLength(new SimpleText()));
Dekoratory idą od środka w górę, a u Ciebie odnoszę wrażenie, że idziesz od początku w dół, przynajmniej tak wynikało z pierwszego opisu.

Trochę wracając jeszcze do tematu frameworka i jego roli, o czym mówiliśmy wcześniej to przykład od olx:
(IMG:http://i63.tinypic.com/bjm9.png)

Ten post edytował com 11.01.2017, 19:27:12
Go to the top of the page
+Quote Post
solificati
post
Post #59





Grupa: Zarejestrowani
Postów: 26
Pomógł: 10
Dołączył: 17.03.2012

Ostrzeżenie: (0%)
-----


Cytat(Omenomn @ 11.01.2017, 02:46:22 ) *
Nieprawda, znajdź mi informację, że w dekoratorze kolejność dekoratorów ma nie mieć znaczenia.
Choćby zawsze musi istnieć końcowy dekorator, który nie przyjmuje wartości do konstrukora, więc jeżeli musi istnieć końcowy, to może istnieć początkowy i może istnieć ustalona kolejność.

Principle of least astonishment jak to się w kulturze OOP nazywa. Gdy kolejność ma znaczenie to wprowadzasz składnię a to się liczy conajmniej jako "zaskoczenie".

Precyzując, Dekorator implementuje ten sam interfejs, który implementuje obiekt który jest dekorowany. Żeby dekorator mógł korzystać z pól dodanych przez inny dekorator, musisz wprowadzić drugie drzewo dekoratorów bazujące na poszerzonym interface albo ich produkcie.

Ten post edytował solificati 11.01.2017, 15:34:27
Go to the top of the page
+Quote Post
daro0
post
Post #60





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Jeszcze rok albo dwa lata temu przy wcześniejszych projektach to też myślałem że to co wtedy pisałem jest super. Jakże się myliłem, bo teraz jak na to popatrzę to aż szlak trafia bo można było to napisać inaczej. Ale dalej. Weźmy np. nie uploader ale StaticServer

  1. class Controller_Image extends Controller
  2. {
  3.  
  4. public function action_serve()
  5. {
  6. $image = Image::factory(DOCROOT . '/test.jpg');
  7.  
  8. $size = $this->request->query('size');
  9. $rotate = $this->request->query('rotate');
  10. $sharp = $this->request->query('sharp');
  11. $quality = $this->request->query('quality');
  12.  
  13. if ($size)
  14. {
  15. $width = $image->width;
  16. $height = $image->height;
  17. $image->resize($width * $size / 100, $height * $size / 100);
  18. }
  19.  
  20. if ($rotate)
  21. {
  22. $image->rotate($rotate);
  23. }
  24.  
  25. if ($sharp)
  26. {
  27. $image->sharpen($sharp);
  28. }
  29.  
  30. if ($quality)
  31. {
  32. $image = $image->render('jpg', $quality);
  33. }
  34.  
  35. $this->response->headers('Cache-Control', 'max-age=3600, public');
  36. $this->response->headers('Content-Type', 'image/jpg');
  37. $this->response->body($image);
  38. }
  39.  
  40. }


I tak:

http://localhost/image/serve - wyświetla oryginalny obrazek JPG który wczyta
http://localhost/image/serve?size=50 - wyświetla obrazek w rozmiarach 50% oryginału
http://localhost/image/serve?size=50&sharp=100 - to samo ale wyostrzone
http://localhost/image/serve?quality=10 - jakość JPG 10%
http://localhost/image/serve?rotate=90 - obraza o 90 stopni w prawo

Domyślnie metoda __toString() wywołuje na render() w tym module.

I teraz jest pytanie, co w takim przypadku daje zastosowanie dekoratora (bo też można by to zrobić) vs. to podejście jakie jest tu?
Go to the top of the page
+Quote Post
Omenomn
post
Post #61





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


daro0 seriooo?(IMG:style_emoticons/default/questionmark.gif) Ten kod jest naprawdę kiepski...
to podejście jest nawet gorsze od tego, które chciałem poprawić.

com

przykładowy dekorator
  1. $decorator = new Decorator( new Decorator1( new Decorator2( new Decorator3);
  2. $decorator->make($decorationObject);


Widzisz, że Decorator3 nie przyjmuje obiektu?
Chcesz mi tłumaczyć coś, czego sam nie kumasz i jeszcze wmawiasz mi, że tego nie rozumiem.

Ten post edytował Omenomn 11.01.2017, 22:17:29
Go to the top of the page
+Quote Post
Pyton_000
post
Post #62





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


@Omenomn weź w końcu przeczytaj co to jest Decorator i przestań się upierać przy czymś o czym nie masz pojęcia bo aż szkoda.
Go to the top of the page
+Quote Post
Omenomn
post
Post #63





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Szlag mnie trafi:
http://blogophp.com/2009/08/16/dekorator/#more-40

Cytat
Jeśli chcemy zezwolić na wyświetlanie na wyjściu wiadomości, których długość przekracza pięć znaków wystarczy zapis:

  1. $obj = new TextLength(new SimpleText());
  2. $obj->Write('Napis');

Warunki mogą być łatwo dołączane jak zaprezentowano poniżej:

  1. // wyswietli napis gdy bedzie on mial wiecej niz
  2. // 5 znakow a pierwszym bedzie litera A.
  3. $obj = new FirstLetter(new TextLength(new SimpleText()));
  4. $obj->Write('Napis');

W ten prosty sposób możemy dowolnie nakładać ograniczenia na parametr $message. Proszę zwrócić uwagę na fakt, iż gdy obiekt dekorowany jest tego samego typu co dekoratory jesteśmy w stanie ?dekorować? również dekoratory ? tak właśnie dzieje się w powyższym przykładzie. Zachęcam do korzystania z tego wzorca.


Cytat z linku, widzisz, żeby SimpleText przyjmowała obiekt? Więc chyba musi być ostatnia, no nie?(IMG:style_emoticons/default/questionmark.gif) (IMG:style_emoticons/default/questionmark.gif) (IMG:style_emoticons/default/questionmark.gif) ?
Proste jak konstrukcja cepa.
Najwyraźniej nie dla wszystkich.

Ten post edytował Omenomn 11.01.2017, 22:58:25
Go to the top of the page
+Quote Post
Pyton_000
post
Post #64





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


SimpleText nie jest ostatnim a pierwszym. Na dodatek nie jest dekoratorem a Obiektem bazowym który jest DEKOROWANY a NIE jest DEKORATOREM.
Go to the top of the page
+Quote Post
com
post
Post #65





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Omenomn Specjalnie Ci już podkreśliłem fragmenty z tego bloga, ale zamiast przeczytać ze zrozumieniem uparłeś się na swoje rozwiązanie. Przeczytaj jeszcze raz co ja napisałem i co napisał Pyton_000 i można zakończyć te dyskusję.

Ostatecznie dekoratory bez klasy bazowej nie istnieją bo nie maja co dekorować, dlatego zawsze musi być jakaś baza tak jak tam jest to SimpleText, który nie jest dekoratorem, nim są dopiero TextLength oraz FirstLetter. Źle przeczytałeś i potem dobudowałeś sobie do tego teorie, zdarza się (IMG:style_emoticons/default/smile.gif) SimpleText możesz zawsze wywołać wgl bez dekoratorów i spełni swoje podstawowe zadanie, dekoratora nie da się bo nie będzie klasy która dekoruje i tyle.

  1. $obj = new Decorator( new Decorator1( new Decorator2( new ObjectToDecorate);
  2. $obj->make($object);


Tak miał wyglądać Twój kod dla Twojego przykładu (IMG:style_emoticons/default/wink.gif)

Ten post edytował com 12.01.2017, 01:15:38
Go to the top of the page
+Quote Post
Omenomn
post
Post #66





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Okej, teraz widzę, że w tych tutorialach oni ostatni dekorator przekazują jako obiekt do dekorowania.

Jednak klasa SimpleText musi implementować interfejs dekoratora, wymagany w konstruktorze dekoratora TextLength, więc jeśli implementuje interfejs dekoratora to też nim jest, według mojego rozumowania.

Pierwszy dekorator jaki wywołuje metodę write() to FirstLetter, więc jest pierwszy, a ostatnia wywołana metoda jest z SimpleText.

  1. $obj = new Decorator( new Decorator1( new Decorator2( new ObjectToDecorate);
  2. $obj->make($object);


Co przekazujesz w tym kodzie do zmiennej $object? Nie widzisz tu błędu logicznego?

Teorycznie metoda make() może nie przyjmować parametru i wtedy pracujesz na sztywnych danych z ObjectToDecorate(), ale według mnie lepiej jest przekazać do metody make($object), obiekt do obróbki a klasę ObjectToDecorate (w tym przypadku nazwa błędna) potraktować jako ostatni krok obróbki obiektu $object.

Takie podejście wydaje mi się o wiele sensowniejsze.

Po za tym co to ma do rzeczy, że jest w dekoratorze ustalona kolejność. Może być tak, że któryś z dekoratorów zmieni dane, które otrzymał w taki sposób, że dekorator przed nim nie byłby w stanie ich obsłużyć, jeśli wystąpi po nim.

Wymyślanie problemów tam gdzie ich nie ma.

Ten post edytował Omenomn 12.01.2017, 08:52:00
Go to the top of the page
+Quote Post
daro0
post
Post #67





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Omenomn
Tym razem nie Kohana i nie wiem czy jest to do końca poprawnie ale podczas pisania tego kodu myślałem że zwariuję(IMG:style_emoticons/default/exclamation.gif) ! Dosłownie.

  1. <?php
  2.  
  3. define('DOCROOT', realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR);
  4.  
  5. interface IDecoratedImage
  6. {
  7. public function render();
  8. }
  9.  
  10. class Driver
  11. {
  12. protected $file;
  13. protected $resource;
  14.  
  15. public function __construct($file)
  16. {
  17. $this->file = $file;
  18. $this->resource = imagecreatefromjpeg($this->file->getRealPath());
  19. }
  20.  
  21. public function __destruct()
  22. {
  23. imagedestroy($this->resource);
  24. }
  25.  
  26. public function getResource()
  27. {
  28. return $this->resource;
  29. }
  30. }
  31.  
  32. class Image implements IdecoratedImage
  33. {
  34. protected $driver;
  35. protected $resource;
  36.  
  37. public function __construct($driver)
  38. {
  39. $this->driver = $driver;
  40. $this->resource = $this->driver->getResource();
  41. }
  42.  
  43. public function render()
  44. {
  45. imagejpeg($this->resource);
  46. }
  47.  
  48. public function getResource()
  49. {
  50. return $this->resource;
  51. }
  52. }
  53.  
  54. class GrayscaleImage implements IDecoratedImage
  55. {
  56. protected $image;
  57.  
  58. public function __construct($image)
  59. {
  60. $this->image = $image;
  61. }
  62.  
  63. public function render()
  64. {
  65. $resource = $this->image->getResource();
  66. imagefilter($resource, IMG_FILTER_GRAYSCALE);
  67. imagejpeg($resource);
  68. }
  69.  
  70. public function getResource()
  71. {
  72. return $this->resource;
  73. }
  74.  
  75. }
  76.  
  77. class NegateImage implements IDecoratedImage
  78. {
  79. protected $image;
  80.  
  81. public function __construct($image)
  82. {
  83. $this->image = $image;
  84. }
  85.  
  86. public function render()
  87. {
  88. $resource = $this->image->getResource();
  89. imagefilter($resource, IMG_FILTER_NEGATE);
  90. imagejpeg($resource);
  91. }
  92. }
  93.  
  94.  
  95. header('Cache-Control: max-age=3600, public');
  96. header('Content-Type: image/jpeg');
  97.  
  98. $path = DOCROOT . 'test.jpg';
  99.  
  100. // Display original image
  101. //$image = new Image(new Driver(new SplFileInfo($path)));
  102.  
  103. // Display decorated grayscale image
  104. //$image = new GrayscaleImage(new Image(new Driver(new SplFileInfo($path))));
  105.  
  106. // Display decorated negative image
  107. $image = new NegateImage(new Image(new Driver(new SplFileInfo($path))));
  108. $image->render();


Też chodzi o ładowanie JPEG oraz przy użyciu jak (poprawnie?(IMG:style_emoticons/default/questionmark.gif) ) myślę dekorowania bazowego Image tak żeby uzyskać efekty w odcieniach szarości albo nagatywu obrazu. W takim razie odpowiedz mi na pytanie: po co tyle zabawy?(IMG:style_emoticons/default/questionmark.gif) ? Mam jeszcze dekorować ten udekorowany obiekt w ten sposób:

  1. $image = new GrayscaleImage(new NegateImage(new Image(new Driver(new SplFileInfo($path)))));
  2. $image->render();


A co z dodatkowymi opcjami? Albo jeszcze takie coś:

  1. $image = new SharpenImage(new GrayscaleImage(new NegateImage(new Image(new Driver(new SplFileInfo($path))))));
  2. $image->render();


vs. to:

  1. $image = Image::factory(DOCROOT . 'test.jpg')
  2. ->grayscale()
  3. ->negate()
  4. ->sharpen()
  5. ->render();


Co też moim zdaniem można zrobić bardzo prosto w tylko jednej klasie operując na resource i tych wbudowanych funkcjach z modułu GD.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #68





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


single responsibility principle - słyszał?
Go to the top of the page
+Quote Post
Omenomn
post
Post #69





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Cytat
  1. $image = Image::factory(DOCROOT . 'test.jpg')
  2. ->grayscale()
  3. ->negate()
  4. ->sharpen()
  5. ->render();

Co też moim zdaniem można zrobić bardzo prosto w tylko jednej klasie operując na resource i tych wbudowanych funkcjach z modułu GD.


Wydaje mi się, że o wiele gorzej z dodawaniem kolejnych funkcji przy takim rozwiązaniu, bo w końcu klasa może urosnąć do gigantycznych rozmiarów z ogromną ilością metod, a właśnie ten problem chciałem wyeliminować.
Trzeba pamiętać o tym, że to ma obsługiwać różne pliki, nie tylko obrazy, ale też wideo.

Czyli właśnie zasada jednej odpowiedzialności jest tu wykluczona, bo jeśli jeszcze można by ją odnieść do obrazu, to nie odniesie się tego do uploadu filmu z wygenerowaniem trzech miniaturek.

Po za tym istnieje taka klasa do obróbki obrazów jaką przedstawiasz daro0:
http://image.intervention.io/

i Ja ją wykorzystuję właśnie w moim dekoratorze.

Ten post edytował Omenomn 12.01.2017, 09:53:41
Go to the top of the page
+Quote Post
mrc
post
Post #70





Grupa: Zarejestrowani
Postów: 160
Pomógł: 27
Dołączył: 22.09.2008
Skąd: Tarnów

Ostrzeżenie: (0%)
-----


@Omenomn

Męczysz się chłopak niemiłosiernie. Przeczytaj i przeanalizuj to, co jest napisane w Czystym Kodzie + SOLID. Sam kiedyś tak kombinowałem jak Ty. Tak jak ktoś już wcześniej napisał - uzbrój się w pokorę, przeczytaj, i zastanów się nad sensem tego, co tam jest napisane. Nie bez powodu jest to best seller.
Go to the top of the page
+Quote Post
Omenomn
post
Post #71





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Przeczytam na pewno.

Ps.
Nie męczę się, bo już to jest gotowe i dobrze działa.

Tak sobie ogólnie pomyślałem teraz, że tak jak backend tworzy się pod frontend, tak bebechy bibliotek do obsługi jakichś zadań powinno się tworzyć pod sposób ich wywoływania. Czyli najpierw zastanowić się trzeba jak chce się korzystać z danej biblioteki, jak ją wywoływać, a później dopiero tworzyć jej wnętrze.

Ten post edytował Omenomn 12.01.2017, 20:21:24
Go to the top of the page
+Quote Post
com
post
Post #72





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Dalsza dyskusja nie ma sensu wiec na tym poście zakończę.
Cytat
Okej, teraz widzę, że w tych tutorialach oni ostatni dekorator przekazują jako obiekt do dekorowania.

No bo taka jest definicja dekoratora. Masz obiekt do dekorowania który istniej zanim wgl ktokolwiek pomyśli o tym żeby stworzyć dekorator i masz dekoratory które dodają nowe funkcjonalności do klasy nie modyfikując jej.
Cytat
Jednak klasa SimpleText musi implementować interfejs dekoratora


Co za bzdury gadasz, to nie klasa która dekorujesz musi implementować interfejs dekoratora, a dekoratory interfejsy klasy która dekorują. Czyli zupełnie na odwrót.

Cytat
Teorycznie metoda make() może nie przyjmować parametru i wtedy pracujesz na sztywnych danych z ObjectToDecorate(), ale według mnie lepiej jest przekazać do metody make($object), obiekt do obróbki a klasę ObjectToDecorate (w tym przypadku nazwa błędna) potraktować jako ostatni krok obróbki obiektu $object.


Pracując na sztywnych danych jaki miałby sens dekorować klasę, skoro bez jej modyfikacji niczego nie jesteś wstanie zmienić. Podstawowym zadaniem które da się tu zrobić jest wykonanie takiego kodu:
  1. $obj = new ObjectToDecorate();
  2. $obj->make($object);

Nie potrzebuje mieć ani jednego dekoratora, żeby taki kod wywołać, bo on dostarcza to co daje mi interfejs.

To co Ty stworzyłeś nie można nazwać po prostu dekoratorem. Stworzyłeś własna implementacje jako rozwiązanie dla tego problem, bo to co Ty masz nawet obok dekoratora nie stało.

Tylko te rozwiązanie ma dwa podstawowe problemy, nie jest testowalne i skalowalne. Wraz z każdym dekoratorem wzrasta złożoność tego rozwiązania i uzależnienie jednego obiektu od drugiego.

Ale jedno muszę Ci przyznać wykazałeś się pomysłowością w wymyślaniu "koła" na nowo, bo otrzymałeś coś co w programowaniu istnieje od dawna pod nazwą dziedziczenie, tylko zamiast zrobić to tradycyjnie, stworzyłeś implementacje poprzez składanie obiektów. (IMG:style_emoticons/default/biggrin.gif)
Go to the top of the page
+Quote Post
Omenomn
post
Post #73





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


i tak głównie chodzi o warstwowe nakładanie klas new Class(new Class1( new Class2( itd.)))

To, czy Class2 traktujesz jako obiekt dekorowany, czy ostatni dekorator nie ma takiego znaczenia.

Cytat
Ale jedno muszę Ci przyznać wykazałeś się pomysłowością w wymyślaniu "koła" na nowo, bo otrzymałeś coś co w programowaniu istnieje od dawna pod nazwą dziedziczenie, tylko zamiast zrobić to tradycyjnie, stworzyłeś implementacje poprzez składanie obiektów.


To nie jest dziedziczenie tylko przypisanie, co czyni ogromną różnicę.

Cytat
Tylko te rozwiązanie ma dwa podstawowe problemy, nie jest testowalne i skalowalne. Wraz z każdym dekoratorem wzrasta złożoność tego rozwiązania i uzależnienie jednego obiektu od drugiego.


Jest testowalne. Przetestowałem, działa, chociaż jest dość zawiłe w implementacj, jeszcze nad tym popracuję

Cytat
Cytat
Jednak klasa SimpleText musi implementować interfejs dekoratora

Co za bzdury gadasz, to nie klasa która dekorujesz musi implementować interfejs dekoratora, a dekoratory interfejsy klasy która dekorują. Czyli zupełnie na odwrót.


Chodziło mi o to, że mają ten sam interfejs.

Widzę, że wszędzie piszą tak jak Ty tutaj, rzuciłem okiem na ten wzorzec i jakoś mi umknęło to, że ostatni obiekt ma być traktowany jako obiekt dekorowany, bo sensowniejsze dla mnie jest podejście, że obiekt dekorowany to ten który przekazujesz do make, jakoś tak podświadomie to potraktowałem:

  1. $obj = new ObjectToDecorate();
  2. $obj->make($object);


bo załóżmy przekazujemy tablicę $array do make($array)
  1. $array = [
  2. 'name' => 'plik.jpg',
  3. 'extension' => 'jpg',
  4. 'height' => 200,
  5. 'width' => 300,
  6. ]
  7. $obj = new ObjectToDecorate();
  8. $obj->make($array)


i teraz ObjectToDecorate może zmienić nazwę pliku, rozszerzenie i rozmiar, więc modyfikuje tablicę (dekoruje), która jest w tym momencie obiektem dekorowanym/modyfikowanym.

Dalsza dyskusja na temat dekoratora nie ma sensu naprawdę, bo rozumiem Twoje podejście, jednak niekoniecznie się z nim zgadzam.
Go to the top of the page
+Quote Post
com
post
Post #74





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Ponieważ zaczynasz bardziej sensownie pisać to jeszcze na to Ci odpowiem

Cytat
To, czy Class2 traktujesz jako obiekt dekorowany, czy ostatni dekorator nie ma takiego znaczenia.


Ma ogromne znaczenie, bo u Ciebie nie da się nawet wyciągnąć podstawowej funkcjonalności, może poza propertisami pliku ale to podobno ma być upload. To gdzie jest ten wspólny interfejs

Cytat
To nie jest dziedziczenie tylko przypisanie, co czyni ogromną różnicę.

W programowaniu obiektowym mocno upraszczając obiekty, mogą albo po sobie dziedziczyć, albo może nastąpić ich kompozycja. Ty zrobiłeś kompozycje, ale ponieważ wszystkie te twoje klasy dziedziczą po tym samym interfejsie to zasadniczo zrobiłeś ich rozszerzenie wiec defakto uzyskałeś to samo jakby zrobić :
Class : Class1 : Class2, efekt masz dokładnie identyczny, z tym że dla takiego podejścia bez problemu napiszesz testy automatyczne, dla Twojego już niekoniecznie.
Bo to co ty zrobiłeś:
Cytat
Jest testowalne. Przetestowałem, działa, chociaż jest dość zawiłe w implementacj, jeszcze nad tym popracuję


czyli test zero jedynkowy, działa nie działa to żaden dowód, że to zawsze tak będzie działać jakby się tego oczekiwało.

Cytat
Widzę, że wszędzie piszą tak jak Ty tutaj, rzuciłem okiem na ten wzorzec i jakoś mi umknęło to, że ostatni obiekt ma być traktowany jako obiekt dekorowany, bo sensowniejsze dla mnie jest podejście, że obiekt dekorowany to ten który przekazujesz do make


ten obiekt który przekazujesz do make nie jest wgl z żadna z klas związany, to jest po prostu model na którym operujesz. Ani dekoratory ani klasa która dekorujesz wgl nie musza istnieć, żeby istniał ten objekt, a to może być cokolwiek.

Cytat
i teraz ObjectToDecorate może zmienić nazwę pliku, rozszerzenie i rozmiar, więc modyfikuje tablicę (dekoruje), która jest w tym momencie obiektem dekorowanym/modyfikowanym.


Nadal nie rozumiesz co to jest dekorator, ten obiekt to model danych, jaki, taki jaki sobie wymarzysz. On wgl nie ma związku ze wzorcem dekorator.

Cytat
bo rozumiem Twoje podejście

No właśnie nie rozumiesz, uwierz, że gdybyś stworzył dekorator nie potrzebowałbyś obserwatora który śledzi zmiany w poszczególnych klasach.

Ja tego podejścia nie wymyśliłem, ja po prostu tłumacze Ci jak działa dekorator. Dekorator ma jedna jedyna definicje i jest to najprostszy z możliwych wzorców, ale jak się go nie zrozumie to wychodzi taki problem, że można uzyskać coś zupełnie innego.

a wystarczyło napisać to tak z użyciem dekoratorów skoro tak bardzo to chciałeś zrobić:

  1. $obj = new Thumbnail(new Upload());
  2. $obj->make($model);


No i które rozwiązanie jest bardziej akceptowalne te czy te:
  1. $image = new PropertyGeter(
  2. new ContentImageGeter(
  3. new ImageNoResizer(
  4. new Encoder(
  5. new FilePuter))));
  6. $image->make($request->file);


Wgl spójrz ile zależności i klas potrzebujesz żeby stworzyć cokolwiek.

Chcesz mieć rożne typy obsłużone, proszę bardzo:
  1. $obj0 = new Thumbnail(new Upload());
  2. $obj0->make($model0);
  3.  
  4. $obj = new Thumbnail(new ImageUpload());
  5. $obj->make($model);
  6.  
  7. $obj1 = new Thumbnail(new VideoUpload());
  8. $obj1->make($model1);
  9.  
  10. ...


Wiec nie:
  1. - zwykły obraz:
  2. $image = new Property(
  3. new ContentImage(
  4. new Image(
  5. new Encoder(
  6. new File))));
  7. $image->make($request->file);
  8. - miniaturka:
  9. $thumbnail = new Property(
  10. new ContentImage(
  11. new Thumbnail(
  12. new Encoder(
  13. new File))));
  14. $image->make($request->file);
  15. - video:
  16. $video = new Property(
  17. new Content(
  18. new Video(
  19. new File)));
  20. $video->make($request->file);
  21. - video z miniaturką
  22. $video = new Property(
  23. new ThumbnailFromVideo(
  24. new Content(
  25. new Video(
  26. new File))));
  27. $video->make($request->file);
  28. - video z trzema miniaturką
  29. $video = new Property(
  30. new ThumbnailFromVideo(
  31. new GetThumbnail(
  32. new ThumbnailFromVideo(
  33. new GetThumbnail(
  34. new ThumbnailFromVideo(
  35. new GetThumbnail(
  36. new Content(
  37. new Video(
  38. new File))));
  39.  
  40. lub
  41.  
  42. $video = new ThreeThumbnailsFromVideo(
  43. new Content(
  44. new Video(
  45. new File))));
  46. $video->make($request->file);

A :
  1. - zwykły obraz:
  2. $obj = new ImageUpload(); // objekt który może zostać udekorowany lub nie
  3. $obj->upload($request->file);
  4. - miniaturka:
  5. $obj = new Thumbnail(new ImageUpload());
  6. $obj->upload($request->file);
  7. - video:
  8. $obj1 = new VideoUpload(); // objekt który może zostać udekorowany lub nie
  9. $obj1->upload($request->file);
  10. - video z miniaturką:
  11. $obj1 = new Thumbnail(new VideoUpload());
  12. $obj1->upload($request->file);
  13. - video z trzema miniaturkami:
  14. $obj1 = new ThreeThumbnails(new VideoUpload());
  15. $obj1->upload($request->file);


Chcesz mieć jakiś Encoder, nie ma problemu
  1. - zwykły obraz:
  2. $encoder = new DummyEncoder();
  3. $obj = new ImageUpload($encoder); // objekt Encoder wstrzykiwany jako zależność czyli DI
  4. $obj->upload($request->file);


Ten post edytował com 13.01.2017, 00:53:23
Go to the top of the page
+Quote Post
Omenomn
post
Post #75





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Napisałeś praktycznie to samo co Ja, z tym, że u mnie jest rozbite na więcej mniejszych kroków...

Zdecyduj się, czy klasa ImageUpload pobiera parametr do konstruktora czy nie.

  1. $obj = new ImageUpload(); // objekt który może zostać udekorowany lub nie
  2. $obj->upload($request->file);

  1. $encoder = new DummyEncoder();
  2. $obj = new ImageUpload($encoder); // objekt Encoder wstrzykiwany jako zależność czyli DI
  3. $obj->upload($request->file);


Poniżej jest pomniejszanie obrazu, czy generowanie obrazu z miniaturką?
  1. $obj = new Thumbnail(new ImageUpload());
  2. $obj->upload($request->file);


Jak pobierzesz w Thumbnail informacje o pliku, skoro ImageUpload to klasa bazowa, która za pewne pobiera te dane?
Chcesz w każdej klasie pobierać dane o pliku?

Moje rozwiązanie startuje od klasy PropertyGet, żeby pobrało informacje o pliku raz, a później na nich bazowało.
Gdzie pobierasz kontent pliku, gdzie go enkodujesz, jak chciałbyś zrobić zmianę nazwy?

Taki uproszczony schemat to Ja też mogłem napisać w poście, ale jest bezużyteczny.

Ten post edytował Omenomn 13.01.2017, 01:34:17
Go to the top of the page
+Quote Post
com
post
Post #76





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Napisałeś praktycznie to samo co Ja, z tym, że u mnie jest rozbite na więcej mniejszych kroków...


No właśnie, że nie bo ja nie potrzebuje u mnie nic więcej poza klasa bazowa i jej interfejsem, żeby stworzyć dowolny dekorator teraz.

Cytat
Zdecyduj się, czy klasa ImageUpload pobiera parametr do konstruktora czy nie.


To nie ma znaczenia, jeśli potrzebujesz dodatkowe zależności to je dodajesz, co pokazałem, ale do tego jest inny wzorzec.

Cytat
Poniżej jest pomniejszanie obrazu, czy generowanie obrazu z miniaturką?


Generowanie miniaturki, ale wystarczy zmienić ten dekorator na inny i masz inne zadanie.

Cytat
Jak pobierzesz w Thumbnail informacje o pliku, skoro ImageUpload to klasa bazowa, która za pewne pobiera te dane?
Chcesz w każdej klasie pobierać dane o pliku?


Ale do czego Ci są potrzebne te dane? Zrobienie miniaturki nie wymaga niczego więcej jak tylko pliku na którym ma zostać to wygenerowane.

Cytat
Taki uproszczony schemat to Ja też mogłem napisać w poście, ale jest bezużyteczny.


To nie jest uproszczony schemat tylko pełna funkcjonalność taka sama jak u Ciebie.

Implementacja:
  1. class ImageUpload : UploadInterface
  2. {
  3. private $encoder;
  4. private $renamer;
  5.  
  6. public function __construct (EncoderInterface $encoder, RenamerInterface $renamer)
  7. {
  8. $this->encoder = $encoder;
  9. $this->renamer = $renamer;
  10. }
  11.  
  12. public function upload($file)
  13. {
  14. // tutaj jakieś operacje na pliku typu enkodowanie, zmiany nazwy itd
  15. (...)
  16.  
  17. return $encodedAndRenamedAndEtcFile;
  18. }
  19. }
  20.  
  21. class GenerateWithThumbnail : UploadInterface
  22. {
  23. private $base;
  24.  
  25. public function __construct (UpoladInterface $upload)
  26. {
  27. $this->base = $upload;
  28. }
  29.  
  30. public function upload($file)
  31. {
  32. // tutaj wygenerowanie miniaturki
  33. (...)
  34.  
  35. $this->base->upload($fileWithThumbnail);
  36. }
  37. }
  38.  
  39. // Wywołanie
  40. $encoder = new DummyEncoder();
  41. $renamer = new DummyRenamer();
  42. $obj = new GenerateWithThumbnail(new ImageUpload($encoder, $renamer));
  43. $obj->upload($request->file);
  44.  


Cytat
Poniżej jest pomniejszanie obrazu, czy generowanie obrazu z miniaturką?


Ok nazwa była zła zmienię na GenerateWithThumbnail

Ten post edytował com 13.01.2017, 11:45:47
Go to the top of the page
+Quote Post
Omenomn
post
Post #77





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


To co zrobiłeś jest sztywne i kompletnie nie rozszerzalne, chyba, że za każdym razem jak chcę coś dodać, będę musiał modyfikować konstruktor klasy ImageUpload i jej metodę upload() co jest bez sensu, dodatkowo wtedy musiałbym modyfikować kod wszędzie tam gdzie ta klasa jest używana.

Cytat
Ale do czego Ci są potrzebne te dane? Zrobienie miniaturki nie wymaga niczego więcej jak tylko pliku na którym ma zostać to wygenerowane.


Wegenerowanie pliku wymaga:
- nazwy pliku,
- ścieżki
- kontentu wygenerowanego ze ścieżki
- ścieżki na którą ma zostać zapisany.

Wszystkie te dane należy wyciągnąć z pliku, żeby go przesłać, oprócz ścieżki do zapisu.

Jeżeli ImageUpload pobiera te dane, to w jaki sposób dostanie je GenerateWithThumbnail, żeby mogło zmodyfikować plik i w jaki sposób prześle zmodyfikowany plik do ImageUpload. Pliku z requesta nie da się modyfikować, można co najwyżej zapisać zmodyfikowane dane o pliku i przesłać je dalej do obróbki, więc tak czy siak format przesyłanych danych się zmienia, a klasa bazowa ImageUpload musi je przyjąć.

Kod
        $propeties->name = $file->getClientOriginalName();
        $propeties->extension = $file->getClientOriginalExtension();
        $propeties->path = $file->getRealPath();
        $propeties->disk = '/uploadFolder/';


Jeżeli te dane wyciągniesz z file w ImageUpload to w jaki sposób dostanie je GenerateWithThumbnail i w jaki sposób encoder i renamer przekaże dane do GenerateWithThumbnail ze zmienioną nazwą i zmienionym rozszerzeniu.
Najpierw powinna zostać wygenerowana miniatruka później plik bazowy, bo co jeśli chcę po prostu pomniejszyć plik, a nie generować dwóch? Najpierw muszę go pomniejszyć, a później wygenerować.

Natomiast jeżeli masz podstawową kompozycję z trzech klas:

Kod
$file = new GetProperty(new GetContent(new Put)));
$file->make($request->file);


to wtedy bez problemowo można tworzyć nakładki bez jakichkolwiek modyfikacji wnętrzna klas już istniejących, przykładowo:

Kod
$file = new GetProperty(new Rename(new ToThumbnailResize(new GetContent(new Put))));
$file->make($request->file);

lub
Kod
$file = new GetProperty(new Rename(new GenerateWithThumbnail(new GetSizeOfImage(new PutToSission(new GetContent(new Put))))))));
$file->make($request->file);


w ten sposób bazę trzech klas można rozszerzać jak się chce, trzymając się jedynie kolejności klas bazowych, bo taki kod też będzie działał:
Kod
$file = new GetProperty(new PutToSession(new GenerateWithThumbnail(new GetSizeOfImage(new Rename(new GetContent(new Put))))))));
$file->make($request->file);


tylko, że do sesji nie zostanie zapisana informacja o miniaturce, bo jest wygenerowana po zapisaniu danych do sesji.

Jest to o wiele bardziej elastyczne rozwiązanie niż Twoje według mnie, nadbudowujące kod, a nie modyfikujące go.

Teraz tak sobie pomyślałem, że w sumie do dekoratora nie musi być plik przekazywany, a może być obiekt:
Kod
$object->name;
$object->extension;
$object->content
$object->saveDisk


i wtedy klient dziedziczący po klasie abstrakcyjnej metodę do utworzenia takiego obiektu wywoływałby dekorator.
Kod
$client = new Image
$client->make($request->file);


Klient pobiera plik, a w metodzie make, lub w konstruktorze klienta byłoby

Kod
class Image extends ClientAbstract
{
protected $dekorator;
public function __construct()
{
$this->decorator = new ImageUpload();
}

public function make($file)
{
$object = stdClass;
$object->name = $file->getName();
$object->content= $file->getContent();
$object->saveDisk= '/saveDisk/;

$this->decorator->make($object);
}
}


i wtedy kolejność dekoratorów nie ma żadnego znaczenia, bo można zrobić sam:
Kod
new ImageUpload()
lub
Kod
new Rename(new ImageUpload());


Kod
new Rename(new Resize(new ImageUpload)))


Co sądzicie?

Ten post edytował Omenomn 13.01.2017, 14:32:15
Go to the top of the page
+Quote Post
rafkon1990
post
Post #78





Grupa: Zarejestrowani
Postów: 37
Pomógł: 9
Dołączył: 14.09.2016
Skąd: Śląskie

Ostrzeżenie: (0%)
-----


Cytat(Omenomn @ 13.01.2017, 13:03:39 ) *
...
Co sądzicie?

Sądzę że twoje posty są zbyt chaotyczne i trudne do zrozumienia, często zmieniasz tok myślowy a ponadto masz problem ze zrozumieniem wzorca dekorator.

Ten post edytował rafkon1990 13.01.2017, 14:34:58
Go to the top of the page
+Quote Post
Omenomn
post
Post #79





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Wydaje Ci się (IMG:style_emoticons/default/biggrin.gif)
Go to the top of the page
+Quote Post
kapslokk
post
Post #80





Grupa: Zarejestrowani
Postów: 965
Pomógł: 285
Dołączył: 19.06.2015
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


A mnie zastanawia, po co w ogóle zadajesz pytania @Omenomn, skoro później olewasz wszystkie odpowiedzi upierając się przy swoim? Zupełnie jak tutaj: http://forum.php.pl/index.php?showtopic=243138 :/

Ten post edytował kapslokk 13.01.2017, 15:54:18
Go to the top of the page
+Quote Post
Omenomn
post
Post #81





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


To się zastanawiaj dalej, możemy gadać o php, a nie o mnie i moim podejściu do Waszych wypowiedzi.

Przedstawiłem nowy pomysł rozwiązania, więc się do niego odnieście, a nie do mnie.

Co Wy jesteście, wyrocznia, że mam Wasze oceny i opinie przyjmować jako jedyne prawdziwe i niezaprzeczalne?
Dyskutować można, a to co się wyciągnie z dyskusji to prywatna sprawa każdego z osobna.

Tacy świetni jesteście, a jak com, albo daro0 wrzucili swój kod, to się okazuje, że gorzej przemyślany niż mój.

Ten post edytował Omenomn 13.01.2017, 17:04:30
Go to the top of the page
+Quote Post
com
post
Post #82





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
To co zrobiłeś jest sztywne i kompletnie nie rozszerzalne, chyba, że za każdym razem jak chcę coś dodać, będę musiał modyfikować konstruktor klasy ImageUpload i jej metodę upload() co jest bez sensu, dodatkowo wtedy musiałbym modyfikować kod wszędzie tam gdzie ta klasa jest używana.


Nie ma takiej potrzeby bo klasa ImageUpload nigdy się nie zmieni, po to masz przecież dekorator żeby dodać do niej nowe funkcjonalności bez zmiany tej klasy. Te parametry które tam dostaje w konstruktorze one są stałe i nie maja znaczenia, równie dobrze możesz tam przekazać sam Encoder, a Renamer może być dekoratorem, bo w zasadzie zmieniasz źródło danych. Ja po prostu założyłem , że to jest podstawowa funkcjonalność i te kroki są wykonywane zawsze. Klasa mogła nie otrzymywać wgl parametrów i wszystko to dziać się w jej wnętrzu ale wtedy łamiesz zasady programowania obiektowego.

Cytat
Wegenerowanie pliku wymaga:
- nazwy pliku,
- ścieżki
- kontentu wygenerowanego ze ścieżki
- ścieżki na którą ma zostać zapisany.

Wszystkie te dane należy wyciągnąć z pliku, żeby go przesłać, oprócz ścieżki do zapisu.


No i co mi po tych danych, owszem potrzebuje je w klasie ImageUpload, która zapisuje mi przesłany plik, ale to już nie interesuje GenerateWithThumbnail, bo jego jedynym zdaniem jest stworzenie miniaturki, wiec do czego tu potrzebne są te inne informacje.

Cytat
Jeżeli te dane wyciągniesz z file w ImageUpload to w jaki sposób dostanie je GenerateWithThumbnail i w jaki sposób encoder i renamer przekaże dane do GenerateWithThumbnail ze zmienioną nazwą i zmienionym rozszerzeniu.
Najpierw powinna zostać wygenerowana miniatruka później plik bazowy, bo co jeśli chcę po prostu pomniejszyć plik, a nie generować dwóch? Najpierw muszę go pomniejszyć, a później wygenerować.


Jak chcesz coś pomniejszyć skoro to coś nie istnieje. Najpierw musisz mieć coś co będziesz zmniejszał a potem możesz to zmniejszyć, a nie najpierw zmniejszyć a potem dopiero to stworzyć.

Sadze, że nadal nie stworzyłes dekoratora bo nie rozumiesz dalej czym on jest i rozwiązanie które powstało jest strasznie nie elastyczne i wgl nie testowalne.

Cytat
Tacy świetni jesteście, a jak com, albo daro0 wrzucili swój kod, to się okazuje, że gorzej przemyślany niż mój.


Ja wrzuciłem kod dekoratora bo się na niego uparłeś, wiec skoro według Ciebie rozwiązanie jest złe to znaczy że dekorator nie był dobrym pomysłem i tyle

Implementacja wersja 2:
  1. class ImageUpload : UploadInterface
  2. {
  3.  
  4. public function save($file)
  5. {
  6. // tutaj zapis pliku
  7. (...)
  8. return true;
  9. }
  10. }
  11.  
  12. class GenerateWithThumbnail : UploadInterface
  13. {
  14. private $base;
  15.  
  16. public function __construct (UpoladInterface $upload)
  17. {
  18. $this->base = $upload;
  19. }
  20.  
  21. public function save($file)
  22. {
  23. // tutaj wygenerowanie miniaturki
  24. (...)
  25.  
  26. $this->base->save($fileWithThumbnail);
  27. }
  28. }
  29.  
  30. class Encode : UploadInterface
  31. {
  32. private $base;
  33.  
  34. public function __construct (UpoladInterface $upload)
  35. {
  36. $this->base = $upload;
  37. }
  38.  
  39. public function save($file)
  40. {
  41. // tutaj encodowanie pliku
  42. (...)
  43.  
  44. $this->base->save($encodedFile);
  45. }
  46. }
  47.  
  48. class Renamer : UploadInterface
  49. {
  50. private $base;
  51.  
  52. public function __construct (UpoladInterface $upload)
  53. {
  54. $this->base = $upload;
  55. }
  56.  
  57. public function save($file)
  58. {
  59. // tutaj zmiana nazwy pliku
  60. (...)
  61.  
  62. $this->base->save($renamedFile);
  63. }
  64. }
  65.  
  66. // Wywołanie
  67. $obj = new Encode(new Renamer(new GenerateWithThumbnail(new ImageUpload())));
  68. $obj->save($request->file);
  69.  
  70. $obj1 = new Renamer(new Encode(new GenerateWithThumbnail(new ImageUpload())));
  71. $obj1->save($request->file);
  72.  
  73. // $obj === $obj1; => true


Ten post edytował com 13.01.2017, 18:14:01
Go to the top of the page
+Quote Post
Omenomn
post
Post #83





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Cytat
No i co mi po tych danych, owszem potrzebuje je w klasie ImageUpload, która zapisuje mi przesłany plik, ale to już nie interesuje GenerateWithThumbnail, bo jego jedynym zdaniem jest zmiana rozmiaru obrazka, do czego tu potrzebne są te inne informacje.


żeby zmienić rozmiar obrazka, musisz przekazać kontent pliku klasie GenerateWithThumbnail

Cytat
Jak chcesz coś pomniejszyć skoro to coś nie istnieje. Najpierw musisz mieć coś co będziesz zmniejszał a potem możesz to zmniejszyć, a nie najpierw zmniejszyć a potem dopiero to stworzyć.


Przed uploadem plik znajduje się folderze z plikami tymczasowymi, jak nie wiesz takich rzeczy to o czym my rozmawiamy w ogóle? Na tym pliku się operuje, chyba, że chcesz najpierw go wysłać, a później obrabiać, co jest bez sensu, bo można to zrobić przed wysłaniem.

Cytat
Te parametry które tam dostaje w konstruktorze one są stałe i nie maja znaczenia, równie dobrze możesz tam przekazać sam Encoder, a Renamer może być dekoratorem, bo w zasadzie zmieniasz źródło danych.


W ogóle parametry w konstruktorze nie mają znaczenia, zupełnie...

Cytat
Sadze, że nadal nie stworzyłes dekoratora bo nie rozumiesz dalej czym on jest i rozwiązanie które powstało jest strasznie nie elastyczne i wgl nie testowalne.


Jest elastyczne, bo można nakładać warstwy jak się chce i jakie się chce, a klasa ImageUpload działa samoistnie bez żadnego dekoratora, tak jak chciałeś i oczywiście jest testowalne, bo znowu przetestowałem i działa w różnych konfiguracjach.

Dajmy sobie spokój, bo to co przedstawiasz po prostu nie może działać, jest nieścisłe, ogólne, nierozszerzalne i nietestowalne i proszę Cię skończ mi wmawiać, że nie rozumiem dekoratora.

Ten post edytował Omenomn 13.01.2017, 17:45:33
Go to the top of the page
+Quote Post
com
post
Post #84





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
żeby zmienić rozmiar obrazka, musisz przekazać kontent pliku klasie GenerateWithThumbnail


Niczego nie musisz przekazywać bo ta klasa otrzyma surowy plik.

Cytat
Przed uploadem plik znajduje się folderze z plikami tymczasowymi, jak nie wiesz takich rzeczy to o czym my rozmawiamy w ogóle? Na tym pliku się operuje, chyba, że chcesz najpierw go wysłać, a później obrabiać, co jest bez sensu, bo można to zrobić przed wysłaniem.


No wiec ten plik istnieje w tempie, a nie Ty go dopiero tworzysz potem.

Cytat
W ogóle parametry w konstruktorze nie mają znaczenia, zupełnie...


No nie mają, bo to są zależności potrzebne klasie ImageUpload, tam może być cokolwiek

Cytat
Jest elastyczne, bo można nakładać warstwy jak się chce i jakie się chce, a klasa ImageUpload działa samoistnie bez żadnego dekoratora, tak jak chciałeś i oczywiście jest testowalne, bo znowu przetestowałem i działa w różnych konfiguracjach.


Tak ale tylko w ściśle określonej kolejności i żadnego nie można pominąć. Zacznijmy od tego, że nawet nie wiesz co są testy, wiec nie rozumiesz tego, że to nie działa. Masz nieskończona ilość kombinacji i co przetestowałeś je wszystkie, nie, zrobiłeś testy działa nie działa, a to nie jest testowalność.

Cytat
Dajmy sobie spokój, bo to co przedstawiasz po prostu nie może działać, jest nieścisłe, ogólne, nierozszerzalne i nietestowalne i proszę Cię skończ mi wmawiać, że nie rozumiem dekoratora.


No nie rozumiesz bo mimo wielu prób dekorator nie powstał, ale tak zakończmy to, wróć za parę lat z doświadczeniem (IMG:style_emoticons/default/smile.gif)

Ten post edytował com 13.01.2017, 18:02:00
Go to the top of the page
+Quote Post
Omenomn
post
Post #85





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Nie kpij sobie, doświadczeniem nie nadrobisz kumatości.
Dakorator powstał. Mam to gdzieś, czy nazwiesz to dekoratorem, modyfikatorem, warstwami, czy jeszcze jakoś inaczej, ważne, że porządkuje kod.
Go to the top of the page
+Quote Post
com
post
Post #86





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Nie kpij sobie, doświadczeniem nie nadrobisz kumatości.
Dakorator powstał. Mam to gdzieś, czy nazwiesz to dekoratorem, modyfikatorem, warstwami, czy jeszcze jakoś inaczej, ważne, że porządkuje kod.


Owszem nie nadrobisz, ale to nie ja nie kumam jak działa dekorator tylko Ty go nie zrozumiałeś.
A twój kod nie został uporządkowany, a bardziej zaciemniony niż jakbyś zrobił po prostu wszytko w kontrolerze i tyle (IMG:style_emoticons/default/wink.gif)

Go to the top of the page
+Quote Post
Omenomn
post
Post #87





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Szaleństwo! Najlepiej piszmy apki w jednym pliku i jednej klasie (IMG:style_emoticons/default/biggrin.gif)

Ten post edytował Omenomn 13.01.2017, 18:16:44
Go to the top of the page
+Quote Post
com
post
Post #88





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Zróbmy tak, wrzuć całą swoja implementacje na gita i daj linka. Specjalnie dla Ciebie zrobię z tego dekorator (IMG:style_emoticons/default/smile.gif)

Cytat
Najlepiej piszmy apki w jednym pliku i jednej klasie


Bardzo skrajne rozwiązanie, ale istnieje takie coś jak

Zasada Keep It Simple, Stupid (czyli tłumacząc: nie komplikuj, głupku) jest to reguła mówiąca, że nie należy na siłę komplikować prostych rzeczy, aby przykładowo wykorzystać niepotrzebne w danym momencie wzorce projektowe.
Go to the top of the page
+Quote Post
Omenomn
post
Post #89





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Ok wrzucę, może ktoś się czegoś nauczy.

https://github.com/omenomn/uploadDecorator

Masz, ciekawe jak to poprawisz.

Ten post edytował Omenomn 13.01.2017, 18:33:43
Go to the top of the page
+Quote Post
daro0
post
Post #90





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


@Omenomn

Zanim zaczniesz jechać po czyimś kodzie czy tam w ogóle podejściu (i nie mówię o swoim) to tak:

1. Napisz jakiś serwis pokroju tego forum albo coś innego, co się wiąże z kilkumiesięcznym nakładem pracy
2. Napisz kolejny serwis za rok i wróć do kodu sprzed roku
3. Napisz coś kolejnego za 2 lata, za 3 itd.. i znowu wróć

Gwarantuję Ci że będziesz miał niesmak po tym co zrobiłeś wcześniej. Akurat @com przedstawił tu dość klarowne rozwiązanie, łatwe do zrozumienia a konkretniej chodzi o to na czym polega i co się dzieje po zastosowaniu wzorca dekorator.

Podałem tylko wcześniej pewną realizację wczytywania zdjęć modułem Image z Kohany i ich obróbkę na podstawie parametrów z request query, podaj może tutaj praktyczną realizację jak byś zrobił taki static server, który w zależności od parametrów z paska przeglądarki wyświetlałby odpowiednio udekorowane zdjęcia na bazie swojego rozwiązania.
Go to the top of the page
+Quote Post
Omenomn
post
Post #91





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Po moim jadą wszyscy cały czas (IMG:style_emoticons/default/biggrin.gif)

Wrzuciłem link na github.
Coś długo te poprawki (IMG:style_emoticons/default/biggrin.gif)

Ten post edytował Omenomn 13.01.2017, 21:15:38
Go to the top of the page
+Quote Post
com
post
Post #92





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Coś długo te poprawki


Bo tam w tym kodzie niczego się nie dało wykorzystać, no może poza tym co jest gotowe czyli wykorzystanie FFMpeg. I wcale nie powiedziałem, że dam Ci to od razu, przecież cały czas nie siedziałem nad tym rozwianiem, robię inne rzeczy o wyższym priorytecie niż ten kod.

https://github.com/ComStudio/decorator

Ten post edytował com 13.01.2017, 23:43:48
Go to the top of the page
+Quote Post
Omenomn
post
Post #93





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Gdzie Ty tam masz ten Twój niezrozumiały przeze mnie dekorator, bo nie widzę tam ani jednej klasy wywołanej w konstruktorze innej?

I w czym niby Twój kod jest lepszy od mojego?

info o pliku pobierasz w trzech, albo więcej miejscach:
  1. public function save(File $file)
  2. {
  3. $this->image->save($file);
  4. $storage = $this->getStorage();
  5. $fileName = $file->getName();
  6. $thumbnailFromImage = new ThumbnailFromImage(150);
  7. $thumbnail = new File(
  8. $fileName . '_thumb',
  9. $file->getExtension(),
  10. $thumbnailFromImage->create($file),
  11. $file->getPath()
  12. );
  13. if($storage->has($fileName))
  14. {
  15. $image = $storage->get($fileName);
  16. $image['thumbnail'] = $thumbnail;
  17. }
  18. }


  1. public function save(File $file)
  2. {
  3. $this->image->save($file);
  4. $storage = $this->getStorage();
  5. $fileName = $file->getName();
  6. $thumbnailFromVideo = new ThumbnailFromVideo();
  7. $thumbnail = new File(
  8. $fileName . '_thumb',
  9. $file->getExtension(),
  10. $thumbnailFromVideo->create($file),
  11. $file->getPath()
  12. );
  13. if($storage->has($fileName))
  14. {
  15. $image = $storage->get($fileName);
  16. $image['thumbnail'] = $thumbnail;
  17. }
  18. }

  1. public function __construct($name, $extension, $content, $path)
  2. {
  3. $this->name = $name;
  4. $this->extension = $extension;
  5. $this->content = $content;
  6. $this->path = $path;
  7. }
  8. public static function CreateFromRequest($file)
  9. {
  10. return new File(
  11. $file->getClientOriginalName(),
  12. $file->getClientOriginalExtension(),
  13. \File::get($file->getRealPath()),
  14. $file->getRealPath()
  15. );
  16. }


Nawet nie chce mi się już analizować tego kodu, burdel taki, że głowa boli.
Go to the top of the page
+Quote Post
com
post
Post #94





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Gdzie Ty tam masz ten Twój niezrozumiały przeze mnie dekorator, bo nie widzę tam ani jednej klasy wywołanej w konstruktorze innej?


https://github.com/ComStudio/decorator/blob/master/index.php

Tu masz wywołanie.

Cytat
info o pliku pobierasz w trzech, albo więcej miejscach:

A tu co niby robisz https://github.com/omenomn/uploadDecorator/...sformers/Makers
W każdej klasie zwracasz 95% tych samych informacji.
Ja tam niczego nie pobieram, poza klasa File, w pozostałych miejscach tylko zwracam te informacje, żeby wygenerować nowy plik z miniaturka na bazie oryginału.
W dodatku te dwie metody save to przecież dwie rożne klasy, jedna dla Image, druga dla Video.

Ten fragment to tworzenie nowego obrazka, czyli tej miniaturki, bo coś źle chyba to zrozumiałeś.
  1. $thumbnail = new File(
  2. $fileName . '_thumb',
  3. $file->getExtension(),
  4. $thumbnailFromVideo->create($file),
  5. $file->getPath()
  6. );


Moje File to Twoje:
https://github.com/omenomn/uploadDecorator/...kerAbstract.php

Klasa abstrakcyjna ma co najmniej jedna metodę abstrakcyjna, inaczej nie jest klasą abstrakcyjną, wiec nie ma sensu.

A tu to już wgl szaleństwo
https://github.com/omenomn/uploadDecorator/...s/Puter.php#L11

Potrafisz stworzyć obiekt klasy abstrakcyjnej. Aż dziw że ten kod działa (IMG:style_emoticons/default/aarambo.gif)

Cytat
Nawet nie chce mi się już analizować tego kodu, burdel taki, że głowa boli.


Burdel to masz w swoim kodzie, widać, że nawet nie używasz porządnego IDE, bo masz masę rzeczy które są zbędne i albo nigdzie nie używasz.
Skoro te rozwiązanie jest dla Ciebie nie zrozumiałe, to nie mamy o czym rozmawiać, bo nie potrafisz pisać jeszcze obiektowo. Za parę lat jak wrócisz i się tego nauczysz to wtedy zrozumiesz to co stworzyłem (IMG:style_emoticons/default/smile.gif)

Twój kod to idealny przykład jak tego nie robić (IMG:style_emoticons/default/smile.gif)

Utrzymanie takiego kodu jaki stworzyłeś już dziś jest problematyczne. Nie mówiąc już o zrozumieniu jego, bo z niego nie wynika nic co chciałeś tam zrobić i jak ktoś dostanie ten kod to będzie się bał wgl to ruszyć (IMG:style_emoticons/default/smile.gif)

Polecam lekturę CzystyKod.

Ten post edytował com 14.01.2017, 01:16:27
Go to the top of the page
+Quote Post
Omenomn
post
Post #95





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


  1. $upload = new Upload($imageSession);
  2. $upload->save($file);
  3. //Obraz z miniaturka
  4. $uploadImageWithThumbnail = new ImageWithThumbnail(new Upload($imageSession));
  5. $uploadImageWithThumbnail->save($file);
  6. //Video
  7. $videoSession = new SessionStorage('video');
  8. //Zwykły upload
  9. $upload = new Upload($videoSession);
  10. $upload->save($file);
  11. //Wideo z miniaturka
  12. $uploadVideoWithThumbnail = new VideoWithThumbnail(new Upload($videoSession));
  13. $uploadVideoWithThumbnail->save($file);


Ciekawe jak zapiszesz plik bez zapisywania informacji o nim do sesji, skoro klasa Upload wymaga interjejsu StorageInterface.
Gdzie masz kodowanie, zmianę nazwy randomową i do ustawienia?

W dekoratorze używa się jednego interfejsu, a nie jak tutaj:
  1. class Upload implements UploadInterface{}
  2. class SessionStorage implements StorageInterface{}
  3. class ImageWithThumbnail implements UploadInterface{}


No chyba, że bazę traktujesz jako:
  1. (new Upload($videoSession))

tylko po co ta sesja w konstruktorze?

Cytat
A tu co niby robisz https://github.com/omenomn/uploadDecorator/...sformers/Makers
W każdej klasie zwracasz 95% tych samych informacji.


To są transformery, one nie pobierają danych tylko transformują otrzymane dane do postaci jaką się potrzebuje. Działają na pojedynczym elemencie i kolekcji.

Cytat
A tu to już wgl szaleństwo
https://github.com/omenomn/uploadDecorator/...s/Puter.php#L11

Potrafisz stworzyć obiekt klasy abstrakcyjnej. Aż dziw że ten kod działa aarambo.gif


Nie tworzę obiektu klasy abstrakcyjnej tylko jej interfejsu. Klasa abstrakcyjna działa jak interfejs z tym, że metody możesz w niej dodawać.


Przykłady wywołania mojego kodu:
  1. $file = new Puter(new ImageSessionPuter(new Returner)); //Wysłanie pliku, zapis do sesji, zwrócenie
  2. $file = new Returner; // Samo zwrócenie danych o pliku
  3. $file = new ImageSessionPuter(new Returner); // Zapis do sesji danych o pliku bez uploadu
  4. $file = new Puter(new Returner); // Zapis pliku i zwrócenie informacji o nim
  5. $file = new ImageSessionPuter(new Puter(new Returner)) // zapis do sesji, wysłanie pliku,, zwrócenie - odwrotna kolejność
  6. $file = new RandomNamer(new Puter(new Returner));
  7. $file = new RandomNamer(new Encoder(new Puter(new Returner))) // losowa nazwa, kodowanie, zapis, zwrócenie danych
  8. $file->make($object);


Który kod jest bardziej elastyczny?
Odpowiedź jest chyba oczywista.

Ogólnie rzecz biorąc problem nie jest tak oczywisty do rozwiązania i błachy, jak wydaje mi się, że go większość potraktowała.

Ten post edytował Omenomn 14.01.2017, 06:02:35
Go to the top of the page
+Quote Post
daro0
post
Post #96





Grupa: Zarejestrowani
Postów: 88
Pomógł: 12
Dołączył: 17.09.2014
Skąd: Krasnystaw

Ostrzeżenie: (0%)
-----


Pod Laravela jest coś interesującego np. do obróbki zdjęć a i z uploadem sprawa powinna być prosta.

http://image.intervention.io/

Podobne podejście jak w Kohanie (gdzie jest moduł Image).

http://www.easylaravelbook.com/blog/2015/0...with-laravel-5/

Go to the top of the page
+Quote Post
Omenomn
post
Post #97





Grupa: Zarejestrowani
Postów: 77
Pomógł: 0
Dołączył: 4.02.2014

Ostrzeżenie: (20%)
X----


Wrzucałem już link do intervention image w tym temacie i pisałem, że go wykorzystuję.

Daro0 nie rozumiesz problemu, jeśli podrzucasz mi bibliotekę do obróbki zdjęć.
Ona nie wykonuje uploadu, zmiany nazw plików, zapisu danych o plikach do sesji, wycinania miniaturek z video, czy innych czynności związanych ogólnie z plikami, a nie tylko z obrazami.

Rozwiązanie, które przedstawiłem wykonuje wszystkie te operacje plus do tego jest całkowicie elastyczne, bo można dodawać poszczególne warstwy odpowiedzialne za kolejne operacje, bez ingerencji, w którąkolwiek warstwę już istniejącą, np. pobieranie wysokość i szerokość (wykorzystanie intervention image), albo rozmiaru pliku, czy innych właściwości. Mogę np. chcieć zmienić wielkość filmiku i wtedy po prostu dodaję warstwę odpowiedzialną za to.

Jeśli nie widzicie plusów takiego rozwiązania to Ja nie wiem...

ps.
Jednak warto było mimo wszystko temat umieścić, bo pomysł z dekoratorem przyszedł mi po próbach szukania odpowiedniego wzorca zainspirowany odpowiedziami tutaj między innymi mrc, a ostateczny szlif dokonał się po uzmysłowieniu sobie, że klasa bazowa dekoratora powinna funkcjonować sama (com)
Go to the top of the page
+Quote Post
rafkon1990
post
Post #98





Grupa: Zarejestrowani
Postów: 37
Pomógł: 9
Dołączył: 14.09.2016
Skąd: Śląskie

Ostrzeżenie: (0%)
-----


Jako obserwator tematu dziwię się że com jeszcze chce z tobą dyskutować. Jego kod jest czytelny, samoopisujacy sie, zrozumiały dla osób postronnych (przynajmniej tych znających OOP). Wystarczyło mi 3 minuty na zrozumienie całości (może dlatego że sam bym to zaimplementował bardzo podobnie).

Twoj kod omenomn analizowałem 5 minut i zrezygnowałem. Nie ma tam dzbła KISS, jeszcze te nazwy klas (puter, returner) ... może i twoje rozwiązanie jest zrozumiałe dla ciebie i w twoim mniemaniu jest elastyczne, ale do cholery nie mógł bym pracować na twoim kodzie, bo jest po prostu zbyt skomplikowany.

Ten post edytował rafkon1990 14.01.2017, 11:13:40
Go to the top of the page
+Quote Post
com
post
Post #99





Grupa: Zarejestrowani
Postów: 3 034
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


Cytat
Ciekawe jak zapiszesz plik bez zapisywania informacji o nim do sesji, skoro klasa Upload wymaga interjejsu StorageInterface.
Gdzie masz kodowanie, zmianę nazwy randomową i do ustawienia?


Tam masz interfejs wiec zapisujesz do czegokolwiek co implementuje ten interfejs. Przecież nie zrobię Ci gotowca, ja tylko wskazałem drogę która masz iść, Zmiana kodowania,nazwy itd to będą kolejne dekoratory, które sobie dopiszesz w miarę potrzeb.

Dekoratorem jest z tego fragmentu tylko:
  1. class ImageWithThumbnail implements UploadInterface{}


Upload to klasa bazowa, a SessionStorage wgl nie ma znaczenia dla dekoratora. Bo to jest zależność wstrzykiwana do Upload, dlatego możesz wstawić dowolny storage jaki sobie wymarzysz, warunek jest tylko taki musi implementować zdefiniowany interfejs.

Cytat
To są transformery, one nie pobierają danych tylko transformują otrzymane dane do postaci jaką się potrzebuje. Działają na pojedynczym elemencie i kolekcji.


Nie rozumiem wgl ich zastosowania, ale ja to wszytki zawarłem w jednej klasie File która działa dla wszystkich.

Cytat
Nie tworzę obiektu klasy abstrakcyjnej tylko jej interfejsu. Klasa abstrakcyjna działa jak interfejs z tym, że metody możesz w niej dodawać.


Owszem klasa abstrakcyjna może posiadać definicje jakiś wspólnych metod ale musi posiadać co najmniej jedną metodę abstrakcyjną, żeby można było ja nazwać klasa abstrakcyjna, inaczej to jest zwykła klasa.
To są podstawy programowania obiektowego.
Cytat
Który kod jest bardziej elastyczny?
Odpowiedź jest chyba oczywista.


Owszem jest, nie Twój i to nie jest moja tylko subiektywna opinia, ale reszta osób stwierdziła to samo.

Nie wiem gdzie Ty pracujesz, czy robisz to sam czy w jakimś zespole ale jak w zespole to niech ktoś zrobi Ci code review tego co stworzyłeś (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
Pyton_000
post
Post #100





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


@com Co do abstrakcji to klasa abstrakcyjna nie musi zawierać metod abstrakcyjnych (IMG:style_emoticons/default/wink.gif) Za to każda klasa która posiada przynajmniej 1 abstrakcyjną metodą musi być abstrakcyjna.

Tak więc

Kod
abstract class Test {
public function testing() {

}
}

jest poprawne.
Go to the top of the page
+Quote Post

10 Stron V   1 2 3 > » 
Closed TopicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.12.2025 - 19:29