Giữ các lớp học và phương pháp của tôi càng nhỏ càng tốt?


20

Vài ngày trước, tôi đã nói chuyện với một ứng cử viên Tiến sĩ Kỹ thuật phần mềm và đôi lúc cô ấy nói với tôi:

Giữ các lớp học và phương thức của bạn càng nhỏ càng tốt

Và tôi tự hỏi nếu điều này luôn luôn là một thực hành tốt.

Ý tôi là, chẳng hạn, có xứng đáng để có một lớp chỉ có 2 người tham gia không? Chẳng hạn, trong một số phương thức tôi cần các cặp số nguyên để làm việc. Tôi có nên viết một lớp "PairOfIntgers" không?

Cách suy nghĩ này có thể "phá vỡ" mã trong quá nhiều phần không?


10
Đó phải là"As small as possible, but no smaller."
StuperUser

"Tôi có nghĩa là ví dụ, nó có xứng đáng để có một lớp chỉ có 2 thành viên trong đó không?" - Có thể là, tìm kiếm "Nỗi ám ảnh nguyên thủy" (ví dụ: jamesshore.com/Blog/PrimitiveObsession.html )
Torsten

Tôi nghĩ nguồn gốc của sự nhầm lẫn là từ "có thể". Nguyên tắc trở nên lố bịch nếu "có thể" chỉ đề cập đến mã, bởi vì lớp nhỏ nhất có thể làm bất cứ điều gì hữu ích chỉ có một phương thức (và trong một số trường hợp là 0). Ứng cử viên rất có thể có nghĩa là phải tính đến sự gắn kết và khớp nối.
Kelvin

Câu trả lời:


23

Có một hạt của sự thật trong lời khuyên đó, nhưng IMHO nó không được thể hiện rất tốt, do đó dễ hiểu lầm và / hoặc đưa đến một thái cực ngu ngốc. Ở bất kỳ giá nào, đây phải là một quy tắc của ngón tay cái, thay vì luật cứng. Và bạn phải luôn ngụ ý trong các quy tắc như vậy mệnh đề "trong giới hạn hợp lý" hoặc "nhưng đừng quên sử dụng ý thức chung của bạn" :-)

Điểm mấu chốt của sự thật là trong thực tế, các lớp học và phương pháp luôn có xu hướng phát triển tự nhiên, không co lại . Một sửa lỗi ở đây, một phần mở rộng tính năng nhỏ ở đó, xử lý một trường hợp đặc biệt ở đó ... và thì đấy, lớp học nhỏ gọn và gọn gàng của bạn bắt đầu nở rộ. Theo thời gian, mã của bạn gần như chắc chắn có xu hướng trở thành một mớ hỗn độn của mì spaghetti - trừ khi bạn chủ động chống lại xu hướng này thông qua tái cấu trúc . Tái cấu trúc hầu như luôn tạo ra nhiều lớp / phương thức nhỏ hơn từ một vài lớp lớn. Nhưng tất nhiên, có một giới hạn hợp lý để thu nhỏ. Điểm của tái cấu trúc không phải là có các lớp và phương thức nhỏ hơn, mà là để làm cho mã của bạn sạch hơn, dễ hiểu và dễ bảo trì hơn. Tại một thời điểm nhất định, làm cho các phương thức / lớp của bạn nhỏ hơn bắt đầu giảm khả năng đọc, thay vì tăng nó. Nhằm mục đích tối ưu đó. Đây là một khu vực mục tiêu mờ và di chuyển, vì vậy bạn không cần phải đánh vào đó. Chỉ cần cải thiện mã một chút bất cứ khi nào bạn nhận thấy một số vấn đề với nó .


1
chắc chắn là một quy tắc để không tuân theo một cách mù quáng, quá nhiều lớp học nhỏ là tồi tệ hơn nhiều so với một vài lớp lớn hơn hầu hết thời gian.
Ryathal

4
Nguyên tắc cá nhân của tôi là: nếu bạn không thể thấy toàn bộ phương thức thực hiện trên màn hình, hãy cấu trúc lại.
Dan Ray

6
@DanRay, yeah, tôi đã từng có quy tắc tương tự, cho đến khi tôi đọc Clean Code . Đó là một cú sốc khá lớn, nhưng dần dần khiến cho tối ưu của tôi giảm xuống khoảng 10 dòng.
Péter Török

