Codice legacy, usciamo dal pantano! @iad11
Upcoming SlideShare
Loading in...5
×
 

Codice legacy, usciamo dal pantano! @iad11

on

  • 567 views

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?...

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.

Statistics

Views

Total Views
567
Views on SlideShare
567
Embed Views
0

Actions

Likes
0
Downloads
11
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Codice legacy, usciamo dal pantano! @iad11 Codice legacy, usciamo dal pantano! @iad11 Presentation Transcript

  • 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 giocoValida il campo da gioco Classe BirdInizializza il campo (start)Gestisce le logiche degli shot
  • 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; this.height = height; this.depth = depth; this.fieldSize = fieldSize; birds = new ArrayList<Bird>(); }
  • 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)); ... }
  • 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(FieldSize fieldSize) { this.fieldSize = fieldSize; birds = new ArrayList<Bird>(); }
  • 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())); ... }
  • 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 duck = new Duck(); duck.setLocation(new Location(10,5)); duck.setHeight(3);
  • 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);
  • Location location = new Location(new Random().nextInt(fieldSize.width()), new Random().nextInt(fieldSize.height()), new Random().nextInt(fieldSize.depth()));
  • 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;}
  • 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;}
  • 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;}
  • 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;}
  • 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();}
  • 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) { } }
  • 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;}
  • 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;}
  • 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;}
  • 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;}
  • 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; }
  • ...ad Oggettiprivate boolean isGameFieldValid(){ boolean isValid = true; for(Bird bird : birds) { isValid = fieldSize.isWithinField(bird.getLocation()); if (!isValid) Text break; } return isValid;}
  • Gli IF proprio non ci piacciono!
  • 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) { } }
  • 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
  • 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); } } }
  • Il risultatopublic class GameField { ... public boolean startGame(PlacingMode pm) { placingStrategyFactory.create(pm, fieldSize).place(birds); gameStarted = isGameStarted(); return gameStarted; } ...}
  • 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;}
  • 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
  • Stesso discorsopublic boolean shot(Location shotLocation) { boolean hit = false; if (gameStarted) { for(Bird bird : birds) { hit = bird.wasHit(shotLocation) if (hit) { break; } } } return hit;}
  • 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
  • Di nuovo sulleresponsabilità
  • 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; }
  • BirdsArmy
  • ed ecco i chiamantiprivate boolean isGameStarted() { return birds.areAllBirdsPlacedWithinField(fieldSize);} public boolean shot(Location shotLocation) { return birds.anyBirdWasHit(shotLocation) && gameStarted;}
  • Doppia personalita’
  • Conclusioni Test funzionali attorno al codice da refattorizzare Refactoring ad ogni step e’ l’idealeSe si parte con codice legacy usate le techniche viste
  • ConclusioniRimozione della duplicazioneRimozione degli ifOggetti invece che primitive typeTell don’t ask
  • Repositoryhttp://github.com/sleli/BirdWatching
  • GRAZIEhttp://joind.in/4513 @simonecasc @sleli