Clojure style / idiom:创建地图并将其添加到其他地图

时间:2014-09-16 18:29:21

标签: clojure styles idioms idiomatic

我正在编写一个Clojure程序来帮助我执行安全风险评估(最终厌倦了Excel)。

我对Clojure成语和风格有疑问。

要在风险评估中创建有关资产的新记录,我会通过我目前正在处理的风险评估(地图),并且有关资产和我的品牌资产功能的大量信息会创建资产,将其添加到RA并返回新的RA。

(defn make-asset
  "Makes a new asset, adds it to the given risk assessment
  and returns the new risk assessment."
  [risk-assessment name description owner categories
   & {:keys [author notes confidentiality integrity availability]
      :or   {author "" notes "" confidentiality 3 integrity 3 availability 3}}]
  (let [ia-ref (inc (risk-assessment :current-ia-ref))]
    (assoc risk-assessment
      :current-ia-ref ia-ref
      :assets (conj (risk-assessment :assets)
                    {:ia-ref ia-ref
                     :name name
                     :desc description
                     :owner owner
                     :categories categories
                     :author author
                     :notes notes
                     :confidentiality confidentiality
                     :integrity integrity
                     :availability availability
                     :vulns []}))))

这看起来像是一种明智的方式吗?

我可以让它更惯用,更短,更简单吗?

我正在考虑的具体事情是:

  • 应该让资产将资产添加到风险评估中吗? (在风险评估之外,资产毫无意义)。
  • 是否有更简单的方法来创建资产;和
  • 将其添加到风险评估中?

谢谢

2 个答案:

答案 0 :(得分:1)

一些建议,可能适用也可能不适用。

  1. 无价值的Clojure成语是nil。使用它。
  2. asset显示为平面地图。位置和的混合 关键字参数容易混淆,容易受到什么变化的影响 使资产有效。
  3. 正如@Symfrog建议的那样,将资产的验证与其分开 与风险评估相关联。
  4. 不要将:current-ia-ref作为风险条目 评定。这只是资产数量。
  5. 将资产的默认条目拉出到地图中。 您可以根据需要更改假定的默认值。
  6. 这给了我们类似以下内容(未经测试):

    (def asset-defaults {:confidentiality 3, :integrity 3, :availability 3})
    
    (defn asset-valid? [asset] (every? asset [:name :description :owner]))
    
    (defn add-asset [risk-assessment asset]
      (if (asset-valid? asset)
        (update-in
          risk-assessment
          [:assets]
          conj (assoc
                 (merge asset asset-defaults)
                 :ia-ref (inc (count (:assets risk-assessment)))
                 :vulns []))))
    

    回复评论

    :current-ia-ref不是计数。如果资产被删除,则不应减少:current-is-ref

    然后(4)不适用。

    我不确定你的陈述的相关性,即没有价值的Clojure成语是零。可以在这方面进一步解释吗?

    引用Differences with other Lisps在Clojure中 nil 表示“没有”。它表示没有任何类型的值,并且不是特定于列表或序列

    在这种情况下,我们不需要给:author:notes空字符串值。

    '平面地图':你是在谈论函数的参数,如果是的话,我同意。

    是。

    我不确定为什么要定义asset-valid?函数。这似乎有点超出了原来的需要:我个人更喜欢确保只能创建有效资产而不是事后检查。

    您的add-asset函数使用其参数列表的结构来确保风险评估名称 description 所有者类别存在(我忘记检查类别)。如果您将数据显示为地图 - 无论是作为单个参数还是通过解构 - 您将失去此约束。所以你必须明确检查数据(是否在单独的函数中这样做是没有意义的)。但是有好处:

    • 您可以查看超过某些参数的存在。
    • 您不必记住参数的顺序。

    你的版本不会意味着如果我决定将资产作为未来的记录,我必须更改所有名为add-asset的代码吗?

    没有。记录表现为地图 - 它实现IPersistentMap。显然,您必须更改make-asset

    ...而我的方法是隐藏资产的细节吗?

    隐藏资产的内容在什么意义上?资产是具有特定密钥所需的映射,并且可能具有若干其他特定密钥。资产是否“真的”是一个记录并不重要。

答案 1 :(得分:0)

Clojure(以及任何其他Lisp方言)的核心原则是创建小的可组合函数。

如果资产是在风险评估之外创建的,只要资产在被添加到风险评估之前没有接触到期望完全形成的资产的代码,那么这不是问题。

所以我建议以下(未经测试):

(defn add-asset-ra
  [{:keys [current-ia-ref] :as risk-assessment} asset]
  (let [ia-ref (if current-ia-ref
                 (inc current-ia-ref)
                 1)] 
    (->  risk-assessment
         (assoc :current-ia-ref ia-ref)
         (update-in [:assets] #(conj % (assoc asset :ia-ref ia-ref))))))

(defn make-asset
  [name description owner categories
   & {:keys [author notes confidentiality integrity availability]
      :or   {author "" notes "" confidentiality 3 integrity 3 availability 3}}]
  {:name name
   :desc description
   :owner owner
   :categories categories
   :author author
   :notes notes
   :confidentiality confidentiality
   :integrity integrity
   :availability availability
   :vulns []})

您可能还会发现Schema库可用于验证函数参数的形状。