Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > если нужно сделать функцию, возвращающую bool


Автор: Alek86 22.2.2008, 14:31
данный опрос возник, из-за долгого спора, как лучше поступать в данном случае.
Во всех вариантах, имхо, можно найти и плюсы и минусы.
Если что есть сказать по этому поводу (к примеру, свой вариант) - прошу

Автор: Earnest 22.2.2008, 14:42
Чушь это - пытаться предусмотреть заранее всевозможные изменений требований.
Если по логике вещей программа должна возвращать bool (т.е. одну из альтернатив) - возвращай bool.
Если значений вроде может быть больше, хотя сейчас только 2 - то enum.
При нормальном имени функции и хорошем дизайне - изменить определение функции и ее использование - полчаса работы + сколько нужно для перекомпиляции проекта.
И вообще, нужно решать проблемы по мере поступления, а не пытаться общую теорию всего соорудить.
Что касается 3 последних вариантов - это просто абсурд и конец ООП.

Автор: Alek86 22.2.2008, 14:49
Цитата(Earnest @  22.2.2008,  14:42 Найти цитируемый пост)
При нормальном имени функции и хорошем дизайне - изменить определение функции и ее использование - полчаса работы + сколько нужно для перекомпиляции проекта.

в случае энама это 1 минута работы + сколько нужно для перекомпиляции проекта
но енамы плодить вредно, потому и опрос создал


интересно, чем 3й вариант не понравился... зачем же еще исключения?

Автор: bel_nikita 22.2.2008, 14:58
Все уже придумано до нас smile
Код

#define TRUE 1
#define FALSE 0
typedef int BOOL;

BOOL SomeFunction()
{
  return TRUE;
}


З.Ы.: А ваще, прежде чем что-то писать, нужно хорошенько все продумать и алгоритм нарисовать на бумаге ( а лучше использовать UML ). Тогда такие споры и вопросы отпадут сами по себе

Автор: Earnest 22.2.2008, 15:26
Цитата(Alek86 @  22.2.2008,  15:49 Найти цитируемый пост)
интересно, чем 3й вариант не понравился... зачем же еще исключения?

Исключения нужны для обработки нештатных ситуаций, возникающих  во время работы программы, а не во время разработки оттого что программист что-то забыл. Для того, чтобы чего-нибудь не забыть при изменениях, есть ASSERTы, времени выполнения или времени компиляции.
А насчет enum, когда по смыслу предполагается альтернатива... это все равно, что на вопрос, требующий четкого ответа да\нет отвечать "ну, вы понимаете, в некотором смысле, если конечно, ..."

Кстати, при расширении списка возвращаемых значений все равно нужно убедиться, что вызывающий код корректно обработает все варианты. Т.е. туда тоже сходить надо.

Автор: Lazin 22.2.2008, 15:29
возврат bool или enum - это абсолютно разная семантика, если ф-я должна ответить на простой вопрос - да или нет, то - bool -если ответить на более сложный (например описать состояние объекта, который на данном этапе может быть в 2х состояниях, но потом их может прибавица) - тогда enum.))

Автор: Alek86 22.2.2008, 15:41
спецально для идеалистов. Ситуация:

есть функция, которая делает импорт файла. возвращает bool - сделала или нет

и тут, оказывается, что потребовалась возможность дать юзеру прервать импорт. Ну, и иногда нужно знать. была ошибка или юзер остановил професс. Получается, что нужно менять прототип функции, перекомпиливать ВСЕ проекты (функция библиотечная, да и проекты немелкие), поскольку она вызывается не раз и не два.

Кто виноват? Ведь разработчик свою задачу сделал - написал функцию, которая возвращает даже, получилось ли импортировать файл.
Что делать? Вариант с throw не подходит, так как это не ошибка, да и заставлять дописывать везде try catch нет желания


Тут волей-неволей даже о 4м варианте задумаешься...

Автор: marcusmae 22.2.2008, 15:59
Alek86, это очень специфический пример. Полагаю, что возможность прерывания составной операции будет реализована через Thread-ы c событиями. Если так, то наша BOOL Name (/* arguments */) уходит глубоко в пучину вызовов, а точкой доступа для пользователя будет какая-то новая обёрточная функция, заключающая в себе весь новоиспечённый механизм. То есть, была функция - понадобилось её расширить, не трогая её кода - сделали обёртку-фасад. И дело с концом. В более простых случаях Name может даже заинлайнится.

Автор: Lazin 22.2.2008, 16:11
Цитата(Alek86 @  22.2.2008,  15:41 Найти цитируемый пост)
есть функция, которая делает импорт файла. возвращает bool - сделала или нет

