From this amazing course: Applying Functional Principles in C#
I am trying to apply domain drive design, functional principles and railway oriented programming approaches.
Can someone help me to concise those lines of code below?.
I know that I need to create some Result of T extension methods, I tried but I am not able to get them work.
What the pseudo code does is...
- Create an email value object -> Email.Create
- Create and EmailAddress entity -> EmailAddress.Create
- The result is stored at the Result of T variable emailAddress
(We do this operation before hitting the database for update operations, if we got an invalid EmailAddress, has no sense to hit the database at all)
(The railway gets broken due to the necessity to have available the variable emailAddress later on :( so sad!!. Even worst... a failed EmailAddress Result entity wasn't checked, and it should be)
- Fetch the player by Id through the player repository -> repository.GetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")
- The result is stored on the Result of T variable playerResult
(The railway gets broken once more due to the necessity to have available the variable playerResult later on :( so sad!!. Even worst... a failed to return Result Player entity wasn't checked, and it should be)
- Add the newly created EmailAddress to the Player email addresses collection -> p.AddEmailAddress(emailAddress.Value)
(The railway gets broken once more :( so sad!!. Even worst... a failure to add the EmailAddress to the player collection wasn't checked, and it should)
- Lastly save changes async and return the number or rows affected.
Here below the code lines reduced for brevity
var emailAddress = Email.Create("[email protected]")
.OnSuccess(email => EmailAddress.Create(email, default));
var playerResult = await emailAddress.OnSuccess(e => repository.GetAsync("336978e9-837a-4e8d-6b82-08d6347fe6b6")).ToResult(""));
var wasAdded = playerResult.OnSuccess(p => p.AddEmailAddress(emailAddress.Value));
var wasSaved = await wasAdded.OnSuccess(a => unitOfWork.SaveChangesAsync());
var message = wasSaved
.Ensure(r => r > 0, "No record were saved")
.OnBoth(result => result.IsSuccess ? "Ok" : result.Error);
Here below the signature of the methods
Email.Create -> public static Result<Email> Create(string email)
EmailAddress.Create -> public static Result<EmailAddress> Create(Email mailAddress, string mailAddressInstructions)
GetAsync -> public Task<Maybe<Player>> GetAsync(string id)
AddEmailAddress -> public Result<bool> AddEmailAddress(EmailAddress emailAddress)
SaveChangesAsync -> public async Task<int> SaveChangesAsync()
I performed some unit test and the code is working but as far as you can see is very far to be railway oriented.
Thanks in advance.