Pull to refresh

Comments 77

> Диаграмма Ганта, Agile, Scrum, Экстремальное программирование, Пользовательские истории

О да. Какую же я испытываю ненависть ко всем этим скрумам и прочим модным штукам теперь, после участия в одном проекте. Меня прямо натурально бесило, когда вместо того, чтобы просто писать код или обсуждать какие-то нужные и полезные штуки тратили почти весь рабочий день на очередной митинг, 99% вопросов на «повестке дня» которого можно было бы решить в рабочем порядке, через скайп/почту, без отрыва ВСЕЙ команды от работы.
Да, по началу в этом утверждении кажется что-то неправильным — не хватает какой-то упорядоченности, что ли. Но со временем приходит понимание )
Значит ваш скрам-лидер (или что у вас там была за методология) мало что действительно знал.
При грамотном внедрении в процессы этих вещей творятся чудеса =)
Вот-вот. Каждый скрам-лидер думает, что он грамотный, и потому скрам будет творить чудеса. В результате практически весь процесс разработки — это надежда на чудо. А потом команда как минимум срывает сроки. Потому что чудес не бывает.
Митинг не должен превышать 10 минут, так что у вас что-то было не в порядке.
У нас так вообще был 5 минут.

Этот митинг как раз и был частью рабочего процесса, который лишь давал понятия каждому члену команды, кто и что делает сегодня.
Ну извините, мне кажется, что один раз договориться о стиле написания кода, табах, всяких camelCase'ах, запретить короткие тэги php — все это делается в начале разработки за полчаса, и потом никаких проблем, а работать с таким кодом приятнее, и форматирование кода не портится, когда открываешь файл с кодом в IDE, отличной от той, с которой работал автор файла (это я о табах и пробелах).
Более того — для этого есть специальные стандарты аля PSR* — один раз прочитать их и всегда следовать им — не так уж и сложно.
И никакие дни это не занимает, и деньги заказчика не ест.
Одно дело увлечение какими-то новомодными штуками, которое не приносит ощутимой пользы, а другое — простые вещи, следовать которым несложно и полезно.
Не нужно призывать писать код как попало — как раз это потом может сожрать деньги заказчика и время разработчика.
форматирование кода не портится, когда открываешь файл с кодом в IDE, отличной от той, с которой работал автор файла
Дык есть же компромисное решение, которое должно устраивать всех: отступы — табами, выравнивание — пробелами. И не портится нигде ничего, и регулировать размер отступа можно, и нет проблем при открытии «деревянным» редактором, который не вставит пробелы при нажатии таба сам. Нет же, продолжают упорствовать и настаивать на чём-то одном.
Не затруднит ли вас аргументировать?
Если разработчики используют разное форматирование, то при слиянии файлов могут быть проблемы. Трудно понять какие изменения в коде, а какие из-за смены табов на пробелы (или наоборот).
Собственно, если разработчики используют разное форматирование, то проблемы будут независимо от того, о каком конкретно форматировании идёт речь.

Или я чего-то не понял?
Напомню, Вы вверху попросили аргументировать, почему плохо использовать одновременно разное форматирование.
Я ответил на ваш вопрос: это ведёт к проблемам при слиянии файлов.
Нет, я попросил аргументировать, почему плохо использовать стиль форматирования «indent with tabs, align with spaces». Это не разное форматирование.
Я подумал вы про картинку спрашиваете.

А если про «indent with tabs, align with spaces», т.е. форматировать текст вручную, а не средствами IDE? ИМХО лучше использовать функционал автоматического форматирования IDE.
Я про картинку и спрашивал, просто я подумал, что смысл картинки в том, что «indent with tabs, align with spaces» — это плохо.

Про автоматическое форматирование я не уверен. Форматирование кода вручную — это не работа, это то, что выходит само собой. Точно так же, как значимые имена переменных. (А ещё я никогда не мог понять спор про значимые отступы в Питоне — ну как можно писать без значимых отступов, казалось мне).
форматировать текст вручную, а не средствами IDE
Vim так умеет (см. ссылку на вики ниже), студия в комплекте с решарпером тоже умеет. Если IDE не в состоянии обеспечить какой-то функционал, то это проблема IDE и повод допилить его плагинами.
Вот не понимаю. И почему это проблема? Что, действительно у кого-то НАСТОЯЩАЯ ПРОБЛЕМА от того, что разработчики используют разное форматирование?
Вообще говоря при слиянии веток использование разных стилей — это проблема. Автоматическая мержилка может посчитать изменениями то, что ими не является, и всё сломать.
На самом деле это не «компромиссное решение», а просто корректно реализованное «indent with tabs».
отступы — табами, выравнивание — пробелами

