Це запах коду, якщо ви часто створюєте об'єкт просто для виклику методу на ньому


14

Я успадкував базу коду, де існує багато коду, який має щось подібне:

SomeDataAdapter sda = new SomeDataAdapter();
sda.UpdateData(DataTable updateData);

І тоді sda більше не використовується.

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


Чи реалізують ці класи будь-які інтерфейси?
Реакційний

7
На наступний день після рефактора до статичних методів буде день, коли ви хочете запустити тести одиниць із насмішкованою версією адаптера даних.
Майк

22
@Mike: Чому вам коли-небудь потрібно знущатися над статичним методом? Мені стає дуже нудно від цього помилкового аргументу, що статичні методи не піддаються контролю. Якщо ваші статичні методи тримають стан або створюють побічні ефекти, це ваша вина, а не вина вашої методології тестування.
Роберт Харві

9
На мою думку, це запах мови, що показує слабкість аналізу "все має бути клас".
Бен

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

Відповіді:


1

Я вважав би це запахом архітектури в тому, що UpdateData, ймовірно, повинен належати до класу "service".

Де дані - Apple. Там, де AppleAdapter - сервіс / бізнес-розвідувальний клас. Якщо AppleService - це посилання Singleton на AppleAdapter, що існує поза поточного методу.

private static volatile AppleAdapter _appleService = null;
private static object _appleServiceLock = new object();
private AppleAdapter AppleService
{
    get
    {
        if (_appleService == null)
        {
            lock (_appleServiceLock)
            {
                if (_appleService == null)
                    _appleService = new AppleAdapter();
            }
        }
        return _appleService;
    }
}

public SomeAppleRelatedMethod(Apple apple)
{
    AppleService.UpdateData(apple);
}

Я не думаю, що ви робите неправильно обов'язково, але якщо SomeDataAdapter справді представляє якусь службу без громадянства, то одиночка буде найкращою практикою для цього. Сподіваюся, що це допомагає! Наведений приклад - фантастичний спосіб забезпечити відсутність суперечок _appleService, якщо воно сталося як нульовим, так і доступ до них в один і той же час двома або більше потоками.

Знаєш, що? Якщо SomeDataAdapter є ADO IDbDataAdapter (що це майже напевно є), ігноруйте всю цю відповідь!

: P

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

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


12
Довідка! Я тону в програмних зразках.
Роберт Харві

4
... або вводиться як залежність. ;)
Роб

12
Метерення з одинарними кнопками та двічі перевірене блокування, щоб отримати щось еквівалентне простої функції / процедури, для мене набагато більший запах коду!
Бен

3

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


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

1

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

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


Це також може означати, що ви хочете, щоб статичний метод повертав модифіковану версію (або модифіковану копію) об'єкта, який ви йому передаєте.
Роберт Харві

2
"якщо ви застрягли в мові без першокласних функцій": Немає різниці між об'єктом лише одним методом і функцією першого класу (або закриттям першого класу): це лише два різних погляди одного і того ж річ.
Джорджіо

4
@ Джорджіо Теоретично, ні. На практиці, якщо у вашій мові немає принаймні синтаксичного цукру, це різниця між fn x => x + 1та new Function<Integer, Integer>() { public Integer eval(Integer x) { return x + 1; }};обмеженням себе декількома жорстко кодованими та вузько корисними функціями.
Доваль

Чому не fn x => x + 1можна бути синтаксичним цукром new Function<Integer, Integer>() { public Integer eval(Integer x) { return x + 1; }}? Гаразд, можливо, ви маєте на увазі, якщо хтось застряг у мові без такого синтаксичного цукру.
Джорджіо

@Giorgio Вам доведеться запитати Oracle. (Звичайно, це остаточно змінюється з Java 8). Зауважте, що вам знадобиться більше синтаксичного цукру, ніж просто це, щоб бути дійсно корисним - ви також хочете мати можливість передавати заздалегідь оголошені методи по імені. Каррінг також буде корисним. У якийсь момент вам доведеться замислитися, чи варто проводити всі ці хаки, а не ставитися до функцій як до перших громадян. Але зараз я виходжу з теми.
Доваль

0

Якщо утримання держави робить даний клас більш утилітарним, функціональним ... повторним користуванням, то ні. Чомусь приходить в голову шаблон дизайну команд ; ця причина, безумовно, не в бажанні втопити Роберта Харві.


0

Визначте "часто". Як часто ви інстанціюєте об'єкт? Багато - напевно, ні?

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

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

Так, це кодовий запах, просто невеликий.


0

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


0

Запах тут полягає в тому, що це процесуальний код, загорнутий (мінімально) в об'єкти.

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

У функціональній мові так ви робите речі;), але в парадигмі ОО ви хочете моделювати деяку абстракцію, яка включала цю операцію. Тоді ви використовуєте методи OO, щоб обробляти цю модель і надавати набір пов'язаних операцій, які зберігають певну семантику.

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

BTW стежте за будь-яким часом, коли ви бачите, що програма моделюється замість проблемного простору . Це знак того, що дизайн може виграти від більшої думки. Іншими словами, слідкуйте за класами, які є "xAdaptor" і "xHandler" і "xUtility", і зазвичай прив'язані до анемічної моделі домену . Це означає, що хтось просто поєднує коди для зручності, а не насправді моделює ті концепції, які вони хочуть реалізувати.

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