нужно использовать исключение
Цитата(Alek86 @  22.2.2008,  15:41 Найти цитируемый пост)
и тут, оказывается, что потребовалась возможность дать юзеру прервать импорт.

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

bool do_part_of_whole_job();
...
while ( do_part_of_whole_job () ) {
  ..проверка - не нужно-ли прервать выполнение?
}

Автор: Alek86 22.2.2008, 16:11
Цитата(marcusmae @  22.2.2008,  15:59 Найти цитируемый пост)
понадобилось её расширить, не трогая её кода

тут наоборот: понадобилось изменить код - пожалуйста.
А трогать "интерфейс" - ох как больно...


1. получается, что в библиотечных функциях лучше bool не возвращать. Ибо потом скажется. И чем это "потом" будет позднее, тем хуже.
2. второй вариант плох только тем, что плодит лишние типы? или есть что-то, чего я не заметил?
3. еще интересно услышать, как определить, будет функция возвращать "одну из 2х альтернатив" или "одну из n альтернатив"?

Автор: Lazin 22.2.2008, 16:12
ну и работать весь этот огород должен в соседнем потоке))

Автор: Alek86 22.2.2008, 16:14
Lazin, не совсем так.
та библиотечная функция теперь и должна реализовывать такое поведение
а вот изменение интерфейса (и очень много перекомпиляции) как раз из-за того, что разработчик посчитал:
Цитата(Earnest @  22.2.2008,  14:42 Найти цитируемый пост)
Если по логике вещей программа должна возвращать bool (т.е. одну из альтернатив) - возвращай bool.



Цитата(Lazin @  22.2.2008,  16:11 Найти цитируемый пост)
нужно использовать исключение

можно подробней? где именно?

Автор: Lazin 22.2.2008, 16:25
Цитата(Alek86 @  22.2.2008,  16:14 Найти цитируемый пост)
можно подробней? где именно? 

вот здесь
Цитата(Alek86 @  22.2.2008,  15:41 Найти цитируемый пост)
есть функция, которая делает импорт файла. возвращает bool - сделала или нет

если не сделала, значит исключение - ошибка импорта

Цитата(Alek86 @  22.2.2008,  16:14 Найти цитируемый пост)
та библиотечная функция теперь и должна реализовывать такое поведение
а вот изменение интерфейса (и очень много перекомпиляции) как раз из-за того, что разработчик посчитал:
Цитата(Earnest @  22.2.2008,  14:42 Найти цитируемый пост)
Если по логике вещей программа должна возвращать bool (т.е. одну из альтернатив) - возвращай bool.

разработчик правильно посчитал, функция в первом случае(делает весь импорт сразу) и во втором(делает импорт по частям), имеют разную семантику, они не могут вызываться одинаково, и не могут быть заменены одна на другую. Здесь возвращаемое значение вообще не причем.
а сделал-бы я так:
Код

class Importer
{
bool do_part_of_whole_job();

void do_whole_job()
 {
   while ( do_part_of_whole_job() );
 }

}; 


Автор: Mayk 22.2.2008, 16:29
Цитата(Alek86 @  22.2.2008,  20:11 Найти цитируемый пост)
А трогать "интерфейс" - ох как больно...

Мне кажется речь  о том чтобы а) сделать ф-цию myCoolLibraryFunctionEx которая возвращает enum б) реализовать ф-цию myCoolLibraryFunction примерно как
Код

/// Return true iff completed successfully.
bool myCoolLibraryFunction(int argc, char**argv){
 return myCoolLibraryFunctionEx(argc, argv) == WorkCompleted;
}

в) наслаждаться жизнью без перекомпиляции проектов.
Цитата(Alek86 @  22.2.2008,  20:11 Найти цитируемый пост)

1. получается, что в библиотечных функциях лучше bool не возвращать. Ибо потом скажется. И чем это "потом" будет позднее, тем хуже.

Ой ли?
Код

// java.lang.String
    /**
     * Tests if this string starts with the specified prefix.
     *
     * @param   prefix   the prefix.
     * @return  <code>true</code> if the character sequence represented by the
     *          argument is a prefix of the character sequence represented by
     *          this string; <code>false</code> otherwise.
     *          Note also that <code>true</code> will be returned if the
     *          argument is an empty string or is equal to this
     *          <code>String</code> object as determined by the
     *          {@link #equals(Object)} method.
     * @since   1. 0
     */
    public boolean startsWith(String prefix) {
    return startsWith(prefix, 0);
    }
 
на что тут boolean заменять? FileNotFound добавлять?

Автор: marcusmae 22.2.2008, 16:34
Цитата(Alek86 @  22.2.2008,  16:11 Найти цитируемый пост)
тут наоборот: понадобилось изменить код - пожалуйста.А трогать "интерфейс" - ох как больно...


