diff --git a/2. Services/2.1 Foundations/2.1 Foundations.md b/2. Services/2.1 Foundations/2.1 Foundations.md index cbbcd89..e0d8d0d 100644 --- a/2. Services/2.1 Foundations/2.1 Foundations.md +++ b/2. Services/2.1 Foundations/2.1 Foundations.md @@ -253,7 +253,7 @@ Our `AddStudentAsync` function in this scenario is now required to validate whet public ValueTask AddStudentAsync(Student student) => TryCatch(async () => { - await ValidateStudentOnAddAsync(student); + ValidateStudentOnAdd(student); return await this.storageBroker.InsertStudentAsync(student); }); @@ -355,7 +355,7 @@ A non-circuit-breaking or continuous validation process will require the ability In a scenario where we want to ensure any given Id is valid, a dynamic continuous validation rule would look something like this: ```csharp -private static async ValueTask IsInvalidAsync(Guid id) => new +private dynamic IsInvalid(Guid id) => new { Condition = id == Guid.Empty, Message = "Id is invalid" @@ -369,7 +369,7 @@ It's really important to point out the language engineers must use for validatio Dynamic rules by design will allow engineers to modify both their inputs and outputs without breaking any existing functionality as long as `null` values are considered across the board. Here's another manifestation of a Dynamic Validation Rule: ```csharp -private static async ValueTask IsNotSameAsync( +private static dynamic IsNotSame( Guid firstId, Guid secondId, string secondIdName) => new @@ -407,14 +407,14 @@ private void Validate(params (dynamic Rule, string Parameter)[] validations) The above function now will take any number of validation rules, and the parameters the rule is running against then examine the conditions and upsert the report of errors. This is how we can use the method above: ```csharp -private async ValueTask ValidateStudentOnAddAsync(Student student) +private static void ValidateStudentOnAdd(Student student) { ...... Validate( - (Rule: await IsInvalidAsync(student.Id), Parameter: nameof(Student.Id)), - (Rule: await IsInvalidAsync(student.Name), Parameter: nameof(Student.Name)), - (Rule: await IsInvalidAsync(student.Grade), Parameter: nameof(Student.Grade)) + (Rule: IsInvalid(student.Id), Parameter: nameof(Student.Id)), + (Rule: IsInvalid(student.Name), Parameter: nameof(Student.Name)), + (Rule: IsInvalid(student.Grade), Parameter: nameof(Student.Grade)) ); } ``` @@ -456,17 +456,17 @@ private async ValueTask ValidateStudentOnAddAsync(Student student) ...... Validate( - (Rule: await IsInvalidAsync(student.Id), Parameter: nameof(Student.Id)), - (Rule: await IsInvalidAsync(student.Name), Parameter: nameof(Student.Name)), - (Rule: await IsInvalidAsync(student.Address), Parameter: nameof(Student.Address)) + (Rule: IsInvalid(student.Id), Parameter: nameof(Student.Id)), + (Rule: IsInvalid(student.Name), Parameter: nameof(Student.Name)), + (Rule: IsInvalid(student.Address), Parameter: nameof(Student.Address)) ); ...... Validate( - (Rule: await IsInvalidAsync(student.Address.Street), Parameter: nameof(StudentAddress.Street)), - (Rule: await IsInvalidAsync(student.Address.City), Parameter: nameof(StudentAddress.City)), - (Rule: await IsInvalidAsync(student.Address.ZipCode), Parameter: nameof(StudentAddress.ZipCode)) + (Rule: IsInvalid(student.Address.Street), Parameter: nameof(StudentAddress.Street)), + (Rule: IsInvalid(student.Address.City), Parameter: nameof(StudentAddress.City)), + (Rule: IsInvalid(student.Address.ZipCode), Parameter: nameof(StudentAddress.ZipCode)) ); } ``` @@ -627,14 +627,14 @@ Here's how an Id validation would look like: ```csharp -private async ValueTask ValidateStudentOnAddAsync(Student student) +private static void ValidateStudentOnAdd(Student student) { ...... - Validate((Rule: await IsInvalidAsync(student.Id), Parameter: nameof(Student.Id))); + Validate((Rule: IsInvalid(student.Id), Parameter: nameof(Student.Id))); } -private static async ValueTask IsInvalidAsync(Guid id) => new +private static dynamic IsInvalidAsync(Guid id) => new { Condition = id == Guid.Empty, Message = "Id is invalid" @@ -671,7 +671,7 @@ Now, with the implementation above, we need to call that method to structurally public ValueTask AddStudentAsync(Student student) => TryCatch(async () => { - await ValidateStudentOnAddAsync(student); + ValidateStudentOnAdd(student); return await this.storageBroker.InsertStudentAsync(student); }); @@ -902,21 +902,21 @@ Just like we did in the structural validations section, we are going to validate ValidateStudentIsNotNull(student); Validate( - (Rule: await IsInvalidAsync(student.Id), Parameter: nameof(Student.Id)), - (Rule: await IsInvalidAsync(student.Name), Parameter: nameof(Student.Name)), - (Rule: await IsInvalidAsync(student.CreatedBy), Parameter: nameof(Student.CreatedBy)), - (Rule: await IsInvalidAsync(student.UpdatedBy), Parameter: nameof(Student.UpdatedBy)), - (Rule: await IsInvalidAsync(student.CreatedDate), Parameter: nameof(Student.CreatedDate)), - (Rule: await IsInvalidAsync(student.UpdatedDate), Parameter: nameof(Student.UpdatedDate)), - - (Rule: await IsValuesNotSameAsync( + (Rule: IsInvalid(student.Id), Parameter: nameof(Student.Id)), + (Rule: IsInvalid(student.Name), Parameter: nameof(Student.Name)), + (Rule: IsInvalid(student.CreatedBy), Parameter: nameof(Student.CreatedBy)), + (Rule: IsInvalid(student.UpdatedBy), Parameter: nameof(Student.UpdatedBy)), + (Rule: IsInvalid(student.CreatedDate), Parameter: nameof(Student.CreatedDate)), + (Rule: IsInvalid(student.UpdatedDate), Parameter: nameof(Student.UpdatedDate)), + + (Rule: IsNotSame( createBy: student.UpdatedBy, updatedBy: student.CreatedBy, createdByName: nameof(Student.CreatedBy)), Parameter: nameof(Student.UpdatedBy)), - (Rule: await IsDatesNotSameAsync( + (Rule: IsDatesNotSame( createdDate: student.CreatedDate, updatedDate: studente.UpdatedDate, nameof(Studente.CreatedDate)), @@ -930,30 +930,30 @@ Just like we did in the structural validations section, we are going to validate In the above implementation, we have implemented our rule validation engine method to validate the student object for the OnAdd operation, with a compilation of all the rules we need to setup to validate structurally and logically the student input object. We then call the logical validation methods `IsInvalidAsync`, `IsValuesNotSameAsync`, `IsDatesNotSameAsync` and `IsNotRecentAsync` to asure are conditional requirements are met. Here are the example implementations for these methods: -#### For `IsInvalidAsync` +#### For `IsInvalid` ```csharp -private async ValueTask IsInvalidAsync(Guid id) => new +private dynamic IsInvalid(Guid id) => new { Condition = id == Guid.Empty, Message = "Id is invalid" }; -private async ValueTask IsInvalidAsync(string name) => new +private dynamic IsInvalidc(string name) => new { Condition = String.IsNullOrWhiteSpace(name), Message = "Text is required" }; -private async ValueTask IsInvalidAsync(DateTimeOffset date) => new +private dynamic IsInvalid(DateTimeOffset date) => new { Condition = date == default, Message = "Date is invalid" }; ``` -#### For `IsValuesNotSameAsync` +#### For `IsValuesNotSame` ```csharp -private async ValueTask IsValuesNotSameAsync( +private dynamic IsValuesNotSame( string createBy, string updatedBy, string createdByName) => new @@ -963,9 +963,9 @@ private async ValueTask IsValuesNotSameAsync( }; ``` -#### For `IsDatesNotSameAsync` +#### For `IsDatesNotSame` ```csharp -private async ValueTask IsDatesNotSame( +private dynamic IsDatesNotSame( DateTimeOffset createdDate, DateTimeOffset updatedDate, string createdDateName) => new @@ -1174,7 +1174,7 @@ The above implementation will take care of categorizing a `NotFoundStudentExcept public ValueTask RetrieveStudentByIdAsync(Guid studentId) => TryCatch(async () => { - await ValidateStudentIdAsync(studentId); + ValidateStudentId(studentId); Student maybeStudent = await this.storageBroker.SelectStudentByIdAsync(studentId);