Аргументи полів проти методу [закрито]


9

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

Це означає, що багато методів, які не можуть мати аргументів, закінчуються одним, двома або трьома.

Мені хотілося б почути вашу думку щодо того, що ви думаєте про цей компроміс, і як ви вирішуєте, який підхід використовувати в якій ситуації?

Оскільки код часто легше зрозуміти, ніж англійський при описі коду, я створив невелику суть, яка має в ньому обидва варіанти: https://gist.github.com/JeroenDeDauw/6525656


Аргументи, які використовуються лише як локальна змінна (не глобальна впродовж життя об’єкта), повинні мати сферу застосування лише доки це має сенс ... Мені здається, це дуже дратує, коли devs зберігають неінстанційний стан як стан екземпляра, тому що це зручно ... Хоча тільки моя думка. Складано зрозуміти, яким потоком виконання є насправді.
Макс

Використовуючи параметри та дозволяючи класу піклуватися про те, чи може він повинен змінити стан під час виконання методу, добре поєднується з принципом "сказати не запитувати" . Тільки майте на увазі, що «Не запитувати» не означає, що ви не можете запитувати об’єкт про його стан ( кричущий штекер )
Marjan Venema

Відповіді:


2

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

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

Приклад псевдокоду:

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

     private class TableUpdater { ... }
}

Таким чином, ви уникаєте полів, які використовуються лише одним публічним методом. Крім того, код є безпечним для потоків у тому сенсі, що кожен виклик до updateTable використовує власну копію TableUpdater і, таким чином, змінних екземплярів TableUpdater.


7

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

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


Мультитречінг не стосується мого випадку використання, як це є в PHP. Я згоден, що такий підхід поганий, якщо спосіб використання полів не є тривіальним. У цьому випадку вони записуються (і завжди пишуться) лише з публічного методу. Я не думаю, що це спричинить проблеми. Що стосується таких полів, які лише трохи кращі, ніж глобальних, я зовсім не впевнений, що ви маєте на увазі. Чи можете ви докладно?
Jeroen De Dauw

7

Словами мирянина:

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

Знову ж таки, на мою скромну думку, некогезивні методи належать до класу корисності, а не до класу з доменним іменем.


1

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

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


0

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

У цьому випадку ми повинні керуватися не ефективністю (різниця все-таки незначною), або (Боже, збережіть!) Простотою введення тексту, а зрозумілістю та природністю коду.


0

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

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

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

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

Ви можете скасувати і діяти, але не функцію .

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