Является ли более чистый способ реализации логической логики, который проходит, если происходит одна из двух вещей? - PullRequest
3 голосов
/ 13 августа 2011

Это случается со мной время от времени, и я всегда заканчиваю тем, что решаю это одинаково, а затем желаю более чистого пути.

Я начинаю с вызовов соответствующих служебных функций, за которыми следуют ивызов обновления.

SynchA();
SynchB();
UpdateLastTime();

Затем позже я добавляю флажки, чтобы у меня было:

if(synchA.Checked)
{
  SynchA();
}
if(synchB.Checked)
{
  SynchB();
}

НО теперь я хочу вызывать UpdateLastTime () из ОДНОГО ИЛИ ОБА, оба выполняются так неизменноВ итоге я получаю:

bool synchHappened = false;
if(synchA.Checked)
{
  SynchA();
  synchHappened = true;
}
if(synchB.Checked)
{
  SynchB();
  synchHappened = true;
}
if(synchHappened)
{
  UpdateLastTime();
}

Этот последний шаг всегда беспокоит меня, потому что я распространяю этот бул на три ветви логики.

Есть ли какой-то очевидный лучший подход к вышеупомянутомулогика / сценарий, который я мог бы использовать?

Ответы [ 5 ]

3 голосов
/ 13 августа 2011

Основной целью было бы - каждый раз, когда логика изменялась - на код следует воздействовать, по крайней мере, насколько это возможно. Таким образом, вы должны структурировать такие вещи один раз, и тогда это будет работать для вас.

В вашем конкретном случае я бы предложил Keep It Simple (без Pattern Strategy и т. Д.), Поэтому извлеките и инкапсулируйте логику переключателей в свойствах.Таким образом, каждый раз, когда изменяются требования - вы должны обновлять либо логику конкретного коммутатора, либо саму основную логику.

Переключатели с инкапсулированными правилами:

bool IsUpdateLastTime
{
 get
 {
    // logic here even can be fully or partially injected 
    // as Func<bool>
    return this.IsSyncA || this.IsSyncB;
 }
}

bool IsSyncA { get { return synchA.Checked; } }
bool IsSyncB { get { return synchB.Checked; } }

Основная логика:

if (this.IsUpdateLastTime)
{
  this.UpdateLastTime();
}
2 голосов
/ 13 августа 2011

Можно считать этот шаблон более компактным (и, возможно, читабельным), хотя для него все еще требуется отдельная переменная.

bool syncHappened = false;
if(syncHappened |= synchA.Checked) SynchA();
if(syncHappened |= synchB.Checked) SynchB();
if(syncHappened) UpdateLastTime();
2 голосов
/ 13 августа 2011

Проблема такого рода в том, что Rx действительно полезно, так как вы можете объединить несколько событий в одно.Это можно сделать с помощью чего-то подобного.

(Предполагается, что winforms для этого примера похожи на WPF и т. Д., Просто изменив имена событий / общий тип arg для FromEvent.)

var synchAchecked = Observable.FromEvent<EventArgs>(synchA.CheckedChanged);
var synchBchecked = Observable.FromEvent<EventArgs>(synchB.CheckedChanged);
var merged = Observable.Merge(synchAchecked, synchBchecked);

synchAchecked.Subscribe(x => SynchA());
synchBchecked.Subscribe(x => SynchB());
merged.Subscribe(x => UpdateLastTime());
0 голосов
/ 13 августа 2011

Немного C, но:

if (checked_syncs & SYNC_A)
    SyncA();
if (checked_syncs & SYNC_B)
    SyncB();
if (checked_syncs)
    UpdateLastTime();

Преимущество этого в том, что последняя проверка не должна изменяться (если только у вас не заканчивается бит, в этом случае вы можете переключиться на больший примитивный тип или просто использовать более одного). Он также имеет преимущество, заключающееся в эффективном параллельном выполнении всех операций OR для UpdateLastTime (), поэтому это также быстрое решение.

ПРИМЕЧАНИЕ: Конечно, SYNC_A и SYNC_B должны быть уникальными степенями двойки, и да - это может немного нарушить вашу инкапсуляцию и предполагает, что вы можете | = условие, когда происходит проверка (может быть невозможно или выгодно по сравнению с установка логического значения, если вы говорите об определенном наборе инструментов GUI).

0 голосов
/ 13 августа 2011

Некоторым это может не понравиться, но я нахожу это очень полезным и чистым. Это немного странно, поэтому решение использовать это зависит только от вас.

UpdateLastTime(Either(SynchA(synchA.Checked), SynchB(synchB.Checked)));

private bool Either(bool first, bool second)
{
    return first || second;
}

Для этого необходимо изменить SynchA(), SynchB() и UpdateLastTime(), чтобы они не работали, если shouldRun имеет значение false, и возвращать значение true или false в зависимости от того, произошла синхронизация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...