2
IMO Clean Code là cực kỳ khủng khiếp đối với các phương pháp nhỏ. Vấn đề là khi các phương thức được làm nhỏ hơn, sẽ có nhiều hơn chúng. Tất nhiên các phương thức quá dài là quá dài, nhưng Bob Martin dường như thích 10 phương thức 1 dòng hơn 1 phương thức 10 dòng (do đó, cùng một mã có hiệu quả chiếm khoảng 5x không gian màn hình). Có lẽ nó có nghĩa là một loại mánh khóe giáo dục nào đó, tôi không thể tin ai đó thực sự nghĩ rằng mã trong cuốn sách đó là tốt.
Joonas Pulakka

5
@JoonasPulakka - Hãy nói rằng tôi chưa bao giờ đọc một phương pháp và nghĩ, "Tôi ước phương pháp này làm được nhiều hơn thế." Bằng cách rút ngắn các phương thức, bạn có thể viết các tên phương thức rất mô tả mà thường có thể loại bỏ nhu cầu đọc toàn bộ thân phương thức. Tôi tìm thấy lời khuyên trong Clean Code rất hợp lý. Chúng ta sẽ phải đồng ý không đồng ý. :)
David Harkness

9

Vấn đề quan trọng hơn để nhấn mạnh ở đây là tạo ra sự trừu tượng tốt . Các lớp nhỏ được liên kết lỏng lẻo và có độ gắn kết cao là sản phẩm của sự trừu tượng tốt .

Đôi khi nó có ý nghĩa hoàn hảo để gói gọn hai số nguyên trong một lớp. Đặc biệt là nếu bạn muốn có các phương thức 'gắn liền' với lớp này để gói gọn cách người ta có thể thao tác các thuộc tính này và để đảm bảo bạn bảo vệ chúng khỏi các phần khác của chương trình thay đổi chúng.

Một điểm tích cực khác để tạo một lớp trong trường hợp này là lớp có thể phát triển tốt hơn / đẹp hơn rất nhiều so với giả sử cấu trúc dữ liệu cấp thấp hơn như Bản đồ hoặc Danh sách có thể.

Thứ ba, một sự trừu tượng tốt có thể cải thiện khả năng đọc rất nhiều. Các lớp tuân thủ SRP thường dễ hiểu hơn rất nhiều so với các lớp không.

Và giống như một lưu ý cuối cùng ... cho dù bạn là học sinh giỏi đến đâu ... để hiểu OOP và trừu tượng tốt và khi nào sử dụng chúng, bạn cần có kinh nghiệm. Bạn cần viết mã xấu và trải qua nỗi đau để duy trì nó. Bạn cần phải thấy người khác viết mã tốt để xây dựng kiến ​​thức của bạn về điều gì là 'tốt' và điều gì sẽ là vấn đề ... Vì vậy, đừng tự đánh bại mình nếu bạn không hiểu ngay lập tức.


2

Mẫu đối tượng của God Object là thứ mà cô ấy có lẽ đã ám chỉ. Tôi có xu hướng nghĩ rằng nếu tôi có một "và" trong mô tả lớp học của mình, tôi nên có hai lớp. Nếu tôi có hơn mười dòng mã trong một phương thức / hàm, thì tôi nên chia nó ra. Là mã cướp biển, đó là những hướng dẫn nhiều hơn các quy tắc.


2

