Given:
private void UpdataFieldItems(List<FieldItemBase> existingFieldItems, List<FieldItemBase> selectedFieldItems)
{
List<FieldItemBase> newFieldItemsSelected;
var fieldSelectionChanges = GetFieldSelectionChanges(out newFieldItemsSelected);//retuns a Flagged enum
if (Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedFieldItem))
{
StartEditMode();
SetColumnDescriptorsToAdd(newFieldItemsSelected);
UpdateItems(selectedFieldItems);
SetColumnsToShow();
CustomizeAlignmentAndCellFormatters(_tfaTableGrid.TableGrid);
if (_tfaTableGrid.TableGrid.ColumnDescriptors.Count() > 0)
{
SetAdditionalFirstGroupedColumn();
}
StopEditMode();
}
else if (Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Summary))
{
StartEditMode();
UpdateItems(fieldItems);
SetColumnsToShow();
if (_tfaTableGrid.TableGrid.ColumnDescriptors.Count() > 0)
{
SetAdditionalFirstGroupedColumn();
}
StopEditMode();
}
else if (Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Order) ||
Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedCustomFieldItem) ||
Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.RemovedItem))
{
UpdateItems(fieldItems);
SetColumnsToShow();
}
Invalidate();
}
//Coding.cs
public static bool EnumHas(FieldSelectionChanges selectionChanges, FieldSelectionChanges valueToCheck)
{
return (selectionChanges & valueToCheck) == valueToCheck;
}
I am willing to refactor the above code.
There are two things that i don't like about the code above:
1) Writing same method calls in different cases, its not being possible to pull out the common method calls from these cases.
2) The readability of this code is very bad. It would be very confusing to understand and debug, if later needed.
Can someone suggest a design pattern for this code? or some way to improve upon the above two concerns?
Thanks for your interest.
Use extract method for body of each if statement
Create Dictionary> to choose appropriate action for fieldSelectionChanges. This is Strategy pattern
I would make the different conditions more expressive in terms of what it actually does to your application seeing you already use quite descriptive method names for the actions. Something like:
private void UpdataFieldItems(List<FieldItemBase> existingFieldItems, List<FieldItemBase> selectedFieldItems)
{
List<FieldItemBase> newFieldItemsSelected;
var fieldSelectionChanges = GetFieldSelectionChanges(out newFieldItemsSelected);//retuns a Flagged enum
if (IsValidChange(fieldSelectionChanges))
{
List<FieldItemBase> targetfields = null;
if (IsInEditMode(fieldSelectionChanges))
StartEditMode();
if (IsItemAdded(fieldSelectionChanges))
{
SetColumnDescriptorsToAdd(newFieldItemsSelected);
targetFields = selectedFieldItems;
}
else
targetFields = existingFieldItems;
UpdateItems(targetFields);
SetColumnsToShow();
if (IsItemAdded(fieldSelectionChanges))
CustomizeAlignmentAndCellFormatters(_tfaTableGrid.TableGrid);
if (IsInEditMode(fieldSelectionChanges))
{
if (_tfaTableGrid.TableGrid.ColumnDescriptors.Count() > 0)
SetAdditionalFirstGroupedColumn();
StopEditMode();
}
}
Invalidate();
}
private bool InEditMode(FlaggedEnum fieldSelectionChanges)
{
return Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Summary) || Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedFieldItem);
}
private bool IsItemAdded(FlaggedEnum fieldSelectionChanges)
{
Coding.EnumHas(Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedFieldItem);
}
private bool IsValidChange(FlaggedEnum fieldSelectionChanges)
{
return Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Order) ||
Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedCustomFieldItem) ||
Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.RemovedItem) ||
Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Summary) ||
Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedFieldItem);
}
//Coding.cs
public static bool EnumHas(FieldSelectionChanges selectionChanges, FieldSelectionChanges valueToCheck)
{
return (selectionChanges & valueToCheck) == valueToCheck;
}
Well the part that is repetitive/somewhat ugly is the IF statements.
Suggest holding the result of those IF conditions in a boolean variable, and leverage that.
This code isnt complete, but you get the idea.
bool scenarioOne = Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedFieldItem);
bool scenarioTwo = Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Summary);
bool scenarioThree = Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.Order) || Coding.EnumHas(fieldSelectionChanges, FieldSelectionChanges.AddedCustomFieldItem) || Coding.EnumHas(fieldSelectionChanges,FieldSelectionChanges.RemovedItem);
if (scenarioOne || scenarioTwo)
StartEditMode();
if (scenarioOne) {
SetColumnDescriptorsToAdd(newFieldItemsSelected);
UpdateItems(selectedFieldItems);
}
else if (scenarioTwo || scenarioThree) {
UpdateItems(fieldItems);
}
if (scenarioOne || scenarioTwo || scenarioThree)
SetColumnsToShow();
Obviously, pick better names for the variable.
Or better yet, seperate out into seperate methods.
I would suggest extracting the three blocks into separate, well-named, methods. This will improve the readability if the UpdateFieldItems method. Since the three blocks are totally different, there is imo no way of consolidating these further.
Related
I want to parse only some data out of a ~100 MB rdf cell line ontology. So far I am interested in 169.796 out of 1.387.097 tripples (1.217.301 tripples being skipped).
I need ~24 seconds using the handler below to create the graph. This is only some seconds less then parsing the ontology in total.
Is there something I could improve in skipping the tuples I am not interested in?
Thanks!
private class MyHandler : VDS.RDF.GraphHandler
{
public MyHandler(IGraph g)
: base(g)
{
}
protected override bool HandleTripleInternal(Triple t)
{
if (t.Predicate is UriNode uri
&& uri.Uri.AbsoluteUri != "http://www.w3.org/2000/01/rdf-schema#subClassOf"
&& uri.Uri.AbsoluteUri != "http://www.w3.org/2000/01/rdf-schema#label")
{
return true;
}
else if (t.Object is LiteralNode l && l.Language == "zh")
{
return true;
}
return base.HandleTripleInternal(t);
}
}
To make the comparison of nodes a bit faster you could try comparing directly with a UriNode created from the graph instead of comparing URI strings. If you use the IGraph.CreateUriNode() method in your filter constructor to create nodes for rdfs:subClassOf and rdfs:label and then use IUriNode.Equals() as your comparator then you should find that the node comparison can use a faster object reference equality rather than a string comparison.
private class MyHandler : GraphHandler
{
private readonly IUriNode _rdfsSubClassOf;
private readonly IUriNode _rdfsLabel;
public MyHandler(IGraph g)
: base(g)
{
_rdfsSubClassOf = g.CreateUriNode(UriFactory.Create("http://www.w3.org/2000/01/rdf-schema#subClassOf"));
_rdfsLabel = g.CreateUriNode(UriFactory.Create("http://www.w3.org/2000/01/rdf-schema#label"));
}
protected override bool HandleTripleInternal(Triple t)
{
if (t.Predicate is UriNode uri
&& !uri.Equals(_rdfsSubClassOf)
&& !uri.Equals(_rdfsLabel))
{
return true;
}
else if (t.Object is LiteralNode l && l.Language == "zh")
{
return true;
}
return base.HandleTripleInternal(t);
}
}
However that is only going to speed up the filter and I suspect that if you profile the parse of the file you will find that the majority of the time is spent in parsing the syntax to create the triple that is passed to your filter. There isn't really a way to get around this issue in the dotNetRDF handler architecture.
Is there a way to quickly check the following logic in C#?
if (a)
{
}
if (b)
{
}
if (c)
{
}
else //none of the above, execute if all above conditions are false
{
/* do something only if !a && !b && !c */
}
This differs from using if-else in that a, b, and c can all be true at once, so I can't stack them that way.
I want to run the else block when a, b, and c are all false without writing if (!a && !b && !c). This is because the code can get quite messy when the if conditions become more complex. It requires rewriting a lot of code.
Is this possible?
Firstly, no, else blocks only respect the if clause immediately above them, so you'll need an alternative.
This option isn't especially "clean", but I'd do:
bool noneAreTrue = true;
if(a)
{
noneAreTrue = false;
}
if(b)
{
noneAreTrue = false;
}
if(c)
{
noneAreTrue = false;
}
if(noneAreTrue)
{
//execute if all above conditions are false
}
Also, if your conditions are really pretty big, I recommend the rule G28 (Encapsulate Conditionals) from the book Clean Code from Robert C. Martin.
It is pretty verbose, but can be easier to read in some instances:
public void YourMethod()
{
if(SomeComplexLogic())
{
}
if(SomeMoreLogic())
{
}
if(EvenMoreComplexLogic())
{
}
if(NoComplexLogicApply())
{
}
}
private bool SomeComplexLogic(){
return stuff;
}
private bool EvenMoreComplexLogic(){
return moreStuff;
}
private bool EvenMoreComplexLogic(){
return evenMoreStuff;
}
private bool NoComplexLogicApply(){
return SomeComplexLogic() && EvenMoreComplexLogic() && EvenMoreComplexLogic();
}
How about combine the concepts of Strategies and Specifications
var strategies = _availableStrategies.All(x => x.IsSatisfiedBy(value));
foreach (var strategy in strategies)
{
strategy.Execute(context);
}
if (!strategies.Any()) {
// run a different strategy
}
Rather than encapsulate some complex condition in a method that you will only ever call once or twice, I would just keep in a variable. This is also more readable than using some marker boolean as other answers suggest.
A contrived example,
bool isBlue = sky.Color == Colors.Blue;
bool containsOxygen = sky.Atoms.Contains("oxygen") && sky.Bonds.Type == Bond.Double;
bool canRain = sky.Abilities.Contains("rain");
if(isBlue)
{
}
if(containsOxygen)
{
}
if(canRain)
{
}
if(!isBlue && !containsOxygen && !canRain)
{
}
Now we have abstracted what might otherwise be complex conditions into readable English!
I have two functions whose underlying logic is the same but in one case it sets one property value on a class and in another case it sets a different one. How can I rewrite the following two functions to abstract away as much of the algorithm as possible so that I can make changes in logic in a single place?
SetBillingAddress
private void SetBillingAddress(OrderAddress newBillingAddress)
{
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
OrderAddress oldBillingAddress = basketHelper.Basket.Addresses[basketHelper.BillingAddressID];
bool NewBillingAddressIsNotOldBillingAddress = ((oldBillingAddress == null) || (newBillingAddress.OrderAddressId != oldBillingAddress.OrderAddressId));
bool BillingAddressHasBeenPreviouslySet = (oldBillingAddress != null);
bool BillingAddressIsNotSameAsShippingAddress = (basketHelper.ShippingAddressID != basketHelper.BillingAddressID);
bool NewBillingAddressIsNotShippingAddress = (newBillingAddress.OrderAddressId != basketHelper.ShippingAddressID);
if (NewBillingAddressIsNotOldBillingAddress && BillingAddressHasBeenPreviouslySet && BillingAddressIsNotSameAsShippingAddress)
{
basketHelper.Basket.Addresses.Remove(oldBillingAddress);
}
if (NewBillingAddressIsNotOldBillingAddress && NewBillingAddressIsNotShippingAddress)
{
basketHelper.Basket.Addresses.Add(newBillingAddress);
}
basketHelper.BillingAddressID = newBillingAddress.OrderAddressId;
basketHelper.Basket.Save();
}
And here is the second one:
SetShippingAddress
private void SetShippingAddress(OrderAddress newShippingAddress)
{
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
OrderAddress oldShippingAddress = basketHelper.Basket.Addresses[basketHelper.ShippingAddressID];
bool NewShippingAddressIsNotOldShippingAddress = ((oldShippingAddress == null) || (newShippingAddress.OrderAddressId != oldShippingAddress.OrderAddressId));
bool ShippingAddressHasBeenPreviouslySet = (oldShippingAddress != null);
bool ShippingAddressIsNotSameAsBillingAddress = (basketHelper.ShippingAddressID != basketHelper.BillingAddressID);
bool NewShippingAddressIsNotBillingAddress = (newShippingAddress.OrderAddressId != basketHelper.BillingAddressID);
if (NewShippingAddressIsNotOldShippingAddress && ShippingAddressHasBeenPreviouslySet && ShippingAddressIsNotSameAsBillingAddress)
{
basketHelper.Basket.Addresses.Remove(oldShippingAddress);
}
if (NewShippingAddressIsNotOldShippingAddress && NewShippingAddressIsNotBillingAddress)
{
basketHelper.Basket.Addresses.Add(newShippingAddress);
}
basketHelper.ShippingAddressID = newShippingAddress.OrderAddressId;
basketHelper.Basket.Save();
}
My initial thought was that if I could pass a class's property by refernce then I could rewrite the previous functions into something like
private void SetPurchaseOrderAddress(OrderAddress newAddress, ref String CurrentChangingAddressIDProperty)
and then call this function and pass in either basketHelper.BillingAddressID or basketHelper.ShippingAddressID as CurrentChangingAddressIDProperty but since I can't pass C# properties by reference I am not sure what to do with this code to be able to reuse the logic in both places.
Thanks for any insight you can give me.
You can pass lambda expressions:
private void SetPurchaseOrderAddress(OrderAddress newAddress, Func<string> addressIDGetter, Action<string> addressIDSetter)
Call it like this:
SetPurchaseOrderAddress(newAddress, () => basketHelper.BillingAddressID, a => basketHelper.BillingAddressID = a);
Send in a Func and an Action, one to get the property out, and another to set it again.
private void SetPurchaseOrderAddress(OrderAddress newAddress,
Func<BasketHelper, int> getAddId, Action<BasketHelper, int> setAddId) {}
Which would give something like:
SetPurchaseOrderAddress(address,
bh => bh.Basket.Addresses[bh.BillingAddressID],
(bh,s) => bh.BillingAddressID = s);
You can use delegates to create a method that takes some simple behavior (such as setting a value of the property) as an argument. In C# 3.0, you can easily create a delegate using lambda expressions and in C# 2.0 you can do similar thing using anonymous delegates.
In your example, you would write a method that takes Action<BasketHelper> delegate - the delegate allows you to specify some operation that should be done with the BasketHelper after you initialize it and before you save it:
private void SetBasketProperty(Action<BasketHelper> action) {
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
// Code that is repeated for all similar methods
// Invoke the specific action
action(basketHelper);
basketHelper.Basket.Save();
}
To call this method in C# 3.0 you can write something like this:
SetBasketProperty(basketHelper => {
basketHelper.ShippingAddressID = newShippingAddress.OrderAddressId;
});
The lambda expression simply provides the code that you want to run before calling Save.
I have a simple method that returns bool, but it internally loads various objects.
I check for null for each, but it becomes very ugly.
Is there a better way?
public bool SomeTest(int id1)
{
bool result = false;
User user = userDao.GetById(id1);
if(user != null)
{
Blah blah = blahDao.GetById(user.BlahId);
if(blah != null)
{
FooBar fb = fbDao.GetById(blah.FooBarId);
if(fb != null)
{
// you_get_the_idea!
}
}
}
return result;
}
Is there a pattern that could make this a more inline instead of nested if's?
Does it need to do anything other than check whether the entity exists? I'll assume not.
First step: ignore the "one exit point" rule and reduce nesting:
public bool SomeTest(int id1)
{
User user = userDao.GetById(id1);
if (user == null)
{
return false;
}
Blah blah = blahDao.GetById(user.BlahId);
if (blah == null)
{
return false;
}
FooBar fb = fbDao.GetById(blah.FooBarId);
if (fb == null)
{
return false;
}
return true;
}
What comes next is likely to be language-specific... what language are you using, and which version of the platform? Can you alter your DAOs? C# has a bit more language flexibility (lambda expressions, the null coalescing operator, things like that) which may be handy in this situation.
Assuming there's nothing you can do to recover, you could just return as soon as you get a null:
User user = UserDAO.GetById(id1);
if(user == null) return false;
Blah blah = blahDao.GetById(user.BlahId);
if(blah == null) return false;
You might also want to look at the Null object pattern
seriously?
Blah blah = GetBlah();
if (blah == null) return false;
To add to all other answers, if you had an IDao interface for instance
public interface IDao
{
bool CanGetUser(int id);
}
Then you can pass in a List of DAO's created somewhere else.
public bool SomeTest(int id1, IEnumerable<IDao> daoList)
{
return daoList.Any( dao => dao.CanGetUser(id1) );
}
Perhaps:
User user;
Blah blah;
FooBar fb;
if( (user = userDao.GetById(id1)) != null
&& (blah = blahDao.GetById(user.BlahId)) != null
&& (fb = fbDao.GetById(blah.FooBarId)) != null)
{
// set flag, manipulate user/blah/fb, etc
}
What is the best way in c# to determine whether the programmer is running the program via IDE or its user?
if (System.Diagnostics.Debugger.IsAttached) {
// You are debugging
}
public static bool IsInVisualStudio
{
get
{
bool inIDE = false;
string[] args = System.Environment.GetCommandLineArgs();
if (args != null && args.Length > 0)
{
string prgName = args[0].ToUpper();
inIDE = prgName.EndsWith("VSHOST.EXE");
}
return inIDE;
}
}