Login
Оператор goto в языках программирования.
NEW 01.02.12 20:33
in Antwort swar0g 01.02.12 17:03
Функция не умещается на одну страницу => говнокод.
NEW 01.02.12 21:07
Разбей на сотню подфункций, а потом, если нужно что-то добавить-изменить-убрать - переписывай заново. Особенно как в этом примере, когда делается stack based unrolling - т.е. требуется откатить те шаги, которые уже были сделаны, если что не так.
Правило про функция на одну страницу - не абсолютно, иной раз надо взвешивать и сопоставлять выгоду и недостатки.
in Antwort Simple 01.02.12 20:33
В ответ на:
Функция не умещается на одну страницу => говнокод.
Функция не умещается на одну страницу => говнокод.
Разбей на сотню подфункций, а потом, если нужно что-то добавить-изменить-убрать - переписывай заново. Особенно как в этом примере, когда делается stack based unrolling - т.е. требуется откатить те шаги, которые уже были сделаны, если что не так.
Правило про функция на одну страницу - не абсолютно, иной раз надо взвешивать и сопоставлять выгоду и недостатки.
NEW 01.02.12 21:36
in Antwort swar0g 01.02.12 21:07
Разбей на сотню подфункций
------
На 100 - не надо. Но вот разделить три операции, плотненько перемешанных в функции,
- совсем не вредно. Тем более, что начальный шаг уже сделан - alloc_tty_struct() - выделена,
но не доведена до нормальности.
т.е. требуется откатить те шаги
-----
И кто мешает иметь корректную - free_tty_struct() - делающую именно корректный фрее?
если нужно что-то добавить-изменить-убрать - переписывай заново
-----
Разумеется! Синхронизировать указанную пару - в любом случае это придется делать...
Что существенно - так это чтобы не надо было переписывать init_dev() когда поменяется
что- то в tty&Co
------
На 100 - не надо. Но вот разделить три операции, плотненько перемешанных в функции,
- совсем не вредно. Тем более, что начальный шаг уже сделан - alloc_tty_struct() - выделена,
но не доведена до нормальности.
т.е. требуется откатить те шаги
-----
И кто мешает иметь корректную - free_tty_struct() - делающую именно корректный фрее?
если нужно что-то добавить-изменить-убрать - переписывай заново
-----
Разумеется! Синхронизировать указанную пару - в любом случае это придется делать...
Что существенно - так это чтобы не надо было переписывать init_dev() когда поменяется
что- то в tty&Co
NEW 02.02.12 11:01
Хорошо, что я не программирую на С
. Не в смысле функция плоха сама по себе, но...
Я не знаю общепринятых нотаций в С, но читать такой код с ходу тудно. Особенно, если не представляешь, о чем идет речь. Все имена построены на сокращениях и со стороны ни о чем не говорят. Если по условию встречается goto, то это не прокомментировано. Понятно, что тому, кто это писал, это понятно. Но со стороны не понятно, почему был совершен прыжок из основного кода. Каждый goto блок освобождает определенные ресурсы и вызывает return. Зачем для каждого return нужен goto? Почену return нельзя сразу вызвать с того места, где он нужен?
in Antwort swar0g 01.02.12 17:03
В ответ на:
Функция init_dev()
Функция init_dev()
Хорошо, что я не программирую на С

