Комментарии 231
Функция больше 10 строк – слишком длинная.
Почему именно 10? Заголовок и скобки тоже включать?
Я правильно понимаю, что функцию такого вида нужно делить?
void foo()
{
--7 строк кода
}
А потом, через 5 лет, будет еще и других учить, что так делать правильно?
Там и в две строчки функция — уже слишком длинная.Это смотря сколько в одну строчку писать:
: SetWTimer ( pd h -- ior )
>R
>R
TRUE 0 ['] APCWTimer 0
R>
R> SetWaitableTimer ERR
;
: WakeAfter { ms \ ht -- }
WaitableTimer THROW TO ht
ms 10000 UM* DNEGATE SWAP SP@ ht SetWTimer THROW 2DROP
TRUE ms 10000 + SleepEx DROP
ht CloseHandle DROP
;
Ерундовый совет. Если поток управления в функции прямой как палка и в ней нет каких-то кусков, имеющих потенциал переиспользования, то можно и функцию на 1000 строк написать без потери читаемости.
можно и функцию на 1000 строк написать без потери читаемости.
Тут проблема будет не с читаемостью, а с переиспользованием переменных в рамках одной области видимости. Так что лучше разбить на логические изолированные куски и оформить в самостоятельные функции. И логика работы функции будет выражена намного яснее метаязыком названий внутренних функций.
Совсем на днях сменил тактику разработки моделей в KSP — догадался, что не стоит делать «монолитные» изделия в сохранениях. Перешел как раз к более промышленной тактике: делаю отдельно те же ускорители / ступени / сегменты / полезную нагрузку (те же зонды/спутники). А потом уже по мере надобности из готовых сегментов собираю конкретный экземпляр под конкретную задачу.
Вот казалось бы, я программист, а почти месяц не приходило в голову такой подход использовать — как же я мучился раз за разом собирая сложные конструкции, мучаясь с подгонкой частей… никому такое не пожелаю.
Модульность — великое «изобретение» (на самом деле подход).
Ирония в том, что я не сообразил изначально весь итоговый простор.
UPD: пардон, перечел еще раз ваше сообщение… кажется вы несколько об ином, хм… пойду опять шерстить CKAN.
В моей практики была ситуация, когда в функции из 30 строк, при этом 20 из них занимало строки с переносом значений из распарсенного xml-файла в класс. Сами понимаете, что это делить не имеет смысла, т.к. нужно сделать всё или ничего.
Иногда можно обойтись минимумом тестов. Если все компоненты, используемые в функции, оттестированы, возможность описок минимизирована с использованием системы типов, в функции нет ветвлений, то достаточно проверить пару случаев с известным входом/выходом, чтобы убедиться, что все требуемые шаги выполнены.
Это я про языки с развитой системой типов. В языках с динамической типизацией, тестировать естественно нужно всё.
// Я через несколько месяцев == другой.
От того, что в код залезет кто-то, кто не понимает, что ситуация поменялась, и нужно дописать ещё тестов, никакие тесты не застрахуют.
Когда код покрыт тестами, то любая доработка естественным образом мигрирует на TDD, так как сначала все равно нужно формализовать изменения контрактов.
Потому что в противном случае приходится держать контракт в голове, пока правишь под него код.
В языках с развитыми системами типов некоторые контракты (переменная не может быть null, например) можно выражать с помощью этой самой системы типов. И они будут работать для всех входных данных, а не для некоторых входных данных, как в случае с тестами.
Другие языки, вроде Rust, ещё добавляют гарантии безопасности памяти, так что писать кучу тестов, для того что и так не сломается (последовательный вызов оттестированных функций, о котором я говорил) — совершенно не имеет смысла. Единственный реалистичный случай внесения сложной логики в такую функцию — рефакторинг, с переносом функциональности одной из вызываемых функций в эту функцию, но тогда будет несложно заметить и необходимость переноса тестов. И от того, что эту необходимость не заметят, тесты не защитят.
Или другим языком: единственный тест может покрыть все code paths, если на верхнем уровне этот code path один, а все подуровни уже покрыты тестами/правильность гарантирована системой типов.
единственный тест может покрыть все code paths, если на верхнем уровне этот code path один, а все подуровни уже покрыты тестами/правильность гарантирована системой типов.
Так тест покрывает только верхний уровень, т.е. логику выполнения самой функции, а не её внутренностей.
Это контракт: если на входе это, то на выходе должно быть то.
И простота данной схемы сразу выявляется функции, которые, вроде бы, не сильно параметризированы, но внутренняя логика зависит от состояния объектов, которые в неё поданы. И либо писать на каждое состояние объектов и их пересечение свой контракт (а нам все равно это надо делать, хотя бы разбираясь с тем, какая для каждого случая будет бизнес-логика), либо переписывать.
Удалено.
TDD + ООП та ещё смесь. Если рассматривать программу как способ преобразования данных, а не как групповое поведение кучи объектов, у каждого из которых есть своё поведение, всё становится намного проще. Это не всегда применимо, но если не смотреть на всё как на объект, то жизнь себе можно упростить.
А по факту перед нами может и всё правильно делающая функция, но не тестируемая из-за своей архитектуры. Переход на TDD, как раз, позволяет уйти от сложных и умных архитектур, как потенциально не тестируемых. Хотя без тестов они могут выглядеть очень даже красиво. Тесты позволяют видеть за этой красотой уязвимые участки кода и места совмещение функционала.
Не используйте длинные строки. Строку длиннее 80 символов очень трудно читать. Используйте специальные инструменты для приведения кода в порядок (ESLint, Prettier для js).
Ограничение в 80 символов лично мне кажется перебором
А документирующий сам себя код - это как?
А такой подход применим к любому языку? И где можно прочитать об этом больше?
А на классических языках достаточно легко. Давайте всем функциям и переменным имена, говорящие об их назначении. Выделяйте малопонятные фрагменты кода в функции с говорящими именами или вводите промежуточные переменные. И в целом помните, что код читают гораздо чаще, чем пишут.
Сравните:
const float a = 9.81; //gravitational force
float t = 5; //time in seconds
float s = (1/2)*a*(t^2) //multiply the time and gravity together to get displacement.
иfloat computeDisplacement(float timeInSeconds) {
const float gravitationalForce = 9.81;
float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2)
return displacement;
}
А что-нибудь посерьёзнее есть?
Действительно.
Нет смысла тащить ограничение из времён DOS. Обычно выбирают так, чтобы строчка влезала на экраны у всей команды. И чаще это 110-130 символов, но не всегда.
Название системы — три буквы?) За два с лишним года так и не смог привыкнуть к именованию датасетов вида "птчк", " упрлс"...
Менять больше всего поразило в ней, что в ней есть ограничение по длине ПРАКТИЧЕСКИ на все поля. И диагностика ошибок нулевая или на уровне, что документ не сохраняется с формулировкой «Нельзя сохранить документ», без всякого объяснения почему…
На перфокарту переносили готовую программу для выполнения.
Саму разработку на перфокарте не вели.
Очки, сорокадюймовый монитор, нет?
Строчка должна выполнять одну логическую операцию. Если используются длинные имена переменных, то она может быть длинной, особенно если там вызывается метод класса с хорошим длинным названием и неудачно большим количеством параметров (больше трех).
Разбиенеие одного вызова получения чего-то откуда-то на несколько строк ухудшает читаемость.
Те, кому надо сконцентрироваться на этой конкретной строке — прокрутят и прочитают.
Такое ограничение сохранилось не только благодаря досу, перфокартам и чему-то устаревшему, но благодаря тому, что чем меньше длина строки — тем проще делать дифф.
Будет ли удобно делать дифф для целого абзаца в виде одной строки? Кстати, поэтому и в Markdown сделали мягкие переносы, которые не разрывают абзац. На хабре правда они не работают, но это уже другой вопрос.
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let's do more of those!
Надо написать очевидный скрипт на 2 строчки — не пишите тесты, не используйте Dependency injection framework'и если у вас в проекте 3 простейших класса, не засовывайте паттерн проектирование только потому что можете.
В общем, при использовании любых правил — думайте сами насколько они вам нужны. Это сложно, но очень полезно. Иначе так и останетесь начинающими с 20 лет годами опыта.
Помимо просадок по скорости такие громоздкие библиотеки требуют зачастую специфичных знаний, просто так бездумно использовать такие вещи не стоит.
Но в целом посыл верен, если это позволит сэкономить много времени, при этом минусы такого решения не критичны, то да, почему бы и не воспользоваться.
github.com/sizeofcat/civitas
github.com/Areso/1255-burgomaster
Первая, правда, более богата функционалом, но начинались они примерно в одно и то же время с диаметрально разным подходом по отношению к зависимостям, и у обоих игр решение было принято на начальном этапе.
по правде сказать я смирился. у меня prettier по умолчанию так настроен был и я не стал менять. Да, иногда раздражает автоперенос, но в общем терпимо
В этой строчке 101 символ. Что у вас с глазами?
UNIQUE отслеживает уникальность величины столбца в масштабах всей таблицы. Идеально подходит для хранения логина или почты пользователя.
Нет не подходит. У таблице пользователей не может быть уникальных полей, за исключением id. Уникальным может быть только связка электропочта+valid range.
А если есть сервисные записи без почты или сотрудники без логина то и эта связка тоже не может присутствовать.
для процентов нужно проверять вхождение в интервал от 0 до 100
смотря для каких, есть множество случаев когда нужны отрицательные проценты или процент более сотни. Подобные преждевременные ограничения кстати очень распространенная проблема.
Одержимость производительностью
Спорный момент. Где грань, когда необходимость становицо одержимостью? Огромное количество проектов насилует сервера понапрасну, только из-за того, что лень было подумать над SQL запросами.
Но если вам нужно колесо для его обычных целей, то, пожалуйста, не переизобретайте его заново. Просто возьмите обычное колесо и используйте.
ох не всегда это работает, ох не всегда)
Ну и кроме всего прочего: KISS, YAGNI. Остальное от лукавого 8)
заглянул в первую попавшуюся документацию, это было по SQL:
you can have many UNIQUE constraints per table…
для любого поля можно задать уникальность и оно будет соблюдаться в рамках всей таблицы
Впрочем, я не согласен про логины, хотя соглашусь про почты (если они не выступают логинами). Я люблю регать на 1 почту несколько аккаунтов)
У нас всем сотрудникам выдаются легко произносимые почты из двух букв, дабы легко можно было диктовать/запоминать/итд
Самая потрясающая корпоративная идея тысячелетия!
Пишешь на почту vp@crazycompany.com и не знаешь к кому попадешь — к Василию Пупкину или он уже уволился и эту почту читает совсем другой человек.
А если Василий Пупкин уже работает в компании, то новобранцу Виталию Пупковичу дадут очевидный и запоминающийся логин ip или vu — логично же!
1. А вы желаете получить автоматический отлуп? Не нужно ничего знать, вам все расскажут.
2. Я так понимаю у вас сотрудники знают фонетический альфавит и могут легко диктовать vasyapupkin@crazycompany.ru? действительно идея тысячилетия
3. Вы явно не в продажах работаете да?) У второй компании адреса 01, 02, 03 У третьей m1, m2, m3. Это удобно и клиентам нра.
1. А вы желаете получить автоматический отлуп? Не нужно ничего знать, вам все расскажут.
Естественно! Категорически не хочу, чтобы вместо юриста Пупкина наши договоры читал программист Пупкинович.
2. Я так понимаю у вас сотрудники знают фонетический альфавит и могут легко диктовать vasyapupkin@crazycompany.ru?
Собственно, все компании, кроме вашей, как-то справляются.
У второй компании адреса 01, 02, 03 У третьей m1, m2, m3.
Хм, да, очень удобно — клиент сразу понимает, что Василию Пупкину надо писать на vp07@crazycompany.com — логично и интуитивно!
Естественно! Категорически не хочу, чтобы вместо юриста Пупкина наши договоры читал программист Пупкинович.
Для этого есть специальные адреса.
Собственно, все компании, кроме вашей, как-то справляются.
У многих торговых компаний короткие мыльца сейсас. А у мосигры например прикольные. Кроме того слышал как они справляются, по 10 минут на почтовый адрес, ага.
Хм, да, очень удобно — клиент сразу понимает, что Василию Пупкину надо писать на vp07@crazycompany.com — логично и интуитивно!
У меня почта 02 уже на многих доменах. Никто не жаловался.
ЗЫ А вообще в таком тоне мне общаться неприятно. Удачи вам с таким подходом.
Для этого есть специальные адреса.
Ну вот, в случае юристов и реальной ответственности, здравый смысл как-то быстренько возвращается.
У многих торговых компаний короткие мыльца сейсас. А у мосигры например прикольные.
Да, вот, хоть на примере мосигры: если мы связываемся не с человеком, а с функцией, то вполне логично писать на invest@ или ecommerce@. А если мы пишем на короткий адрес hi@, то мы ожидаем, что это прочитает собственно Сергей Абдульманов, а не рандомный Христофор Иванов.
У меня почта 02 уже на многих доменах. Никто не жаловался.
Ну, конечно, глупо жаловаться, если неизвестно кто прочтет — уборщица или вахтер.
У нас всем сотрудникам выдаются легко произносимые почты из двух букв, дабы легко можно было диктовать/запоминать/итд Естественно они наследуются
У нас писарь в уезде был, в пачпортах год рождения одной только циферкой обозначал.
Чернила, шельмец, вишь, экономил. Потом дело прояснилось, его в острог, а пачпорта переделывать уж не стали. Документ все-таки. Ефимцев, купец, третьего года рождения
записан, Куликов — второго… Культякин — первого. Да, много тут долгожителей.
из к/ф Формула любви
В статье имеется ввиду преждевременная оптимизация производительности. Это писать код сначала понятно и просто, не заморачиваясь на оптимизации, просто потому, что код ещё несколько раз может поменяться. И вот когда код уже написан, он работает, покрыт тестами и выполняет задачу, для который написан, профилирование показало, что этот код работает медленно, вот только тогда стоит браться за оптимизацию. Да и то, тут ещё стоит рассмотреть систему в целом, а то может у вас больше тормоза даёт I/O, недели ваш код, и даже его оптимизация не даст ощутимого прироста.
В статье все же речь про языки программирования, а не языки выполнения запросов, потому что в последних свои нюансы, которые отличаются. И речь скорее всего про оптимизиции без предварительного профилирования, которые в большинстве не приносят существенной пользы, зато тратят время и даже могут ухудшать читабельность кода.
В общем, посыл такой, что не нужно заморачиваться на производительности при написании кода на языке программирования (не запросов), если эффективность этого кода не определена эмпирически и не доказана целесообразность увеличения его производительности. Иначе — это, с большой вероятностью, пустая трата времени.
И не меньшее — потому что было НЕ лень. Работал в проекте, где ВСЯ серверная логика была вынесена в СУБД. Ну и 150 запросов в минуту и не больше. После разделения логики и упрощения запросов, получили около 10К запросов в минуту.
И не меньшее
Ну все таки меньше) Порок входа в это дело куда выше, чем в клепание простых запросов.
Работал в проекте, где ВСЯ серверная логика была вынесена в СУБД. Ну и 150 запросов в минуту и не больше. После разделения логики и упрощения запросов, получили около 10К запросов в минуту.
Странная корреляция. Я даже придумать не могу как можно было сделать так плохо.
Эх, детство у меня было замечательным.
Изменение разрешения экрана ради демонстрации пиксель-сцены.
Переменные а1, а1_0, аа, аа0.
Полное отсутствие каких бы то ни было проверок на наличие тех файлов, которые я честно-честно положил.
Карты местности в jpeg.
Могу сказать, что данная статья действительно полезна, но уже не для новичка. Новичок может и половины не понять.
я полагаю и многие мои коллеги считали так же, что проверять входные данные во всех функциях — это антипаттерн, который ведет к раздуванию кода и проседанию перформанса. Этот антипаттерн будет особенно драматичен, если вы начнете рефакторить большую функцию, разбивая её на несколько меньших — получается, вам теперь и там нужно добавлять проверять входные данные.
проверять данные нужно в момент поступления их от пользователя и к пользователю — это да, это необходимо. Возможно, в ряде других случаев эта проверка тоже уместна — к примеру, при вращении катапульты в играх уместно ограничивать предельные значения углов поворота.
А если программист передает объект в функцию, в документации которой описан четко тип передаваемых аргументов — это не создатель функции виноват.
Категорически согласен, всего не предусмотришь. И, кажется, я знаю откуда у автора появилась эта паранойя — в Javascript'e, с его динамической и слабой типизацией, даже во вполне безобидном коде приходится писать проверки типов.
В языках с динамической типизацией одна и та же переменная может иметь разный тип, в результате ошибки или явно, но это факт и от наверного типа никто не застрахован. Более того, есть такое понятие, как duck typing, так что тут больше по интерфейсу матчинг, а не по типу объекта. Ну и Null, None, null, undefined и так далее никто не отменял, их как минимум нужно проверять.
А ещё если вы пишете библиотечную функцию и есть внешний клиентский код, который может передать в нее все, что угодно, проверки входных параметров все же стоит делать)
Если использовать прием «не возвращать Null, None, null, undefined» — то и проверки не будут нужны так часто
это да, от этого особенно часто страдаешь, работая с чужими библиотеками
вот на приеме от таких функций, любящих подсовывать разные типы объектов и надо ставить проверки — главное, что не во всех своих функциях писать
в JavaScript использование одного типа является крайне желательной практикой — это позволяет движку V8 проводить дополнительные оптимизации после «разогрева», да и уменьшает вероятность ошибок в коде из-за того, что вы описываете )
1. Недостаточно делать что-то.
2. Чрезмерно делать что-то.
Последствия нарушения правил типографики не очевидны для читателя. Он чувствует, что устал читать, но не понимает из-за чего именно. Шрифты, отступы, интервалы, засечки, колонки, думаете это все только декораций ради? Если вы заметите, то на всех популярных ресурсах ширина основного контента ограничена, а не растянута на весь монитор.
И в коде я тоже всегда использую две колонки, иногда в них даже открыт один файл в разных местах.
Я вот знаю, что наоборот, к утомлению приводит статичный взгляд в одну точку
Совершенно верно, поэтому ширина колонки не должна быть в один символ. Не нужно приводить глупые примеры.
Работать за двумя широкими мониками менее напряжно, потому что чаще двигаешь глазами.
Типографика — это про оформление текста, а не про организацию ваших окошечек. Два монитора — удобно. Слишком широкий текст — неудобно. Вы попробуйте на два монитора растянуть сплошной текст. Возьмите статью с хабра, вставьте ее в блокнот, растяните его на два монитора и прочитайте до конца (а лучше на три). Тогда вы поймете, что не нужно бросаться в крайности, и оптимальная ширина колонки взята не с потолка.
Короче не ту тему вы выбрали для спора.
Товарищ выше прислал вам ссылки ознакомиться, но вы попросили ссылки на исследования. А от вас можно ссылки на исследования получить, что широкий код — благо глазу? Или даже без исследований, есть где-нибудь признанные в IT-сообществе стандарты или рекомендации в отношении ширины кода в 120 символов?
Шрифты, отступы, интервалы, засечки, колонки — где вы это всё увидели в программном коде?
Везде, например? В любой профессиональной IDE, на любом профессиональном ресурсе (типа гитхаба или стека, и даже хабра) код и вставки кода имеют строго определенную типографику. Да, везде шрифты без засечек, моноширенные, узкая колонка. Могу забросать примерами. А вы можете найти пример, где по умолчанию пропагандируется широкий код? А не моноширинный шрифт? А уплотненный интервал?
Вопреки аргументам, вы конечно же можете воскликнуть, что не смотря на статистику, они все дураки и быдло, а вы один такой умный с железными глазами. Но чтобы делать такие заявления, должна быть какая-то репутация. А вы пока производите впечатление не признанного гения с синдромом даннинга крюгера.
В программном коде свои способы организации текста — это отступы и подсветка синтаксиса. И читают программный код люди не подряд, они ориентируются на уровень вложенности в первую очередь, на цвет ключевых слов, на пустые строчки.
Верно, и это никак не исключает необходимость типографики, поэтому она везде и есть по умолчанию. Если вы у себя в IDE ее намеренно ломаете, это не говорит о том, что типографики там не было изначально.
Отступы есть? Есть.
Подсветка синтаксиса есть? Есть.
Одна проблема: типографики нет.
Глаза уже зачесались?
Ваш пример доказывает как раз мой тезис о том, что если бездумно применить правила типографики для текста к программному коду — получится херня.
Мой пример лишь доказывает важность типографики, не более. А всплыл пример после вашего вопроса:
Шрифты, отступы, интервалы, засечки, колонки — где вы это всё увидели в программном коде?
То есть, это вы ставили под сомнение само наличие типографики в коде. Давайте повнимательнее, а то я уже устаю.
Вы, похоже, почему-то решили, что 80 символов — это некое божественное откровение, или на худой конец результат исследований в области эргономики.
Так вот, ни то, ни то :)
А вы похоже решили, что это результат поддержки обратной совместимости со старыми форматами. Взяли и выдумали эту причинно-следственную связь, задвигая ее как очевидную.
Опять вынужден обратиться за примерами. Окунемся в чудовие времена узких терминалов, бумаги и мониторов. Текстовый редактор vi может похвастаться тем, что может работать на терминалах с ограниченным набором клавиш. Но те времена прошли, и сейчас vi-подобными редакторами пользуются меньшинство. Например, я использую vi только там, где ничего больше нет. Угадайте почему? Потому что обратная совместимость абсолютно не причем, люди пользуются новыми редакторами, потому что это удобно. По этой же причине везде используется узкая ширина колонки кода.
Вы проигнорировали мой пример с двухколоночным расположением панелей в IDE. Судя по всему, у вас одна колонка. Ну да и хрен с ним. А как быть с двухколоночным diff? Я им не пользуюсь, мне с головой хватает git diff, но я знаю, что многие пользуются. Как им ваш широкий код дифать?
Лично я допускаю в коде широкие строки до 120 символов, но таких строк должно быть немного, потому что мне уже такое читать тяжело, и значительную часть кода я стараюсь умещать в узкую колонку.
Про цепочку вызовов интересный аргумент, но руби тут не причем. Я цепочку вызовов могу сделать практически на любом языке на базовых механизмах ООП. Вот только я не понимаю, почему эта цепочка должна быть в строку? Вы понимаете, что подобным аргументом вы утверждаете, что цепочка вызовов должна ограничиваться шириной экрана? Это разве не смешно?
Да даже с точки зрения читабельности, гораздо удобнее цепочку вызовов читать в столбик, чем в строку, сравните сами:
# код здорового человека
datasource->get_data()
->filter('first_filter')
->filter('second_filter')
->sort('some_field')
->reverse()
->slice(10, 20)
->format()
->render();
# код курильщика
$datasource->get_data()->filter('first_filter')->filter('second_filter')->sort('some_field')->reverse()->slice(10, 20)->format()->render();
Прошу прощения за пхп, взял самый попсовый язык.
А если в сообществе руби кто-то и ставил этот вопрос (который, как я понял, не одобрил электорат), то видимо идея не прижилась. Либо, нужны подробности.
Я ставил под сомнение применимость правил типографики для печатного текста (ну или даже вообще текста на естественном языке) к программному коду. Остальное вы сами додумали.
Ну и я примером показал важность и применимость этих самых правил для печатного текста. Вы же взяли и соскочили. Сначала спрашиваете, где я вижу в коде типографику, на что я вам показываю, где же я вижу в коде типографику, а потом соскакиваете, что типа типографика в коде есть, и мой пример иллюстрирует важность типографики. Завязывайте, я серьезно.
Не знаю, как вам, нормальным людям при мерже важнее структура (отступы), чем всё остальное.
Мне все важно, и контент, и чтобы контент было удобно читать. Широкий код лишен одного из этих двух требований, поэтому я его и выделил.
Потому что гораздо лучше, когда код скомпонован логически, а не потому, что кто-то из консоли с ним извращаться будет, и его надо нарезать на строки где попало, куда 80й символ пришелся.
И каким это образом мой восхитительный код в столбик не скомпонован логически? Разверните строку, чтобы она не переносилась узким хабром, ее один хрен неудобно читать.
И знаете что еще, есть такое удивительное изобретение, как скролл.
Тогда в сторону уходит начало строки. Удобнее и быстрее читать не проматывая
Повторяюсь, но всё же: чтоб понять, о чем абзац текста, его надо прочитать слово за словом весь, в структурированном программном коде же куча метаинформации — подсветка, скобочки, структура.
От того, что вы десять раз это повторите, истиной это не станет. Код, который не умещается в колонку и требует прокрутки по двум осям неудобно ни читать, ни редактировать, ни искать в нем нужную инфу, ни дифать. Короче аргумент с горизонтальным скролом плохой.
Кроме того, если у вас есть необходимость в очень длинной строке, возможно вы что-то делаете не так. Возможно причина в использовании каких-то антипаттернов, которые могут приводить к длинным строкам (может слишком сильные зависимости, жирные интерфейсы функций, жесткие запутанные связи, слабая декомпозиция, нехватка слоев)
Никто не говорит, что каждая строка кода должна быть 120-150 символов, но делать специальное ограничение в 80 для всего кода, если можно писать и 90 и 100 и 120 в строке, а не выдумывать как тут я сокращу название переменной, чтобы все влезно — вот тут я и ставлю вопрос — почему 80 символов это прямо такое правило?
нормальные diff-ы умеют автоматически переносить текст, и все красиво отображается.
habrastorage.org/webt/ga/8a/ha/ga8ahabgwzxzdbh96pwmjfmdgni.gif (6MB)
Тут есть один нюанс — эти символы потом кому-то, вполне возможно, придётся читать.
Как оно там живётся в 90-х? Какие 80 символов? Кто еще пишет на калькуляторах код? Зачем это? 120 символов в строке можно смело писать. А если это какое-нибудь перечисление, то можно и больше символов.
У тех, кто использует IDE в двухколоночном режиме, на среднем мониторе ширина колонки 85-100 символов. На ноутбуках и того меньше. А фича, между прочим, удобная
Коллеги с экранами ноутбуков 1280x800 (стандарт на ноутах старых моделей) скажут вам "спасибо" за 120 и более символов. Потому что 80 символов позволяют открыть два файла с кодом на таком экране и ничего не будет переноситься)
Ну с таким подходом непонятно, почему все должны под вас подстраиваться) А почему не взять тогда уж все 320 символов? И больше ж кода то влезет на экран и будет стимул всем мониторы обновить. Я вам так скажу. Есть рекомендации (например, pep8 в Python), которые не с потолка взяты, а следовать им или нет — ваше личное дело. В команде, как правило, code conventions принимают либо на базе общепринятых рекомендаций, либо на базе мнения большинства. Если в вашем случае большинству удобнее со 120 символами — ради бога. А в статье приводятся общепринятые рекомендации, а следовать им или нет — каждый сам решает
И калькуляторы тут не причем, я вам привел пример наиболее распространенного разрешения на ноутбуках. И большинство ноутов старых моделей именно с таким разрешением. И именно 80 символов позволяют на таком разрешении делать 2 колоночный просмотр кода без переноса строк. И это одна из причин такого выбора
Кроме того, про все языки программирования не знаю, но если дело касается кода, то превышение 80-120 символов в строках происходит редко, и на удобство чтения кода на любом мониторе влияет не сильно.
— Using lists (arrays) instead of maps (objects) to manage records
The most common data structure mistake is probably the use of lists instead of maps to manage a list of records. Yes, to manage a LIST of records you should use a MAP.
Перевод
Массив или объект?
Самая распространённая ошибка – это использование массивов вместо объектов для хранения списка записей. Да, вы не ослышались, для хранения списка записей нужно использовать объекты.
Немножко настораживает, что так называемый «full-stack» девелопер не знает слова map.
структура «ключ-значение»
может быть массив структур «ключ-значение»
Хотя тоже коряво.
Вроде есть одна структура «ключ-значение». А потом их становится много — массив из них. Array of structs — вроде такой термин, к примеру, в BigQuery используется. Правда там структура не обязательно «ключ-значение»…
Я бы перевёл как "хеш-таблицу" (немного вольный перевод, но зато сразу понятна идея) или "ассоциативный массив" (точный перевод, но не очень очевидный).
Ассоциативный массив — это тип «интерфейса» структуры данных. Реализации могут быть разными — «хеш-таблица», какое-либо дерево поиска и т.д.
Хэштаблица — это конкретная структура данных (на самом деле, не совсем, там тоже есть разные стратегии разрешения коллизий.)
А общая рекомендация проста — не используй для поиска элемента плоские структуры.
А как лучше было перевести по вашему?
[Один из пример ошибочного использования структур данных — это ...]
— Использование списков (массивов) вместо ассоциативных массивов(*) для обработки записей(**)
Возможно, самая частая ошибка, связанная со структурами данных — это использование списков вместо ассоциативных массивов для обработки списков записей. Да, верно, для обработки СПИСКА записей нужно использовать АССОЦИАТИВНЫЙ МАССИВ(***).
Заметьте, когда я говорю о списке записей, я имею в виду, что каждая запись должна иметь идентификатор, который будет использоваться для поиска. Использовать списки для скалярных значений — нормально и зачастую даже предпочтительно, особенно если мы в основном добавляем значения в список.(****)
(*) — вот то, что в оригинале maps ( в скобочках objects ) — это какой-то джаваскриптизм, который не способствует пониманию, по-моему его можно опустить ( тем более, что дальнейшие упоминания джаваскрипта вы подрезали)
(**) — «запись» — немножко устаревший термин, я бы потестировал на людях, не будет понятнее здесь везде вместо «запись» писать «объект». Смысл тот же, хотя и не дословно.
(***) — автор КРИЧИТ, ну и мы тоже будет, нуачо?
(****) — дабл неловкость, во-первых потому что что-то не придумывается благозвучный перевод этого «focus of usage», во-вторых потому что автор что-то по-моему загнался ( и почему «pushing» в кавычках?)
Вот примерно такое я придумал за минутку.
Как я понял автор имеет ввиду когда используют обычный массив:
[{id: 1, title: "entry1"}, {id: 2, title:"entry2"}, .... ]
Хотя лучше использовать ассоциативный массив:
{ 1: {id: 1, title: "entry1"}, 2: {id: 2, title:"entry2"}, ....}
И предлагает использовать обычный массив, только если нам нужно активно пользоваться Методами типа push, pop, shift, unshift (которые обращаются к записям не через ключ, а ориентируюсь на порядок в списке).
Имхо, решать костылями то что должно (в идеале) проверяться другими методами — не верно.
const daysInYear = 365;
Никогда не делайте так. Понимаю, что это просто пример, но, не дай бог, кто-то так в реальном коде напишет. По поводу заблуждений программистов о времени — была хорошая статья, здесь, на хабре. Начать читать можно здесь https://habr.com/post/313274/ — много удивительного можно узнать.
P.S.: Для примера можно использовать безопасный аналог — const monthsInYear = 12; Месяцев в нашем календаре всегда 12.
А так можно:const daysInYear = 365;Никогда не делайте так
const integerPartOfDaysInUsualYearInMostCalendarsInEurope = 365;
?
Или лучше писать в коде 365?
Плюс мы облегчаем интерфейс пользователю, когда не спрашиваем у него в обязательном порядке в каком году он хочет открыть депозит или кредит или whatever что он хочет там сделать или посчитать.
)))
const daysInYear = 365.2425;
const answerToLifeTheUniverseAndEverything = 42;
if (b % 2 === 1) { // If the current number is even
Вот тоже зло в чистом виде: комментарий не соответствующий коду.
Если вкратце — «Пишите хорошие программы, а плохие — не пишите».
К сожалению, у большей части указанных ошибок нет внятных численных критериев. А значит если я даже искренне хочу воспользоваться ценным материалом статьи — то… как? Любая написанная программа которая работает — это лучшее, что сделал программист в существующих условиях. Объяснить как и главное — почему можно сделать лучше — может только более умный/опытный программист в каждом конкретном случае.
Обычно что-то такое говорят про велосипед.
Раз влез, терпи, упорство и труд все перетрут
В то же время заучивание сильных и слабых сторон разных структур данных вашего языка программирования, несомненно, повысит ваше качество как разработчика.
Самая распространённая ошибка – это использование массивов вместо объектов для хранения списка записейНу и расскажите мне, как я в ванильном си, узнав самую распространённую ошибку в структурах данных среди новичков, буду ходить по объекту (ага), который представлен ассоциативным массивом/словарём (ага) со стринговыми (ага) ключами, чтобы интерпретатор (ага) в рантайме мне нашёл (ага) содержимое этого самого т.н. «объекта», да ещё и сделал это быстрее (ага) массивов. Код новичка, млин.
Пользуйтесь командой git blame, выдающей автора каждой строки кода.Пользуйтесь им везде. В Subversion, в Mercurial, в Team Foundation, вместо вечерней молитвы и в качестве приветствия. Просто бездумно запомните git blame и не забывайте почаще отрабатывать джебы по груше. Потому что «Не использование систем контроля версий (Git)». Потому что исключительно front-end open source на github в vs code. Потому что иначе вы пользуетесь примитивными инструментами из старой кладовки и не любите снуды.
И снова это не про сравнение парадигмы функционального программирования с остальными.С какими остальными? Неправильными и неверными, потому что не модными? Конкатенативными и Логическими? Какими? Или, типа, всё-таки в очередной раз пошёл срач про модность в противостоянии Императивной и Декларативной парадигм?
Есть обратный вариант. Пишите статью на Хабр, в ней приводите небольшие кусочки кода и ссылку на проект, впадаете в депрессию от комментариев и общей оценки ваших трудов
Очень спорная статья. Минимум к 6-10 пунктам можно нпписать замечаний.
Маленькие коммиты с осмысленными заголовками помогут сопровождающим код людям понять, как шаг за шагом образовывалась программа, пока не достигла текущего состояния.
Представил ситуацию, когда мой код коммит за коммитом кто-то так сопровождает.
Варианта два:
1. Это библиограф, а я Билл Гейтс. Мертвый.
2. Это ботаны из УИТ ЦИБ ФСБ. А я в Лефортово.
Насчет першого пункта. Пока сам что-то не закодишь в уме это совсем никак не работает, а вот когда что-то написано, то все сразу хорошего видно
«Новичкам можно посоветовать такое правило: любой недокументированный код, который вы не понимаете — плохой.»
С какой стати код плохой? Он недокументирован, это плохо. Но с чего ему быть плохим?
Очень много из 25 примеров в статье даны с неправильным толкованием.
А код плохой — это что-то типа презумпции невиновности, только наоборот. Если не понимаешь код — не говори, что он хороший, пока не поймешь. Говори что хороший, только когда полностью понял. То есть призыв сомневаться, понимать и проверять. А не клеймить.
«Новичкам можно посоветовать такое правило: любой недокументированный код, который вы не понимаете — плохой.»
А код плохой — это что-то типа презумпции невиновности, только наоборот. Если не понимаешь код — не говори, что он хороший, пока не поймешь. Говори что хороший, только когда полностью понял. То есть призыв сомневаться, понимать и проверять. А не клеймить.
Взаимоисключающие параграфы. То вы говорите, что код плохой, то вы говорите, что не нужно клеймить.
Так не нужно говорить что код плохой или код хороший, пока не понимаешь что он делает. Просто нужно либо ничего не говорить, либо говорить «я не знаю, не разобрал еще». особенно, если это новичок.
«As a beginner, you should just assume that any undocumented code that you do not understand is a candidate for being bad.»
«Новичкам можно посоветовать такое правило: любой недокументированный код, который вы не понимаете — плохой.»
«candidate for being bad» и «плохой» — так переводить не нужно.
17) Не ориентироваться на конечного пользователя — должен быть №1
26) Не задавать себе вопрос «а зачем»?
Про тесты не хочу холиварить, но это тоже про экономику. На этапе тестирования идей и поиска бизнес-модели тесты вредны.
Программирование – это на 90% изучение существующего кода и его изменение посредством маленьких, легко тестируемых порций, вписывающихся в общую систему. Само написание кода это всего лишь 10% работы программиста.
Программирование – это не просто написание строк кода, а творчество, основанное на логике, которое надо развивать в себе.
Ни прибавить, ни убавить
Вот например про комнату с одеждой. Есть одно большое правило, Работает — не трогай. Т.е. как только начнешь делать уборку в комнате хотя бы отдельного участка, так за ним посыпется все остальное. Без глубокого понимания того всего бардака и что с чем связано убираться очень опасно. А новичек уж точно не сможет ни разобраться ни поменять, а только что ни будь похерит, как уборщица на столе инжинера…
25 ошибок начинающего программиста