Статья — про вас. Я содрагаюсь от ужаса от одной мысли, что мне придётся следить за жёстким соблюдением порядка невидимых символов.

А если кусок кода откуда-нибудь копипастить… Скопипастил и сидишь, пробелы и табы балансируешь полдня.
следить за жёстким соблюдением порядка невидимых символов.
Это работа IDE и прочей автоматики, задаётся через вещи типа .editorconfig в корне проекта.
Скопипастил и сидишь, пробелы и табы балансируешь полдня.
У меня такое чувство, что противники табов пребывают в неведении относительно существования хоткея, заставляющего IDE переформатировать файл/выделенный кусок текста в соответствии с настройками.
Любители табов почему-то забывают, что первый аргумент за табы — это что «можно открыть в любом редакторе, и всё будет зашибись».

А тут — какая-то жёсткая зависимость от редактора. Я не могу открыть исходник в Блокноте и добавить одну строчку. А для Notepad++ есть плагин, который такое поддерживает? А в UltraEdit опция есть? Между тем, форматирование пробелами доступно абсолютно везде.

Такие правила абсолютно несовместимы с опен-сорсными проектами, потому что за предупреждение вроде «Нет решарпера для форматирования табов — не смей делать пулл-реквесты» поднимут насмех.

Конфиг решарпера надо распихивать по проектам и расшаривать, тоже лишняя работа.

В общем, куча лишних телодвижений с минимальным выхлопом. Всё ради чего? Чтобы кто-то мог читать сорцы с отступом в 2 символа, а не в 4? А оно правда настолько нужно?
А оно правда настолько нужно.
У меня табы настроены на двухсимвольный отсуп, мне так удобно, строки не разъезжаются на полэкрана (один отступ на неймспейс, второй на класс, третий на функцию, уже 12 пробелов, а я ещё ни строчки кода написал). И я такой не один. При этом заставлять всю команду делать себе отступ в 2 символа — явно не правильно, кому-то удобнее и привычнее жить со стандартными настройками.

Я не могу открыть исходник в Блокноте и добавить одну строчку
Можете. Более того, вам не надо будет руками набивать 12 пробелов (мы ведь про notepad.exe, правда?), достаточно три раза ткнуть в таб.
Между тем, форматирование пробелами доступно абсолютно везде.

Кнопка tab тоже работает везде, представляете?

Конфиг решарпера надо распихивать по проектам и расшаривать, тоже лишняя работа.

Его в любом случае придётся расшаривать, редко для какого проекта не приходится менять хоть одну настройку. Строго говоря как раз сам решарпер перенастраивать и не надо, достаточно .editorconfig.

Как бы то ни было, сей вечный срач предлагаю тут не продолжать, захламляем комментарии только.
У меня табы настроены на двухсимвольный отсуп, мне так удобно, строки не разъезжаются на полэкрана (один отступ на неймспейс, второй на класс, третий на функцию, уже 12 пробелов, а я ещё ни строчки кода написал).

Если в коде вложенность за 10 уровней, то проблема в коде. С массовым распространением широкоформатных мониторов мало кто ограничивает строки 80 символами, поэтому проблема 12 пробелов надумана — это от силы 10% от строки.

Кстати, вы используете решарперовское ограничение длины строки? Интересно, как ведут себя переносы при автоформатировании кода, если у одного разработчика таб одного размера, а у другого — другой.

Можете. Более того, вам не надо будет руками набивать 12 пробелов (мы ведь про notepad.exe, правда?), достаточно три раза ткнуть в таб.

А если нужен перенос строки, то мне нужно отсчитать три таба и десять пробелов.

Кнопка tab тоже работает везде, представляете?