Trong lập trình hướng đối tượng, nguyên tắc trách nhiệm duy nhất nói rằng mọi đối tượng nên có một trách nhiệm duy nhất và trách nhiệm đó phải được gói gọn trong lớp. Thông thường bạn đang làm nhiều hơn một điều nếu lớp học của bạn trở nên quá lớn. Trong trường hợp của bạn, lớp chỉ là một lớp dữ liệu chứa dữ liệu hoàn toàn ổn. Bạn không nên đặt tên cho lớp PairOfInteger. Các số nguyên mô tả những gì? Tùy thuộc vào kịch bản của bạn, một Tuple (như trong C #) cũng có thể là đủ. Và bạn có thể muốn nghĩ về một thanh chống thay vì một lớp học.

Cố gắng tổ chức các lớp học nhỏ của bạn. Và phương pháp thậm chí còn nhỏ hơn. Có lẽ 10 dòng?!? Hiện tại tôi đang cố gắng sử dụng các thành phần dựa trên thiết kế và sự kiện có vẻ như giúp tổ chức các lớp nhỏ. Đầu tiên tôi lo lắng khi được đến nhiều lớp nhưng nó thực sự hiệu quả !!! http://geekswithbloss.net/theArchitectsNapkin/archive/2011/03/19/flow-design-cheat-sheet-ndash-part-i-notation.aspx http://geekswithbloss.net/theArchitectsNapkin/archive/2011/03 /20/flow-design-cheat-sheet-ndash-part-ii-translation.aspx


2

Làm cho mọi thứ đơn giản nhất có thể, nhưng không đơn giản. Đó là quy tắc tôi cố gắng thực hiện. Đôi khi, nó thực sự có ý nghĩa đối với một lớp để thực hiện những gì nói đúng với số lượng nhiều hơn một điều, nếu những điều đó có liên quan đến một số chủ đề chung . Nhìn vào .NET; có hàng tấn các lớp thực hiện một số lượng lớn các giao diện, mỗi lớp có danh sách các thành viên cần thiết riêng. Một phương thức cuối cùng có thể cần phải trở nên hơi dài nếu nó thực hiện một số thứ phức tạp với một số bước trung gian được liên kết với nhau và do đó không cho vay rất tốt để tái cấu trúc. .

Để chỉ "làm cho các lớp và phương thức càng nhỏ càng tốt", theo tôi, là sai lầm. Thách thức thực sự là, như @c_maker chỉ ra, để cung cấp sự trừu tượng tốt. Ví dụ của bạn về việc nhóm hai số lại với nhau thật tuyệt, chẳng hạn, nếu bạn đang thực hiện triển khai số học số phức hoặc nếu trên hệ thống Unix, bạn cần tham khảo ngữ cảnh người dùng / nhóm. Sẽ rất ít ý nghĩa nếu các số đại diện, giả sử, ID hóa đơn và ID sản phẩm được thêm vào hóa đơn đó.


0

Đó là lời khuyên OK, nhưng nó cần được thực hiện một cách thông minh. Chắc chắn đừng theo nó một cách mù quáng.

Khi tôi nhìn vào mã của mình, tôi biết nếu một phương thức quá lớn. Nếu nó làm quá nhiều, và quá khó để đọc, thì đó là thời gian tái cấu trúc.

Đây là một ví dụ điển hình: bạn có một vòng lặp và bạn có thể có 60 dòng mã trong phương thức đó. Trong trường hợp đó, có lẽ đã đến lúc phải cấu trúc lại bởi vì bạn có thể làm quá nhiều trong phương thức đó.

Nhưng, đó không phải là một quy tắc khó và nhanh. Đó chỉ là thứ bạn có thể học bằng cách làm. Và, các nhà phát triển khác mà bạn đang làm việc với tôi không phải lúc nào cũng đồng ý và có thể gọi bạn ra trong một đánh giá mã hoặc bất cứ điều gì.


Không bao giờ làm cho các phương thức nhỏ hơn thay vì làm theo SRP và nó sẽ tự động thực hiện công việc.
Vinay Prajapati

0

Chú Bob nói rằng bạn nên cấu trúc lại / tách / trích xuất các phương thức của mình cho đến khi không thể làm cho chúng nhỏ hơn . Điều này thường kết thúc bằng việc có một vài phương thức với mỗi 3 hoặc 4 dòng. Khi bạn nhận được quá nhiều phương thức, bạn phải tạo nhiều lớp hơn.

Nếu bạn cố gắng tuân theo SRP và một mức độ trừu tượng cho mỗi phương thức, các quy tắc này sẽ phục vụ tốt cho bạn. Ít nhất họ phục vụ tôi tốt. Nhắm mục tiêu "càng nhỏ càng tốt" mang lại cho tôi những phương pháp nhỏ hợp lý, vì tôi thường không đạt được mục tiêu.

Và nó luôn luôn dễ dàng hơn để hiểu các lớp nhỏ hơn. Hãy tiếp tục, đọc "Mã sạch"

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.