2010-02-08 40 views
6

Tôi có câu hỏi về phong cách Java. Tôi đã lập trình Java trong nhiều năm, nhưng chủ yếu cho mục đích của riêng tôi, nơi mà tôi không phải lo lắng nhiều về phong cách, nhưng tôi đã không có một công việc mà tôi phải sử dụng nó một cách chuyên nghiệp. Tôi hỏi vì tôi sắp có người thực sự đi qua mã của tôi lần đầu tiên và tôi muốn trông giống như tôi biết những gì tôi đang làm. Heh.Câu hỏi về kiểu getter/setter Java

Tôi đang phát triển thư viện mà những người khác sẽ sử dụng tại nơi làm việc của tôi. Cách mà mã khác sẽ sử dụng thư viện của tôi về cơ bản là để khởi tạo lớp chính và có thể gọi một hoặc hai phương thức trong đó. Họ sẽ không phải sử dụng bất kỳ cấu trúc dữ liệu nào của tôi, hoặc bất kỳ lớp nào tôi sử dụng trong nền để hoàn thành công việc. Tôi có thể sẽ là người chính duy trì thư viện này, nhưng những người khác có lẽ sẽ xem xét mã này một lần trong một thời gian. Vì vậy, khi tôi đã viết thư viện này, tôi chỉ sử dụng mức truy cập không có trình sửa đổi mặc định cho hầu hết các trường của tôi, và thậm chí đã đi xa đến mức có các lớp khác đôi khi đọc và có thể ghi trực tiếp từ các trường đó lên. Vì đây là trong gói của tôi, điều này dường như là một cách tốt để làm mọi thứ, cho rằng các trường đó sẽ không hiển thị từ bên ngoài gói, và dường như không cần thiết để làm cho mọi thứ riêng tư và cung cấp getters và setters. Không ai ngoài tôi sẽ viết mã bên trong gói của tôi, đây là nguồn đóng, v.v.

Câu hỏi của tôi là: đây có phải là kiểu xấu đối với các lập trình viên Java khác không? Tôi có nên cung cấp getters và setters ngay cả khi tôi biết chính xác những gì sẽ nhận được và thiết lập các lĩnh vực của tôi và tôi không lo lắng về người khác viết cái gì đó sẽ phá vỡ mã của tôi?

Trả lời

1

Tôi sẽ rất lo lắng khi xem xét mã với bất kỳ điều gì trừ các trường riêng tư, ngoại trừ trường có thể được bảo vệ vì lợi ích của lớp con. Nó sẽ không làm cho bạn trông tốt. Chắc chắn, tôi nghĩ từ điểm thuận lợi của một chuyên gia Java, bạn có thể biện minh cho độ lệch từ phong cách, nhưng vì đây là công việc chuyên nghiệp đầu tiên của bạn bằng cách sử dụng Java, bạn không thực sự ở vị trí đó.

Vì vậy, để trả lời câu hỏi của bạn trực tiếp: "Đây có phải là kiểu trông xấu không?" Nó sẽ được thôi.

Quyết định của bạn có hợp lý không? Chỉ khi bạn thực sự tự tin rằng mã này sẽ không đi đâu cả. Trong một cửa hàng điển hình, có thể có cơ hội để tái sử dụng mã, yếu tố điều vào các lớp tiện ích, vv Mã này sẽ không phải là một ứng cử viên mà không có thay đổi đáng kể. Một số thay đổi có thể được tự động hóa với IDE, và về cơ bản là rủi ro thấp, nhưng nếu thư viện của bạn ở điểm ổn định, được kiểm tra và sử dụng trong sản xuất, đóng gói sau này sẽ bị coi là rủi ro lớn hơn mức cần thiết.

+0

Cảm ơn, câu trả lời trực tiếp là những gì tôi đang tìm kiếm. Có rất nhiều lý do thực sự tốt để sử dụng getters và setters được liệt kê trong câu trả lời khác. Tôi đã có lý do riêng của tôi để phá vỡ đóng gói và muốn biết nếu điều này sẽ được một cái gì đó khác Java lập trình viên thực sự sẽ quan tâm. – jsn

1

