Inf1-OP Refactoring and Design Patterns Volker Seeker School of Informatics March 8, 2019
Refactoring
Hockey Analysis Season Game -minutesPlayed:double -games:List<Game> -goalsAgainst:int -shotsOnGoalAgainst:int +getGoalsAgainst():int +addGame(Game):void +getShotsOnGoalAgainst():int +removeGame(Game):void +getMinutesPlayed():double +getGames():List<Game> +getGoalieStatistics():GoalieStatistics GoalieStatistics ? Implement a class to calculate goalie statistics from all games in a season.
Hockey Analysis ◮ Goals Against Average (GAA) : Number of goals scored against a goalie divided by the number of minutes the goalie played for a season multiplied by 60 (number of minutes in a hockey game).
Hockey Analysis ◮ Goals Against Average (GAA) : Number of goals scored against a goalie divided by the number of minutes the goalie played for a season multiplied by 60 (number of minutes in a hockey game). � � GA GAA = 60 timeplayed mins
Hockey Analysis ◮ Goals Against Average (GAA) : Number of goals scored against a goalie divided by the number of minutes the goalie played for a season multiplied by 60 (number of minutes in a hockey game). � � GA GAA = 60 timeplayed mins ◮ Save Percentage (SV%) : Total number of saves (shots on goal, SOG, minus the number of goals scored on a goalie) divided by the total SOG.
Hockey Analysis ◮ Goals Against Average (GAA) : Number of goals scored against a goalie divided by the number of minutes the goalie played for a season multiplied by 60 (number of minutes in a hockey game). � � GA GAA = 60 timeplayed mins ◮ Save Percentage (SV%) : Total number of saves (shots on goal, SOG, minus the number of goals scored on a goalie) divided by the total SOG. SV % = SOG − Goals SOG
Hockey Analysis Game Season -games:List<Game> -minutesPlayed:double -goalsAgainst:int -shotsOnGoalAgainst:int +getGoalsAgainst():int +addGame(Game):void +getShotsOnGoalAgainst():int +removeGame(Game):void +getGames():List<Game> +getMinutesPlayed():double +getGoalieStatistics():GoalieStatistics GoalieStatistics ? Let’s make a rough plan first!
Hockey Analysis Game Season -games:List<Game> -minutesPlayed:double -goalsAgainst:int -shotsOnGoalAgainst:int +getGoalsAgainst():int +addGame(Game):void +getShotsOnGoalAgainst():int +removeGame(Game):void +getGames():List<Game> +getMinutesPlayed():double +getGoalieStatistics():GoalieStatistics GoalieStatistics -season:Season +getGoalsAgainstAverage:double +getSavePercentage():double Let’s make a rough plan first!
Test Driven Development A set of unit tests is provided to check the expected behaviour of the code. 1. implement test to check expected behaviour 2. implement feature to make test pass
Hockey Analysis Game Season -games:List<Game> -minutesPlayed:double -goalsAgainst:int -shotsOnGoalAgainst:int +getGoalsAgainst():int +addGame(Game):void +getShotsOnGoalAgainst():int +removeGame(Game):void +getGames():List<Game> +getMinutesPlayed():double +getGoalieStatistics():GoalieStatistics GoalieStatistics -season:Season +getGoalsAgainstAverage:double +getSavePercentage():double We use test driven development.
Hockey Analysis Game Season -games:List<Game> -minutesPlayed:double -goalsAgainst:int -shotsOnGoalAgainst:int +getGoalsAgainst():int +addGame(Game):void +getShotsOnGoalAgainst():int +removeGame(Game):void +getGames():List<Game> +getMinutesPlayed():double +getGoalieStatistics():GoalieStatistics GoalieStatistics GoalieStatisticsT est -season:Season +getGoalsAgainstAverage:double +getSavePercentage():double We use test driven development.
Demo
Refactoring We have now successfully improved the internal structure of the code using small incremental steps whilst maintaining the original program logic.
Refactoring We have now successfully improved the internal structure of the code using small incremental steps whilst maintaining the original program logic. We have refactored the code.
Importance of Tests It is important that the expected behaviour of the code does not change during refactoring. Source: https://dzone.com/articles/what-is-refactoring
Importance of Tests Optimally, refactoring is part of the test driven development cycle. But this is not always possible. Source: https://dzone.com/articles/what-is-refactoring
Refactoring Techniques A large catalog of standard refactoring techniques exists, for example: ◮ loop splitting ◮ method extraction ◮ renaming ◮ . . . https://www.refactoring.com/catalog/
Code Smell Identify the need for refactoring based on Warning signs in your own code.
Code Smell A large list of common code smells exist, for example: ◮ Bloaters ◮ Object-Orientation Abusers ◮ Change Preventers ◮ . . . https://refactoring.guru/refactoring/smells
Design Patterns
Towards Software Engineering First learn your basic tools and material. Source: https://i.kinja-img.com/gawker-media/image/upload/s–Zo3E8URT– /c scale,f auto,fl progressive,q 80,w 800/18muwoa3oozw6jpg.jpg
Towards Software Engineering First learn your basic tools and material. Then build large houses ... Source: http://hannesdorfmann.com/images/legohouse/legohouse.jpg
Towards Software Engineering First learn your basic tools and material. Then build large houses ...or even cities. Source: https://i.kinja-img.com/gawker-media/image/upload/s–uTscbBDV– /c scale,f auto,fl progressive,q 80,w 800/tu3yxy86lxwmw5vw8yeu.jpg
Design Patterns Software Design Patterns are blueprints of solutions for common software design problems. Source: https://www.rff.com/cloverleaf.png
Classification ◮ Creational Patterns ◮ Structural Patterns ◮ Behavioural Patterns
Creational Example: Singleton Problem ◮ access a resource in your program
Creational Example: Singleton Problem ◮ access a resource in your program → database resource
Creational Example: Singleton Problem ◮ access a resource in your program → database resource ◮ initialising resource access is expensive
Creational Example: Singleton Problem ◮ access a resource in your program → database resource ◮ initialising resource access is expensive → only one instance
Creational Example: Singleton Problem ◮ access a resource in your program → database resource ◮ initialising resource access is expensive → only one instance ◮ multiple classes need access
Creational Example: Singleton Problem ◮ access a resource in your program → database resource ◮ initialising resource access is expensive → only one instance ◮ multiple classes need access → globally available
Creational Example: Singleton Solution? public class Database { private final DBConnection connection; public Database() { connection = new DBConnection("myuser", "myhost", "mydatabase"); connection.connect(); } public List<String> query(String q) { ... }
Creational Example: Singleton Solution? public class Database { private final DBConnection connection; public Database() { connection = new DBConnection("myuser", "myhost", "mydatabase"); connection.connect(); } public List<String> query(String q) { ... } Globally available instance not guaranteed!
Creational Example: Singleton Solution! public class Database { private static Database dbase; private final DBConnection connection; public Database() { connection = new DBConnection("myuser", "myhost", "mydatabase"); connection.connect(); } public List<String> query(String q) { ... } Add private static field for storing the singleton instance.
Creational Example: Singleton Solution! public class Database { private static Database dbase; private final DBConnection connection; public Database() { connection = new DBConnection("myuser", "myhost", "mydatabase"); connection.connect(); } public static Database getInstance() { // ? } public List<String> query(String q) { ... } Declare public static creation method to access the singleton instance.
Creational Example: Singleton Solution! public class Database { private static Database dbase; private final DBConnection connection; public Database() { connection = new DBConnection("myuser", "myhost", "mydatabase"); connection.connect(); } public static Database getInstance() { if(dbase == null) dbase = new Database(); return dbase; } public List<String> query(String q) { ... } Lazily create the instance of the singleton if necessary and return it.
Creational Example: Singleton Solution! public class Database { private static Database dbase; private final DBConnection connection; private Database() { connection = new DBConnection("myuser", "myhost", "mydatabase"); connection.connect(); } public static Database getInstance() { if(dbase == null) dbase = new Database(); return dbase; } public List<String> query(String q) { ... } Make the singleton constructor private.
Creational Example: Singleton Solution! public static void main(String[] args) { Database db = Database.getInstance(); db.query(args[0]); } In a client, use the getInstance method to access the singleton.
Recommend
More recommend