Найкраща булева задача [закрито]


10

У програмі, яку я взяв від іншого розробника, я натрапив на таке умовне:

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.NeedsChange = false;
}

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

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE;

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

obj.NeedsChange = (obj.Performance <= LOW_PERFORMANCE) ? true : false;

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

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


25
Третя форма смішна; це просто констатувати те, що вже повинно бути очевидно очевидним у другій формі.
Роберт Харві

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

3
@scriptin 5-8 рядків v 1 рядок - це більше, ніж перевагу, 5-8 вкладишів звичайно чіткіше і краще для нього. У цьому простому прикладі я віддаю перевагу 1-й лінії, але загалом я бачив занадто багато 10 лайнерів, які були зруйновані на 1-лайнери для комфорту. Враховуючи це, я ніколи не скаржиться на варіант 1, він може бути не дуже гарним, але він робить роботу так само чітко і очевидно.
gbjbaanb

4
Варіанти 1 і 3 кажуть мені "Автор не дуже розуміє булеву логіку".
17 з 26

2
Варіант 1 може бути корисним, якщо вам потрібно часто встановлювати точку розриву, яка залежить від значення.
Ян

Відповіді:


39

Я віддаю перевагу 2, але я можу попрацювати над цим:

obj.NeedsChange = ( obj.Performance <= LOW_PERFORMANCE );

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


4
це правильна відповідь - хоча код у питанні правильний, додавання дужок вказує читачеві, що це не як призначення. Якщо ви швидко переглядали код, дужки надають вам ту миттєву додаткову інформацію, яка зупиняє вас придивитися ближче, щоб побачити, чи не означав код такий, а не випадковий помилку. Наприклад, уявіть, що рядок був a = b == c, ви мали на увазі призначити bool або ви мали на увазі призначити c і b, і a.
gbjbaanb

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

23

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

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

Варіант 3 поєднує недоліки як 1, так і 2. '.


Ну, варіант 1 ділиться своєю перевагою з варіантом 2 ...
Дедуплікатор

1
+1 для інфантильного коду. Я дивився на такий код роками, мені просто бракувало потрібного слова, щоб його визначити.
Ліліенталь

1
Моє перше припущення з кодом, як Варіант 1, полягає в тому, що дві гілки в один момент минулого були складнішими, і хтось не звертав уваги під час рефакторингу. Якщо все-таки це було, коли було написано вперше, то я погоджуюся з "не розуміючим булевих"
Ізката

13

Код у будь-який час є складнішим, ніж потрібно, щоб викликати "що це має робити?" запах у читача.

Наприклад, перший приклад змушує мене замислитися, "чи була інша функціональність у операторі if / else в якийсь момент, який був видалений?"

Приклад (2) простий, зрозумілий і робить саме те, що потрібно. Я читаю його і одразу розумію, що робить код.

Додатковий пух (3) змусить мене замислитися, чому автор написав саме так, а не (2). Там повинна бути причина, але в даному випадку не здається , немає, так що це не корисно взагалі і важче читати , тому що синтаксис передбачає , що - то справжнє , яке не існує. Намагання дізнатися, що є (коли нічого немає) робить код важче читати.


2

Неважко помітити, що Варіант 2 та Варіант 1 пов'язані через низку очевидних та простих реконструкцій:

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.NeedsChange = false;
}

Тут у нас є непотрібне дублювання коду, ми можемо визначити призначення:

obj.NeedsChange = if (obj.Performance <= LOW_PERFORMANCE)
{
    true
}
else
{
    false
}

або написано більш стисло:

obj.NeedsChange = if (obj.Performance <= LOW_PERFORMANCE) true else false

Тепер повинно бути відразу очевидно, що це буде присвоювати істину, якщо умова істинна, і призначити помилковим, якщо умова помилковим, IOW це просто призначить значення умови, тобто воно еквівалентно

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE

Варіанти 1 і 3 є типовим початковим кодом, написаним особою, яка не розуміє, що таке повернене значення порівняння.


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

2

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

Одним із таких є синтаксис мови, якою він користується.

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE;

дуже зрозуміло для всіх, хто знає синтаксис C / C ++ / C # / Java / Javascript.

Це також набагато читабельніше, ніж 8 рядків.

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.NeedsChange = false;
}

і менш схильні до помилок

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.Needschange = false;
}

І це краще, ніж додавати непотрібні символи, ніби ви напівзабули синтаксис мови:

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE ? true : false;

obj.NeedsChange = (obj.Performance <= LOW_PERFORMANCE);

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

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


Взагалі річ №1, яка робить код Real World TM нечитабельним, - це його кількість.

Між непатологічною програмою на 200 ліній та тривіально ідентичною програмою 1600 ліній коротша програма майже завжди буде простішою для розбору та розуміння. Я б вітав вашу зміну в будь-який день.


1

Більшість розробників зможуть розібратися у 2-му класі з першого погляду. На мою думку, спрощення, як у 1-му класі, просто зайве.

Ви можете покращити читабельність, додавши пробіли та дужки, такі як:

obj.NeedsChange =    obj.Performance <= LOW_PERFORMANCE;

або

obj.NeedsChange = ( obj.Performance <= LOW_PERFORMANCE );

як згадував Яків Райхле.

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