1
00:00:00,110 --> 00:00:14,880
Oggi parliamo di alcuni degli argomenti più importanti nell'analisi e progettazione del software, i pattern di progettazione e i code smell, che sono i due lati della stessa medaglia.

2
00:00:16,610 --> 00:00:25,650
I primi riguardano come progettare bene e i secondi come accorgersi di aver progettato male.

3
00:00:25,650 --> 00:00:40,430
Partiamo dalla definizione di design pattern. Che cos'è? È una soluzione comune a un problema di progettazione ricorrente.

4
00:00:42,350 --> 00:00:57,640
Questi differiscono da un altro tipo di pattern, che si chiamano pattern GRASP, con cui condividono parte del nome, ma questi ultimi sono principi, consigli.

5
00:00:57,640 --> 00:01:05,180
mentre i design pattern si spingono oltre e arrivano fino allo schema delle classi

6
00:01:05,180 --> 00:01:11,090
partiamo dalla classificazione GOF

7
00:01:11,090 --> 00:01:14,730
prima di tutto per cosa sta GOF?

8
00:01:14,730 --> 00:01:22,690
sta per Gang of Four che deriva dal fatto che i suoi ideatori erano quattro persone

9
00:01:22,690 --> 00:01:27,870
si tratta di 23 pattern in totale

10
00:01:27,870 --> 00:01:44,600
Però nel corso ne vedremo solamente sette. Come si classificano? Si classificano su due assi, per lo scopo e per il raggio d'azione.

11
00:01:44,600 --> 00:01:54,440
per quanto riguarda lo scopo possono essere creazionali, strutturali o comportamentali

12
00:01:54,440 --> 00:02:04,060
per quanto riguarda il raggio d'azione possono essere su classi oppure su oggetti

13
00:02:04,060 --> 00:02:10,960
facciamo qualche esempio di combinazioni di questi due assi

14
00:02:10,960 --> 00:02:17,200
abbiamo per esempio il factory method che è un creazionale su classi

15
00:02:17,200 --> 00:02:22,560
abbiamo per esempio l'adapter che è un pattern strutturale

16
00:02:22,560 --> 00:02:30,480
e abbiamo observer e strategy che sono due pattern comportamentali su oggetti

17
00:02:30,480 --> 00:02:39,620
adesso soffermiamoci su questi ultimi due perché spesso all'inizio vengono confusi

18
00:02:39,620 --> 00:02:55,470
Allora, partiamo dal definire questi due pattern, indicando quale problema risolvono e come lo risolvono.

19
00:02:55,470 --> 00:03:13,080
Lo strategy risponde al problema di un insieme di algoritmi correlati e variabili e vogliamo poterli cambiare. Cambiare come? Scegliere a quale utilizzare.

20
00:03:13,080 --> 00:03:16,800
Quindi come risolviamo questo problema?

21
00:03:17,820 --> 00:03:24,900
Ogni algoritmo viene messo in una classe separata, tutte con un'interfaccia comune.

22
00:03:26,270 --> 00:03:32,810
Il context tiene un riferimento alla strategia e la usa senza sapere quale sia,

23
00:03:32,810 --> 00:03:51,570
Mentre il client può sostituirla a runtime con una strategia diversa della stessa interfaccia per sostituirla con una strategia diversa all'occorrenza.

24
00:03:51,570 --> 00:04:04,550
Per quanto riguarda l'observer, il problema che si pone è quello di più oggetti che vogliono sapere quando un altro oggetto cambia stato.

25
00:04:05,050 --> 00:04:10,820
Ognuno reagendo a modo proprio. Il publisher non deve conoscerli.

26
00:04:12,080 --> 00:04:21,120
Prima di tutto vediamo chi è il publisher nel pattern observer. È l'oggetto che viene osservato dagli altri.

27
00:04:23,040 --> 00:04:24,740
Come risolviamo questo problema?

28
00:04:25,500 --> 00:04:34,070
Abbiamo un'interfaccia, che è il subscriber, e ogni subscriber si registra al publisher

29
00:04:34,070 --> 00:04:38,670
in modo che possa essere avvisato quando succede qualcosa.

30
00:04:40,610 --> 00:04:45,170
Quindi qual è la distinzione tra questi due pattern?

31
00:04:45,170 --> 00:04:53,430
Lo strategy serve a scambiare un comportamento, quindi scegliere quale comportamento vogliamo applicare.

32
00:04:55,040 --> 00:05:00,780
Observer serve a notificare un cambiamento a più interessati.

33
00:05:02,430 --> 00:05:06,510
Cos'hanno in comune? Si basano entrambi su polymorphism.

34
00:05:06,690 --> 00:05:11,210
e forniscono delle protected variations

35
00:05:11,210 --> 00:05:25,430
vediamo anche un'altra coppia di pattern che vengono spesso confusi

