Качество кода open-source
От: Lonely Dog Россия  
Дата: 22.05.08 15:53
Оценка: 6 (2) +4 :)
Привет!

Сразу же хочу сказать, что я свои выводы я сделал на основании просмотра одной open-source программы под названием PuTTY. Это виндовый клиент для SSH, Telnet и rlogin. Знаю, что он достаточно популярен.
Просматривая код я ловил себя на мысли, что это гавно лучше переписать чем попытаться понять, как оно работает.

Приведу несколько примеров:
1. Файл ssh.c
В начале файла есть несколько дефайнов:
/* Coroutine mechanics for the sillier bits of the code */
#define crBegin1    static int crLine = 0;
#define crBegin2    switch(crLine) { case 0:;
#define crBegin        crBegin1; crBegin2;
#define crFinish(z)    } crLine = 0; return (z)
#define crFinishV    } crLine = 0; return
#define crReturn(z)    \
    do {\
        crLine=__LINE__; return (z); case __LINE__:;\
    } while (0)
#define crReturnV    \
    do {\
        crLine=__LINE__; return; case __LINE__:;\
    } while (0)
#define crStop(z)    do{ crLine = 0; return (z); }while(0)
#define crStopV        do{ crLine = 0; return; }while(0)
#define crWaitUntil(c)    do { crReturn(0); } while (!(c))
#define crWaitUntilV(c)    do { crReturnV; } while (!(c))


