Codice Legacy,usciamo dal pantano! Simone Casciaroli (@simonecasc)       Stefano Leli (@sleli)
Bird Watching Game  http://github.com/sleli/BirdWatching
Il Gioco• Simulatore di Bird Watching• Una sorta di “battaglia navale”... ma qui gli assi sono 3 (gli uccelli volano)
Classe GameField       Responsabilità                     CollaborazioniGestisce la collezione di BirdsDispone il campo da...
Refactoring HintsRimozione della duplicazioneRimozione degli ifOggetti invece che primitive typeTell don’t ask
Passi di refactoring
Duplicazione
Duplicazione (semplice)@Before	 public void Setup() {        field = new GameField(10,5,3, new FieldSize(10,5,3));	 }
Duplicazione (semplice)public GameField(int width, int height, int depth,FieldSize fieldSize) {	 	 this.width = width;	 	 ...
Duplicazione (semplice)//Place the birds on the fields	 private void placeBirds(PlacingMode type) throws Exception {      ...
Eliminiamola!
Eliminiamola!@Before	 public void Setup() {        field = new GameField(new FieldSize(10,5,3));	 }
Eliminiamola!@Before	 public void Setup() {        field = new GameField(new FieldSize(10,5,3));	 }public GameField(FieldS...
Eliminiamola!             @Before             	 public void Setup() {                     field = new GameField(new FieldS...
Diamo a Cesareciò che è di Cesare
public class Location {	 int x = 0;	 int y = 0;		 public Location (int x, int y) {	 	 this.x = x;	 	 this.y = y;	 }}
bird.setLocation(location);if (!(bird instanceof Chicken))	 bird.setHeight(new Random().nextInt(this.depth));
bird.setLocation(location);if (!(bird instanceof Chicken))	 bird.setHeight(new Random().nextInt(this.depth));     Bird duc...
bird.setLocation(location);if (!(bird instanceof Chicken))	 bird.setHeight(new Random().nextInt(this.depth));     Bird duc...
Location location = new Location(new Random().nextInt(fieldSize.width()),                                 new Random().nex...
private boolean isGameFieldValid(){	 boolean isValid = true;	 for(Bird bird : birds) {	 	 int h = bird.getHeight();	 	 Loc...
private boolean isGameFieldValid(){	 boolean isValid = true;	 for(Bird bird : birds) {	 	 Location location = bird.getLoca...
public boolean shot(int x, int y, int h) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird : birds) {	 	 	 int...
public boolean shot(int x, int y, int h) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird : birds) {	 	 	 Loc...
public abstract class Bird {	 Location location;	 int height;		 public void setHeight(int height) throws Exception{	 	 thi...
Serve ancora?private void placeBirds(PlacingMode type) throws Exception {	 	 		 	 //Random Distribution	 	 if (type == Pla...
Tell, don’t Askpublic boolean shot(int x, int y, int h) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird : bi...
Appliedpublic boolean shot(Location shotLocation) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird : birds) {...
Let’s apply it another timepublic boolean shot(Location shotLocation) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(...
Another time toopublic boolean shot(Location shotLocation) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird :...
Programmiamo ad oggetti o     a tipi primitivi...?   private boolean isGameFieldValid()   {   	 boolean isValid = true;   ...
...ad Oggettiprivate boolean isGameFieldValid(){	 boolean isValid = true;	 for(Bird bird : birds) {	 	 isValid = fieldSize...
Gli IF proprio non ci      piacciono!
Come procediamo?private void placeBirds(PlacingMode type) throws Exception {	 	 		 	 //Random Distribution	 	 if (type == ...
I Passi di refactoring•   Estratta responsabilità di “Random placing strategy” in    una classe•   estratta interfaccia IP...
Il risultatopublic class PlacingStrategyFactory {                                                        public interface ...
Il risultatopublic class GameField {   ...	 public boolean startGame(PlacingMode pm) {	 	 placingStrategyFactory.create(pm...
Altri IF che non ci          piaccionoprivate boolean isGameFieldValid(){	 boolean isValid = true;	 for(Bird bird : birds)...
private boolean isGameFieldValid(){	 boolean isValid = true;	 for(Bird bird : birds) {	 	 isValid = isValid && fieldSize.i...
Stesso discorsopublic boolean shot(Location shotLocation) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird : ...
public boolean shot(Location shotLocation) {	 boolean hit = false;	 if (gameStarted)	 {	 	 for(Bird bird : birds) {       ...
Di nuovo sulleresponsabilità
Notate qualcosa?private boolean isGameFieldValid(){	 boolean isValid = true;	 for(Bird bird : birds) {	 	 isValid = isVali...
BirdsArmy
ed ecco i chiamantiprivate boolean isGameStarted() {	 return birds.areAllBirdsPlacedWithinField(fieldSize);}	public boolea...
Doppia personalita’
Conclusioni Test funzionali attorno al codice da refattorizzare         Refactoring ad ogni step e’ l’idealeSe si parte co...
ConclusioniRimozione della duplicazioneRimozione degli ifOggetti invece che primitive typeTell don’t ask
Repositoryhttp://github.com/sleli/BirdWatching
GRAZIEhttp://joind.in/4513     @simonecasc        @sleli
Codice legacy, usciamo dal pantano! @iad11
Codice legacy, usciamo dal pantano! @iad11
Codice legacy, usciamo dal pantano! @iad11
Codice legacy, usciamo dal pantano! @iad11
Codice legacy, usciamo dal pantano! @iad11
Upcoming SlideShare
Loading in...5
×

Codice legacy, usciamo dal pantano! @iad11

466

Published on

Avete mai provato la sensazione di essere immersi in una melma di codice putrido e maleodorante e di non riuscire a venirne fuori nonostante tutti i vostri sforzi?

In questo workshop si cercherà di simulare proprio questo scenario proponendovi un esempio di progetto mal scritto e che sarete chiamati in prima persona a rifattorizzare.

Nel nostro ruolo di coach vi faremo capire come riconoscere il codice che ha bisogno di essere migliorato, ed applicando i solid principles verrete guidati verso un buon design in grado di portarvi in acque più sicure e pulite.

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

  • Be the first to like this

No Downloads
Views
Total Views
466
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
12
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Codice legacy, usciamo dal pantano! @iad11

  1. 1. Codice Legacy,usciamo dal pantano! Simone Casciaroli (@simonecasc) Stefano Leli (@sleli)
  2. 2. Bird Watching Game http://github.com/sleli/BirdWatching
  3. 3. Il Gioco• Simulatore di Bird Watching• Una sorta di “battaglia navale”... ma qui gli assi sono 3 (gli uccelli volano)
  4. 4. Classe GameField Responsabilità CollaborazioniGestisce la collezione di BirdsDispone il campo da giocoValida il campo da gioco Classe BirdInizializza il campo (start)Gestisce le logiche degli shot
  5. 5. Refactoring HintsRimozione della duplicazioneRimozione degli ifOggetti invece che primitive typeTell don’t ask
  6. 6. Passi di refactoring
  7. 7. Duplicazione
  8. 8. Duplicazione (semplice)@Before public void Setup() { field = new GameField(10,5,3, new FieldSize(10,5,3)); }
  9. 9. Duplicazione (semplice)public GameField(int width, int height, int depth,FieldSize fieldSize) { this.width = width; this.height = height; this.depth = depth; this.fieldSize = fieldSize; birds = new ArrayList<Bird>(); }
  10. 10. Duplicazione (semplice)//Place the birds on the fields private void placeBirds(PlacingMode type) throws Exception { ... Location location = new Location(new Random().nextInt(this.width), new Random().nextInt(this.height)); bird.setLocation(location); if (!(bird instanceof Chicken)) bird.setHeight(new Random().nextInt(this.depth)); ... }
  11. 11. Eliminiamola!
  12. 12. Eliminiamola!@Before public void Setup() { field = new GameField(new FieldSize(10,5,3)); }
  13. 13. Eliminiamola!@Before public void Setup() { field = new GameField(new FieldSize(10,5,3)); }public GameField(FieldSize fieldSize) { this.fieldSize = fieldSize; birds = new ArrayList<Bird>(); }
  14. 14. Eliminiamola! @Before public void Setup() { field = new GameField(new FieldSize(10,5,3)); } public GameField(FieldSize fieldSize) { this.fieldSize = fieldSize; birds = new ArrayList<Bird>(); }//Place the birds on the fields private void placeBirds(PlacingMode type) throws Exception {... Location location = new Location(new Random().nextInt(fieldSize.width()), new Random().nextInt(fieldSize.height())); bird.setLocation(location); if (!(bird instanceof Chicken)) bird.setHeight(new Random().nextInt(fieldSize.depth())); ... }
  15. 15. Diamo a Cesareciò che è di Cesare
  16. 16. public class Location { int x = 0; int y = 0; public Location (int x, int y) { this.x = x; this.y = y; }}
  17. 17. bird.setLocation(location);if (!(bird instanceof Chicken)) bird.setHeight(new Random().nextInt(this.depth));
  18. 18. bird.setLocation(location);if (!(bird instanceof Chicken)) bird.setHeight(new Random().nextInt(this.depth)); Bird duck = new Duck(); duck.setLocation(new Location(10,5)); duck.setHeight(3);
  19. 19. bird.setLocation(location);if (!(bird instanceof Chicken)) bird.setHeight(new Random().nextInt(this.depth)); Bird duck = new Duck(); duck.setLocation(new Location(10,5)); duck.setHeight(3); int h = bird.getHeight(); Location location = bird.getLocation(); int x = location.x; int y = location.y; isValid = fieldSize.isWithinField(h, x, y);
  20. 20. Location location = new Location(new Random().nextInt(fieldSize.width()), new Random().nextInt(fieldSize.height()), new Random().nextInt(fieldSize.depth()));
  21. 21. private boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { int h = bird.getHeight(); Location location = bird.getLocation(); int x = location.x; int y = location.y; isValid = fieldSize.isWithinField(h, x, y); if (!isValid) break; } return isValid;}
  22. 22. private boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { Location location = bird.getLocation(); int h = location.h; int x = location.x; int y = location.y; isValid = fieldSize.isWithinField(h, x, y); if (!isValid) break; } return isValid;}
  23. 23. public boolean shot(int x, int y, int h) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { int height = bird.getHeight(); Location location = bird.getLocation(); hit = location.x == x && location.y == y && height == h; if (hit) { bird.sing(); break; } } } return hit;}
  24. 24. public boolean shot(int x, int y, int h) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { Location location = bird.getLocation(); hit = location.x == x && location.y == y && location.h == h; if (hit) { bird.sing(); break; } } } return hit;}
  25. 25. public abstract class Bird { Location location; int height; public void setHeight(int height) throws Exception{ this.height = height; } public int getHeight() { return height; } public void setLocation(Location location) { this.location = location; } public Location getLocation() { return location; } public abstract void sing();}
  26. 26. Serve ancora?private void placeBirds(PlacingMode type) throws Exception { //Random Distribution if (type == PlacingMode.Random) { for(Bird bird : birds) { Location location = new Location(new Random().nextInt(fieldSize.width()), new Random().nextInt(fieldSize.eighth()), new Random().nextInt(fieldSize.depth())); bird.setLocation(location); if (!(bird instanceof Chicken)) bird.setHeight(new Random().nextInt(this.depth)); } } //Custom Distribution else if (type == PlacingMode.Custom) { } }
  27. 27. Tell, don’t Askpublic boolean shot(int x, int y, int h) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { Location location = bird.getLocation(); hit = location.x == x && location.y == y && location.h == h; if (hit) { bird.sing(); break; } } } return hit;}
  28. 28. Appliedpublic boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = shotLocation.equals(bird.getLocation()); if (hit) { bird.sing(); break; } } } return hit;}
  29. 29. Let’s apply it another timepublic boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = bird.wasHit(shotLocation) if (hit) { bird.sing(); break; } } } return hit;}
  30. 30. Another time toopublic boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = bird.wasHit(shotLocation) if (hit) { break; } } } return hit;}
  31. 31. Programmiamo ad oggetti o a tipi primitivi...? private boolean isGameFieldValid() { boolean isValid = true; for(Bird bird : birds) { Location location = bird.getLocation(); int h = location.h; int x = location.x; int y = location.y; isValid = fieldSize.isWithinField(h, x, y); if (!isValid) break; } return isValid; }
  32. 32. ...ad Oggettiprivate boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { isValid = fieldSize.isWithinField(bird.getLocation()); if (!isValid) Text break; } return isValid;}
  33. 33. Gli IF proprio non ci piacciono!
  34. 34. Come procediamo?private void placeBirds(PlacingMode type) throws Exception { //Random Distribution if (type == PlacingMode.Random) { for(Bird bird : birds) { Location location = new Location(new Random().nextInt(fieldSize.width()), new Random().nextInt(fieldSize.eighth()), new Random().nextInt(fieldSize.depth())); bird.setLocation(location); } } //Custom Distribution else if (type == PlacingMode.Custom) { } }
  35. 35. I Passi di refactoring• Estratta responsabilità di “Random placing strategy” in una classe• estratta interfaccia IPlacingStrategy• creata class NullPlacingStrategy• creata Factory per Placing strategy• inline metodo placeBirds• trasformata la factory in un field ed estratto come parametro del costruttore
  36. 36. Il risultatopublic class PlacingStrategyFactory { public interface IPlacingStrategy { public IPlacingStrategy create(PlacingMode type, void place(List<Bird> birds); FieldSize fieldSize) { if (type == PlacingMode.Random) { } return new RandomPlacingStrategy(fieldSize); } public class NullPlacingStrategy implements IPlacingStrategy { return new NullPlacingStrategy(); } @Override public void place(List<Bird> birds) {} // Do nothing } } public class RandomPlacingStrategy implements IPlacingStrategy { private FieldSize fieldSize; public RandomPlacingStrategy(FieldSize fieldSize) { this.fieldSize = fieldSize; } @Override public void place(List<Bird> birds) { for(Bird bird : birds) { Location location = new Location(new Random().nextInt(fieldSize.width()), new Random().nextInt(fieldSize.height()), new Random().nextInt(fieldSize.depth())); bird.setLocation(location); } } }
  37. 37. Il risultatopublic class GameField { ... public boolean startGame(PlacingMode pm) { placingStrategyFactory.create(pm, fieldSize).place(birds); gameStarted = isGameStarted(); return gameStarted; } ...}
  38. 38. Altri IF che non ci piaccionoprivate boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { isValid = fieldSize.isWithinField(bird.getLocation()); if (!isValid) break; } return isValid;}
  39. 39. private boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { isValid = isValid && fieldSize.isWithinField(bird.getLocation()); } return isValid;} what does it mean? Groovy Java + Guava
  40. 40. Stesso discorsopublic boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = bird.wasHit(shotLocation) if (hit) { break; } } } return hit;}
  41. 41. public boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = hit || bird.wasHit(shotLocation) } } return hit;} or Groovy Java + Guava
  42. 42. Di nuovo sulleresponsabilità
  43. 43. Notate qualcosa?private boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { isValid = isValid && fieldSize.isWithinField(bird.getLocation()); } return isValid;} public boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = hit || bird.wasHit(shotLocation) } } return hit; }
  44. 44. BirdsArmy
  45. 45. ed ecco i chiamantiprivate boolean isGameStarted() { return birds.areAllBirdsPlacedWithinField(fieldSize);} public boolean shot(Location shotLocation) { return birds.anyBirdWasHit(shotLocation) && gameStarted;}
  46. 46. Doppia personalita’
  47. 47. Conclusioni Test funzionali attorno al codice da refattorizzare Refactoring ad ogni step e’ l’idealeSe si parte con codice legacy usate le techniche viste
  48. 48. ConclusioniRimozione della duplicazioneRimozione degli ifOggetti invece che primitive typeTell don’t ask
  49. 49. Repositoryhttp://github.com/sleli/BirdWatching
  50. 50. GRAZIEhttp://joind.in/4513 @simonecasc @sleli
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×