我是函数式编程的新手,并且正在尝试在非常强制的代码库中工作,所以我试图编写主要是FP的代码,但不能是完整的。
我必须为下面的方法写一个重写...
protected override string CreateEntity(XElement xe)...where xe包含数据库更新所需的两部分数据。该方法需要验证xe的内容,然后执行更新,如果成功则返回"“,否则返回以竖线分隔的错误列表。
我在language-ext测试中借鉴了credit card validation sample,并编写了一些辅助方法,如下所示(实现与示例非常相似,所以省略了)……
private Validation<string, int> ValidateRegionID(XElement xe)在示例中,他对这些元素的集合使用Apply,如果一切正常,则返回作为新信用卡对象的Validation,如果没有,则返回Error。在我的例子中,如果一切顺利,我没有任何东西可以返回(因为我正在进行数据库更新,而不是创建新对象),所以到目前为止……
Validation<string, Unit> validation = (ValidateRegionID(xe), ValidateClinAppsID(xe))
.Apply((regionID, clinAppsID) =>
{
// Do the database update (yes, impure code)...
return Unit.Default;
});我不知道这是不是最好的方法,所以欢迎任何建议。
我更大的问题是下一步该怎么做。以下工作,但看起来不是很优雅或FP对我来说…
return validation.IsFail
? string.Join("|", validation.FailAsEnumerable())
: "";有没有更好的方法来做这件事?
发布于 2020-04-23 20:25:02
代码的最后一部分(格式化错误)可以这样完成:
[Fact]
void Test()
{
Validation<string, Unit> resultFromDatabase = Fail<string, Unit>("error");
var showError1 = string.Join("|", resultFromDatabase.FailToSeq()); // use the fact that FailToSeq() will return empty seq for success
var showError2 = string.Join("|", resultFromDatabase.IfSuccess(Seq<string>())); // explicitly supply a value of the error type (Seq<string>) for success case
var showError3 = resultFromDatabase.Match(_ => "", errors => string.Join("|", errors)); // only call string.Join for errors
}选择你最喜欢的变体。如果您想要干净的代码/不依赖于FailToSeq()实现同时适用于这两种情况,那么您应该使用Match或IfSuccess/IfFail显式地处理这两种情况。
如果你想改进你的整体设计(避免不纯的代码),你可能需要改变一些基本的东西。一种(非常FP的)选择是使用一个免费的Monad,在LanguageExt中有一些进展使得这变得更容易,但这可能是转换传统OO代码库的一大步。请参见:
https://github.com/louthy/language-ext/releases/tag/3.4.11 (使用CodeGen的免费单曲) https://github.com/louthy/language-ext/wiki/Thinking-Functionally:-Application-Architecture
发布于 2020-04-23 00:36:10
您可以简单地在验证失败的情况下抛出异常。无论谁稍后调用您的代码,都可以在其上应用异常处理。
另一种选择是发送错误代码而不是消息。在这种情况下,被调用者可以将每个错误代码转换为特定的错误。
https://stackoverflow.com/questions/61370225
复制相似问题