I have multiple similar performing functions across many files in my project that all derive from a base class. Each of these files contains a function called IsAt() that returns a boolean based on whether I am on the correct page or not in my process. Below are some examples of the functions being used across these files..
Example 1.
public bool IsAt()
{
try
{
DriverUtils.WaitTillElementVisible(_driver, ObjectRepository.H1);
}
catch (WebDriverTimeoutException)
{
return false;
}
if (ObjectRepository.PageHeaderLocator.Text != ObjectRepository.textOnPageIdentifier)
return false;
Console.WriteLine($"Login Page loaded successfully");
return true;
}
Example 2.
public bool IsAt()
{
try
{
DriverUtils.WaitTillElementVisible(_driver, ObjectRepository.UseAuthCodeBy);
}
catch (WebDriverTimeoutException)
{
return false;
}
if (ObjectRepository.UseAuthCodeLocator.Text != ObjectRepository.textOnPageIdentifier)
return false;
Console.WriteLine("Select two factor provider page loaded successfully!");
return true;
}
Example 3.
public bool IsAt()
{
try
{
DriverUtils.WaitTillElementVisible(_driver, ObjectRepository.H1);
}
catch (WebDriverTimeoutException)
{
return false;
}
if (ObjectRepository.PageHeaderLocator.Text != ObjectRepository.TextInPageIdentifier)
return false;
Console.WriteLine("Forgot password page loaded successfully");
return true;
}
The Structure:
Based on the functions here is the structure here's how I think it would be implemented..
public virtual bool IsAt()
{
OpenQA.Selenium.By obj;
var message = "My message!";
try
{
DriverUtils.WaitTillElementVisible(_driver, obj);
}
catch (WebDriverTimeoutException)
{
return false;
}
if(obj.locator.text != obj.textOnPageIdentifier)
return false;
Console.WriteLine(message);
return true;
}
How can I implement these functions as a single generic function? Is it possible without introducing parameters to the function? eg. public bool IsAt(string message, obj myObject)
Do you mean this?
//example 1
public bool IsAt()
{
return this.IsAt(ObjectRepository.H1, ObjectRepository.PageHeaderLocator.Text, $"Login Page loaded successfully");
}
//example 2
public bool IsAt()
{
return this.IsAt(ObjectRepository.UseAuthCodeBy, ObjectRepository.UseAuthCodeLocator.Text, "Select two factor provider page loaded successfully!");
}
//example 3
public bool IsAt()
{
return this.IsAt(ObjectRepository.H1, ObjectRepository.PageHeaderLocator.Text, "Forgot password page loaded successfully");
}
//base class
protected bool IsAt(object element, string match, string message)
{
try
{
DriverUtils.WaitTillElementVisible(_driver, element);
}
catch (WebDriverTimeoutException)
{
return false;
}
if(match != ObjectRepository.TextInPageIdentifier)
return false;
Console.WriteLine(message);
return true;
}
I was looking at a piece of error handling code that looks like this:
if (condition) {
thereIsAProblem = true;
problemDescription = "x";
}
if (!thereIsAProblem && condition2) {
thereIsAProblem = true;
problemDescription = "y";
}
And I got to wondering whether there is a way to define a local variable called thereIsNotAProblem that is dynamically based on the value of thereIsAProblem. In other words:
var thereIsAProblem = false;
var thereIsNotAProblem = *** some expression... ***
Console.WriteLine(thereIsNotAProblem); // true
thereIsAProblem = true;
Console.WriteLine(thereIsNotAProblem); // false
if (thereIsNotAProblem && condition3) {
..
}
Is there some expression that can be entered on the line above that would assign the value of thereIsNotAProblem to be a dynamic formula based on !thereIsAProblem, and still allow thereIsNotAProblem to be supplied anywhere a bool value is required?
Not quite... but you could make it a delegate instead:
Func<bool> thereIsNotAProblem = () => { /* some expression */ };
Console.WriteLine(thereIsNotAProblem()); // true
thereIsAProblem = true;
Console.WriteLine(thereIsNotAProblem()); // false
Note how now each time was want to evaluate thereIsNotAProblem we invoke the delegate... which evaluates the expression to get a bool value.
Whilst you can do this by declaring a lambda,
var thereIsAProblem = false;
Func<bool> thereIsNotAProblem = () => !thereIsAProblem;
I'd argue you shouldn't. thereIsAProblem and thereIsNotAProblem look very similar and so one could easily be misread for the other. the use of ! to negate a variable with a positive name is well understood and easy to read and should lead to less bugs.
I'd further argue that a better solution is the "fail fast" approach of returning as soon as there is a problem, avoiding the need to test for an earlier problem in the first place:
if (condition)
{
problemDescription = "x";
return;
}
if (condition2)
{
problemDescription = "y";
return;
}
...
You could use do something like the following
(also see on .NET Fiddle https://dotnetfiddle.net/E9X6XJ )
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Console.WriteLine("YourQuestion() returns " + YourQuestion());
Console.WriteLine("AnswerOne() returns " + AnswerOne());
Console.WriteLine("AnswerTwo() returns " + AnswerTwo());
}
private static bool condition1()
{
return false;
}
private static bool condition2()
{
return true;
}
private static bool condition3()
{
return true;
}
public static string YourQuestion()
{
var thereIsAProblem = false;
var problemDescription = "";
if (condition1()) {
thereIsAProblem = true;
problemDescription = "x";
}
if (!thereIsAProblem && condition2()) {
thereIsAProblem = true;
problemDescription = "y";
}
return problemDescription;
}
public static string AnswerOne()
{
return checkCondition1() ??
checkCondition2() ??
checkCondition3();
}
private static string checkCondition1()
{
return condition1() ? "x" : null;
}
private static string checkCondition2()
{
return condition2() ? "y" : null;
}
private static string checkCondition3()
{
return condition3() ? "z" : null;
}
public static string AnswerTwo()
{
var conditionChecks = new Dictionary<string,Func<bool>>();
conditionChecks.Add("x",condition1);
conditionChecks.Add("y",condition2);
conditionChecks.Add("z",condition3);
foreach (var check in conditionChecks)
{
if (check.Value())
{
return check.Key;
}
}
return null;
}
}
I am writing to seek help with regards to implementing a return statement for my test method. I am currently getting a null response from my test() method, but I would like to know, how can I catch the error from my "IsValidEmailDomain" method in my "test" method:
public static bool IsValidEmailDomain(MailAddress address)
{
if (address == null) return false;
var response = DnsClient.Default.Resolve(address.Host, RecordType.Mx);
try
{
if (response == null || response.AnswerRecords == null) return false;
}
catch (FormatException ex)
{
ex.ToString();
throw ex;
//return false;
}
return response.AnswerRecords.OfType<MxRecord>().Any();
}
public static bool IsValidEmailDomain(string address)
{
if (string.IsNullOrWhiteSpace(address)) return false;
MailAddress theAddress;
try
{
theAddress = new MailAddress(address);
}
catch (FormatException)
{
return false;
}
return IsValidEmailDomain(theAddress);
}
public static string test()
{
string mail = "########";
if (IsValidEmailDomain(mail))
{
return mail;
}
else
{
///How to return error from IsValidEmailDomain() method.
}
}
Any hint or suggestion would be most appreciated.
public static string test()
{
string mail = "########";
bool? answer;
Exception ex;
try
{
answer = IsValidEmailDomain(mail);
}
catch(Exception e)
{
ex = e;
}
if (answer)
{
return mail;
}
else
{
// here you can check to see if the answer is null or if you actually got an exception
}
}
There are a couple of ways to do this.
Use an out parameter.
Throw an exception if there was an issue. (Defeats the purpose of bool)
I usually go with a combination when I come across something like this.
public bool IsValidEmailDomain(string email)
{
return IsValidEmailDomain(email, false);
}
public bool IsValidEmailDomain(string email, bool throwErrorIfInvalid)
{
string invalidMessage;
var valid = ValidateEmailDomain(email, out invalidMessage);
if(valid)
return true;
if (throwErrorIfInvalid)
throw new Exception(invalidMessage);
return false;
}
public bool ValidateEmailDomain(string email, out string invalidMessage)
{
invalidMessage= null;
if (....) // Whatever your logic is.
return true;
invalidMessage= "Invalid due to ....";
return false;
}
I am in the process of converting code from VB to C# from an old system that used a base classes for web forms to inherit classes from. My hope is to build a new login for our new extranet that functions like the old system, I may have missed a step but here is the block I tried to convert.
public bool CheckAD()
{
string fncADStatus = "Failure";
string fncSuccess = "Success";
string fncFailure = "Failure";
fncADStatus = Convert.ToString(Session["SessionADStatus"]);
try
{
if (fncADStatus == fncSuccess)
{
return true;
}
}
catch
{
if (fncADStatus == fncFailure)
{
return false;
}
if (Session["SessionADStatus"] == null)
{
return false;
}
}
}
And I get the following error "not all code path return a value" but I don't quite understand why.
it give you the error because you have not mentioned the else statment; nothing will be returned if condition fall in else. do the following will not give you the errro.
public bool CheckAD() {
string fncADStatus = "Failure";
string fncSuccess = "Success";
string fncFailure = "Failure";
fncADStatus = Convert.ToString(Session["SessionADStatus"]);
try
{
Boolean output = false;
if (fncADStatus == fncSuccess)
{
output = true;
}
return output;
}
catch
{
Boolean output = true;
if (fncADStatus == fncFailure)
{
output = false;
}
if (Session["SessionADStatus"] == null)
{
output = false;
}
return output;
}
}
Not all the code paths in the catch block return a result. Usually, you would write something like this
public bool CheckAD()
{
try {...}
catch
{
if (fncADStatus == fncFailure)
{
logger.Debug("One");
}
if (Session["SessionADStatus"] == null)
{
logger.Debug("Two");
}
return false; // <<<<< This bit is missing in your case
}
}
I am experimenting with different areas of C# and refactoring best practices/patterns.
As can be seen the Validate method below has 3 child validation methods.
Is there a way to redesign this method/refactor it so that the if statement are remove? (possibly using Delegate?).
Also what general code standard improvements would you suggest?
public bool Validate()
{
bool validDump;
validDump = ValidateRecordIdentifiers();
if (!validDump)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}
validDump = ValidateTotals();
if (!validDump)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}
validDump = ValidateRecordCount();
if (!validDump)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationPassed));
return true;
}
bool valid = false;
if(ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
{
valid = true;
}
/******AN Alternate Suggestion for the above code********/
bool valid = ValidateRecordIdentifiers() &&
ValidateTotals() &&
ValidateRecordCount();
/*******End Alternate Suggestion*************/
var statusMessage = (valid) ?
LogMessages.StatusMessages.JobValidationPassed :
LogMessages.StatusMessages.JobValidationFailed
LogLogic.AddEntry(LogLogic.GetEnumDescription(statusMessage));
return valid;
See short circuiting:
http://msdn.microsoft.com/en-us/library/2a723cdk%28VS.71%29.aspx
Framework:
class Validator
{
Func<bool> validatorDelegate;
Action failDelegate;
public Validator(Func<bool> v, Action fail)
{
validatorDelegate = v;
failDelegate = fail;
}
public bool Validate()
{
bool rc = validatorDelegate();
if (!rc) failDelegate();
return rc;
}
}
class ValidatorCollection : List<Validator>
{
Action successDelegate;
Action failDelegate;
public ValidatorCollection(Action failDelegate, Action successDelegate)
{
this.successDelegate = successDelegate;
this.failDelegate = failDelegate;
}
public bool Validate()
{
var rc = this.All(x => x.Validate());
if (rc) successDelegate();
return rc;
}
public void Add(Func<bool> v)
{
this.Add(new Validator(v, failDelegate));
}
}
Usage:
class test
{
public bool Validate()
{
return new ValidatorCollection(
FailAction,
SuccessAction)
{
valTrue,
valTrue,
valFalse
}.Validate();
}
public void FailAction()
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
}
public void SuccessAction()
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
}
public bool valTrue()
{
return true;
}
public bool valFalse()
{
return false;
}
}
public bool Validate()
{
return Validate(ValidateRecordIdentifiers, ValidateTotals, ValidateRecordCount);
}
public bool Validate(params Func<bool>[] validators)
{
var invalid = validators.FirstOrDefault(v => !v());
if (invalid != null)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
You could modify your validate methods so that they take in the LogLogic parameter and add an entry themselves for failing.
They could still return a boolean value, and this could be used to keep your return as soon as possible.
return ValidateRecordIdentifiers(LogLogic)
&& ValidateTotals(LogLogic)
&& ValidateRecordCount(LogLogic);
The first thing that jumps out is duplication:
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
So I'd look to collapse it into something like:
public StatusMessages Validate() {
LogMessages.StatusMessages status = LogMessages.StatusMessages.JobValidationFailed;
if( ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
status = LogMessages.StatusMessages.JobValidationPassed;
LogLogic.AddEntry(status.ToString());
return status;
}
There's a number of different ways to write this but your method is short and readable. The suggestions posted so far are, imo, much less readable and harder to debug (where would you set a breakpoint?). I would leave this method as is and look for other refactoring opportunities.
You are writing the same error message regardless of which validation function fails. It might be more helpful to log a specific error message in each case.
Otherwise you can rewrite what you already have much simpler:
if (ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
You can take a look at Validation Application Block and Code Contracts
You could do something simple like this:
bool validDump;
string message;
if ((!ValidateRecordIdentifiers()) ||
(!ValidateTotals()) ||
(!ValidateRecordCount()))
{
message = LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed);
}
else
{
message = LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed);
validDump = true;
}
LogLogic.AddEntry(message);
return validDump;
Maybe:
public bool Validate()
{
if (ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
This looks to me like a case for structured exception handling. It looks like an exception condition that you are handling in the sense that something invalid has been input, and it results in abandoning the process. Have you considered using try/catch in the parent function and throw within the child functions to handle this?
Example:
public bool Validate()
{
try
{
ValidateRecordIdentifiers();
ValidateTotals();
ValidateRecordCount();
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
catch (ValidationException ex)
{
LogLogic.AddEntry(ex.status);
return false;
}
}
class ValidationException : ApplicationException
{
public readonly LogMessages.StatusMessages status;
ValidationException(LogMessages.StatusMessages status)
{
this.status = status;
}
}
void ValidateRecordIdentifiers()
{
if (bad)
throw new ValidationException(LogMessages.StatusMessages.JobValidationFailed);
}
void ValidateTotals()
{
if (bad)
throw new ValidationException(LogMessages.StatusMessages.JobValidationFailed);
}
void ValidateRecordCount()
{
if (bad)
throw new ValidationException(LogMessages.StatusMessages.JobValidationFailed);
}
Edit: I generally don't like to use exception handling for errors that are not immediately reported out to the UI because exception handling can be costly, and excessive exception throwing can make the application harder to debug if you're trying to find real exception cases among a bunch of exceptions that aren't really "exceptional". But depending on your specific case, it may be appropriate. Just use with caution.
Your function does two things: validation and logging. You could separate them like this. This also lets you log these errors differently if you ever decide to do this.
public bool ValidateAndLog()
{
LogMessages.StatusMessages result=Validate();
LogLogic.AddEntry(LogLogic.GetEnumDescription(result));
return result==LogMessages.StatusMessages.JobValidationPassed;
}
private LogMessages.StatusMessages Validate()
{
//of course you can combine the next three ifs into one
if (!ValidRecordIdentifiers())
return LogMessages.StatusMessages.JobValidationFailed;
if (!ValidateTotals())
return LogMessages.StatusMessages.JobValidationFailed;
if (!ValidateRecordCount())
return LogMessages.StatusMessages.JobValidationFailed;
return LogMessages.StatusMessages.JobValidationPassed;
}
public bool Validate()
{
return LogSuccess(
new[] {ValidateRecordIdentifiers, ValidateTotals, ValidateRecordCount }
.All(v=>v()));
}
private bool LogSuccess(bool success)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(success
? LogMessages.StatusMessages.JobValidationPassed
: LogMessages.StatusMessages.JobValidationFailed
);
return success;
}
Value readability above all else (well, as long as it is in the same ballpark efficiency).
About the only changes I would make is to eliminate the unneeded variable, and use the function call in the conditional, and replace the ! operator with == false. This is easier to see for aging programmers like myself with bad eyesight :)
As implied by the comment of another poster, it is better to make the function read InvalidXX instead, to avoid using negation or == false and for better readability.
Also, as far as combining all the conditionals into a single "AND" statement, I would do that in lisp, but not in c#, because it will making debugging and tracing harder.
In particular, you probably don't want to put the same error message for each case - you should have a different one for each case so you know exactly what happened. Combining all cases into a single expression won't allow you to do this.
public bool Validate() {
if (ValidRecordIdentifiers() == false) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
if (ValidTotals() == false) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
if (ValidateRecordCount() == false) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
As the statement of those if conditions are the same for all, so you can do the check in one condition and do the reset job at the below.
public bool Validate()
{
bool validDump;
if(ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount()) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationPassed));
return true;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}