Sử dụng các lớp công cộng lồng nhau để tổ chức các hằng số


21

Tôi đang làm việc trên một ứng dụng có nhiều hằng số. Trong lần xem xét mã cuối cùng, các hằng số quá phân tán và tất cả nên được tổ chức thành một tệp hằng "chính". Sự bất đồng là về cách tổ chức chúng. Đa số cảm thấy rằng sử dụng tên hằng phải đủ tốt, nhưng điều này sẽ dẫn đến mã trông như thế này:

public static final String CREDITCARD_ACTION_SUBMITDATA = "6767";
public static final String CREDITCARD_UIFIELDID_CARDHOLDER_NAME = "3959854";
public static final String CREDITCARD_UIFIELDID_EXPIRY_MONTH = "3524";
public static final String CREDITCARD_UIFIELDID_ACCOUNT_ID = "3524";
...
public static final String BANKPAYMENT_UIFIELDID_ACCOUNT_ID = "9987";

Tôi thấy loại quy ước đặt tên này là cồng kềnh. Tôi nghĩ rằng có thể dễ dàng hơn để sử dụng lớp lồng nhau công khai và có một cái gì đó như thế này:

public class IntegrationSystemConstants
{
    public class CreditCard
    {
        public static final String UI_EXPIRY_MONTH = "3524";
        public static final String UI_ACCOUNT_ID = "3524";
        ...
    }
    public class BankAccount
    {
        public static final String UI_ACCOUNT_ID = "9987";
        ...
    }
}

Ý tưởng này không được đón nhận vì nó "quá phức tạp" (Tôi không nhận được nhiều chi tiết về lý do tại sao điều này có thể quá phức tạp). Tôi nghĩ rằng điều này tạo ra sự phân chia tốt hơn giữa các nhóm hằng số liên quan và tự động hoàn thành giúp dễ dàng tìm thấy chúng hơn. Tôi chưa bao giờ thấy điều này được thực hiện, vì vậy tôi tự hỏi liệu đây có phải là một thực tiễn được chấp nhận hoặc nếu có lý do tốt hơn mà nó không nên được thực hiện.


1
Tôi thích ý tưởng hơn. Tôi thấy mình đã làm một cái gì đó tương tự trong C ++ khi tôi muốn phạm vi và hành vi giống như kiểu enum của C #, nhưng với các giá trị có ý nghĩa (tôi nghĩ ý tưởng nảy sinh vì tôi đã quen với việc sử dụng các lớp tình huống thay cho enum trong Scala). Cấp, đây là một dự án cá nhân cho vui, và không phải là một nỗ lực nhóm.
KChaloux

Câu trả lời:


13

Tôi không đồng ý với một trong hai đề xuất.

Các hằng số phải ở trong các lớp thích hợp của chúng , không phải trong một lớp không đổi trong cả hai dạng được đề xuất.

Không nên có các lớp / giao diện chỉ hằng.

Một lớp CreditCard(không phải là một lớp bên trong) nên tồn tại. Lớp / giao diện này có các phương thức liên quan đến thẻ tín dụng cũng như các hằng số UI_EXPIRY_MONTHUI_ACCOUNT_ID.

Cần tồn tại một lớp / giao diện BankAccount(không phải là một lớp bên trong). Lớp / giao diện này có các phương thức liên quan đến tài khoản ngân hàng cũng như hằng số UI_ACCOUNT_ID.

Ví dụ, trong API Java, mọi lớp / giao diện đều có các hằng số của nó. Chúng không nằm trong một lớp / giao diện Hằng với hàng trăm hằng số, được nhóm thành các lớp bên trong hoặc không.

Ví dụ: các hằng số thích hợp cho các tập kết quả nằm trong giao diện ResultSet:

static int  CLOSE_CURSORS_AT_COMMIT 
static int  CONCUR_READ_ONLY 
static int  CONCUR_UPDATABLE 
static int  FETCH_FORWARD 
static int  FETCH_REVERSE 
static int  FETCH_UNKNOWN 
static int  HOLD_CURSORS_OVER_COMMIT 
static int  TYPE_FORWARD_ONLY 
static int  TYPE_SCROLL_INSENSITIVE 
static int  TYPE_SCROLL_SENSITIVE 

Giao diện này có chữ ký phương thức liên quan đến tập kết quả và các lớp triển khai thực hiện hành vi đó. Họ không chỉ là những người nắm giữ liên tục.

Các hằng số thích hợp với các hành động UI nằm trong giao diện javax.swing.Action:

static String   ACCELERATOR_KEY 
static String   ACTION_COMMAND_KEY 
static String   DEFAULT 
static String   LONG_DESCRIPTION 
static String   MNEMONIC_KEY 
static String   NAME 
static String   SHORT_DESCRIPTION 
static String   SMALL_ICON 

Các lớp triển khai có hành vi liên quan đến các hành động UI, chúng không chỉ là các chủ sở hữu liên tục.

Tôi biết ít nhất một giao diện "hằng" ( SwingConstantskhông có phương thức nhưng nó không có hàng trăm hằng số, chỉ một vài và tất cả chúng đều liên quan đến hướng và vị trí của các thành phần UI:

static int  BOTTOM 
static int  CENTER 
static int  EAST 
static int  HORIZONTAL 
static int  LEADING 
static int  LEFT 
static int  NEXT 
static int  NORTH 
static int  NORTH_EAST 
static int  NORTH_WEST 
static int  PREVIOUS 
static int  RIGHT 
static int  SOUTH 
static int  SOUTH_EAST 
static int  SOUTH_WEST 
static int  TOP 
static int  TRAILING 
static int  VERTICAL 
static int  WEST 

Tôi nghĩ rằng chỉ các lớp không phải là thiết kế OO tốt.


1
Mặc dù tôi đồng ý rằng hầu hết các lớp chỉ là các dấu hiệu của thiết kế xấu, có những cách sử dụng hợp pháp. Chẳng hạn, hằng số không luôn luôn "thuộc về" một lớp cụ thể. Chìa khóa cho các tính năng bổ sung Intent trong lập trình Android là một ví dụ cụ thể như vậy.
curioustechizen

1
+1, nhưng các hằng số UI có lẽ không nên có trong các mô hình kinh doanh như BankAccount. Chúng thuộc một số lớp UI.
kevin cline

10

nó xuất hiện rằng các hằng số quá phân tán và tất cả nên được tổ chức thành một tệp hằng số "chính".

Đây là giải pháp sai 100% cho vấn đề hằng số "khó tìm". Đó là một lỗi cơ bản (không may là tất cả quá phổ biến bởi các lập trình viên) để nhóm các thứ theo các tiêu chí kỹ thuật như là hằng số, enum hoặc giao diện.

Ngoại trừ kiến ​​trúc lớp, mọi thứ nên được nhóm theo miền của chúng và các hằng số nhiều hơn vì chúng là các phần tử mức rất thấp. Các hằng số phải là một phần của các lớp hoặc giao diện sử dụng chúng như một phần của API của chúng. Nếu bạn không thể tìm thấy một nơi tự nhiên để họ sống, bạn cần dọn sạch thiết kế API của mình.

Ngoài ra, một tệp hằng lớn duy nhất giết chết tốc độ phát triển trong Java vì các hằng số được đưa vào các lớp sử dụng chúng trong thời gian biên dịch, do đó, bất kỳ thay đổi nào cũng buộc phải biên dịch lại tất cả các tệp đó và tất cả phụ thuộc vào chúng. Nếu bạn có một tệp với các hằng số được sử dụng ở mọi nơi, bạn sẽ mất phần lớn lợi ích của việc biên dịch gia tăng: xem Eclipse khóa trong 15 phút khi nó biên dịch lại toàn bộ dự án của bạn cho mỗi thay đổi đối với tệp đó. Và vì tệp đó chứa tất cả các hằng được sử dụng ở bất cứ đâu, bạn sẽ thay đổi nó khá thường xuyên. Vâng, tôi đang nói từ kinh nghiệm cá nhân.


Tôi đã không nhận thức được tác động tiềm tàng đối với môi trường phát triển và tôi đoán cách tiếp cận lớp lồng nhau sẽ không giúp ích nhiều cho điều đó, phải không?
Thất vọngWithFormsDesigner

1
@FrustratedWithFormsDesigner: Nó phụ thuộc vào mức độ nỗ lực của cơ chế biên dịch gia tăng dành cho việc phụ thuộc vào mô hình hóa.
Michael Borgwardt

9

Bạn đúng rồi. Đề xuất của bạn cho phép lập trình viên import static Constants.BankAccount.*và loại bỏ vô số lần lặp lại 'BANKACCOUNT_'. Sự kết hợp là một sự thay thế nghèo nàn cho phạm vi thực tế. Điều đó nói rằng, tôi không có nhiều hy vọng để bạn thay đổi văn hóa đội bóng. Họ có một quan niệm về các thực hành đúng đắn và không có khả năng thay đổi ngay cả khi bạn chỉ cho họ 100 chuyên gia nói rằng họ sai.

Tôi cũng tự hỏi tại sao bạn chỉ có một tệp 'Hằng số'. Đây là thực tế rất xấu, trừ khi các hằng số này đều có liên quan bằng cách nào đó và rất ổn định. Thông thường hơn, nó trở thành một loại bồn rửa nhà bếp thay đổi liên tục và phụ thuộc vào mọi thứ.


Hiện tại chúng tôi có một tệp Hằng chứa hầu hết các hằng số ID trường UI và một vài tệp hằng khác dành riêng cho tiểu dự án. Nhưng bây giờ, các hằng số cụ thể của tiểu dự án đang cần được sử dụng bởi các tiểu dự án liên quan khác, vì vậy đó là ý tưởng thúc đẩy tất cả chúng thành một tệp hằng "chủ". Điều này tốt hơn bây giờ bởi vì đôi khi tôi thậm chí không biết tệp hằng nào để giới thiệu giá trị và ai đó đã tạo một bản sao của hằng số vì họ không thể tìm thấy nó trong tệp hằng số của tiểu dự án khác.
Thất vọngWithFormsDesigner

8
Một lớp hằng số liên tục thay đổi ... có một cái gì đó trong đó, nếu bạn đào đủ mạnh.
KChaloux

2
@FrustratedWithFormsDesigner: ID trường UI? Không biết tìm giá trị ở đâu? Âm thanh như một đống WTF khổng lồ. Bạn có sự thông cảm của tôi.
kevin cline

6

Cả hai phương pháp đều hoạt động, và đó là điều quan trọng vào cuối ngày.

Điều đó nói rằng, cách tiếp cận của bạn đủ phổ biến để được coi là một mẫu, hoặc chính xác hơn là một cải tiến đủ tốt so với mẫu chống giao diện liên tục . Tôi không thấy những gì phức tạp về nó, nhưng đó là một cuộc thảo luận bạn nên có với nhóm của mình.


Đối với một danh sách các hằng số đủ dài, tôi thậm chí còn thích các giao diện không đổi hơn là có tất cả chúng trong cùng một lớp. Thật nguy hiểm khi có thể chọn sai từ tự động hoàn thành. Tất nhiên, điều đó phụ thuộc vào thời gian đủ dài :)
Goran Jovic

