S>Согласен целиком и полностью. Но этож рсдн, слово мимо — вэлкам в холивар
Один пример с свитчем я привёл выше, ну и вариант с "срезанием углов", куда без него:
S>S>// псевдокод
S>bool IsValid(SomeObject x)
S>{
S> if (x == null) return false;
S> if (cache.Contains(x)) return true;
S> if (x.State == State.Raw) return false;
S> // тут собственно проверка
S>}
S>
Это прекрасно трансформируется в
bool IsValid(SomeObject x) {
return x != null
&& cache.Contains(x)
&& x.State != State.Raw
&& validate(x)
}
bool validate(SomeObject x) {
// собственно проверка
}
Здравствуйте, Mamut, Вы писали:
S>>Согласен целиком и полностью. Но этож рсдн, слово мимо — вэлкам в холивар
Один пример с свитчем я привёл выше, ну и вариант с "срезанием углов", куда без него:
M>Это прекрасно трансформируется в
bool IsValid(SomeObject x) {
return x != null
&& cache.Contains(x)
&& x.State != State.Raw
&& validate(x)
}
Я узнал тебя, синтаксичейский_оверхед
Если проверки совсем простые — да, конечно. Но не всё так однозначно, логически несвязанные проверки лучше разделять.
А то видел несколько раз примерно такую цепочку:
1. Убираем "x != null", т.к. "cache.Contains(x)" один фиг не сработает
2. "cache.Contains(x)" внезапно срабатывает. Понятно, что в настоящем коде проверка другая, вспоминать лень, да и не важно. Допустим, в конкретно этом кэше вместо null отдаётся синглтон.
3. Возвращаем, разделяем проверку на несколько частей, для гарантии добавляем комментарий
M>>Это прекрасно трансформируется в
| | Скрытый текст |
| | S>S>bool IsValid(SomeObject x) {
S> return x != null
S> && cache.Contains(x)
S> && x.State != State.Raw
S> && validate(x)
S>}
S>
|
| | |
S>Я узнал тебя, синтаксичейский_оверхед
S>Если проверки совсем простые — да, конечно. Но не всё так однозначно, логически несвязанные проверки лучше разделять.
Ну, понятно, что то надо покрывать тестами и т.п. Я лично сам не против многоразовых return'ов, если функции короткие, и они видны сразу.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Во времена оные был полезный совет : у функции (тогда еще не было классов) должен быть один вход и один выход.
И корни его как раз в Фортране и в Ассемблере. Они оба позволяли, грубо говоря, иметь в одной функции несколько точек входа, плюс возвращать управление эта функция могла не только в вызвавший ее код, но и в совершенно другое место. См.
тут, "ENTRY Statement" и "Alternate RETURN".
Ну и в неуправляемых языках множественные return'ы были чреваты утечками ресурсов.
В нынешних реалиях (управляемые языки и всякие ARC'и с RAII) множественные return'ы совершенно не страшны и позволяют получать гораздо более читабельный код.
Здравствуйте, AndrewVK, Вы писали:
PD>>Конечно, при этом могут получиться if-else чудовищной вложеннности.
AVK>И это что, ты считаешь нормальным?
Вложенные IF-ы всегда можно сделать плоскими, и заменить на эквивалентную последовательность одноуровневых IF-ов
Например,
if(C1)
...
if(C2)
...
if(C3)
else
else
...
if(C4)
else
else
...
if(C5)
else
преобразуется в
простейшем случае в нечто подобное
if( C1 )
...
if( C1 & C2 )
...
if( C1 & !C2 )
...
if( C1 & C2 & C3 )
...
if( C1 & C2 & C4 )
...
if( !C1 )
...
if( C5 )
...
// лень писать все варианты :)
Здравствуйте, Нахлобуч, Вы писали:
Н>И корни его как раз в Фортране и в Ассемблере. Они оба позволяли, грубо говоря, иметь в одной функции несколько точек входа, плюс возвращать управление эта функция могла не только в вызвавший ее код, но и в совершенно другое место. См. тут, "ENTRY Statement" и "Alternate RETURN".
И несмотря ни на что, Фортран forever.

Справедливости ради отмечу, что применялись эти штуки крайне редко. Я в свое время довольно много кода на Фортране перелопатил,
ENTRY несколько раз встретил.
Alternate RETURN я не видел никогда. Что там говорить, вычисляемый
GOTO я видел лишь однажды, копая код какой-то библиотеки.