Её включать-отключать не очень весело. Длина таба вообще в настройках VS хранится, решарпер её не перекрывает, поэтому индивиадульно для каждого проекта назначить невозможно. Рано или поздно возникает необходимость работать с сорцами «не своего» проекта — и тогда начинается веселье.

Это веселье проявляется при работе с любым кодом, автор которого решил проявить свою «индивидуальность»; не только из-за табов. В некоторые опен-сорсные проекты я пулл-реквестил решарперовские конфиги, чтобы о форматировании не думать. А вот с табами такое не сделать, хоть ты тресни. В баг-трекере JetBrains лежит запрос, но когда ж до него доберутся…

В общем и целом, мне, конечно, глубоко пофиг, кто как с пробельными символами извращается, пока я это не вижу и в этом не участвую. Вот только если сорцы выкладываются на публику, то очень желательно, чтобы отступлений от официальных рекомендаций по форматированию кода, по именованию и прочему было как можно меньше.
решарпер её не перекрывает, поэтому индивиадульно для каждого проекта назначить невозможно
.editorconfig, я уже давал ссылку выше в этой ветке, прочитайте сначала сообщения, а потом пишите длинные стены текста. Засим всё же предлагаю дискуссию закончить, всё равно каждый останется при своём мнении.
А, да. По поводу широкоформата. У меня монитор развёрнут на 90 градусов, потому разрешение у меня 1200х1920. Кода видно больше, пустого белого пространства справа от него меньше.
С массовым распространением широкоформатных мониторов мало кто ограничивает строки 80 символами, поэтому проблема 12 пробелов надумана — это от силы 10% от строки.
Вот даже прямо так? Мало кто? Android и Chromium, Linux Kernel иLLVM, а также многие другие проекты ограничиваются 80ю символами. Кое-где допускается больше, но в целом — 80 по прежнему «отраслевой стандарт».
Если смотреть только сишные и плюсовые проекты, принадлежащие компаниям, которым больше десятка лет, разумеется, каких только анахронизмов не найдёшь. Здесь важно единообразие кода. Сам Гугл пишет:
We recognize that this rule is controversial, but so much existing code already adheres to it, and we feel that consistency is important.
The 80-column limit is an hidebound throwback to 1960s mainframes; modern equipment has wide screens that can easily show longer lines.

Грег относительно «проблемы 12 пробелов» однозначно высказывается:
The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program.

Я сужу со своей шарповой колокольни, конечно, но 80 символов практически нигде не встречаю.

Кстати, глянул отношение к табам: у половины пробелы, у половины жёсткий размер таба в 8 символов. Интересно, есть ли среди старичков те, кто разводит пробельно-табовый зоопарк.
The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program.

using + try/catch + два вложенных цикла… Уже 4 уровня. Прибавляем 3 уровня связки неймспейс-класс-функция, получаем 7 отсупов (28 пробелов). Для сишки, может, он и прав, но к шарпу плохо применимо. Особенно если используются сложные конструкции с LINQ.

Из действительно крупных проектов с кодовой базой на C#, где используются табы, могу навскидку назвать Mono.
Глянул. Непривычные у Моно стандарты. Пробелы в вызовах методов… Но что они ядрёными стандартами вдохновлялись — это ясно.

Читаю сорцы. Куда ни плюнь — стандарты лесом. Файлов, соблюдающих ограничение в 80 символов, найдено не было. :))

github.com/mono/mono/blob/master/mcs/class/System.Core/System/TimeZoneInfo.AdjustmentRule.cs — 80 символами и не пахнет.
github.com/mono/mono/blob/master/mcs/class/System.Core/System/TimeZoneInfo.Android.cs#L361 — неправильная смесь пробельных символов, вообще во всём файле табы для выравнивания при переносе строк.
github.com/mono/mono/blob/master/mcs/class/Microsoft.Build/Microsoft.Build.Construction/ProjectChooseElement.cs — отступы пробелами.
github.com/mono/mono/blob/master/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/Binder.cs — переносы фигурных скобок не соблюдаются.

Табы, конечно, есть, но если их настроить на что-то отличное от 8 пробелов, то код поедет. А если размер таба жёсткий, то спор «табы против пробелов» невозможен, потому что пробельные символы ни на что не влияют.

