Як я можу переформатувати свій стан, щоб покращити його?


35

У мене є стан

if(exists && !isDirectory || !exists)
{}

як я можу це змінити, щоб воно було більш зрозумілим.


1
яке значення маєDirectory, коли існує, помилково?
Мартані

1
існує тип Bool, isDirectory також є змінними типу BOOL
Spynet

5
якщо (! isDirectory) ... (існує ||! існує) завжди буде правдою.
Акула

@Shark - Що робити, existsі те і те isDirectoryй інше?
pasawaya

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

Відповіді:


110

|| комутативно, так

if(!exists || (exists && !isDirectory))

рівнозначний.

Тепер, оскільки існує завжди вірно, у другій частині ||ви можете скинути &&:

if(!exists || !isDirectory)

Або ви можете піти на крок далі і зробити:

if(!(exists && isDirectory))

5
Те, що малося на увазі, але прямо не згадується тут, &&має більшу перевагу (принаймні, у більшості відомих мов - можуть бути винятки), ніж ||. Таким чином a && b || c, рівнозначно, (a && b) || cале не a && (b || c).
Péter Török

27
Я думаю, що !exists || !isDirectoryце більш «зрозумілим», тому що, isDirectoryне може бути правдою , якщо !exists. Тож як людина ми скажемо "якщо її не існує, або вона [існує і вона] не є каталогом".
duros

6
Я вважаю за краще! Існує || ! isDirectory над останнім.
Апоорв Хурасія

3
||є лише комутативним, якщо використовується для значень без побічних ефектів - якщо, наприклад, використовується з функціями, деякі функції можуть не викликатися (коротке замикання) або повертати інше значення в іншому порядку.
orlp

26
Той, хто покладається на відносну перевагу '&&', '||', '==', '! =' Тощо, і не зробить свого наміру зрозумілим за допомогою дужок, заслуговує на те, щоб його зняли. На всіх мовах щось на кшталт "a&& b || c 'еквівалентний коментарю, який говорить про те, що автор, ймовірно, накрутив всю річ у своєму поспіху, щоб увести кілька зайвих символів.
Брендан

51

В якості процесу я пропоную побудувати таблицю правдивості:

e = exists
d = isDirectory

e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0

Це відповідає NANDоперації , яка просто:

!(exists && isDirectory)

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


@Christoffer Hammarström підкреслив важливий момент про стан isDirectoryприв'язаності до держави exists. Якщо припустити, що вони посилаються на ту саму посилання і що неможливо мати стан, коли посилання не існує і є каталогом, таблицю істинності можна записати так:

e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | n/a
1 | 0 | 1
1 | 1 | 0

n/aВикористовується для позначення стану , яке не має значення. Прийнятні скорочення можуть призвести до стану 1або 0до стану, що призведе до n/a.

Зважаючи на це, !(exists && isDirectory)все-таки є дійсним зменшення, що призводить до 1отримання !e && d.

Тим НЕ менше, !isDirectoryбуло б набагато простіше , скорочення, в результаті чого 0для !e && d.


4
Наступний крок - усвідомити, що isDirectoryзалежить від цього exists. Це не може бути і каталогом, і не існувати.
Крістофер Хаммарстрем

@ChristofferHammarstrom, Поза контекстом я не можу припустити, що змінні стосуються одного і того ж, але це дійсна точка. Стовпчик результатів має бути заповнений n/aу місцях, де стан неможливо досягти, а рівняння відповідно зменшити.
zzzzBov

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

Але побудова таблиці істини та її оцінка не є повною!
Томас Едінг

@ThomasEding, я маю для вас дві цитати тоді: "Теоретично, теорія та практика однакові; на практиці їх немає". і "Передчасна оптимізація - корінь усього зла".
zzzzBov

22

Для кращої читабельності я люблю вилучати булеві умови методами:

if(fileNameUnused())
{...}

public boolean fileNameUnused() {
   return exists && !isDirectory || !exists;
}

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


+1, щоб сказати щось про корисні імена. Але десь доведеться переформатувати умовне.
Апоорв Хурасія

4
Менш екстремальною альтернативою, яка все ще передає наміри, є лише назвати використану умову:boolean fileNameUnused = !exists || !isDirectory; if (fileNameUnused) { doSomething(); }
Стівен

8

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

while(someCondition) {

    if(exists && isDirectory)
        continue;
        // maybe "break", depends on what you're after.

        // the rest of the code
}

або навіть

function processFile(someFile)
{ 
    // ...
    if(exists && isDirectory)
       return false;
    // the rest of the code
    // ...
}

Не зламайте, продовжуйте, і більш ніж одне твердження про повернення вважається кодом запахом?
Freiheit

8
@Freiheit Це залежить від контексту. Іноді оператор раннього повернення використовується для зменшення відступу, підвищуючи таким чином читабельність.
marco-fiset

Найкраща відповідь - складні умовні умови витрачають величезну кількість часу на читання та точне їх розуміння. Внаслідок цього часто «приймаються як прочитані», що призводить до підступних помилок.
mattnz

6

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

Використання законів булевої алгебри - ще один підхід:

A = існує
B =! IsDirectory
! A =! Існує

&& = *
|| = +

[Редагувати]
Простіше перетворення, оскільки операції І та АБО взаємно розподіляють:

існує &&! isDirectory || ! існує
= A * B +! A
= (A +! A) * (B +! A)
= 1 * (B +! A)
= B +! A
[/ редагувати]

існує &&! isDirectory || ! існує
= A * B +! A
= A * B +! A * 1 // Ідентичність
= A * B +! A * (B + 1) // Annihilator
= A * B +! A * B +! A / / Розповсюдження та ідентичність
= B * (A +! A) +! A // Розподільність
= B * 1 +! A // Доповнення 2
= B +! A // Ідентичність
=! IsDirectory || ! існує

Або з подвійним доповненням (!! x = x):

A * B +! A
= !! (A * B +! A)
=! (! (A * B) * A)
=! ((! A +! B) * A)
=! (! A * A + ! B * A)
=! (0 +! B * A)
=! (! B * A)
= B +! A
=! IsDirectory || ! існує


+1 за використання формальних правил (я ніколи не бачив одного з них після першого курсу навчання в коледжі).
Nemanja Boric


5

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

doesNotExist = !exists;
isFile = exists && !isDirecotry;
if (isFile || doesNotExist) 
   {}

+1 Це полегшує зчитування як "якщо файл чи не існує", що набагато ближче до англійської.
Філ

Це рефакторинг під назвою Ввести пояснення змінної .
Едді Гаспарян

1

Як було зазначено раніше, стан можна зменшити до:

if (!(exists && isDirectory))

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

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