cách gọi chức năng này là một thực hành xấu?


10

Tôi có đoạn mã sau:

public void moveCameraTo(Location location){
    moveCameraTo(location.getLatitude(), location.getLongitude());
}

public void moveCameraTo(double latitude, double longitude){
    LatLng latLng = new LatLng(latitude, longitude);
    moveCameraTo(latLng);
}

public void moveCameraTo(LatLng latLng){
    GoogleMap googleMap =  getGoogleMap();
    cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, INITIAL_MAP_ZOOM_LEVEL);
    googleMap.moveCamera(cameraUpdate);
}

Tôi nghĩ rằng với cách này, tôi loại bỏ trách nhiệm biết những gì LatLngtrong một lớp khác, ví dụ.

Và bạn không cần chuẩn bị dữ liệu trước khi gọi hàm.

Bạn nghĩ sao?

Liệu cách tiếp cận này có một tên? Nó thực sự là một thực hành xấu?


2
Tôi nghĩ rằng bạn chỉ đang xử lý Đóng gói bằng cách sử dụng Phương thức quá tải tích hợp sẵn của ngôn ngữ. Nó không tốt / xấu. Chỉ cần một công cụ có thể giúp hoặc làm tổn thương mã của bạn.
bitoflogic

5
Nếu mục tiêu của bạn là che giấu LatLngkhỏi các khách hàng của Cameralớp này , thì có lẽ bạn không muốn moveCameraTo(LatLng)trở thành public.
bitoflogic

Ngoài những lời khuyên được đưa ra trong các câu trả lời, cảm giác này giống như một nơi tốt để đề cập đến YAGNI. Bạn không cần Gonna. Không xác định phương thức API trước khi có trường hợp sử dụng tốt vì ... Bạn không cần nó.
Patrick Hughes

Không có gì sai với moveCameraToLocationmoveCameraTo/ moveCameraToCoords. Chắc chắn sẽ không muốn vượt qua Địa điểm / lat / long tất cả trong cùng một tên.
bên trong

Câu trả lời:


9

Bạn đang sử dụng tính năng nạp chồng phương thức ngôn ngữ của mình để cung cấp cho người gọi các cách khác để giải quyết sự phụ thuộc của phương thức vào thông tin vị trí. Sau đó, bạn đang ủy quyền cho một phương pháp khác để giải quyết công việc cập nhật máy ảnh còn lại.

Mùi mã ở đây sẽ là nếu bạn tiếp tục mở rộng chuỗi phương thức gọi phương thức. Phương thức lấy vị trí gọi phương thức lấy kép gọi phương thức lấy latLng, cuối cùng gọi một cái gì đó biết cách cập nhật máy ảnh.

Chuỗi dài chỉ mạnh như liên kết yếu nhất của họ. Mỗi phần mở rộng của chuỗi làm tăng dấu chân của mã phải hoạt động hoặc điều này bị hỏng.

Đó là một thiết kế tốt hơn nhiều nếu mỗi phương pháp có con đường ngắn nhất có thể để giải quyết vấn đề đã được trình bày cho nó. Điều đó không có nghĩa là mỗi người phải biết cách cập nhật máy ảnh. Mỗi người nên dịch loại tham số vị trí của họ thành một loại thống nhất có thể được chuyển sang một loại nào đó biết cách cập nhật máy ảnh khi trình bày loại này.

Làm theo cách đó và bạn có thể loại bỏ một mà không phá vỡ một nửa mọi thứ khác.

Xem xét:

public void moveCameraTo(Location location){
    moveCameraTo( new LatLng(location) );
}

Điều này làm cho việc xử lý LatLngvấn đề vĩ độ và kinh độ . Chi phí là nó lan truyền kiến ​​thức LatLngxung quanh. Điều đó có vẻ đắt tiền nhưng theo kinh nghiệm của tôi, đó là một sự thay thế thích hợp hơn cho nỗi ám ảnh nguyên thủy , đó là điều tránh việc thiết lập một đối tượng tham số khiến bạn bị mắc kẹt.

Nếu Locationcó thể tái cấu trúc nhưng LatLngkhông, hãy xem xét giải quyết điều này bằng cách thêm một nhà máy vào Location:

moveCameraTo( location.ToLatLng() );

Điều này cũng độc đáo tránh nỗi ám ảnh nguyên thủy.


1
Điều đó dường như không tệ với tôi - nó thực sự chỉ là sự tiện lợi cho người tiêu dùng. Nếu điều này bị xiềng xích 10 lần hoặc nếu người tiêu dùng không thực sự cần tất cả các tùy chọn này thì tôi sẽ gọi đó là mùi mã.
mcknz

1
Nhưng đâu là sự thay thế đặt tất cả logic để chuyển đổi nhân đôi thành LagLng hoặc Location thành LagLng trong mỗi chức năng?
Tlaloc-ES

@ Tlaloc-ES tốt hơn?
candied_orange

@ Tlaloc-ES Việc "biến đổi" chỉ cần xảy ra một lần khi các nguyên thủy đang được tải vào logic miền. Nó sẽ xảy ra khi bạn giải trừ DTO. Sau đó, tất cả logic miền của bạn được truyền xung quanh LatLnghoặc Locationcác đối tượng. Bạn có thể chỉ ra mối quan hệ giữa hai người với New LatLng(Location)hoặc Location.toLatLng()nếu bạn cần đi từ người này sang người kia.
bitoflogic

1
@ Tlaloc-ES Bài đọc liên quan: FlagArgument của Martin Fowler. Đọc phần "Thực hiện rối".
Marc.2377

8

Không có gì đặc biệt sai với giải pháp của bạn.

Nhưng sở thích cá nhân của tôi sẽ là những phương pháp đó không hữu ích. Và chỉ làm phức tạp giao diện của bất kỳ đối tượng nào mà họ tham gia.

Việc void moveCameraTo(double latitude, double longitude)không thực sự đơn giản hóa mã, vì tôi thấy không có vấn đề gì chỉ đơn giản là gọi moveCameraTo(new LatLng(latitude, longitude));vào vị trí của nó. Phương pháp này cũng có mùi của nỗi ám ảnh nguyên thủy.

void moveCameraTo(Location location)thể được giải quyết tốt hơn bằng cách chứng minh Location.ToLatLng()phương pháp và gọi moveCameraTo(location.ToLatLng()).

nếu đây là C # và nếu một phương thức như vậy là thực sự cần thiết, tôi sẽ thích chúng làm phương thức mở rộng thay vì phương thức cá thể. Việc sử dụng các phương thức mở rộng sẽ trở nên thực sự rõ ràng nếu bạn thử trừu tượng hóa và kiểm tra đơn vị trường hợp này. Vì sẽ dễ dàng hơn nhiều khi chỉ giả mạo phương thức đơn lẻ thay vì nhiều lần quá tải với các chuyển đổi đơn giản.

Tôi nghĩ rằng với cách này, tôi loại bỏ trách nhiệm biết LatLng là gì trong một lớp khác chẳng hạn.

Tôi thấy không có lý do tại sao điều này sẽ là một vấn đề. Miễn là mã tham chiếu lớp của bạn có chứa void moveCameraTo(LatLng latLng), nó vẫn gián tiếp phụ thuộc vào LatLng. Ngay cả khi lớp đó không bao giờ được khởi tạo trực tiếp.

Và bạn không cần chuẩn bị dữ liệu trước khi gọi hàm.

Tôi không hiểu ý của bạn. Nếu nó có nghĩa là tạo cá thể mới hoặc chuyển đổi các lớp từ lớp này sang lớp khác, tôi thấy không có vấn đề gì với điều đó.

Nghĩ về nó, tôi cảm thấy rằng những gì tôi đang nói cũng được hỗ trợ bởi chính thiết kế API của .NET. Trong lịch sử, rất nhiều lớp .NET tuân theo cách tiếp cận của bạn là có quá nhiều quá tải với các tham số khác nhau và các chuyển đổi đơn giản bên trong. Nhưng đó là trước khi các phương thức mở rộng tồn tại. Các lớp .NET hiện đại hơn có trọng lượng nhẹ hơn trong các API của riêng chúng và nếu có bất kỳ phương thức nào có quá tải tham số, chúng được cung cấp làm phương thức mở rộng. Ví dụ cũ hơn là NLog ILogger có hàng tá quá tải để ghi vào nhật ký. So sánh điều đó với Microsoft.Extensions.Logging.ILogger mới hơn có tổng cộng 3 phương thức (và chỉ 1 nếu bạn tính chính việc đăng nhập). Nhưng có rất nhiều người trợ giúp và các tham số khác nhau như các phương pháp mở rộng .

