2009-02-16 24 views
39

Hầu như mọi lập trình viên đã làm điều đó một lần trong cuộc đời của mình: thiết lập một số cờ nếu giá trị của biến thay đổi. Luôn luôn có rất nhiều đặc tính và bạn muốn theo dõi nếu có điều gì thay đổiCác cách khác nhau để thực hiện chức năng 'cờ bẩn'

  1. trong bất cứ tài sản
  2. trong một tài sản cụ thể
  3. hoặc trong một số bộ thuộc tính

Tôi quan tâm theo các cách khác nhau để thực hiện chức năng "cờ bẩn" cho các tình huống trên, bên cạnh cờ bẩn rộng đối tượng tiêu chuẩn được cập nhật trên mỗi thay đổi thuộc tính. Phải có một cái gì đó tốt hơn là đặt "dirty = true" trong mỗi bộ setter: nó chỉ trông xấu xí và là một công việc tẻ nhạt.

Trả lời

24

Đối với DAO của tôi, tôi giữ một bản sao của các giá trị ban đầu như được lấy từ cơ sở dữ liệu. Khi tôi gửi nó để được cập nhật, tôi chỉ đơn giản là so sánh các giá trị ban đầu với hiện tại. Nó chi phí một chút trong chế biến nhưng nó là tốt hơn rất nhiều so với việc có một lá cờ bẩn cho mỗi tài sản.

EDIT để tiếp tục biện minh cho việc không có cờ bẩn: nếu thuộc tính trở về giá trị ban đầu, không có cách nào để phản ánh điều đó, cờ bẩn tiếp tục bẩn vì giá trị ban đầu bị mất.

+1

Tại sao nó tốt hơn rất nhiều so với việc có cờ bẩn cho mỗi thuộc tính? Bạn đang giữ nhiều dữ liệu hơn trong bộ nhớ. Tôi không nói những gì bạn đang làm là không tốt hơn, nhưng bạn đã không biện minh cho nó. –

+4

Nếu bạn thực sự nghĩ về nó, tôi không nhất thiết phải giữ nhiều dữ liệu hơn trong bộ nhớ vì tôi không cần phải mang cờ trạng thái cho mỗi thuộc tính. Tôi không cần phải lo lắng về việc thiết lập nó trở lại "không thay đổi" nếu giá trị trả về giá trị ban đầu. Cũng lá cờ bẩn sẽ KHÔNG cho phép tôi quay trở lại. –

+1

Tôi đang làm điều tương tự với DAO của tôi. Rất vui được xác nhận! – MicSim

4

Tôi sẽ đặt thay đổi() trong mỗi trình thiết lập, tức là gọi phương thức riêng thay vì chỉ thay đổi cờ. Sau đó, phương pháp có thể đặt cờ hoặc thực hiện bất kỳ việc xử lý nào là cần thiết, ví dụ: nó cũng có thể thông báo cho bất kỳ người quan sát nào.

6

Nếu bạn đang đặt cờ "bẩn" nhận ra rằng bạn đang giữ trạng thái. Tại một số điểm bạn cần phải thực hiện một hành động dựa trên trạng thái đó, nếu không bạn sẽ không cần phải giữ cờ. Vì vậy, câu hỏi sau đó sẽ trở thành: có cách nào khác để kích hoạt hành động cần thiết không? Gửi tin nhắn của một số loại? Ai tiêu thụ trạng thái "bẩn" và hành động, và có giao diện rõ ràng hơn cho thông báo đó không?

10

Tôi đã từng có lớp Cơ sở thực thể, cung cấp Logic loại bỏ/Loại bỏ.

Khi viết Entity-lớp con, bạn có thể làm một cái gì đó như:

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

này hoạt động tốt, nhưng có 'chuỗi xấu xí' bệnh ...

Hôm nay bạn có thể sử dụng Lambda Expressions để loại trừ các dây:

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

Hoặc, và tôi nghĩ rằng đây là giải pháp tốt nhất, bạn có thể sử dụng AOP:

https://www.postsharp.net/

Bằng cách này, bạn có thể xác định hành động theo Thuộc tính. Bạn tạo một thuộc tính và chỉ định rằng khi người dùng thay đổi thuộc tính liên quan, thực thể trở nên bẩn.

Ngoài ra, bạn có thể giữ một danh sách các thuộc tính trong lớp của bạn (cơ sở thực thể) sẽ ghi nhớ các thuộc tính đã thay đổi và truy cập danh sách đó từ mã AOP của bạn.

+0

Điều này nghe có vẻ giống như phương pháp tốt nhất IMO –

+1

