чи такий спосіб називати функцію поганою практикою?


10

У мене є такий код:

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);
}

Я думаю, що таким чином я усуваю відповідальність за те, що, наприклад, є LatLngв іншому класі.

І вам не потрібно готувати дані до виклику функції.

Як ти гадаєш?

Чи має цей підхід назву? Це справді погана практика?


2
Я думаю, що ви просто маєте справу з інкапсуляцією, використовуючи вбудований у мову метод перевантаження. Це не добре / погано. Просто інструмент, який може допомогти або нашкодити вашому коду.
bitsoflogic

5
Якщо ваша мета - приховати LatLngвід клієнтів цього Cameraкласу, ви, мабуть, не хочетеmoveCameraTo(LatLng) бути ними public.
bitsoflogic

Окрім порад, наданих у відповідях, це відчуває себе гарним місцем згадати YAGNI. Вам це не потрібно. Не визначайте методи API, перш ніж буде корисний випадок використання, тому що ... Вам це не потрібно.
Патрік Х'юз

Нічого поганого moveCameraToLocationі moveCameraTo/ moveCameraToCoords. Однозначно не хотілося б передавати Location / lat / long всі в тих же назвах.
Insidesin

Відповіді:


9

Ви використовуєте функцію перевантаження ваших методів для мов, щоб запропонувати абоненту альтернативні способи вирішення залежності методів від позиційної інформації. Потім ви делегуєте інший метод, щоб вирішити решту роботи з оновлення камери.

Тут пахне кодом, якщо ви продовжуєте просто розширювати ланцюжок методів виклику методів. Метод вибору місця розташування викликає метод подвійного зйомки, який викликає метод зйомки latLng, який нарешті викликає те, що знає, як оновити камеру.

Довгі ланцюги є настільки ж міцними, як і їх найслабша ланка. Кожне розширення ланцюга збільшує слід коду, який повинен працювати, або ця річ порушується.

Це набагато краща конструкція, якщо кожен метод проходить найкоротший шлях до вирішення проблеми, яка йому була представлена. Це не означає, що кожен повинен знати, як оновити камеру. Кожен повинен перевести свій тип параметра позиції в один рівномірний тип, який може бути переданий тому, що не знає, як оновити камеру, коли представлений цей один тип.

Зробіть це так, і ви можете видалити один, не порушуючи половини всього іншого.

Поміркуйте:

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

Це зумовлює вирішення проблеми широти та довготи LatLng. Вартість полягає в тому, що вона поширює знанняLatLng навколо. Це може здатися дорогим, але, на мій досвід, це краща альтернатива примітивній одержимості, тому що уникнення встановлення об'єкта параметрів залишає вас застрягти.

Якщо Location це не піддається реабілітації, але LatLngце не так, розгляньте це рішення, додавши завод до Location:

moveCameraTo( location.ToLatLng() );

Це також чудово уникає примітивної одержимості.


1
Мені це не здається поганим - це справді просто зручність для споживача. Якщо це було прикуто 10 разів або якщо споживачеві не потрібні всі ці варіанти, то я б назвав це запахом коду.
mcknz

1
Але яка альтернатива покласти всю логіку для перетворення парних у LagLng або Location to LagLng у кожній функції?
Tlaloc-ES

@ Tlaloc-ES краще?
candied_orange

@ Tlaloc-ES "Перетворення" має відбутися лише один раз, коли примітиви завантажуються в логіку домену. Це станеться, коли ви дезаріалізуєте DTO. Потім вся логіка вашого домену проходить навколо LatLngабо Locationоб'єкти. Ви можете показати відносини між двома New LatLng(Location)або Location.toLatLng()якщо вам потрібно перейти від одного до іншого.
bitsoflogic

1
@ Tlaloc-ES Пов'язане читання: FlagArgument Мартіна Фаулера. Прочитайте розділ «Заплутане втілення».
Марк.2377,

8

У вашому рішенні немає нічого особливо поганого.

Але мої особисті переваги полягають у тому, що ці методи не такі корисні. І просто ускладніть інтерфейс будь-якого об'єкта, який вони відривають.

Код void moveCameraTo(double latitude, double longitude)насправді не спрощує код, тому що я не бачу жодної проблеми просто зателефонуватиmoveCameraTo(new LatLng(latitude, longitude)); на своє місце. Цей метод також пахне примітивною одержимістю.

Можливо, void moveCameraTo(Location location)краще вирішити Location.ToLatLng()метод доказування та викликуmoveCameraTo(location.ToLatLng()) .

