Post
#1
|
|
|
Grupa: Zarejestrowani Postów: 82 Pomógł: 20 Dołączył: 17.01.2009 Skąd: Kraków Ostrzeżenie: (0%)
|
Witam,
Chciałem was prosić o ocenę jakości kodu OOP na przykładzie klasy. Ostatnio zacząłem zwracać większą uwagę na jakość swojego kodu. Jest to prosta klasa Mailer. Ma zadanie wysyłać maila oraz zapisywać go do bazy(w razie czego gdyby np była awaria smtp, to dobrze byłoby mieć tego maila w bazie). Mail to zwykła encja z polami (from, to, subject, body, created) - (kod będzie wykorzystywany w SF2.0) Pierwsza wersja klasy poniżej, to jest kod jaki zawsze pisałem. Generalnie z braku czasu mógłbym go zostawić. Ale ponieważ chciałem coś poprawić to zacząłem refaktorować.
Po pierwsze co mi się nie podoba to jaki pisze Robert C Martin im mniej argumentów mają funkcje tym lepiej. Chcę mieć publicznie metodę send(from,to,subject,body) dostępną bo tak mi pasuje, ale czy muszę te same argumenty wywoływać w dwóch metodach prywatnych ? Zastanawiałem się też, czy klasa nie łamię zasadę jednej odpowiedzialności(w końcu ona wysyła maila oraz zapisuje go do bazy) ale uznałem, że nie. Traktuję moją klasę jako Facadę(mamy pierwszy wzorzec projektowy) koordyującą te dwie czynności. Ok teraz druga wersja kodu:
Co się zmieniło - dopisaliśmy funkcję createMail - która ma za zadanie, utworzyć instancję klasy Mail i przypisać jej attrybuty. Zmieniłem nazwę metody addMailToDatabase na save. Być może w jakieś klasie dziediczącej będziemy chcieli zapisywać np do pliku a nie do bazy danych. Więc nazwa będzie odpowiedniejsza. Myślę, że już jest lepiej. Co możemy zrobić dalej. Na pewno createMail - jest do poprawy(nazwa jest zła, ona nie tylko tworzy ale także buduje mail) pasowałoby wykorzystać wzorzec FactoryMethod, gdybyśmy chcieli zmieniać encję,
Ok co zrobiliśmy - mamy teraz dwie metody createMail oraz buildMail, naturalnym okazało się przeniesienie $mail jako atrybut klasy, dzięki temu w poszeczególnych metodach mamy mniej argumentów - super. Czy to już koniec ? Moim zdaniem nie, zdecydowanie pasuję zrobić MailerBuilder(kolejny wzorzec) osobną klasę z metodami createMail oraz buildMail. Ok więc teraz wersja 4 kodu:
Ok mamy w końcu zamiast jednej klasy, dwie klasy. MailerBuilder i Mailer. W Mailerze w fajny sposób wykorzystujemy Buildera. Wszystko ok, generalnie mógłbym zakończyć refaktoryzacje. Niby wszystko ok, możemy przeciążąć save, sendMail, Buildera. Ale ciągle coś mi tu nie pasuję, czy to łamanie zasady jednej odpowiedzialności, czy może to, że w Mailer wykorzystujemy EntityManager oraz SwiftMailer a nie powinniśmy. No właśnie zdecydowanie należy stworzyć kolejne abstrakcje nazwijmy Sender or Saver i wykorzystać wzorzec Strategy. Ok a więc teraz wersja 5 kodu. Namnożyło się klas i interfejsów (IMG:style_emoticons/default/smile.gif)
SaverInterface oraz implementacja Savera zapisująca mail do bazy.
SenderInteface oraz implementacja Sendera wykorzystująca Swift_Mailer.
Oraz nasza klasa Mailera, która nie potrzebuje już zależności EntityManager oraz Swift_Mailer. Klasa MailBuilder nie zmieniła się już w stosunku do wersji 4. Teraz mamy chyba wszystko idealnie, możemy sobie konfigurować Mailera dowolnie z różnych Builderów, Senderów or Saverów. Pozbyłem się też wrażenia, że Mailer łamie zasadę jednej odpowiedzialności, teraz wyraźnie widać, że on koordynuję pracę róznych obiektów. Wykorzystane wzorce projektowe(Facade, Builder, FactoryMethod, Strategy, DI) I teraz chciałem się zapytać o ocenę, jakbyście ocenieli wersję 5 kodu, w skali 1-10. Patrząc też na to jak się zmieniłą wersja 1 od wersji5. Kto uważa, że to jest przerost formy nad treścią ? |
|
|
|
![]() |
Post
#2
|
|
|
Grupa: Zarejestrowani Postów: 279 Pomógł: 60 Dołączył: 25.02.2012 Ostrzeżenie: (0%)
|
Spoko rozwiązanie, ale co, jeśli zechcę zapisać maila za pomocą kilku różnych implementacji SaverInterface jednocześnie? (IMG:style_emoticons/default/tongue.gif)
|
|
|
|
Post
#3
|
|
|
Grupa: Zarejestrowani Postów: 82 Pomógł: 20 Dołączył: 17.01.2009 Skąd: Kraków Ostrzeżenie: (0%)
|
Spoko rozwiązanie, ale co, jeśli zechcę zapisać maila za pomocą kilku różnych implementacji SaverInterface jednocześnie? (IMG:style_emoticons/default/tongue.gif) Faktycznie dobry pomysł (IMG:style_emoticons/default/smile.gif) Teraz jest jeszcze elastyczniej, tak samo można wstrzykiwać tablicę senderów jakbyśmy chcieli. Wychodzi też zaleta OOP, bo kolejne wymagania/zmiany wymagań dużo łatwiej zakodować (IMG:style_emoticons/default/tongue.gif)
Ten post edytował ziolo 5.10.2014, 22:00:52 |
|
|
|
ziolo OOP - Design Patterns - Ocena jakości kodu 5.10.2014, 12:38:43
skowron-line Dam 2 za chęci.
Klasa Saver to pomyłka
1. wstrzyku... 5.10.2014, 14:06:40 
ziolo @skowron-line Dzięki wielkie za odpowiedź.
Cytat(... 5.10.2014, 15:17:37
MateuszS Hm akurat w tak prostym mailerze raczej ciężko o j... 26.10.2014, 21:31:33 ![]() ![]() |
|
Aktualny czas: 26.12.2025 - 17:35 |