Потом эти дефайны используются в коде следующим образом:
static int ssh1_rdpkt(unsigned char **data, int *datalen)
{
    struct rdpkt1_state_tag *st = &rdpkt1_state;

    crBegin;

  next_packet:

    pktin.type = 0;
    pktin.length = 0;

    for (st->i = st->len = 0; st->i < 4; st->i++) {
    while ((*datalen) == 0)
        crReturn(4 - st->i);
    st->len = (st->len << 8) + **data;
    (*data)++, (*datalen)--;
    }
    ...


Т.е., пришли в функцию, что-то сделали, и вышли, сохранив номер строки из которой мы вышли. В следующий раз мы продолжим выполнение с этого же места. Этот код не компилируется в студии если установлен режим сохранения отладочной информации Edit and continue. Выводится ошибка "case label not a constant" или типа того. Меняем эту настройу на что-нибудь другое, и все работает.
Как это поддерживать? Какой смысл в открытости кода, если поддерживать его могут только авторы?

2. В файле window.c приведена функция TranslateKey длиной в 800 строк! Это же убиться можно.
3. Мой любимый пример. Функция term_out из файла terminal.c. Она занимает 1830 строк. Там реализован какой-то офигенный конечный автомат. С какими-то вложенными состояниями и метками case вида:
           case 40:
             compatibility_level &= TM_VTXXX;
             break;
           case 41:
             compatibility_level = TM_PUTTY;
             break;
           case 42:
             compatibility_level = TM_SCOANSI;
             break;

или
               case 14:
            get_window_pixels(&x, &y);
            len = sprintf(buf, "\033[4;%d;%dt", x, y);
            ldisc_send(buf, len, 0);
            break;
               case 18:
            len = sprintf(buf, "\033[8;%d;%dt",
                     rows, cols);
            ldisc_send(buf, len, 0);


4. Также советую посмотреть на то, какое количество статических и глобальных переменных используется в этом коде.

Мне интересно, весь open-source написан так же или это мне так повезло?
Как при таком качестве кода они умудряются что-то разумное делать?
Re: Качество кода open-source
От: kuj  
Дата: 22.05.08 16:01
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Мне интересно, весь open-source написан так же или это мне так повезло?


Это Вы, батенька, еще индусского кода не пробовали.

OSS весь разный.
Re: Качество кода open-source
От: IT Россия linq2db.com
Дата: 22.05.08 16:12
Оценка: 2 (2) +8
Здравствуйте, Lonely Dog, Вы писали:

LD>Мне интересно, весь open-source написан так же или это мне так повезло?

LD>Как при таком качестве кода они умудряются что-то разумное делать?

Качество open-source кода абсолютно ничем не отличается от качества любого другого кода. Как и везде есть код хороший, есть не очень, есть откровенное дерьмо. Не думаю, что кривыми руками за деньги писать получится лучше, чем open-source.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Качество кода open-source
От: Cyberax Марс  
Дата: 22.05.08 16:14
Оценка: 5 (2)
Здравствуйте, Lonely Dog, Вы писали:

LD>Т.е., пришли в функцию, что-то сделали, и вышли, сохранив номер строки из которой мы вышли. В следующий раз мы продолжим выполнение с этого же места. Этот код не компилируется в студии если установлен режим сохранения отладочной информации Edit and continue. Выводится ошибка "case label not a constant" или типа того. Меняем эту настройу на что-нибудь другое, и все работает.

LD>Как это поддерживать? Какой смысл в открытости кода, если поддерживать его могут только авторы?
Нормально его поддерживают. Я вот Putty на GTK2 под Линукс помог перенести, сейчас пакет делаю (https://launchpad.net/putty2).

LD>2. В файле window.c приведена функция TranslateKey длиной в 800 строк! Это же убиться можно.

LD>3. Мой любимый пример. Функция term_out из файла terminal.c. Она занимает 1830 строк. Там реализован какой-то офигенный конечный автомат. С какими-то вложенными состояниями и метками case вида:
Используется подход с С coroutines, описаный вот здесь: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

Об этом, кстати, в их доке по разработке сказано.

LD>4. Также советую посмотреть на то, какое количество статических и глобальных переменных используется в этом коде.

Об этом там тоже сказано.
Sapienti sat!
Re: �������� ���� open-source
От: Roman Odaisky Украина  
Дата: 22.05.08 16:33
Оценка: 3 (1)
????????????, Lonely Dog, ?? ??????:

LD>1. ???? ssh.c

LD>? ?????? ????? ???? ????????? ????????:
LD>
LD>/* Coroutine mechanics for the sillier bits of the code */
LD>#define crBegin1    static int crLine = 0;
LD>#define crBegin2    switch(crLine) { case 0:;
LD>#define crBegin        crBegin1; crBegin2;
LD>#define crFinish(z)    } crLine = 0; return (z)
LD>#define crFinishV    } crLine = 0; return
LD>#define crReturn(z)    \
LD>    do {\
LD>        crLine=__LINE__; return (z); case __LINE__:;\
LD>    } while (0)
LD>#define crReturnV    \
LD>    do {\
LD>        crLine=__LINE__; return; case __LINE__:;\
LD>    } while (0)
LD>#define crStop(z)    do{ crLine = 0; return (z); }while(0)
LD>#define crStopV        do{ crLine = 0; return; }while(0)
LD>#define crWaitUntil(c)    do { crReturn(0); } while (!(c))
LD>#define crWaitUntilV(c)    do { crReturnV; } while (!(c))
LD>

Hands off the coroutines! This is the most beautiful implementation I?ve ever encountered! I?ve used a similar approach several times myself, as in:
#define COROUTINE static int _coroutineState = 0; switch(_coroutineState) case 0:
#define YIELD(_expr_) do { _coroutineState = __LINE__; return (_expr_); case __LINE__:; } while(0)

char nextMove() // this was from a TCMM
{
    COROUTINE
    {
        while(1)
        {
            assert(depth == 0);
 
            while(condition1)
            {
                YIELD('R');
            }
 
            YIELD('D');
 
            while(condition2)
            {
                YIELD('R');
            }
 
            YIELD('U');
        }
    }
}

If one calls nextMove() repeatedly, one would get something like RRRDRRURRRRRRRRDRURR... (the return value depends on the place where the function returned the previous time).

Sorry for the offtopic language, all I get when trying to post in Russian is krakozyabras.
До последнего не верил в пирамиду Лебедева.
Re: Качество кода open-source
От: superlexx  
Дата: 22.05.08 19:28
Оценка:
Здравствуйте, Lonely Dog, Вы писали:
LD> Этот код не компилируется в студии если установлен режим сохранения отладочной информации Edit and Continue. Выводится ошибка "case label not a constant" или типа того. Меняем эту настройу на что-нибудь другое, и все работает.

им просто надо было использовать __COUNTER__ вместо __LINE__ под MSVC. Сейчас навалял себе небольшой вспомогательный класс с __COUNTER__, очень понравилось. Практически получается C#-овский yield (не так же красиво, но всё-таки).
Re[2]: Качество кода open-source
От: Programador  
Дата: 22.05.08 20:19
Оценка:
Здравствуйте, superlexx, Вы писали:

S>им просто надо было использовать __COUNTER__ вместо __LINE__ под MSVC. Сейчас навалял себе небольшой вспомогательный класс с __COUNTER__, очень понравилось. Практически получается C#-овский yield (не так же красиво, но всё-таки).

__LINE__ при оладке может быть удобней чем __COUNTER__
Re[2]: �������� ���� open-source
От: Programador  
Дата: 22.05.08 20:27
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>????????????, Lonely Dog, ?? ??????:


че за �������� ���� глюки сегодня на сайте, и здесь http://www.rambler.ru/news/sport/0/562437840.html
в разных боузерах такие чудеса, наверно день плохой, или комп перегрузить?
Re: Качество кода open-source
От: Maxim S. Shatskih Россия  
Дата: 22.05.08 20:47
Оценка: 3 (2) +1 -3
LD> crLine=__LINE__; return (z); case __LINE__:;\

Жесть!

LD>Мне интересно, весь open-source написан так же или это мне так повезло?


Примерно так.

LD>Как при таком качестве кода они умудряются что-то разумное делать?


Видимо, высокое качество исходного кода не особо и нужно
Занимайтесь LoveCraftом, а не WarCraftом!
Re: Качество кода open-source
От: Константин Л.  
Дата: 22.05.08 21:23
Оценка: 3 (1)
Здравствуйте, Lonely Dog, Вы писали:

[]

имею дело с thunderbird. резюме — дерьмо. методы на 1500 строк в порядке вещей. свичи на 1500 строк в порядке вещей. написано просто грязно. как это работает я не представляю.
Re[2]: Качество кода open-source
От: Сергей  
Дата: 22.05.08 21:46
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

LD>>Мне интересно, весь open-source написан так же или это мне так повезло?


MSS>Примерно так.


Ты знаком со всем open-source кодом?
Re[2]: Качество кода open-source
От: Pzz Россия https://github.com/alexpevzner
Дата: 22.05.08 22:46
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Нормально его поддерживают. Я вот Putty на GTK2 под Линукс помог перенести, сейчас пакет делаю (https://launchpad.net/putty2).


А зачем он там нужен? Чем он лучше, чем сочетание вашего любимого эмулятора терминала с комманд-лайновым ssh клиентом?
Re[3]: GPuTTY
От: OCTAGRAM Россия http://octagram.name/
Дата: 22.05.08 23:55
Оценка:
Pzz пишет:
> Здравствуйте, Cyberax, Вы писали:
>
> C>Нормально его поддерживают. Я вот Putty на GTK2 под Линукс помог
> перенести, сейчас пакет делаю (https://launchpad.net/putty2).
>
> А зачем он там нужен? Чем он лучше, чем сочетание вашего любимого
> эмулятора терминала с комманд-лайновым ssh клиентом?
В команд–лайновом нужно помнить esc-последовательности, чтобы порты
форвардить. Ты вот их помнишь?

--
ISO/IEC 8652:1995/Amd 1:2007
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Качество кода open-source
От: Cyberax Марс  
Дата: 22.05.08 23:59
Оценка:
Здравствуйте, Pzz, Вы писали:

C>>Нормально его поддерживают. Я вот Putty на GTK2 под Линукс помог перенести, сейчас пакет делаю (https://launchpad.net/putty2).

Pzz>А зачем он там нужен? Чем он лучше, чем сочетание вашего любимого эмулятора терминала с комманд-лайновым ssh клиентом?
Putty удобнее. Например, есть killer feature — "duplicate session". Или гибкие и простые настройки терминала. Ещё удобное указание ключей.

А в обычном SSH мне приходилось делать кучу запускающих sh-файлов.
Sapienti sat!
Re[4]: Качество кода open-source
От: Pzz Россия https://github.com/alexpevzner
Дата: 23.05.08 00:08
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>>>Нормально его поддерживают. Я вот Putty на GTK2 под Линукс помог перенести, сейчас пакет делаю (https://launchpad.net/putty2).

Pzz>>А зачем он там нужен? Чем он лучше, чем сочетание вашего любимого эмулятора терминала с комманд-лайновым ssh клиентом?
C>Putty удобнее. Например, есть killer feature — "duplicate session". Или гибкие и простые настройки терминала. Ещё удобное указание ключей.

Если честно, мне он не показался очень-то удобным. Возможно, это дело вкуса.

Кроме того, я сильно сомневаюсь, что у него хороший эмулятор терминала. Собственно, хороших-то почти нет. Попробуйте прогнать на нем vttest из любопытства. Реально его более-менее полностью проходит только xterm и rxvt.

C>А в обычном SSH мне приходилось делать кучу запускающих sh-файлов.


У него есть файл с опциями.
Re[2]: Качество кода open-source
От: azzx Россия  
Дата: 23.05.08 03:21
Оценка: 2 (1)
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, Lonely Dog, Вы писали:


КЛ>[]


КЛ>имею дело с thunderbird. резюме — дерьмо. методы на 1500 строк в порядке вещей. свичи на 1500 строк в порядке вещей. написано просто грязно. как это работает я не представляю.


А они точно кодогенерацию не применяют нигде? У меня бывают в СПЕЦИФИЧЕСКИХ случаях такие методы — но всегда в том или ином варианте используется кодогенерация, ибо я не идиот это ручками поддерживать. Так что вся "поддержка" такого кода заключается в изменении настроек кодогенератора ( и не важно что это — список вызовов макросов в отдельном файле, Excel-таблица с макросами на VBA или действительно специально написанная программа).
Re: Качество кода open-source
От: SergeCpp Россия http://zoozahita.ru
Дата: 23.05.08 04:10
Оценка: 2 (1)
Здравствуйте, Lonely Dog!

LD>Сразу же хочу сказать, что я свои выводы я сделал на основании просмотра одной open-source программы...


Это ещё цветочки

Ягодки — вот тут
Автор: SergeCpp
Дата: 08.02.07
http://zoozahita.ruБездомные животные Екатеринбурга ищут хозяев
Re[3]: Качество кода open-source
От: Константин Л.  
Дата: 23.05.08 07:07
Оценка:
Здравствуйте, azzx, Вы писали:

A>Здравствуйте, Константин Л., Вы писали:


КЛ>>Здравствуйте, Lonely Dog, Вы писали:


КЛ>>[]


КЛ>>имею дело с thunderbird. резюме — дерьмо. методы на 1500 строк в порядке вещей. свичи на 1500 строк в порядке вещей. написано просто грязно. как это работает я не представляю.


A>А они точно кодогенерацию не применяют нигде? У меня бывают в СПЕЦИФИЧЕСКИХ случаях такие методы — но всегда в том или ином варианте используется кодогенерация, ибо я не идиот это ручками поддерживать. Так что вся "поддержка" такого кода заключается в изменении настроек кодогенератора ( и не важно что это — список вызовов макросов в отдельном файле, Excel-таблица с макросами на VBA или действительно специально написанная программа).


точно. там такие места, где нужно все руками (WndProc e.g.), да и оформлено так, что если захочешь не нагенеришь
Re[2]: Качество кода open-source
От: Lonely Dog Россия  
Дата: 23.05.08 07:15
Оценка: +1
Здравствуйте, Cyberax, Вы писали:

C>Нормально его поддерживают. Я вот Putty на GTK2 под Линукс помог перенести, сейчас пакет делаю (https://launchpad.net/putty2).

Ну не знаю. У меня голова опухла после одного дня копания в этом коде.


C>Используется подход с С coroutines, описаный вот здесь: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

C>Об этом, кстати, в их доке по разработке сказано.
Доку по разработке читал. Легче не стало. Как это отлаживать то? На code-review я бы вынес автора этого кода. Ему бы пришлось его переписывать полностью.
Re[2]: �������� ���� open-source
От: Lonely Dog Россия  
Дата: 23.05.08 07:16
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>If one calls nextMove() repeatedly, one would get something like RRRDRRURRRRRRRRDRURR... (the return value depends on the place where the function returned the previous time).

Неужели этого нельзя добиться менее грязным способом?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.