В общем, стандарт кодирования или адекватный, или не работает.
Мы договорились делать выравнивание тоже табами, просто первый параметр (при наличии нескольких) тоже переносится. Вполне читаемо, да ещё и занимает меньше места по горизонтали при длинных названиях функций.
И не нужно никаких компромиссов)
+1.
Да и неужели так сложно следовать этим правилам, которые вдруг у вас «отнимающих часы, а то и дни программистского времени»? А вот функции > 100 строчек, с кучей всевозможных if-ов вложений… вот что отнимает часы, когда задача занимает 3 часа исследований и 2 строчки правки кода… Когда вызываешь функцию, а она не делает то что ожидаешь, т.к. в ней костыль из ифов на 600 строк, используются глобальные переменные с именами «ttmb, sa, qa », а разработчик, который это все делал уже давно уволился.
Если почитать статью, становится ясно, что автор не против самих соглашений, автор против излишнего фанатизма. Очень хорошо, если ваши ф-ции меньше 50 строк, но плохо, если вы пытаетесь переписать в соответствии с этим правилом все, уже существующие, ф-ции
Все это обычно ерунда. Какие-нибудь индусы столкнувшись с каким-нибудь Сонаром отлично разбивают все длинные методы на куски по несколько методов ровно по 25 строк в каждом (чтоб запас был). Понятно, что код от этого лучше не становится.
А дрянь можно написать и в 3 строчки.

Недавно был пост перевод текста человека из IBM, который рассказывал как они писали OS/2 ( habrahabr.ru/post/188202/ ), вот он там вспомнил о том какими полезными оказались количественные метрики:
Синий гигант довел свои причудливые показатели производительности — количество KLOC-ов, тысяч строк кода — до такого состояния, что используемые нами редакторы исходного кода устанавливались вместе с макросами, помогающими увеличить число строк в коде, например, разбивавшими комментарии C на множество строк, чтобы ваш код соответстовал невероятно тупым показателям. И внезапно все начинало выглядеть хорошо.
Какие-нибудь индусы столкнувшись с каким-нибудь Сонаром


Наши нашли тег //NOSONAR и понаставили везде.
да… какие-то жалкие 600 строчек костылей… мне недавно пришлось разбираться с исходником на 590кб костылей. Строчки не считал, побоялся… после удаления лишних пробелов файл похудел на 90кб. Костыли копились годами, но зато какие! Читаем из базы данных поля(на каждый день месяца отдельное поле) и в зависимости от содержимого поля на каждый день по два IF-а и простое действие, и так 3 раза с разными проверками и действиями НА КАЖДЫЙ день месяца отдельно… что такое циклы… их придумал извращенец!
да, плюс ко всему была использована команда GOTO…
Выбираете стиль, который прямо противоположен привычному Вам стилю написания кода. Пишите код в таком стиле пока не привыкните. Потом устраиваетесь на работу, где в качестве стандарта выбран стиль, отличающийся от вновь освоенного Вами. Пишите код пока не привыкните. Повторяете процесс заново несколько раз.
один раз договориться о стиле написания кода, табах, всяких camelCase'ах, запретить короткие тэги php — все это делается в начале разработки за полчаса

