2009-08-27 27 views
7

Vì vậy, có quy tắc "Do One Thing" trong sách "Clean Code". Nhưng chúng ta thực sự phải thực hiện điều này bao xa.Thực hiện một điều - Cách thực hiện quy tắc này bao xa?

Ví dụ những điều khoản sau đây:

Settings.Default.BaudRate = baudRate; 
Settings.Default.COMPort = port; 
Settings.Default.DataBits = dataBits; 
Settings.Default.Handshake = handshake; 
Settings.Default.Parity = parity; 
Settings.Default.ReadTimeout = readTimeout; 
Settings.Default.WriteTimeout = writeTimeout; 
Settings.Default.CommunicationTimeout = communicationTimeout; 
Settings.Default.Save(); 

Ok, chắc chắn có nhiều hơn một tuyên bố ở đây, nhưng nó cảm thấy với tôi như họ chỉ làm một điều. Lưu cài đặt.

Tôi có tính năng này trong một hàm duy nhất. Bạn có thực sự lấy appart này và có một phương pháp duy nhất cho mọi cài đặt không?

Khi nào bạn tuân theo quy tắc này và khi nào bạn không?

+1

Nếu những được tài sản, sau đó bạn về cơ bản có một phương pháp khác nhau cho mỗi người, phải không? Tôi không phải là một anh chàng C#, nhưng những người giống như đạo cụ. –

+0

Cảm ơn tất cả các bạn đã trả lời :-) – TimothyP

Trả lời

18

Trông hoàn toàn hợp lệ với tôi. Tên phương thức hiển nhiên cho mã đó là SaveSettings, cho biết phương thức thực hiện chính xác một điều. Không có gì phải lo lắng về.

+0

hoặc saveSettings phụ thuộc vào kiểu mã hóa. Câu trả lời này là hoàn hảo mặc dù. – wlashell

+0

Có, nó có *** một điều: Lưu cài đặt. Đừng lo lắng ... – awe

6

Tôi muốn giữ tất cả chúng trong một hàm SaveSettings() duy nhất - nếu bạn đặt chúng theo chức năng riêng của chúng, bạn vẫn cần phải gọi tất cả các chức năng đó từ một hàm khác.

4

Tôi giả định tham chiếu quy tắc này khi chia một hàm thành nhiều hàm phụ.

Bạn có ý tưởng đúng - cài đặt lưu là "một thứ" và có thể có chức năng riêng. Đặt mỗi thiết lập trong chức năng riêng của nó sẽ là quá mức cần thiết. Một hướng dẫn khác mà tôi đã nghe có thể giúp bạn hiểu khái niệm "một điều": Nếu chức năng dài hơn một hoặc hai trang, có thể nó được viết tốt hơn bằng cách chia nội dung của nó thành nhiều chức năng phụ.

18

Phần tiếp theo của sách, Một mức trừu tượng cho mỗi chức năng, đi một chặng đường dài để trả lời câu hỏi này. Tất cả các câu lệnh đó đều ở cùng mức trừu tượng, do đó chức năng này đã làm một việc, lưu các thiết lập.

+0

Vẫn cần đến phần đó: p – TimothyP

6

Có, mọi phương pháp chỉ nên thực hiện một chỉ. Nhưng đó là một điều gì?

Điều này tùy thuộc vào mức độ trừu tượng của phương pháp của bạn. Một phương pháp (thuộc tính) để lưu một cài đặt đơn giản là trừu tượng thấp. Sự trừu tượng cao hơn tiếp theo sẽ là phương pháp được đề xuất SaveSettings.

Ngay ở đầu trang bạn có một phương pháp đơn/chức năng main mà cũng không chỉ có một điều: Toàn bộ chương trình ...

2

On đội của chúng tôi, chúng tôi cố gắng làm theo một mục đích cho mỗi hướng dẫn chức năng. Để giúp các nhà phát triển, chúng tôi đã thêm một đề xuất vào các tiêu chuẩn của chúng tôi mà họ xem xét tái cấu trúc nếu một hàm vượt quá 25 dòng. Vì vậy, nếu bạn có 100 dòng thuộc tính cài đặt mã, bạn có thể xem xét tách chúng theo các loại như SaveUserSettings, SaveNetworkSettings, v.v.

Mục tiêu cuối cùng là làm cho mã dễ đọc hơn. Nếu bạn lấy phương pháp của bạn và chia nó thành 20 cuộc gọi mỗi thiết lập một tài sản, tôi sẽ nghĩ rằng nó sẽ tốn nhiều thời gian hơn để theo dõi và hỗ trợ.

4

Nhìn vào mã của bạn trong sự cô lập, rất khó để nói.Bạn có thể lập luận rằng chức năng của bạn làm hai việc - cập nhật các cài đặt rồi lưu các thay đổi. Ngoài ra, làm thế nào để bạn cư các giá trị, chúng được truyền vào như là các đối số cho hàm của bạn (thích hợp hơn) hay hàm của bạn nhận được các giá trị chính nó (làm cái gì khác)?

tôi sẽ làm theo các Single Responsibility Principle được tóm tắt như sau:

Không bao giờ nên có nhiều hơn một lý do cho một lớp học để thay đổi

và bình đẳng có thể được áp dụng cho phương pháp này. Trong ví dụ của bạn sẽ có một lý do để cập nhật các thiết lập, nhưng không lưu chúng?

+0

Không thực sự. Tôi sẽ không bao giờ cập nhật chúng trừ khi tôi phải lưu chúng – TimothyP

