[PL] Jak programować aby nie zwariować?

406 views

Published on

Oprogramowanie można podzielić na typu według wielu rożnych
kluczy, jednym z nich może być: czy buduje produkt który będę utrzymywał przez lata, czy piszę kod dla kogoś - i przyszłość rozwiązania to nie będzie już moje zmartwienie. Przy tak postawionym pytaniu zasadnicza różnica dotyczy jakości, nie tylko ostatecznego produktu (działa czy nie działa) ale jakości samego rozwiązania. Nie tego co zostało dostarczone ale jak zostało zrobione. Bo właśnie to 'jak' wpływa później na koszt nanoszenia poprawek, dodawania kolejnych elementów, poprawiania ewentualnych błędów. Na wykładzie chciałbym przybliżyć te zasady jak, jak programować aby później z trwoga nie wracać do fragmentów sprzed lat. Jakich trzymać się zasad aby kod był czytelny, klarowny, intencja jasna a całość była dobrze zaprojektowana

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
406
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

[PL] Jak programować aby nie zwariować?

  1. 1. Jak programować abynie zwariować?Jakub Marchwicki04.04.2013
  2. 2. Na początek
  3. 3. Co to za gość?
  4. 4. Co ja tu robię?
  5. 5. Co ja tu robię?
  6. 6. Co ja tu robię?
  7. 7. Co ja tu robię?ból
  8. 8. Co ja tu robię?bólliczba slajdów
  9. 9. Co ja tu robię?bólliczba slajdówOKRyzykoutratyzdrowia35 slajdów
  10. 10. Co ja tu robię?bólliczba slajdówOKRyzykoutratyzdrowia205 slajdów
  11. 11. I po co to wszystko?Bo software to nasze hobby
  12. 12. I po co to wszystko?Bo software to nasze hobbyfach
  13. 13. I po co to wszystko?Bo software to nasze hobbyfachzawód
  14. 14. I po co to wszystko?Bo software to nasze hobbyfachzawódprzyjemność
  15. 15. I po co to wszystko?bo płacą nam za pisaniedokumentacjipisanie kodu to przyjemność
  16. 16. Punkt wyjścia
  17. 17. Punkt wyjścia
  18. 18. Kiedy software jest dobry?Oprogramowanie musi działaćMusi być na czasMusi być rozbudowywalneModyfikowalneMusi mieć odpowiednią jakośćPunkt wyjścia
  19. 19. Kiedy software jest dobry?Oprogramowanie musi działaćMusi być na czasMusi być rozbudowywalneModyfikowalneMusi mieć odpowiednią jakośćTo zależy???Punkt wyjścia
  20. 20. Więc czym jest jakośćDla kogoś Dla siebieDla kogo pracuje?
  21. 21. Więc czym jest jakośćDla kogoś Dla siebieDla kogo pracuje?
  22. 22. „Jakość (jak piękno) jest sądemwartościującym, wyrażonym przezużytkownika. Jeśli nie ma takiegoużytkownika – nie ma takiego sądu”PlatonWięc czym jest jakość
  23. 23. Więc czym jest jakośćDla kogoś Dla siebieDla kogo pracuje?
  24. 24. „Jakość to sposób myślenia,który powoduje, że stosuje się ibez przerwy poszukujenajlepszych rozwiązań”William Edwards DemingWięc czym jest jakość
  25. 25. Plan-Do-Study-Act
  26. 26. If design is a hypothesishow can you prove it?Czy mój software jest dobrej jakości?
  27. 27. Czy mój software jest dobrej jakości?Oprogramowanie musi działaćMusi być na czasMusi być rozbudowywalneModyfikowalneMusi mieć odpowiednią jakość
  28. 28. Jak programować aby nie zwariować?
  29. 29. Użyjmy frameworka
  30. 30. Konkretyzacja pewnej ideiWprowadzenie uporządkowanegosposoby pracyUjęcie złożonych czynności w zestawpowtarzalnych krokówFramework to pewna obietnica
  31. 31. No więc mamy to zadanieI ten ciekawy framework…Wyobraźmy sobie nowy projekt…
  32. 32. …w którym framework nie zadziałał
  33. 33. Szukamy doświadczenia, pytamy
  34. 34. Samodzielnie poszukujemy drogi
  35. 35. Stosujemy framework na siłę
  36. 36. Porzucamy framework i robimy po staremu
  37. 37. I jeżeli ma szczęście do pierwszy dwóch
  38. 38. A po latach
  39. 39. • Kod jest podstawowym mediumkomunikacji w projekcie• Zły kod to jak solenie herbaty koledzez zespołu albo plucie do kanapki – aprzecież nie jesteśmy złośliwiWartości
  40. 40. • Jako zespół jesteśmy jednością– Jak ja pójdę na skróty, to kolegabędzie się męczył– I jako całość i tak będziemynieefektywniWartości
  41. 41. • Programy są częściej czytane niżpisane• Więcej czasu poświęcamy namodyfikację istniejącego kodu niż natworzenie nowegoImplementation Patterns
  42. 42. • Komunikacja – kod źródłowy powinnosię czytać jak książkę• Prostota – wprowadzaj złożonośćtylko wtedy, kiedy jest to konieczne• Elastyczność – elastyczność tododatkowa złożoność, więcwprowadzaj ją tylko tam gdzie tokonieczneImplementation patterns
  43. 43. • Lokalne konsekwencje – zmiana wjednym miejscu nie powoduje zmian winnych• Minimalne powtórzenia – DRYImplementation patterns
  44. 44. • Dane i logika razem – ponieważ danei logika z reguły zmieniają się w tymsamym czasie• Symetria – utrzymuj podobny poziomabstrakcji w obrębie metody / klasyImplementation patterns
  45. 45. „Czysty kod jest prosty i bezpośredni.Czysty kod czyta się jak dobrzenapisaną prozę. Czysty kod nigdy niezaciemnia zamiarów projektanta; jestpełen trafnych abstrakcji i prostychścieżek sterowania.”Grady Booch – to jeden z tych panów od UMLa
  46. 46. Czysty kod
  47. 47. Czysty kod
  48. 48. • Po prostu głęboko wierzymy że dobrykod nam pomoże• Choć nie wiemy jak, intuicyjniestaramy się go stosować• Z pokorą przyjmujemy karcący wzrokmnichaNie wiemy że nie wiemy
  49. 49. • Uczymy się… bez wnikania w kontekst Nazywaj zmienne w taki a taki sposób Stosuj komentarze w takich a nie innychprzypadkach Dziel funkcje na części zgodnie z takimia takimi zasadami• Z czasem zobaczymy że z czystymkodem lepiej się pracuje… tak poludzku
  50. 50. Nasz mózg lepiej reaguje na czysty kod• Utrzymujemy koncentrację• Nie gubimy wątków, swobodniejpodążamy tokiem myślenia• Cognitive load – możemy pomieścićposzczególne kawałki kodu w głowiewięc potrafimy się miedzy nimiswobodnie przemieszczać
  51. 51. • Nazwy• Funkcje• Komentarz• Formowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  52. 52. • Nazwy• Funkcje• Komentarz• Formatowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  53. 53. • Nazwy zmiennych, metod, klaspowinny być wystarczająco opisoweaby zrozumieć jaką wartośćprzetrzymuje zmienna i jaką czynnośćwykonuje metoda.Zmienne
  54. 54. • Nazwy nie powinny wymagaćdodawania komentarza• Nazwy zmiennych nie mogąwprowadzać w błąd!• Nazwy metod nie mogą ukrywaćfunkcjonalności!Nazewnictwo
  55. 55. int d1; //dni od rozpoczęciaint d2; //dni do zakończeniaint d3; //dni wolnychint daysSinceStart;int daysTillEnd;int daysOf;public List<int[]> getThem() {List<int[]> list1 = new ArrayList<int[]>();for (int[] x : theList)if (x[0] == 4)list1.add(x);return list1;} public List<int[]> getDates() {List<int[]> dateList = new ArrayList<int[]>();for (int[] week : theWeeksArray)if (week[0] == BEGIN_DATE)dateList.add(x);return dateList;}
  56. 56. for (int i=0; i<10; i++){k += ((l[i]*1.5) / 3 );}float milleageRate;const int NUMER_OF_EMPLOYEE = 3;float sum = 0;for ( int i=0; i<numberOfTrips; i++ ){float totalCompensation = tripLength[i] * milleageRate;float deduction = totalCompensation / NUMER_OF_EMPLOYEE;sum += deduction;}
  57. 57. • Korzystaj z nazw, które możnawymówićUłatwiają zapamiętywanieUmożliwiają swobodną dyskusję o kodzieNazwewnictwo
  58. 58. public class CsmrDt {public void crtshpcrt() {/*...*/};public void remcrt() {/*...*/};private final int ssntm = 10;/*...*/}public class CustomerDataset {public void createShoppingCart() {/*...*/};public void removeCart() {/*...*/};private final int sessionTimeout = 10;/*...*/}
  59. 59. • Używaj rzeczowników lub wyrażeńrzeczownikowych do nazywania klasnp.: Customer, Account, Page• Nie nazywaj klas za pomocączasowników• Używaj nazw konkretnych a nie“wszystkoznaczących”ManagerFactoryProcessorKlasy
  60. 60. • Używaj czasowników lub wyrażeńczasownikowych do nazywania metod np.:addUser, deleteCustomer, update• Twórz nazwy metod tak, aby wyrażały to corobiąMetody
  61. 61. • Nazwy powinny sugerować co zwracają• Nazwy muszą mówić o całym zakresiefunkcjonalnościMetodyString findLastNameOfCustomerWithId(long customerId){...}Map<Long, Customer> customers;Customer getCustomer(Long id){Customer customer = customers.get(id);if(customer == null){customer = createNewCustomer(id);}return customer;}
  62. 62. • Bądź konsekwentny i używaj tych samychsłów do określania podobnych czynności,np.: add, get, DeviceManager,ProtocolControllerMetody
  63. 63. • Nazwy• Funkcje• Komentarz• Formatowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  64. 64. • Zasada pierwsza:funkcje powinny być małe• Zasada druga:funkcje powinny być jeszcze mniejszeFunkcje
  65. 65. Functions should do one thing.Should do it wellShould do it only!Funkcje
  66. 66. Funkcje• Korzystaj z nazw dokładnie opisującychprzeznaczenie funkcji• Nie obawiaj się konstruowania długich nazw• Stosuj spójne nazwy - wykorzystuj te same frazy,rzeczowniki czy czasowniki dla funkcjiwykonujących analogiczne operacje• addCustomer, putItemToBasket• UserSettings, AdminConfiguration• Nie ukrywaj funkcjonalności za złymi nazwamifunkcji
  67. 67. Funkcje• Pisz funkcje zawierające jak najmniejszą liczbęargumentów• Funkcją idealną jest funkcja bezargumentowa• Dopuszczalne są funkcjejedno- i dwuargumentowe• Unikaj funkcji już z trzema argumentami• Funkcje posiadające więcej niż trzy argumentystosuj tylko w uzasadnionych sytuacjach
  68. 68. writeField(outputStream, name);outputStream.writeField(name);createSquare(width, height);calculateRectangularPrismVolume(double height,double width, double depth);calculateRectangularPrismVolume(Area rectangle,double depth);
  69. 69. Funkcje• Stosuj wyjątki zamiast zwracaniakodów błędów• Korzystanie z kodów błędów tworzygłęboko zagnieżdżone struktury• Wyjątki pozwalają na oddzielenieprzetwarzania błędów od prawidłowejścieżki wykonywania kodu
  70. 70. if (changeDate(date) == OK) {if (dateFilled(date) == OK) {if (dateFromFuture(date) == OK) {System.out.println("Data została zmieniona.");} else {System.out.println("Data niepoprawna.");}} else {System.out.println("Brak podanej daty.");}} else {System.out.println("Błąd podczas zmiany daty.");return ERROR;}try {changeDate(date);dateFilled(date);dateFromFuture(date);}catch (Exception e) {System.out.println(e.getMessage());}
  71. 71. FunkcjeDRY – Don’t repeat yourself• Duplikacja zmniejsza czytelność• Zwiększa koszty utrzymania, refactoringu ipoprawiania błędów• Prowadzi do rozbieżności funkcjonalnejmodułów wykonujących to samo• Zmniejsza reusability kodu
  72. 72. FunkcjeJeden poziom abstrakcji na funkcje• Nie realizuj w funkcji zadań które operująna innych poziomach abstrakcji• Pomieszane poziomy abstrakcjizmniejszają czytelność kodu, utrudniajązrozumienie logiki i prowadzą dozwiększenia duplikacji kodu
  73. 73. • Nazwy• Funkcje• Komentarz• Formatowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  74. 74. KomentarzeDON’T
  75. 75. Komentarze„Nie komentuj złego kodu – popraw go”Brian W. Kernighan i P.J. Plaugher
  76. 76. KomentarzeSą złe bo• Często się powtarzają• Są mylące• Nadmiarowe• Klamry zamykające• Zakomentowany kod• Informacje nielokalne• Nie są utrzymywane
  77. 77. Komentarze• Konieczność dodania komentarzaoznacza zazwyczaj kod dopoprawienia• Napraw i uporządkuj zły kod a niekomentuj
  78. 78. //Sprawdzenie czy klient ma możliwość korzystania ze zniżkiif (customer.isStudent() ||(customer.age < 18) || (customer.age > 65))if (customer.isEligibleForDiscount())
  79. 79. KomentarzeBywają dobre, np:• Komentarze prawne• Komentarze informacyjne• Wyjaśnienia• Ostrzeżenia• Komentarze TODO// Dopasowany format kk:mm:ss EEE, MMM dd, yyyyPattern timeMacher = Pattern.compile("d*:d*:d* w*, w* d*, d*")
  80. 80. Komentarze• Nieprawdą jest, że wszystkie funkcjepowinny posiadać Javadoc, a każdazmienna komentarz• Ten typ komentarzy powodujezaciemnianie kodu i dezorganizację
  81. 81. public abstract class ContainerBase implementsContainer, Lifecycle, Pipeline,MBeanRegistration, Serializable {/*** The processor delay for this component.*/protected int backgroundProcessorDelay = -1;/*** The lifecycle event support for this component.*/protected LifecycleSupport lifecycle = new LifecycleSupport(this);/*** The container event listeners for this Container.*/protected ArrayList listeners = new ArrayList();/*** The Loader implementation with which this Container is associated.*/protected Loader loader = null;/*** The Logger implementation with which this Container is associated.*/protected Log logger = null;/*** Associated logger name.*/protected String logName = null;/*** The Manager implementation with which this Container is associated.*/protected Manager manager = null;
  82. 82. „If you decide to write a comment, thenspend the time necessary to make sure it isthe best comment you can write”Robert C. MartinKomentarze
  83. 83. • Nazwy• Funkcje• Komentarz• Formatowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  84. 84. Formatowanie• Konwencje formatowania w zespole.Ustal i się ich trzymaj
  85. 85. Formatowanie• Odpowiednie formatowanie koduułatwia czytanie klasy.• Redukuje czas potrzebny na szukanieskładowych, konstruktorów itp.• Nie musimy przeglądać całej klasy abysprawdzić czy ma konstruktor bowiemy dokładnie gdzie go szukać
  86. 86. • Nazwy• Funkcje• Komentarz• Formatowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  87. 87. • Ukrywaj szczegóły techniczne i stosujterminy abstrakcyjneAbstrakcja danychpublic static interface Vehicle {double getFuelTankCapacityInGallons();double getGallonsOfGasoline();}public static interface Vehicle {double getPercentFuelRemaining();}
  88. 88. • Prawo Demeter – zasada minimalnejwiedzy• Moduł powinien nie wiedzieć nic ownętrzu obiektów, którymi manipulujePrawo Demeter
  89. 89. • Prawo Demeter głosi, że metoda fklasy C powinna wywoływać tylkometody z:• Klasy C,• Obiektu utworzonego przez f,• Obiektu przekazanego jako argument f,• Obiektu umieszczonego w zmiennejinstancyjnej klasy C.Prawo Demeter
  90. 90. • Możesz bawić się ze sobą• Możesz bawić się własnymizabawkami (ale nie możesz ichrozbierać)• Możesz bawić się zabawkami któredostałeś• Możesz bawić się zabawkami którezrobiłeś samodzielniePrawo Demeter
  91. 91. final String outputDir = context.getOptions().getScratchDir().getAbsolutePath();Options options = context.getOptions();File scratchDir = options.getScratchDir();final String outputDir = scratchDir.getAbsolutePath();
  92. 92. // before refactoringclass Customer {String getMailingAddressLine1();String getMailingAddressLine2();String getShippingAddressLine1();String getShippingAddressLine2();}class Employee {String getHomeAddressLine1();String getHomeAddressLine2();}public void method() {customer.getMailingAddressLine1();employee.getHomeAddressLine1();}
  93. 93. // before refactoringclass Customer {String getMailingAddressLine1();String getMailingAddressLine2();String getShippingAddressLine1();String getShippingAddressLine2();}class Employee {String getHomeAddressLine1();String getHomeAddressLine2();}public void method() {customer.getMailingAddressLine1();employee.getHomeAddressLine1();}// after refactoring, before Demeteringclass Address {String getLine1();String getLine2();}Class Customer {Address getMailingAddress();Address getShippingAddress();}class Employee {Address getHomeAddress();}public void method() {customer.getMailingAddress().getLine1();employee.getHomeAddress().getLine1();}
  94. 94. // before refactoringclass Customer {String getMailingAddressLine1();String getMailingAddressLine2();String getShippingAddressLine1();String getShippingAddressLine2();}class Employee {String getHomeAddressLine1();String getHomeAddressLine2();}public void method() {customer.getMailingAddressLine1();employee.getHomeAddressLine1();}// after refactoring, before Demeteringclass Address {String getLine1();String getLine2();}Class Customer {Address getMailingAddress();Address getShippingAddress();}class Employee {Address getHomeAddress();}public void method() {customer.getMailingAddress().getLine1();employee.getHomeAddress().getLine1();}//after Demeterizingclass Address { // same as aboveString getLine1();String getLine2();}class Customer {Address getMailingAddress();Address getShippingAddress();String getMailingAddressLine1();String getMailingAddressLine2();String getShippingAddressLine1();String getShippingAddressLine2();}class Employee {Address getHomeAddress();String getHomeAddressLine1();String getHomeAddressLine2();}public void method() {customer.getMailingAddressLine1();employee.getHomeAddressLine1();}
  95. 95. • Ukrywaj szczegóły wnętrza obiektów• Nie łam hermetyzacji bez powodu,łatwiejsze pisanie testów nie jestpowodemPrawo DemeterBufferedOutputStream bos =context.createScratchFileStream(classFileName);
  96. 96. • Za idealną formę struktur danychprzyjmuje się obiekty transferu danych(DTO)• Są przydatne do komunikowania się zbazą danych, analizowaniakomunikatów z gniazd sieciowych itp.Data Transfer Objects
  97. 97. • DTO są to mogą być klasypozbawione funkcji, ale ze zmiennymipublicznymi• Częściej spotykaną formą jest postaćtypu beans• Posiada ona zmienne prywatne, doktórych dostęp uzyskuje się zapomocą getterów i setterówData Transfer Objects
  98. 98. public class Client {private String name;private String lastName;private long clientId;public Client(long clientId, String name, String lastName) {this.clientId = clientId;this.name = name;this.lastName = lastName;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getLastName() {return lastName;}public void setlastName(String lastName) {this.lastName = lastName;}public long getClientId() {return clientId;}}
  99. 99. Budowanie oprogramowania zwykorzystaniem struktur danychwpływa w przyszłości na:Budowanie oprogramowania zwykorzystaniem obiektów wpływa na:łatwość i elastyczność dodawanianowych funkcji – dodanie nowejfunkcji nie wymaga zmiany żadnej zestrukturłatwość i elastyczność w dodawaniunowych obiektów – nie wymagazmiany żadnych funkcji ani innychobiektówtrudność dodawania nowych struktur– musimy zmienić wszystkie funkcjetrudność dodawania nowych funkcji –musimy zmienić wszystkie obiektyObiekty vs struktury danych
  100. 100. • Nazwy• Funkcje• Komentarz• Formatowanie kodu• Obiekty i struktury danych• Obsługa błędówPoziom I
  101. 101. • Mówiliśmy o kodach błędu i wyjątkach• O blokach try-catch-finally
  102. 102. • Grupuj wyjątki ze względu na kontekst izachowuj symetrię w kodzie• Osłaniaj wyjątki:• przechwytuj i przekształcaj zgłaszane wyjątki• uniezależniaj się od wyjatków wprowadzonych przezAPI, używaj wyjątków specyficznych dla własnejaplikacjiKlasy wyjątków
  103. 103. ACMEPort port = new ACMEPort(12);try {port.open();} catch (DeviceReponseException e) {reportPortError(e);logger.log("Wyjątek odpowiedzi urządzenia", e);} catch (ATM1212UnlockedException e) {reportPortError(e);logger.log("Wyjątek odblokowania", e);} catch (GMXError e) {reportPortError(e);logger.log("Wyjątek odpowiedzi urządzenia");} finally {/*...*/}
  104. 104. ACMEPort port = new ACMEPort(12);try {port.open();} catch (DeviceReponseException e) {reportPortError(e);logger.log("Wyjątek odpowiedzi urządzenia", e);} catch (ATM1212UnlockedException e) {reportPortError(e);logger.log("Wyjątek odblokowania", e);} catch (GMXError e) {reportPortError(e);logger.log("Wyjątek odpowiedzi urządzenia");} finally {/*...*/}LocalPort port = new LocalPort(12);try {port.open();} catch (PortDeviceFailure e) {reportError(e);logger.log(e.getMessage(), e);} finally {/*...*/}public class LocalPort {private ACMEPort innerPort;public LocalPort(int portNumber) {innerPort = new ACMEPort(portNumber);}public void open() {try {innerPort.open();} catch (DeviceResponseException e) {throw new PortDeviceFailure(e);} catch (ATM1212UnlockedException e) {throw new PortDeviceFailure(e);} catch (GMXError e) {throw new PortDeviceFailure(e);}}/*...*/}
  105. 105. Zwracanie nullDON’T
  106. 106. • Wykorzystuj zgłaszanie wyjątków lubzwracanie obiektu specjalnegoprzypadkuZwracanie nullList<Item> items = getItems();if (items != null) {for (Item i : items) {totalCost += i.getCost();}}List<Item> items = getItems();for(Item i : items) {totalCost += i.getCost();}
  107. 107. public interface Animal {public void makeSound();}public class Dog implements Animal {public void makeSound() {System.out.println("woof!");}}public class NullAnimal implements Animal {public void makeSound() {}}
  108. 108. • Przekazywanie null jest gorsze odjego zwracaniaPrzekazywanie nullpublic class MetricsCalculator {public double rectanglePerimeterCalculate(double x, double y) {return 2 * (y + x);}/* ... */}
  109. 109. • Defensive programmingPrzekazywanie nullpublic class MetricsCalculator {public double rectanglePerimeterCalculate(double x, double y) {if (x == null || y == null) {throw InvalidArgumentException("Niewłaściwyargument.");}return 2 * (y + x);}} public class MetricsCalculator {public double rectanglePerimeterCalculate(double x, double y) {assert x != null : "x nie może być null";assert y != null : "y nie może być null";return 2 * (y + x);}}
  110. 110. Miara czystego kodu
  111. 111. Czysty projekt
  112. 112. • SOLID• Zasady programowania obiektowego• Zasady projektowania obiektowegoPoziom II
  113. 113. SOLIDny programista• The Single Responsibility Principle – klasapowinna mieć tylko jeden powód do zmiany• The Open Closed Principle – klasę możnałatwo rozszerzać, nie modyfikując jej• The Liskov Substitution Principle – klasypochodne muszą być przeźroczystymizamiennikami klasy nadrzędnej
  114. 114. • The Interface Segregation Principle – dlaróżnych klientów twórz osobne interfejsy• The Dependency Inversion Principle –bądź zależny od abstrakcji a nie odkonkretnych implementacjiSOLIDny programista
  115. 115. • Należy znać hierarchię dziedziczenia, abyzrozumieć metodę• Kod metody polimorficznej jest rozrzuconypo kilku klasach• Nie zawsze jest oczywisty stan obiektu, zktórego dziedziczymy• Dodatkowe elementy (pola, metody) sąmocno związane (coupling) z klasąnadrzędnąKompozycja i dziedziczenie
  116. 116. • Niezależność klas zawieranych• Można je używać w wielu kontekstach• Niskie związanie (coupling)• Łatwiej testowaćKompozycja i dziedziczenie
  117. 117. To znaczy jaki?Kod obiektowy
  118. 118. • Odpowiedzialność – tylko jedna obiekty maja własną osobowość,unikaj schizofrenicznych obiektów• Enkapsulacja – to co się zmieniaenkaspuluj• Preferencja kompozycji ponaddziedziczenie
  119. 119. • Dokładanie ponad modyfikacje– Gdy dodajemy nową funkcjonalność raczej dokładamynowe byty niż modyfikujemy istniejące.• Lokalne zmiany– Zmiana ma konsekwencje lokalne, a nie globalne.Zasięg rażenia zmian jest jak najmniejszy.• Nieinwazyjność zmian– Dodanie nowych rzeczy (odpowiedzialności,funkcjonalności, zachowań) do istniejących bytów jestprzezroczyste ich dla klientów.
  120. 120. public class Sql {public Sql(String table, Column[] columns)public String create()public String insert(Object[] fields)public String selectAll()public String fieldByKey(String keyColumn, String keyValue)private String ColumnList(Column[] columns)private String valuesList(Object[] fields, final Column[] columns)}
  121. 121. abstract public class Sql {public Sql(String table, Column[] columns)abstract public String generate();}public class CreateSql extends Sql {public CreateSql(String table, Column[] columns)@Override public String generate()}public class SelectSql extends Sql {public SelectSql(String table, Column[] columns)@Override public String generate()}public class InsertSql extends Sql {public InsertSql(String table, Column[] columns)@Override public String generate()private String valuesList(Object[] fields, final Column[] columns)}public class FindKeyBySql extends Sql {public FindKeyBySql(String table, Column[] columns, String keyColumn, String keyValue)@Override public String generate()}public class ColumnList {public ColumnList(Column[] columns)public String generate()}
  122. 122. Odpowiedzialność. Enkapsulacja. Kompozycja• To co leży u podstaw możemystosować na każdym poziomie• Projektując klasy• Projektując moduły, komponenty• Projektując systemy
  123. 123. • Każdy wzorzec opisujemy w trzechkontekstach: Odpowiedzialność Enkapsulacja / hermetyzacja KompozycjaWzorce projektowe
  124. 124. • Rozdziela i przesłania implementacjęzachowań, czynności.• Hermetyzujemy zmienny sposóbtworzenia obiektów• Nowe funkcjonalności uzyskujemypoprzez dodawanie komend, poprzezkompozycję.Wzorce projektowe: komenda
  125. 125. Wzorce projektowe: komenda
  126. 126. • Każdy element systemu: Ma swoją odpowiedzialność Hermetyzuje pewne zachowania Składa się z kilku współpracującychelementówModuły
  127. 127. • Boundary: zewnętrzny interfejs,kontrakt, fasada• Control: logika biznesowa,implementacja• Entity: persystencjaBoundary. Control. Entity
  128. 128. Entity. Control. Boundary
  129. 129. • Każdy framework opisujemy w trzechzdaniach: Odpowiedzialność Enkapsulacja Preferowanie kompozycjiFrameworki
  130. 130. • Pozwala na obiektowy dostęp do bazydanych• Enkapsulujemy typ bazy, sposóbdostępu do danych• Preferencja kompozycji (?)ORM
  131. 131. • Nie ważne czy na poziomie klasy,modułu, frameworka – stosujemy tesame bazowe pojęcia• Dedukujemy, indukujemy –posługujemy się doświadczeniem• Rozumiemy że nie ma uniwersalnychrozwiązań – ważny jest kontekst.
  132. 132. • Spring czy EJBNie ma idealnych rozwiązań
  133. 133. • Spring czy EJB• JSF czy JSPNie ma idealnych rozwiązań
  134. 134. • Spring czy EJB• JSF czy JSP czy VelocityNie ma idealnych rozwiązań
  135. 135. • Spring czy EJB• JSF czy JSP czy Velocity• JPA czy iBatisNie ma idealnych rozwiązań
  136. 136. • Spring czy EJB• JSF czy JSP czy Velocity• JPA czy iBatis czy JDBCNie ma idealnych rozwiązań
  137. 137. • Spring czy EJB• JSF czy JSP czy Velocity• JPA czy iBatis czy JDBC• MVC czy MVPNie ma idealnych rozwiązań
  138. 138. • Spring czy EJB• JSF czy JSP czy Velocity• JPA czy iBatis czy JDBC• MVC czy MVP• Java czy .NETNie ma idealnych rozwiązań
  139. 139. • Spring czy EJB• JSF czy JSP czy Velocity• JPA czy iBatis czy JDBC• MVC czy MVP• Java czy .NET czy PythonNie ma idealnych rozwiązań
  140. 140. • Spring czy EJB• JSF czy JSP czy Velocity• JPA czy iBatis czy JDBC• MVC czy MVP• Java czy .NET czy Python czy PHPNie ma idealnych rozwiązań
  141. 141. Po co to wszystko?
  142. 142. Build better systems
  143. 143. Complexity and confusion
  144. 144. Complexity and confusion
  145. 145. Bo nasz mózg pracuje zupełnie inaczej
  146. 146. Affordance
  147. 147. Affordancea quality of an object, whichallows an individual to performan action. For example, a knobaffords twisting, and perhapspushing, while a cord affordspulling
  148. 148. public class Sql {public Sql(String table, Column[] columns)public String create()public String insert(Object[] fields)public String selectAll()public String fieldByKey(String keyColumn, String keyValue)private String ColumnList(Column[] columns)private String valuesList(Object[] fields, final Column[] columns)}
  149. 149. abstract public class Sql {public Sql(String table, Column[] columns)abstract public String generate();}public class CreateSql extends Sql {public CreateSql(String table, Column[] columns)@Override public String generate()}public class SelectSql extends Sql {public SelectSql(String table, Column[] columns)@Override public String generate()}public class InsertSql extends Sql {public InsertSql(String table, Column[] columns)@Override public String generate()private String valuesList(Object[] fields, final Column[] columns)}public class FindKeyBySql extends Sql {public FindKeyBySql(String table, Column[] columns, String keyColumn, String keyValue)@Override public String generate()}public class ColumnList {public ColumnList(Column[] columns)public String generate()}
  150. 150. George Miller
  151. 151. Multi store memory model
  152. 152. Mihaly Csikszentmigalyi
  153. 153. ME-HI CHICKS-SENT-ME-HI
  154. 154. Po co to wszystko?
  155. 155. Budujemy nawyki
  156. 156. Nie po to aby było ładnie
  157. 157. Nie aby było elegancko
  158. 158. By żyło się lepiej
  159. 159. • Pytamy doświadczonego kolegęCo robimy gdy robi się gorąco
  160. 160. • Pytamy doświadczonego kolegę• Sami szukamy drogiCo robimy gdy robi się gorąco
  161. 161. • Pytamy doświadczonego kolegę• Sami szukamy drogi• Próbujemy na siłęCo robimy gdy robi się gorąco
  162. 162. • Pytamy doświadczonego kolegę• Sami szukamy drogi• Próbujemy na siłę• Porzucamy i wracamy donawykówCo robimy gdy robi się gorąco
  163. 163. SingleResponsibilityOpen ClosesPrincipleLiskov SubstitutionInterfaceSegregationDependencyInjectionSingletonsTight CouplingUntestable CodePrematureOptimizationIndescriptiveNamingDuplication
  164. 164. SingleResponsibilityOpen ClosesPrincipleLiskov SubstitutionInterfaceSegregationDependencyInjectionSingletonsTight CouplingUntestable CodePrematureOptimizationIndescriptiveNamingDuplication
  165. 165. • Nie ma kodu perfekcyjnego• Ale jest wystarczająco dobry modyfikowalny refaktoryzowalny „disposible” over „maintainable”• Kod który mogę w każdej chwiliwyrzucić i wymienićTworzymy dobry kod
  166. 166. Jak żyć?
  167. 167. Jak żyć?
  168. 168. Jak żyć?
  169. 169. Jak żyć?
  170. 170. Jak żyć?
  171. 171. Jak żyć?2010
  172. 172. Jak żyć?2010
  173. 173. Jak żyć?20102009
  174. 174. Jak żyć?20102009
  175. 175. Jak żyć?20102009
  176. 176. Jak żyć?201020092009
  177. 177. Jak żyć?201020092009
  178. 178. Jak żyć?2010200920092008
  179. 179. Jak żyć?2010200920092008
  180. 180. Jak żyć?20102009200920082007
  181. 181. Jak żyć?
  182. 182. Jak żyć?2002
  183. 183. Jak żyć?2002
  184. 184. Jak żyć?20021996 / 2000
  185. 185. Jak żyć?20021996 / 2000
  186. 186. Jak żyć?20021996 / 20002002
  187. 187. Jak żyć?20021996 / 20002002
  188. 188. Jak żyć?20021996 / 200020021994
  189. 189. Jak żyć?
  190. 190. Jak żyć?
  191. 191. Shu-Ha-Ri
  192. 192. jmarchwicki@ydp.euhttp://marchwicki.pl/blog@kubemShu-Ha-Ri

×