2011-07-05 32 views
8

Tôi đã viết/đang viết một đoạn mã phân tích vật lý, ban đầu cho bản thân mình, bây giờ hy vọng sẽ được sử dụng và mở rộng bởi một nhóm nhỏ các nhà vật lý. Không ai trong chúng ta là những người kinh nghiệm C++. Tôi đã đặt cùng một khuôn khổ nhỏ tóm tắt dữ liệu "sự kiện vật lý" vào các đối tượng được thực hiện bởi một chuỗi các công cụ có thể dễ dàng được hoán đổi vào và ra tùy thuộc vào các yêu cầu phân tích.Tình bạn không được thừa hưởng - lựa chọn thay thế là gì?

Điều này đã tạo hai nửa cho mã: mã "phân tích vật lý" điều khiển các đối tượng sự kiện và tạo kết quả của chúng tôi thông qua các dẫn xuất của cơ sở "Công cụ"; và mã "cấu trúc" đính kèm tệp đầu vào, chia công việc thành các lần chạy song song, liên kết các công cụ thành chuỗi theo một số tập lệnh, v.v.

Vấn đề là: để người khác sử dụng mã, điều cần thiết mọi người dùng đều có thể theo dõi từng bước đơn lẻ để sửa đổi dữ liệu sự kiện theo bất kỳ cách nào. Do đó, (thêm) nhiều dòng mã cấu trúc khó có thể gây khó khăn, trừ khi nó rõ ràng và có tính chất ngoại biên rõ ràng với vật lý. Tồi tệ hơn, nhìn vào nó quá chi tiết có thể cho mọi người ý tưởng - và tôi muốn họ không chỉnh sửa mã cấu trúc mà không có lý do rất tốt - và quan trọng nhất là họ không được giới thiệu bất cứ thứ gì ảnh hưởng đến vật lý.

Tôi muốn để có thể:

  • A) chứng minh một cách rõ ràng rằng mã cấu trúc không chỉnh sửa dữ liệu sự kiện trong bất kỳ cách nào
  • B) thực hiện này người dùng một lần khác bắt đầu tự mở rộng mã số (không ai trong số chúng tôi là chuyên gia và vật lý luôn luôn đến trước - bản dịch: mọi thứ không bắt vít là trò chơi công bằng cho một khó khăn hack)

Trong kịch bản lý tưởng của tôi dữ liệu sự kiện sẽ là riêng tư, với các công cụ vật lý có nguồn gốc kế thừa quyền truy cập từ lớp cơ sở Công cụ. Tất nhiên trong thực tế điều này là không được phép. Tôi nghe có lý do chính đáng cho việc này, nhưng đó không phải là vấn đề. Thật không may, trong trường hợp này, phương pháp gọi getters/setters từ cơ sở (là một người bạn) sẽ tạo ra nhiều vấn đề hơn giải quyết - mã phải sạch sẽ, dễ theo dõi và được kết nối với vật lý càng tốt trong việc thực hiện các công cụ chính nó (một người sử dụng không cần phải là một chuyên gia trong cả hai C + + hoặc các hoạt động bên trong của chương trình để tạo ra một công cụ).

Vì tôi có lớp cơ sở đáng tin cậy và mọi dẫn xuất sẽ phải chịu sự giám sát chặt chẽ, có bất kỳ vòng xoay nào khác nhưng cũng được thử nghiệm cách cho phép truy cập vào chỉ những dẫn xuất này? Hoặc bất kỳ cách nào từ chối truy cập vào các dẫn xuất của một số cơ sở khác?


Để làm rõ tình hình tôi có cái gì đó như

class Event 
{ 
    // The event data (particle collections etc) 
}; 

class Tool 
{ 
    public: 
     virtual bool apply(Event* ev) = 0; 
}; 

class ExampleTool : public Tool 
{ 
    public: 
     bool apply(Event* ev) 
     { 
      // do something like loop over the electron collection 
      // and throw away those will low energy 
     } 
}; 

Các lý tưởng sẽ để hạn chế quyền truy cập vào các nội dung của sự kiện để chỉ những công cụ này vì hai lý do (A và B) trên đây.

Cảm ơn mọi người về các giải pháp được đề xuất. Tôi nghĩ, như tôi nghi ngờ, giải pháp hoàn hảo mà tôi mong ước là không thể.giải pháp của dribeas sẽ hoàn hảo trong bất kỳ cài đặt nào khác, nhưng chính xác trong hàm apply() mà mã cần phải rõ ràng và gọn gàng nhất có thể, về cơ bản chúng ta sẽ dành cả ngày viết/chỉnh sửa hàm apply(), và cũng sẽ cần hiểu từng dòng được viết bởi từng người khác. Nó không quá nhiều về khả năng như khả năng đọc và nỗ lực. Tôi thích giải pháp tiền xử lý từ "Vô ích". Nó không thực sự thực thi sự tách biệt, nhưng ai đó sẽ cần phải thực sự độc hại để phá vỡ nó. Đối với những người đề xuất một thư viện, tôi nghĩ rằng đây chắc chắn sẽ là một bước đầu tiên tốt, nhưng không thực sự giải quyết hai vấn đề chính (vì tôi vẫn sẽ cần phải cung cấp nguồn anyway).

+2