Alek86, ну а не надо трогать интерфейс! Пусть себе живёт простая и счастливая bool Name() в том виде, как она сделана - без турбо-двигателя, нитро и спойлеров. А новый фасад, может, будет реализовывать расширенный или совсем другой интерфейс на её основе. Вам же проще будет. И почему никому не пришло в голову char и wchar_t сварить некоторое квази-общее представление, так сказать РАСШИРИТЬ char до wchar_t..? smile Вместо этого многие системные вызовы существуют в двух вариантах - с постфиксами A и W.

Автор: Mayk 22.2.2008, 16:35
Цитата(Earnest @  22.2.2008,  18:42 Найти цитируемый пост)
Что касается 3 последних вариантов - это просто абсурд и конец ООП. 

Цитата

Все равно bool, а все, что потом может добавиться - это ошибки - их записываю в глобальную переменную, а потом, если надо, юзер использует мой GetLastError().

имхо that depends. Если ф-ция принадлежит какому-либо классу, то от ООП не убудет если в этот же класс ввести "interruptionReason()"/"wasInteruptedByUser()".
Если же она не принадлежит классу, то ООП уже был мёртв  smile 

Автор: marcusmae 22.2.2008, 16:39
поддерживаю тз Mayk-а.

Автор: Alek86 22.2.2008, 16:45
Lazin, Mayk, почти убедили smile

правда значит есть еще один вариант - возвращать bool, но под тайпдефом

ибо когда в логике много отаких от булов, очень удобно, когда компилятор вместо тебя следит, чтобы в функцию
Код

typedef bool IsRed;
typedef bool IsRound;
void func(IsRed i_is_red, IsRound i_is_round);

передаваются результаты функций
Код

IsRed Red();
IsRound Round();

именно в том порядке, в каком нужно

Автор: Mayk 22.2.2008, 17:08
Цитата(Alek86 @  22.2.2008,  20:45 Найти цитируемый пост)
1:
2:
3:
    
typedef bool IsRed;
typedef bool IsRound;
void func(IsRed i_is_red, IsRound i_is_round);

передаваются результаты функций
Выделить всёкод C++
1:
2:
    
IsRed Red();
IsRound Round();

именно в том порядке, в каком нужно

Так ведь фокус в том что не следит.
Код

typedef bool IsRed;
typedef bool IsRound;
void f( IsRed r, IsRound rr );
int main(){
    IsRed red;
    IsRound round;
    f( round, red ); //съедаеццо
}

хотя в данном примере разумеццо следует делать структуры/enum'ы Color и Shape.

Автор: JackYF 22.2.2008, 17:33
bel_nikita, не поддерживаю, костыль, имхо.

Первый вариант, конечно же.

Автор: marcusmae 22.2.2008, 18:55
JackYF, если что

Код

typedef int BOOL


- это в WINAPI так сделано.

Автор: Alek86 22.2.2008, 18:57
Цитата(marcusmae @  22.2.2008,  18:55 Найти цитируемый пост)
- это в WINAPI так сделано.

то есть чистые C


Mayk, и правда
тогда только енамы smile

Автор: JackYF 22.2.2008, 22:01
Цитата(marcusmae @  22.2.2008,  17:55 Найти цитируемый пост)
это в WINAPI так сделано. 

я WinAPI не уважаю.

Автор: Lazin 22.2.2008, 23:45
Цитата(marcusmae @  22.2.2008,  18:55 Найти цитируемый пост)
это в WINAPI так сделано. 

там так сделано для совместимости с Си, в котором нет bool  smile 

Автор: MAKCim 22.2.2008, 23:52
Цитата(Lazin @  22.2.2008,  23:45 Найти цитируемый пост)
там так сделано для совместимости с Си, в котором нет bool

смотря какая версия С рассматривается  smile 
Цитата(JackYF @  22.2.2008,  22:01 Найти цитируемый пост)
я WinAPI не уважаю.

чего так?

Автор: JackYF 23.2.2008, 00:04
 smile 
Цитата(MAKCim @  22.2.2008,  22:52 Найти цитируемый пост)
чего так? 

так получилось (с)  smile Костылей много. И за макросы типа LPSCWTSTR.

Помню, прикол был... есть функция API, которая возвращает список сетевых адаптеров... так вот, порядок выдачи самих адаптеров определялся настройкой из гуя в експлорере, что чётко записано в MSDN. Я долго недоумевал...

Автор: MAKCim 23.2.2008, 00:08
 smile 
JackYF, 
ясно
для меня в WinAPI букаф много, пальцы болят  smile 

Автор: vadiml 26.2.2008, 20:58
проголосовал за enum, хотя именно в С на такие грабли не наступал, а вот в базах данных -- несколько раз было, теперь там использую только int

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)