对于这个简单的逻辑,什么是惯用的Clojure?

对于这个简单的逻辑,什么是惯用的Clojure?,clojure,idioms,Clojure,Idioms,我用Clojure编写了一个简单的人工编写的auth函数,我觉得它一点也不习惯。有没有更好的写作方法: (defn auth [username password] (let [user-record (credential-fn username)] (if (and user-record (verify-pw password)) (let [user-record (dissoc user-record :password)] {:status

我用Clojure编写了一个简单的人工编写的auth函数,我觉得它一点也不习惯。有没有更好的写作方法:

(defn auth [username password] 
  (let [user-record (credential-fn username)]
    (if (and user-record (verify-pw password))
      (let [user-record (dissoc user-record :password)]
        {:status 200 :body user-record})
      {:status 401})))
我认为可以通过使用
if let
摆脱
if
,但是
if
正在进行布尔检查,我需要绑定
用户记录
?卡住了


注意:
dissoc
正在从
用户记录中删除密码,因此它不会返回到正文中。

我认为您的函数最大的问题是它试图同时处理三件事:

  • 检查用户名和密码是否对用户有效(
    凭证fn
    验证pw
  • 清理记录数据
    (dissoc用户记录密码)
  • 构建环形响应图(
    {:status 401}
    vs.
    {:status 200:body user record}
  • 我将把你的代码分成两个独立的函数:

    (defn authenticate
      [username password]
      (and (verify-pw password) 
           (dissoc (credential-fn username) :password)))
    
    (defn login
      [username password]
      (if-let [user-record (authenticate username password)]
        {:status 200 :body user-record}
        {:status 401}))
    

    我更喜欢这个版本,因为它将事物分割成不同的函数,这正是我想要的。这里唯一的问题是,在通过
    凭证fn
    读取用户记录之前执行
    验证pw
    ,这对于这个人为的示例很好,但我认为在实际场景中,我需要先读取用户记录,然后验证密码,但这会使身份验证返回布尔值,不是吗,阅读
    login
    时,
    authenticate
    是否会从地图中删除密码并不明显。对我来说,这将是
    登录的责任,因为它处理的是响应映射。@PaulDrummond,我大部分时间只是将您的代码重新排序(因此顺序可能不正确)。这看起来很奇怪,因为无论是
    verify pw
    还是
    credential fn
    都不需要用户名和密码来检查用户是否有效。在我的例子中,我试图描述认证用户是低级逻辑(服务逻辑?)和清理敏感数据的数据,例如密码应该在那里完成。我会考虑一些(和(用户存在的用户名)(验证盘用户名密码)(凭据fn用户名))。并定义凭证fn,以不返回密码或密码散列等潜在“风险”数据。这将降低某人犯简单错误的可能性。实际上,您可能需要一些更复杂的东西,因为当前示例没有反馈有关身份验证失败原因的任何信息,例如错误的用户名或错误的密码等。