Vì bạn là người duy nhất viết mã trong gói/thư viện nguồn đóng của mình, tôi không nghĩ bạn nên lo lắng quá nhiều về phong cách - chỉ cần làm những gì phù hợp nhất với bạn.

Tuy nhiên, đối với tôi, tôi cố gắng tránh truy cập trực tiếp các trường vì nó có thể khiến mã khó duy trì và đọc hơn - ngay cả khi tôi là người duy trì duy nhất.

2

Hầu hết các nhà phát triển Java sẽ thích xem getters và setters.

Không ai có thể là mã đang phát triển trong gói của bạn, nhưng những người khác đang tiêu thụ. Bằng cách hiển thị giao diện công khai rõ ràng, bạn có thể đảm bảo rằng người tiêu dùng bên ngoài sử dụng giao diện của bạn như bạn mong đợi.

Nếu bạn tiếp xúc với một lớp thực hiện nội bộ công khai:

  • Không thể để ngăn chặn người tiêu dùng từ việc sử dụng các lớp không thích hợp
  • kiểm soát
  • Có bị mất trên điểm vào/ra; bất kỳ lĩnh vực nào có thể được biến đổi bất cứ lúc nào
  • Tăng khớp nối giữa việc thực hiện nội bộ và người tiêu dùng bên ngoài

Duy trì getter và setter có thể mất một ít thời gian hơn, nhưng cung cấp an toàn hơn rất nhiều cộng:

  • Bạn có thể cấu trúc lại mã của mình bất cứ lúc nào, tùy ý bạn, miễn là bạn không phá vỡ API công khai của mình (getters, setters và phương thức công khai)
  • Đơn vị kiểm tra các lớp đóng gói dễ dàng hơn - bạn kiểm tra giao diện công cộng và đó là nó (chỉ yo đầu vào/đầu ra ur vào "hộp đen")
  • Thiết kế thừa kế, bố cục và giao diện đều có ý nghĩa hơn và dễ thiết kế hơn với các lớp tách rời
  • Quyết định bạn cần thêm một số xác thực vào trình biến tần trước Nó được thiết lập? Một nơi tốt là trong một setter.

Bạn có thể quyết định xem các lợi ích có đáng giá thêm thời gian hay không.

4

Tôi sẽ tuân thủ một kiểu chung (và trong trường hợp này cung cấp bộ định vị/getters). Tại sao ?

  1. đó là thực hành tốt cho khi bạn làm việc với những người khác hoặc cung cấp các thư viện cho các bên thứ 3
  2. rất nhiều các khuôn khổ Java giả ước getter/setter và tay sai để tìm kiếm những/lộ họ/thẩm vấn họ. Nếu bạn không làm điều này, thì các đối tượng Java của bạn sẽ bị đóng khỏi các khung công tác và thư viện này.
  3. nếu bạn sử dụng bộ định vị/getters, bạn có thể dễ dàng cấu trúc lại những gì đằng sau chúng. Chỉ cần sử dụng các trường trực tiếp giới hạn khả năng của bạn để làm điều này.

Thật sự hấp dẫn khi áp dụng cách tiếp cận 'chỉ dành cho tôi', nhưng có rất nhiều quy ước ở đó vì công cụ thúc đẩy chúng và/hoặc thực hành tốt vì lý do. Tôi sẽ cố gắng làm theo những điều này càng nhiều càng tốt.

+0

Đối với 2, nó cũng là một phần của đặc tả JavaBean. – Powerlord

8

Ngay cả trong gói nguồn đóng của bạn, việc đóng gói là một ý tưởng hay.

Hãy tưởng tượng rằng một nhóm lớp trong gói của bạn đang truy cập vào một thuộc tính cụ thể và bạn nhận ra rằng bạn cần lưu trữ thuộc tính đó hoặc ghi lại tất cả quyền truy cập vào đó hoặc chuyển từ giá trị được lưu trữ thực tế sang giá trị bạn tạo ra một cách nhanh chóng. Bạn sẽ phải thay đổi rất nhiều lớp học mà thực sự không cần phải thay đổi. Bạn đang phơi bày các hoạt động bên trong của một lớp với các lớp khác mà không cần phải biết về những hoạt động bên trong đó.

