我有几个处理数据库交互的函数。 (比如readModelById,updateModel,findModels等)我尝试在函数式中使用。
在OOP中,我创建了一个在构造函数中获取DB-connection-parameters的类,创建数据库连接并在实例中保存DB-handle。然后,这些函数将使用来自"此"。
的数据库句柄FP处理这个问题的最佳方法是什么?我不想在整个应用程序中处理数据库句柄。我想到了部分应用于"烘烤"句柄,但这会创建丑陋的样板代码,逐个执行并将其交还。
FP中这样的最佳实践/设计模式是什么?
答案 0 :(得分:0)
数据库操作实际上并不是函数式编程的目标域,因为它们是副作用。 FP中的主要值是尽可能使用纯函数。
但是,在OOP中有一个与此相似的可能暗示正确的方法是将数据库资源作为参数。考虑使用SOLID原则在OOP中的数据库实现。由于Interface Segregation Principle,您最终会得到每个数据库方法的接口和每个接口至少一个实现类。
// C#
public interface IGetRegistrations
{
public Task<Registration[]> GetRegistrations(DateTime day);
}
public class GetRegistrationsImpl : IGetRegistrations
{
public Task<Registration[]> GetRegistrations(DateTime day)
{
...
}
private readonly DbResource _db;
public GetRegistrationsImpl(DbResource db)
{
_db = db;
}
}
然后,为了执行您的用例,您只传入所需的依赖项而不是整组数据库操作。 (假设ISaveRegistration
存在且定义如上)。
// C#
public async Task Register(
IGetRegistrations a,
ISaveRegistration b,
RegisterRequest requested
)
{
var registrations = await a.GetRegistrations(requested.Date);
// examine existing registrations and determine request is valid
// throw an exception if not?
...
return await b.SaveRegistration( ... );
}
在上面调用此代码的地方,您必须新建这些接口的实现并为它们提供DbResource
。
var a = new GetRegistrationsImpl(db);
var b = new SaveRegistrationImpl(db);
...
return await Register(a, b, request);
注意:您可以在此处使用DI框架来尝试避免使用某些样板文件。但我觉得从彼得那里借钱给保罗。您需要花费同样多的钱来学习DI框架,以及如何让它像您自己一样连接依赖项。这是新成员必须学习的另一项技术新成员。
在FP中,您可以通过简单地定义将DB资源作为参数的函数来执行相同的操作。您可以直接传递函数,而不必将它们包装在实现接口的类中。
// F#
let getRegistrations ( DbResource : db ) ( day : DateTime ) =
...
let saveRegistration ( DbResource : db ) ... =
...
用例功能:
// F#
let register fGet fSave request =
async {
let! registrations = fGet request.Date
// call your business logic here
...
do! fSave ...
}
然后调用它你可能会做这样的事情:
register (getRegistrations db) (saveRegistration db) request
此处db
的部分应用类似于构造函数注入。你的损失&#34;从无需为每个数据库操作定义接口+实现的节省,将其传递给多个函数是最小的。
尽管使用的是功能优先的语言,但上面原则上与OO / SOLID方式相同......只需更少的代码行。要进一步深入功能领域,您必须努力消除业务逻辑中的副作用。副作用可能包括:当前时间,随机,抛出异常,数据库操作,HTTP API调用等。
由于F#不要求你声明副作用,我指定一个副作用应该停止使用的地方。对我来说,用例级别(上面的register
函数)是副作用的最后一个位置。任何低于此的业务逻辑,我都致力于将它们推向用例。这是一个学习过程,所以如果一开始看起来不可能,不要气馁。现在就做你必须做的事情,随时学习。
我a post试图对FP的好处以及如何获得它们设定正确的期望。