Requisito 6
È arrivato il momento di introdurre la Depedency Injection.
Vorrei che il Samurai ricevesse la propria arma in termini di interfaccia, dal costruttore, così che dal codice produttivo e dai test si possano creare istanze di Samurai armati di Katana o di pistola con il codice
new Samurai(new Katana());
new Samurai(new Gun());
Mi piacerebbe anche l’introduzione della Dependency Injection avvenisse senza mai rompere né la compilazione né i test, ma che si proceda a colpi di refactoring.
Anche l’arma TwoHands dovrebbe ricevere le proprie dipendenze tramite il costruttore.
Suggerimenti sulla procedura di refactoring
- Object Initializer nei chiamanti: individuare tutti i punti del codice dove viene invocato
Samuraie trasformare il set della proprietàWeaponToUsein Object initializer, in modo che assomigli al passaggio di parametro dal costruttore; - No
setesetdaWeaponToUse: iniziamo ad avvicinareWeaponToUsea un field privato, cominciando dall’eliminare i suoi getter e setter - *Estrarre
BuildWeapon(): nel codice di Samurai c’è uno snippet il cui scopo è quello di creare l’istanza corretta di arma. Isoliamo quel codice usando Extract Mehod. - Rendere
BuildWeapon()pura: il metodoBuildWeapon()accede alla proprietàWeaponToUse, per cui non è una funzione pura. Dal momento che il nostro obiettivo è quello di spostare la costruzione delle armi nel chiamante, in modo che l’arma possa essere iniettata, avremo bisogno di spostareBuildWeapon(). Non possiamo farlo fintanto cheBuildWeapon()dipende da variabili diverse dai proprio parametri. Usando Introduce Variable e Extract Parameter suWeaponToUserendereBuildWeapon()pura. Facciamo caso che non possiamo ancora spostare l’invocazioe del metodo nel costruttore, perchéWeaponToUseviene valorizzato dopo che il costruttore è stato eseguito. - Join declaration and initialization
- Introdurre il costruttore di default e il costruttore per iniettare WeaponToUse
- Trasformare gli Object Initializer a chiamate a costruttore
- WeaponToUse può diventare privata e readonly
- Eliminare il costruttore di default
- Adesso possiamo spostare la chiamata a
BuildWeaponnel costruttore. Per fare questo, introdurre il field_weapon.WeaponToUsediventa superfluo, e possiamo eliminarlo con Inline - Rendere
BuildWeaponpubblica e statica per poterla spostare al chiamante. - Spostarla nel chiamante introducendola come parametro
- Eliminare il dead code, compreso
weaponToUse, estraendo variabili dai parametri nel chiamante
Per rifattorizzare TwoHands si può procedere così:
- Selezionare le new che istanziano le armi e usare Introduce Field, specificando che si desidera che il valore vanga iniettato dal costruttore.
- Usare Inline per eliminare le eventuali variabili superflue.