Nếu không có ai cần làm việc hoặc nhìn vào nguồn là chuyên gia tại C++, thì không sử dụng C++. C++ là một ngôn ngữ khó chịu đối với những người không phải chuyên gia và không thể trở thành chuyên gia, đặc biệt là nếu các kỹ thuật OO nặng đang được sử dụng. – DarenW

+0

Nghe có vẻ quen thuộc ... ai hay cái gì sở hữu dữ liệu sự kiện?Những công cụ người dùng này có phải thay đổi dữ liệu sự kiện hay sử dụng nó để tạo dữ liệu sự kiện mới không? – juanchopanza

+0

@ DarenW, tôi mạnh mẽ nghi ngờ OP không có sự lựa chọn ở đây ... – juanchopanza

Trả lời

2

Có ba giới hạn truy cập trong C++: public, protectedprivate. Câu với các công cụ vật lý có nguồn gốc kế thừa quyền truy cập từ lớp cơ sở Công cụ dường như chỉ ra rằng bạn muốn truy cập protected, nhưng không rõ liệu dữ liệu thực tế là private là trong Tool (và do đó protected suffices) hoặc hiện tại private trong một lớp học kết bạn với Tool.

Trong trường hợp đầu tiên, chỉ cần làm cho dữ liệu protected:

class Tool { 
protected: 
    type data; 
}; 

Trong trường hợp thứ hai, bạn có thể cố gắng để chơi thủ đoạn bẩn thỉu vào ngôn ngữ, ví dụ như, cung cấp một accessor ở cấp Tool:

class Data { 
    type this_is_private; 
    friend class Tool; 
}; 
class Tool { 
protected: 
    static type& gain_acces_to_data(Data& d) { 
     return d.this_is_private; 
    } 
}; 
class OneTool : public Tool { 
public: 
    void foo(Data& d) { 
     operate_on(gain_access_to_data(d));  
    } 
}; 

Nhưng tôi sẽ tránh hoàn toàn. Có một điểm mà các thông số truy cập dừng lại có ý nghĩa. Chúng là những công cụ để tránh những sai lầm, không phải để cảnh sát đồng nghiệp của bạn, và thực tế là miễn là bạn muốn họ viết mã cần truy cập vào dữ liệu đó (Tool extensions), bạn cũng có thể quên mất việc bảo vệ tuyệt đối: bạn không thể.

Một người sử dụng mà muốn truy cập vào dữ liệu cũng có thể chỉ cần sử dụng backdoor mới được tạo ra để làm như vậy:

struct Evil : Tool { 
    static type& break_rule(Data & d) { 
     return gain_access_to_data(d); 
    } 
}; 

Và bây giờ tất cả mọi người chỉ có thể sử dụng Evil như một cánh cửa để Data. Tôi khuyên bạn nên đọc số C++FAQ-lite để có thêm thông tin chi tiết về C++.

+0

(+1) Để mô tả một vấn đề chương trình, với một ví dụ mã, ngay cả khi âm thanh rõ ràng ;-) – umlcat

+0

Cảm ơn đề xuất. Tình hình với Evil sẽ là tốt - Tôi có theo dõi và đăng nhập được xây dựng vào lớp cơ sở Tool và tất cả các công cụ và các thiết lập của họ được lưu vào đầu ra chương trình cùng với kịch bản cấu hình. Nếu các công cụ đã đăng nhập không phù hợp với kịch bản thì một người rõ ràng của nó đang trở nên xấu xa - nếu chúng khớp với kịch bản thì nó sẽ làm những gì bạn yêu cầu. Nhưng cảm ơn vì lời cảnh báo. – Anthony

0

Ngoài ra còn có cách tiếp cận kiểu C, hạn chế khả năng hiển thị thay vì quyền truy cập. Nó được thi hành nhiều hơn theo quy ước và (ở một mức độ nào đó) hệ thống xây dựng của bạn, chứ không phải ngôn ngữ - mặc dù bạn có thể sử dụng một loại bảo vệ để ngăn chặn sự rò rỉ "ngẫu nhiên" của các chi tiết thực hiện Công cụ vào mã cấu trúc.

-- ToolInterface.hpp -- 
class Event; // just forward declare it 

class ToolStructuralInterface 
{ 
    // only what the structural code needs to invoke tools 
    virtual void invoke(std::list<Event*> &) = 0; 
}; 

-- ToolImplementation.hpp -- 
class Event 
{ 
    // only the tool code sees this header 
}; 
// if you really want to prevent accidental inclusion in the structural code 
#define TOOL_PRIVATE_VISIBILITY 

-- StructuralImplementation.hpp -- 
... 
#ifdef TOOL_PRIVATE_VISIBILITY 
#error "someone leaked tool implementation details into the structural code" 
#endif 
... 

Lưu ý rằng loại phân vùng vay chính nó để đặt các công cụ và mã cấu trúc trong thư viện riêng biệt - bạn thậm chí có thể có thể để hạn chế truy cập vào mã cấu trúc riêng rẽ vào mã công cụ, và chỉ chia sẻ tiêu đề và biên dịch thư viện.

2

Cung cấp mã làm thư viện với tiêu đề được sử dụng bởi bất kỳ ai muốn tạo công cụ. Điều này độc đáo đóng gói những thứ bạn muốn giữ nguyên vẹn. Không thể ngăn chặn hack nếu mọi người đều có quyền truy cập vào nguồn và muốn thay đổi bất kỳ thứ gì.