Я не знаю общепринятых нотаций в С, но читать такой код с ходу тудно. Особенно, если не представляешь, о чем идет речь. Все имена построены на сокращениях и со стороны ни о чем не говорят. Если по условию встречается goto, то это не прокомментировано. Понятно, что тому, кто это писал, это понятно. Но со стороны не понятно, почему был совершен прыжок из основного кода. Каждый goto блок освобождает определенные ресурсы и вызывает return. Зачем для каждого return нужен goto? Почену return нельзя сразу вызвать с того места, где он нужен?
NEW 02.02.12 11:34
ну да, если мы хотим наплодить ещё больше строк исходника, то это был бы самый правильный путь.
а когда надо будет что-то добавить или убрать, то править все функции и не дай если кто забыл какой-то указатель освободить. а так всё явно в одном месте.
в принципе, я так и знал, что кто-то будет из себя строить эксперта, абсолютно им не являясь
in Antwort Murr 01.02.12 21:36
В ответ на:
На 100 - не надо. Но вот разделить три операции, плотненько перемешанных в функции,
- совсем не вредно. Тем более, что начальный шаг уже сделан - alloc_tty_struct() - выделена,
но не доведена до нормальности.
На 100 - не надо. Но вот разделить три операции, плотненько перемешанных в функции,
- совсем не вредно. Тем более, что начальный шаг уже сделан - alloc_tty_struct() - выделена,
но не доведена до нормальности.
ну да, если мы хотим наплодить ещё больше строк исходника, то это был бы самый правильный путь.
а когда надо будет что-то добавить или убрать, то править все функции и не дай если кто забыл какой-то указатель освободить. а так всё явно в одном месте.
в принципе, я так и знал, что кто-то будет из себя строить эксперта, абсолютно им не являясь
NEW 02.02.12 11:55
swar0g, практически любое предложение по оптимизации имеет свои основания и если вы с основанием не согласны, то это не повод штамповать. Для меня, например, в моей области, на первом месте стоит читаемость кода. По возможности отсутствие повторяемости кусков кода. И где-то около последнего места количество строк исходника.
Я, например, очень даже соглашусь, что все мои идеи по оптимизации и ломаного гроша в той области, где применяется этот код и на том языке, на котором написан этот код, не стоят.
in Antwort swar0g 02.02.12 11:34
В ответ на:
в принципе, я так и знал, что кто-то будет из себя строить эксперта, абсолютно им не являясь
в принципе, я так и знал, что кто-то будет из себя строить эксперта, абсолютно им не являясь
swar0g, практически любое предложение по оптимизации имеет свои основания и если вы с основанием не согласны, то это не повод штамповать. Для меня, например, в моей области, на первом месте стоит читаемость кода. По возможности отсутствие повторяемости кусков кода. И где-то около последнего места количество строк исходника.
Я, например, очень даже соглашусь, что все мои идеи по оптимизации и ломаного гроша в той области, где применяется этот код и на том языке, на котором написан этот код, не стоят.
NEW 02.02.12 12:06
да не знаю, код нормально читается. обычный драйвер на си, то бишь его инициализация. если хоть один сам в своей жизни написал, то сходу понимаешь, что там делается. по-сути использование goto в том примере - это как уже правильно говорил господин simple - реализация отсутствующих в си эксепшенов. но в отличие от последних, goto позволяет довольно однозначно и стройно построить схему stack unrolling, т.е. когда нужно выполнение несколько зависящих друг от друга операций, а в случае ошибки откатывать операции в обратном порядке. в драйверах такое сплошь и рядом. инициализация оборудования, выделение памяти под структуры, инициализация структур и т.п. если в каком-то месте ошибка - откатывать именно пройденные операции.
do a
if (err) goto err_a
do b
if (err) goto err_b
do c
if (err) goto err_c
...
return
...
undo c
err_c:
undo b
err_b:
undo a
err_a:
return
драйвер пишут люди. куча разных людей. разработка для ядра, где недочёты более трагично отражаются на стабильности системы, чем разработка в юзерспейсе. использование дебаггера либо очень осложнено, либо невозможно. нужно заранее сделать логичный и читаемый код.
вот представим себе, что в теле функций десяток выходов. в случае, если к коду что-то добавили - то добавивший должен был бы в каждом выходе проставлять подчищение за своей добавкой. один return пропустить и не добавить подчистку не легко, а просто очень легко. а потом ищи на уровне ядра, где память текёт. если же выход из функции в одном месте, то и подчистка в любом случае будет автоматически соблюдена при до/переписывании функций.
в данном же примере сильно фанатично старались оставлять лишь один return. я бы в двух последних местах, где стоит goto end_init, тоже бы поставил return. но это в данном случае непринципиально.
in Antwort except 02.02.12 11:01
В ответ на:
Я не знаю общепринятых нотаций в С, но читать такой код с ходу тудно. Особенно, если не представляешь, о чем идет речь. Все имена построены на сокращениях и со стороны ни о чем не говорят. Если по условию встречается goto, то это не прокомментировано. Понятно, что тому, кто это писал, это понятно. Но со стороны не понятно, почему был совершен прыжок из основного кода. Каждый goto блок освобождает определенные ресурсы и вызывает return.
Я не знаю общепринятых нотаций в С, но читать такой код с ходу тудно. Особенно, если не представляешь, о чем идет речь. Все имена построены на сокращениях и со стороны ни о чем не говорят. Если по условию встречается goto, то это не прокомментировано. Понятно, что тому, кто это писал, это понятно. Но со стороны не понятно, почему был совершен прыжок из основного кода. Каждый goto блок освобождает определенные ресурсы и вызывает return.
да не знаю, код нормально читается. обычный драйвер на си, то бишь его инициализация. если хоть один сам в своей жизни написал, то сходу понимаешь, что там делается. по-сути использование goto в том примере - это как уже правильно говорил господин simple - реализация отсутствующих в си эксепшенов. но в отличие от последних, goto позволяет довольно однозначно и стройно построить схему stack unrolling, т.е. когда нужно выполнение несколько зависящих друг от друга операций, а в случае ошибки откатывать операции в обратном порядке. в драйверах такое сплошь и рядом. инициализация оборудования, выделение памяти под структуры, инициализация структур и т.п. если в каком-то месте ошибка - откатывать именно пройденные операции.
do a
if (err) goto err_a
do b
if (err) goto err_b
do c
if (err) goto err_c
...
return
...
undo c
err_c:
undo b
err_b:
undo a
err_a:
return
В ответ на:
Зачем для каждого return нужен goto? Почену return нельзя сразу вызвать с того места, где он нужен?]
Зачем для каждого return нужен goto? Почену return нельзя сразу вызвать с того места, где он нужен?]
драйвер пишут люди. куча разных людей. разработка для ядра, где недочёты более трагично отражаются на стабильности системы, чем разработка в юзерспейсе. использование дебаггера либо очень осложнено, либо невозможно. нужно заранее сделать логичный и читаемый код.
вот представим себе, что в теле функций десяток выходов. в случае, если к коду что-то добавили - то добавивший должен был бы в каждом выходе проставлять подчищение за своей добавкой. один return пропустить и не добавить подчистку не легко, а просто очень легко. а потом ищи на уровне ядра, где память текёт. если же выход из функции в одном месте, то и подчистка в любом случае будет автоматически соблюдена при до/переписывании функций.
в данном же примере сильно фанатично старались оставлять лишь один return. я бы в двух последних местах, где стоит goto end_init, тоже бы поставил return. но это в данном случае непринципиально.
NEW 02.02.12 12:22
в данном случае предложение по оптимизации не отражали реалий жизни. если бы разработчики изначально знали что писать, они естественно более стройно разбили код на нужные функции. а это кусок кода, который годами дополнялся, дописывался, изменялся, в зависимости от нужд, изменяющегося api, погоды, наличия месячных у жён разработчиков.
и тем более предложение по оптимизации уводило тему в оффтопик. я продемонстрировал кусок кода, где применение goto было приемлимым, необходимым, делало код более читаемым, даже не смотря на длину функции (я специально длинную выбирал). если бы код был бы разбит на более мелкие функции и именно init_dev была бы короче, это бы ни насколько не умаляло оправданность использования goto.
in Antwort except 02.02.12 11:55
В ответ на:
swar0g, практически любое предложение по оптимизации имеет свои основания и если вы с основанием не согласны, то это не повод штамповать. Для меня, например, в моей области, на первом месте стоит читаемость кода. По возможности отсутствие повторяемости кусков кода. И где-то около последнего места количество строк исходника.
swar0g, практически любое предложение по оптимизации имеет свои основания и если вы с основанием не согласны, то это не повод штамповать. Для меня, например, в моей области, на первом месте стоит читаемость кода. По возможности отсутствие повторяемости кусков кода. И где-то около последнего места количество строк исходника.
в данном случае предложение по оптимизации не отражали реалий жизни. если бы разработчики изначально знали что писать, они естественно более стройно разбили код на нужные функции. а это кусок кода, который годами дополнялся, дописывался, изменялся, в зависимости от нужд, изменяющегося api, погоды, наличия месячных у жён разработчиков.
и тем более предложение по оптимизации уводило тему в оффтопик. я продемонстрировал кусок кода, где применение goto было приемлимым, необходимым, делало код более читаемым, даже не смотря на длину функции (я специально длинную выбирал). если бы код был бы разбит на более мелкие функции и именно init_dev была бы короче, это бы ни насколько не умаляло оправданность использования goto.
NEW 02.02.12 12:51
in Antwort swar0g 02.02.12 12:06
В ответ на:
по-сути использование goto в том примере - это как уже правильно говорил господин simple - реализация отсутствующих в си эксепшенов. но в отличие от последних, goto позволяет довольно однозначно и стройно построить схему stack unrolling, т.е. когда нужно выполнение несколько зависящих друг от друга операций, а в случае ошибки откатывать операции в обратном порядке.
Че-то не пойму, в чем отличие. по-сути использование goto в том примере - это как уже правильно говорил господин simple - реализация отсутствующих в си эксепшенов. но в отличие от последних, goto позволяет довольно однозначно и стройно построить схему stack unrolling, т.е. когда нужно выполнение несколько зависящих друг от друга операций, а в случае ошибки откатывать операции в обратном порядке.
NEW 02.02.12 12:55
in Antwort swar0g 02.02.12 11:34
а так всё явно в одном месте.
------
У меня с одним из шефов был серьезный спор именно по данному вопросу.
Он мужик умный, но ему не всегда хватает времени сделать не как сделает,
а как надо сделать. И вот однажды он слепил что-то подобное...
Год оно глючило. Год Я просил его переписать, разделив смесь на компоненты.
Потом, когда больше делать было нечего, протрассировал что там делается.
Поправил с 10-к багов... и оставил глючить дальше.
Так что "всё явно в одном месте" при наличии более чем одной операции в
методе для меня аргументом не является.
Аргументом для меня будет следующее - есть методы:
- аллоцирования tty
- деаллоцирования tty
- подвязки tty к системе
- отвязки tty от системы
- валидации tty
и порядок их использования.
Если этих методов не хватит - опять таки посмотреть если среди требуемого
парные операции и так их и имплементировать. А танцы с бубном - нафиг-нафиг...
если мы хотим наплодить ещё больше строк исходник
-----
Количество строк уменьшится, если будет видна логика процесса и тот кто
пишет код понимает что он делает. На моей практике 29к сишного кода
ужались до 16 строк кода и таблицы с данными. При этом Я практически
ничего не сделал - только заменил написанный с использованием конструкций
языка автомат на его эквивалент в данных и простую процедуру изменения
состояния.
------
У меня с одним из шефов был серьезный спор именно по данному вопросу.
Он мужик умный, но ему не всегда хватает времени сделать не как сделает,
а как надо сделать. И вот однажды он слепил что-то подобное...
Год оно глючило. Год Я просил его переписать, разделив смесь на компоненты.
Потом, когда больше делать было нечего, протрассировал что там делается.
Поправил с 10-к багов... и оставил глючить дальше.
Так что "всё явно в одном месте" при наличии более чем одной операции в
методе для меня аргументом не является.
Аргументом для меня будет следующее - есть методы:
- аллоцирования tty
- деаллоцирования tty
- подвязки tty к системе
- отвязки tty от системы
- валидации tty
и порядок их использования.
Если этих методов не хватит - опять таки посмотреть если среди требуемого
парные операции и так их и имплементировать. А танцы с бубном - нафиг-нафиг...
если мы хотим наплодить ещё больше строк исходник
-----
Количество строк уменьшится, если будет видна логика процесса и тот кто
пишет код понимает что он делает. На моей практике 29к сишного кода
ужались до 16 строк кода и таблицы с данными. При этом Я практически
ничего не сделал - только заменил написанный с использованием конструкций
языка автомат на его эквивалент в данных и простую процедуру изменения
состояния.
NEW 02.02.12 13:05
in Antwort swar0g 02.02.12 12:06
если же выход из функции в одном месте, то и подчистка в любом случае будет автоматически соблюдена
-----
Эээ... как бы это сказать по проще, что одно из другого как бы не очень следует...
Ну наверное так - написал Я в произвольном месте переход на ретурн...
Ну а ты мне объяснишь как автоматически подчиститься память...
-----
Эээ... как бы это сказать по проще, что одно из другого как бы не очень следует...
Ну наверное так - написал Я в произвольном месте переход на ретурн...
Ну а ты мне объяснишь как автоматически подчиститься память...
NEW 02.02.12 13:40
В обсуждении слово "исключение" используется в двух смыслах:
1. как общий паттерн, когда нечто (ужасное, хотя и не обязательно) может случиться в разных местах, а обработчик нужен один. Это обсуждать довольно сложно, поскольку мы быстро доберемся до основ мироздания или из какого полупроводника компьютеры делают. В лучшем случае обсудим аспектно-ориентированное программирование.
2. как конкретная синтаксическая констукция современных языков (try-catch). Это, как уже было показано, это обобщение механизма возврата. В частности, возможность вернуть объекты разных типов, а потом при возврате фильтровать их по типу.
В данном примере (как и во многих подобных), goto это скорее общий ручной способ организовать процедуры (структуру), что, в частности, испльзуется для обработки особенных ситуаций (хотя ничего особенного в них конечно нет). Почему не объявить процедуры?
1. Это несколько дороже (что для драйверов важно).
2. Процедура ничего не должна знать о внешнем контексте (ведь ее могут вызвать откуда угодно). В Си это конечно легко обойти (что собственно и делается), но это будет нарушение логики, поэтому всю эту логику и забивают в одну длинную процедуру.
3. Процедура это уже совершенно конкретный способ работы со стеком, а значит других быть не должно быть. Если мы хотим сами ковыряться в стеке, то значит процедуры лучше не использовать. Если используем процедуры, то не надо работать со стеком вручну.
Я бы назвал это ручным управлением структурой стека, но при чем тут исключения? Это обычная логика почти любой программы. Что тут особенного? Что какое-то событие может произойти в разных частях, а обработать его (например, откатиться) хочется только в одной точке?
И почему ручной способ является однозначным и стройным? Если это ручное управление, то все зависит от того, кто написал. Один напишет криво, другой ровно. В этом и проблема goto (как и любых низкоуровневых операций), что он не гарантирует правильности и легко ведет к ошибкам.
Так что еще раз: goto не имеет большого отношения к исключениям. Исторически, раньше были только jmp, и все мыслили в терминах перехода. Соответственно, (дураки) его автоматически перетащили в новые высокоуровненвые языки в виде goto. А далее пришел Дейкстра и сказал, что все вокруг козлы и goto не нужел. Если бы это не был Дейкстра, то его бы забили камнями, поскольку это было как серпом по яйцам. Вот и все. А исключения здесь при том, что goto можно использовать, для ручной организации внутренней структуры программы (без структуризации с помощью процедур). А далее эта структура может использоваться для реализации определенных логических паттернов, типа когда обработчики ситуаций имеют лейблы, переход к которым осуществляется по goto из разных точек программы. Даже если мы назывем это механизмом исключений, то goto это всего лишь один из способов его реализации.
in Antwort swar0g 02.02.12 12:06
В ответ на:
... что там делается. по-сути использование goto в том примере - это как уже правильно говорил господин simple - реализация отсутствующих в си эксепшенов.
... что там делается. по-сути использование goto в том примере - это как уже правильно говорил господин simple - реализация отсутствующих в си эксепшенов.
В обсуждении слово "исключение" используется в двух смыслах:
1. как общий паттерн, когда нечто (ужасное, хотя и не обязательно) может случиться в разных местах, а обработчик нужен один. Это обсуждать довольно сложно, поскольку мы быстро доберемся до основ мироздания или из какого полупроводника компьютеры делают. В лучшем случае обсудим аспектно-ориентированное программирование.
2. как конкретная синтаксическая констукция современных языков (try-catch). Это, как уже было показано, это обобщение механизма возврата. В частности, возможность вернуть объекты разных типов, а потом при возврате фильтровать их по типу.
В данном примере (как и во многих подобных), goto это скорее общий ручной способ организовать процедуры (структуру), что, в частности, испльзуется для обработки особенных ситуаций (хотя ничего особенного в них конечно нет). Почему не объявить процедуры?
1. Это несколько дороже (что для драйверов важно).
2. Процедура ничего не должна знать о внешнем контексте (ведь ее могут вызвать откуда угодно). В Си это конечно легко обойти (что собственно и делается), но это будет нарушение логики, поэтому всю эту логику и забивают в одну длинную процедуру.
3. Процедура это уже совершенно конкретный способ работы со стеком, а значит других быть не должно быть. Если мы хотим сами ковыряться в стеке, то значит процедуры лучше не использовать. Если используем процедуры, то не надо работать со стеком вручну.
В ответ на:
... эксепшенов. но в отличие от последних, goto позволяет довольно однозначно и стройно построить схему stack unrolling, т.е. когда нужно выполнение несколько зависящих друг от друга операций, а в случае ошибки откатывать операции в обратном порядке.
... эксепшенов. но в отличие от последних, goto позволяет довольно однозначно и стройно построить схему stack unrolling, т.е. когда нужно выполнение несколько зависящих друг от друга операций, а в случае ошибки откатывать операции в обратном порядке.
Я бы назвал это ручным управлением структурой стека, но при чем тут исключения? Это обычная логика почти любой программы. Что тут особенного? Что какое-то событие может произойти в разных частях, а обработать его (например, откатиться) хочется только в одной точке?
И почему ручной способ является однозначным и стройным? Если это ручное управление, то все зависит от того, кто написал. Один напишет криво, другой ровно. В этом и проблема goto (как и любых низкоуровневых операций), что он не гарантирует правильности и легко ведет к ошибкам.
Так что еще раз: goto не имеет большого отношения к исключениям. Исторически, раньше были только jmp, и все мыслили в терминах перехода. Соответственно, (дураки) его автоматически перетащили в новые высокоуровненвые языки в виде goto. А далее пришел Дейкстра и сказал, что все вокруг козлы и goto не нужел. Если бы это не был Дейкстра, то его бы забили камнями, поскольку это было как серпом по яйцам. Вот и все. А исключения здесь при том, что goto можно использовать, для ручной организации внутренней структуры программы (без структуризации с помощью процедур). А далее эта структура может использоваться для реализации определенных логических паттернов, типа когда обработчики ситуаций имеют лейблы, переход к которым осуществляется по goto из разных точек программы. Даже если мы назывем это механизмом исключений, то goto это всего лишь один из способов его реализации.
NEW 02.02.12 13:44
Ну так это же просто песня!
in Antwort except 02.02.12 11:01
В ответ на:
Все имена построены на сокращениях и со стороны ни о чем не говорят. Если по условию встречается goto, то это не прокомментировано.
Все имена построены на сокращениях и со стороны ни о чем не говорят. Если по условию встречается goto, то это не прокомментировано.
Ну так это же просто песня!

