Що таке вихідний аргумент, про який йдеться у чистому кодексі Мартіна?


14

На сторінці 45 чистого кодексу Роберта К. Мартіна: Підручник з гнучкої майстерності програмного забезпечення, Мартін пише, що слід уникати аргументів виводу. У мене виникають проблеми з розумінням значення "вихідних аргументів" і чому їх слід уникати.

Приклад Мартіна для вихідного аргументу appendFooter(s);називає функцію public void appendFooter(StringBuffer report). Його поліпшення коду єreport.appendFooter();

Можливо, це пов'язано з відсутністю контексту коду, але я не бачу, як використання вихідних аргументів вважається поганим кодуванням. Чи може хтось пояснити поняття чи надати приклад прикладу коду, щоб зрозуміти це?

Чи вважалася б така функція прикладом нечистого коду за вищезазначеним принципом?

int[] numberArray = {3, 5, 7, 1};
sortArray(numberArray);

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

ObjectWithArrayField numberArray = new ObjectWithArrayField(3, 5, 7, 1);
numberArray.sort();

Відповіді:


11

Боб Мартін просто говорить про читабельність .

Проблема з appendFooterприкладом полягає в тому, що якщо ви знайдете рядок коду appendFooter(s)десь у програмі, це не відразу очевидно, якщо цей виклик приймається sяк вхідний і додає його кудись, або якщо sпросто передається для отримання результату цієї функції. Для впевненості потрібно перевірити документацію функції. Однак такий дзвінок report.appendFooter()дозволяє уникнути цієї проблеми: набагато очевидніше зараз те, що відбувається.

Зауважте, проте Боб Мартін не каже, що "ніколи не використовуйте вихідні аргументи", він каже: "загалом, вам слід цього уникати, оскільки це допоможе вам зберегти свій код трохи більш чистим". Отже, це не вантажне культове правило, яке слід сліпо слідувати.

Sortметоди для стандартних масивів і колекцій трохи відрізняються. Наявність sortметоду член-функції кожного стандартного типу даних масиву мала б кілька недоліків з точки зору дизайнера мови, наприклад, такий метод, як Array.sortдозволяє зберігати це в стандартній бібліотеці, поза межами виконання Java. Але якщо ви створили індивідуальний тип колекції, який доводиться іноді сортувати, додавання sortв якості функції члена може бути справді кращою ідеєю, ніж переведення його в окремий клас.


2
sortArray(numberArray)звичайно, сортує numberArrayна місці. Або він робить копію numberArray, сортує копію та повертає відсортовану копію, не змінюючи її numberArrayвзагалі?
8bittree

@ 8bittree: це правда, але тут не сенс дискусії - sort()метод контейнера може працювати і на місці, не використовуючи "вихідний аргумент". Тож лише тому sortArray(numberArray), що це місцевий метод, абсолютно немає причин, які виправдовують "форму аргументу виводу".
Док Браун

1
Моя думка була більше, що не зовсім очевидно, що sortArray(numberArray)робиться. Це може бути очевидним, якщо він не повертає того ж типу, який приймає, тоді він повинен бути на місці. Але не бачачи тип повернення або якщо тип повернення відповідає типу введення, його незрозуміло, не дивлячись на визначення.
8bittree

1
@ 8bittree: Гаразд, ти мене зрозумів, я видалив заяву на карту зі своєї відповіді. Однак проблема, яку описує, не зникає, використовуючи функцію члена - навіть функція "сортування" члена може поводитися таким чином.
Док Браун

11

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

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

Єдиним винятком є ​​дуже загальні алгоритми. Наприклад, алгоритм сортування може бути справедливо відокремлений від контейнерів, які він сортує, якщо він може бути застосований до будь-якого типу контейнерів за допомогою його загальнодоступного інтерфейсу. Функція одного удару appendFooterне має цього виправдання.

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