Названі аргументи (параметри) як допомогу для читання


11

Давно я багато програмував в ADA, і було нормально називати аргументи при виклику функції - SomeObject.DoSomething (SomeParameterName => someValue);

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

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

contentFetcher.DownloadNote (примітка, посібник: правда);

Я думаю, що я міг би створити Enums замість того, щоб використовувати true або false (в цьому випадку посібник, автоматичний).

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


Також допомагає коментар параметрів у верхній частині методів.
Амір Резай

1
@ amir-rezaei: коментарі до параметрів на основі методів допомагають лише в тому випадку, якщо ви можете довіряти коментарям. Якщо у вас є хороші розробники та хороші процеси перегляду коду, я б не довіряв коментарям.
btilly

Як одноразовий користувач Ada, я час від часу використовую, як ви описуєте. Ось так я пам’ятаю, як вони використовувались в Ada, BTW - я б не називав це «ненормальним», але, здається, слово «нормальне» означає, що більшість викликів визначають імена параметрів, які я не пам'ятаю. Звичайно, умовності різняться, але непотрібне захаращення є поганою умовою в будь-якій мові ІМО.
Steve314

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

Відповіді:


7

Це було запропоновано при розробці C ++, і Stroustrup обговорює це у своєму "Дизайні та еволюції C ++", стор. 153 і далі. Пропозиція була добре сформована і спиралася на попередній досвід роботи з Ада. Він не був прийнятий.

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

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

З ним можна також обробляти за допомогою об'єктів, а не викликів функцій. Замість виклику GetWindow з десятком параметрів створіть клас Window з десятком приватних змінних та додайте сетерів за необхідності. Прив’язуючи сетери, можна написати щось подібне my_window.SetColor(green).SetBorder(true).SetBorderSize(3);. Також можливі різні функції з різними типовими значеннями, які викликають функцію, яка насправді виконує роботу.

Якщо ви просто переживаєте про ефект документації contentFetcher.DownloadNote(note, manual : true);, ви завжди можете написати щось подібне contentFetcher.DownloadNote(note, /* manual */ true);, тому це навіть не дуже допомагає в документації.


Як не дивно, коли я перейшов з Ада на С, я почав використовувати конвенцію, яку ви описуєте - оглядачі коду ненавиділи її. Погодьтеся, не використовуйте його для великої кількості параметрів.
Даміан

7

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

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

Якщо у методів є лише 1 або 2 параметри, і з назви методу зрозуміло, що таке параметр, то названий параметр нічого не додає. Це ідеальний випадок.

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


1
Функція з двома параметрами може бути заплутаною, якщо обидва параметри одного типу і не мають підказки, до чого це. Звичайно, ви можете назвати функцію таким чином, що забезпечує цю підказку, але ви все одно просто робите те, що імена параметрів так чи інакше роблять, - за винятком того, що ви зобов’язуєте включати це багатослів’я навіть у контексті (наприклад, вирази, які постачають джерело параметри) дають зрозуміти, який саме параметр.
Steve314

1
@ Steve314 Приклад:void TrackDataChange(Data oldData, Data newData)
Олександр

3

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

public Content DownloadNote(Note note)
{
    return downloadNote(note, manual: false);
}

public Content DownloadNoteManually(Note note)
{
    return downloadNote(note, manual: true);
}

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


3
Якщо у вас є вибір x, ви зробите 2 ^ x фронти?
apoorv020

@ apoorv020 - якби у мене було достатньо параметрів для виклику методу, який 2 ^ x став значущим, я б створив новий клас, щоб містити значення параметрів, і просто передав би один параметр.
Скотт Вітлок

@ scott-whitlock: Варіант 1 - створити об'єкт, встановити властивості x, викликати метод один раз зі своїм об’єктом. Варіант 2 - викликати метод з x названими параметрами. Що краще, залежить від вашої мови. У мові, що динамічно набирається, варіант 1 вимагає значно більше пластини котла без посилення, і тим гірше. Статично набраною мовою ви все одно додаєте котловую панель, але тести на неправильно названі ключі повинні бути виконані під час компіляції, а не час виконання. Тому варіант 1 краще в C #, але варіант 2 - це явна перемога в Python.
btilly

@btilly - як зазначав Іан, Clean Code чітко говорить вам, що ви не маєте функцій з більш ніж 2 або 3 параметрами. Справедливо кажучи, вона мала справу з Java, яка є статично типізованою. ОП також запитує про C #, який статично набраний. Я все-таки вважаю за краще використовувати перевантаження функцій та / або інше точно названі назви функцій, ніж довгий список параметрів.
Скотт Вітлок

@ scott-whitlock: Ми насправді не погоджуємось? Ми погоджуємося, що найкраще в C #. Ми обидва знаємо, що говорить Чистий кодекс. Моя думка полягала в тому, що важливо зрозуміти, чому це добре, щоб ви знали, коли порада робить чи не відповідає іншому середовищу.
btilly

3

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

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


0

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

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

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