36
00:05:25,430 --> 00:05:29,150
che sono l'adapter e il facade

37
00:05:29,150 --> 00:05:33,220
partiamo vedendo l'adapter

38
00:05:33,220 --> 00:05:40,480
abbiamo due interfacce incompatibili che però hanno bisogno di parlarsi

39
00:05:40,480 --> 00:05:46,680
Quindi cosa facciamo per permettere che comunichino tra loro?

40
00:05:47,280 --> 00:05:55,720
Mettiamo in mezzo un oggetto adattatore che converte i messaggi che si devono scambiare.

41
00:05:57,260 --> 00:06:02,100
Esistono in due forme, adapter di classe e adapter di oggetto.

42
00:06:03,840 --> 00:06:11,940
Invece la facade si applica quando abbiamo un sottosistema disordinato e complicato.

43
00:06:11,940 --> 00:06:35,890
Mettiamo davanti a questo sottosistema un punto di contatto unico che offre un'interfaccia semplificata in modo che chi deve interfacciarsi con questo sottosistema non debba sapere di tutto e di più oppure confondersi su cosa effettivamente deve chiamare.

44
00:06:35,890 --> 00:06:50,360
La distinzione tra questi due pattern è che l'adapter converte un'interfaccia che c'è già, mentre facade semplifica l'accesso a un insieme di cose.

45
00:06:52,800 --> 00:06:55,200
Vediamo che cosa risolvono.

46
00:06:56,090 --> 00:07:02,490
L'adapter risolve un'incompatibilità, mentre facade risolve una complessità.

47
00:07:02,490 --> 00:07:13,980
Al facade di solito si accede tramite un singleton e sostiene il low coupling aggiungendo un livello di indirection

48
00:07:13,980 --> 00:07:23,800
Vediamo a questo punto che cos'è singleton e anche i suoi difetti

49
00:07:23,800 --> 00:07:26,510
Prima di tutto cos'è?

50
00:07:26,510 --> 00:07:32,890
è una sola istanza di una classe con un punto di accesso globale

51
00:07:32,890 --> 00:07:39,090
cioè tutti gli oggetti che si interfacciano con essa

52
00:07:39,090 --> 00:07:45,980
si interfacciano sempre con la stessa istanza

53
00:07:45,980 --> 00:07:51,520
abbiamo un metodo statico getInstance

54
00:07:51,520 --> 00:07:57,700
che ci restituisce l'istanza unica che è stata creata

55
00:07:57,700 --> 00:08:00,540
e ha un costruttore privato

56
00:08:00,540 --> 00:08:08,750
per negare la possibilità di crearne una ulteriore quando ne esiste già una.

57
00:08:10,750 --> 00:08:12,690
Come si riconosce in UML?

58
00:08:13,660 --> 00:08:19,000
Abbiamo solitamente un 1 in alto a destra nella classe.

59
00:08:21,060 --> 00:08:26,400
Le due implementazioni possono essere lesi oppure non lesi.

60
00:08:28,100 --> 00:08:29,640
Come si differenziano?

61
00:08:29,640 --> 00:09:00,140
Quelle lazy vengono create solo quando servono, perciò se magari all'avvio del nostro software quel singleton non è necessario ma invece ne abbiamo bisogno solamente nel momento in cui una richiesta o una certa azione appunto richiede di usare questa istanza, la creiamo solo in quel momento.

62
00:09:00,160 --> 00:09:09,540
invece possiamo avere quelle non lazy che vengono create subito anche se non sono necessarie in quel momento

63
00:09:09,540 --> 00:09:21,740
quali sono i limiti? serve synchronized su getinstance oppure con più thread rischiamo di avere due o più istanze

64
00:09:21,740 --> 00:09:32,510
non funziona bene nelle applicazioni distribuite perché comunque ogni macchina virtuale avrebbe la propria istanza

65
00:09:32,510 --> 00:09:46,350
e quindi questi sono due grossi limiti che si applicano in situazioni particolari ma non proprio di nicchia

66
00:09:46,350 --> 00:09:53,240
vediamo invece adesso i code smell

67
00:09:53,240 --> 00:09:56,910
allora che cosa sono i code smell?

68
00:09:57,110 --> 00:10:03,910
sono delle caratteristiche del codice che possono essere indizio di una cattiva pratica

69
00:10:03,910 --> 00:10:22,340
Non si tratta necessariamente di bug, è proprio un cattivo odore, cioè qualcosa che non va ma che non è effettivamente un bug o un problema di per sé.

70
00:10:22,340 --> 00:10:51,830
Che cosa si fa? Si fa refactoring per toglierli. In cosa consiste il refactoring? Consiste nel riscrivere il codice senza cambiarne il comportamento esterno a piccoli passi rieseguendo i test dopo ognuno. Quindi una cosa importantissima da tenere sempre a mente è che il refactoring non corregge i bug.

