I have a method, but the whole method doesn't need to run all the time.
I want only parts of the method to run sometimes.
In trying to follow DRY (Don't Repeat Yourself) principle, how can I have different entry points for this method based on a passed argument?
public void SetDisplayCollection(string input)
{
//SWITCH:
//Input 1 entry Point
ChosenSite = SiteCollection.Where(x => x.Guid == chosenConcept.SiteGuid && x.Name == chosenConcept.SiteName).FirstOrDefault();
//Input 2 entry point
BuildingDisplayCollection = new ObservableCollection<BuildingConcept>(BuildingCollection.Where(x => x.RelatingName == ChosenSite.Name).ToList());
ChosenBuilding = BuildingDisplayCollection.Where(x => x.Guid == chosenConcept.BuildingGuid && x.Name == chosenConcept.BuildingName).FirstOrDefault();
//Input 3 entry point
BuildingStoreyDisplayCollection = new ObservableCollection<BuildingStoreyConcept>(BuildingStoreyCollection.Where(x => x.RelatingName == ChosenBuilding.Name).ToList());
ChosenBuildingStorey = BuildingStoreyDisplayCollection.Where(x => x.Name == chosenConcept.BuildingStoreyName).FirstOrDefault();
//default no entry
}
For clarity sake, there are 3 desired scenarios:
- Run 100% of the code
- Run last 2/3 of the code (skip beginning)
- Run the last 1/3 of the code (skip 2/3)
CodePudding user response:
The simplest way would be to use if
statements:
public void SetDisplayCollection(string input)
{
if(input=="1")
{
ChosenSite = SiteCollection.Where(x => x.Guid == chosenConcept.SiteGuid && x.Name == chosenConcept.SiteName).FirstOrDefault();
}
if(input=="1" || input=="2")
{
BuildingDisplayCollection = new ObservableCollection<BuildingConcept>(BuildingCollection.Where(x => x.RelatingName == ChosenSite.Name).ToList());
ChosenBuilding = BuildingDisplayCollection.Where(x => x.Guid == chosenConcept.BuildingGuid && x.Name == chosenConcept.BuildingName).FirstOrDefault();
}
if(input=="1" || input=="2" || input=="3")
{
BuildingStoreyDisplayCollection = new ObservableCollection<BuildingStoreyConcept>(BuildingStoreyCollection.Where(x => x.RelatingName == ChosenBuilding.Name).ToList());
ChosenBuildingStorey = BuildingStoreyDisplayCollection.Where(x => x.Name == chosenConcept.BuildingStoreyName).FirstOrDefault();
}
//default no entry
}
Certainly you can rearrange the blocks to simplify the "if" logic, or separate the three blocks into separate functions and call them individually, or use more complicated patterns, but the first step is to get something that works, then make it better as time allows.
CodePudding user response:
Work backwards, and try to execute the last step first, unless the requirements aren't met (ChosenBuilding
isn't defined yet). In that case, execute the second step first. Again, if the requirements of the second step (ChosenSite
are not defined) then you need to run the first step.
This is called lazy evaluation, but the general idea is as follows:
public void SetDisplayCollection()
{
if (ChosenBuilding == null)
{
if (ChosenSite == null)
{
// step #1
ChosenSite = SiteCollection.Where(x => x.Guid == chosenConcept.SiteGuid && x.Name == chosenConcept.SiteName).FirstOrDefault();
}
// step #2
BuildingDisplayCollection = new ObservableCollection<BuildingConcept>(BuildingCollection.Where(x => x.RelatingName == ChosenSite.Name).ToList());
ChosenBuilding = BuildingDisplayCollection.Where(x => x.Guid == chosenConcept.BuildingGuid && x.Name == chosenConcept.BuildingName).FirstOrDefault();
}
// step #3
BuildingStoreyDisplayCollection = new ObservableCollection<BuildingStoreyConcept>(BuildingStoreyCollection.Where(x => x.RelatingName == ChosenBuilding.Name).ToList());
ChosenBuildingStorey = BuildingStoreyDisplayCollection.Where(x => x.Name == chosenConcept.BuildingStoreyName).FirstOrDefault();
}
Now can force the evaluation of steps #1 and steps #2 given an input.
Something like this
public void SetDisplayCollection(string input)
{
if (ChosenBuilding == null || input == "1" || input == "2")
{
if (ChosenSite == null || input == "1")
{
// step #1
ChosenSite = SiteCollection.Where(x => x.Guid == chosenConcept.SiteGuid && x.Name == chosenConcept.SiteName).FirstOrDefault();
}
// step #2
BuildingDisplayCollection = new ObservableCollection<BuildingConcept>(BuildingCollection.Where(x => x.RelatingName == ChosenSite.Name).ToList());
ChosenBuilding = BuildingDisplayCollection.Where(x => x.Guid == chosenConcept.BuildingGuid && x.Name == chosenConcept.BuildingName).FirstOrDefault();
}
// step #3
BuildingStoreyDisplayCollection = new ObservableCollection<BuildingStoreyConcept>(BuildingStoreyCollection.Where(x => x.RelatingName == ChosenBuilding.Name).ToList());
ChosenBuildingStorey = BuildingStoreyDisplayCollection.Where(x => x.Name == chosenConcept.BuildingStoreyName).FirstOrDefault();
}
CodePudding user response:
Don't add unnecessary load to your CPU. Building on D Stanley's answer, if you make your code slightly less DRY, you can significantly reduce the number of conditions that need processing:
if(new string[] { "1", "2", "3" }.contains(input))
{
Function1();
Function2();
Function3();
}
else if(new string[] { "1", "2" }.contains(input))
{
Function1();
Function2();
}
else if(input=="1")
{
Function1();
}
void Function1() {
ChosenSite = SiteCollection.Where(x => x.Guid == chosenConcept.SiteGuid && x.Name == chosenConcept.SiteName).FirstOrDefault();
}
void Function2() {
BuildingDisplayCollection = new ObservableCollection<BuildingConcept>(BuildingCollection.Where(x => x.RelatingName == ChosenSite.Name).ToList());
ChosenBuilding = BuildingDisplayCollection.Where(x => x.Guid == chosenConcept.BuildingGuid && x.Name == chosenConcept.BuildingName).FirstOrDefault();
}
void Function3() {
BuildingStoreyDisplayCollection = new ObservableCollection<BuildingStoreyConcept>(BuildingStoreyCollection.Where(x => x.RelatingName == ChosenBuilding.Name).ToList());
ChosenBuildingStorey = BuildingStoreyDisplayCollection.Where(x => x.Name == chosenConcept.BuildingStoreyName).FirstOrDefault();
}
There's likely a nicer way to actually do what you're trying to do, but this is probably the most performant and least repetitive solution for your program as it stands.