Tôi nghĩ rằng câu trả lời này cho thấy rằng một số ngôn ngữ sẽ có các công cụ để thiết kế như thế này đẹp hơn. Tôi không biết nhiều về Java, vì vậy tôi không chắc sẽ có tương đương hay không. Nhưng ngay cả khi sử dụng các phương thức tĩnh đơn giản có thể là một lựa chọn.


Không chắc chắn tại sao nhưng tôi thấy mình root cho câu trả lời này mặc dù có một đối thủ cạnh tranh. Tôi nghĩ rằng bạn chỉ cần quản lý để làm cho điểm tốt hơn. Phản hồi duy nhất của tôi là hãy nhớ rằng không phải ai cũng xử lý vấn đề này là trên .NET. +1
candied_orange

@candied_orange Phải. Bây giờ tôi nhìn tốt hơn câu hỏi của OP, nó trông giống Java hơn C #.
Euphoric

Tôi nghĩ rằng thực sự không có vấn đề gì khi sử dụng moveCameraTo(new LatLng(latitude, longitude));ở bất kỳ nơi nào trong dự án, nhưng tôi nghĩ rằng việc sử dụng rõ ràng hơn trực tiếp moveCametaTo (latLng), giống như một Tệp trong java bạn có thể truyền đường dẫn như chuỗi hoặc như một lớp Đường dẫn
Tlaloc-ES

1

Tôi không chắc tên thích hợp cho cái này là gì, nếu nó có một cái, nhưng nó là một thực hành tốt. Bạn phơi bày nhiều tình trạng quá tải, cho phép lớp gọi xác định tham số nào nó muốn sử dụng. Như bạn nói, một lớp khác có thể không biết LatLngđối tượng là gì, nhưng có thể biết nó Location.

Có một phương thức gọi phương thức khác cũng là chìa khóa, vì bạn không muốn mã trùng lặp trên các phương thức đó. Như bạn đã thực hiện, chọn một phương thức là phương thức thực hiện công việc và yêu cầu các phương thức khác gọi (trực tiếp hoặc gián tiếp)


1

Nếu bạn nhớ sử dụng loại phương thức, nó chỉ là tính năng nạp chồng phương thức thì tốt.

Nhưng không loại bỏ trách nhiệm biết LatLng là gì . Bởi vì bạn đang khởi tạo LatLng latLng = new LatLng(latitude, longitude). Đây là phụ thuộc hoàn toàn vào LatLng. (Để hiểu lý do tại sao Khởi tạo là một vấn đề phụ thuộc, bạn có thể kiểm tra Dependency Injection ) Tạo phương thức quá tải chỉ giúp khách hàng không quan tâm LatLng. Nếu bạn muốn nói điều này, nó cũng tốt nhưng tôi không nghĩ đó là một cách tiếp cận. Nó chỉ là nhiều phương pháp dịch vụ cho khách hàng.

Vì vậy, có hai tùy chọn để thiết kế kiến ​​trúc của bạn:

  1. Tạo nhiều phương thức quá tải và cung cấp chúng cho khách hàng.
  2. Tạo một vài phương thức quá tải cần tham số (s) làm giao diện hoặc lớp cụ thể.

Tôi chạy trốn hết mức có thể từ việc tạo các phương thức cần các kiểu nguyên thủy làm tham số (Tùy chọn 1). Bởi vì nếu doanh nghiệp của bạn thay đổi nhiều lần và bạn cần phát các tham số phương thức, thực sự rất khó để thay đổi và thực hiện tất cả chức năng của người gọi.

Thay vì điều này, sử dụng giao diện (Dependency Injection). Nếu bạn nghĩ rằng đó là chi phí và mất nhiều thời gian hơn, thì hãy sử dụng các lớp và cung cấp các phương thức mở rộng ánh xạ của chúng (Tùy chọn 2).

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.