Làm thế nào để bạn thường bố trí các khu vực của một lớp?


17

Tôi đã tự hỏi nếu có một tiêu chuẩn để đặt ra các khu vực của một lớp học.

Tôi hiện đang sử dụng

Fields
Constructor
Properties
Public Methods
Private Methods

Fieldslà tài sản riêng tư và Propertieslà tài sản công cộng. Thông thường tôi sẽ sử dụng các tiểu vùng trong đó nếu cần hoặc đôi khi sẽ thêm các khu vực khác bên dưới (chẳng hạn như các thành viên cơ sở hoặc giao diện).


1
Bạn đang nói về bố cục nói chung hoặc sử dụng "#regions"?
snmcdonald

1
@snmcdonald Tôi sử dụng #regionthẻ để xác định một phần
Rachel

Đây không phải là một câu hỏi wiki cộng đồng? Tôi không tin có một tiêu chuẩn và câu trả lời có thể thay đổi tùy thuộc vào ngôn ngữ.
Raveline

7
Tôi bắt đầu bằng cách xóa tất cả #regions
Ed S.

3
@Ed S. +1 vì các vùng là ma quỷ. Tất cả những gì họ cho phép bạn làm là che khuất thực tế rằng tệp mã của bạn quá lớn và cần phải được cấu trúc lại.
MattDavey

Câu trả lời:


4

Enums liên quan đến lớp hoặc đôi khi cấu trúc / lớp dữ liệu thuần túy (trên định nghĩa lớp thực tế)

--- Định nghĩa lớp ---

Thành viên tư nhân

CTOR / DTOR nếu ngôn ngữ có DTOR

Tài sản công cộng

Các phương thức tiện ích (phương thức riêng tư hoặc được bảo vệ với phạm vi nhỏ)

Chức năng của lớp (Có thể được chia thành nhiều vùng tùy theo phạm vi của lớp).


17

Tiểu vùng? Lớp học của bạn có một trách nhiệm duy nhất ? .


2
Tôi đang lập trình trong WPF ngay bây giờ và một ví dụ về một số tiểu vùng tôi sẽ sử dụng là ViewModel có các thuộc tính công khai được chia thành các thuộc tính, Lệnh, Dữ liệu, v.v. Điều này giúp tôi dễ dàng tìm thấy những gì tôi tìm kiếm nhanh chóng
Rachel

2
Tại sao không sử dụng biểu ngữ bình luận lớn thay vì khu vực? // ----------ViewModel Properties---------- Bằng cách đó, bạn vẫn có thể nhìn thấy mã (hoặc thu gọn nó bằng cách phác thảo và xem các thành viên). Khu vực là để che giấu những thứ. Mã không nên bị ẩn, trừ khi nó được tự động hoặc một cái gì đó.
Kyralessa

1
@Rachel thành phần ủng hộ.
MattDavey

10

Tôi chỉ muốn xác nhận rằng bạn có nghĩa là "#regions" chứ không phải bố cục lớp nói chung.

Tôi ngạc nhiên không ai đề cập đến để tránh sử dụng các khu vực. Tôi hiểu rằng OP muốn thực hiện một cuộc thăm dò ý kiến ​​về việc đặt ra các khu vực, nhưng tôi muốn đưa ra một quan điểm khác.

Tôi tránh các khu vực. Tôi muốn xem mã tôi đang làm việc với. Nếu bạn cảm thấy khó khăn để tìm thấy những gì bạn đang tìm kiếm thì hãy sử dụng mã gấp và nhóm các cấu trúc lớp tương tự lại với nhau.

Tại sao tôi ghét các khu vực? CTRL+M,LCTRL+M,Osẽ chuyển mã gấp. Tuy nhiên, khi sụp đổ nó che giấu toàn bộ khu vực. Tôi chỉ cần thu gọn các phương thức / thuộc tính / bình luận.

Nếu có quá nhiều vùng, có thể đó là mùi mã và lớp của bạn đang làm quá nhiều việc. Jeff Atwood cung cấp một bài viết tốt về các khu vực đáng đọc.

Trích dẫn yêu thích của tôi trên #regions:

Không, tôi sẽ không sử dụng #regions. Và không, tôi KHÔNG NEGOTIATE VỚI TERRORIST. Câm miệng.

- Jeff Atwood

Điều đó đang được nói, tôi biết nhiều lập trình viên khăng khăng sử dụng chúng. Câu hỏi này là một chủ quan. Tôi chỉ nghĩ rằng tôi sẽ cung cấp một sự thay thế.


1
Đây là một macro để thu gọn các định nghĩa nhưng mở rộng các vùng, trong trường hợp bạn bị mắc kẹt khi làm việc với những người say mê các vùng: stackoverflow.com/questions/523220/awclaw-visual-studio-macros/. Nó hoạt động tốt trừ khi bạn làm việc với những người thực sự bị bệnh, những người đưa các khu vực vào trong các phương pháp .
Kyralessa