+0

Hoặc, bạn có thể sử dụng AOP cho tất cả các trường hợp đó. –

+0

Ngoài ra, về mặt tinh thần, dễ dàng hơn để nắm bắt một biến riêng tư trong nháy mắt. Bạn ngay lập tức biết đó là những hạn chế, không có cách nào điều này sẽ thay đổi trừ khi một cái gì đó trong NÀY FILE thay đổi nó. Từ bỏ khả năng đó để nhập một vài nhân vật có vẻ tội phạm - tôi sẽ không cảm thấy thoải mái khi làm việc với một người đã làm điều đó với mục đích - tôi sẽ phải cho rằng anh ta không nghĩ đến lập trình viên tiếp theo AT ALL khi anh ấy lập trình . –

1

Kiểu là một vấn đề về quy ước. Không có câu trả lời đúng miễn là nó phù hợp.

Tôi không phải là người hâm mộ của lạc đà, nhưng trong thế giới Java, quy tắc camelStyle tối cao và tất cả các biến thành viên phải là riêng tư.

getData(); 
setData(int i); 

Thực hiện theo các quy ước chính thức Java của Sun (ho Oracle) và bạn sẽ ổn thôi.

http://java.sun.com/docs/codeconv/

+0

+1 cho liên kết đến quy ước mã, tôi đã cần một cái gì đó như thế – jsn

0

Mặc dù nó đau đớn, mã hóa lên các thuộc tính với getter và setter là một chiến thắng lớn, nếu bạn lại sẽ tiếp tục sử dụng đối tượng của bạn trong một bối cảnh như JSP (ngôn ngữ biểu thức đặc biệt), OGNL, hoặc một ngôn ngữ mẫu khác. Nếu các đối tượng của bạn tuân theo các quy ước Bean cũ tốt thì rất nhiều thứ sẽ "hoạt động" sau này.

0

Tôi tìm thấy getters và setters là cách tốt hơn để lập trình và nó không chỉ về vấn đề quy ước mã hóa. Không ai biết tương lai, vì vậy chúng ta có thể viết một chuỗi phonenumber đơn giản ngày hôm nay nhưng ngày mai chúng ta có thể phải đặt "-" giữa mã vùng và số, trong trường hợp đó, nếu chúng ta có phương thức getPhonenumber() đã định nghĩa, chúng ta có thể làm vẻ đẹp như vậy rất dễ dàng. Vì vậy, tôi sẽ tưởng tượng, chúng tôi luôn luôn nên làm theo phong cách này của mã hóa cho khả năng mở rộng tốt hơn.

4

Tôi không nghĩ một ngôn ngữ tốt nên có bất kỳ cấp truy cập nào ngoại trừ riêng tư - tôi không chắc chắn rằng tôi thấy lợi ích.

Mặt khác, cũng phải cẩn thận về getter và setter ở tất cả - họ có rất nhiều cạm bẫy:

  • Họ có xu hướng khuyến khích thiết kế OO xấu (Bạn thường muốn hỏi đối tượng của bạn để làm một cái gì đó cho bạn, không hành động trên các thuộc tính của nó)
  • Thiết kế OO xấu này gây ra mã liên quan đến đối tượng của bạn được lan truyền xung quanh các đối tượng khác nhau và thường dẫn đến trùng lặp.
  • những người định cư làm cho đối tượng của bạn có thể thay đổi được (nếu bạn có thể tránh được điều này), thì bạn có thể thay đổi điều đó thành một đôi- -Bạn phải chạm vào mọi nơi mà nó đã được truy cập và đảm bảo nó có thể xử lý gấp đôi mà không bị tràn/gây ra lỗi, nếu bạn vừa yêu cầu đối tượng thao tác giá trị ngay từ đầu, những thay đổi duy nhất sẽ là nội bộ đối tượng của bạn
+0

