I have several methods that do the same thing yet, when interfacing with the MySQL database, save or load a different type of parameter. Currently, I have a different method for each type. How can I combine these methods so that they support different types?
Below is an example of two methods that are very similar yet use different types:
public static void saveLongArray(Connection con, int playerID, String tableName, String fieldName, long[] array, long[] originalArray) {
try {
for (int i = 0; i < array.length; i++) {
// Check for change before running query
if (array[i] != originalArray[i]) {
if (array[i] != 0 && array[i] != -1) {
PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)");
updateQuery.setInt(1, playerID);
updateQuery.setInt(2, i);
updateQuery.setLong(3, array[i]);
updateQuery.execute();
} else {
PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?");
deleteQuery.setInt(1, playerID);
deleteQuery.setInt(2, i);
deleteQuery.execute();
}
originalArray[i] = array[i];
}
}
} catch (SQLException ex) {
Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving a long array!", ex);
}
}
public static void saveIntArray(Connection con, int playerID, String tableName, String fieldName, int[] array, int[] originalArray) {
try {
for (int i = 0; i < array.length; i++) {
// Check for change before running query
if (array[i] != originalArray[i]) {
if (array[i] != 0 && array[i] != -1) {
PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)");
updateQuery.setInt(1, playerID);
updateQuery.setInt(2, i);
updateQuery.setInt(3, array[i]);
updateQuery.execute();
} else {
PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?");
deleteQuery.setInt(1, playerID);
deleteQuery.setInt(2, i);
deleteQuery.execute();
}
originalArray[i] = array[i];
}
}
} catch (SQLException ex) {
Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving an int array!", ex);
}
}
Note in that example the types are both numerical. In a case where types are completely different (e.g. int and String), what could I do to avoid have near-duplicate methods?
And, as the same itself suggests, this is yet another refactoring technique that offers more than one approach. Here are the two options that you'll be getting: Simplifying Method Calls Refactoring. Simplifying Conditional Expressions Refactoring.
If the duplicate code is inside a constructor, use Pull Up Constructor Body. If the duplicate code is similar but not completely identical, use Form Template Method. If two methods do the same thing but use different algorithms, select the best algorithm and apply Substitute Algorithm.
Such verification process can be achieved via automatically predicting, for a given commit, the method-level type of refactoring being applied, namely Extract Method, Inline Method, Move Method, Pull-up Method, Push-down Method, and Rename Method.
Move Method Refactoring (MMR) refers to moving a method from one class to the class in which the method is used the most often. Manually inspecting and analyzing the source code of the system under consideration to determine the methods in need of MMR is a costly and time-consuming process.
You can apply the Strategy pattern here.
interface TypeDependentBehavior<T> {
void setFieldValue(PreparedStatement st, T value);
}
interface StringBehavior extends TypeDependentBehavior<String> {
void setFieldValue(PreparedStatement st, String value) {
st.setString(3, value);
}
}
interface IntBehavior extends TypeDependentBehavior<Integer> {
void setFieldValue(PreparedStatement st, Integer value) {
st.setInt(3, value);
}
}
...
public static void saveArray<T>(Connection con, int playerID, String tableName, String fieldName, T[] array, T[] originalArray, TypeDependentBehavior<T> behavior) {
try {
for (int i = 0; i < array.length; i++) {
// Check for change before running query
if (array[i] != originalArray[i]) {
if (array[i] != 0 && array[i] != -1) {
PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)");
updateQuery.setInt(1, playerID);
updateQuery.setInt(2, i);
behavior.setFieldValue(updateQuery, array[i]);
updateQuery.execute();
} else {
PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?");
deleteQuery.setInt(1, playerID);
deleteQuery.setInt(2, i);
deleteQuery.execute();
}
originalArray[i] = array[i];
}
}
} catch (SQLException ex) {
Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving an int array!", ex);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With