14. Kiedy software jest dobry?
Oprogramowanie musi działać
Musi być na czas
Musi być rozbudowywalne
Modyfikowalne
Musi mieć odpowiednią jakość
Punkt wyjścia
16. I po co to wszystko?
Bo software to nasze hobby
17. I po co to wszystko?
Bo software to nasze hobby
fach
18. I po co to wszystko?
Bo software to nasze hobby
fach
zawód
19. I po co to wszystko?
Bo software to nasze hobby
fach
zawód
przyjemność
20. I po co to wszystko?
bo płacą nam za pisanie
dokumentacji
pisanie kodu to przyjemność
21. Więc czym jest jakość
Dla kogoś Dla siebie
Dla kogo pracuje?
22. Więc czym jest jakość
Dla kogoś Dla siebie
Dla kogo pracuje?
23. „Jakość (jak piękno) jest sądem
wartościującym, wyrażonym przez
użytkownika. Jeśli nie ma takiego
użytkownika – nie ma takiego sądu”
Platon
Więc czym jest jakość
31. Więc czym jest jakość
Dla kogoś Dla siebie
Dla kogo pracuje?
32. „Jakość to sposób myślenia,
który powoduje, że stosuje się i
bez przerwy poszukuje
najlepszych rozwiązań”
William Edwards Deming
Więc czym jest jakość
36. • Uczymy się… bez wnikania w kontekst
Nazywaj zmienne w taki a taki sposób
Stosuj komentarze w takich a nie innych
przypadkach
Dziel funkcje na części zgodnie z takimi
a takimi zasadami
• Z czasem zobaczymy że z czystym
kodem lepiej się pracuje… tak po
ludzku
37. Nasz mózg lepiej reaguje na czysty kod
• Utrzymujemy koncentrację
• Nie gubimy wątków, swobodniej
podążamy tokiem myślenia
• Cognitive load – możemy pomieścić
poszczególne kawałki kodu w głowie
więc potrafimy się miedzy nimi
swobodnie przemieszczać
38. • Nazwy
• Funkcje
• Komentarz
• Formowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
39. • Nazwy
• Funkcje
• Komentarz
• Formatowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
40. int d1; //dni od rozpoczęcia
int d2; //dni do zakończenia
int d3; //dni wolnych
int 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;
}
41. 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;
}
42. 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;
/*...*/
}
43. • Nazwy powinny sugerować co zwracają
• Nazwy muszą mówić o całym zakresie
funkcjonalności
Metody
String findLastNameOfCustomerWithId(long customerId){...}
Map<Long, Customer> customers;
Customer getCustomer(Long id){
Customer customer = customers.get(id);
if(customer == null){
customer = createNewCustomer(id);
}
return customer;
}
44. • Nazwy
• Funkcje
• Komentarz
• Formatowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
45. • Zasada pierwsza:
funkcje powinny być małe
• Zasada druga:
funkcje powinny być jeszcze mniejsze
Funkcje
50. Funkcje
DRY – Don’t repeat yourself
• Duplikacja zmniejsza czytelność
• Zwiększa koszty utrzymania, refactoringu i
poprawiania błędów
• Prowadzi do rozbieżności funkcjonalnej
modułów wykonujących to samo
• Zmniejsza reusability kodu
51. • Nazwy
• Funkcje
• Komentarz
• Formatowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
54. //Sprawdzenie czy klient ma możliwość korzystania ze zniżki
if (customer.isStudent() ||
(customer.age < 18) || (customer.age > 65))
if (customer.isEligibleForDiscount())
55. „If you decide to write a comment, then
spend the time necessary to make sure it is
the best comment you can write”
Robert C. Martin
Komentarze
56. • Nazwy
• Funkcje
• Komentarz
• Formatowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
58. • Nazwy
• Funkcje
• Komentarz
• Formatowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
59. • Prawo Demeter – zasada minimalnej
wiedzy
• Moduł powinien nie wiedzieć nic o
wnętrzu obiektów, którymi manipuluje
Prawo Demeter
60. • Prawo Demeter głosi, że metoda f
klasy C powinna wywoływać tylko
metody z:
• Klasy C,
• Obiektu utworzonego przez f,
• Obiektu przekazanego jako argument f,
• Obiektu umieszczonego w zmiennej
instancyjnej klasy C.
Prawo Demeter
61. • Możesz bawić się ze sobą
• Możesz bawić się własnymi
zabawkami (ale nie możesz ich
rozbierać)
• Możesz bawić się zabawkami które
dostałeś
• Możesz bawić się zabawkami które
zrobiłeś samodzielnie
Prawo Demeter
62. final String outputDir = context.getOptions().getScratchDir().getAbsolutePath();
Options options = context.getOptions();
File scratchDir = options.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();
63. • Nazwy
• Funkcje
• Komentarz
• Formatowanie kodu
• Obiekty i struktury danych
• Obsługa błędów
Poziom I
65. • Wykorzystuj zgłaszanie wyjątków lub
zwracanie obiektu specjalnego
przypadku
Zwracanie null
List<Item> items = getItems();
if (items != null) {
for (Item i : items) {
totalCost += i.getCost();
}
}
List<Item> items = getItems();
for(Item i : items) {
totalCost += i.getCost();
}
66. 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() {
}
}
67. • Przekazywanie null jest gorsze od
jego zwracania
Przekazywanie null
public class MetricsCalculator {
public double rectanglePerimeterCalculate(
double x, double y) {
return 2 * (y + x);
}
/* ... */
}
68. • Defensive programming
Przekazywanie null
public class MetricsCalculator {
public double rectanglePerimeterCalculate(
double x, double y) {
if (x == null || y == null) {
throw InvalidArgumentException("Niewłaściwy
argument.");
}
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);
}
}
71. Poziom II - SOLIDny programista
• The Single Responsibility Principle – klasa
powinna mieć tylko jeden powód do zmiany
• The Open Closed Principle – klasę można
łatwo rozszerzać, nie modyfikując jej
• The Liskov Substitution Principle – klasy
pochodne muszą być przeźroczystymi
zamiennikami klasy nadrzędnej
72. • The Interface Segregation Principle – dla
różnych klientów twórz osobne interfejsy
• The Dependency Inversion Principle –
bądź zależny od abstrakcji a nie od
konkretnych implementacji
SOLIDny programista
74. • Odpowiedzialność – tylko jedna
obiekty maja własną osobowość,
unikaj schizofrenicznych obiektów
• Enkapsulacja – to co się zmienia jest
hermetyzowane
• Preferencja kompozycji ponad
dziedziczenie
75. • Dokładanie ponad modyfikacje
– Gdy dodajemy nową funkcjonalność raczej dokładamy
nowe 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 jest
przezroczyste ich dla klientów.
76. 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)
}
77. 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()
}
79. • Każdy wzorzec opisujemy w trzech
kontekstach:
Odpowiedzialność
Enkapsulacja / hermetyzacja
Kompozycja
Wzorce projektowe
80. • Rozdziela i przesłania implementację
zachowań, czynności.
• Hermetyzujemy zmienny sposób
tworzenia obiektów
• Nowe funkcjonalności uzyskujemy
poprzez dodawanie komend, poprzez
kompozycję.
Wzorce projektowe: komenda
96. • Kod jest podstawowym medium
komunikacji w projekcie
• Kod to miejsce w którym spędzamy
najwięcej czasu
• Zły kod to jak solenie herbaty koledze
z zespołu albo plucie do kanapki – a
przecież nie jesteśmy złośliwi
Wartości
97. • Jako zespół jesteśmy jednością
– Jak ja pójdę na skróty, to kolega
będzie się męczył
– I jako całość i tak będziemy
nieefektywni
Wartości
99. • Programy są częściej czytane niż
pisane
• Więcej czasu poświęcamy na
modyfikację istniejącego kodu niż na
tworzenie nowego
Implementation Patterns
101. • Komunikacja – kod źródłowy powinno
się czytać jak książkę
• Prostota – wprowadzaj złożoność
tylko wtedy, kiedy jest to konieczne
• Elastyczność – elastyczność to
dodatkowa złożoność, więc
wprowadzaj ją tylko tam gdzie to
konieczne
Implementation patterns
102. • Lokalne konsekwencje – zmiana w
jednym miejscu nie powoduje zmian w
innych
• Minimalne powtórzenia – DRY
Implementation patterns
103. • Dane i logika razem – ponieważ dane
i logika z reguły zmieniają się w tym
samym czasie
• Symetria – utrzymuj podobny poziom
abstrakcji w obrębie metody / klasy
Implementation patterns
104. „Czysty kod jest prosty i bezpośredni.
Czysty kod czyta się jak dobrze
napisaną prozę. Czysty kod nigdy nie
zaciemnia zamiarów projektanta; jest
pełen trafnych abstrakcji i prostych
ścieżek sterowania.”
Grady Booch – to jeden z tych panów od UMLa
109. Affordance
a quality of an object, which
allows an individual to perform
an action. For example, a knob
affords twisting, and perhaps
pushing, while a cord affords
pulling
110. 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)
}
111. 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()
}