2015-02-01 2 views
0

Когда-то я написал учебное приложение для JavaScript с SVG (закрытый источник для компании). В своей самой основной форме приложение состоит из двух столбцов (левый и правый), а каждый столбец содержит различные геометрические фигуры (квадраты, треугольники, круги и т.д.)Рефакторинг логики внутри оператора if до минимального минимума

Каждая геометрическая форма в одном столбце может подключиться (, рисуя линию) другой геометрической форме в противоположном столбце. Тем не менее, форма в любом столбце может иметь одно или несколько подключений к нему/в зависимости от его настроек.

Таким образом, форма с настройкой {multiple: false} может иметь только одно соединение с ней или от нее. Не имеет значения, возникло ли соединение от него или из другой формы к нему; одно соединение означает только одно соединение независимо от источника.

Часть кода, который соединяет фигуры путем рисования строки, является чрезмерно сложным оператором if. Здесь:

if ((!sourceHasLines && !targetHasLines) || 
    (sourceHasLines && sourceCanMultiply && !targetHasLines) || 
    (sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply) || 
    (!sourceHasLines && !sourceCanMultiply && targetHasLines && targetCanMultiply) || 
    (!sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply)) { 
    // Create a line only if one of the above comparisons succeeds 
    connection = self.connect($source, $target); 
} 
  • Источник относится к форме в одну колонку и мишени к форме в противоположном колонке.
  • Пользователи могут инициировать соединение из любого столбца, сначала щелкнув одну форму в первом столбце, а затем щелкнув другую фигуру во втором столбце.
  • Невозможно подключить фигуры в одном столбце.

Теперь, глядя на код, я чувствую, что логика внутри оператора if может быть сжата, и у меня есть некоторые идеи. Тем не менее, я чувствую, что это связано с перестановками или с какой-либо другой связанной с CS логикой, такой как Discrete Math. Я в основном самоучка, поэтому я хотел бы посмотреть, как кто-то подходит к этому и реорганизует приведенное выше заявление if.

Обратите внимание, что код отлично работает, но мне интересно, как его можно улучшить.Вот скриншот прототипа с верхними/нижними рядами вместо левой/правой колонки:

Connect top objects with bottom objects

ответ

1

Как насчет:

if ((!SL || SM) && (!TL || TM)) ... 

т.е. источник должен быть пустым или принимать несколько строк и цель должна быть пустой или принимать несколько строк

+0

Я смог упростить его немного больше, но ваш пример, безусловно, самый простой и элегантный для меня. Благодаря! :) – istos

1

Посмотрите на этих двух линий

(!sourceHasLines && !sourceCanMultiply && targetHasLines && targetCanMultiply) 

(!sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply) 

, если любой из них истинны, мы будем рисовать линию

давайте

a = source has lines 
A = source can multiply 
b = target has lines 
B = target can multiply 

вышеуказанные две линии становятся

(1) ~a AND ~ A AND b AND B 
(2) ~a AND A AND b AND B 

мы используем (1) и (2) для принятия решения, которое делает A (источник может умножаться) DONT CARE, когда источник не имеет линий.

Следовательно, эти две линии могут быть заменены

(!sourceHasLines && targetHasLines && targetCanMultiply) 

Теперь ваш код становится

if ((!sourceHasLines && !targetHasLines) 
    || (sourceHasLines && sourceCanMultiply && !targetHasLines) 
    || (sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply) 
    || (!sourceHasLines && targetHasLines && targetCanMultiply)) {  
    connection = self.connect($source, $target); 
} 

Это может быть упрощены только

if ((!sourceHasLines || sourceCanMultiply) && (!targetHasLines || targetCanMultiply)) {  
    connection = self.connect($source, $target); 
} 
+1

Было полезно увидеть, как вы смогли объединить последние два состояния в один, а затем приблизились к тому же пониманию, что и @Hurelu. Поскольку Хюрелу ответил первым, я приму этот ответ, но ваш ответ был в равной степени полезен. Спасибо! :) – istos

1

Вы можете применить алгебру, чтобы уменьшить логика вашего кода:

Пред- полагая:

A = sourceHasLines; 
B = targetHasLines; 
C = sourceCanMultiply; 
D = targetCanMultiply; 

было бы перевести в:

if ((!A && !B) || 
    (A && C && !B) || 
    (A && C && B && D) || 
    (!A && !C && B && D) || 
    (!A && C && B && D)) { 
    // Create a line only if one of the above comparisons succeeds 
    connection = self.connect($source, $target); 
} 

, что бы перевести с помощью алгебры в:

(!A * !B) + (A * C * !B) + (A * C * B * D) + (!A * !C * B * D) + (!A * C * B * D) 

Применение некоторых математикой:

!A * (!B + (B * D)) + A * C * (!B + (B * D)) 

(!B + (B * D)) * (!A + (A * C)) 

(!A + C) * (!B + D) 

Henc e:

if(!sourceHasLines || sourceCanMultiply) && (!targetHasLines || targetCanMultiply)) { 
    connection = self.connect($source, $target); 
} 
+0

Хотя я не собираюсь притворяться, что понимаю ваш математический вывод, я признаю, что это выглядит потрясающе, и я, несомненно, вдохновлен, чтобы узнать больше о концепции (-ях). Спасибо! – istos

+1

Добро пожаловать, просто рефакторинг, применяющий булеву алгебру. – acontell

Смежные вопросы