OberonCore https://forum.oberoncore.ru/ |
|
Именование переменных https://forum.oberoncore.ru/viewtopic.php?f=27&t=3089 |
Страница 1 из 2 |
Автор: | Андрей [ Понедельник, 20 Декабрь, 2010 23:26 ] |
Заголовок сообщения: | Именование переменных |
Давно уже заметил у Илья Ермакова и некоторых других необычную манеру именования переменных. Сейчас обратил на это внимание вновь, просматривая коды из раздела wiki на сайте. На мой взгляд, слишком короткие имена переменных ухудшают читабельность кода. В чём причина такого подхода? Чтобы не быть голословным, вот пример даже не самой плохой в этом смысле функции: Код: PROCEDURE (rd: StdReader) SetPos (t: INTEGER); VAR p1, p2: Page; BEGIN ASSERT((t >= 0), 20); p2 := rd.base.first; WHILE (p2 # NIL) & (p2.t[p2.n-1] < t) DO p1 := p2; p2 := p2.next END; (* Post: (p1 = NIL) OR (p1.t[last] < t), (p2 = NIL) OR (t <= p2.t[last]), (p1 # NIL) OR (p2 # NIL) ==> Post: (p1 = NIL) & (p2 # NIL) & (t <= p2.t[last]) OR (p1 # NIL) & (p2 # NIL) & (p1.t[last] < t) & (t <= p2.t[last]) OR (p1 # NIL) & (p2 = NIL) & (p1.t[last] < t) *) IF p1 = NIL THEN rd.page := p2; rd.n := LookAtPage(p2, t); ELSIF p2 # NIL THEN IF t >= p2.t[p2.n-1] THEN rd.page := p2; rd.n := LookAtPage(p2, t) ELSE rd.page := p1; rd.n := pageSize-1 END ELSE rd.page := p1; rd.n := pageSize END; ExtractIt(rd) END SetPos; Почему бы не писать таким образом, чтобы названия переменных отражали их смысл? Тем более для примеров\учебных пособий. Для и для работы очень полезно. Вот, например, та же функция ( имена могли быть поняты неверно, просто чтобы сравнить два варианта ): Код: PROCEDURE (reader: StdReader) SetPosition (time: INTEGER);
VAR page1, page2: Page; BEGIN ASSERT((time >= 0), 20); page2 := reader.base.first; WHILE (page2 # NIL) & (page2.time[page2.num-1] < time) DO page1 := page2; page2 := page2.next END; (* Post: (page1 = NIL) OR (page1.time[last] < time), (page2 = NIL) OR (time <= page2.time[last]), (page1 # NIL) OR (page2 # NIL) ==> Post: (page1 = NIL) & (page2 # NIL) & (time <= page2.time[last]) OR (page1 # NIL) & (page2 # NIL) & (page1.time[last] < time) & (time <= page2.time[last]) OR (page1 # NIL) & (page2 = NIL) & (page1.time[last] < time) *) IF page1 = NIL THEN reader.page := p2; reader.num := LookAtPage(page2, time); ELSIF page2 # NIL THEN IF time >= page2.time[page2.num-1] THEN reader.page := page2; reader.num := LookAtPage(page2, time) ELSE reader.page := page1; reader.num := pageSize-1 END ELSE reader.page := page1; reader.num := pageSize END; ExtractIt(reader) END SetPosition; |
Автор: | Пётр Кушнир [ Вторник, 21 Декабрь, 2010 00:52 ] |
Заголовок сообщения: | Re: Именование переменных |
но ведь сам факт того, что ты написал их(имён) полный вариант свидетельствует об их понятности. |
Автор: | Александр Ильин [ Вторник, 21 Декабрь, 2010 04:17 ] |
Заголовок сообщения: | Re: Именование переменных |
Согласен с Андреем. Чрезмерное сокращение имён переменных вижу повсеместно в исходниках на Обероне. С именами процедур и типами обычно всё в порядке. Локальные переменные простительны, если используются стандартные буквы (i - INTEGER, s - строка и т.п.). Но параметры процедур и поля записей в одну-две буквы не способствуют чтению, это точно. Я всегда для них использую одно или два полных слова, иногда сокращение (prev вместо previous, res вместо result и т.п.). |
Автор: | Александр Ильин [ Вторник, 21 Декабрь, 2010 04:18 ] |
Заголовок сообщения: | Re: Именование переменных |
Пётр Кушнир писал(а): но ведь сам факт того, что ты написал их(имён) полный вариант свидетельствует об их понятности. Речь не о понятности.
|
Автор: | adva [ Вторник, 21 Декабрь, 2010 10:00 ] |
Заголовок сообщения: | Re: Именование переменных |
вот еще одна причина, по которой автокомплит не помешает. Если бы его не было в других средах, то там бы тоже наверняка сокращали наименования |
Автор: | Александр Ильин [ Вторник, 21 Декабрь, 2010 10:30 ] |
Заголовок сообщения: | Re: Именование переменных |
adva писал(а): вот еще одна причина, по которой автокомплит не помешает. Если бы его не было в других средах, то там бы тоже наверняка сокращали наименования Автокомплит решает две задачи: вспомнить название и ввести без ошибок с минимумом нажатий. Если уж мы пытаемся угадать причину краткости имён, то к автокомплиту, вроде бы, имеет отношение только вторая, а первая относится к общей культуре именования (общепринятые типичные имена).Если уж гадать о причинах, то помимо автокомплита можно назвать чувствительность к регистру. Получается, что нужно не только набирать вручную, но и набирать без ошибок. Но всё это мне кажется сильно второстепенным. На первом месте - культура работы. Тут, мне кажется, существенную роль играет то, что читает человек, осваивающий систему. Как кто усвоил, так и сам потом пишет, и так далее по цепочке. А вы заглядывали в ОС Оберон? Да что там ОС, достаточно посмотреть виртовские исходники компилятора, которые без словаря (т.е. его учебного курса) читать невозможно. Ну и, конечно, модульность играет роль. Если пространство имён глобальное, как в Си, то будешь подробно выписывать идентификаторы, с префиксами и суффиксами - хоть есть у тебя автокомплит, хоть нету его. А если каждый модуль изолирован, и импорт квалифицирован, то всё можно именовать одинаково: Init + Do. |
Автор: | Илья Ермаков [ Вторник, 21 Декабрь, 2010 11:33 ] |
Заголовок сообщения: | Re: Именование переменных |
Это не только мой стиль, он когда-то сформировался под влиянием исходных текстов Блэкбокса. Стиль заключается в том, что имена процедур, типов, глобальных переменных объявляются полноценно и с отражением смысла, имена параметров процедур - тоже достаточно содержательно, а вот имена локальных переменных - коротко. У этого стиля, на мой взгляд, есть ряд достоинств. Начать с того, что краткие обозначения сущностей близкого контекста вообще привычны для математиков и физиков. Голова хорошо держит контекст, выставленный для небольшого участка формального текста. Зато запись получается ёмкой, ориентация не на том, с какими объектами идёт работа (они и так ближнего контекста), а какие действия выполняются с ними. Назначение локальных переменных обычно очевидно из их типа и того, как они используются (откуда получили начальное значение, параметрами какого цикла являются). В редком случае, когда неочевидно, действительно стоит назвать длиннее. Наконец, при взгляде на текст сразу видно, то ли это обращение к внешней по отношению к процедуре сущности (и это сразу бросится в глаза из-за длинного имени, что и нужно), то ли это работа с локальным значением. В общем, такой стиль как раз верно расставляет акценты и помогает воспринимать исходный текст. Текст с длинными локальными именами для меня наоборот читать некомфортно. Не поймёшь, какие сущности внешние, а какие локальные, как-то содержание алгоритма "замылено" лексикой. Правило "именуйте локальную переменную длинно" пришло в том числе из книжек, в которых новичкам не прививается сразу манера декомпозиции программы на процедуры. Там же советуется комментировать. Смысл же происходящего должен быть отражён в декомпозиции на процедуры (с длинными понятными именами). А уже действия должны быть "самопонятны". Для локальных переменных цикла, если он нестандартной схемы, пишется в комментарии инвариант - вот и весь их смысл. |
Автор: | Alexey Veselovsky [ Вторник, 21 Декабрь, 2010 11:52 ] |
Заголовок сообщения: | Re: Именование переменных |
Для разделения на локальны переменные, параметры функции и глобальный переменные вовсе не обязательно обрубать длину кого-нибудь из них. Я тоже люблю по внешнему виду переменной сразу понимать откуда она пришла (в тех языках где это значимо), но переменные у меня таки читабельные. А то, что физикам и математикам привычно писать короткие (одно-двух буквенные) названия переменных, это да. В результате они генерируют в больших количествах совершенно неподдерживаемый код. Насмотрелся я на такой код в своё время. Схема возможно и хороша, но при одном условии -- над кодом будет работать его автор. Т.е. автор не уволится, его не собьет машина и вообще он бессмертен. |
Автор: | Илья Ермаков [ Вторник, 21 Декабрь, 2010 12:11 ] |
Заголовок сообщения: | Re: Именование переменных |
Не могу себе представить нормально написанную процедуру, в которой употребление коротких имён вместо длинных снизило бы понятность. Что там вообще понимать-то, внутри процедуры? Только циклы, навороченные не по базовым схемам и без инвариантов. |
Автор: | Александр Шостак [ Вторник, 21 Декабрь, 2010 12:21 ] |
Заголовок сообщения: | Re: Именование переменных |
Долгое время не решался высказать это же "фи". Поражает "читаемостью" как виртовский, так и ББ-ный код. Казалось бы, уж они точно должны быть теми примерами, на которые стоит равняться. Линейка виртовских языков славится читаемостью, но эта читаемость подобным стилем для не-авторов рубится по корню. То же самое, кстати, касается математики и физики. Сокращение умножения до записи двух идентификаторов слитно поставило жирный запрет на возможность использования более понятных имён сущностей (а также необходимость использовать греческие буквы, кирилицу и иные извращения). Во время обучения те страницы формул, что вводят в дрожь, могли бы казаться вполне ясным и осмысленным псевдокодом. Возвращаясь к переменным, нисколько не затрудняет использование идентификаторов вроде: KeyPreprocessFunc, ItemsAreObjects, MiddleItemHash, NumNotProcessedNodes. Что может быть понятно стороннему читателю, когда эти имена превратятся в PrFn, IAreObjs, mh, npNodes? Фактически, нужно загружать временную память информацией расшифровки каждой переменной (обязательно глянуть VAR-секцию, все типы, а также, возможно и объявление этих типов в модуле). Потом на каждом шаге усилием воли восстанавливать r до Reader, mh до MiddleItemHash, IAreObjs до ItemsAreObjects и т.д. В итоге мозг трещит по швам и не хочет в упор переваривать цикл с тремя операторами на одной строке с мини-именами переменных. |
Автор: | Geniepro [ Вторник, 21 Декабрь, 2010 12:28 ] |
Заголовок сообщения: | Re: Именование переменных |
Alexey Veselovsky писал(а): Схема возможно и хороша, но при одном условии -- над кодом будет работать его автор. Т.е. автор не уволится, его не собьет машина и вообще он бессмертен. В серьёзных конторах такие вопросы вообще закреплены внутрифирменным стандартом. Зуев об этом хорошо написал -- как им пришлось работать с нелепым устарелым стандартом, который, тем не менее, был принят в фирме, на которую они работали. И для той фирмы это было выгодно... |
Автор: | Info21 [ Вторник, 21 Декабрь, 2010 12:39 ] |
Заголовок сообщения: | Re: Именование переменных |
Опять какая-то агрессивная клеветнически заряженная возбужденность из-за ерунды. Илья Ермаков писал(а): Что там вообще понимать-то, внутри процедуры? Если процедура хорошо выделена (решает одну четкую задачу и хорошо изоолирована от внешнего мира механизмами языка), то на время разбирательства с ней можно запомнить пяток-другой коротких обозначений. Тем более, что:1) Такие короткие обозначения сопровождаются объявлениями типов, которые обычно длинные и читабельные. В недлинной процедуре этого достаточно. 2) Такие обозначения обычно стандартные и общие для целой серии процедур в одном модуле, и даже для нескольких модулей. p для страниц, i, n, k для стандартных счетчиков и т.п. На одной строке налепить больше одной инструкции -- часто сильно помогает глазу. Плюс экономия пространства экрана. Обмен значений двух переменных. Прицепить в конце строки вспомогательный ASSERT. Короткий IF x < a THEN x := a END или простенький поиск-WHILE. и т.п. Хотя у Вирта в книжках бывает чуть чрезмерная плотность кода. Но это просто привычка со времен маленьких экранов. Так что филиппики AV в этом пункте -- в сущности, сотрясения воздуха. ( Надеюсь, "филиппики" не так обидны, как "истерики" ![]() |
Автор: | Сергей Губанов [ Вторник, 21 Декабрь, 2010 12:58 ] |
Заголовок сообщения: | Re: Именование переменных |
Berserker писал(а): KeyPreprocessFunc, ItemsAreObjects, MiddleItemHash, NumNotProcessedNodes. Что может быть понятно стороннему читателю, когда эти имена превратятся в PrFn, IAreObjs, mh, npNodes? Локальные переменные процедуры убирающейся на полэкрана не превратятся в PrFn, IAreObjs, mh, npNodes, они превратятся во что-то из множества: q, w, e, r, t, u, i, p, a, s, d, f, g, h, j, k, z, x, c, v, b, n, m.Для локальных переменных (область действия которых полностью на виду) стараюсь использовать однобуквенные обозначения. |
Автор: | Андрей [ Вторник, 21 Декабрь, 2010 15:57 ] |
Заголовок сообщения: | Re: Именование переменных |
У кого есть желание выработать единый стандарт оформления кода для проектов на КП (если это ещё не сделано)? Думаю, будет полезно для общих КП-проектов: примеры кода, модули для BB, правки в BB и т.д. Вот мой вариант ( касается только именования переменных ):
2) Экспортируемые переменные носят не сокращённые имена, начинаются с большой буквы: Maps, Page, IgnoreCase 3) Поля записей и параметры функции пишутся без сокращений, с маленькой буквы: PROCEDURE (VAR list: List) AddItem(IN data : Data), RECORD sessionID: LONGINT; count: INTEGER END Название можно сократить, если оно используется в смысле индекса, например t 4) Локальные переменные пишутся с маленькой буквы, и сокращаются. Чем меньше область видимости, тем короче название. 5) Для индексов резервируются переменные: i, j, k, m, n, t 6) Для длины и количества резервируются переменные length и сount соответственно 7) Константы именуются заглавными буквами, слова разделяются _: PAGE_SIZE С учётом вышеописанного, исходная функция выглядела бы так: Код: PROCEDURE (reader: StdReader) SetPosition (t: INTEGER); VAR p1, p2: Page; BEGIN ASSERT((time >= 0), 20); p1:= reader.Base.First; WHILE (p2 # NIL) & (p2.time[p2.length-1] < t) DO p1 := p2; p2 := p2.next END; (* Post: (p1 = NIL) OR (p1.time[n] < t), (p2 = NIL) OR (time <= p2.time[n]), (p1 # NIL) OR (p2 # NIL) ==> Post: (p1 = NIL) & (p2 # NIL) & (t<= p2.time[n]) OR (p1 # NIL) & (p2 # NIL) & (p1.time[n] < t) & (t<= p2.time[n]) OR (p1 # NIL) & (p2 = NIL) & (p1.time[n] < t) *) IF p1 = NIL THEN reader.page := p2; reader.length:= LookAtPage(p2, t); ELSIF p2 # NIL THEN IF time >= p2.time[p2.length-1] THEN reader.page := p2; reader.length:= LookAtPage(p2, t) ELSE reader.page := p1; reader.length:= PAGE_SIZE -1 END ELSE reader.page := p1; reader.length:= PAGE_SIZE END; ExtractIt(reader) END SetPosition; Какие у кого идеи? |
Автор: | Александр Ильин [ Вторник, 21 Декабрь, 2010 16:05 ] |
Заголовок сообщения: | Re: Именование переменных |
Андрей писал(а): Какие у кого идеи? В ББ есть документ по стилю: Docu\BB-Rules.odc.
|
Автор: | Александр Ильин [ Вторник, 21 Декабрь, 2010 16:08 ] |
Заголовок сообщения: | Re: Именование переменных |
Андрей писал(а): 7) Константы именуются заглавными буквами, слова разделяются _: PAGE_SIZE Ужас!
|
Автор: | Peter Almazov [ Вторник, 21 Декабрь, 2010 16:15 ] |
Заголовок сообщения: | Re: Именование переменных |
Андрей писал(а): Чтобы не быть голословным, вот пример даже не самой плохой в этом смысле функции: А откуда эта функция взялась? Укажите, пж, URL.
|
Автор: | Андрей [ Вторник, 21 Декабрь, 2010 16:45 ] |
Заголовок сообщения: | Re: Именование переменных |
Александр Ильин писал(а): Ужас! Согласен ![]() Документ по стилю не помню, но кажется там не было ничего касающегося именования. Вечером посмотрю. Peter Almazov писал(а): А откуда эта функция взялась? http://oberoncore.ru/wiki/blackbox/ex/history_models |
Автор: | Александр Ильин [ Вторник, 21 Декабрь, 2010 16:53 ] |
Заголовок сообщения: | Re: Именование переменных |
Андрей писал(а): Документ по стилю не помню, но кажется там не было ничего касающегося именования. Цитата: 8 Case
In general, each identifier starts with a small letter, except • A module name always starts with a capital letter • A type name always starts with a capital letter • A procedure always starts with a capital letter, this is true for procedure constants, types, variables, parameters, and record fields. Good null = 0X; DrawDot = PROCEDURE (x, y: INTEGER); PROCEDURE Proc (i, j: INTEGER; Draw: DrawDot); Bad NULL = 0X; PROCEDURE isEmpty (q: Queue): BOOLEAN; R = RECORD draw: DrawDot END; Don't use all-caps identifiers with more than one character. They should be reserved for the language. 9 Names • A proper procedure has a verb as name, e.g. DrawDot • A function procedure has a noun or a predicate as name, e.g. NewObject(), IsEmpty(q) • Only declare a record type if necessary (FooDesc for each Foo are normally not needed anymore) • Procedure names which start with the prefix Init are snappy, i.e., they have an effect only when called for the first time. If called a second time, a snappy procedure either does nothing, or it halts. In contrast, a procedure which sets some state and may be called several times starts with the prefix Set. Examples PROCEDURE InitDir (dir: Directory); PROCEDURE (p: Port) Init (unit, colors: LONGINT); • Guard procedures have the same name as the guarded command, except that they have a Guard suffix appended. Example PROCEDURE PasteChar; PROCEDURE PasteCharGuard (VAR par: Dialog.Par); |
Автор: | Илья Ермаков [ Вторник, 21 Декабрь, 2010 17:12 ] |
Заголовок сообщения: | Re: Именование переменных |
Berserker писал(а): Долгое время не решался высказать это же "фи". Поражает "читаемостью" как виртовский, так и ББ-ный код. Казалось бы, уж они точно должны быть теми примерами, на которые стоит равняться. Линейка виртовских языков славится читаемостью, но эта читаемость подобным стилем для не-авторов рубится по корню. Вы не забывайте что в книге Вирта алгоритмы повыше повседневного уровня. И код ББ в местах системного характера - тоже. Тут просто в голове у Вас корреляция, наверное, получилась: надо-разбираться-с-алгоритмом-сразу-не-понятно + ах-да-тут-ещё-переменные-короткие-какой-ужас. Горячие споры про эти идентификаторы - частый пример, когда пытаются улучшать, изменяя только один фактор. Т.е. выработать оптимальные правила именования, держа в голове вообще любой самый ужасный код, который может кто-нибудь написать (типа, пусть хоть переменные понятными будут). Тогда как при улучшении по нескольким факторам - т.е. внедрении нормальных привычек написания программы - вдруг оказывается, что фактор именования локальных переменных уже не принципиален. И его можно оптимизировать в обратную сторону - покороче. |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |