Я знаю, что вы спросили о GCD, но если вы хотите, NSOperationQueue
также обрабатывает этот материал действительно изящно, например :
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Starting 3");
}];
NSOperation *operation;
operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Starting 1");
sleep(7);
NSLog(@"Finishing 1");
}];
[completionOperation addDependency:operation];
[queue addOperation:operation];
operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Starting 2");
sleep(5);
NSLog(@"Finishing 2");
}];
[completionOperation addDependency:operation];
[queue addOperation:operation];
[queue addOperation:completionOperation];
По словам Стива МакКоннелла, автора Code Complete , вам следует
"Рассмотреть случай, который вы обычно ожидаете сначала процесс. Это соответствует общий принцип размещения кода что является результатом решения как можно ближе по возможности к решению ... [ положить нормальный случай после if ] ставит сосредоточьтесь на чтении основного потока, а чем пробираться через исключительное случаях, поэтому код легче читать в целом. "
Код завершен , 2-е издание, страницы 356-357.
Используйте наиболее читаемую версию для вашего конкретного случая и, кстати, не сравнивайте логическое выражение с истинным и ложным. Используйте условие
и Не условие
(! Условие
в C #.)
if (condition == true) // bad
if (condition) // better
В окончательной сборке / машинном коде это имеет значение. Оператор, который, скорее всего, будет выполнен, выполняется в пути без ветки. Таким образом, конвейер не прерывается, что приводит к потере ценных циклов.
Я понятия не имею, оставляет ли компилятор порядок операторов if then нетронутым и таким образом заставляет сборку использовать этот оптимизированный маршрут.
У меня есть прочтите, что Visual Studio 2008 (когда было объявлено) будет иметь функцию оптимизации, при которой компилятор добавляет измерения в ветвях, а затем во время выполнения измеряет, как часто используется Certian-путь. Затем при последующих перекомпилях предпочтение отдается наиболее оптимальному пути кода.
Я не имею ни малейшего понятия, прошла ли эта функция когда-либо «фазу проектирования / обучения»
Прежде всего, вы не должны сравнивать с логическими значениями, это делать
if condition then
вместо
if condition = true then
Что касается вашего вопроса, это зависит от естественных имен переменных, IMO.
Например, если вы создаете клиента, которому необходимо проверить, подключен ли он (наиболее частый случай)
if connected then
//Proceed
else
//Throw error
end if
Или, если вы создаете другую программу, где у вас есть переменная, скажем, полученная, и вы хотите знать, был ли получен контент
if not retrieved then
//Error
end if
Не делать
if retrieved then
else
//Error
end if
Обычно я всегда ставлю на первое место истинное предложение. Что-то вроде этого для меня запутывает смысл:
If not something Then
'do something 1
Else
'do something 2
End If
Это приводит к двойному отрицательному результату, гораздо лучше написать это так:
If something Then
'do something 2
Else
'do something 1
End If
Я считаю, что эта рекомендация исходит из завершенного кода. Отличная книга, которую стоит прочитать
Если у вас будет больше одной книги, то, возможно, будет лучше рассмотреть вариант случая.
Как говорили другие, удобочитаемость обычно более важна. Однако для разных людей удобочитаемость означает разные вещи.
Для меня это обычно означает такую организацию оператора if так, чтобы сначала было более короткое действие (с точки зрения строк кода), так что если оператор находится в нижней части окна I '
Используйте то, что упрощает чтение кода. Обычно это второй из ваших вариантов.
Редактировать
Во многих случаях это зависит от того, чего вы пытаетесь достичь, например, если вы хотите проверить правильность запуска соединения:
Connect()
if connected then
SendString("Hello!")
else
FlagConnectionFailed()
endif
Если вы хотите поймать ошибку:
' Just about to send something
if not connected then
FlagConnectionLost()
return
endif
SendString("Still connected!")
Но вы можете даже захотеть:
Disconnect()
if not connected then
return "Complete"
else
FlagConnectionDisconnectFailure()
endif
(Я не программист VB, поэтому синтаксис выше в значительной степени придуман!)
Второй вариант - наиболее распространенный. сначала действие.
Это упрощает чтение кода, поскольку вы не отвлекся на код для менее используемого / исключительного случая.
Если наиболее частый случай не так просто выразить, у вас может быть возможность для повторного факторинга
Один полезный повторный факторинг, который я нашел:
if (a.getFoo() == 1 && a.getBar() == 2)
может быть преобразован в
if (a.isFooBar())
В некоторых случаях нечто вроде этого может быть
if (!(fooSet.contains(a.getValidFoo())))
может быть
if (a.hasInvalidFoo(fooSet))
Это может сделать вариант 1 также вариантом 2 за счет упрощения оценки наиболее распространенного состояния.
Вы уже получили неплохие ответы. Я собираюсь подойти к этому вопросу с другой стороны.
Во-первых, что касается производительности, она может не иметь такого большого значения, как вы думаете в современных процессорах. Это потому, что они используют функцию, называемую предсказанием ветвления, в которой ЦП пытается предсказать наиболее вероятное направление, в котором пойдет код. Конечно, я по-прежнему согласен с тем, что вы должны размещать наиболее вероятную ветвь вверху, если производительность является вашей основной заботой.
Во-вторых, я предпочитаю удобочитаемость банальному повышению производительности. В большинстве случаев преимущества удобочитаемости перевешивают преимущества производительности.
В-третьих, по возможности используйте защитные предложения . Это делает код более читабельным.