NEW 02.02.12 13:50
навеяло. Братко, автор толстенного учебника по Прологу, в предисловии написал, что программы на Прологе похожи на стихи.
in Antwort svnv 02.02.12 13:44
В ответ на:
Ну так это же просто песня!
Ну так это же просто песня!
навеяло. Братко, автор толстенного учебника по Прологу, в предисловии написал, что программы на Прологе похожи на стихи.
NEW 02.02.12 13:58
in Antwort svnv 02.02.12 13:40
Столько написать, ничего при этом не сказав - тебе надо было становиться политиком! :-D
NEW 02.02.12 14:30
Столько прочитать, так ничего и не поняв - пора тебе в народ возвращаться! :-/
in Antwort Simple 02.02.12 13:58
В ответ на:
Столько написать, ничего при этом не сказав - тебе надо было становиться политиком! :-D
Столько написать, ничего при этом не сказав - тебе надо было становиться политиком! :-D
Столько прочитать, так ничего и не поняв - пора тебе в народ возвращаться! :-/
NEW 02.02.12 14:33
in Antwort digital.pilot 02.02.12 13:50
Девиз кодера - все, что с такими мучениями было написано, должно так же мучительно читаться
. Это по поводу отсутствия комментариев.
Я драйвера никогда не писал. Согласен, что многие особенности продиктованы условиями.

Я драйвера никогда не писал. Согласен, что многие особенности продиктованы условиями.
NEW 02.02.12 14:37
in Antwort except 02.02.12 14:33
Комментарии писать надо тоже уметь. Просто комментировать код - лучше бы таких комментариев не было.