Далеко не всегда получается договорится даже за несколько часов.
Я вообще давно презрел все эти стили и практики — ну хороший код остается хорошим кодом и не важно стоят там скобки по Кнуту/Алберту/Кернигану-Ритчи, а плохой — ну вы поняли… С табами/пробелами аналогично — я вообще считаю что большинстов дорогостоящих ошибок заложены не в конкретной строчке кода, а в структре проекта — самое страшное когда понимаеш что новую фичу или фикс придется тащить через весь каркас проекта и понимать что есть риск что что-то отвалится. После такого мне кажется полным маразмом цеплятся к тому как стоят скобки и как выровнен код.
Тем не менее programming guidelines никто не отменял и обще принятый стандарт, все же, должен быть.
Гайдлайны не самоцель — мне искренне жаль тех людей кому приходится об этом напоминать. :(
Есть Best practises и есть здравый смысл, у хорошего программиста они никогда не противоречат друг другу, а дополняют.
Мне кажется нельзя смешивать в кучу стиль написания кода, стиль программирования и паттерны. Для всего должна быть своя причина, весь срач о том sql или nosql можно решить просто подумав что в итоге нужно, ровно как и остальные вещи
Мне кажется, должен быть один главный у команды. Который всех послушает, быстро решение примет, и все ему будут следовать. Не нужно 6-часовые встречи устраивать и тратить оплачиваемое время на споры.
UFO just landed and posted this here
UFO just landed and posted this here
Выбирается президент, который говорит, как всё будет сделано. И все следуют его воле, даже если считают его решение глупым. Это очень просто и не нужно никаких споров.
Так демократия и работает.
Ну, если люди считают решения президента глупыми, то их весьма наглядно характеризует их «умное» решение выбрать именно этого президента.

Если аналогия не очень прозрачна, то поясню: если человек не может принять как данность единые правила, установленные выбранным на общем собрании человеком, то чем лучше лучше для общего блага будет его индивидуальная непримиримая позиция по поводу этих единых правил? Или вы отрицаете необходимость единых для всех правил в принципе?
С помощью аналогии про президента я пытался указать на чересчур идеалистическое и противоречивое содержание комментария. У людей есть собственные мнения и чувства (зачастую обоснованные). И, если в коллективе существуют сотрудники, считающие выбранный стиль глупым, то могу предположить, что насильное следование этому стилю будет вызывать у них постоянное раздражение, выплёскивающееся в других ситуациях.

Что касается стиля кодирования, то я считаю, что следует отдавать предпочтение языкам, сводящим к минимуму вариации стилей. А вместо единоличного выбора стиля одним человеком (я подразумеваю случай, когда стиль выбирается на основе личных предпочтения этого человека, а не на основе рационального анализа вариантов написания конструкций языка), проводить обсуждение и выбор стиля на основе общего мнения (т.е. на основе мнения тех, кто непосредственно будет использовать этот стиль изо дня в день).
Ну, вы меня простите, президент же не от балды принимает решения =). У него целая армада консультантов, советников и прочих техспециалистов, подсовывающих ему под руки на выбор несколько готовых стратегий, из которых можно выбирать. Плюс он повязан обещаниями, данными электорату и парламенту, что ещё больше ограничивает его в действиях. В этом плане я вообще не уверен, что позиция президента в современном мире вообще нужна.
Так что если в вашей аналогии было заложено предположение об использовании личных предпочтений, то вряд ли такая аналогия справедлива.

Ну а использование языков программирования с уже заложенными стилистическими ограничениями разве не будет вызывать то же раздражение у разработчиков? Ведь на этот раз их лишили свободы с самого начала, и если мы исходим из предположения, что люди ригидны и подстраиваться под чужие решения не могут, то эффект выйдет ровно тот же самый, только на этот раз виноват не член твоей команды, а разработчик языка, принимавший решения, и на это решение повлиять уже в принципе невозможно.
> Так что если в вашей аналогии было заложено предположение об использовании личных предпочтений, то вряд ли такая аналогия справедлива.

Нет, этого заложено не было. Речь шла исключительно о легкомысленных, на мой взгляд, фразах «и все следуют его воле, даже если считают его решение глупым» и «это очень просто, и не нужно никаких споров». Да и аналогия эта была по большей части шуточная, не стоит её так серьёзно воспринимать.

> Ну а использование языков программирования с уже заложенными стилистическими ограничениями разве не будет вызывать то же раздражение у разработчиков?

Я предположил, что программисты сами уже предпочли такой язык и на работу набираются именно эти программисты. Если брать случай с языком, в котором возможно множество вариаций стилей, то на работу набираются программисты, которые сами предпочли и указанный работодателем язык и указанный работодателем стиль кодирования.