1
@GoranJovic Vâng, mọi mô hình chống đều hữu ích theo một cách nào đó (hoặc ít nhất là thuận tiện), nó sẽ không trở thành một mô hình nếu không.
yannis

1

Một trong những thách thức với danh sách dài các hằng số là tìm hằng số "chính xác" sẽ được sử dụng. Lúc nào cũng vậy, ai đó giải quyết một hằng số ở cuối dòng thay vì thêm nó vào nhóm mà nó thuộc về.

Điều này dẫn đến một điểm khác để thảo luận với nhóm của bạn - đã có một phân loại thực tế của các hằng số thông qua tên của chúng. Vì vậy, nó thực sự không nên là một sự thay đổi lớn đối với họ từ trạng thái hiện tại sang những gì bạn đang đề xuất. Sử dụng tự động hoàn thành giúp việc tra cứu liên tục trở nên dễ dàng hơn.

Nếu bất cứ điều gì, đề xuất của bạn giúp ngăn cản sử dụng hằng số "sai" mặc dù nó có thể phù hợp với một tình huống cụ thể. Bằng cách gói các hằng số trong một lớp đại diện, nó sẽ khuyến khích các nhà phát triển suy nghĩ xem họ có nên sử dụng nó không. Ví dụ, nếu tôi CreditCard.SomeConstantsử dụng chung, tôi thực sự nên tự hỏi tại sao không có General.SomeConstanttình huống đó thay vào đó.

Tôi đã tham gia vào các dự án với số lượng hằng số khổng lồ và tôi muốn có phương pháp mà bạn đề xuất. Nó sạch hơn, trực tiếp hơn, và nó giúp tránh việc sử dụng vô ý.


1

Thỉnh thoảng tôi làm điều này (trong C #), đặc biệt nếu tôi cần lập trình chống lại / phân tích cấu trúc XML nổi tiếng và cố định hoặc một cái gì đó tương tự lồng và chuỗi nặng ... ví dụ như trình phân tích cú pháp khối cấu hình tùy chỉnh.

Tôi xây dựng cấu trúc lớp lồng nhau phù hợp với cấu trúc phân cấp của XML w / tên lớp tương ứng với các phần tử chứa thuộc tính const Element "ElementName" và thuộc tính tương tự tương ứng với mỗi Thuộc tính (nếu có).

Nó làm cho nó rất dễ dàng để lập trình chống lại Xml tương ứng.

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.