bỏ phiếu cho đề xuất AOP, nhưng phương thức "setValue" ban đầu làm cho tôi rìa :) – msulis

8

Tôi đã tạo một lớp có tên là DirtyValue<T> có giá trị ban đầu và giá trị hiện tại.Trong lần sử dụng đầu tiên, nó đặt cả giá trị ban đầu và giá trị hiện tại. Các cuộc gọi liên tiếp chỉ thiết lập giá trị hiện tại.

Bạn có thể biết nếu nó đã thay đổi bằng cách so sánh hai, với thuộc tính bool chỉ đọc được gọi là IsDirty(). Sử dụng kỹ thuật này, bạn cũng có thể nhận được quyền truy cập vào giá trị ban đầu.

+0

Thuộc tính của loại DirtyValue hoặc bạn chỉ có các trường kiểu DirtyValue và sau đó chỉ hiển thị Currentvalue thông qua tài sản? Vẫn có vẻ như công việc khó khăn - mặc dù tốt đẹp mà bạn không phải đặt isDirty = true; tất cả các nơi –

+0

Có họ là những giá trị không thuộc tính. Tôi phơi bày chúng thông qua các đạo cụ nếu cần thiết. Tôi muốn đảm bảo rằng bất kể chúng được thiết lập như thế nào (với một tài sản hoặc trực tiếp) rằng điều bẩn thỉu vẫn hoạt động. –

+0

erm, các trường tôi ngụ ý, không phải là giá trị! :) –

5

Trong một số trường hợp với tác vụ ghi dữ liệu và tác vụ đọc độc lập, tôi đã cho mỗi tác vụ một biến số updateCount. Nhà sản xuất tăng số lượng của nó bất cứ khi nào nó viết. Bất cứ khi nào người đọc thức dậy và thấy số lượng của nó ít hơn số lượng của nhà sản xuất, nó thực hiện cập nhật với các giá trị hiện tại. Bạn cần một chút xử lý đặc biệt để tràn bộ đếm, nhưng điều này khá đơn giản để thực hiện.

Tôi đã sử dụng thành công kỹ thuật này trong mô phỏng - nơi nhà sản xuất là vòng lặp vật lý và người đọc là màn hình hiển thị 3d.

2

Một giải pháp thay thế thú vị cho cách tiếp cận rõ ràng dirty=true, mặc dù có thể là quá mức cần thiết cho hầu hết các trường hợp và thường không áp dụng, sẽ sử dụng các trang bảo vệ. Đặt trang bộ nhớ là chỉ đọc (ví dụ: VirtualProtect() trên Windows) và nắm bắt tín hiệu/ngoại lệ khi chương trình cố ghi vào trang. Tạo một bản ghi rằng trang đã được sửa đổi, sau đó thay đổi cờ bảo vệ của trang thành có thể ghi và tiếp tục thực hiện.

Đây là kỹ thuật thường được sử dụng bởi hệ điều hành để xác định xem một trang cần phải được ghi vào tệp hoán đổi trước khi nó bị xóa khỏi RAM.

-1

Bạn có thể muốn xem xét ghi đè mã gethashcode và bằng các phương thức của đối tượng miền của mình và lưu trữ mã băm ban đầu trong khóa có thể bắt đầu bằng khóa đối tượng. Sau đó tạo một quy trình lấy một đối tượng, tìm khóa của nó trong các giá trị băm có thể bắt đầu và so sánh được.

  • Nếu băm giống nhau, không thay đổi. (không gửi đến kho lưu trữ hoặc cơ sở dữ liệu)
  • nếu hàm băm khác nhau, đối tượng có thay đổi. (cập nhật)
  • Nếu không tìm thấy khóa, đối tượng là mới. (chèn)
  • Bạn không chắc chắn cách xác định xem đối tượng có cần xóa không phải là quá trình xóa theo yêu cầu và không sử dụng theo dõi mã băm cho chúng.

Tôi chưa thử điều này và hashtable có thể không phải là cách tốt nhất để theo dõi khóa đối tượng/giá trị băm. Nó sẽ lưu mem bằng cách chỉ theo dõi các mã băm và khóa. Tôi không chắc chắn 100%, nhưng tôi nghĩ rằng một số orm có thể sử dụng phương pháp này trong bối cảnh dữ liệu/đối tượng theo dõi của họ.

+3

Có một vấn đề với cách tiếp cận này: "Hash same" không phải lúc nào cũng có nghĩa là "không thay đổi", nó có thể có nghĩa là "thay đổi", nhưng các giá trị băm va chạm. –

+0

-1 xem http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx – reggaeguitar

Các vấn đề liên quan