71
00:10:51,830 --> 00:10:58,050
vediamo adesso le 5 famiglie di code smell

72
00:10:58,050 --> 00:11:04,940
abbiamo i bloaters che sono codice sproporzionato

73
00:11:04,940 --> 00:11:09,700
ad esempio long method, large class, long parameter list

74
00:11:09,700 --> 00:11:14,000
poi abbiamo gli object orientation abusers

75
00:11:14,000 --> 00:11:17,520
che è l'uso sbagliato dell'object oriented

76
00:11:17,520 --> 00:11:22,520
che sono lo switch statement e il refused bequest

77
00:11:22,520 --> 00:11:31,100
abbiamo poi i change preventers che sono parti troppo accoppiate che impediscono le modifiche

78
00:11:31,100 --> 00:11:33,600
per esempio shotgun surgery

79
00:11:33,600 --> 00:11:41,030
poi abbiamo i dispensables, cose che è meglio togliere

80
00:11:41,030 --> 00:11:45,510
duplicated code, data class, comments

81
00:11:45,510 --> 00:11:53,360
infine abbiamo i couplers che sono accoppiamento eccessivo

82
00:11:53,360 --> 00:11:56,160
come ad esempio il code smell, feature envy

83
00:11:56,160 --> 00:12:04,440
Per ognuno di questi il sintomo si può riassumere in una sola frase.

84
00:12:04,440 --> 00:12:17,400
Per esempio il long method è un metodo con troppe righe e quindi è probabilmente una buona idea dividerlo in più metodi separati

85
00:12:17,400 --> 00:12:28,380
che fanno una parte dell'esecuzione che sia, come dire, che abbia un senso proprio.

86
00:12:30,400 --> 00:12:34,580
Poi, come possiamo definire refused bequest?

87
00:12:35,620 --> 00:12:41,120
La sottoclasse non usa quello che eredita e quindi la gerarchia è sbagliata.

88
00:12:43,120 --> 00:12:45,060
Poi abbiamo shotgun surgery.

89
00:12:45,060 --> 00:13:09,640
Per una modifica piccola devi toccare tante classi diverse che crea grossi problemi perché comunque modificando tante classi si rischia di rompere qualcosa o di cambiare comportamenti e di non rendersene conto subito perché passano inosservati.

90
00:13:09,640 --> 00:13:21,940
Le data class, semplicemente sono classi che sono solo contenitori di dati ma che non hanno logica e quindi non fanno niente

91
00:13:21,940 --> 00:13:34,500
Infine vediamo per esempio il feature envy, che cos'è? È un metodo che usa più i dati di un altro oggetto che i propri

92
00:13:34,500 --> 00:13:41,400
Vediamo delle coppie sintomo rimedio

93
00:13:41,400 --> 00:13:44,480
switch statement

94
00:13:44,480 --> 00:13:47,320
se puoi sfruttare il polimorfismo

95
00:13:47,320 --> 00:13:51,040
replace conditional with polymorphism

96
00:13:51,040 --> 00:13:59,750
è il metodo di refactoring adatto a risolvere questo problema

97
00:13:59,750 --> 00:14:02,890
per quanto riguarda il feature envy

98
00:14:02,890 --> 00:14:06,050
se il metodo sta chiaramente nel posto sbagliato

99
00:14:06,050 --> 00:14:10,030
applichiamo il metodo di refactoring move method

100
00:14:10,030 --> 00:14:17,830
che consiste semplicemente nel spostare il metodo nella classe più corretta

101
00:14:17,830 --> 00:14:28,440
per quanto riguarda il long method il metodo di refactoring che possiamo applicare è extract method

102
00:14:28,440 --> 00:14:38,110
se il problema sono le variabili locali invece replace temp with query oppure introduce parameter object

103
00:14:38,110 --> 00:14:51,120
che sono tutti dei metodi di refactoring che si basano appunto su motivi diversi per cui il metodo sia lungo.

104
00:14:51,120 --> 00:15:08,160
Quindi, riassumendo, la regola del 3. Si fa refactoring quando la stessa porzione è riusata almeno tre volte. Il copia e incolla è permesso una volta sola.

105
00:15:08,160 --> 00:15:18,660
Gli altri momenti buoni, quando si aggiunge una funzionalità, quando si corregge un bug e durante una revisione del codice.

106
00:15:19,000 --> 00:15:21,560
Si può fare refactoring anche in questi momenti.

107
00:15:23,790 --> 00:15:34,560
Quindi, i pattern ci dicono come fare le cose bene, mentre i code smell come accorgerci di non averle fatte bene.

108
00:15:34,560 --> 00:15:43,880
Questo chiude questa piccola lezione sui design pattern e i code smell.