Я предположил, что в случае в ограничивающим языком разнообразие программистов, отличающихся друг от друга по стилю кодирования, в таком сообществе будет меньше и, соответственно, работодателю будет подходить большая часть программистов из этого сообщества. Плюс я предположил, что именно наличие в языке возможности использования множества вариаций стилей кодирования порождает разнообразие отличающихся по этому признаку программистов, а не наоборот (когда сами программисты, следуя своим желаниям, порождают разнообразные стили кодировании, переделывая язык — в таком случае работодателю будет подходить одинаковое кол-во программистов из обоих сообществ).
Может еще при наборе работников указывать цвет предпочитаемой туалетной бумаги?
Только если походы в туалет являются важной частью технического процесса.
P.S.: случай с указанием работодателем языка и стиля кодирования я указывал в качестве аналогии.
Поход в туалет, как и работа в определенном стиле явно влияет на качество кода… если в туалете розовая бумага, а я люблю зеленую это не может не влиять.
Вы на работе часто слышите споры между программистами по-поводу цвета туалетной бумаги?
По поводу стиля кодирования, отступов и т.д. я споров тоже ниразу не слышал. В команде, работающей над одним проектом обычно все эти вещи документируют в самом начале и все затем следуют документации.
Тогда перечитайте статью, к которой пишите комментарии. Она как раз этой проблеме и посвящена.
Стиль кода используется постоянно при написании кода, а туалет лишь изредка (я предполагаю, что Вы не на толчке код по 8 часов в день пишите).
Думаю, куда проще один раз в компании разработать файлик с правилами для статического анализатора кода (StyleCop, CheckStyle, JsHint), а потом просто вставлять в каждый проект.
UFO just landed and posted this here
После этой статьи пополнятся ряды фетишистов, отрицающих все стандарты.
По идее я согласен с автором, но в частности многие вещи не соответствуют реальности. Те же отсупы и скобочки приводятся к нужному виду за минуту
php php-cs-fixer.phar fix /path/to/project --level=all
RESTful при использовании laravel ускоряет разработку в разы
Выбор правильного стораджа и знанине его сильных слабых сторон и вовсе может спасти либо угробить проект.

Всё хорошо когда в меру и без фанатизма.
Как показала личная практика работы, оптимальным вариантом является создание спецификации, как должен выглядеть код в проекте. И жёсткое правило для команды: работаешь над проектом — будь бдобр, придерживайся общего стандарта.

Мне не встречались описанные автором перегибы, но много раз видел другую сторону медали. Последний яркий образец проекта, где CSS «размазан» по десятку файлов, в каждом «потоптались» несколько разработчиков, которым было наплевать на дальнейшую судьбу файла (в одной декларации и табы, и пробелы, и в одну строку код). Сидишь, разгребаешь завалы.
Как много, оказывается, проблем в команде может решить простая фича в IDE «Reformat Code».
«Свобода есть осознанная необходимость».
Методологии, технологии, стандарты, стили кода, функциональные и архитектурные решения [вроде весь список из статьи классифицировал],… это всё есть ограничения свобод, которые разработчики также осознанно выбирают. Если команда ограничивает себя без понимания необходимости (повинуясь только моде!), то это серьезная организационно-техническая беда. Такая команда много теряет из-за неосознанного использования системных подходов
зачем-то придуманных другими для неизвестных и непонятных целей, а может и совсем иных задач.

«У меня красивый индивидуальный почерк и хочу чтоб мои творения по нему узнавали!»
Непонимание отдельными участниками команды причин выбранных ограничений есть серьезный повод для руководителя задуматься о:
а) повышении квалификации сотрудников
б) улучшении методологической базы своих проектов.
Давно перестал форматировать код руками и доверяю эту работу специальным программам-стайлерам.
Конфиг пишется 30 минут, работает всегда и для всей команды. У меня hook сделан в vim'е, запускающий форматирующий скрипт при сохранении файла.
Время потраченное мной на приведение такого кода к виду, соответствующему моему эстетическому вкусу — будет просто тратой денег клиента.

Есть программы для автоматического приведения кода к любимому стилю, например astyle. Когда передают код, где всё оформлено непривычным способом, да ещё без единой системы, такие жесткие меры могут быть оправданы.

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

То же самое касается остальных «фетишей». Пока ваш проект умещается в десятке классов и в голове одного разработчика, всякие строгости только мешают. Но как только число классов перевалит за сотню и в одиночку с ними станет невозможно работать, да еще все это будет разбросано по автономным узлам, которые независимо что-то обрабатывают и разрабатывают — вот тут жесткий орднунг нужен для сдерживания «рака кода», когда каждый новый разработчик не разобравшись в имеющемся коде и архитектуре начинает приделывать свои «ноги и костыли», которые не вписываются в архитектуру и еще больше усложняют ее.
Sign up to leave a comment.

Articles