代码之家  ›  专栏  ›  技术社区  ›  Tristan Havelick

数据库和函数式编程有矛盾吗?

  •  109
  • Tristan Havelick  · 技术社区  · 16 年前

    我已经做了一段时间的Web开发人员,最近开始学习一些函数式编程。像其他人一样,我在将这些概念应用到我的专业工作中遇到了一些重大困难。对我来说,这主要是因为我看到了FP保持无状态的目标之间的冲突,这与我所做的大多数Web开发工作都与以数据为中心的数据库紧密相连这一事实相矛盾。

    有一件事使我在OOP方面变得更有效率,那就是发现了对象关系映射器,比如mygeneration d00dads for.net、class::dbi for perl、activerecord for ruby等等。这使我可以整天不写insert和select语句,而把精力集中在作为对象轻松地处理数据上。当然,当需要SQL查询的能力时,我仍然可以编写它们,但是如果不这样的话,它在幕后被很好地抽象出来了。

    现在,转向函数式编程,在许多FP Web框架中,比如Links,似乎需要编写大量的样板SQL代码,如 this example . Weblocks似乎更好一些,但它似乎使用某种OOP模型来处理数据,并且仍然需要为数据库中的每个表手动编写代码,如中所示。 this example .我想您应该使用一些代码生成来编写这些映射函数,但这显然不像Lisp那样。

    (请注意,我没有非常密切地查看Weblocks或链接,我可能只是误解了它们是如何使用的)。

    因此,问题是,对于Web应用程序的数据库访问部分(我认为相当大),或者其他需要与SQL数据库接口的开发,我们似乎被强制执行以下路径之一:

    1. 不使用函数式编程
    2. 以一种恼人的、非抽象的方式访问数据,包括手动编写大量SQL或类似SQL的代码ala链接
    3. 迫使我们的函数语言成为一个伪OOP范式,从而消除了真正函数式编程的优雅和稳定性。

    显然,这些选择似乎都不理想。找到了规避这些问题的方法吗?这里真的有什么问题吗?

    注意:我个人最熟悉FP前端的Lisp,因此如果您想给出任何示例并了解多种FP语言,Lisp可能是首选语言

    PS:有关特定于Web开发其他方面的问题,请参阅 this question .

    9 回复  |  直到 10 年前
        1
  •  41
  •   Svante    16 年前

    首先,我不会说CLOS(公共Lisp对象系统)是“伪OO”。这是头等舱。

    第二,我相信你应该使用符合你需要的范例。

    当函数是数据流并且实际上不需要状态时,不能无状态地存储数据。

    如果你有几个需要混合在一起,混合你的范例。不要限制自己只使用工具箱的右下角。

        2
  •  74
  •   Alex R    13 年前

    从数据库人员的角度来看,我发现前端开发人员很难找到使数据库适合他们的模型的方法,而不是考虑最有效的使用数据库的方法,这些方法不是面向对象的或功能性的,而是关系和使用集理论。我已经看到了这通常会导致代码性能不佳。此外,它还创建了难以进行性能调优的代码。

    在考虑数据库访问时,有三个主要考虑因素:数据完整性(为什么所有业务规则都应在数据库级别执行,而不是通过用户界面)、性能和安全性。编写SQL是为了比任何前端语言更有效地管理前两个考虑事项。因为它是专门设计的。数据库的任务与用户界面的任务相差甚远。奇怪的是,在管理任务时最有效的代码类型在概念上是不同的吗?

    数据库保存着对公司生存至关重要的信息。奇怪的是,当企业的生存受到威胁时,他们不愿意尝试新的方法。见鬼,许多企业甚至不愿升级到现有数据库的新版本。因此,在数据库设计中存在着固有的保守性。这是故意的。

    我不会尝试编写T-SQL或使用数据库设计概念来创建用户界面,为什么要尝试使用接口语言和设计概念来访问我的数据库?因为你认为SQL不够新颖?或者你觉得不舒服?仅仅因为某些东西不适合你最喜欢的模型,并不意味着它是坏的或错误的。这意味着它是不同的,可能是出于正当的原因而不同。您可以为不同的任务使用不同的工具。

        3
  •  28
  •   opncow Kevin Albrecht    10 年前

    你应该看看Ben Moseley和Peter Marks的论文《走出沥青坑》,可从以下网址获得: "Out of the Tar Pit" (Feb. 6, 2006)

    这是一个现代的经典,它详细描述了一个称为函数关系编程的编程范例/系统。虽然与数据库没有直接关系,但它讨论了如何将与外部世界(例如数据库)的交互与系统的功能核心隔离开来。

    本文还讨论了如何使用关系代数来定义和修改应用程序的内部状态,这显然与关系数据库有关。

    本文将不会给出一个关于如何集成数据库和函数式编程的确切答案,但它将帮助您设计一个最小化问题的系统。

        4
  •  23
  •   J. Abrahamson    13 年前
    1. 函数语言没有保持无状态的目标,它们有使状态管理显式的目标。例如,在haskell中,可以将状态monad视为“正常”状态的核心,而io monad则表示必须存在于程序之外的状态。这两个单子都允许您(a)显式地表示有状态的操作,(b)通过使用引用透明的工具组合它们来构建有状态的操作。

    2. 您引用了许多窗体,这些窗体根据其名称将数据库抽象为一组对象。事实上,这不是关系数据库中的信息所代表的!根据其名称,它表示关系数据。SQL是一种代数(语言),用于处理关系数据集上的关系,实际上它本身就是“功能性”的。我提出这一点是为了考虑:(a)ORM不是映射数据库信息的唯一方法;(b)对于某些数据库设计来说,SQL实际上是一种非常好的语言;(c)函数语言通常具有关系代数映射,这些映射以惯用方式(以及在haskell的情况下,类型检查)公开了SQL的功能。

    我想说大多数口齿不清是穷人的功能语言。根据现代的功能实践,它完全可以被使用,但是由于它不需要它们,社区就不太可能使用它们。这导致了各种方法的混合,这些方法可能非常有用,但肯定掩盖了纯功能接口如何仍然有意义地使用数据库。

        5
  •  14
  •   Mendelt    16 年前

    我不认为FP语言的无状态性质是连接到数据库的问题。Lisp是一种非纯函数编程语言,因此它不应该在处理状态时有任何问题。像haskell这样的纯函数编程语言有处理输入和输出的方法,可以应用于使用数据库。

    从您的问题看来,您的主要问题似乎在于找到一种很好的方法,将您从数据库中得到的基于记录的数据抽象为lisp-y(lisp-ish?)不用编写大量的SQL代码。这看起来更像是工具/库的问题,而不是语言范式的问题。如果你想做纯fp,也许lisp不是适合你的语言。与纯FP相比,普通的Lisp似乎更多地是关于集成来自OO、FP和其他范例的好想法。如果你想走纯FP路线,也许你应该使用Erlang或Haskell。

    我认为Lisp中的“伪OO”思想也有其优点。你可能想试试看。如果它们不适合您处理数据的方式,您可以尝试在Weblocks上创建一个层,该层允许您以您想要的方式处理数据。这可能比你自己写所有的东西更容易。

    免责声明:我不是口齿不清专家。我最感兴趣的是编程语言,一直在使用lisp/clos、scheme、erlang、python和一些ruby。在日常编程生活中,我仍然被迫使用C。

        6
  •  14
  •   David Tonhofer    11 年前

    如果您的数据库不破坏信息,那么您可以按照与“纯功能”编程值一致的功能方式使用它,方法是将整个数据库的函数作为一个值。

    如果在T时,数据库声明“Bob喜欢Suzie”,并且您有一个接受数据库和Liker的函数like,那么只要您能在T时恢复数据库,您就有一个涉及数据库的纯函数程序。例如

    # Start: Time T
    likes(db, "Bob")
    => "Suzie"
    # Change who bob likes
    ...
    likes(db "Bob")
    => "Alice"
    # Recover the database from T
    db = getDb(T)
    likes(db, "Bob")
    => "Suzie"
    

    要做到这一点,你永远不能丢弃你可能使用的信息(在所有的实用性中,这意味着你不能丢弃信息),因此你的存储需求将单调地增加。但是,您可以开始将数据库作为一系列线性离散值来使用,其中随后的值通过事务与先前的值相关。

    这是背后的主要想法 Datomic 例如。

        7
  •  12
  •   ConcernedOfTunbridgeWells    16 年前

    一点也不。有一种数据库称为“功能数据库”,其中 Mnesia 可能是最容易理解的例子。基本原理是函数式编程是声明性的,因此可以对其进行优化。可以使用 List Comprehensions 对于持久性集合和查询优化程序,可以自动计算出如何实现磁盘访问。

    记忆症是写在 Erlang 至少有一个Web框架( Erlyweb )可用于该平台。Erlang本质上是与无共享线程模型并行的,因此在某些方面,它适合于可扩展的架构。

        8
  •  6
  •   Honza Pokorny    13 年前

    我和哈斯克尔在一起很舒服。最突出的haskell Web框架(类似于rails和django)被称为yesod。它似乎有一个相当酷,类型安全,多后端ORM。看看 Persistance chapter 在他们的书中。

        9
  •  4
  •   Fried Brice    10 年前

    数据库是跟踪无状态API中状态的完美方法。如果您订阅了REST,那么您的目标是编写无状态代码,该代码与以透明方式跟踪状态信息的数据存储(或其他后端)交互,这样您的客户机就不必这样做。

    对象关系映射器的概念,即将数据库记录作为对象导入,然后对其进行修改,对于函数式编程和面向对象编程同样适用和有用。一个警告是函数式编程不会修改 对象 但数据库API允许您修改 记录 就位。客户机的控制流如下所示:

    • 将记录作为对象导入(此时数据库API可以锁定记录)。
    • 根据对象和分支的内容随意读取对象和分支,
    • 用所需的修改打包一个新对象,
    • 将新对象传递给相应的API调用,该调用将更新数据库上的记录。

    数据库将用您的更改更新记录。纯函数编程可能不允许重新分配变量 在你的计划范围内 但是您的数据库API仍然允许就地更新。

    推荐文章