I have 3 functions where the only difference in is the values I point out with comment
//-- point of difference
The majority of the function is the same across all three. The "DRY" factor is haunting my sleep :). I was wondering; can these could be merged easily and readably?
I have had situations like this before and I am hoping to learn something here.
private string RenderRequestType(string render, NameValueCollection nvp, string prefix, string regexWild, string suffix)
{
string regex = prefix + regexWild + suffix;
MatchCollection matches = Regex.Matches(render, regex);
foreach (Match match in matches)
{
foreach (Capture capture in match.Captures)
{
string name = capture.Value.Replace(prefix, "", StringComparison.CurrentCultureIgnoreCase).Replace(suffix, "", StringComparison.CurrentCultureIgnoreCase);
//-- point of difference
string value = nvp[name];
render = render.Replace(capture.Value, value);
}
}
return render;
}
private string RenderSessionType(string render, HttpContext httpContext, string prefix, string regexWild, string suffix)
{
string regex = prefix + regexWild + suffix;
MatchCollection matches = Regex.Matches(render, regex);
foreach (Match match in matches)
{
foreach (Capture capture in match.Captures)
{
string name = capture.Value.Replace(prefix, "", StringComparison.CurrentCultureIgnoreCase).Replace(suffix, "", StringComparison.CurrentCultureIgnoreCase);
//-- point of difference
object session = httpContext.Session[name];
string value = (session != null ? session.ToString() : "");
render = render.Replace(capture.Value, value);
}
}
return render;
}
private string RenderCookieType(string render, HttpContext httpContext, string prefix, string regexWild, string suffix)
{
string regex = prefix + regexWild + suffix;
MatchCollection matches = Regex.Matches(render, regex);
foreach (Match match in matches)
{
foreach (Capture capture in match.Captures)
{
string name = capture.Value.Replace(prefix, "", StringComparison.CurrentCultureIgnoreCase).Replace(suffix, "", StringComparison.CurrentCultureIgnoreCase);
//-- point of difference
HttpCookie cookie = httpContext.Request.Cookies[name];
string value = (cookie != null ? cookie.Value : "");
render = render.Replace(capture.Value, value);
}
}
return render;
}
Refactoring is the process of restructuring code, while not changing its original functionality. The goal of refactoring is to improve internal code by making many small changes without altering the code's external behavior.
It's fine to have a function even if only used once. Blocks of code should ideally only do one thing, perform one computation, one calculation. This makes it easy to work on the flow of your logic, instead of getting bogged down with huge blocks of code.
a) Methods should not have more than an average of 30 code lines (not counting line spaces and comments).
The best time to consider refactoring is before adding any updates or new features to existing code. Going back and cleaning up the current code before adding in new programming will not only improve the quality of the product itself, it will make it easier for future developers to build on the original code.
You could modify the function to take a Func<string, string>
to do the lookup:
private string RenderType(string render, Func<string, string> lookupFunc, string prefix, string regexWild, string suffix)
{
string regex = prefix + regexWild + suffix;
MatchCollection matches = Regex.Matches(render, regex);
foreach (Match match in matches)
{
foreach (Capture capture in match.Captures)
{
string name = capture.Value.Replace(prefix, "", StringComparison.CurrentCultureIgnoreCase).Replace(suffix, "", StringComparison.CurrentCultureIgnoreCase);
//-- point of difference
string value = lookupFunc(name);
render = render.Replace(capture.Value, value);
}
}
return render;
}
Then write your functions in terms of this one, e.g.:
private string RenderRequestType(string render, NameValueCollection nvp, string prefix, string regexWild, string suffix)
{
return RenderType(render, name => nvp[name], prefix, regexWild, suffix);
}
Pass in a Func<string, string>
to get the value associated with a given name. In the first case that would just use nvp's indexer; in the second it would use the session. You could either use separate methods to create the delegates, or lambda expressions. (I'd definitely use a lambda expression for the first one; I might use a separate method for the second.)
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