In the 2nd Code Clone result it’s pointing out a block of code that is duplicated across 5 different screens.
TLDR: Refactored the code out to a abstract ViewModel base class. Also identified a bunch of other obvious code that belonged in the base class and deleted a TON of duplicate code in the process (over 4% of Rawr’s total code!).
Net Lines Of Code Deleted: 4625 (!!!)
Each character class has a separate screen allowing the user to input stats for their character and then it performs some character-specific calculations. The problem is there are some base stats that pretty much every character class uses, then a handful of character-specific stats that only some classes use. This block of code takes the value of a bunch of checkboxes for these stats and builds an array out of them. And it is almost identical across many different character classes.
When I looked into I discovered that each character class has a separate options screen that looks very similar to every other character class. This specific code relates to the Stat Graph section at the bottom:
This Stat Graph section is repeated across many separate Character Options screens, the only difference being slightly different stat checkboxes available depending on the character type. My first thought was to wrap this up in it’s own User Control and have the character specific-code simply supply the list of stats it was interested in.
As I dug into the code a little more, I discovered that these Checkboxes are data-bound to a separate class (CalculationOptionsRogue in this case) that is basically acting as a ViewModel. So I figured I could achieve the goal I wanted (eliminate the duplicate code) with a lighter-weight refactoring than creating a whole new User Control (and having to get my hands dirty with XAML – blech!). I first pushed the function that Code Clone identified down into the ViewModel (since the ViewModel has the properties that the Checkboxes are bound to the function has access to all the data it needs). Then I refactored out a base class from the ViewModel that contained properties for every character stat, and the BuildStatsList function that can be reused between subclass ViewModels.
As you can see in the below code, I also moved a couple of functions and interface implementations up to the base class since they were duplicated across all of the subclass ViewModels: ICalculationOptionBase.GetXml & INotifyPropertyChanged.OnPropertyChanged. The end result was over 4500 net lines of code removed, over 4% of the total codebase of Rawr!