2009-02-16 82 views
39

幾乎每個程序員都會在他的生活中做過一次:如果變量的值發生變化,則設置一些標誌。總是有很多的屬性,你想跟蹤某些東西在任何財產 實現「髒」標記功能的不同方法

  • 在一個特定的屬性
  • 或在某些屬性集合改變

    我感興趣以不同的方式來實現上述情況下的「髒標誌」功能,除了標準對象寬髒標誌在每個屬性更改上更新。必須有一些東西比在每個引用者中放入「dirty = true」:它看起來很醜並且是一件乏味的工作。

  • 回答

    24

    對於我的DAO,我保留了從數據庫中檢索的原始值的副本。當我發送它來更新時,我只是將原始值與當前值進行比較。它在處理上花費了一些成本,但比每個屬性都有髒旗要好得多。

    編輯進一步證明沒有髒標誌:如果屬性返回到它的原始值,沒有辦法反映,髒標誌因爲原始值丟失而繼續髒。

    +1

    爲什麼它比每個屬性都有髒標誌好多了?你將更多的數據保存在內存中。我不是說你在做什麼不好,但你沒有理由。 – 2009-02-16 17:52:14

    +4

    如果你真的考慮過它,我不一定要在內存中保存更多的數據,因爲我不需要爲每個屬性攜帶狀態標誌。如果數值恢復到原來的值,我不必擔心將其設置回「不變」。另外骯髒的國旗不會讓我回去。 – 2009-02-16 17:59:35

    +1

    我正在用我的DAO做同樣的事情。這是很好的被證實! – MicSim 2009-02-16 18:59:49

    4

    我會把改變()在每個setter,即調用一個私人的方法,而不是隻改變一個標誌。然後該方法可以設置標誌或做任何需要的處理,例如,它也可以通知任何觀察員。

    6

    如果您正在設置一個「髒」標誌意識到您正在保持狀態。在某些情況下,你需要根據該狀態採取行動,否則你不需要保持國旗。那麼問題就變成了:是否有另一種觸發所需行動的方式?發送某種消息?誰消耗「髒」狀態並採取行動,並且是否有更清晰的通知界面?

    10

    我曾經有一個基本的實體類,提供髒/刪除邏輯。

    當寫實體-子類,你可以這樣做:

    public string Name 
    { 
        get { return name; } 
        set { setValue("Name", value); } 
    } 
    

    這工作得很好,但有「醜陋的字符串」病......

    今天,你可以使用Lambda表達式來排除字符串:

    set {setValue(x => x.Name, value);} 
    

    或者說,我認爲這是最好的解決方案,你可以使用AOP

    https://www.postsharp.net/

    這樣,您可以通過屬性定義操作。您創建一個屬性並指定當用戶更改關聯的屬性時,該實體變髒。

    此外,您可以保留您的班級(基本實體)中的屬性列表,以記住更改後的屬性,並從您的AOP代碼中訪問該列表。

    8

    我創建了一個名爲DirtyValue<T>的類,它具有原始值和當前值。在第一次使用時,它會設置原始值和當前值。連續呼叫僅設置當前值。

    如果你可以告訴它通過比較兩個改變,稱爲IsDirty只讀布爾屬性()。使用這種技術,您也可以訪問原始值。

    5

    在有數據寫入任務和獨立的讀取器任務某些情況下,我已經給每個任務updateCount變量。生產者在寫入時增加其計數。只要讀者醒來並發現其計數小於生產者數量,它就會使用當前值進行更新。你需要對計數器溢出進行一些特殊的處理,但這很容易實現。

    我已經成功地在模擬中使用了這種技術 - 生產者是物理循環,讀者是3D顯示器。

    2

    一個有趣的替代明確dirty=true的做法,儘管它可能是矯枉過正的大多數情況下,往往不適用,是使用防護頁面。將內存頁面設置爲只讀(例如在Windows上使用VirtualProtect()),並在程序嘗試寫入頁面時捕獲信號/異常。記錄該頁面已被修改,然後將頁面的保護標誌更改爲可寫並恢復執行。

    這通常是由操作系統以確定是否需要之前將其從RAM逐出將被寫入到交換文件中的頁面所採用的技術。

    -1

    你可能想看看重寫的GetHashCode和等於你的域對象的方法和對象密鑰存儲在哈希表中原來的哈希碼。然後創建一個接受對象的過程,在散列表中找到它的關鍵字並比較散列值。

    • 如果散列相同,沒有變化。 (不發送到存儲庫或數據庫)
    • 如果散列不同,對象有變化。 (更新)
    • 如果找不到密鑰,對象是新的。 (插入)
    • 不知道如何確定是否需要刪除對象,而不是根據請求刪除進程而不使用哈希碼跟蹤。

    我還沒有嘗試過這一點,並且散列表可能不是跟蹤對象鍵/散列值的最佳方式。它將通過僅跟蹤哈希代碼和密鑰來保存mem。我不是100%確定的,但我認爲一些orm可能會在他們的數據上下文/跟蹤對象中使用這種方法。