Có phải setters và getters luôn phá vỡ Nguyên tắc trách nhiệm đơn?


8

Như chúng ta đã biết, SRP tuyên bố rằng mỗi lớp nên có trách nhiệm duy nhất và trách nhiệm đó phải được gói gọn trong lớp.

Nhưng setters và getters không phục vụ một trách nhiệm khác - họ thực hiện truy cập thuộc tính lớp dữ liệu (dữ liệu) trừu tượng.

nếu Setters và getters thực hiện truy cập thuộc tính lớp trừu tượng, thì chúng sẽ phục vụ một trách nhiệm khác .

Vì vậy, nếu tôi có một cái gì đó như thế này,

class Config
{

    private location;


    public function write(array $data)
    {
        ....
    }

    public function read($key)
    {
        ...
    }

    public function exists($key)
    {
        ...
    }

    public function delete($key)
    {
        ...
    }

    // Below comes property abstraction

    // Here I doubt - I CANNOT USE this class without them
    // but they seem to break the SRP at the same time!?

    public function setFileLocation($location)
    {
        $this->location = $location;
    }


    public function getFileLocation()
    {
        return $this->location;
    }


    public function setConfigArray(...)
    {
        ...
    }

    public function getConfigArray()
    {
        ...
    }
}

Tôi phá vỡ SRP. Vấn đề là, đó là cách duy nhất lớp có thể tồn tại.

Vì vậy, câu hỏi là

Trong tình huống của tôi, hầu như không thể tránh setFileLocation()getFileLocation()phương pháp với CRUD.

Vì vậy, nếu bằng cách kết hợp các phương thức CRUD với trừu tượng truy cập dữ liệu, tôi sẽ phá vỡ SRP,

Có cách nào để tôi có thể tuân thủ SRP và giữ khái niệm chung về lớp Cấu hình (hoạt động CRUD) cùng một lúc không?


1
@metal_fan: Bạn phá vỡ chính xác nhiều chức năng nếu bạn có thành viên công cộng hoặc nếu bạn có thành viên riêng với getter và setter công khai tầm thường. Và tôi nói chính xác như vậy bởi vì nó có thể không có gì trong một số trường hợp và tất cả trong những trường hợp khác. Tùy thuộc vào việc sử dụng chúng có thể phá vỡ bất biến nội bộ.
Jan Hudec

1
Trách nhiệm của lớp cấu hình là gì nếu nó không cung cấp một nơi tập trung để lưu trữ và truy xuất các giá trị cấu hình đó? Là SRP bị hỏng trong mọi cơ sở dữ liệu? Trong ví dụ bạn liên kết có hai trách nhiệm, 1 là getters và setters, 2 là CRUD. Trong ví dụ bạn đăng không có CRUD, vì vậy chỉ có 1 trách nhiệm.
Trylks

" Bạn đã nhầm lẫn giữa thật và thật. " - George Stanley trong cuộc trò chuyện, được trích dẫn bởi Samuel R Delany

Câu trả lời:


11

Thành thật mà nói, tôi nghĩ rằng bạn đang mang khái niệm trách nhiệm đơn lẻ quá xa. Getters và setters là ngẫu nhiên cho hoạt động của lớp cho dù bạn làm điều đó bằng cách truy cập trực tiếp vào các thành viên công cộng hoặc sử dụng các phương thức (hoặc thuộc tính) để làm điều đó.

Bạn đang đưa ra lập luận rằng việc nhận và thiết lập một số thành viên của lớp là trách nhiệm riêng biệt và do đó nên được chuyển đi nơi khác. Hãy nói rằng chúng tôi làm điều đó, và bây giờ bạn có các lớp được gọi ConfigConfigAccessor. Tại thời điểm này, bây giờ bạn có một khoảng cách không khí giữa hai lớp, vì Configkhông có giao diện để truy cập locationthành viên của nó . Điều đó làm cho nó không thể viết ConfigAccessor, và bạn bị bỏ lại với một lớp viết bất biến, một lần mà không có ích gì. Nếu bạn thêm một số loại giao diện để cho phép ConfigAccessorthực hiện công việc của nó, bạn sẽ thấy mình có vấn đề đệ quy.

SRP, giống như nhiều thứ khác trong lĩnh vực này là một nguyên tắc, không phải là quy tắc khó và nhanh. Điều đó có nghĩa là bạn nên áp dụng phán đoán vào tình huống của mình thay vì cố gắng tuân theo nó vô điều kiện. Có một ranh giới giữa việc trở thành một người theo chủ nghĩa thuần túy và hoàn thành công việc, và khi người trước ngăn cản người sau, bạn đã ở phía sai của nó.

Nếu tôi có thể phê bình thiết kế của bạn một chút: Nếu Configlớp của bạn được thiết kế là giao diện giữa tệp cấu hình được lưu trên đĩa và mã của bạn, điều cuối cùng bạn muốn làm là thay đổi vị trí giữa dòng. Nếu bạn đang thay đổi locationcách bắt đầu truy cập vào một tệp khác, bạn nên hủy đối tượng cũ và tạo một đối tượng mới. Bạn đã không làm rõ liệu bạn có ý định lưu trữ nội dung của tệp trong đối tượng hay không. Nếu bạn dự định sử dụng nó như một cách để hít vào nội dung của một tệp cấu hình và ghi nó vào một tệp khác, hãy xem xét sử dụng phương pháp sao chép dữ liệu vào một đối tượng mới trỏ vào tệp mới.


4

Có hai cấp độ khác nhau mà bạn có thể áp dụng SRP.

Cấp độ đầu tiên là cấp độ của các chức năng / phương thức riêng lẻ. Mỗi người chỉ nên thực hiện một nhiệm vụ (và đánh giá theo tên phương thức, không có phương thức nào Configphá vỡ SRP).

Cấp độ thứ hai là cấp độ của một lớp. Ở đây khái niệm về một trách nhiệm đơn lẻ trở nên trừu tượng hơn một chút, nhưng một chỉ báo tốt là nếu bạn có thể nêu trách nhiệm của một lớp trong một câu mà không sử dụng (ngụ ý) từ đó . Nếu bạn có thể làm điều đó với sự hiện diện của getters và setters, thì lớp không phá vỡ SRP.

Nói chung, getters và, ở mức độ thấp hơn, setters , tuy nhiên, một dấu hiệu cho thấy sự đóng gói của một lớp bị phá vỡ. Trong trường hợp của Configlớp, setFileLocationphương thức này là tốt, vì Configcần một số cách để biết dữ liệu được đặt ở đâu, nhưng những người khác có vẻ nghi ngờ, vì họ tiết lộ thông tin mà người dùng Configkhông cần phải có.


4

Lớp cấu hình của bạn có trách nhiệm theo dõi cấu hình, được thực hiện bằng cách giữ các tham chiếu riêng đến dữ liệu nhất định và cung cấp quyền truy cập vào chúng thông qua các phương thức trình biến đổi. Điều này không phá vỡ SRP, vì bản thân lớp vẫn có một trách nhiệm duy nhất ; các trình biến đổi chỉ đơn giản là giúp nó hoàn thành trách nhiệm đó bằng cách trừu tượng hóa quyền truy cập vào dữ liệu. Những kẻ gây đột biến không có trách nhiệm riêng biệt với lớp; họ là một phần của trách nhiệm lớn hơn của lớp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.