Các trường so với đối số phương thức [đã đóng]


9

Tôi mới bắt đầu viết một số lớp mới và tôi nhận thấy rằng tôi đã thêm rất nhiều đối số phương thức không thực sự cần thiết. Đây là theo thói quen để tránh có trạng thái trong các lớp dành riêng cho một số cuộc gọi phương thức, thay vì là cấu hình chung hoặc các phụ thuộc của lớp.

Làm như vậy có nghĩa là rất nhiều phương thức không thể có đối số kết thúc bằng một, hai hoặc ba.

Tôi muốn nghe ý kiến ​​của bạn về những gì bạn nghĩ về sự đánh đổi này, và cách bạn quyết định nên tiếp cận phương pháp nào trong tình huống nào?

Vì mã thường dễ hiểu hơn tiếng Anh khi mô tả mã, tôi đã tạo ra một ý chính nhỏ có cả hai biến thể trong đó: https://gist.github.com/JeroenDeDauw/6525656


Các đối số chỉ được sử dụng như một biến cục bộ (không phải toàn cầu trong suốt vòng đời của đối tượng) chỉ nên ở trong phạm vi miễn là nó có ý nghĩa ... Tôi thấy rất khó chịu khi các nhà phát triển lưu trữ trạng thái phi thể hiện như trạng thái cá thể vì nó thuận tiện ... chỉ là ý kiến ​​của tôi mặc dù. Làm cho nó khó khăn để xem dòng thực thi là như thế nào.
Tối đa

Sử dụng các tham số và để cho lớp quan tâm xem liệu nó có thể phải thay đổi trạng thái trong khi thực hiện một phương thức hay không, liên kết chặt chẽ với nguyên tắc "nói không hỏi" . Hãy nhớ rằng Tell đừng hỏi không có nghĩa là bạn không thể truy vấn một đối tượng về trạng thái của nó ( phích cắm trắng trợn )
Marjan Venema

Câu trả lời:


2

Vì phương thức hiển thị bên ngoài duy nhất của ví dụ của bạn là updateTable, tôi nghĩ sử dụng các trường thay vì tham số phương thức là tốt.

Nếu đây là một phần của một lớp chung hơn (ví dụ TableTools), tôi sẽ di chuyển các phương thức của trình trợ giúp cần trạng thái vào một lớp bên trong ẩn.

Ví dụ mã giả:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

Bằng cách đó, bạn tránh các trường chỉ được sử dụng bởi một phương thức công khai. Ngoài ra, mã này an toàn theo luồng theo nghĩa là mọi lệnh gọi updateTable đều sử dụng bản sao TableUpdater của riêng nó và do đó, các biến đối tượng của TableUpdater.


7

Việc sử dụng các trường đồng nghĩa với khả năng đa luồng có sẵn cho các phương thức sử dụng các trường đó.

Sử dụng các trường như thế chỉ tốt hơn một chút so với sử dụng toàn cầu theo quan điểm có thể sử dụng lại và bảo trì, điểm mấu chốt ở đây là các thiết lập phức tạp cần tài liệu cẩn thận và cập nhật về phương pháp nào sử dụng và / hoặc ghi lại trường nào; một cái gì đó bạn không cần phải làm khi sử dụng đối số.


Đa luồng không liên quan đến trường hợp sử dụng của tôi, vì nó là trong PHP. Tôi đồng ý rằng cách tiếp cận này là xấu nếu cách các trường được sử dụng không tầm thường. Trong trường hợp này, chúng chỉ được ghi vào (và luôn được ghi vào) từ phương thức công khai duy nhất. Tôi không lường trước được điều này gây ra vấn đề. Đối với các lĩnh vực như thế này chỉ tốt hơn một chút so với toàn cầu, tôi khá không chắc ý của bạn là gì. Bạn có thể xây dựng?
Jeroen De Dauw

7

Theo cách nói của giáo dân:

  • các phương thức nên có càng ít đối số càng tốt (Mã sạch của Martin)
  • một trong những tính năng của các đối tượng là chúng có thể (và nên) có trạng thái
  • các phương thức không tĩnh không hoạt động trên trạng thái của đối tượng, tức là nhận mọi thứ dưới dạng tham số, không gắn kết
  • các phương thức không gắn kết cũng có thể được tạo thành tĩnh và được nhóm trong một lớp tiện ích

Một lần nữa, theo quan điểm khiêm tốn của tôi, các phương thức không gắn kết thuộc về một lớp tiện ích và không thuộc về một lớp có tên miền.


1

Đừng sử dụng các trường trong trường hợp hiện tại! Hai "luồng" sử dụng đối tượng cùng một lúc sẽ gây nhầm lẫn nghiêm trọng cho nhau. Chúng không phải là các chủ đề thực, riêng biệt (do đó là trích dẫn). Nếu bạn thiết lập đối tượng cho một bảng, sau đó gọi một phương thức sử dụng nó cho một bảng khác, sau đó thử sử dụng thiết lập ban đầu, bạn có một vấn đề. Gắn bó với các thông số cho thời điểm này.

Những gì bạn muốn làm ở đây là tạo một lớp cập nhật mới chỉ được sử dụng trong một trường hợp. Lớp ban đầu có thể có một phương thức để tạo một cá thể bất cứ khi nào cần. Lớp mới sẽ có các lĩnh vực. Bạn có tốt nhất của cả hai thế giới. Đôi khi đơn giản hơn là chỉ cần gắn bó với các tham số, nhưng trong ví dụ của bạn, bạn đã đến nơi một lớp riêng biệt sẽ tốt hơn.


0

Tôi nghĩ rằng việc lựa chọn nên theo tình hình thực tế, như bạn thấy. Nếu một mục thuộc về một thể hiện, nó sẽ được xem như là trường của nó. Nếu mục bên ngoài đối tượng, nó sẽ được truyền dưới dạng tham số phương thức.

Chúng ta nên được hướng dẫn trong trường hợp này không phải bởi tính hiệu quả (dù sao sự khác biệt là không đáng kể), hoặc (Chúa tiết kiệm!) Dễ dàng gõ, nhưng bởi tính dễ hiểu và tự nhiên của mã.


0

Theo ý kiến ​​của tôi, nếu bạn đang viết mã làm một cái gì đó cho một cái gì đó thì nó nên lấy các tham số xác định những gì nó nên làm và tên của nó sẽ xác định càng nhiều càng tốt những gì nó làm với nó.

Nếu bạn đang viết mã đóng gói một hành động được thực hiện trên một cái gì đó thì bạn nên bọc những thứ mà nó nên được thực hiện trong một đối tượng và chuyển chúng cho thứ bạn làm điều gì đó .

Hành động này sau đó trở thành một loại mô tả meta của các cuộc gọi đến các phương thức đầu tiên mà sau đó bạn có thể thực hiện vào một ngày sau đó bằng cách xếp hàng hoặc thậm chí quyết định không thực hiện nó vì một số lý do.

Vì vậy, câu hỏi của bạn chuyển thành là một hành động hoặc một chức năng ? Một hành động có thể bị hoãn hoặc hủy bỏ và do đó sẽ gói gọn những hành động mà nó hành động. Một chức năng xảy ra ngay lập tức vì vậy không cần bảo toàn các tham số hàng đầu của nó.

Bạn có thể hoàn tácHành động nhưng không phải là Chức nă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.