якщо це був C # і якщо такі методи були справді необхідні, я б віддав перевагу їх як розширення, а не методи екземпляра. Використання методів розширення стане по-справжньому очевидним, якби ви спробували відібратись і перевірити цей примірник. Оскільки було б набагато простіше просто підробити один метод замість декількох перевантажень простими перетвореннями.

Я думаю, що таким чином я знімаю відповідальність за те, що, наприклад, є LatLng в іншому класі.

Я не бачу причин, чому це було б проблемою. Поки ваш клас посилань на код, який містить void moveCameraTo(LatLng latLng), він все одно опосередковано залежить від LatLng. Навіть якщо цей клас ніколи не є безпосередньо примірником.

І вам не потрібно готувати дані до виклику функції.

Я не розумію, що ти маєш на увазі. Якщо це означає створення нового примірника або перетворення класів з одного в інший, я не бачу в цьому жодної проблеми.

Думаючи про це, я відчуваю, що те, що я говорю, також підтримується дизайном API самого .NET. Історично багато класів .NET слідкували за вашим підходом до перевантаження з різними параметрами та простої конверсії всередині. Але це було до того, як існували методи розширення. Більш сучасні .NET-класи мають більш малу вагу у власних API, і якщо є якісь методи з перевантаженням параметрів, вони надаються як методи розширення. Старіший приклад - NLog ILogger, який має десятки перевантажень для запису в журнал. Порівняйте це з новішим Microsoft.Extensions.Logging.ILogger, який має всього 3 способи (і лише 1, якщо рахувати сам журнал). Але є безліч помічників і різних параметрів як методів розширення .

Я думаю, що ця відповідь свідчить про те, що деякі мови мали б інструменти, щоб зробити дизайн подібним приємнішим. Я не знаю багато Java, тому не впевнений, чи був би еквівалент. Але навіть використання простих статичних методів може бути варіантом.


Не знаю чому, але я вважаю, що я вболіваю за цю відповідь, незважаючи на те, що я конкуруюча. Я думаю, що вам просто вдалося зробити кращу справу. Єдиним моїм відгуком було б пам’ятати, що не всі, хто займається цією проблемою, є у .NET. +1
candied_orange

@candied_orange Вправо. Тепер, коли я краще розглядаю питання ОП, це більше схоже на Java, ніж на C #.
Ейфорія

Я думаю, що насправді немає проблем у використанні moveCameraTo(new LatLng(latitude, longitude));в будь-якому місці проекту, але я думаю, що більш чітко використовувати безпосередньо moveCametaTo (latLng), це як файл у Java, який ви можете пройти шлях, як рядок, або як клас Path
Tlaloc-ES

1

Я не впевнений, що це за власне ім'я, якщо воно є, але це є хорошою практикою. Ви піддаєте кілька перевантажень, дозволяючи класу виклику визначати, який набір параметрів він хоче використовувати. Як ви кажете, інший клас може не знати, що таке LatLngоб’єкт, але може знати його Location.

Ключове значення має і виклик одного методу, і інший, оскільки ви не хочете дублювати код у цих методах. Як ви зробили, виберіть один метод, який буде таким, який виконує роботу, а інші методи називають його (прямо чи опосередковано)


1

Якщо ви заперечуєте з використанням таких методів, це добре лише функція перевантаження методу.

Але відповідальності знати, що таке LatLng, не усунути . Тому що ви ініціалізуєте LatLng latLng = new LatLng(latitude, longitude). Це в повній мірі залежність від LatLng. (Щоб зрозуміти, чому ініціалізація є проблемою залежності, ви можете перевірити залежність введення ) Створення перевантаженого методу просто допомагає клієнтам, яким не байдуже LatLng. Якщо ви це маєте на увазі, це також добре, але я не думаю, що це підхід. Це просто багато методів обслуговування клієнтів.

Отже, є два варіанти проектування вашої архітектури:

  1. Створіть багато перевантажених методів і надайте їх клієнту.
  2. Створіть кілька перевантажених методів, для яких потрібні параметри, як інтерфейс або конкретний клас.

Я тікаю як можна більше від створення методів, яким потрібні примітивні типи як параметри (Варіант 1). Тому що якщо ваш бізнес багато разів змінюється і вам потрібно грати в параметри методу, змінити та реалізувати всі функції виклику дійсно важко.

Замість цього використовуйте інтерфейси (Dependency Injection). Якщо ви вважаєте, що це коштує і вимагає більше часу, то використовуйте класи та надайте їх методи розширення картографування (варіант 2).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.