I have a class that follows the Command Pattern.
It has 2 methods which are Execute, and CanExecute which checks whether to invoke Execute or not (they derive from ICommand).
CanExecute invokes a few methods that check that all required services are running, the version is correct, etc.
After CanExecute is invoked, it may fail and return false and I need to know why. Is it because of a bad version, services, missing file, etc.
What is the best strategy to know what is the problem
One option is whenever a required condition fails I can throw an exception that will describe the error in the message field. However the possibility that it will fail is expected and you shouldn't use exceptions for regular flow of control. So I'm really not sure.
Thank you.
You can use a collection of "reasons" that will tell the users of the class why CanExecute returned false. The reasons can be a simple IEnumerable<string>.
public bool CanExecute() {
var messages = new List<string>();
if (!Condition1) {
messages.Add("Missing Condition1");
}
...
Messages = messages;
return messages.Count == 0;
}
public IEnumerable<string> Messages { get; private set; }
Then, client code can show the collection of messages to end-users.
UPDATE:
You can also associate new commands with the messages to give the users ways to fix the problems found. In this case, instead of an IEnumerable<string>, you can create your own class that encapsulates that information:
public class Message {
public string Text { get; set; }
public ICommand Command { get; set; }
}
...
public bool CanExecute() {
var messages = new List<Message>();
if (!Condition1) {
messages.Add(
new Message {
Text = "Missing Condition1",
Command = new FixCondition1Command()
}
);
}
...
Messages = messages;
return messages.Count == 0;
}
public IEnumerable<Message> Messages { get; private set; }
UPDATE: Reworked based on feedback.
Since the UI needs the reasons CanExecute() returns false, two things come to mind:
Option 1: Add an enumerable message property to the command interface and populate it as needed during the call to CanExecute(). The UI could then interrogate the property as needed. If you go this route, make sure you clear out the contents of the property each call to CanExecute() so you don't lose track of state.
public interface ICommand
{
IEnumerable<string> Messages { get; }
bool CanExecute();
void Execute();
}
public class SomeCommand : ICommand
{
public IEnumerable<string> Messages { get; private set; }
public bool CanExecute()
{
var messages = new List<string>();
var canExecute = true;
if (SomeCondition)
{
canExecute = false;
messages.Add("Some reason");
}
if (AnotherCondition)
{
canExecute = false;
messages.Add("Another reason");
}
Messages = messages;
return canExecute;
}
public void Execute() { }
}
Option 2: Have CanExecute() return an object which contains the bool as well as an enumerable messages property. This makes it obvious that the messages only apply to that call of CanExecute(). However, depending on where/how you're implementing (e.g. data binding), this could complicate other scenarios more than you're looking for.
public class CanExecuteResult
{
public bool CanExecute { get; set; }
public IEnumerable<string> Messages { get; set; }
}
public interface ICommand
{
CanExecuteResult CanExecute();
void Execute();
}
public class SomeCommand : ICommand
{
public CanExecuteResult CanExecute()
{
var result = new CanExecuteResult { CanExecute = true };
var messages = new List<string>();
if (SomeCondition)
{
result.CanExecute = false;
messages.Add("Some reason");
}
if (AnotherCondition)
{
result.CanExecute = false;
messages.Add("Another reason");
}
result.Messages = messages;
return result;
}
public void Execute() { }
}
Obviously, the specifics of how you want to handle the interfaces, enumerable types, etc. is up to you. The code is just a representation of the idea.
Bool CanExecute()
{
if(!CheckXXX)
throw new Exception("CheckXXX function throws an exception")
if(!CheckYYY)
throw new Exception("CheckYYY function throws an exception")
if(!CheckZZZ)
throw new Exception("CheckZZZ function throws an exception")
return true; //everything is working fine
}
Related
I have a class named ValidationsResult with this properties:
public class ValidationsResult
{
public bool IsValid { get; set; }
public string[] Errors { get; set; }
public void AddError(string error)
{
Errors.Append(error);
}
}
But I want that the property IsValid to be read only, and depending if the object has Errors or not modify that property automatically.
How can I do that?
public class ValidationsResult
{
public bool IsValid { get => Errors != null && Errors.Length == 0; } // no errors = valid
public string[] Errors { get; set; }
public void AddError(string error)
{
Errors.Append(error);
}
}
That will make it readonly and it will tell you if you have errors
Based on the comment, yes. Better if you designed it in the following fashion.
public class ValidationsResult
{
public bool IsValid { get => Errors.Count == 0; } // or !Errors.Any()
public List<string> Errors { get; } = new List<string>();
public void AddError(string error)
{
Errors.Add(error);
}
}
You initialize the errors but outside consumer can still use it. Hence - next evolution
public class ValidationsResult
{
private List<string> _errors = new List<string>(); // private member
public bool IsValid { get => _errors.Count == 0; } // or !Errors.Any()
public string[] Errors { get => _errors.ToArray(); }
public void AddError(string error)
{
_errors.Add(error);
}
}
Now you encapsulating your error collection not letting consumer to modify it directly, but via AddError
As an answer is already posted and accepted, I just want to point to a different thing.
Never implement this type of mechanism in a class! Keep classes as simple as possible.
Please use classes as POCOs, and implement this type of logic in a different layer of the application (e.g. Business Logic layer).
Otherwise, over time, your application will become complex and convoluted and hence hard to maintain.
I'm processing messages from an MSMQ.
For each message there are ten steps such as :
VerifyDates
VerifyPatientInformation
VerifyClinicalInformation
If there is a failure in any one of the three steps, I would like to throw out the message.
Can someone point to a SOLID example demonstrating this principal? I'm not sure how to structure my classes.
For example
public class VerifyDates()
{
private validateSomething ValidateSomething();
public VerifyDates()
{
validateSomething = new ValidateSomething();
}
public bool Verify()
{
validateSomething.IsValid();
}
}
Assuming that VerifyDates() is part of my processing logic, should I be adding a public field to the class bool Flag that returns whether or not to continue processing?
Perhaps I should add an Interface IHasFlag where every class that is used within my processing logic has a Flag that I check at the end to see whether or not to continue message processing?
Processing messages would go something like this
public void ProcessMessages()
{
var verifyDates = new VerifyDates();
if(!verifyDates.IsValid)
{
return;
}
//continue processing
//but every step of the process I would need to check IsValid for that specific class
}
How do you abstract the success/failure of every step within a sequential process?
You could use a fluent API. Something similar to the following:
public interface IFluentValidation<T>
{
bool IsValid { get; }
T ObjectToValidate { get; }
}
internal class FluentValidation<T>: IFluentValidation<T>
{
public bool IsValid { get; }
public T ObjectToValidate { get; }
public FluentValidation(bool isValid, T target)
{
Debug.Assert(target != null);
IsValid = isValid;
ObjectToValidate = target;
}
}
And now build the following extension methods:
public static IFluentValidation<T> ValidateBy<T>(this T target, Predicate<T> validator)
{
if (target == null) throw new ArgumentNullException(name(target));
if (validator == null) throw new ArgumentNullException(name(validator));
if (validator(target))
return new FluentValidation<T>(true, target);
return new FluentValidation<T>(false, target);
}
public static IFluentValidation<T> AndBy<T>(this IFluentValidation<T> target, Predicate<T> validator)
{
if (validator == null) throw new ArgumentNullException(name(validator));
if (!target.IsValid)
return target;
if (validator(target.ObjectToValidate)
return target;
return new FluentValidation<T>(false, target.ObjectToValidate);
}
Implementing an OrBy is trivial as a AndFinallyBy if you want to return the validated object and not a IFluentValidation<T>.
And you would use it like this:
var validated = myObject.ValidateBy(t => //whatever needs to checked t.ObjectToValidate.DateIsValid)
.ThenBy(t => ... //whatever needs to be checked t. ObjectToValidate.PatientIsValid)
.ThenBy(t => ... //t.ObjectToValidate .ClinicalInformationIsValid)
.IsValid;
You can also embellish this a little more and add optional custom error messages in each validation step; public static IFluentValidation<T> AndBy<T>(this IFluentValidation<T> target, Predicate<T> validator, Func<T, string> failureMessageProvider = null) and add the corresponding property string ValidationFailedMessage { get; } to IFluentValidation
I have the following model:
internal static List<Contracts.DataContracts.Report> GetReportsForSearch(string searchVal, string searchParam)
{
var param1 = new SqlParameter("#SearchVal", searchVal);
var ctx = new StradaDataReviewContext2();
var reports = new List<Contracts.DataContracts.Report>();
try
{
//Validate param1 here and return false if the requirment are not met
}
catch(Exception e)
{
//Throw
}
}
param1 here Is a value entered by a user and I want to validate It here, and If the requirements are not met, I want to return an error.
But how can I return an error here from the model? The method Is of the type List, and I can't not just write return false in this method.
Any suggestion how to do It?
It is good that you didn't thought about throwing an exception, when requirements are not met. We shouldn't use exceptions for controlling program flow.
I have two options in my mind :
1. Use objects
Modify your GetReportsForSearch method to following signature:
internal static List<Contracts.DataContracts.Report> GetReportsForSearch(string searchVal,
string searchParam, ReportRequestor requestor)
{
var param1 = new SqlParameter("#SearchVal", searchVal);
var ctx = new StradaDataReviewContext2();
var reports = new List<Contracts.DataContracts.Report>();
try
{
//Validate param1 here and call RequirementsAreNotMet method if the requirements are not met
requestor.RequirementsAreNotMet();
}
catch(Exception e)
{
//Throw
}
}
And then you can implement code responsible for handling this situation in ReportRequestor class
public class ReportRequestor
{
public void RequiremenrsAreNotMet()
{
//code which handle situation when requiremenets are not met
}
}
2. Use return type as indicator of status
In this way, when requirements are not met you should create ReportGenerationStatus object with HasResult flag set to false.
In other case just set HasResult to true and also set results accordingly. This somewhat mimics Option type known from functional languages
internal static ReportGenerationStatus GetReportsForSearch(string searchVal, string searchParam)
{
//code for your method
}
public class ReportGenerationStatus
{
public List<Contracts.DataContracts.Report> Result { get; set; }
public bool HasResult { get; set; }
}
I have 2 data sources: online and offline (cached). Both of them returns IObservable of object which contains 2 flags - IsSuccess and IsCached. I would like to get data from online source but only when IsSuccess=true. If this fail I would like to get data from offline source. Additionally I want to save new data in cache for future. I am not sure how to do it best in RX.
Here is my implementation of that but I think it can be done much better
public IObservable<Result<SampleModel>> GetSampleModel()
{
IObservable<Result<SampleModel>> onlineObservable = _onlineSource.GetData<SampleModel>();
IObservable<Result<SampleModel>> offlineObservable = _offlineSource.GetData<SampleModel>();
var subject = new Subject<Result<SampleModel>>();
onlineObservable.Do(async (result) =>
{
if (result.IsSuccess)
{
await _offlineSource.CacheData(result.Data).ConfigureAwait(false);
}
}).Subscribe((result) =>
{
if (result.IsSuccess)
{
subject.OnNext(result);
}
subject.OnCompleted();
});
return subject.Concat(offlineObservable).Take(1);
}
Result class - wrapper for data:
public class Result<T>
{
public Result(Exception exception)
{
Exception = exception;
}
public Result(T data, bool isCached = false)
{
IsCached = isCached;
IsSuccess = true;
Data = data;
}
public bool IsSuccess { get; private set; }
public bool IsCached { get; private set; }
public T Data { get; private set; }
public Exception Exception { get; private set; }
}
Your implementation will not work reliably, because there is a race condition in there. Consider this:
var temp = GetSampleModel(); // #1
// Do some long operation here
temp.Subscribe(p => Console.WriteLine(p)); // #2
In this case, fetching data will start in #1, and if the data is received and pushed to subject before #2 executes, nothing will be printed no matter how long you wait.
Usually, you should avoid subscribing inside a function returning IObservable to avoid such issues. Using Do is also a bad smell. You could fix the code using ReplaySubject or AsyncSubject, but in such cases I generally prefer Observable.Create. Here is my rewrite:
public IObservable<SampleModel> GetSampleModel(IScheduler scheduler = null)
{
scheduler = scheduler ?? TaskPoolScheduler.Default;
return Observable.Create<SampleModel>(observer =>
{
return scheduler.ScheduleAsync(async (s, ct) =>
{
var onlineResult = await _onlineSource.GetData<SampleModel>().FirstAsync();
if (onlineResult.IsSuccess)
{
observer.OnNext(onlineResult.Data);
await _offlineSource.CacheData(onlineResult.Data);
observer.OnCompleted();
}
else
{
var offlineResult = await _offlineSource.GetData<SampleModel>().FirstAsync();
if (offlineResult.IsSuccess)
{
observer.OnNext(offlineResult.Data);
observer.OnCompleted();
}
else
{
observer.OnError(new Exception("Could not receive model"));
}
}
return Disposable.Empty;
});
});
}
You can see that it still isn't terribly pretty. I think that it's because you chose not to use natural Rx system of handling errors, but instead to wrap your values in Result type. If you alter your repository methods to handle errors in Rx way, resulting code is much more concise. (Note that I changed your Result type to MaybeCached, and I assume that now both sources return IObservable<SampleModel>, which is a cold observable either returning a single result or an error):
public class MaybeCached<T>
{
public MaybeCached(T data, bool isCached)
{
IsCached = isCached;
IsSuccess = true;
}
public bool IsCached { get; private set; }
public T Data { get; private set; }
}
public IObservable<SampleModel> GetSampleModel()
{
_onlineSource
.GetData<SampleModel>()
.Select(d => new MaybeCached(d, false))
.Catch(_offlineSource
.GetData<SampleModel>()
.Select(d => new MaybeCached(d, true))
.SelectMany(data => data.IsCached ? Observable.Return(data.Data) : _offlineSource.CacheData(data.Data).Select(_ => data.Data));
}
Catch is used here in order to obtain a conditional switch you asked for.
My code looks like this right now:
return Ok(new
{
error = "Username not found",
errors = "Username not found",
success = false
});
and
return Ok(new
{
error = "Username not found",
errors = results.Errors,
success = false
});
What I would like to do is to make errors into a list of strings and then in the first return have the first element of the list set to "Username not found". I would also like to have a class for this instead of new but should I use a private or a public class?
Can someone give me some advice on how I could do this?
If you go with private constructor than you have to expose this by another public API - for example static method. So you have two options one is public constructor or property initializer.
Finally making a list of errors is easy way and Lucas Trzesniewski gave you example of it.
Version with public constrcutor:
public class Ok
{
public Ok(IList<string> errors, bool success)
{
this.Errors = errors;
this.Success = success;
}
public IList<string> Errors { get; set; }
public bool Success { get; set; }
}
Version with private constructor:
public class Ok
{
private Ok(IList<string> errors, bool success)
{
this.Errors = errors;
this.Success = success;
}
public IList<string> Errors { get; set; }
public bool Success { get; set; }
public static Ok Create(IList<string> errors, bool success)
{
return new Ok(errors, success);
}
}
Looking at response, you could use the built-in methods in Web API to simplify this.
For instance, the success property of your response highlights that the response was probably not OK and should probably be a BadRequest.
You could use ModelState to return a list of errors, built-up throughout the method. For example in your controller:
if (!userFound) {
ModeState.AddModelError("Username", "Username not found");
return BadRequest(ModelState);
}
In this instance I would suggest using the built-in constructs to handle errors. This way you do not need an extra class to client errors.