Невже використання внутрішніх блоків області в межах функції погано?


10

Є деякі (досить рідкісні) випадки, коли існує ризик:

  • повторне використання змінної, яка не планується повторно використовувати (див. приклад 1),

  • або використовуючи змінну замість іншої, семантично близької (див. приклад 2).

Приклад 1:

var data = this.InitializeData();
if (this.IsConsistent(data, this.state))
{
    this.ETL.Process(data); // Alters original data in a way it couldn't be used any longer.
}

// ...

foreach (var flow in data.Flows)
{
    // This shouldn't happen: given that ETL possibly altered the contents of `data`, it is
    // not longer reliable to use `data.Flows`.
}

Приклад 2:

var userSettingsFile = SettingsFiles.LoadForUser();
var appSettingsFile = SettingsFiles.LoadForApp();

if (someCondition)
{
    userSettingsFile.Destroy();
}

userSettingsFile.ParseAndApply(); // There is a mistake here: `userSettingsFile` was maybe
                                  // destroyed. It's `appSettingsFile` which should have
                                  // been used instead.

Цей ризик можна зменшити, ввівши область застосування:

Приклад 1:

// There is no `foreach`, `if` or anything like this before `{`.

{
    var data = this.InitializeData();
    if (this.IsConsistent(data, this.state))
    {
        this.ETL.Process(data);
    }
}

// ...

// A few lines later, we can't use `data.Flows`, because it doesn't exist in this scope.

Приклад 2:

{
    var userSettingsFile = SettingsFiles.LoadForUser();

    if (someCondition)
    {
        userSettingsFile.Destroy();
    }
}

{
    var appSettingsFile = SettingsFiles.LoadForApp();

    // `userSettingsFile` is out of scope. There is no risk to use it instead of
    // `appSettingsFile`.
}

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


7
Чи можете ви стверджувати, що кожен незалежний "блок дії" повинен бути власним методом чи функцією?
Ден Пішельман

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

Відповіді:


35

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

Підтверджуючи це особистим досвідом: кілька років тому я успадкував спадковий проект C ++ з ~ 150K рядків коду, і він містив кілька методів, що використовують саме цю техніку. І здогадайтесь, що - всі ці методи були занадто довгими. Коли ми переробили більшу частину цього коду, методів стало все менше і менше, і я впевнений, що більше немає методів "внутрішнього застосування"; вони просто не потрібні.


4
Але чому це погано? Наявність багатьох названих функцій також заплутано.
Kris Van Bael

1
+1 Точно, якщо вам потрібен діапазон, ймовірно, ви виконуєте певну дію, яку можна витягти до функції. Кріс, справа не в створенні партій і безлічі функцій, це те, що коли ці випадки трапляються (де область одного блоку може суперечити іншому), зазвичай функція повинна була використовуватися. Я бачу це і на інших мовах (а саме JavaScript, з IIFE замість простих "старих функцій") також весь час.
Бенджамін Грюнбаум

10
@KrisVanBael: "Багато іменованих функцій також заплутано" - якщо ви використовуєте описові імена, то навпаки. Створення занадто великих функцій є найвищою причиною того, як коду стає важко підтримувати, а ще важче в міру.
Док Браун

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

3
Досі не переконаний. Часто довгі функції справді погані. Але сказати, що для кожної потреби в області застосування потрібна окрема функція, для мене занадто чорно-біла.
Kris Van Bael

3

Початківцю (і будь-якому програмісту) набагато простіше думати:

  • не використовувати змінну, яка не стосується

ніж думати:

  • додавання структур коду, спрямованих на те, щоб не допустити використання змінної, яка не стосується.

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


2

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


0

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

Є один конкретний сценарій, OTOH, у C #, коли вони мають тенденцію до спливу - це при використанні конструкцій з комутаторами. Ситуація дуже красиво пояснюється в: C # Переключення оператора з / без фігурних дужок ... в чому різниця?

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