Comments 22
Но я считаю, что мы можем более согласованно сойтись на том, каким хотим видеть язык
Не можем, и это - одна из причин популярности php, python, c++, java и прочих подобных. Пока одна группа людей будет тратить время на выяснение того, какой подход – самый лучший, вторая будет писать больше прикладного кода так, как получается, и склеивать используя более гибкий язык.
В итоге у первой будет красивый hello world, а у второй - таки работающий продукт.
Проблема в том, что вы медленно окажетесь в мире, где каждая база кода написана на собственном подмножестве языка.
Не вижу ничего плохого в том, что кодовые базы разных проектов и организаций используют разный стиль. Важно, чтобы в одной и той же кодовой базе стиль был одинаковый.
Так же как и города во всем мире не обязаны быть как под копирку. Главное, чтобы на одной и той же улице рядом со строениями 18-го века не стояли небоскребы :)
Взять упомянутый язык Scala. В каких-то командах привыкли использовать его в "better Java" стиле, какие-то команды любят и умеют писать на Scala в функциональном стиле.
Было бы очень странно и бессмысленно всем в мире диктовать "используй от всей Scala только ООП подмножество" или "ты обязан писать на Scala исключительно в функциональном стиле".
Насчет строений не согласен.
Hidden text
Ну норм же смотрится: St Mary Axe - Google Maps
Даже в одном проекте живущем достаточно долго кодовый стиль не будет одинаковыми. Через какое то время выйдет новая версия языка, вам что-то из него понравится и вы начнете использовать новый стиль написания кода. А в какой то момент вы просто не сможете нанимать разработчиков которые готовы будут писать в старом стиле - на рынке их не останется. Но это неизбежно и предложение из статьи не поможет)
Даже в пределах одной версии языка на большом моно-проекте в разных частях присутствует разный стиль, т.к. за разные части большого проекта отвечают разные люди, весь проект кому-то одному физически нет возможности охватить, это слишком большой объем информации для человеческого мозга. Разные части еще и написаны в разное время и разными людьми, многих из которых уже нет на проекте. А неизбежная текучка приводит к постепенной утрате экспертизы, и через несколько лет уже не остается тех, кто знает код достаточно хорошо - начинают появляться велосипеды и дублирующая функциональность: люди не знают что уже что-то где-то в недрах кода решено, и пишут свои реализации, и эти реализации множатся. Старый код постепенно начинает отмирать - появляются и растут фрагменты кода, которые больше ни за что не отвечают, не работают, не вызываются, но их просто некому удалить, уже никто уже не может сказать можно ли этот фрагмент трогать, и не поломает ли это что-то, и желающих рисковать нет. Затрудняется поддержка: команда больше не контролирует кодовую базу, кодовая база начинает жить своей жизнью, пухнуть в размерах и сложности. Растет количество ошибок: команда не контролирует код, боится его трогать, никто больше не понимает как он вообще работает, из каких частей состоит - проект превращается в огромный черный ящик. Поддержка такого кода становится настоящей болью для команды, и все меньше и меньше людей хотят в это ввязываться, и деньги тут уже второстепенный фактор, нервы дороже. А еще за эту боль никто не доплачивает: можно уйти на туже или большую зарплату в небольшой молодой проект и забыть про легаси-монстров с огромными монорепозиториями и вечным хаосом, болью и страданиями
Собственно почему и имеет смысл большие проекты разбивать на отдельные части, и связывать их общим публичным интерфейсом, который стандартизируется и закрепляется в документации, и выносить их код в отдельные репозитории. Тогда совершенно не важно что разные части написаны в разном стиле, т.к. за них отвечают отдельные команды, которые их полностью контролируют. Сам код, и соответственно сферы ответственности команд, никак не пересекаются с другими частями проекта, важно лишь чтобы все команды придерживались единого публичного интерфейса. И самим командам проще работать с такими проектами: уже не нужно разрываться и растекаться по огромной кодовой базе, достаточно наработать экспертизу по той небольшой ее части, за которую отвечает твоя команда, что сделать не так сложно. Людей на такие проекты тоже проще искать: погрузиться в небольшую кодовую базу значительно проще, чем в огромного легаси-монстра, в его темные джунгли, которые полны неизвестности и опасностей. Важно что команда способна полностью контролировать свою небольшую часть кодовой базы, и, если нужно, даже переписать ее с нуля, т.к. в сфере ответственности каждой команды вполне конкретная и относительно небольшая часть общего функционала, роль этой части в общем проекте четко описана, ожидаемое поведение документировано, детали реализации полностью отданы в руки конкретной команды. Сейчас такие архитектуры модно обзывать микросервисными, но это не обязательно могут быть прям отдельные сервисы, главное разграничить код и сферы ответственности, стандартизировать интерфейс взаимодействия, иначе быть беде
"Старый код постепенно начинает отмирать - появляются и растут фрагменты кода, которые больше ни за что не отвечают, не работают, не вызываются, но их просто некому удалить, уже никто уже не может сказать можно ли этот фрагмент трогать" - Это не имеет никакого отношения дискуссии - неумение следить за кодовой базой и актуализировать её согласно фичам это отдельная проблема никак не связанная с кодстайлом.
"погрузиться в небольшую кодовую базу значительно проще, чем в огромного легаси-монстра" - это манипуляция - как сравнить фуллстака с фронтендером. Такой подход годится для гигантов на сотни человек, но если ваша команда в 10 - либо все должны знать всё, либо у вас появляется автобусный фактор а это критично. А изучать модульные проекты столь-же сложно если нужно знать все модули. При небольшой команде не получиться разбить проект по модулю на человека или два - все всё равно будут писать в модулях друг друга потому, что "фича нужна завтра а Ваня который отвечает за модуль занят другой задачей".
Плюс разбиение на части общающиеся через интерфейсы это обычно где-то между дорого и безумно дорого и не всегда производительно, хотя в целом подход хороший)
Моя идея в том, чтобы каждый релиз языка поставлялся с руководством по стилю. Никто не обязан ему следовать.
И не будет их читать. Чтобы это работало нужна реализация на уровне компилятора, чтобы можно было указывать в опциях, операторы каких стилей он будет считать ошибками. Тогда руководитель разработки сможет задавать единый стиль, в котором работает команда. Но создание такого компилятора скажем для Scala с учетом размытости границ между стилями очень сложная и неоднозначная задача.
Есть ruby где gem, bundler и все идиоматично, но Python победил.
Живу в Монреале и очень его люблю :) Часто программирую на C++ и, в зависимости от проекта, требований, конкретной компании - использую разные подмножества языка. То что, легче - не всегда лучше, и очень часто, "жить в городе с разными-разными районами" классно. Особенно, если во всем городе хотя бы единый стандарт электрической сети :)
Нужен формат файла, Внутри как там есть. А у каждого программиста и его тулзенях, показывается его стиль. Т.е. отдельть код, и стиль языка.
Не понимаю как это решит проблему кодовой базы огромного проекта который живёт и развивается на протяжении более 5 лет. Тут либо с выходом например новых фич в языке все на них переписывать, либо на годы похоронить себя (и проект) в парадигме возможностей языка 5..10ти летней давности.
Да никто ничего не переписывает. Работает - не трогай. Новые фичи в продукте можно реализовать и в рамках старой "изначально выбранной парадигмы", если всё впишется в неё.
Новые фичи потому и новые, что раньше их небыло. Вот нельзя было раньше в Dart вызывать конструктор без new, а сейчас можно. И у нас либо половина кода так, половина эдак, либо мы не используем новую фичу. А через 5 лет когда вы будете нанимать нового разраба и покажете ему ваш кодстайл - где конструкторы с new, точка с запятой в конце каждой строки, неиспользования лябд и прочие радости - он просто скажет - пойду ка я на другой проект. Сейчас схожая проблема у андроид-проектов которые не перешли на котлин а продолжили писать новый функционал на яве (это конечно новый язык, но сравнить оригинальный c++ и современный - тоже считай новый язык).
Не совсем понятно, что имеется в виду под "в рамках старой "изначально выбранной парадигмы", если всё впишется в неё ". Вот, например, раньше в С++ не было default в классах, а потом он появился. Можно его можно использовать, если код написан до того, как эта фича стала поддерживаться? Лямбд раньше не было, а потом появились. Можно их использовать, если весь код усеян std::bind1st, std::std::bind2nd ? Аналогично с auto и вообще со всеми остальными фичами, реализованными в C++ после выхода самой первой версии языка.
Именно так. Я даже больше скажу. 5 лет - не так уж и много. У нас в кампании есть С / С++ проект, который стартовал в 1995 году. Разумеется, с тех пор там многое переписано, но есть и немало кода из 90-х годов, т.к. он полностью рабочий и его ни разу не требовалось менять. При этом новые части, разумеется, пишутся с использованием фич из самой свежей версии С++. И что в таком случае предлагает делать автор? Переписать почти весь проект, чтобы он соответствовал последнему стандарту С++ ? Переписать не потому, что там баги, не потому что там спагетти, которое невозможно поддерживать, и т.п., а просто, чтобы все было на С++ 20 ? А с выходом С++ 23 снова все переписать, чтобы была возможность использовать фичи из нового стандарта? И делать так с каждым релизом С++? Внутренний голос говорит мне, что это, ну очень мягко говоря, не самая хорошая идея :)
Кто нибудь постановку задачи читал? У нас набор сервисов, над которыми работают 100 человек, грубо 10 человек на сервис = 10 сервисов.
Зачем нам сервисная архитекутра если мы требуем один язык и один стандарт?
Пусть каждая команда сама решает. Главное чтобы протокол взамодействия был нормально задокументирован.
В микросервисной архитектуре все так, да: каждая команда сама решает, без оглядки на остальных, главное чтобы протокол взаимодействия сервисов был документирован и соблюдался. Описанное в посте все же наверное больше проявляется именно в огромных монорепах: в одной части все на коллекциях, в другой на циклах, в третьей вообще рекурсия, а в четвертой автор упоролся в побитовые операции, потому что привык так писать для МК - несколько человек писали в разных стилях, как им было удобно, они свои задачи решили и забыли, а все последующие, стараясь соблюдать существующий стиль, продолжают писать именно в том стиле, который видят в конкретном месте кода, просто потому что проще сделать так, чем связываться с бюрократией и что-то менять. За редкими исключениями: у некоторых все же рано или поздно не выдерживают нервы, и они переписывают какие-то реализации в своем стиле, и таких переписываний туда-сюда за время жизни монорепы может быть несколько штук для одного и того же участка кода.
С микросервисами все гораздо проще: кода немного, его можно быстро понять, команда маленькая, можно со всеми договориться о чем угодно, ответственность за сервис полностью на команде, можно принимать самые смелые решения и делать так, как требуется, а не так, как вынуждает тонна легаси в монорепе, вот и получается что каких-то серьезных проблем с поддержкой просто не возникает, а те что бывают, их можно решить силами команды, просто пользуясь полной свободой в принятии решений.
Вася и Петя одновременно начали писать один и тот же продукт.
Вася был «ориентирован на результат» и начал сразу писать говнокод не продумав толком архитектуру.
А Петя месяц разрабатывал архитектуру, месяц делал удобный интуитивный интерфейс, которому позавидывал бы Джони Айв, потом месяц писал тесты, потом два месяца писал сам код и получил идеальное стабильное приложение.
Но Вася выпустил уже через месяц первую версию программы, пусть и не идеальную, пусть с багами, но рабочую, и начал её продавать. Ещё через месяц выпустил вторую версию исправляющие баги первой и добавляющие новые баги. Ещё через месяц на доходы от продаж нанял двух толковых программеров, которые за два месяца перелопатили весь код, согласно пожеланиям пользователей допилили интерфейс и выпустили третью версию программы.
Итого, через пять месяцев у Васи было два работника, куча клиентов и сносно работающее приложение отвечающее желаниям клиентов.
У Пети было вылизанное никому не известное приложение, минус на банковском счёте и ни одного клиента.
В завершение этого выдуманного примера можно сказать, что через полгода Вася купил все наработки Пети, Петю взял в штат тестировщиком.
А для смены парадигмы есть прекрасный паттерн strangler. Только из названия стоит про него знать. ?
Но Вася выпустил уже через месяц первую версию программы, пусть и не идеальную, пусть с багами, но рабочую, и начал её продавать.
В области OSS всё выглядит не так радужно: Вася выпустил программу и загадил поле. В результате, Петя даже не стал делать более продуманную версию, и все безуспешно воюют с Васиной программой, которая из-за плохой архитектуры изначально не может нормально решить задачу.
Вел за корону смертный бой со Львом Единорог
Гонял Единорога Лев вдоль городских дорог,
Давали им и черный хлеб, с черникою пирог,
А после же под барабан прогнали за порог.
Ещё хочется добавить что интернет поиск чаще всего выдает старые публикации (это и про книги и про статьи). И если у книг хотя бы есть год издания, то в статьях ещё и не всегда понятно сколько ей лет. Начинаешь их изучать и потом вдруг чисто случайно узнаешь что всё это был давно устаревший стиль и больше так делать не стоит, а как именно надо делать сейчас либо фиг найдешь, либо фиг поймёшь, ибо очень мутно изложено. И запросто можешь нарваться на то что "новый современный стиль" - на самом деле всего лишь очередной эксперимент, который не приживется потому что нежизнеспособен.
В общем всё сложно и непонятно как найти выход. Жёсткие рамки жёстко мешают - по сути они всего лишь один из стилей (скорее всего не самый удачный) просто зафиксированный. А свобода прекрасна, но может вызвать хаос.
Эффект Монреаля: почему языкам программирования нужен Царь стилей