Một macro rất hữu ích! Tôi không chắc tại sao họ không xây dựng nó thành phòng thu trực quan, không hơn không kém, cảm ơn bạn.
snmcdonald

Ông chủ của tôi yêu khu vực, nới lỏng chúng. Ông cũng yêu thích các lớp học bên trong tư nhân và phương pháp lớn. Mã của chúng tôi có một lớp với khoảng một chục vùng chia nó, 3 lớp bên trong và một số phương thức lâu đến mức chúng có một tá vùng cấp cao nhất bên trong chúng, với các vùng con bên trong chúng.
CodexArcanum

4

Nó thay đổi từ ngôn ngữ để ngôn ngữ. Vì tôi là một lập trình viên Delphi, tôi có xu hướng tuân theo quy ước chuẩn Delphi, trông giống như sau:

type
  TMyClass = class(TBaseClass)
  private
    private fields
    private methods
  protected
    protected fields
    protected methods
    protected properties
  public
    constructor(s)
    destructor
    public methods
    public properties
  end;

Tôi thấy đó là một cách tốt để tổ chức thông tin dễ đọc và dễ hiểu.


3
Tôi thấy khá tuyệt vời khi cả tư nhân, được bảo vệ, công khai và xuất bản đều được sắp xếp theo thứ tự abc và đóng gói và tất cả đều bắt đầu bằng P!
Peter Turner

thú vị, tôi không. Tôi luôn thấy rằng việc liệt kê publicđầu tiên là tự nhiên hơn , vì hầu hết người dùng chỉ quan tâm đến publiccông cụ.
Matthieu M.

Tôi luôn thấy quy ước này là một ý tưởng thực sự ngớ ngẩn. Khả năng hiển thị phải làm gì với chức năng? Trong mọi trường hợp, tôi luôn sử dụng Giao diện để xác định chức năng công cộng, nhưng đã triển khai Giao diện như được bảo vệ trên lớp. Các mục duy nhất tôi sẽ liên tục nhóm là các phương thức và thuộc tính được công bố cho các thành phần và nếu không, tôi luôn nhóm theo Giao diện và kế thừa, sử dụng nhiều từ khóa hiển thị khi cần. Những mục duy nhất cho việc triển khai lớp (Tức là: không ghi đè) nên thực sự được liệt kê đầu tiên.
S.Robins

3

Tôi có xu hướng đặt chúng ra theo cách sau:

Public fields (usually static constants)
Constructors
Public methods
Private methods
Private fields

Không sử dụng một ngôn ngữ sử dụng Propertiesvì vậy đó là lý do tại sao những ngôn ngữ đó không được đặt ra. Tôi đặt các phương thức và trường riêng ở dưới cùng vì nếu có ai đó đang sử dụng tệp này trong mã của họ, họ chỉ cần quan tâm đến API, đó là công cụ công khai. Và tất cả các trình soạn thảo văn bản mà tôi biết và thậm chí cả IDE đều đặt con trỏ ở trên cùng khi mở tệp.


+1 để đặt các trường riêng ở dưới cùng. Tôi nhóm các phương thức công khai theo giao diện mà chúng triển khai và đặt các phương thức không triển khai bất kỳ giao diện nào lên trên cùng, ngay sau các hàm tạo / hàm hủy.
Sjoerd

2

Đó là một cuộc gọi phán xét cho tôi. Tôi sử dụng các vùng khi chúng cần thiết cho khả năng đọc.

Tôi cũng sử dụng một màu khác trong bảng màu Visual Studio của mình (hiện tại là màu đỏ sẫm) để làm cho chúng nổi bật so với phần còn lại của mã.


Một ví dụ về nơi tôi có thể sử dụng #region: Nếu tôi viết phương thức thử nghiệm cho một thử nghiệm đơn vị yêu cầu một đoạn mã XML nhiều dòng, chuỗi XML sẽ phá vỡ vết lõm thông thường (vì nó bắt đầu dọc theo lề trái của cửa sổ mã. Để che giấu sự xấu xí, tôi sẽ bọc nó trong một #region, để tôi có thể thu gọn nó.


2

Cuốn sách Clean Code của Bob Martin dành toàn bộ chương thứ 5 để định dạng. Có một vài điểm chính mà tôi cảm thấy tóm tắt nó một cách độc đáo.

  • Hầu hết các nỗ lực để nhóm các biến và phương thức theo mức độ hiển thị và độ sạch Không có nhiều ý nghĩa và khiến bạn phải điều hướng xung quanh mã rất nhiều.
  • Giữ các phương thức gọi nhau theo chiều dọc sẽ giảm lượng điều hướng bạn cần thực hiện và giúp tìm đồ dễ dàng hơn.
  • Chuyến tàu tư tưởng của bạn sẽ không bị phá vỡ nếu bạn phải dừng lại và nghĩ rằng "đoạn mã này thuộc về vùng nào?" cứ sau vài phút
  • Các biến sơ thẩm thường nên có ít và có khả năng được sử dụng ở mọi nơi, do đó chúng thuộc về đầu của lớp nơi chúng sẽ dễ dàng xác định vị trí nhất. Các biến và khai báo sẽ chỉ được sử dụng bởi một phương thức cần tồn tại bên trong phương thức đó. Nếu chỉ được sử dụng bởi một vài phương thức, thì chúng nên được đóng theo chiều dọc nhưng trên một vài phương thức đang sử dụng chúng.

Giữ mã của bạn được sắp xếp với các yếu tố thường tương tác theo chiều dọc gần nhau sẽ loại bỏ hiệu quả mọi nhu cầu tạo các vùng cụ thể. Nếu mã của bạn quá dài đến nỗi nó yêu cầu các vùng ẩn rất nhiều mã, thì có lẽ đó là mùi mã cho biết rằng lớp đang cố gắng làm quá nhiều. Có lẽ một số chức năng có thể được chuyển ra một lớp tiện ích hoặc được đẩy lên tổ tiên.

Nếu bạn cần "ẩn" mã bởi vì nó quá dài hoặc quá "xấu xí", thì có lẽ bạn đã gặp phải vấn đề lớn hơn là lo lắng về việc có nên sử dụng các vùng hay không. Cá nhân tôi không bao giờ cần sử dụng chúng, và khi làm việc với mã của người khác, tôi thấy tôi luôn cần phải mở tất cả chúng ra, vậy tại sao phải bận tâm?


1
+1 - Tôi ngạc nhiên rằng điều này đã không được đề cập nổi bật hơn. Nguyên tắc gắn kết cũng áp dụng cho cách bạn đặt mã ra và nhóm theo công cụ sửa đổi truy cập là (thường xuyên hơn là không) phản tác dụng.
Daniel B

0

Tôi hiện đang bố trí các lớp như thế này:

class types
constructors
destructor
accessors
methods
properties (where properties are present in the language)
member variables

và sau đó tiền tố mức truy cập cho mỗi khai báo (sắp xếp, đôi khi nhóm theo quyền truy cập). Tôi đã từng thực hiện việc phân nhóm cấp cao nhất bằng cách truy cập, nhưng tại một thời điểm nào đó, tôi không biết khi nào, nó không hoạt động tốt như ở trên. Ví dụ: trong C ++ / CLI (hiện tại tôi buộc phải sử dụng :-() bạn có thể thực hiện việc này, điều này làm rối tung việc phân nhóm theo truy cập:

public: property int SomeProperty
{
private: void set (int value) { ... }
public: int get () { ... }
}

"Thành viên" ở phía dưới là gì? Đối với tôi đó là một thuật ngữ hấp dẫn cho tất cả các phần của một lớp.
Mason Wheeler

@Mason: nên là "biến thành viên" để tránh nhầm lẫn.
Skizz

Tôi thực sự không nhận được nhóm các loại như thế. Sự khác biệt giữa một phương pháp và một tài sản thực sự là gì? Tôi chưa bao giờ đi tìm các thuộc tính của một lớp, tuy nhiên tôi sẽ tìm mã liên quan đến logic, cho dù chúng là thuộc tính, phương thức, bất cứ thứ gì.
Ed S.

0

Câu trả lời ngoài lề: Tôi không, ít nhất là khi nói đến C #. Giữa Visual Studio và R # tôi có thể điều hướng một cách kỳ diệu đến bất kỳ thành viên hoặc triển khai nào để không bị ám ảnh về nội dung này; chỉ cần bắt đầu nhập nơi con trỏ là.


0

Giống như Wyatt và một vài câu trả lời khác, tôi cũng thường tránh sử dụng các vùng. Khu vực có một mục đích; để ẩn mã bạn không muốn phải xem. Nếu bạn có rất nhiều mã trong một lớp mà bạn không muốn xem, và do đó bạn cần rất nhiều vùng để cho phép bạn thu gọn mã đã nói, thì có lẽ bạn có quá nhiều mã trong lớp. ReSharper không tôn trọng các khu vực khi quyết định nơi đặt mã mới, trừ khi nó tạo ra khu vực (mà nó thực hiện cho việc triển khai giao diện).

Việc sử dụng các vùng mà tôi thấy chấp nhận được là ẩn mã "xấu không thể tránh khỏi"; mã liên quan đến các chi tiết triển khai cụ thể không thể được kiến ​​trúc nội bộ theo các tiêu chuẩn hiện hành. Đây thường là mã tiên tiến, bí truyền thường không bị nhầm lẫn bởi các lập trình viên cơ sở trung bình một khi đã viết. Đây là những thứ như:

  • Một số triển khai giao diện tích hợp nhất định (IDis Dùng một lần, IConvertible, đôi khi IEnumerable hoặc IComparable khi chúng yêu cầu triển khai chung và không chung)
  • P / Gọi ra bên ngoài và các cấu trúc liên quan.
  • Hoàn thiện / hủy bỏ (thường đi với IDis Dùng)
  • Móc vào bộ nhớ / con trỏ / mã "không an toàn" không được quản lý.
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.