1

Mã ví dụ sẽ tốt hơn với câu hỏi, khi nào nên sử dụng thuộc tính và thời điểm sử dụng thông số trên hàm tạo hoặc phương thức để đặt trạng thái đối tượng. Tôi biết có một phần về điều này trong .NET framework guidelines, trong đó nó thảo luận về mẫu cơ sở thành phần (rất nhiều thuộc tính và trạng thái bên trong thành phần có thể không hợp lệ giữa việc gán đầu tiên và cuối cùng) so với mẫu khác (rất nhiều tham số hàm và tham số phương thức) và các đối tượng trạng thái nội bộ có giá trị sau mỗi dòng mã thực thi.

+0

Tôi sẽ xem xét – TimothyP

4

tôi đã không đọc cuốn sách cụ thể, nhưng như với khái niệm ...

"một điều" không có nghĩa là "một dòng mã "." Một điều "có nghĩa là mọi thứ trong hàm phải liên quan một cách hợp lý.

Tôi muốn chia sẻ với một số áp phích trước đây khi nói rằng" saveSetti ngs "là" một điều ". Có lẽ nó chỉ là một bất cẩn với từ ngữ, nhưng tôi sẽ tận dụng cơ hội để chỉ ra cái bẫy tiềm năng. Trong trường hợp của bạn, nó giống như "saveCommunicationSettings", mà tôi nghĩ dễ dàng phù hợp với định nghĩa "một điều". Nếu bạn đã thêm "Settings.Default.customerLoyaltyDiscount = ..." vào danh sách đó, tôi cho rằng bạn có thể đang ở trên mặt đất nguy hiểm, bởi vì bạn hiện đang trộn cài đặt liên lạc với cài đặt tính giá.

Trong cuộc sống thực, quyết định sự gắn kết hợp lý không phải là một công thức mà là một cuộc gọi phán đoán đòi hỏi phải thực hiện trí thông minh. Nếu một hàm tính toán tổng số tiền của một đơn đặt hàng bao gồm tính thuế bán hàng? Có thể cho rằng đó là hai điều: tổng giá của tất cả các mặt hàng theo thứ tự VÀ tính thuế bán hàng. Nhưng bạn cũng có thể tranh luận rằng nó chỉ là một: tìm tổng giá của lệnh, bất kể cái gì liên quan đến nó. Trong thực tế, tôi thường đưa ra quyết định dựa trên sự phức tạp của logic. Nếu tất cả những gì cần thiết để tính tổng số đơn đặt hàng là một vòng lặp đơn giản thông qua tất cả các mục tăng giá của chúng và sau đó lấy thuế suất bán hàng từ một bảng và nhân lên, tôi có thể làm tất cả trong một hàm. Nếu có nhiều hơn thế - như hệ thống tôi đang làm việc vào những ngày này, tính giá liên quan đến cổ phiếu so với đơn hàng tùy chỉnh, tìm kiếm tất cả các loại giảm giá có thể, thêm vào bảo hành, v.v. - chúng tôi thực sự cần phải phá vỡ nó lên.

0

Nếu bạn muốn chia nhỏ phương pháp của mình, tôi sẽ xem xét việc phá vỡ ánh xạ các giá trị từ tiết kiệm thực tế của đối tượng. Bạn có thể nói rằng ánh xạ các giá trị là một mức trừu tượng riêng biệt. Vì vậy, bạn sẽ có:

public void save(){ 
    mapSettings(); 
    Settings.Default.Save(); 
} 

private void mapSettings(){ 
    Settings.Default.BaudRate = baudRate; 
    Settings.Default.COMPort = port; 
    Settings.Default.DataBits = dataBits; 
    Settings.Default.Handshake = handshake; 
    Settings.Default.Parity = parity; 
    Settings.Default.ReadTimeout = readTimeout; 
    Settings.Default.WriteTimeout = writeTimeout; 
    Settings.Default.CommunicationTimeout = communicationTimeout; 
} 

Có vẻ như bản đồ có thể được sử dụng lại ở nơi khác hoặc bạn có thể muốn. Ngoài ra, nếu các cài đặt số tăng lên, chúng có thể được chia nhỏ hơn theo danh mục.

Trong trường hợp như thế này, tôi sẽ không cho rằng nó đáng giá và tôi có làm hay không tùy thuộc vào tâm trạng của tôi hoặc lượng mây trên bầu trời. Nhưng có, về mặt kỹ thuật có hai cấp độ ở đây bạn có thể tách ra.

0

làm cách nào để biết liệu một hàm có thực hiện một điều hay không? nó phụ thuộc vào mức độ trừu tượng hóa. tôi cố gắng để mô tả mức độ trừu tượng trong các ví dụ kéo (cuốn sách mã sạch, chương 3) thấy mã này

public function buildPage() { 
    $page = header(); 
    $page .= body(); 
    $page .= footer(); 
    return $page; 
} 

chức năng này chỉ làm một điều và tất cả subfunctions là một phần của cụm từ buildPage

public function sendMail() { 
    $user = $this->getUser(); 
    $this->mailer->content("send this message!") 
     ->to($user->email)->send(); 
} 

chức năng này cần email người dùng, do đó, với sự trợ giúp của hàm getUser, sendMail quản lý để nhận email người dùng. nhưng $ user = getUser() không được mô tả trong cụm từ sendmail thực hành tốt nhất cho chức năng này là

public function sendMail($email,$message) { 
    $this->mailer->content($message)->to($email)->send(); 
} 
Các vấn đề liên quan