我试图使用铁路导向编程原则http://fsharpforfunandprofit.com/rop/和此http://indiedevspot.azurewebsites.net/2015/01/20/two-track-coding-rop-for-dummies-part-2/作为参考
我已经成功地为大多数代码库实现了这个,除了现在我们将项目放入SQL并希望使用ROP来验证这些类型。典型的模式是
图1:
let createSomething a b c = {A = a; B = b; C = c}
let createValidSomething so =
createSomething
<!> validateFunction1 so.param1
<*> validateFunction2 so.param2
<*> ...so forth and so on
您会注意到createSomething是一个返回记录类型实例的函数a - &gt; b - &gt; c - &gt;一个&#39; - &GT; B&#39; - &GT; C&#39; SQL类型提供程序返回可变类型(非记录)。让我们看看我尝试构建类似的createSomething函数
图2:
let createSQS(a, b, c, d, e, f, g) =
let sqs = context.``[dbo].[Something]``.Create(a, b, c, d, e, f, g)
sqs
此时,我们知道这已经不起作用,我们有a-&gt; b-&gt; c-&gt; d-&gt; e-&gt; f-&gt; g-&gt; context。{{1 }}。实体
我知道我可以拥有中间记录类型并遵循ROP主体,匹配成功/失败,然后从已经验证的对象创建我的对象。但这看起来不是太多步骤吗?
有人知道这个好模式吗?理想情况下,我们可以使用类似于图1的函数来生成与类型提供程序兼容的记录类型。
我愿意尝试并在Skype上闲逛:)。
答案 0 :(得分:1)
你的函数createSQS
不应该更好:
let createSQS a b c d e f g =
context.``[dbo].[Something]``.Create(a, b, c, d, e, f, g)
这个将具有a->b->c->d->e->f->g->context.[dbo].[Something].Entity
答案 1 :(得分:1)
所以我们在开发会议上得到了答案,并决定我们实际上想要在自己的功能中执行每个部分。对于内在的束缚,我们发明了自己的运算符;类似于plus(&amp;&amp;&amp;)(我将在我的网站上发布博客www.indiedevspot.com),在顶层我们使用普通绑定运行。
我们的顶级代码如下所示:
[<HttpPost>]
x.member Add(sa:Something) =
sa|>ValidateSomething
>>= converttoSSA
>>= persistSSA
由于验证,转换和持久性的独立可测试性,我们决定将问题分开。该理论认为,功能组合如果由保证有效的功能组成,本身就可以保证工作(或者有更好的机会)。
如果我们采用所提出的方法(我们还没有解决),我们会混淆创建,验证和转换的问题。这也最终会创建一个不必要的额外记录类型。