is_реклам:

пошук, категорії та ін. показати ▼

Багато return’ів і малі if’и

Багато return’ів і малі if’и
автор опубліковано

Ось ще кілька порад програмісту-початківцю з безцінної книги Ален И. Голуб. Правила программирования на Си и Си++ з дивною назвою "Веревка достаточной длины, чтобы выстрелить себе в ногу".

Функція має мати лише одну точку виходу

Це правило застосовне лише до програм на С. Взагалі, багато переходів goto до однієї точки виходу краще, ніж багато операторів return. Таким чином Ви можете розмістити точку переривання біля єдиної точки виходу, замість того, щоб мати справу з декількома перериваннями. Наприклад:

f()
{
	int значення_повернення = ПОМИЛКА;
	if ( деяка_умова )
	{
		// ...
		значення_повернення = ЩОСЬ;
		goto вихід;

	}
	else
	{
		// ...
		значення_повернення = ЩЕ_ЩОСЬ;
		goto вихід;
	}
	вихід:
		return значення_повернення;
}

Цей метод не спрацює в С++, тому що функції конструктора викликаються неявно в якості частини оголошення; оголошення часто приховує виклик функції. Якщо Ви пропускаєте оголошення, то Ви пропускаєте і виклик конструктора. Наприклад, в наступній програмі деструктор для х викличеться, а конструктор - ні:

foo()
{
	if ( деяка_умова )
		goto вихід;

	User_Class x;		// Конструктор не викликається. (Оператор
				// goto перескочить через нього. )

	вихід:
				// Тут викличеться деструктор для х
				// при виході х з області видимості.

Внаслідок цієї проблеми краще за все зовсім уникати переходів goto в програмах на С++.

Завжди передбачайте повернення значення із блоку зовнішнього рівня

Іноді, коли підпрограми короткі, не варто старатися забезпечити єдину точку виходу. Часто правило "уникати заплутаності" перекриває будь-яке інше правило, з яким воно входить в конфлікт. В цій ситуації завжди старайтесь переконатися, що з підпрограми немає таких шляхів, які не проходять через оператор return. Не так:

if ( a )
{
	// ...
	return роби_що_потрібно();
}
else
{
	// ...
	return ПОМИЛКА;
}

а так:

if ( a )
{
	// ...
	return роби_що_потрібно();
}
// ...
return ПОМИЛКА;

В ідеалі, вихід через помилку організується із зовнішнього рівня блоку так, щоб Ви правильно обробити неочікуваний аварійний вихід на зовнішній рівень.

Якщо оператор if закінчується оператором return, то не використовуйте else

Замість:

if ( умова )
	return xxx;
else
{
	code();
}

зазвичай краще записати:

if ( умова )
	return xxx;
code();

Краще зробити так, щоб останнім оператором return було аварійне повернення через помилку, так щоб Ви отримали повідомлення про помилку, якщо випадково загубились.

Умовний оператор також може вирішити цю проблему в простих ситуаціях і зробити код більш читабельним для новачка. Замість:

f()
{
	// ...
	if ( x )
		return 123;
	else if ( y )
		return 456;
	else
		return ERROR;
}

використовуйте:

f()
{
	// ...
	return x ? 123   :
	       y ? 456   :
		   ERROR ;
}

Зверніть увагу, наскільки форматування покращує читабельність попереднього коду.
Одна поширена ситуація, в якій у Вас є багато точок повернення, виглядає наступним чином:

if ( A )
	return FAIL;
else if ( B )
	return SUCCESS;
else
{
	// Багато коду
	return SUCCESS;   // Підозрілі два однакових
			  // значення повернення.
}

Ви можете цьому запобігти наступним чином. По-перше, позбавтесь від повтору значень повернення, перемістивши їх у зовнішній рівень таким чином:

if ( A )
	return FAIL;
else if ( B )
	;
else
{
	// Багато коду
}
return SUCCESS;

Потім позбавтеся від виклику if, пов'язаного з порожнім оператором

if ( A )
	return FAIL;
else if ( !B )
{
	// Багато коду
}
return SUCCESS;

Розташовуйте більш короткий блок умовного оператора if/else першим

Часто буває, що у оператора if/else одна частина коротка (зазвичай оператор для обробки помилки), а інша, яка відповідно виконує роботу, - більша:

if ( деяка_помилка() )
	error ( "AAAAxxxx!!!!!" );
else
{
	// Тут слідує 30 рядків коду
}

Завжди розташовуйте коротшу частину на початку. Тобто, не робіть так:

if ( !деяка_помилка() )
{
	// Тут слідує 30 рядків коду
}
else
	error ( "AAAAxxxx!!!!!" );

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

схоже за тегами

Коментарів 2

  1. Anna пише: Відповіcти

    обсуждаем чей-то код на работе:
    xxx: Так вы представляете, у него там фрагмент кода в 15 строк повторяется 37 раз. Если вынести в функцию можно сэкономить полтыщи строк!
    yyy: это припев. (c)

    По цьому принципу замість
    // Тут слідує 30 рядків коду
    потрібно написати
    //припев

    :)

Залишити коментар:

Яндекс цитирования UA TOP Bloggers