Nhân tiện - Tôi không chắc tôi thấy sự khác biệt lớn giữa biến FINAL công khai và biến với getter ngoại trừ các lập trình viên có xu hướng thích "Quy tắc" và quy tắc setter/getter "" dễ hiểu và đứng sau. Về mặt kỹ thuật, có rất ít lý do để sử dụng một getter trên một lĩnh vực cuối cùng - xem xét các công cụ tái cấu trúc những ngày này, trên thực tế, tôi muốn nói rằng hoàn toàn không có lý do kỹ thuật - nhưng bạn vẫn sẽ freak ra rất nhiều lập trình viên giống như quy tắc. –

1

Tóm lại, bạn nói "Tôi hỏi vì tôi sắp có người thực sự xem mã của tôi lần đầu tiên và tôi muốn trông giống như tôi biết mình đang làm gì".Vì vậy, thay đổi mã của bạn, bởi vì nó làm cho nó trông giống như bạn không biết những gì bạn đang làm.

Thực tế là bạn đã nêu ra điều đó cho thấy rằng bạn biết rằng nó có thể trông xấu (đây là một điều tốt), và nó có. Như đã đề cập, bạn đang phá vỡ các nguyên tắc cơ bản của thiết kế OO cho tính hiệu quả. Điều này chỉ đơn giản là kết quả trong mong manh, và mã unmaintainable thường.

1

Phá vỡ đóng gói là một ý tưởng tồi. Tất cả các trường phải là riêng tư. Nếu không, lớp không thể tự bảo đảm rằng các bất biến riêng của nó được giữ lại, bởi vì một số lớp khác có thể vô tình sửa đổi các trường theo cách sai.

Có getters và setters cho tất cả các trường cũng là một ý tưởng tồi. Một trường với getter và setter gần như giống như một trường công khai - nó cho thấy các chi tiết thực hiện của lớp và tăng sự liên kết. Mã bằng cách sử dụng những getters và setters dễ dàng vi phạm nguyên tắc OO và mã trở thành thủ tục.

Mã phải được viết để mã theo dõi Tell Don't Ask. Bạn có thể thực hành nó ví dụ bằng cách thực hiện bài tập Object Calisthenics.

0

Đôi khi tôi sử dụng public final thuộc tính w/o get/setter cho các đối tượng sống ngắn chỉ mang theo một số dữ liệu (và sẽ không bao giờ làm bất cứ điều gì khác theo thiết kế).

Khi vào đó, tôi thực sự rất muốn nếu Java đã ngụ ý getter và setter tạo bằng cách sử dụng từ khóa property ...

2

tôi sẽ không quan tâm nhiều về phong cách cho mỗi gia nhập (hoặc bất kỳ loại giáo điều cho vấn đề đó), nhưng thay vào đó là sự tiện lợi trong khả năng bảo trì đi kèm với một bộ phương thức getter/setter. Nếu bạn (hoặc người khác) sau đó cần phải thay đổi hành vi liên quan đến thay đổi một trong những thuộc tính đó (ghi nhật ký các thay đổi, làm cho nó an toàn, vệ sinh đầu vào, v.v.), nhưng đã trực tiếp sửa đổi chúng trong nhiều những nơi trong mã của bạn, bạn sẽ muốn bạn sử dụng phương thức getter và setter thay thế.

+1

+1 cho khía cạnh an toàn/đồng thời của luồng –

0

Sử dụng đóng gói là một ý tưởng hay ngay cả đối với nguồn đóng như JacobM đã chỉ ra. Nhưng nếu mã của bạn đang hoạt động như thư viện cho ứng dụng khác, bạn không thể dừng ứng dụng kia truy cập vào các lớp được định nghĩa để sử dụng nội bộ. Nói cách khác, bạn không thể (?) Thực thi hạn chế mà một lớp X công cộng chỉ có thể được sử dụng bởi các lớp trong ứng dụng của tôi.

Đây là nơi tôi thích kiến ​​trúc plugin Eclipse, nơi bạn có thể nói những gói nào trong plugin của tôi có thể phụ thuộc vào quyền truy cập trong thời gian chạy. JSR 277 nhằm đưa loại tính năng mô-đun này vào JDK nhưng nó đã chết rồi. Đọc thêm về nó tại đây, http://neilbartlett.name/blog/2008/12/08/hope-fear-and-project-jigsaw/

Bây giờ tùy chọn duy nhất có vẻ là OSGi.