Русский
Русский
English
Статистика
Реклама

Блог компании plesk

Введение в TLS для практиков Патриков (часть 2)

18.06.2020 12:21:50 | Автор: admin
Сегодня мы продолжаем разбираться, как устроен TLS и чем он может быть полезен Патрику и его друзьям. Первую часть истории можно прочитать тут.

Мы остановились на том, что сервер отправил свою часть TLS-handshake клиенту. Теперь клиент должен прежде всего проверить сертификаты и это самая тяжелая из вещей, которые ему обязательно надо сделать.



Certificate verification: chain


Возможно, вы обратили внимание на формулировку: посылается не сертификат, а сертификаты сейчас станет понятно, почему (в общем-то, догадаться нетрудно).




Сертификат подписывается ишьюером тем человеком, который этот сертификат выписал. Для того, чтобы считать этот сертификат правильным и все данные в нем верными, мы должны доверять этому ишьюеру то есть верить, что он всякую фигню не подписывает. Чтобы вся эта система работала, придумали такую концепцию как корневой сертификат (root certificate).

Root certificate


В принципе, это даже не обязательно должен был быть сертификат вполне хватило бы просто пары ключей. Потому что единственное, что нам от него надо это знать, что такому-то центру сертификации (Certificate Authority, CA) соответствует такой-то публичный ключ. Тогда мы можем проверить все сертификаты, которые он выписал, и если мы считаем, что CA не врет, значит, и в сертификатах всё верно. Так что на самом деле Root CA Certificate это такой же сертификат, как и все, просто самоподписанный.

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



Intermediate certificate


Следующий в цепочке Intermediate Certificate. Зачем он нужен? Дело в том, что в случае, если с Root CA Certificate что-то пошло не так, очень сложно его поменять. Центру сертификации нужно сделать новый приватный ключ, новый публичный ключ, всем это всё нужно обновить и так далее, это утомительно и это ломает всю секьюрити. И вообще, чем меньше мы работаем с машиной, на которой находится этот CA, тем меньше шансов, что этот приватный ключ украдут. Поэтому CA выписывают промежуточные сертификаты и уже с их помощью подписывают конечные (end-entity) сертификаты для вашего домена. Такая цепочка происходит очень часто и сертификат для нашего Патрика может быть подписан Губкой Бобом, а сертификат Губки Боба Мистером Крабсом (а Губка Боб работает на мистера Крабса, как мы знаем из мультика). То есть это, в принципе, может быть вообще одна организация. Для того, чтобы всё это провалидировать, клиенту нужно всю эту цепочку составить и проверить: взять ключик рутового сертификата, проверить, что промежуточный правильный и подпись валидна, потом взять ключик промежуточного сертификата и проверить конечный сертификат.

Цепочка должна присутствовать в списке сертификатов, которые сервер отсылает. По факту бывает всякое. Бывает, что не посылаются. Symantec, например, очень любил в бесплатные сертификаты не вставлять промежуточный. И поэтому в браузерах ничего не работало.

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



Поэтому если вы видите сертификат, в котором этих полей нет, можно возбудиться и что-нибудь покопать возможно, там всё не очень хорошо.

Basic Constraints


Еще одна штука, которая улучшает секьюрити (и с этим были серьезные баги до 2003 года в Internet Explorer): в промежуточных сертификатах в поле Basic Constraints должно быть написано CA: true, что означает, что этим сертификатам разрешено подписывать конечные сертификаты. Если этой штуки нет, то клиент при проверке цепочки должен сказать: я не могу принять этот промежуточный сертификат несмотря на то, что все подписи совпадают, в субъекте всё совпадает и т.д. Этой штуки нет до свидания. Internet Explorer не делал этой проверки и люди страдали из-за этого. Казалось бы, мелочь! Но тем не менее.

Еще раз, если кто не понял: если эту штуку не проверять, я могу получить сертификат от Lets Encrypt и потом этим сертификатом подписывать что угодно. И цепочка будет валидная.

CAPI и SCVP


Еще про верификацию и про цепочку. Есть маленькая особенность похвалим здесь Windows. Если сервер не отдал сертификат, в обычном (традиционном) подходе сертификат нам взять неоткуда, цепочки нет, всё сломалось. Так вот, в Windows есть такая штука как Certificate API, и она может достроить цепочку, взяв промежуточные сертификаты из своего хранилища. То есть, даже если сервер не передал, но у тебя в хранилище они есть, то цепочка построится и всё будет работать. Достаточно удобная штука, можно пересылать меньше информации, не уменьшая секьюрити.

Как эти сертификаты туда попадают? Либо залиты в хранилище, либо из сертификата, установленного на сервере. Например, в Plesk, если получить сертификат от Comodo и поставить его на домен в хранилище попадет промежуточный сертификат от Comodo.

Ну и еще люди, которым Windows нравится, придумали SCVP (Server-based Certificate Validation Protocol). В действительности не работает почти ни у кого и нигде в смысле глобально и массово, но как концепция есть. Более того, есть продукты, которые это делают, и даже в каких-то сетях это может быть настроено. Это сервис, который за тебя эту цепочку строит и частично даже проверяет, что удобно. Если там заявлена поддержка DPV (Delegated Path Validation), то он цепочку еще и провалидирует. То есть, клиенту надо этому сервису отправить сертификат и получить ответ продолжать сессию или рвать.


Предположительно это могло бы всё ускорить, но из-за того, что сервису тоже надо как-то доверять, идея глохнет. И всё-таки она была.

Итак, вот у нас получается такая вот цепочка.



Прежде всего мы проверяем, что с подписями у нас всё нормально: выстраиваем цепочку, проверяем подписи и считаем, что содержимое сертификатов верно. Дальше нам надо проверить конечный сертификат. Промежуточный нам проверять не надо, потому что мы идем к Патрику и проверить нам надо только самый последний сертификат.

Давайте проверять.

Certificate verification


Подпись


Про подпись уже упоминалось. Это вот пример, как это может выглядеть структурно: вот есть подпись, вот алгоритм этой подписи, мы берем какую-нибудь библиотечку, которая умеет с этим работать и проверяем, что тело сертификата подписано вот этой подписью и что всё действительно хорошо.



Дальше мы из этого сертификата достаем следующие поля и начинаем проверять их. Вы видите, что ишьюер у нас Global Sign, мы взяли его ключик и проверили, что подпись работает.

Не протух ли сертификат?


После этого нам надо проверить, что сертификат не протух это логично, ведь сертификаты выдаются на какое-то время.



Сейчас все certificate Authority договорились, что максимальный срок 2 года (раньше было 3). Еще дальше они хотят сделать 1 год, а некоторые радикалы хотят, чтобы был месяц. Lets Encrypt сейчас на 3 месяца выдает. А совсем радикальные радикалы хотят на каждое соединение новый сертификат выписывать. Почему некоторые люди так этим озабочены, станет понятно попозже, когда дойдем до пункта Не отозван ли сертификат?. Еще из интересного сертификат может быть выписан на будущее, так что надо проверять дату старта (по-хорошему).

Тот ли домен?


Тут всё понятно: если домен Wikipedia, а сертификат выписан на домен Plesk, то что происходит вообще? Кажется очевидным и капитанистым, но было несколько багов, когда клиенты это не проверяли. Сейчас, по счастью, такого бардака уже нет и стараются проверять все. Но опять-таки есть нюанс. Это SAN Subject Alternative Name.



Subject Alternative Name


В subject у нас может быть только один домен в нашем случае там, кстати, есть звездочка, про это попозже, это так называемый wildcard-сертификат. Итак, в субъекте доменное имя одно, но если хочется много (например, у нас есть сабдомены и/или разные имена типа plesk.ru, plesk.com и т.д., и хочется один сертификат на это всё иметь) тогда есть возможность всё это запихать в это поле SAN. Но нужно, чтобы это работало, во-первых, на сервере, во-вторых, на клиенте. Потому что, чтобы сервер отдал правильный сертификат, клиент должен ему как-то передать, куда конкретно он пришел. Это важно. И когда сервер выбирает сертификат, он должен знать Subject Alternative Name, потому что, может быть, имя домена там. За всё это отвечает такое расширение TLS, как SNI (Server Name Indication), на эту тему есть 4 RFC, короче, возможность есть, но не все это поддерживают. Например, у продуктов на GNU TLS с поддержкой SNI всё неплохо, а вот на OpenSSL многие не поддерживают. Кажется, это потому, что в GNU TLS это проще.

Ладно, мы, допустим, всё это умеем. Всё хорошо, всё проверили, пришли сюда.


Как мы должны проверять wild-card? Отдельный момент. Можно просто запомнить: звёздочка это не вообще звёздочка, а только один сегмент.

  • Если хотим на domain.com нам нужно без звездочки.
  • Если хотим на foo.bar.domain.com нам нужно *.bar.domain.com.

Поэтому wild card сертификат без SAN используется довольно редко. Хочется защитить не только сабдомены, но и сам домен а поле у тебя одно. С этим связаны интересные штуки, как определить, насколько сертификат хорош есть разные рекомендации. Например, Google Chrome форсит людей на то, чтобы даже если в субъекте у тебя прописан domain.com, то чтобы в SAN он тоже был, потому что они хотят проверять только поле SAN, а субъект не проверять. Но пока еще проверяют.

Еще интересный момент, что www.domain.com это отдельное имя, и если мы хотим по нему ходить, его надо защитить отдельно. Не у всех это в голове есть.

Ну и да, как уже говорилось, серверу надо найти сертификат для домена. Как работает SNI клиент в определенном заголовке передает, какой домен нужен. Поэтому это доступно даже на уровне TCP, где доменных имен нет в TLS есть, а в TCP (и в FTP) нет. Поэтому если мы делаем TLS, мы можем передать имя, но мало передать имя надо же серверу найти этот сертификат, и здесь есть разные нюансы с разными продуктами. Продукты на Windows нередко находят этот сертификат в хранилище сертификатов, а для продуктов на Linux нужно указывать конфиги, где брать эти сертификаты. И здесь тоже есть разные проблемы. Мы недавно чинили SAN в Postfix там может быть очень простая вещь мы, например, указываем, что для domain.com сертификат такой, а человек приходит c mail.domain.com. А mail.domain.com это не domain.com. Всё, сервер не может найти сертификат, всё развалилось. То есть кому-то надо указывать, кто-то сам находит. Для тестирования и разработки это важная вещь в аспекте SAN.

Ок, пойдём дальше.

Тот ли тип использования?


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



Сертификаты бывают разные. То есть, если в Key Usage не указаны вот эти вот два параметра, то это по идее! должно влиять на то, как клиент с этим работает.

Key agreement это как раз когда мы выписываем сеансовые ключи и договариваемся о них. Обычно вся эта коммуникация подписывается или шифруется вот этим вот публичным ключом, который чуть выше. Но если в key usage не прописан key agreement, то это означает, что ишьюер этого сертификата запрещает использовать этот сертификат для вот этого назначения. Сейчас на практике это почти не встречается, то есть эти вещи у большинства сертификатов одинаковые, но тем не менее в принципе могут быть и другие. И бывает, что сертификат НЕ подходит для чего-то. Для чего он подходит написано здесь. Клиент должен это проверять. Кстати, нередко бывает, что в extended key usage вот это вот TLS Web Server Authentication у промежуточных сертификатов отсутствует.

Не отозван ли сертификат?


Самая интересная вещь мы дошли до нее, ура! Самая прикольная, самая неработающая :)

Если говорить кратко, то сейчас здесь во всей инфраструктуре TLS очень большие проблемы, потому что: не работает ничего. И эту проблему как раз и хотят решать тем, чтобы срок действия сертификата сделать очень маленьким. Когда нужно отзывать сертификат? Чаще всего когда ваш приватный ключ утек. Ваш приватный ключ утек вы попали. Надо сертификат отозвать, потому что если не отозвать, тот кто украл ваш ключ, сможет подсовывать клиентам ваш сертификат и представляться вами. Надо сказать: чуваки, я поменял свой ключ тот сертификат не действителен!

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

Как же проверить, отозван сертификат или нет?

Certificate Revocation List


Изначально сделали что (и это до сих пор работает, и это до сих пор по-хорошему надо проверять): Certificate Revocation List. То есть тупо список сертификатов (их серийные номера с ишьюерами), которые отозваны. Ну, вы представляете, сколько за время существования SSL и TLS было отозвано сертификатов очевидный минус в том, что список здоровый. Для того, чтобы понять, отозван сертификат или нет, тебе этот список надо откуда-то скачать, а значит, надо доверять тому, у кого качаешь, ведь там могут подменить, потом себе вгрузить, распарсить и проверить, что вот этого сертификата, который ты проверяешь, там нет то есть посмотреть тебе надо всё. Поэтому это всё медленно, а еще это единая точка отказа. Есть специальные атаки, когда вот этот URL, по которому надо проверять CRL, просто DDOS-ят, клиенты не могут скачать список и расценивают ошибки скачивания как всё хорошо (нет списка значит, всё хорошо).



Поэтому этот механизм считается устаревшим, но в стандартах всё еще есть и по-хорошему надо бы его использовать. Google Chrome на него забил уже давно, Mozilla тоже.

OCSP


Есть другая штука OCSP. Это примерно то же самое, только вместо того, чтобы качать файлик, делается специальный запрос на то, чтобы та сторона сказала тебе отозван сертификат или нет. То есть, клиенту стало проще, а вот чуваку на той стороне проще не стало, потому что вместо того, чтобы просто отдавать список, надо по этому списку проверять запрос и говорить да или нет. Если основываться на CRL, другого варианта, кроме этого, особо-то и нет и это действительно лучше, чем чистый CRL. Тем не менее, Chrome забил и на это, остальные пока используют.

OCSP stapling


Это примерно в ту же степь, но тут мы уже начинаем уходить от структуры Certificate Authority. То есть возлагаем эту проверку на сервер. Как это работает: сервер периодически ходит по этому OSCP URL-у и говорит: OCSP-resolver, посмотри-ка, вот этот мой сертификат в отозванных или нет?. OCSP-resolver отвечает подписанным ответом, наш сервер его запоминает, и когда клиент приходит, ему отдаётся этот ответ. То есть у клиента есть подписанный ответ и в нём написано, что всё хорошо. Из-за того, что серверов меньше, чем клиентов и сервер может на какое-то время это кэшировать, нагрузка на всех становится меньше.



Тут есть тоже некоторые проблемы: текущий механизм это только на один сертификат, а у нас цепочка (и это важно). А еще, из-за того, что мой сервер отвечать на это не обязан, клиент не может рассчитывать на то, что OSCP-stapling точно будет. И поэтому отказаться ни от CRL, ни от OCSP не получается просто потому, что серверы не обязаны опрашивать и отвечать. Ну и еще один аспект: если в вебе с этим нормально, то в почте всё плохо, а в FTP даже слов таких не знают.

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



Вот это всё вместе теоретически может начать работать, но пока еще мало распространено.

Google и Mozilla, так как им всё это не нравится, сделали свой CRL. И зашили его в браузер. Огонь вообще! Это работает быстро, ну и на этом все плюсы заканчиваются. Для того чтобы не помереть, они не запихивают в него DV-сертификаты. То есть если DV-сертификат отозван, они считают ну и ладно. Так что если DV-сертификат отозван и при этом нет OSCP-степлинга, Chrome об этом не скажет он посчитает этот сертификат нормальным. На самом деле, правильно пользоваться OSCP-степлингом и OCSP Must Staple флагом в сертификате. С ним тоже не всё просто большинство генераторов CSR сейчас не умеют его указывать, а большинство Сertificate Authority не умеют его выписывать.

Сertificate Transparency


Итак, всё хорошо, но Google не был бы Google, если бы не придумал еще одну технологию конкретно для себя. Она называется Сertificate Transparency. Откуда что идет: Google очень беспокоится о том, чтобы кто-нибудь не выписал плохой сертификат на него самого чтобы именно Google не пострадал от того, что кто-то там выписывает какие-то нехорошие сертификаты. И вот с помощью Сertificate Transparency каждый владелец домена (и вообще кто угодно) может посмотреть, какие сертификаты на этот домен были выписаны. Дальше он может этот сертификат взять и с ним что-нибудь сделать. Например, проверить, хороший он или нет. Ну и возбудиться (или не возбудиться).



Это не только технология, но и набор процессов. То есть Google говорит: ребята, вот у нас есть Сertificate Transparency, мы в него записываем только нормальные сертификаты такие, где цепочка есть, цепочка правильная и всё нормально. Мы можем время записи Сertificate Transparency Log запихать в сертификат, чтобы клиент мог четче посмотреть, что вот этот сертификат в Transparency Log должен быть тогда-то. Мы гарантируем, что это вот эта штука не редактируема обратно (из-за того, что блокчейн) ну то есть нельзя взять и подменить старые записи, можно только добавлять новые. И давайте, ребята, кто-нибудь из вас будет периодически ходить по этому логу, и проверять, что там всё нормально, а если что-то не так, говорить нам и мы будем это править. А другие ребята пусть держат у себя всё это, потому что надо, чтобы было много мощностей на вот эту вот штуку.

Сейчас Сertificate Transparency поддерживает DigiCert, недавно начал поддерживать Lets Encrypt, а вот из валидаторов практически никого нет, Google сам всё это делает. Когда всё это заработает в полную силу и валидаторов станет больше, то плохих сертификатов должно стать меньше, потому что кто-нибудь будет возбуждаться. На картинке показан HTTP-заголовок Excpect-CT, его можно отдать и клиент будет обязан сходить в Сertificate Transparency и проверить, что вот этот сертификат в нем указан. А из-за того, что там еще есть timestamp, сложнее становится запихать плохую запись в Сertificate Transparency. Но, опять-таки это не очень помогает с Revocation, можно сказать, вообще не помогает. Это только про то, что все сертификаты, выписанные на домен, владелец домена может посмотреть и возбудиться.

Вот такая вот штука. По большому счету хайпа много, но ничего она не решает. А что решает (каким-то образом), но не используется это DANE.

Дополнительная защита


Вся структура TLS является уязвимой в одной точке точке доверия, то есть вот эти вот сертификационные центры, рутовые сертификаты если с ними что-то не то, всё разлетелось. Есть по сути две попытки с этим как-то бороться.

DANE


Первая попытка, собственно, DANE хранить информацию о сертификатах в DNS.


Почему это должно работать потому что DNSSEC. Certificate Authority здесь могут вообще в принципе отсутствовать, можно даже без них. Сейчас DANE используется примерно для того же, для чего HPKP (следующий пункт рассказа) для того, чтобы в базе данных DNS держать информацию о том, какой публичный ключ должен быть у сертификата. То есть это, по существу, еще одна связочка. Можно указать: мой публичный ключ такой-то, и когда клиент получит сертификат и там посмотрит ключ, он сможет из DNS посчитать хэш и если не совпадет, заорать меня хакнули. Так что, чтобы в случае с DANE украсть сертификат, надо еще и на стороне DNS что-то сломать. В этом плане эффект есть. В Голландии, например, DANE обязателен для сервисов, которые предоставляют почту и связаны с госструктурами.



Давайте посмотрим на запись детальнее. Здесь есть разные поля: можно указать, что сертификат должен быть выписан именно этим Authority это уже немного помогает. Принцип тот же, что и у САА, только уже после выписки. Это не зависит от того, смотрит ли ишьюер в САА запись или нет. В DANE написано: клиент обязан посмотреть, что сертификат, который он получил, выписан определенным Certificate Authority, и если это не так ничего не выйдет. Всё зависит только от клиента и не зависит от CA. Это плюс.

Из остального остановимся на Domain issued certificate. В принципе, если бы всё хорошо работало (здесь ключевая проблема с DNSSEC), то мы бы могли указывать в своей DNS-записи свой сертификат и не зависеть ни от кого. То есть, если я владею доменом, сгенерировал хотя бы самоподписанный сертификат, указал его вот сюда, и DNSSEC работает нормально, то клиент доверяет моей DNS-записи и сертификат берет оттуда. Всё, CA не нужны. Бизнес на сертификатах рушится, денег никаких нет :)

Однако это всё не работает. Во-первых, есть EV-сертификаты, для которых всё-таки хочется проверить организацию. Во-вторых, проблема доверия уходит с Certificate Authority на инфраструктуру DNSSEC, которая считается недостаточно рабочей, потому что она мало распространена, на нее все забили, а еще там тоже есть уязвимости.

В общем, спорная вещь, одно меняем на другое, из-за этого теряем EV-сертификаты. Возможно, поэтому это не слишком распространилось.

HPKP


Дальше еще есть одна интересная вещь, называется HPKP.



Идея на картинке: мы в HTTP-заголовке отдаем собственно хэши сертификатов, которые клиент должен проверить, и если публичный ключ сертификата имеет другой хэш (то есть его нет среди перечисленных) до свидания. Google в HPKP разочаровался и Chrome это не поддерживает. На этом можно закончить, хотя вообще выглядит интересно если я знаю, какие у меня есть сертификаты, мне очень легко этот заголовок отдать, и это должно повышать секьюрити по идее.

Policy




Как мы уже знаем, если браузер смотрит в это поле и находит там определенные сочетания циферок и буковок, то он должен понять, что это EV-сертификат и, возможно надо сделать дополнительные вещи. Вот тут у нас указан Global Sign Repository и иногда браузер должен сходить по указанному там адресу и получить ответ, что всё хорошо. Это в основном работает для EV-сертификатов, для OV браузеры это часто просто игнорируют, ну и в DV этих полиси-то и нет собственно. Для чего это надо вам просто для информации.

Ответ клиента


Итак, Патрик проверил сертификаты и начинает отвечать Губке Бобу.



Если у клиента просили сертификаты, он их отдает. Дальше он отдает информацию для того, чтобы сделать ключики так же, как сервер, clientKeyExchange. Поле CertificateVerify неинтересная инфа на тему как валидировать сертификат, в TLS 1.3 она и выглядит-то уже по-другому, потому что не сильно нужна.

После этого клиент переходит на шифрованный канал и посылает сообщение Finished я готов к шифрованному каналу. Сервер проверяет это сообщение что там всё нормально, как договорились, что оно расшифровывается, что не успели на данном этапе ничего подменить и это всё еще Патрик, тоже переходит на шифрованный канал и отдает свое Finished-сообщение, которое в свою очередь проверяет клиент. И после этого идет общение уже данными приложений по шифрованному каналу.



TLS-handshake full vs resumed


В этой статье мы не стали подробно останавливаться на том, как выбираются сессионные ключи. Там тоже много работы на процессоре, много вычислительных действий и следующая проблема после безопасности это производительность. Всё это происходит медленно, особенно, если ходить в CRL списки и делать прочие дополнительные проверки. А если еще цепочка сертификатов огромная, то всё может быть прям совсем медленно, и с этим надо что-то делать.

Session ID


До TLS 1.3 для решения этой проблемы использовались укороченные сессии. Когда сервер отвечает клиенту, он отдает ему Session ID. Если у клиента этот Session ID тоже есть, он отсылает его серверу и вот эта часть, которая в рамочке, пропускается. Потому что сервер запоминает контекст всей этой штуки и продолжает так, как будто это уже произошло. Сессионный ключ выбран, и клиенту не надо проверять сертификат, потому что он есть в этом сессионном ключе. Если окажется, что сертификат там какой-то другой, то выбранный сессионный ключ не будет работать и клиент просто не сможет расшифровать сообщение сервера.



Так это всё работает. Это побыстрее, но тоже есть проблемы, возрастает нагрузка на сервер, ну и есть атаки с перехватом Session ID. Потому что этот Session ID идет по открытому каналу.

Session ticket


Еще для ускорения можно использовать Session Ticket это в принципе то же самое, что и Session ID, только передается зашифрованный контекст, а не циферка, которую можно украсть. Бывает, что сессию установить не удалось, тогда придет алерт. С ними тоже связаны атаки на TLS, потому что алерты имеют определенную структуру и определенный размер. Если алерт произошел на этапе, когда уже трафик идет зашифрованным, то из-за того, что алерт понятной структуры и злоумышленник может знать, что ему в этом алерте отвечают задача расшифровывания становится сильно проще. Поэтому в TLS 1.3 это уже не используется.

Reinit


Что еще бывает в TLS-handshake в принципе? Иногда серверу бывает нужно инициализировать сессию повторно чаще всего тогда, когда сертификат клиента был не нужен и вдруг стал нужен. Тогда сервер говорит: давай перезапустим. Ну и клиент может сказать еще раз Client Hello. В TLS 1.3 это тоже убрали, потому что тоже были атаки атаки были везде!



Что в TLS 1.3?


Все упомянутые трудности решаются использованием TLS 1.3. Половины проблем вообще нет, всё проще, красивее, всё прям отличненько. Но TLS 1.3 еще распространен маловато. Самые важные отличия TLS 1.3 (их очень много, они везде, поэтому только самые важные):

  • Плохие шифры удалены, остались только хорошие. Инициализировать сессию TLS 1.3 на плохих шифрах не получится. Всё дело в новых cipher suites: тут и другие алгоритмы обмена сеансовых ключей, и так называемый HMAC не будем углубляться в подробности, потому что Патрик устал. Вкратце: раньше подпись каждого TLS-пакета шла отдельно. На это были атаки, потому что было известно, какой там контент находится. Сейчас ее запихали вовнутрь (режим AEAD), и в TLS 1.3 по-другому быть не может, соответственно, мы избавились от таких атак.
  • Handshake стал короче нет старых сообщений, нет старых расширений, нет возможности по каким-то странным штукам обменяться ключиками. То есть, он тупо короче количественно даже самый полный TLS 1.3 handshake короче, чем в TLS 1.2.
  • Переход на шифрованный канал происходит почти что сразу. Для этого используются разные ключики: да, пока не договорились о хороших ключиках, оптимальных, мы используем какие попало, но канал уже шифрованный. То есть hello hello и пошло всё зашифрованное. Из-за этого сложнее всё это ломать.
  • Всё регламентировано, больше не надо пытаться менять размеры пакетов, забивая их ноликами, чтобы сложнее было расшифровывать.
  • Своя пара ключей на каждую сеансовую фазу. Сеансовые ключи меняются: пока мы ни о чем не договорились они такие, договорились о более крутых они более крутые, сертификаты проверили и всё хорошо еще другие ключи. В итоге их много, они усложняются и очень трудно это всё поломать. Еще одна важная вещь, почему это быстрее: Early Data (она же 0-RTT, Zero Round Trip Time) это когда у тебя в TLS-handshake посылается полезная инфа ну например GET-запрос. То есть нет такого, что поговорили-поговорили и только потом посылаем что-то отдельным потоком. Сразу же в handshake идет запрос. Как только сервер его получил, он начинает его обрабатывать, отдает клиенту свои данные, сертификат и пока клиент проверяет, сервер уже готов отдать. И может даже в TLS-handshake и отдать иногда.
  • Есть pre-shared key, то есть клиент с сервером могут договориться и сохранить сеансовые ключи для последующих соединений. И, соответственно, когда происходит handshake таких вот договорившихся клиентов, на этап выбора ключей время не тратится. Долго объяснять, как это сделано криптографически, но тех атак, которые были на Session ID, вот в этом месте сейчас нет (что хорошо). Всё стало безопаснее и быстрее.

Основная проблема, что поддержка TLS 1.3 она во всех браузерах, которые актуальны, есть, но не во всех по дефолту включена. Например, в Safari нет (но там очень легко включить), Google Chrome и Mozilla Firefox уже по дефолту поддерживают TLS 1.3. Ngnix с TLS 1.3 без проблем, в Apache есть нюансы, а вот с почтовыми клиентами хуже там только Exim молодец, а остальные не очень.

В общем, это наше будущее, там всё получше и попроще, самое главное. Но пока оно еще не везде наступило.

Как всё это тестить?


Инструментов для тестирования много, большинство из них не очень, вот эти плюс-минус ничего:

  • ssldecoder.org посмотреть поля сертификата
  • www.ssllabs.com/ssltest протестить TLS домена (нужная внешняя машина)
  • ssl-config.mozilla.org генератор конфигов сервисов с хорошими настройками TLS
  • crt.sh поиск по Certificate Transparency. Полезно посмотреть, когда есть проблемы у клиентов, например клиент говорит, что уже пятый раз выписывает сертификат и происходит какая-то фигня. Возможно это поможет, например валидити период не тот, тогда можно угадать.
  • www.checktls.com/TestReceiver сервис проверки TLS на почте (нужна внешняя машина)
  • certificatetools.com крутая штука для генерации CSR, изменения полей сертификата, проверки OCSP и прочих вещей. Можно скормить готовый сертификат, запихнуть какое-то поле, которое тебе надо, и создать еще один сертификат. Соответственно, подпись будет уже твоя, но если тебе надо проверить, как себя ведет софт, как он реагирует на определенное поле в сертификате, ты можешь без всяких CSR-ов выписать такой само-подписанный сертификат. Таким образом можно поиграться с полями.
  • www.immuniweb.com/ssl подробный сканер
  • www.wireshark.org поддерживает даже то, чего еще нет в стандартах
  • www.feistyduck.com/books/openssl-cookbook cookbook по OpenSSL


Маленький бонус


То, что не влезло.



На картинку тоже не всё влезло тема очень большая, но на практике можно фокусироваться таким образом, чтобы на любом уровне понимать идею в целом и смочь разгрести что происходит, понять, что вам нужно доучить, что сейчас конкретно нужно узнать и всё вот это. Эта картинка про ключевые слова. Из литературы можно рекомендовать очень крутую статью на русском языке Ключи, шифры, сообщения: как работает TLS прочитать целиком вряд ли удастся, но в качестве справочника пригодится. Открыл, нашел что надо, почитал, ключевые слова узнал, пошел в википедию и на английском прочитал (на русском почему-то плохо написано). На английском написано отлично: идея, зачем, почему, ссылочки. Не знаешь, что такое HSTS иди в википедию, там будет ссылочки на статьи для Патриков, то есть чайников. Еще на RFC, но это читать невозможно. Общий смысл станет понятен даже из самой статьи в Википедии.

Вот и всё! Вы молодцы :)
Подробнее..

Cypress и его место в нашей тестовой пирамиде

18.05.2021 08:17:48 | Автор: admin

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

Введение в Cypress

Если отбросить капитанское определение, что Cypress это JavaScript-фреймворк для тестирования, то важно отметить, что при работе с ним мы видим на экране браузер. Он не обязательно открыт, он может быть headless, но он есть, и он открывает особое приложение самого Cypress, которое состоит из нескольких фреймов: в одном фрейме открывается продукт, который мы тестируем, в другом фрейме запускаются тесты. Код тестов пишется на JavaScript, поэтому они могут выполняться непосредственно в браузере ведь это нативный для него язык.

Так с помощью JavaScript API производятся все манипуляции, которые делаются в тестах, то есть заполнение форм, клики и тому подобное.

Преимущества Cypress

Нет Selenium WebDriver

Очевидное отличие Cypress от тех библиотек и фреймворков, которые мы использовали раньше это отсутствие основного действующего элемента, Selenium.

Selenium WebDriver это third-party сервис на Java, который обращается к браузеру по WebDriver протоколу. Это накладывает ограничения на работу с браузером в рамках протокола. Сетевое взаимодействие также вносит свой вклад во время выполнения тестов.

Изначально Selenium был создан не специально для тестов, а как общий инструмент автоматизации для браузера. Cypress, в отличие от него, сфокусирован на решении конкретной задачи, а именно, на создании end-to-end (е2е) тестов для интерфейса web-приложений.

Все в одном

Cypress не нужно собирать из кусочков он принес все достаточно современные "батарейки" с собой:

  • Синтаксис BDD (унаследовано из Mocha): describe(), context(), it().
    А также хуки: before(), beforeEach().
    Использовать такой DSL привычно для тех, кто уже писал юнит-тесты на JavaScript.

  • Библиотека ассертов (унаследовано из Chai). Например:
    expect(name).to.not.equal("Jane") ожидание того, что элемент не существует это не то же самое, что ожидание неудачи при проверке существования элемента. Если элемента нет, то это хорошо, это не нужно перепроверять, а нужно идти дальше.
    Такую задачу должен решать тестовый фреймворк, и этого нам очень не хватало в старой самописной библиотеке, при использовании которой многое ложится на плечи разработчика теста.

  • Перехват, отслеживание (spy) и подмена (mock) запросов браузера к бэкенду.

Development experience

Главное преимущество Cypress это отличный development experience. Написать первый тест для своего проекта (неважно, на каком языке написан сам проект) можно минут за 10. Потребуется добавить одну зависимость в package.json (npm install cypress), прочитать документацию про то, куда складывать файлы (cypress/integration/login.spec.js), и написать код в 5 строчек:

describe('Login', () => {it('should log in with credentials', () => {cy.visit('/login');cy.get('[name=login_name]').type(Cypress.env('login'));cy.get('[name=passwd]').type(Cypress.env('password'));cy.get('[name=send]').click();cy.get('.main-header').should('be.visible');});});

Получаем реальный тест, который посещает страницу логина, заполняет форму, нажимает на кнопку и видит результат.

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

Приятной мелочью является то, что каждый cy.get() убеждается, что страница загрузилась, и делает несколько попыток, чтобы найти элемент. С каждым годом интерфейсы веб-приложений становятся все сложнее. Результирующий HTML формируется не на стороне сервера, а на стороне браузера. Делается это асинхронно и с использованием различных библиотек компонентов. В какой момент тот или иной элемент интерфейса появится на экране, сказать уже становится сложнее.

Одна из Best Practices говорит, что не нужно никогда писать таймаут типа "подождать 2 секунды". Абсолютно все таймауты должны ждать чего-то осязаемого, например, окончания Ajax-запроса. Можно подписаться на событие, которое случается в коде продукта. Например, когда нам через веб-сокет прилетает событие с бэкенда, то срабатывает определенный listener на фронтенде.

Вся документация Cypress и Best Practices находятся на одном сайте docs.cypress.io хотелось бы отдельно отметить высокое качество этой документации, а также мастер классов, которые команда разработки Cypress проводит и публикует в открытом доступе.

Кроме того, один из паттернов, от которых стоит отказаться это PageObject. Долгое время он считался обязательным, но для новых тестов он нам уже не понадобится.

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

Тестовая пирамида

Когда говорят про тестовую пирамиду, то обычно приводят в пример анти-паттерн "перевернутая пирамида" или "стаканчик мороженого". То есть на нижнем уровне в таком примере количество юнит тестов стремится к нулю. Лично мне этот случай кажется невероятным для зрелого проекта: ведь в этом случае разработчики должны были полность отказаться писать самые простейшие тесты откуда тогда взялись сложные е2е тесты?

Как бы то ни было, к нам это не относится у нас несколько тысяч PHPUnit-тестов с покрытием около 12% строк кода.

В то же время у нас есть еще несколько тысяч е2е-тестов с Selenium, которые проверяют все возможные конфигурации продукта, занимают кучу времени (подмножество, запускаемое на каждый коммит, мы смогли оптимизировать до 40-60 минут), имеют довольно слабый уровень доверия (с вероятностью 30-40% тесты упадут, хотя коммит не содержит причины этого падения) и покрывают около 30% строк кода.

Получается, наше положение выглядит, как песочные часы нам не хватает среднего слоя в тестировании, где интеграционные тесты проверяют компоненты системы независимо друг от друга. Это горлышко песочных часов и хочется заполнить с помощью Cypress. При этом еще хочется что-то сделать с существующими е2е тестами, чтобы "заострить" вершину пирамиды. То есть, важный акцент здесь в том, что Cypress не является заместителем старого фреймворка: мы не хотим просто взять и переписать все тесты на Cypress иначе мы так и останемся на шарике мороженого. Цель тестов по-прежнему, проверять регрессию в продукте, но проверять на другом уровне, чтобы выполняться быстрее и получать результат раньше, а также быть легче в сопровождении.

Наш подход к написанию тестов

Проект, о котором идет речь, это контрольная панель Plesk. Она предоставляет пользователям интерфейс для управления хостингом веб сайтов. Функциональность панели доступна не только через UI, но и через API и CLI, которые используются для автоматизации.

Мы начали с того, что сделали следующие предположения:

  • Тесты на Cypress относятся чисто к UI. Мы не относим сюда тесты, у которых шаги выполняются через API или CLI.

  • Мы не проводим никакой дополнительной валидации, кроме той, что выполняется средствами UI. Например, если мы проверяем создание домена, то мы не отправляем запросы для проверки Web-сервера или DNS, мы считаем тест пройденным, если в UI появилось сообщение на зеленом фоне о том, что домен создан успешно. Такой подход избавляет нас от предварительной подготовки и написания тестовых сценариев.

  • На первом этапе мы автоматизируем только позитивные сценарии. Негативные сценарии не представляют ценности для клиента, но при этом тесты для их проверки занимают драгоценное время. Так что переносим такие сценарии в нижнюю часть пирамиды они, как правило, легко проверяются юнит-тестами.

Наш опыт работы с Cypress в сочетании с официальными рекомендациями привел нас к использованию следующего набора практик:

Сбрасывать состояние продукта

Мы сбрасываем состояние продукта до исходного перед запуском каждого набора тестов (Cypress рекомендует делать это перед запуском каждого теста, но мы используем облегченный вариант). Мы создаем дамп базы данных и восстанавливаем его перед прогоном каждого набора тестов (test suite / spec). Это занимает порядка 5 секунд.

before(cy.resetInstance);//=> test_helper --reset-instance//=> cat /var/lib/psa/dumps/snapshot.sql | mysql

Такой откат к прежнему состоянию может в общем случае привести Plesk в нерабочее состояние, т.к. помимо общей базы есть еще, например, базы отдельных утилит, а также бэкапы, которые хранятся в файловой системе. Но нас это устраивает, т.к. мы используем Cypress только для тестирования UI.

Использовать фикстуры

Вместо реальных объектов в качестве пререквизитов теста мы используем фикстуры сохраненные структуры, которые содержат необходимое состояние базы данных. Например, для выполнения некоторых тестов необходимо наличие домена. Вместо создания реального домена мы воссоздаем все необходимые записи в базе данных, но не трогаем файловую систему и другие системные сервисы. Это занимает меньше секунды (для сравнения, создание полноценного домена заняло бы около 30 секунд).

cy.setupData(subscription).as('subscription');//=> test_helper --setup-data < {domains: [{ id: 1, name: "example.com" }]}

Такие объекты не будут выполнять полноценные пользовательские сценарии, но для тестирования UI их будет достаточно.

Использовать прямые URL

Мы не используем навигацию и попадаем в нужные места UI по прямым URL-ам. Мы вызываем свою специальную команду login, которая создает сессию, а затем переходим прямо на нужную страницу.

beforeEach(() => {cy.login();cy.visit('/admin/my-profile/');});

В старом фреймворке мы бы использовали PageObject для входа в главное меню, а затем переходили бы из него к нужному элементу. Здесь же этого не требуется, так как мы тестируем только необходимую страницу. Единственное дублирование это команда login, но это не выглядит проблемой.

Фронтенд без бэкенда

Иногда бывает сложно создать условия для определенного состояния, которое мы хотим протестировать. Например, для проверки доступных обновлений. Намного легче подсунуть заготовленный ответ для Ajax-запроса, чем готовить инфраструктуру для обновлений.

const lastChecked = 'Jan 29, 2021 04:42 PM';cy.intercept('POST', '/admin/home/check-for-updates', {status: 'success',lastChecked,newVersion: null,whatsNewUrl: null,}).as('checkForUpdates');cy.get('[data-name="checkForUpdates"]').click();cy.wait('@checkForUpdates');cy.get('[data-name="lastCheckedDate"]').should('contain', lastChecked);

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

Стабильность тестов

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

Дожидаться выполнения Ajax-запроса

Многие формы в нашем продукте отправляются с помощью Ajax-запросов без перехода страницы. Чтобы тест гарантированно прошел, необходимо перехватить этот запрос и дождаться его завершения. Так как в Cypress мы проверяем только то, что происходит в UI, мы дожидаемся нужного нам сообщения.

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

cy.intercept('POST', '/admin/customer/create').as('customerCreate');cy.get('[name=send]').click();cy.wait('@customerCreate');cy.get('.msg-box.msg-info').should('be.visible');

Дожидаться исчезновения индикатора загрузки

Кое-где в нашем интерфейсе фоновые операции, например, обновление списка, сопровождаются анимированным индикатором загрузки ("крутилкой"). Именно на таких страницах после окончания Ajax-запроса случается ошибка "element has been detached from the DOM" при попытке Cypress кликнуть на элементы списка. Поэтому мы добавляем после Ajax-запроса дополнительную строку, которая проверяет, что индикатор загрузки не виден.

cy.get('.ajax-loading').should('not.be.visible');

Мы надеемся, что проблема будет исправлена на стороне Cypress и нам больше не придется за этим следить.

Ajax-запросы после окончания теста

После окончания каждого теста браузер остается на последней открытой странице. Cypress сбрасывает состояние браузера (включая куки) и запускает следующий тест, где первым шагом мы сбрасываем состояние продукта (включая сессии бэкенда).

До того момента, когда следующий тест сделает первый вызов "cy.visit()", предыдущая страница остается открытой и может отправлять Ajax-запросы (например, периодическое обновление), которые будут падать из-за ошибки авторизации (куки нет, сессии нет).

В качестве workaround можно переходить на пустую страницу, чтобы браузер сбрасывал все активные Ajax-запросы. Для этого добавляем в support/index.js

afterEach(() => {cy.window().then(win => {win.location.href = 'about:blank';});});

Первые результаты

За 3 человеко-месяца (3 итерации) мы получили следующие результаты:

  • 335 тестов на Cypress (разбиты на 84 спеки)

  • Пайплайн полностью выполняется за 35-40 минут, из которых сами тесты занимают 20 минут

  • Запуск пайплайна на каждый пулл-реквест в блокирующем режиме (то есть нельзя мержить без успешного прохождения тестов)

  • Уровень доверия выше 95% (то есть вероятность flaky падения ниже 5%)

  • Покрытие интерфейса 35% (ниже расскажу подробнее)

Пайплайн для запуска тестов

За время разработки пайплайн для запуска тестов прошел несколько этапов развития. Требованием было уложиться в час, иначе ожидание мержа в пулл реквесте слишком затягивается.

Как и для большинства наших задач, пайплайн запускается в Jenkins и хранится в Jenkinsfile вместе с кодом проекта.

Линейный пайплайн

В первом заходе получился простой линейный пайплайн.

Мы запускаем Docker-контейнер с Plesk в фоновом режиме и ждем, когда он будет доступен в локальной сети. Потом запускаем другой контейнер с Cypress и кодом тестов, он подключается к Plesk и выполняет все тесты, а мы ждем его завершения (не делаем detach).

Мы запускали тесты на машине с 12 ядрами, которая используется у нас для сборки Plesk и ряда его служб. В течении рабочего дня у нас бывает до 20-30 сборок. В результате Load Average достигал 20, и многие соседние процессы "вставали". Мы добавили ограничение на количество исполняемых сборок до 3-5. Но и этого оказалось недостаточно, соседи по железу продолжали жаловаться на нагрузку.

Тогда мы унесли запуск тестов на выделенный сервер в AWS с 4 ядрами внутри VPC с доступом в нашу офисную сеть. Тем самым мы избавились от недовольных соседей, но сборки тестов так и продолжили подолгу ждать в очереди, время от времени не укладываясь в таймаут.

Пайплайн с параллельными шагами

Чтобы как-то ускорить процесс, мы решили воспользоваться Jenkins EC2 Fleet plugin, который предоставляет Jenkins slave ноду по требованию из Autoscaling Group в AWS и уничтожает неактивные ноды после некоторого простоя. Такой подход позволяет тратить деньги на аренду ресурсов только тогда, когда они необходимы.

Переход на spot-инстансы позволил нам существенно сэкономить: вместо $150 в месяц за ondemand c5.xlarge, мы стали тратить около $60 за c5.xlarge и более мощные c5.2xlarge.

А главное, мы можем делать столько одновременных запусков, сколько нам нужно.

Разворачивание новой ноды занимает порядка 2 минут. Мы сделали в пайплайне несколько шагов параллельными, чтобы за это время успеть собрать продукт и быть готовыми к его установке в Docker на новой ноде.

Однако число наших тестов росло, и время пайплайна неизбежно росло вместе с ним, так что нужно было искать новые шаги для его ускорения.

Пайплайн с параллельными тестами

В Cypress есть платная фича параллельный запуск тестов с помощью Cypress Dashboard. Но мы пошли простым и бесплатным путем перечисляем файлы с тестами при запуске контейнера, при этом первый запускает все четные файлы, второй все нечетные.

cypress run --spec $(find 'cypress/integration' -type f -name '*.js' | awk '(NR - ${RUNNER}) % ${TOTAL_RUNNERS} == 0' | tr '\n' ',')

Получилась матричная сборка, где для каждой оси (axis) запускается свой контейнер с Plesk и свой контейнер с определенным набором тестов.

В итоге мы укладываемся в приемлемые 35-40 минут для всего пайплайна, а время одной пачки тестов занимает примерно 20 минут.

В дальнейшем с увеличением количества тестов нам, очевидно, потребуется больше параллельных потоков, и мы планируем использовать Amazon ECS для запуска контейнеров, чтобы не ограничиваться EC2 инстансом.

Измерение URL coverage

В нашем проекте используется много различных языков программирования и анализ code coverage является больной темой, потому что сбор данных требует специальных билдов и объединения отчетов с нескольких конфигураций.

Для анализа тестового покрытия UI мы решили воспользоваться продуктовой аналитикой и сравнить данные, полученные от тестовых инсталляций, с данными от реальных пользователей. У нас уже был сервис, аналогичный Google Analytics, для сбора пользовательских метрик, а тестовые данные складывались отдельно и никем не использовались. Из множества метрик мы отфильтровали события о посещенных URL-ах (страницах) продукта, начали сохранять эти данные в удобном для нас виде в базу данных и составлять отчет по посещенным адресам.

По полученным данным, за счет всего автоматического и ручного тестирования внутри компании мы покрываем около 60% URL-ов, которые посещают реальные пользователи в течении месяца. Наши старые тесты покрывают около 25%, а новые тесты на Cypress уже достигли 35%.

Эта статистика помогает нам планировать дальнейшее тестирование например, более посещаемые страницы мы планируем автоматизировать в первую очередь.

Следующие шаги

Ускорить сборку Docker

Одна из проблем, над которой мы хотим поработать ускорение сборки контейнеров Docker. Как уже было сказано выше, мы создаем временный сервер в AWS (slave node) для каждой сборки Docker, и эта сборка на данный момент занимает в среднем 8 минут. Но поскольку каждый временный сервер новый, то мы совершенно не используем преимущества кэширования, а хотелось бы ими воспользоваться. Поэтому сейчас мы исследуем возможность использования BuildKit. Альтернативными решениями могут стать Kaniko или AWS CodeBuild.

Сократить количество е2е тестов

Мы хотим уменьшить количество старых е2е тестов, чтобы вершина тестовой пирамиды стала более острой. Сейчас около трети этих тестов относятся к UI. Кроме этого, тесты содержат проверки через командную строку (CLI), причем иногда логика тестов в UI и CLI дублируется.

Основная идея: перенести все UI-тесты в Cypress, а в старом фреймворке оставить только CLI-тесты с детальными проверками. Поэтому для каждого UI-теста из старого фреймворка мы делаем следующее:

  1. Заменяем UI-шаги на CLI (если это возможно).

  2. Удаляем, если уже есть аналогичный тест с CLI.

  3. Если проверка возможна только через UI уносим ее в Cypress.

Например, при создании домена проверяется то, что он резолвится, и что на нем работают определенные скрипты. Эти проверки останутся только для создания домена через CLI. А тест на UI в Cypress будет проверять только появление сообщения о создании домена.

В результате мы избавимся от дублирования тестовых сценариев, сократим нагрузку на сервера с Selenium и в перспективе совсем от них избавимся, когда тестирование UI будет делать только Cypress.

Заключение

Cypress подкупает быстрым стартом к написанию тестов и удобными средствами для отладки. При этом не стоит забывать, что скорость и стабильность тестов зависят от того, как они написаны: легковесные фикстуры и подготовленные ответы бэкенда дают большое ускорение, а сброс состояния позволяет избежать случайного влияния тестов друг на друга.

Cypress позволяет организовать как полноценные e2e тесты с прохождением пользовательских сценариев на реальном продукте, так и интеграционное тестирование отдельных компонентов фронтенда. Лучше заранее выбрать цель и договориться о правилах игры для всей команды.

Кроме того, стоит отметить, что запуск тестов потребляет довольно много ресурсов CPU, поэтому стоит заранее оценить количество параллельных запусков и спланировать масштабирование инфраструктуры.

Подробнее..

О чем спорят строители Умных Домов, Бань, Дач и Гаражей

29.04.2021 08:22:29 | Автор: admin

Я Community Manager и у меня есть зависимость. Ну хорошо, не зависимость, но хобби: я увлекаюсь автоматизацией собственной квартиры с помощью того, что принято теперь называть Умным Домом. Начинал я пару-тройку лет назад с чистого Apple HomeKit, затем расширил его возможности с помощью Homebridge и далее полностью погрузился в дебри HomeAssistant.

Но поскольку я Community Mananger, мне интересна та часть моего хобби, которая касается вопроса коммуникации сообщества людей, имеющих такое же увлечение, как и моё.

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

Статья также о том, как я попал в секту строителей Умных домов и что я о ней узнал. Для начальной ориентации новичков, в общем.

Предыстория

Предупреждая все возможные разговоры о целесообразности Умного Дома, скажу сразу: в настоящее время, в домашних любительских условиях, автоматизация собственного жилища действительно, всего лишь хобби для большинства участников сообщества. Причем весьма дорогостоящее хобби, которое не приносит никаких материальных выгод. Говорить об экономии расходов на тепло, электричество и воду, при использовании весьма дорогостоящих комплектующих для этой экономии, совершенно не приходится. Все это лишь ради собственного удовольствия и для создания некоторых удобств существования в личном пространстве. Новичкам, вступающим на этот путь, нужно четко себе это понимать и быть готовым к существенным расходам.

Мой путь начался с того, что в один прекрасный момент я внезапно осознал, что имеющийся в хозяйстве AppleTV 4K может служить шлюзом для построения Умного Дома на базе Apple HomeKit. Было приобретено и успешно подключено несколько HomeKit ready устройств. Все было прекрасно, стабильно, но дорого. Хотелось дальнейшего расширения, но за меньшие деньги.

И тут я сделал открытие, что существует, оказывается, множество сообществ людей, подобных мне. И что многие устройства можно делать самому и при этом ничуть не хуже, а главное, дешевле. И что вездесущая Xiaomi, со своими инкарнациями вроде Aqara и прочих, делает устройства для Умного Дома значительно менее затратные для моего кошелька.

Так, с помощью внимательного чтения и вопросов к коллективному разуму я влился в обширное и очень эффективное русскоязычное сообщество строителей Умных Домов, Бань, Дач и прочих Гаражей. Мир DIY и OpenSource решений захлестнул меня и, нужно заметить, я был к этому подготовлен. Я уверенно обращался с паяльником и имел очень долгий опыт работы с Linux. Мне было легко и приятно быть среди единомышленников.

С каждой новой итерацией своего продвижения по этому пути все новые и новые ресурсы открывались мне, с великими Гуру можно было спокойно общаться в телеграм группах практически на одном языке и порой даже осмеливаться их критиковать. Я узнал, что большинство самых ценных сообществ живет в профильных телеграм каналах, что сообщество на форуме 4PDA живет какой-то своей жизнью, что известный всем русскоговорящим умнодомщикам Спрут портал раскинул свои щупальца настолько широко, что даже проник на территорию подкастов и инстаграма, что адепты св.Квазиса повсюду и что AlexxIT, Jager, Илья Киров и Иван Бессарабов настолько же доброжелательны и приветливы в общении, насколько круты в своем профессионализме. А для владеющих английским открываются поистине бездонные кладези знаний на Reddit, YouTube и, например, официальном форуме HomeAssistant.

Опыт накапливался быстро и вместе с ним пришло понимание тем и вопросов, вызывающих наиболее горячие и часто повторяющиеся дискуссии. Опыт так же сформировал собственное мнение по этим вопросам. Давайте же их рассмотрим и обсудим.

OpenSource против готовых решений

Xiaomi MiHome стал уже символом консьюмерской системы Умного ДомаXiaomi MiHome стал уже символом консьюмерской системы Умного Дома

На самом деле это не самая животрепещущая и обсуждаемая тема. В той части сообщества, в которой обитаю я, общаются люди, которые уже сделали свой выбор в пользу OpenSource решений. Но тем не менее вопрос нередко ставится ребром новичками и, как следствие, становится весьма актуальным.

На чем строить свой Умный Дом? На готовых решениях от Miija, Sonoff, Tuya, Apple, Aqara, Rubetek, Yandex, Google и прочих и прочих? Или же построить его самому на базе OpenSource решений типа HomeAssistant, NodeRed, OpenHub, IOBroker и так далее?

NodeRed очень популярное OpenSource решение для Умного ДомаNodeRed очень популярное OpenSource решение для Умного Дома

Тем, кто стоит перед таким выбором приходят на помощь авторитетные прожженные линуксоиды и начинают говорить о непревзойденной гибкости автоматизаций и отвязки от коварных "китайских облаков" в OpenSource решениях. Они будут говорить о том, что все будет контролироваться только лично тобой и что ты сможешь использовать почти весь доступный на рынке зоопарк устройств Умного Дома, да еще и DIY устройства. Стоит лишь купить "малинку", установить на нее Linux, потом поколдовать в командной строке, чтобы установить этот самый альтернативный Умный Дом, а потом еще потратить месяцы на настройку и понимание что вообще тут к чему.

И вот новичок, который про Linux только на уроках информатики слышал, а командную строку видел только в голливудских блокбастерах про геройских хакеров, обалдев от такого объема информации, мало ему понятной, принимает решение переплатить, но сделать свой Умный Дом легко и просто на базе существующих на рынке готовых решений. Или вообще ничего не делать. И правильно сделает, кстати.

Консьюмерские решения имеют полное право на существование, и принижать их адептов не стоит в сообществах ни в коем случае. Люди принимают решение, основываясь на собственном опыте, знаниях, ресурсах, и тащить их силком в OpenSource не нужно. Мучения таких людей, вставших на путь, на который их убедили вступить, их обескураживающие и порой наивные вопросы очень хорошо заметны, а попытки профессионалов им помочь выглядят удручающе. Но вызывают неподдельное уважение те, кто начинает с такого уровня вхождения в тему и успешно преодолевает его.

Поэтому отсюда мое наблюдение: не стоит тащить и убеждать не готовых людей. Пусть каждый будет в комфортных для него условиях его личного выбора. И выбор этот нужно уважать.

Малинка против Intel NUC, Gigabyte BRIX и прочих x86

Та самая знаменитая "Малинка" Raspberry Pi 4 Та самая знаменитая "Малинка" Raspberry Pi 4

Итак, новоявленного строителя Умного Дома затащили на темную сторону OpenSouce и перед ним встает первый из ключевых вопросов: а на что мне все это хозяйство устанавливать?

Популярность использования платформы Rapberry Pi для сервера Умного Дома я могу объяснить лишь пресловутыми "исторически сложившимися причинами", а так же, не в последнюю очередь, мощью авторитета Алекса Квазиса и его YouTube канала.

При всех своих недостатках, "малинка" остается самой популярной платформой и поныне. А недостатки у нее серьезные:

  1. Использование в качестве накопителя медленной и очень ненадежной SD карты

  2. Необходимость в хорошем охлаждении

  3. Склонность к троттлингу при недостаточно качественно обеспеченном питании

  4. Слабый встроенный Bluetooth

  5. Довольно слабая производительность ARM процессора, которой, впрочем, в большинстве случаев достаточен для систем Умного Дома

  6. Важная для многих необходимость в приличном корпусе

Для устранения части этих недостатков потребуется покупка SSD или eMMC накопителя, мощного корпуса-радиатора, внешнего Bluetooth донгла, корпуса вроде Argon One. Все эти дополнительные покупки приводят к значительному удорожанию вашего сервера Умного Дома на базе "малинки".

И тут на авансцену выходят опытные члены сообщества с вполне резонным вопросом: А почему бы вам сразу не купить компактное, бесшумное и быстрое решение на базе гораздо более производительных процессоров x86 с встроенным SSD диском, расширяемой памятью? Ну, например, что-нибудь подходящее по цене из обширного семейства миниатюрных компьютеров Intel NUC или Gigabyte BRIX?

Очень популярный Intel NUCОчень популярный Intel NUC

В действительности цены на подобные новые минисерверы довольно высоки и далеко не каждый будет готов потратится. Но на просторах интернет барахолок, вроде Avito, вполне можно найти приличные варианты за вменяемые деньги. Я, например, купил там немного устаревшую модель Gigabyte BRIX с процессором Celeron N3000, 4GB RAM, 120GB SSD и пассивным охлаждением всего за 5 тысяч рублей. И машинка эта прекрасно работает в круглосуточном режиме с HomeAssistant на борту вот уже больше года. Некоторые домовладельцы покупают на Авито даже подержанные HP Microserver Gen8 под свой домашний сервер, на котором, кроме системы Умного Дома, работает еще и медиасервер, торрент-качалка, NAS и что-нибудь еще. Многие используют в качестве сервера Умного Дома уже имеющиеся в хозяйстве NAS от Synology или реже Qnap с поддержкой Docker. Но в этом варианте много подводных камней, которые вызывают множество вопросов и дискуссий. Этот вариант сервера, на мой взгляд, подходит только уверенным пользователям Linux с достаточно глубокими знаниями Docker.

На мой взгляд, если говорить о сервере только для Умного Дома, наиболее целесообразным вариантом сейчас является использование миникомпьютеров на базе процессоров x86 (не Atom!). Это могут быть не обязательно Intel NUC или Gigabyte BRIX, а любой подходящий на базе Celeron и выше, и желательно с пассивным охлаждением, особенно для тех, кто строит Умный Дом в городской квартире и для кого уровень шума сервера является критическим параметром. Наличие именно SSD диска не обязательно, но крайне желательно для общего быстродействия. Памяти в большинстве случаев достаточно 2-4Gb. Подключать к сети такой сервер рекомендую по более надежному Ethernet, но и по WiFi 5Ггц у многих работает вполне стабильно.

Zigbee против WiFi (BLE mesh, Zwave, Thread пока не в счет)

Теперь, когда система успешно установлена на сервер, выполнена первоначальная настройка, приходит время покупать и подключать конечные устройства Умного Дома: всевозможные датчики и исполнительные устройства.

У всех дома есть WiFi роутер и, как правило, Умный Дом начинает разрастаться за счет недорогих WiFi устройств от производителей вроде Sonoff, Yeelight, DIY устройств на базе ESP8266 и прочих. Действительно, WiFi прост, есть у всех, дополнительно что-то приобретать и настраивать не нужно. Отсюда в сообществе происходят иногда не то чтобы споры, но оживленные дискусси с основным посылом - зачем мне вообще этот ваш "зигбее" (варианты написания бывают порой очень забавными, "zig been" как-то попадался), мне и на WiFi хорошо и все отлично работает. Мне кажется это мнение происходит от недостаточно хорошего представления о преимуществах протокола Zigbee новичками. Давайте их перечислим:

  • Низкое энергопотребление конечных устройств (где вы найдете WiFi датчик двери или, например, датчик движения, датчик протечки, который работал бы от батарейки годами?)

  • Самоорганизующаяся Mesh сеть, в отличие от звездообразной WiFi сети, где роутер является центром звезды. Например, так выглядит моя домашняя Zigbee сеть, где хорошо видно, как устройства-роутеры (синие) являются точками подключения физически далеко расположенных устройств:

  • Наличие класса конечных устройств-роутеров с постоянным питанием позволяет строить сеть на очень большой территории. Да, WiFi тоже умеет строить Mesh сети, но не с помощью исполнительных устройств-роутеров, а с помощью дополнительных WiFi роутеров подключенных в mesh сеть.

  • Огромный выбор доступных устройств на рынке. На данный момент Zigbee Alliance насчитывает сотни членов, а на рынке существует тысячи разнообразных решений с заявленной поддержкой Zigbee.

  • Безопасность. С 128-битным алгоритмом AES, используемым для шифрования данных и аутентификации, и тремя типами ключей, используемых для управления безопасностью, конечным пользователям не стоит беспокоиться об опасности взлома.

  • Относительно низкие цены на устройства.

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

Лично для меня преимущества Zigbee очевидны и я строю свой Умный Дом почти полностью на этой технологии. Конечно, у меня еще есть несколько WiFi устройств, например, кондиционер управляемый WiFi USB стиком на ESP8266, датчик потребления фильтрованной воды на Wemos D1 mini, настольная лампа Yeelight. Среди активных сторонников Zigbee такой неоспоримый авторитет в сообществе, как Алекс Квазис, который в подкасте Спрута однозначно высказывался о преимуществах Zigbee перед Wifi. Кстати, кто не слышал подкаст, то рекомендую:

Если говорить о Zigbee дальше, то всплывает еще одна горячая тема: USB Zigbee стик, шлюз Xiaomi Gateway 3 (возможно перепрошитый Sonoff шлюз) или SLS использовать в качестве координатора сети Zigbee. Или еще одна, касающаяся пользователей HomeAssistant: что лучше, Zigbee2mqtt или ZHA? Это настолько объемные темы, что заслуживают отдельной статьи. Скажу лишь за себя - я за использование Zigbee USB стика в союзе с Zigbee2mqtt. В двух словах почему: стабильность, количество поддерживаемого оборудования, независимость от прихотей производителей шлюзов или SLS, при необходимости возможность самостоятельно обеспечить поддержку неподдерживаемого устройства с помощью zigbee2mqtt external converter. Но если вы уже имеете Xiaomi Gateway 3 шлюз и хотите использовать его в качестве координатора вашей Zigbee сети, а также, возможно и для BLE mesh сети, то очень рекомендую вам послушать подкаст с AlexxIT, авторитетнейшим участником сообщества и автором интеграции этого шлюза в HomeAssistant, чтобы узнать все нюансы из первых рук:

Говорить о распространенности других протоколов для Умного Дома можно, но на мой взгляд, пока рано. Отличный протокол Zwave живет своей жизнью уже очень давно, но из-за дороговизны устройств и географического разделения рабочих частот протокола мало распространен в русскоговорящем сообществе. Хотя есть пользователи очень давних реализаций Умных Домов на Vera или Homey, у которых осталось Zwave оборудование, например от Fibaro, и которые в рамках HomeAssistant, где поддержка этого протокола очень развита, успешно используют эти устройства и поныне.

Протокол BLE mesh выглядит очень многообещающим и поддерживается последними версиями шлюзов Xiaomi. Кроме того, явно заметно разделение направлений, если устройства для Умного Дома от Aqara практически все выпускаются для протокола Zigbee, то последние новинки от Xiaomi выпускаются почти исключительно для BLE mesh. И уже сейчас вполне реально активно использовать этот протокол, покупая доступные на рынке устройства.

Что касается протокола Thread, то его в последнее время стали продвигать в Apple, включив его поддержку в HomePod Mini и новой версии AppleTV. Солидные производители вроде Eve или Nanoleaf тоже стали включать поддержку Thread в своих новых устройствах. Я думаю, маркетинговая мощь Apple может продвинуть популярность этого протокола достаточно далеко и стоит не упускать из вида этот очевидный тренд.

Но пока протокол Zigbee в Умных Домах безусловно доминирует. И меня это устраивает. Я за Zigbee, как самое сбалансированное решение на рынке на данный момент.

Красивый GUI против текстовых конфигов и чистых автоматизаций

Это очень обширная тема со множеством ответвлений и нюансов. Постараюсь быть кратким и замечу, что в моем изложении она больше относится к HomeAssistant, как к системе Умного Дома, которую я использую. В целом, эта горячая тема подразделяется на следующие два больших направления:

  • Как настраивать систему и писать автоматизации - через предоставленные возможности GUI или редактированием текстовых файлов конфигураций?

  • Зачем заморачиваться с красивым и удобным интерфейсом, делая его похожим на пульт управления космолета? Ведь настоящий Умный Дом тот, в интерфейс которого вообще не нужно заходить - все работает через точно и тонко настроенные многочисленные автоматизации.

Начнем с первого. В последних версиях HomeAssistant тренд на уход от правки yaml конфигурационных файлов в сторону настройки всего и вся через GUI был настолько очевиден, что многие старожилы сообщества загрустили о старых добрых временах, когда все настраивалось вручную. Кроме того, в свое время весомый вклад в популяризацию правки yaml конфигов внес не раз уже упомянутый Алекс Квазис со своими видео уроками по настройке HomeAssistant. Но его продвижение этого метода дало и обратный результат. Вместо того, чтобы вникать в код его примеров и пытаться в нем разобраться, начинающие, неопытные пользователи стали просто бездумно копипастить код из его уроков и слепо следовать его рекомендациям, как истине в последней инстанции. Я уверен, что Алекс не подразумевал изначально такого эффекта, но теперь в сообществе сложился устойчивый мем "так было у Квазиса в его уроке" или "я делал все по урокам Квазиса". Опытные участники сообщества лишь саркастически ухмыляются, отсылая вопрошающих с их проблемами к чтению документации и к пониманию того, что и как они делают.

Многие не любят HomeAssistant именно из-за его формата конфигураций yaml. Жесткая требовательность к форматированию, отступам многих раздражает. Написать вручную, к примеру, такую автоматизацию света на кухне с учетом датчиков движения, датчика освещенности и времени суток с множеством условий, без серьезной подготовки и опыта очень сложно:

alias: Kitchen Lighttrigger:  - platform: state    entity_id: binary_sensor.kitchen_motion_group    to: 'on'  - platform: state    entity_id: binary_sensor.kitchen_motion_group    to: 'off'    for: '00:02:03'condition: []action:  - choose:      - conditions:          - condition: template            value_template: '{{ trigger.to_state.state == "on" }}'          - condition: time            after: '09:20'            before: '23:00'          - condition: numeric_state            entity_id: sensor.lux_kitchen_illuminance_lux            below: '23'        sequence:          - service: switch.turn_on            target:              entity_id:                - switch.relay_switch_l1                - switch.relay_switch_l2                - switch.switch_kitchen_switch_center          - service: light.turn_on            data:              transition: 4              color_name: crimson            target:              entity_id: light.led_strip      - conditions:          - condition: template            value_template: '{{ trigger.to_state.state == "off" }}'          - condition: time            before: '23:40'            after: '09:20'        sequence:          - service: switch.turn_off            target:              entity_id:                - switch.relay_switch_l1                - switch.relay_switch_l2                - switch.switch_kitchen_switch_center                - switch.switch_kitchen_switch_right                - switch.switch_kitchen_switch_left          - service: light.turn_off            target:              entity_id: light.led_strip      - conditions:          - condition: template            value_template: '{{ trigger.to_state.state == "on" }}'          - condition: time            after: '01:00'            before: '05:30'        sequence:          - service: switch.turn_on            target:              entity_id: switch.relay_switch_l2      - conditions:          - condition: template            value_template: '{{ trigger.to_state.state == "off" }}'          - condition: time            after: '01:00'            before: '05:30'        sequence:          - service: switch.turn_off            target:              entity_id: switch.relay_switch_l2    default: []mode: single

Но с другой стороны, эту же автоматизацию можно собрать в GUI автоматизаций HomeAssistant. А в последних версиях еще и появилась возможность визуального дебага автоматизаций в GUI:

Дебаг автоматизаций в HomeAssistantДебаг автоматизаций в HomeAssistant

Таким образом, по этому пункту, я бы посоветовал начинающим следующее. Попробуйте совмещать оба способа при написании автоматизаций, благо интерфейс теперь это позволяет. Пробуйте составить ее через GUI, потом переключитесь в текстовый режим и поправьте что нужно в нем. Или наоборот, скопипастите готовый yaml код автоматизации и затем переключившись в режим GUI попробуйте понять логику его работы, подставьте свои нужные сущности. На мой взгляд, сочетание обоих режимов при создании автоматизаций сейчас наиболее эффективный и оптимальный подход. Также не следует забывать об очень интересной недавней фиче в автоматизациях HomeAssistant: Blueprints, или готовых шаблонах автоматизаций.

Второй пункт нашего списка касается опять HomeAssistant и настройке его интерфейса Lovelace. Да, сейчас его можно настраивать исключительно средствами интерфейса, предоставленного HomeAssistant и не думать о правке вручную файла ui-lovelace.yaml в режиме Lovelace "yaml", как было в уроках Квазиса. Но лично я предпочитаю ручную полировку интерфейса. Весь интерфейс моих дашбордов как для десктопа, так и для мобильных устройств полностью написаны вручную. Сделать два разных дашборда очень просто, достаточно в configuration.yaml прописать что-то вроде:

lovelace:  mode: yaml  resources:  - url: /hacsfiles/mini-graph-card/mini-graph-card-bundle.js    type: module  - url: /hacsfiles/mini-media-player/mini-media-player-bundle.js    type: module  - url: /hacsfiles/ha-yandex-icons/yandex-icons.js    type: module  - url: /hacsfiles/lovelace-card-mod/card-mod.js    type: module  - url: /hacsfiles/lovelace-auto-entities/auto-entities.js    type: module  - url: /hacsfiles/button-card/button-card.js    type: module  - url: /hacsfiles/vertical-stack-in-card/vertical-stack-in-card.js?v=0.4.0    type: module  - url: /hacsfiles/simple-thermostat/simple-thermostat.js    type: module  - url: /hacsfiles/simple-weather-card/simple-weather-card-bundle.js    type: module  - url: /hacsfiles/text-element/text-element.js    type: module  dashboards:    lovelace-generated: # Needs to contain a hyphen (-)      mode: yaml      filename: mobile-ui.yaml      title: Mobile UI      icon: mdi:cellphone-text      show_in_sidebar: true      require_admin: true

и уже в файле mobile-ui.yaml конфигурировать ваш отдельный Lovelace для мобилок. Для десктопа мой интерфейс сейчас выглядит примерно вот так:

Версия для десктопаВерсия для десктопа

Для мобильных устройств примерно так:

Версия для мобильного телефонаВерсия для мобильного телефона

Ну и наконец, резонный вопрос - зачем этот пульт управления космическим кораблем, если настоящий идеальный Умный Дом не должен подразумевать ручного вмешательства, управления и контроля, а все должно работать как надо автоматически?

Скажу честно, у меня нет аргументированного ответа на этот вопрос и более того, я совершенно согласен с таким пониманием идеального Умного Дома. Но я люблю интерфейсы в который не только все удобно, но и красиво, и это для меня вопрос эстетики и эргономики. Как деревенские мастера украшают совершенно утилитарные вещи вроде ставен на окнах домов изысканной резьбой, так же и мне доставляет эстетическое и эргонометрическое удовольствие оптимизация вручную интерфейса моего Умного Дома. Кроме того, я достаточно регулярно пользуюсь мобильным приложением HomeAssistant, где мой удобный и оптимизированный мобильный дашборд весьма кстати.

Тут у меня не будет никаких выводов и рекомендаций. Все очень просто - выбирайте тот вариант, который вам ближе. Тут любые варианты правильные.

HomeAssistant против Node Red. Или вместе с ним.

Эта тема характерна для споров между уже опытными и продвинутыми строителями Умных Домов, Бань, Дач и Сараек. Она не так остра и популярна, но написать о ней мне все же хочется. Хочется, потому, что когда-то этой теме было посвящено немало споров в уютном лампово-теплом сообществе телеграм чата Homever.

Примерный вид обычного Node RedПримерный вид обычного Node Red

Скажу сразу, я попробовал Node Red и он мне не зашел. Визуальное создание автоматизаций перетаскиванием и связыванием каких-то прямоугольников различного назначения лично мне не показалось удобным и интуитивным. Мне гораздо проще и понятнее описывать автоматизации текстом, в yaml, в HomeAssistant. В общем, опыт с Node Red у меня небольшой, судить о нем авторитетно я не могу. Я запустил и отладил несколько флоу, но не более того.

Логотип HomeAssistantЛоготип HomeAssistant

Но тем не менее, я могу поговорить о чем спорят и говорят на эту тему в сообществе. А говорят следующее. Node Red может быть совершенно самостоятельной системой Умного Дома, с интеграцией устройств, собственным дашбордом, ну и конечно, собственными мощными автоматизациями. Также Node Red может работать в тесной связке с HomeAssistant выступая системой автоматизации для него. То есть вы подключаете устройства через HomeAssistant, который позволяет это сделать намного эффективнее, чем Node Red, и поддерживает гораздо больше интеграций для подключения огромного количества всевозможных устройств, но все автоматизации для этих подключенных устройств и сущностей вы создаете средствами подключенного Node Red.

Почему-то принято считать, что возможности и гибкость автоматизаций в Node Red значительно превосходят таковые в HomeAssistant с чем я совершенно не согласен. Я не знаю ни одного сценария автоматизации, который можно было бы реализовать в Node Red и нельзя было повторить средствами автоматизаций HomeAssistant. На этот неоднократно заданный адептам Node Red вопрос я так ни разу и не получил убедительного примера такого сценария.

Таким образом, целесообразность такой связки двух систем мне кажется избыточной и нерациональной хотя бы с точки зрения стабильности. Каждая из этих двух систем вполне самодостаточна, разве что в Node Red нет такого красивого интерфейса, как в HomeAssistant. Но это важно далеко не всем. Ну и возможности подключения огромного разнообразия устройств у Node Red значительно скромнее. Для чего нужен конгломерат двух серьезных и мощных систем, мне непонятно. Знаю пользователей таких симбиозов, которые используют подключения устройств и там и там, да еще и автоматизации создают средствами обоих систем. Представляете, какая каша из сущностей и связей там образуется? Надежность и стабильность такой связки двух систем вызывает у меня большие сомнения.

Мое мнение: максимально глубоко изучите возможности Node Red или HomeAssistant и используйте что-то одно. Каждая из этих систем в отдельности способна полностью удовлетворить все ваши требования к Умному Дому. Хотя, с другой стороны, я могу понять тех, кто имеет устройства, которые не поддерживаются в Node Red, но подключаются в HomeAssistant и он используется в качестве некоей прослойки для проброса подобных устройств в Node Red, а также, возможно, для красивых дашбордов для настенных панелей в виде вмонтированного планшета, например.

В общем, спор, какая из систем лучше совершенно не актуален. А на вопрос о том, стоит ли собирать их в симбиоз, каждый отвечает сам для себя.

Заключение

На самом деле я затронул лишь малую часть горячих тем в сообществах строителей Умных Домов. Их гораздо больше по самому широкому кругу вопросов. Например, есть популярная тема о том, что лучше и надежнее - проводное или беспроводное подключение устройств? Или тема о том, каким воспользоваться способом для настройки подключения SSL сертификатов и проброса HomeAssistant наружу в интернет.

Если вас интересует тема Умных Домов и вы готовы погрузиться в нее с головой, подписывайтесь на профильные телеграм чаты по HomeAssistant, этот, или этот. На чат обо всем, касающемся темы Zigbee. На персональный канал большого авторитета Ивана Бессарабова, где найдете кладезь полезной информации. Ну и на упомянутый выше ламповый чат сообщества Homever

Хорошо понимаю, что опытным участникам сообщества многие мои выводы могут показаться спорными и даже неверными. Но ведь для того мы и создаем сообщества, чтобы в споре и обсуждениях находить истину, не так ли?

Подробнее..

Практики при работе с PHPUnit

26.04.2021 06:12:41 | Автор: admin

Не секрет, что чем больше проект, тем с большим количеством проблем он сталкивается даже в самых элементарных аспектах. В продукте Plesk, над которым я работаю, PHP является одним из основных языков, и количество кода на нем превышает 1 миллион строк. Соответственно, мы активно используем PHPUnit для тестирования. Кроме большого объема кода, поддержка двух платформ (Linux и Windows) доставляет нюансы, как и тот факт, что поддерживается несколько бранчей с приличной разницей возраста (крупные релизы), а активно вносят правки несколько десятков инженеров. В статье я хочу поделиться некоторыми практиками, которые мы используем при работе с PHPUnit.

Унификация

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

В мире PHP принято, чтобы зависимости устанавливались с помощью composer install, а команда composer test прогоняла набор тестов. В контексте PHPUnit это означает следующее. Зависимость на PHPUnit должна присутствовать в разделе "require-dev" в composer.json:

  "require-dev": {    ...    "phpunit/phpunit": "^9.5",

В разделе scripts, соответственно, должно присутствовать описание для команды test:

  "scripts": {    ...    "test": "phpunit",

Различные линтеры и статические анализаторы, если используются, тоже должны оказаться частью этой команды:

  "scripts": {    ...    "test": [      "@phpcs",      "@phpstan",      "@psalm",      "@phpunit"    ],

Далее конфигурацию для PHPUnit нужно определить в phpunit.xml.dist, а файл phpunit.xml занести в .gitignore. Тем самым мы унифицируем опции запуска PHPUnit, оставляя возможность локального оверрайда для каких-то экспериментов. Репозиторий после клонирования, прогона composer install и запуска composer test не должен требовать каких-то дополнительных манипуляций. Поэтому в phpunit.xml.dist определяем, где искать тесты, что исключать, какие опции использовать и т.п.

<?xml version="1.0"?><phpunit  xmlns:xsi="http://personeltest.ru/away/www.w3.org/2001/XMLSchema-instance"  bootstrap="common/php/tests/bootstrap.php"  executionOrder="random"  ...>  <php>    <ini name="memory_limit" value="-1"/>    <ini name="display_errors" value="true"/>    ...  </php>  <testsuites>    <testsuite name="Plesk Common TestSuite">      <directory>common/php/tests</directory>      <exclude>common/php/tests/stubs</exclude>      ...    </testsuite>  </testsuites>  <coverage includeUncoveredFiles="true">    ...  </coverage></phpunit> 

Осталось определиться с версией PHP, необходимыми расширениями и занести эту информацию в composer.json:

  "require": {    "php": "^7.4",    "ext-fileinfo": "*",    "ext-intl": "*",    "ext-json": "*",    "ext-mbstring": "*",    ...  }

Базовая подготовка закончена. С одной стороны, все просто. С другой стороны, регулярно попадаются проекты, где какой-то из моментов выше оказался проигнорирован.

Docker

А куда же без него? Раз уж мы заговорили об унификации, то неоценимую помощь оказывает и использование Dockerа. Речь не только о его необходимости для запуска тестов в рамках CI-процесса. Для тех, кто не использует PHP в ежедневной работе, например, для QA-инженера, может быть удобным запуск тестов в Docker. Удобным в первую очередь тем, что снимает необходимость в установке нужной версии PHP со всеми расширениями на локальную машину. Кроме того, это если в разных релизах использовалась разная версия PHP, то использование Dockerа облегчает бэкпорт патчей и прогон тестов в соответствующих бранчах.

Организовать все это можно в виде отдельного Dockerfileа, например, Dockerfile-test со следующим содержанием:

FROM php:7.4-cliRUN apt-get update \    && apt-get install -y libxslt1-dev libzip-dev \    && docker-php-ext-install xsl \    && docker-php-ext-install intl \    && docker-php-ext-install zip \    && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Далее создаем инструкции для Docker Compose (в моем случае в файле docker-compose.test.yml):

version: '3'services:  tests:    build:      context: .      dockerfile: Dockerfile-test    command: bash -c "cd /opt/plesk && composer install && composer test"    volumes:      - .:/opt/plesk

В итоге получается достаточно идиоматический запуск тестов:

docker-compose -f docker-compose.test.yml run tests

Разница по времени между между локальным прогоном и прогоном в Dockerе в моем конкретном случае составляет 3 раза. То есть примерно 30 секунд против 10 секунд для локального прогона.

PhpStorm

Для написания PHP кода обычно используется PhpStorm. Есть в нем и удобные инструменты по работе с PHPUnit.

Во-первых, это запуск тестов, выбирая конфигурацию из меню Run (или контекстного меню) phpunit.xml.dist или директорию, где расположены тесты. Накладные расходы на дополнительную визуализацию в PhpStorm на моей локальной машине в конкретном проекте (~4500 тестов.) плавают в диапазоне 10-30%, но в абсолютных цифрах это 13 секунд, против 10 секунд при запуске в терминале, что совершенно несущественно.

Второй удобный момент при интенсивной работе с тестами и их активном написании это режим наблюдения. Включаем его в соответствующей панели:

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

При наличии нескольких мониторов, очень удобно вынести окно с тестами на отдельный монитор и включить автоматический перезапуск. А чтобы тесты не перезапускались слишком часто, можно поиграться с настройкой задержки запуска:

Внешнее наблюдение за тестами

Функционал наблюдения за тестами в PhpStorm существует уже года 3. До этого задача решалась с помощью внешнего наблюдателя. Однако и сейчас по определенным причинам внешний наблюдатель может быть полезен (например, вы правите код в vimе или VSCode).

Наиболее популярный и живой проект по данной теме это phpunit-watcher. Добавляем его с помощью composer и определяем phpunit-watcher.yml примерно следующего содержания:

watch:  directories:    - common/php    - ...  fileMask: '*.php'phpunit:  binaryPath: common/php/plib/vendor/bin/phpunit  arguments: '--stop-on-failure'

Также в composer.json в раздел scripts добавляем еще одну команду:

"scripts": {    ...    "test:watch": "phpunit-watcher watch",    ...

Таким образом, для того, чтобы запустить тесты под наблюдением, используется команда composer test:watch Отправляем ее жить в окошко терминала на отдельный монитор и получаем удобство наблюдения, аналогичное PhpStormу.

Контроль уровня покрытия

При росте кодовой базы и количества тестов возникает желание удерживать code coverage хотя бы на уже существующем уровне (а в идеале увеличивать его). Можно сколько угодно пытаться контролировать это руками (например, силами какого-то конкретного инженера), а можно поручить эту задачу роботу.

Схема выглядит следующим образом. Сначала выполняем подсчет code coverage, смотрим процент покрытия и устанавливаем его как отправную точку. Далее создаем скрипт, который будет возвращать ненулевой код возврата (определяя падение), если текущий процент code coverage стал ниже отправной точки. Данный скрипт используется в проверках на pull requestах, таким образом не давая замержить изменения, если процент code coverage упал. Добавил новый код? Нужно добавить тесты. С роботом-ревьювером уже нельзя договориться, мол, я чуть позже их добавлю. Он беспристрастно поставит блокировку.

Для подсчета code coverage используется расширение Xdebug. На данный момент, на версии 3.0 на всех проектах, которых смотрел, дело заканчивается segfaultом (есть как плавающие баги, так и стабильно повторяемые проблемы), поэтому продолжаем пока использовать 2.9.0. Подключение расширения с настройками по умолчанию (xdebug.mode=develop) даже без подсчета code coverage приводит к 2-3 кратному замедлению прогона тестов. В конкретном случае с ~4500 тестами на моей локальной машине процесс замедляется с 10 секунд до 27 секунд. Пока еще не сильно критично, но уже довольно заметно. Если запустить прогон тестов вместе с подсчетом code coverage, то он займет в моем случае больше 30 минут. Если процент code coverage упал, вы добавляете новые тесты и несколько раз выполняете их прогон, то ждать несколько раз по 30 минут это довольно долго.

Анализ показывает, что больше всего времени требуется для генерации отчета в HTML. Так как сам отчет нас не особо интересует, то можно воспользоваться опцией --coverage-php, а далее полученный файл проанализировать собственным скриптом. В итоге проверка текущего процента code coverage из 30 минут превращается в 2 минуты на прогон тестов и еще примерно 2,5 минуты на анализ репорта (напомню, что проект довольно большой, и файл занимает более 60 Мб). Есть еще поле для оптимизации, но текущий вариант уже устраивает. Например, сократить первую фазу с 2 минут до 1 минуты можно с помощью pcov.

В phpunit.dist.xml нужно определиться с секцией coverage. Также важно указать опцию includeUncoveredFiles, потому что процент покрытия нужно считать от всех файлов, а не только тех, которых касались тесты.

 <coverage includeUncoveredFiles="true">    <include>      <directory suffix=".php">common/php</directory>      ...    </include>    <exclude>      <directory>common/php/plib/locales</directory>      <directory>common/php/plib/vendor</directory>      <directory>common/php/tests</directory>      ...    </exclude>  </coverage>

В composer.json формируем команду для проверки с учетом всего вышесказанного:

 "scripts": {    ...    "test-coverage-threshold": [      "@php -dzend_extension=xdebug.so -dxdebug.mode=coverage common/php/plib/vendor/bin/phpunit --coverage-php .phpunit.coverage.php",      "@php -dzend_extension=xdebug.so common/tools/coverage-threshold.php .phpunit.coverage.php 12.49"    ],    ...

Где магическая цифра 12.49 это текущая отправная точка процент code coverage, ниже которого опускаться нельзя. Она не должна сильно отставать от текущего состояния, и периодически при добавлении новых тестов нужно не забывать ее подкручивать.

Повышение качества кода тестов

Когда тестов становится сотни или тысячи, то возникает проблема их взаимозависимости. Не только код самих тестов, но и код продукта будет преподносить различные сюрпризы. По умолчанию запуск тестов идет в рамках одного PHP-процесса. Любое кэширование, staticи, синглтоны, регистры или, не дай бог, глобальные переменные и даже заглушки и моки обязательно станут проблемой. Нужно понимать, что в большинстве случаев связность возникает совершенно неосознанно, поэтому нужно превентивно бороться с человеческим фактором.

Один из стресс-методов для проверки является запуск тестов командой composer test -- --process-isolation. В таком режиме каждый тест будет запускаться в рамках отдельного PHP-процесса. Изоляция это прекрасно, но на практике в таком режиме возникает сразу несколько нюансов. Во-первых, работает это все крайне медленно. Вместо 10 секунд будет уже порядка 14 минут в моей конкретной ситуации. Во-вторых, не все вещи будут работать в такой конфигурации. Например, в data providerах можно использовать только сериализуемые структуры (а коллеги-программисты могли надобавлять туда уже замыканий, моков и других динамических радостей). С первой проблемой можно пытаться бороться с помощью ParaTest, однако у него есть еще дополнительные ограничения.

Относительной альтернативой опции --process-isolation является запуск тестов в случайном порядке. Для этого можно использовать опцию командной строки --order-by=random, либо указать в phpunit.xml.dist для корневого тега атрибут executionOrder="random". Локализовывать и отлаживать проблемы заметно сложнее, чем в случае с --process-isolation, но вполне реально. Обращаем внимание на сгенерированный random seed в начале вывода от PHPUnit и повторяем прогон командой ниже:

composer test -- --order-by=random --random-order-seed=1617073223

Тест, который падает, может находиться за сотни тестов от того, который создает проблемы. Для того, чтобы по сути просимулировать поведение опции --process-isolation, можно в рамках setUp/tearDown сбрасывать принудительно все кэши, приводить конфигурацию моков в исходное состояние и делать прочие инициализационные действия. В итоге создание взаимозависимых тестов сильно осложняется. Возможно, такой тест не будет пойман с первой попытки, но после несколько прогонов он обязательно всплывет.

Еще один момент, на который стоит обратить внимание, это скорость выполнения каждого отдельного теста. Один из вариантов ее узнать это использование опции --log-junit. В результате будет получен XML-файл с информацией о времени, затраченном на каждый тест. Можно написать простенький скрипт для анализа, а можно воспользоваться встроенным функционалом в PhpStorm и сортировкой по времени:

Код тестов это тоже код, поэтому не стоит игнорировать проверки на соответствие принятого стиля или следования общепринятым практикам написания хорошего кода. Автоматизированные линтеры также должны проверять и директорию с тестами. На самом деле, тесты с низким качеством кода довольно часто в итоге оказываются моргающими (flaky) тестами.

Поддержка двух платформ (Linux и Windows)

Если вам посчастливилось писать продукт под две платформы (Linux и Windows), то в рамках тестов нужно учитывать то, каким образом проверяется платформозависимый код. Вилки по константе PHP_OS, использование PHP_EOL все это обязательно создаст проблемы, а перебить их не получится даже с помощью runkitа. В идеале, прогон тестов на PHP код для Windows должен иметь возможность сделать и разработчик, у которого рабочая машина под Linux или Mac. Поэтому механизм определения платформы лучше сразу сделать конфигурируемым. На поздних этапах вкручивать его довольно тяжело. Если платформозависимого кода довольно много, может оказаться проще использовать два запуска тестов, указывая платформу через переменную окружения:

PHP_OS=WINNT composer testPHP_OS=Linux composer test

Поле для экспериментов

Периодически выходят новые мажорные версии PHP, и самый первый шаг и довольно быстрый способ проверки и поиска проблем это прогон тестов. В этом сильно помогает Docker и упомянутый выше Dockerfile, чтобы не влиять на локальную машину. Ведь для большого проекта момент готовности кодовой базы к новой версии PHP и сам момент перехода на новую версию довольно разнесенные по времени события. Соответственно, в первую очередь делаются forward compatible изменения, и проверяется работоспособность тестов на двух версиях (старой и новой версии PHP).

Проверку новых фичей языка и синтаксиса также очень удобно делать в рамках кода тестов. Это довольно безопасно, так как код тестов не идет в релиз, и при этом вы получаете возможность прочувствовать нововведения. На самом деле, это могут быть любые нововведения в рамках кодовой базы (необязательно новые фичи языка). Допустим, решили, например, следовать PSR-2 и убрать символ нижнего подчеркивания из имен protected и private переменных и методов. Первое, где можно попробовать обкатать скрипты замены и рефакторинга, это код тестов.

Заключение

В заключение отмечу основные моменты. Когда тестов становится много, то их качество выходит на первый план. Контроль уровня покрытия лучше отдать на откуп автоматическим проверкам pull requestов, а код тестов это очень удобное и безопасное поле для экспериментов.

Как говорится, да прибудут с вами всегда зеленые тесты :)

Подробнее..

Легко ли быть рок-звездой, если ты IT-шник и почему вам тоже полезно заниматься музыкой

22.03.2021 12:19:24 | Автор: admin

Их было шестеро - барабанщик, басист, клавишник, гитарист, баянист и человек с татуировками. Как-то так начинался бы фильм о нас, о музыкальной группе Sun-Techniki.

Вы, возможно, скажете ШТА?! Я точно на Хабре? Причём тут какой-то фильм о музыкальных сантехниках?

Да, это Хабр, и это рассказ про музыкальную группу, состоящую из сотрудников одной продуктовой IT-компании.

Я всегда мечтал заглянуть в закулисье музыкальных коллективов, но в данном случае в наше закулисье заглянуть сможете вы. Какие процессы из IT-мира мы используем в нашей музыкальной деятельности, как вообще это выглядит, и почему людям из IT стоит заниматься музыкой - в моём рассказе.

Кратко о нас: мы не профессионалы в музыке, мы профессионалы в разработке софта. Наш софт обслуживает 6% активных веб-сайтов мира (согласно Netcraft), а наша группа выступает на корпоративах в качестве хедлайнеров и за восемь выступлений мы подготовили и сыграли без малого сорок каверов. На каждое выступление мы готовим новую программу, при этом текст часто переделывается так, чтобы отражать тему корпоратива и события в жизни компании. В поддержку выступления идут слайды, которые крутит наш слайд-жокей.

Рассказ получился объёмным, поэтому без оглавления никуда:

  1. Старт проекта / Прикидываем программу выступления

  2. Управление проектом / Дисциплина бьёт талант

  3. Прототип / Щупаем номера

  4. MVP (точнее, MAP) / Минимально допустимое выступление

  5. Тестирование, багфиксинг / Гоняем программу, находим места для улучшений

  6. Релиз (раскатка) / Выступление

  7. Ретроспектива

  8. Заключение / Почему вам тоже стоит заниматься музыкой

  9. Бонусы

Вступление закончено, начинаем!


Старт проекта / Прикидываем программу выступления

Дедлайн / Дата выступления

Корпоратив состоится 21 декабря - если ждать такого письма, то ничего не успеешь. Но зачем ждать, если известно, что корпоративы будут в конце декабря и в конце июля, а восьмое марта будет седьмого марта? Мы ретроспективно знаем свою capacity, поэтому собираемся за три месяца до предполагаемого дедлайна. Позже будет известна точная дата, позже будет известна точная тема, но мы уже должны начинать.

Содержание проекта / Треклист

Начинаем мы с кандидатов в треклист выступления. У выступления есть стандартный общий план:

  • выход (что-то пафосное, заряжающее, вызывающее аппетит)

  • разогрев (может быть совмещён с выходом)

  • заполнение (обычно что-то спокойное)

  • набор напряжения (мы называем это ebanukha, что в переводе с суахили означает это воняет, то есть что-то панковское отвязное, может быть треш)

  • финал, в котором должен произойти катарсис и поставлена точка

Пруф про суахилиПруф про суахили

Ресурсы / Кто участвует в выступлении

Для получения классического проектного треугольника осталось понять ресурсы. Может показаться, что здесь всё понятно - нас шестеро, но были в истории времена, когда кто-то не мог участвовать в конкретном выступлении по разным причинам. Поэтому эти моменты надо проговаривать каждый раз, даже если кажется, что проект типичный.

А ещё у нас был фит с музыкантами не из нашей группы, в таких случаях на этапе старта проекта нужно понять график доступности этих ресурсов ну и интегрировать их в проект.

Брейншторм

Соответственно, на каждый этап брейнштормятся треки. Кандидатов мы берём как просто из головы, так и из нашего слак-канала, ну и конечно же из бэклога.

Про брейншторм на Хабре писали, например, тут: 15 способов превратить мозговой штурм в результат огонь

Брейншторм у нас не совсем классический - после вброса кандидата мы сразу обсуждаем его. Кандидат отбрасывается если:

  • кто-то против. Достаточно одного голоса.

  • штука очевидно нам не по зубам на текущий момент. Такой кандидат обычно идёт в бэклог - в следующий раз может быть мы будем к нему готовы.

  • вещь никак не сочетается с другими кандидатами или темой (конь-цепцией). Тоже в бэклог.

  • вещь очевидно заметно слабее тех, кто уже есть в кандидатах. Нет смысла тратить на неё время сейчас. В бэклог.

  • вещь очевидно не будет принята аудиторией или другими заинтересованными лицами

Очевидно у нас означает мнение большинства. Мы отлично знаем, что нет ничего очевидного.

Как пример пункта 5 - я всегда хотел на восьмое марта (а лучше на 14 февраля) выпустить кавер на трек Pussy от Rammstein. Моё извращённое чувство юмора считает, что это постирония и очень смешно. Но как Product Manager я понимаю, что core segment аудитории этот пассаж не оценит.

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

Управление проектом / Дисциплина бьёт талант

Мы в продуктовых компаниях немного избалованы тем, что дедлайн часто не дедлайн, а ETA, то есть если ты не успеваешь, то ETA можно сдвинуть.

Другое дело релиз концерта. Это проект: тут есть понятный бюджет (наш бюджет - это время, которое мы можем потратить на подготовку), чёткий expected result, жёстко зафиксированная дата, есть неопределённость пути от начала к концу. Поэтому для работы над концертом мы выбираем не гибкие методологии (мы их тоже умеем), а традиционное PMBoK-овское проектное управление.

План (Work Breakdown Structure a.k.a. Иерархическая структура работ)

Ключевые вещи в проектном управлении - это WBS (Work Breakdown Structure), майлстоуны (то есть промежуточные дедлайны), зависимости, ресурсы и управление рисками.

Про проектное управление: PMBoK за 2.5 часа: интервью с Иваном Селиховкиным

Про конкретно WBS: 4 инструмента по полочкам. Управление проектами с WBS, Диаграммой Ганта, CPM и Time-Cost или Преимущества Иерархической Структуры Работ (WBS) для менеджеров ИТ проектов

Про оценку задач: Оценка. Рассчитать и уложиться

Про управление рисками расскажу сам ниже.

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

Капитанские, но, оказывается, не всем очевидные принципы построения WBS:

  • строй WBS справа налево (вот так: <--), то есть:

    • справа напиши результат - концерт готов

    • задай вопрос что мешает считать, что результат достигнут? - номера не готовы, сцена не готова

    • и так рекурсируй до элементарных задач

  • после составления WBS пройди уже слева направо (-->) и на каждую задачу задай вопрос а почему я не могу эту задачу выкинуть?

  • майлстоуны аналогично - справа налево (опять <--). Потому что дедлайн у нас задан заранее

В традиционных трудах по WBS эту структуру рисуют сверху вниз (вверху цель, внизу этапы), но сейчас чаще это всё укладывают в диаграмму Ганта (ужас какой), поэтому я и пишу про справа налево.

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

Вопрос а как мне понять расчётную стоимость задачи оставлю для другой статьи, тема эта считается сложной и здесь я её не раскрою. Мы ретроспективно знаем, что в среднем нужно три-четыре репетиции для MVP одного номера, и ещё пяток репетиций могут уйти на шлифовку. И ещё мы заранее знаем, что мы захотим дополнительные репетиции вне обычного графика, то есть раш (кранч, овертайм - как вам угодно) обязательно будет, так что можно его и запланировать ;)

Инструментарий

Мы не используем ничего тяжёлого - нас не так много, проект структурно не такой сложный. Нам хватает каталога в Google Drive на концерт, в этом каталоге несколько документов:

  • тексты и прочие заметки по номерам

  • документ по планам и рискам (в нём несколько секций, в том числе и оперативные - worklog, brainstorm, шорт-лист треков и подобное)

  • чеклист на сам концерт, он же райдер ;)

  • после концерта в каталог добавится документ по ретроспективе

Отдельно, в корне, лежит документ с общим бэклогом.

Пример записи в ворклоге, кое-как нашёл, ибо такие вещи очень динамичны и лишнее потом просто удаляетсяПример записи в ворклоге, кое-как нашёл, ибо такие вещи очень динамичны и лишнее потом просто удаляется

Управление рисками

Отдельно коснусь моей любимой темы - управление рисками. Почему тема любима - потому что она незаслуженно игнорируется очень многими. А ведь это просто и полезно!

Как и обещал, про риски рассказываю прямо здесь, без ссылок.

Алгоритм:

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

  2. У риска оценивается вероятность срабатывания и тяжесть последствий

  3. Риски сортируются по вероятности и тяжести, и в работу берётся N топов в каждой категории. N зависит от бюджета на работу над рисками

  4. Риску прописываются два плана:

    1. План А - что надо сделать для уменьшения вероятности срабатывания риска

    2. План Б - что надо будет сделать для уменьшения тяжести последствий в случае срабатывания риска

Когда у тебя есть такая таблица, то ты мало-мальски готов встретиться с фортуной лицом к лицу, а не как обычно.

В нашем случае самые сложные риски - это если участник группы не сможет присутствовать на концерте (заболеет, например) и если какой-то из треков не получится нормально подготовить.

Для первого риска (участник заболел) предлагаю вам придумать План А и План Б и написать его в комментариях, а про второй (номер не получается) расскажу сам - План Б там вовремя понять, что не прёт и заменить трек на резервный.

Резервный трек отбирается так, чтобы его можно было легко и быстро подготовить. Как вариант резервного трека можно взять старый трек, который мы уже когда-то готовили. Если даже План Б провалился, то есть План Б2 - выкинуть трек вообще и выходить сокращённой программой. Ну либо затащить слабый номер харизмой ;)

Из типичных рисков - плохой звук на площадке. Здесь хорошего Плана Б нет, поэтому в План А (грамотно подготовить площадку и звук на ней) вкладывается довольно много ресурсов, это и выезд на площадку заранее (чтобы можно было перенести площадку в другое место), и найм крутых звуковиков, и несколько саундчеков, и детальнейший чеклист. Но про это ниже.

Из рисков, которые мы не учитывали, но которые сыграли - это выход из строя оборудования. Один раз у нас сломался баян за пять дней до выступления. Сломался жёстко, я не смог его починить. План Б мы выдумали и осуществили очень оперативно - попросили баян взаймы у знакомых. А План А я потом выполнял самостоятельно - купил новый баян.

Этот опыт нас ничему не научил, и в следующий раз у нас сломалась гитара, точнее, нам её немножко разбили во время фотосессии. Ну а ещё позже мы решили разбить гитару на выступлении - ну а чо, все так делают!

Прототип / Щупаем номера

Кроме каверов на песни мы также пробовали делать каверы на плакаты. Кто не узнал - это Sonne от Rammstein.Кроме каверов на песни мы также пробовали делать каверы на плакаты. Кто не узнал - это Sonne от Rammstein.

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

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

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

Ещё серьёзный момент, который может выкинуть вроде бы подходящее произведение - это необходимость одновременно играть и петь. Номинально у нас четыре вокалиста, но если ритмически инструментальная партия сложна, либо просто сложна технически, то значит этот инструменталист петь нормально не сможет.

Это всё и выясняется на прототипировании, или, как мы это называем, на прощупывании.

Очень хорошая привычка - документировать всё что можно. Сколько раз на репетиции во время свободной импровизации были найдены отличные идеи, но к следующей репетиции эти идеи забывались напрочь :( Всё превращать в бумажный документ слишком затратно, но вот записывать репетиции целиком - это просто и в некоторых случаях бесценно!Очень хорошая привычка - документировать всё что можно. Сколько раз на репетиции во время свободной импровизации были найдены отличные идеи, но к следующей репетиции эти идеи забывались напрочь :( Всё превращать в бумажный документ слишком затратно, но вот записывать репетиции целиком - это просто и в некоторых случаях бесценно!

MVP (точнее, MAP) / Минимально допустимое выступление

Из продуктового опыта мы знаем, что лучше всего сделать MVP (Minimum Viable Product), и потом его дободрить. Почему? Тема для отдельной статьи ;)

В нашем случае более правильно говорить не MVP, а MAP - Minimum Awesome Product. Ни нам, ни нашей публике не нужно тухлое выступление, нужно awesome выступление!

Про MVP: MVP: что это такое и как работает? (а тут разбор знаменитой картинки с самокатом: Как определить функционал MVP и влюбить клиента в пилотную версию продукта) и сорри за Medium, но на Хабре не нашёл подходящей статьи: The MVP is dead, long life to the MAP.

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

Вовлечение / Эмоциональная кривая

В концерте, как и в любом художественном произведении, нужна завязка, развитие и финал. За этим нужно следить на всех уровнях - вечер целиком (наше выступление должно быть кульминацией), само выступление, отдельный номер.

Трёхактная схема, классика.Трёхактная схема, классика.

Отличаемся от других / Фишки номеров

Для успеха продукт должен чем-то выделяться, чем-то отличаться от остальных. Мало кому (а прежде всего нам самим) интересны каверы один в один. Это значит, что в кавере должно быть что-то своё. Это может быть другой стиль, это могут быть какие-то фишечки с заменой инструментов или переплетением разных треков. И всё это должно быть не в одной песне, а цельно на всё выступление.

Кто услышит тут отсылочку к совершенно другому произведению - пишите в комментах! И отдельное спасибо программе "Соль" за proof of concept участия баяна в этой песне.

UI, UX / Тексты

Мы всегда хотим, чтобы тексты у нас были готовы уже на этапе MVP, но как правило по самым разным причинам у нас это не получается. Практически никогда тексты не были готовы заранее. Не делайте так ;) Тексты - это сложно, это важно, они могут поменять аранжировку (когда выбранная аранжировка плохо поддерживает текст). Делайте тексты как можно раньше.

С IT-продуктами аналогично - нужны фишечки, нужны эмоции и нужны тексты, ибо тексты - это UX. И нужно это как можно раньше, ибо чем раньше найдена проблема, тем дешевле её исправление.

Но есть и отличие - в IT часто нужна поддержка разных языков, в музыке такое обычно не делают, хотя синхронный сурдоперевод встречается на концертах всё чаще и чаще.

Тексты писать сложно. Здесь есть своя теория и свои инструменты, кому интересно - могу рассказать и про этот аспект, я как-то потратил приличное количество времени, пытаясь автоматизировать это дело, но на данном этапе развития технологий в нашем случае эффективнее писать вручную.Тексты писать сложно. Здесь есть своя теория и свои инструменты, кому интересно - могу рассказать и про этот аспект, я как-то потратил приличное количество времени, пытаясь автоматизировать это дело, но на данном этапе развития технологий в нашем случае эффективнее писать вручную.

Тестирование, багфиксинг / Гоняем программу, находим места для улучшений

До этапа MVP ты думаешь, что всё будет классно, вы опять зажжёте, будете прекрасно восприниматься, всё хорошо и всё такое. Но когда MVP по сути готов, происходит скачок требований, и ты начинаешь докапываться до себя. Здесь не то, и тут не так. Это ужасно, с этим нельзя выходить на сцену, это позор! Тут главное не опускать руки, спокойно остановиться, осмотреться и понять, что конкретно нужно доработать.

Product Walkthrough / Прогоны, сценические образы

На этом этапе мы уже начинаем прогонять программу целиком, включая слова между номерами, думая над движениями и расстановкой на сцене, прикидывая образы. Очень помогает запись прогона и прослушивание - где провисы, где скучно, где неуверенно, где непонятно, где переход излишне резок или излишне плавен. Включается режим максимального докапывания (я бы даже написал слово пожёстче, но РКН не дремлет).

То есть начинается тестирование и багфиксинг. Тяжёлое время, но именно тут продукт становится полноценным, готовым к продакшену.

Как не вспомнить анекдот:

Ветеринар на на приёме у Терапевта:

Терапевт: На что жалуетесь?

Ветеринар: Не, ну так-то каждый может!

Бета / Последние штрихи, препродакшн

В теории продуктового менеджмента где-то здесь нужно привлечь фокус-группу, но мы такой радости лишены, ибо наше выступление должно быть сюрпризом, и все детали держатся в тайне. Так что в нашем HADI-цикле буква D означает данные только изнутри системы, без участия целевой аудитории. Однако к помощи эксперта-критика мы обращаемся - у нас есть специальный человек, который подключается как раз на этапе тестирования. Это наш слайд-жокей.

Про HADI-цикл: Кейс: как ускорить развитие проекта

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

Релиз (раскатка) / Выступление

Приближается день выступления. И здесь та же самая петрушка, что и в самом начале - если спохватиться поздно, то велики шансы запороть всё то, что ты делал три месяца.

Работа с аутсорсерами / Саундчек

Для концертов нужно концертное оборудование, об аренде которого нужно договориться заранее. Заранее нужно договориться о приезде звуковика, чтобы он настроил всё это. Хороший звуковик стоит дорого, поэтому может быть так, что он нанимается на саунд-чек, а на самом выступлении работает другой звуковик, подешевле. С обоими звуковиками крайне желательно встретиться заранее, чтобы подготовить список оборудования.

О да, это всё должно быть в WBS, о котором я говорил в начале статьи.

Очень важно, нет, не так ОЧЕНЬ ВАЖНО провести нормальный саундчек. Нормальный - это значит прогнать программу несколько раз. В нашем случае программа обычно полчаса, значит, на саундчек нужно три часа. Это не считая монтажа оборудования, который может занимать часа два (иногда и больше).

Это типичная работа с аутсорсерами, со всеми плюсами и минусами. Кто из продуктовых команд и имел такой опыт, вероятно, сейчас смахнули скупую слезу. Да, это может быть сложным и, что самое неприятное, это может быть провальным.

Мы в IT любим канареек, это помогает защищаться от провалов (Ускоряем деплой на продакшен канарейками и самописным мониторингом), но в музыке канареечная раскатка хоть и возможна, но сложна, ну и в нашем случае недоступна - у нас же не тур, а ровно один концерт.

Чеклисты

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

Спасают чеклисты и проверка по ролям, например, после погрузки оборудования очень полезно подробное проговаривание вслух того, что будет происходить, и указывание пальцем на тот предмет, про который мы говорим. Мы приезжаем, заходим в зал, ставим вот это пианино на вот эту стойку - опппа, а где стойка?! не погружена в машину!!1

Про ТЗ: Стандарты и шаблоны для ТЗ на разработку ПО

Ретроспектива

Очередной эксперимент - добавили женский вокал, организовав фит с коллегами. В центре в светлой футболке - наш слайд-жокей, он же критик. И не просто критик - эксперт в тяжёлой музыке, автор статей в музыкальные журналы!Очередной эксперимент - добавили женский вокал, организовав фит с коллегами. В центре в светлой футболке - наш слайд-жокей, он же критик. И не просто критик - эксперт в тяжёлой музыке, автор статей в музыкальные журналы!

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

Обычная такая ретроспектива - что было хорошо и что мы будем продолжать делать; что можно улучшить и каким образом.

Обратная связь (ищем Market Product Fit)

Нередко на аудиторию запускается анонимный опросник. Мы пробовали разные форматы - NPS, market product fit, и так далее, я полагаю, тут всё очень индивидуально. Также мы слушаем, что говорят люди, какие фотки и видео они выкладывают в инстаграм, какие видео на нашем канале набирают больше просмотров, ну в общем после релиза происходит этап валидации успеха и анализ произошедшего. Результаты этого анализа используются при подготовке следующего концерта.

Про market product fit: Market Fit или как найти точку G у стартапа

Growth hacking / Щупаем аудиторию быстро

Я выше говорил, что в нашем цикле HADI нет внешних данных. Как вы сейчас поняли, это немного не так ;) Правильнее говорить, что у нас просто длинный цикл - для проверки гипотезы нам нужен релиз. Многие продакты сейчас, возможно, ударят себя ладонью по лбу, но это та реальность, в которой мы работаем.

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

А на самом деле мы ведь больше для себя это делаем, а не для аудитории. Просто так уж сложилось, что нам с нашей аудиторией по пути. Всем бы продуктам так, да? ;)

Заключение / Почему вам тоже стоит заниматься музыкой

Клавишник группы Sun-Techniki, он же Core Tech Lead.Клавишник группы Sun-Techniki, он же Core Tech Lead.

Может показаться, что всё это очень скучно и очень сложно. Сложно - да, скучно - нет. Я ведь не рассказал про творческую часть, там очень много фана. Само выступление - это чистый фан, чистый адреналин/дофамин/окситоцин/whatever. Иногда ты думаешь - ну ёлки, ну зачем я опять в это ввязался, но эти шестьсот часов подготовки стоят тридцати минут выступления. И тысяча часов тоже были бы адекватной ценой.

Как фанат осознанности, я долго сопротивлялся своему желанию написать эту статью. Я не мог понять, чтобы что я хочу это делать. А душа моя просила поделиться этим всем.

Так вот, я таки понял, чтобы что.

Средство против выгорания

IT - это индустрия высокого стресса. Выгорание - это одно из очень модных слов в последнее время. Также индустрия стареет, то есть и кризис среднего возраста уже тут как тут. От всего этого помогают хобби.

На Хабре про выгорание пишут много, но я бы выделил вот эту статью: Профессиональное выгорание айтишников: 15 ответов психиатра Максима Малявина

Как не выгорать? Это просто (картинка с Тони Роббинсом):

  1. заниматься интересным ненаскучивающим делом

  2. регулярно в этом деле побеждать (получать подкрепление)

  3. работать с удовольствием

Так как крайне сложно найти одно занятие, в котором всё это будет соблюдаться, то очевидный трюк - найти несколько занятий и заниматься ими по очереди. Обязательно нужно, чтобы одно из этих занятий имело проектный характер, и чтобы достижение побед (то есть успешное завершение проекта) было не очень долгим.

Музыка - это хороший вариант такого занятия. То есть музыка - это средство против выгорания. А у айтишников в музыке есть преимущество - мы умеем в процессы, у нас есть дисциплина.

Занимайтесь музыкой, выступайте. Не обязательно выступать на площадках - ютуб также отличное место.

Бонусы

Подробнее..

Тестирование требований как я нахожу ошибки в бизнес-логике фичи прежде, чем их закодят

05.04.2021 08:09:25 | Автор: admin

Привет, Хабр. Меня зовут Ольга, я работаю в тестировании с 2013 года, специализируюсь на тест-анализе и тест-дизайне. Сегодня хочу рассказать, как при планировании тестирования сохранить фокус на пользователях и их потребностях.

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

За время работы я обратила внимание, что аналитики используют в своей работе те же техники, что и тестировщики при тест-анализе, и эти их можно применять как для тестирования требований, так и для составления тестов по задаче.

Под катом покажу, как с помощью одной техники Use Cases найти пробелы в бизнес-логике, протестировать требования и дизайн прежде, чем написан код, и убедиться, что пользователь сможет использовать приложение, даже если что-то пойдет не так.

Статья получилась объемной, так что вот оглавление:

  1. Введение

  2. Зачем и для кого фича?

  3. Какую проблему решает фича?

  4. Как пользователь будет использовать эту фичу?

  5. Варианты использования

  6. Основное направление варианта использования

  7. Альтернативные направления

  8. Исключения

  9. От входных/выходных данных к тест-кейсам

  10. Совет как писать сценарии

  11. Общий алгоритм применения подхода

  12. Профит от подхода для тестировщика

  13. Заключение

Введение

Есть разные команды: в одних командах куча аналитиков пишут требования к софту на сотню страниц, в других есть 1 аналитик на несколько проектов и он пишет, как успеется, в третьих вообще нет аналитика и задачи ставит ПМ, а команда уже на ходу придумывает, что именно реализовать. Причем, может быть непонятно, что нужно сделать по задаче, независимо от того, есть ли аналитик на проекте. И чаще всего так и происходит. То задача идет вразрез с текущим функционалом, то никто не понимает, что там вообще надо сделать, то все всё понимают, но каждый по-своему.

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

Есть разные варианты, что может пойти не так:

  • Ожидания пользователей (пользователи хотят одно, а мы думаем, что они хотят другое; нет важных фичей; фичи есть, но неудобные).

  • Ожидания заказчика (ПМ хочет то, что невозможно/дорого реализовать; или то, что противоречит уже существующей логике).

  • Ожидания бизнеса (бизнес хочет платную фичу, а мы не разобравшись даем ее пользователю бесплатно).

  • Предполагаемые алгоритмы (не делают кое-что важное; не проверяют предусловия; делают вообще не то, что ожидается; от пользователя требуется слишком много лишних действий).

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

Чтобы предоставлять информацию о проблемах своевременно и сократить количество переделок, начинать тестировать нужно как можно раньше.

Другой вопрос: а как тестить до разработки, если по постановке задачи ничего непонятно?

Для этого нам нужно определить:

  • Зачем и для кого фича.

  • Как пользователь/заказчик будет использовать эту фичу.

Это позволит сформулировать задачу понятнее для команды, отловить ошибки в требованиях прежде, чем они будут закодированы и спланировать тестирование.

Зачем и для кого фича?

В первую очередь нужно определить, для кого мы делаем эту фичу, и зачем она заказчику.

Это можно спросить у автора задачи.

Стоит различать пользователя продукта и заказчика

Например, если ваш продукт это софт для частной клиники, то заказчиком тут будет представитель бизнеса, допустим, владелец клиники. А конечные пользователи - это врачи, регистраторы, медсестры и другой персонал клиники, которые используют продукт, чтобы вести записи о здоровье пациентов.

Пользователи продукта тоже могут быть разные. Важно выявить:

  • Какие категории пользователей есть в вашей целевой аудитории (ЦА).

  • Зачем люди из каждой категории используют эту фичу.

  • Какие проблемы они решают с помощью нее.

  • Какие есть варианты использования фичи.

Итак, задача может быть для нужд бизнеса, например, чтобы организовать PR-компанию, или уменьшить затраты на Х, или увеличить доходы с У, или предотвратить/остановить отток пользователей.

Или для определенной категории пользователей нужно реализовать фичу, которую пользователи давно хотят и просят.

Задача может быть для ПМа или владельца продукта, например, чтобы собрать статистику и на основе нее принять решение. При этом важно понимать, что это за решение.

Для команды разработки например, рефакторинг определенной области.

Для саппорта чтобы лучше локализовать проблему или чтобы снизить нагрузку на саппорт.

Для другой команды обычно это интеграции или еще какой-то обмен данными.

Какую проблему решает фича?

С заказчиком разобрались. Дальше нужно понять, какую проблему заказчика решает эта фича и действительно ли проблема будет решена релизом этой фичи.

Можно обдумать это еще и в ключе: как пользователь/заказчик решает эту проблему сейчас?

Например:

  • Делает руками, долго и болезненно. Или наоборот, руками получается быстро и ему ок.

  • Запускает какой-то скрипт.

  • Решает проблему через другое приложение.

  • Никак не делает и страдает.

  • Никак не делает и ему норм.

Ответ на этот вопрос поможет понять: а мы этой фичей точно улучшим пользователю работу или еще хуже сделаем?

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

Если заказчик другая команда и фича про интеграции или обмен данными, то есть риск подумать, что задача простая, т.к. мы просто передаем данные от одного приложения к другому. А приложения бесчувственные, терпимо относятся к огрехам и шероховатостям передачи, так что можно и не стараться.

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

Конфликт интересов

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

В книге Разработка требований к программному обеспечению (Карл Вигерс, Джой Битти) я нашла замечательную таблицу о том, как разрешать конфликты между сторонами при определении требований. Привожу ее здесь:

Разногласия между...

Как разрешать

...отдельными пользователями

Решение принимает сторонник или владелец продукта

...классами пользователей

Предпочтение отдается наиболее важному классу пользователей

...сегментами рынка

Предпочтение отдается сегменту, оказывающему наибольшее влияние на успех бизнеса

...корпоративными клиентами

Решение определяется на основе бизнес-целей

...пользователями и менеджерами

Решение принимает сторонник класса пользователей или владелец продукта

...разработчиками и клиентами

Предпочтение отдается клиентам, но с учетом бизнес-целей

...разработчиками и маркетингом

Предпочтение отдается специалистам по маркетингу

Как пользователь будет использовать эту фичу?

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

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

Если при разработке ориентироваться на пользователя и его работу с продуктом, то этих проблем можно избежать. Для этого удобно использовать технику Варианты Использования (Use Cases).

Варианты использования (Use cases)

Варианты использования это техника, которая применима как к продукту целиком, так и к конкретной фиче. Она позволяет смоделировать, как пользователи используют продукт, и как продукт реагирует на действия пользователя в той или иной ситуации.

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

Полную версию использования техники вы можете посмотреть в книге Разработка требований к программному обеспечению (Карл Вигерс, Джой Битти). В этой статье я покажу упрощенную версию, которую использую в работе.

Возьмем для примера агрегатор доставки заказов из ресторанов и магазинов. В нем можно найти вот такие варианты использования:

  • Заказать еду из ресторана с доставкой.

  • Заказать еду с самовывозом.

  • Заказать доставку продуктов из супермаркета.

  • Найти, в каком ресторане есть желаемое блюдо.

  • Посмотреть стоимость доставки из ресторана Х.

  • Повторить прошлый заказ.

  • Посмотреть, где находится курьер, который доставляет заказ.

Имя варианта использования должно быть понятное (глагол + объект), описывающее, какую именно ценность пользователю дает этот вариант использования, например, информацию о чем-либо (внутри приложения) или еду на обед (в реальном мире, за пределами приложения).

К вариантам использования требуется пошаговое описание того, как пользователь использует продукт и как продукт реагирует на действия пользователя. Так у нас есть как минимум 2 действующих лица: пользователь и продукт (система). Таких участников может быть несколько.

Примеры вопросов, чтобы найти действующих лиц:

  • Кому приходит уведомление о событиях в системе?

  • Кто предоставляет системе информацию или услугу?

  • Кто помогает системе среагировать и выполнить задачу?

Экосистема агрегатора доставки еды предполагает, что есть приложение для того, кто заказывает еду, есть приложение для курьера, и приложение для ресторана.

Т.е. у нас будет как минимум 4 действующих лица:

  • Покупатель

  • Ресторан

  • Курьер

  • Система (т.е. само приложение)

Для разных вариантов использования список действующих лиц может меняться.

Если покупатель выберет в заказе оплату картой, то добавится действующее лицо Банк. Если закажет еду не себе, а бабушке, то появится еще Получатель. А если будет писать в техподдержку, то добавятся Бот и Оператор техподдержки.

Для каждого варианта использования нужно описать еще предусловия, входные и выходные данные, альтернативные сценарии развития и исключения, т.е. когда что-то пошло не так в сценарии.

Основное направление варианта использования

Определим варианты использования основной фичи агрегатора доставки заказа еды из ресторана.

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

Действующие лица:

  • П Покупатель

  • Р Ресторан

  • К Курьер

  • С Система (т.е. само приложение)

  • Б Банк

Предусловия:

  • Пользователь авторизован в приложении

  • Доступен как минимум 1 ресторан

  • Заказ делается в часы работы ресторана

  • У ресторана есть блюда в наличии

Сценарий (основное направление):

П: Добавляет блюда в корзину

С: Проверяет доступность блюд

С: Показывает пользователю сумму заказа в корзине

С: Подсчитывает сумму и прогноз доставки

П: Переходит в Корзину

С: Показывает текущее содержимое заказа

П: Инициирует оформление заказа

С: Предлагает выбрать параметры заказа (адрес, время доставки, вид оплаты)

П: Выбирает оплату картой онлайн и инициирует оплату

Б: Открывает страницу подтверждения оплаты

П: Подтверждает оплату (вводит код из СМС)

Б: Проверяет подтверждение

Б: Передает в Систему данные, что заказ оплачен

С: Присылает покупателю чек об оплате

С: Показывает покупателю, что заказ принят

С: Запрашивает подтверждение заказа у Ресторана

Р: Подтверждает заказ

Р: Начинает готовить заказ (в реальном мире)

С: Находит Курьера и запрашивает у него подтверждение принятия заказа

К: Подтверждает, что принял заказ

К: Идет в ресторан (в реальном мире)

Р: Подтверждает, что заказ готов

К: Подтверждает, что принял заказ в доставку

К: Транспортирует заказ (в приложении видна геометка курьера на карте) (в реальном мире)

П: Получает заказ

К: Подтверждает, что передал заказ покупателю

С: Показывает, что заказ завершен

Альтернативные направления

Дальше нужно составить альтернативные направления развития, т.е. описать, как можно выполнить все то же самое, но немного другим путем.

Можно посмотреть на сценарий целиком и подумать, как можно получить заказ другим способом:

Например:

  • А-1 Зайти в раздел с завершенными заказами и повторить прошлый заказ

А можно смотреть на каждую строку и думать: может ли действующее лицо сделать другой выбор на этом шаге?

Например:

  • А-2 Покупатель оформляет заказ на другого получателя (а не на себя)

  • А-3 Покупатель выбирает оплату наличными (и сценарий минует шаги с онлайн-оплатой)

  • А-4 Покупатель применяет промокод и сумма к оплате пересчитывается

  • А-5 Покупатель выбирает доставку к определенному времени

  • А-6 Курьер сначала принимает заказ, а потом отказывается и заказ берет новый курьер

Нумерация в альтернативах не относится к порядковому номеру шага. А часть альтернатив могут вообще начинаться в другой точке входа, так что цифры можно расставить просто по порядку.

Каждую такую альтернативу можно пошагово расписать, как и основной сценарий. А можно нарисовать блок-схему.

Пример блок-схемы

Исключения

Если на каком-то шаге возникло условие, которое препятствует успешному завершению сценария, то это называется Исключение. Исключения описывают, как поведет себя система в случае ошибки. Для тестировщиков это те самые негативные сценарии. Вообще, техника Use Cases удобнее всего показывает все возможные ошибки, которые могут случиться во время сценария.

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

Например, когда пользователь добавляет блюда в корзину, а система проверяет доступны ли они для заказа, могут произойти такие исключения:

  • И-1.1 Добавляемое блюда закончилось в ресторане и больше недоступно для заказа.

  • И-1.2 У ресторана закончилось время работы.

  • И-1.3 Ресторан прекратил прием заказов и вообще исчез из списка.

  • И-1.4. В корзине лежат блюда другого ресторана (обычно при этом система предлагает убрать блюда другого ресторана из корзины).

На шаге подсчета суммы и прогноза времени доставки может оказаться, что:

  • И2.1 Сумма заказа недостаточна для доставки (возможен только самовывоз).

При оплате онлайн бывает, что страница банка зависает, и невозможно ввести код оплаты.

Вот этот блок в сценарии:

П: Выбирает оплату картой онлайн и инициирует оплату.

Б: Открывает страницу подтверждения оплаты (но страница зависает).

П: Не может ввести код оплаты.

П: Обновляет страницу.

П: Психует и Переходит на предыдущий экран (т.е. обратно в приложение).

Обычно в этот момент система просто отменяет заказ и пользователю нужно пройти весь путь оформления заказа заново.

Так и назовем исключение:

  • И-3.1 Страница подтверждения оплаты зависла.

Еще несколько примеров исключений из этого сценария:

  • И-4.1 Курьер не вышел на связь с рестораном (Система отменила заказ автоматически).

  • И-4.2 Нет доступных курьеров в зоне доставки(Система отменила заказ автоматически).

  • И-5.1 Курьер случайно отменил заказ когда еда уже была у него и отдал заказ бомжу.

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

От входных/выходных данных к тест-кейсам

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

При этом одни и те же параметры на входе в разные сценарии могут иметь разные значения.

Например, при заказе еды в агрегаторе доставки на вход поступают вот такие параметры:

Покупатель:

  • Имя

  • Телефон

  • Адрес

  • Способ оплаты

Заказ:

  • Блюда и их стоимость

  • Количество приборов

  • Прогнозируемое время доставки

  • Время оформления заказа

  • Промокод

Ресторан:

  • Адрес

  • Часы работы

  • Доступные блюда

Курьер:

  • Имя

  • Телефон

  • Местоположение

  • Доступность для заказа

На выходе могут быть такие данные:

  • Доставлен ли заказ

  • Количество доставленных блюд

  • Качество (вкус, температура) доставленных блюд

  • Доставленные приборы (количество, комплектность)

  • Стоимость доставки

  • Стоимость заказа

  • Фактическое время доставки

В случае, если значения в заказе обычные, то на выходе мы получим вовремя доставленную еду. Но некоторые значения параметров могут изменить результат на выходе.

Если Адрес покупателя будет расположен слишком далеко от Адреса ресторана, то доставка будет недоступна вообще, или сумма доставки будет высокой.

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

Но если при этом время оформления и доставки заказа в час-пик, то стоимость будет выше.

Если способ оплаты Наличные курьеру, но по факту покупатель не заплатил курьеру, то заказ не будет доставлен (отменен).

То же самое, если на банковской карте не хватило средств для оплаты заказа, то заказ может быть отменен. Или отложен как не оплаченный и пользователь сможет поменять способ оплаты. Реальный исход зависит от реализации.

Из менее очевидного:

Что если покупатель закажет очень много блюд? В 2-3 раза больше, чем влезет в курьерскую термосумку. Сработает ли ограничение в, допустим, 15кг на 1го курьера? Или системе придется искать 3х курьеров?

Как будет в таком случае спрогнозировано время доставки? Ведь все эти блюда нужно еще успеть приготовить.

Если покупатель закажет доставку из ресторана за минуту до закрытия и ресторан не успеет подтвердить заказ, заказ доставят? Или перенесут на другой день? Или отменят?

Такие вопросы следует уточнять у постановщика задачи, ПМа или аналитиков на вашем проекте и не пытаться угадать/придумать правильную логику самостоятельно.

Получается, что у каждого варианта использования может быть несколько вариантов завершения. При составлении тест-кейсов нужно убедиться, что мы учли все возможные варианты как входных, так и выходных данных.

Пишите в сценариях смысл действия без опоры на внешний вид

При написании сценариев важно опираться на смысл пользовательского действия, а не на интерфейс. Это позволит не переписывать их при каждом редизайне.Т.е. мы можем написать:

  • Покупатель выбирает вид оплаты Картой.

И не стоит писать:

  • Покупатель кликнул на серую кнопку Visa/Mastercard в правом нижнем углу формы.

Кнопка может поменять цвет и перестать быть серой.

В текущей версии приложения это кнопка, а потом ее поменяют на плитку/выпадашку/любой-другой контрол.

В десктопной версии термин кликнуть еще приемлем, а мобильной версии приложения это может быть тап или свайп или другое действие.

Кнопка может поменять название и расположение.

Более того, в мобильной версии приложения кнопка может быть не в правом нижнем углу, а просто внизу или вообще посередине экрана.

Т.е. при описании сценариев желательно не использовать:

  • Цвет

  • Форму

  • Расположение на экране

  • Точное название

  • Вид элемента интерфейса

Общий алгоритм применения подхода

Чтобы составить тест-кейсы по фиче с помощью техники Use Cases нужно сделать следующее:

  1. Определить, зачем и для кого фича:

    • Какие категории пользователей есть в вашей целевой аудитории (ЦА).

    • Зачем люди из каждой категории используют эту фичу.

    • Какие проблемы они решают с помощью нее.

  2. Выписать, какие есть варианты использования фичи.

  3. Для каждого варианта использования нужно определить:

    • Какие действующие лица участвуют в сценарии (включая само приложение, ботов и сторонние системы).

    • Основное направление варианта использования.

    • Альтернативные сценарии.

    • Возможные исключения, когда что-то пошло не так.

В результате мы получаем кучу пользовательских сценариев с предусловиями, шагами и ожидаемым результатом.

Профит от подхода для тестировщика

С помощью всех этих сценариев можно протестировать требования и прототипы интерфейса от дизайнера раньше, чем задача придет к разработчику. А значит можно предотвратить большое количество переделок и недоделок. Мне в работе эта техника позволяет:

  • Найти пробелы в бизнес-логике.

  • Помочь дизайнеру и разработчику разобраться в том, как будет работать фича.

  • Убедиться, что есть обработка всех возможных ошибок.

  • Проверить, что пользователь может пройти сценарий от начала до конца.

  • Выявить все неочевидные предусловия, варианты развития событий, возможные входные/выходные данные.

Заключение

Есть много техник, чтобы тестировать требования, и Use Cases, показанные в этой статье это тоже не панацея от всех бед.

Техника легко ложится на фичи, где есть взаимодействие пользователя с продуктом. И если фича не предусматривает участие человека, но это интеграция 2х или более систем, техника все еще применима. Просто действующие лица будут не Пользователь и Система, а Система 1 и Система 2.

В то же время, подход не применим в задачах, где вообще нет никакого взаимодействия между сторонами.

Но не стоит забывать, что требования можно протестировать с помощью других инструментов, например, используя диаграмму Сущность-Связь (Entity-relationship), анализируя состояния объектов в продукте (State machine diagram) и т.д. Как при работе с требованиями, так и в тестировании все эти инструменты только усиливают друг друга, но это уже тема для отдельной статьи.

Хабравчане, о каких еще техниках по работе с требованиями вам было бы интересно узнать? Пишите в комментариях, поделюсь в следующих статьях.

Подробнее..

Docs as Code введение в предмет

30.04.2021 08:08:53 | Автор: admin

В последние несколько лет в среде технических писателей все больше на слуху концепция Docs as Code. Если вы раньше не сталкивались с этим термином, он обозначает подход к разработке технической документации с использованием тех же инструментов и процессов, что и написание кода. Если DocOps это про процессы и коллаборацию, то Docs as Code про инструментарий, при помощи которого мы несмотря ни на что. Мы выбрали этот подход, когда создавали портал документации Plesk.

В этой статье я кратко расскажу, что такое Docs as Code и зачем оно нужно, а затем дам несколько советов относительно того, как это чудо враждебной техники внедрять, сдобрив всю историю рассказами о тех граблях, на которые мы наступили, топая в светлое будущее. Я старался писать такую статью, которая пригодилась бы мне в 2017 году, когда мы эту кашу заваривали.

(N.B. Сразу оговорюсь, что эта статья - обзорная, в ней нет огрызков конфигов или примеров кода. Если вы уже знаете теорию и ищете, как конкретно пропатчить KDE2 под FreeBSD, статья может быть вам не очень интересна).

Акт 1: Теория

Давным-давно, в далёкой-далёкой галактике

Начнем от противного. Чтобы лучше понять преимущества Docs as Code, посмотрим, как документацию писали (а много где и продолжают писать) мои коллеги в компаниях по всему миру. Как правило, выглядит это так:

  • Документацию пишут и поддерживают технические писатели и только они.

  • Для разработки и публикации используются специализированные проприетарные инструменты, такие как MadCap Flare, Adobe RoboHelp, или Author-it. Реже Wiki или Confluence.

  • Технические писатели работают обособленно. Что происходит у них в отделе, никто в конторе не знает и особо этим не интересуется. Взаимодействие на уровне "разработчик заметил ошибку в примере кода и завел баг в Jira", так как с инструментами технических писателей разработчик не знаком и доступа туда, где хранятся доки, у него нет.

Окей, в чем недостатки status quo? Их несколько:

  • Отсутствие интереса к документации у большинства сотрудников. Хороша документация разрабатываемых продуктов или плоха никто не знает, и никому до этого нет дела. Не мой цирк, не мои обезьяны.

  • Плохая коллаборация. Чтобы исправить опечатку в документации, разработчик или сотрудник поддержки должен написать письмо или завести баг, и станут ли они это делать - бабушка надвое сказала. Это лишний геморрой, а у них и так работы по горло. Процесс совместного ревью также затруднен. Чтобы сделать ревью документа, его нужно выгрузить в гуглдок или файл MS Word, отправить по почте нескольким людям, принять от них комментарии в документах и потом свести их воедино. Ревьюеры не видят комментарии друг друга, делают двойную работу и противоречат друг другу. Это неудобно и техническому писателю, и проверяющему.

  • Отсутствие расширяемости. Проприетарные инструменты могут не иметь тех или иных важных функций (например, не поддерживать версионирование документации) или не удовлетворять каким-то другим параметрам (например, публикация может занимать продолжительное время, даже если вы исправили опечатку в одну букву). В таком случае, шансы что-то исправить минимальны. Если вы обратитесь к производителю, он в лучшем случае предложит кастомную разработку за внушительный ценник, в худшем - просто плечами пожмет. При попытке же перейти на другой инструмент, вы рискуете сполна познать прелести привязки к поставщику. Скорее всего, это будет сложно, дорого, и не застрахует от повторения старых и появления новых проблем.

  • Стоимость. Лицензия на широко используемый продукт MadCap Flare обойдется вам в $149 на человека в месяц. Хотите воспользоваться облачным решением от MadCap? Готовьте $300. Незначительная сумма для большой организации. Большой удар по карману для маленькой фирмы или стартапа, еще не нашедшего стабильный источник финансирования.

Конечно, ни один из этих недостатков не является фатальным. Документация создавалась и еще долгие годы будет создаваться при помощи традиционных подходов и инструментов. Однако, если есть альтернатива, важно знать, в чем она заключается и чем она лучше. Что может нам предложить Docs as Code? Давайте узнаем вместе.

Дивный новый мир

Docs as Code это подход к разработке технической документации, который выглядит следующим образом:

  • Документация пишется не в плейнтексте и не в формате WYSIWYG, а на языке разметки (например, Markdown, reStructuredText, Asciidoc).

  • Документация хранится в репозитории Git.

  • Документация собирается в нужный формат при помощи генератора статических сайтов (Sphinx, Hugo, Jekyll, MkDocs). Форматов может быть сразу много: HTML, PDF, DOCX и так далее.

  • Документация пишется и обновляется коллаборативно.

К чему эти сложности?

Резонный вопрос. Какую головную боль лечит Docs as Code и в чем его преимущества перед классическим подходом? Преимущества есть, и их немало:

  • Docs as Code использует знакомые разработчикам процессы и инструменты, что помогает вовлечь их в процесс создания документации. Это может быть большим подспорьем, если в вашей организации нет выделенного технического писателя и разработкой документации для продукта занимаются сами разработчики. Чудес, правда, ждать не стоит. Для того, чтобы и все заверте, скорее всего, придется терпеливо приучать разработчиков: Василий, смотри, вот ты десять минут заводил баг в Jira, заполнял все необходимые поля и расписывал по шаблону действительность/ожидания только для того, чтобы мы в лоб заменили на по лбу. А что бы было просто не кинуть нам пулл реквест? Быстрее и проще же.

  • Использование репозиториев Git и связанных с ними процессов обеспечивает возможность поддерживать документацию для разных версий продукта, облегчает коллаборацию между сотрудниками, позволяет отслеживать авторов внесенных изменений, и дает возможность быстро откатить эти изменения, если нужно. До начала использования Docs as Code у меня в практике был случай, когда я, неправильно сориентировавшись в обстановке, дал сотруднику задачу, которую тот выполнял полдня. Через пару часов выяснилось, что внесенные изменения нужно откатить, чем я лично и занимался до самого вечера. Сейчас подобный конфуз решился бы за несколько минут.

  • Использование генератора статических сайтов для публикации приносит с собой все связанные с этим преимущества - сайт документации грузится быстро и на нем нечего ломать.

  • В отличие от проприетарных инструментов для разработки документации, функциональность инструментов Docs as Code безгранично расширяема и позволяет создать настолько мощную (или, наоборот, простую и дешевую) систему, насколько нужно именно вашей организации.

  • Значительное (в несколько раз) сокращение временных затрат на рутинные операции. Публикация при помощи проприетарных инструментов запускается вручную и выдает через какое-то время готовый документ в формате .html или .pdf. Разместить его онлайн ваша забота. В результате имеем долгие, многоступенчатые процедуры публикации, требующие ручных действий на каждом из шагов. Публикация же с помощью Docs as Code может быть сведена к выполнению одной команды или даже полностью автоматизирована.

  • Проприетарные инструменты для разработки документации требуют покупки одной или нескольких лицензий (зачастую весьма дорогих). Весь же цикл разработки документации по методологии Docs as Code можно выстроить при помощи свободного программного обеспечения. Это также порадует тех, кто отказывается от использования проприетарного ПО из идейных соображений.

Хотите страшную сказку на ночь? Я расскажу, как было у нас до того, как в Plesk появился Docs as Code. Мы использовали продукт под названием Author-It, и публикация документации с его помощью выглядела так:

  1. Делаешь выгрузку HTML. Это могло занять от пяти минут до часа, в зависимости от размера гайда.

  2. Обрабатываешь полученную россыпь файлов кастомной тулзой, накладывающей стили и брендинг.

  3. Пакуешь все это дело в архив и заливаешь по FTP на сервер.

  4. Запускаешь сборку и ждешь еще полчасика. Молишься, чтобы не упало. Если упадёт, надо перезапускать.

Всё это счастье происходило при каждой публикации. Даже если ты поправил опечатку в одну букву. Это был неописуемо нудный процесс, жравший непристойное количество времени и часто приводивший к ошибкам. Забыл накатить стили перед публикацией? GOTO 20. Забыл накатить стили и уже успел удалить сгенерированные Author-it html-ки? GOTO 10. Теперь же наша документация собирается и публикуется по мерджу пулл реквеста автоматически. Автоматически, Карл! Пока не попробуешь сам, не поймешь, насколько же это круто! А сэкономленное время и внимание можно пустить на решение интересных задач.

Подводные камни

Перечитал предыдущий абзац - звучит, как будто я этим Docs as Code торгую. Что же, у нас на руках идеальное решение? Необязательно. Как и у любого другого подхода, у него есть своя специфика и недостатки:

  • Отсутствие готовой, коробочной версии продукта. Все инструменты, нужные для Docs as Code, доступны, но запускать и настраивать систему вам придется самостоятельно. Будьте готовы к тому, что создание, обслуживание и совершенствование системы публикации документации потребует времени и технической экспертизы.

  • Отсутствие off the shelf решения подразумевает и отсутствие технической поддержки. Если что-то пошло не так, некому завести срочный тикет. Придется разбираться самим при помощи комьюнити.

  • Вашим техническим писателям нужно будет освоить работу с Git хотя бы на базовом уровне (git checkout/pull/commit/push + разрешение конфликтов при слиянии). Поначалу с этим возникнут трудности, и производительность может пострадать.

  • Использовать языки разметки может быть не так удобно людям, привыкшим к WYSIWYG, особенно когда дело доходит до вставки иллюстраций и создания таблиц.

Антракт

Теперь вы знаете, что такое Docs as Code, и дальше рекомендуется читать, только если вам интересно не только что, но и как. Наше путешествие к Docs as Code началось в 2017 году. У нас было много энтузиазма и мало практического опыта, поэтому мы провели в пути дольше, чем планировали, и набили немало шишек. Об этом и пойдет речь дальше.

Но сперва я сделаю еще один реверанс. Прежде чем читать про как, давайте подумаем про зачем. Docs as Code в тренде, но не стоит бросаться внедрять хайповую технологию, не задав себе вопрос чтобы что? В нашем случае ответ выглядел следующим образом:

  • Мы хотели ускорить и упростить процесс публикации - он занимал много времени и требовал ряда ручных действий в независимости от объема внесенных изменений.

  • Нам нужна была поддержка версионирования, а Author-It не мог в него от слова совсем. Author-It позволял хранить и публиковать документацию только для одной версии продукта. Если нужно было внести изменения в документацию для более ранней версии Plesk, приходилось править HTML руками.

  • Мы хотели сделать более удобным процесс ревью. Author-It умел выгружать топики документации в .doc, который потом высылался на ревью ПМу + разработчику + тестировщику. Сводить комментарии и изменения из нескольких вордовых файлов в один было тем еще удовольствием.

  • Также хотелось оставить в прошлом некоторые заскоки Author-It. Например, он позволял молча и без подтверждения выкинуть из структуры гайда топик со всеми его подтопиками. И возможности откатить эту операцию при помощи Ctrl + Z не было. Сами топики при этом не удалялись, страдала только структура, и в теории ее можно было воссоздать руками. На практике было быстрее и проще зайти по RDP на виртуальную машинку, где крутилась серверная часть Author-It, развернуть более старый бэкап базы MSSQL, в которой Author-It хранил всю информацию, выгрузить неповрежденную структуру гайда в XML, снова подключить актуальную базу, удалить гайд, структура которого пострадала, а затем импортировать его из XML. Не шучу, время от времени приходилось заниматься подобным шаманством.

Мы рассматривали различные варианты нового механизма публикации, но все они по тем или иным параметрам не устраивали. Wiki не позволяла сделать версионирование и не имела наглядной структуры и оглавления. Confluence не имел внятной поддержки локализации кроме кошмарного варианта давайте сделаем отдельный спейс для каждой комбинации версия продукта + язык. Смотрели в сторону MadCap Flare, но в итоге отказались, решив, что нет никакой гарантии, что впоследствии не вылезут какие-то проблемы, которые снова заставят переезжать. В итоге выбор пал на Docs as Code как на вариант, обещавший в перспективе удовлетворить всем нашим требованиям.

Акт 2: Практика

Внедряем Docs as Code

Что же, вы решили внедрить в своей организации подход Docs as code. С чего начать?

Сформируйте список требований

Что должна будет уметь ваша новая система разработки документации. Например, нам нужна поддержка версионирования или мы хотим публиковаться в .pdf. Не пожалейте времени и составьте настолько подробный список, насколько сможете. Делать это лучше всего в формате мозгового штурма, в который нужно обязательно вовлечь всю команду технических писателей. Именно они лучше всего знают, какими возможностями обладает их текущий инструментарий, и каких возможностей им недостает. После того, как список сформирован, используйте его как чеклист на этапе проектирования. Прежде чем начинать работу по внедрению, пройдитесь по списку и убедитесь, что в том виде, в котором система спроектирована, она удовлетворяет всем требованиям.

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

Планируйте

Прежде чем начинать работу по внедрению, тщательно спланируйте ваш проект, разберитесь в существующих технологиях и инструментах. Эта грабля нам довольно больно стукнула по лбу. Мы начинали внедрение Docs as code силами отдела технической документации. Когда стало ясно, что нам не хватает где-то ресурсов, а где-то экспертизы, пришлось обратиться за помощью к коллегам. Мы обсудили с ними цели и план работ и пришли к выводу, что некоторые из выбранных инструментов лучше заменить. В итоге часть уже проделанной работы оказалась на свалке.

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

"Да чего тут рассусоливать, всем все понятно, поехали!""Да чего тут рассусоливать, всем все понятно, поехали!"

Пользоваться таким чудом может быть неудобно, а в худшем случае и вовсе невозможно.

Документируйте

Не ленитесь документировать вашу систему Docs as Code. Особенно если вы делаете что-то более сложное, чем один репозиторий Git + генератор статических сайтов в стандартной комплектации. Да, на это всегда не хватает времени, но поверьте, усилия окупятся сторицей. Через пару лет вам не нужно будет морщить лоб, пытаясь разобраться, как же оно тут все устроено. Это что? Как оно работает? Кто писал этот код? Ах, человек уже год как уволился... Чем подробнее вы опишете детали реализации вашего решения, тем проще его потом будет поддерживать и модернизировать. Если вы решили заказать создание системы Docs as Code на стороне, обязательно включите ее документирование в список задач, необходимых для выполнения.

Решите, в каком формате вы хотите публиковать документацию

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

Выберите язык разметки

Зная задачу, проще подобрать инструмент для ее выполнения. Существует целый ряд легковесных языков разметки, но два самых популярных из них - reStructuredText и Markdown:

Markdown

Из двух рассматриваемых языков разметки этот более простой, но и более ограниченный в плане форматов, в которые он может быть сконвертирован без дополнительных приседаний. Существует несколько имплементаций Markdown, ни одна из которых не является канонической. Например, GitHub Flavored Markdown обладает более широкими возможностями по сравнению со своим предком. Выбрав наиболее подходящую для ваших нужд имплементацию Markdown, убедитесь, что используемый вами парсер корректно превращает ее в HTML.

reStructuredText

Более мощный язык разметки, но и более капризный. В нем сложнее писать и проще допустить ошибку в синтаксисе (во всяком случае, пока не привыкнешь). Например, чтобы документ в reStructuredText не собрался корректно, достаточно пропустить или поставить лишний пробел или перенос строки. Большое преимущество reStructuredText в его расширяемости при помощи плагинов вы можете научить систему публикации распознавать и корректно отображать необходимые вам сущности (ссылки, таблички, вставки и так далее) в HTML.

Пример из недавнего нам нужно было добавить возможность вставлять выделенный рамкой текст. Мы используем такое выделение для краткого описания содержания статей документации. Так пользователь может за несколько секунд понять, в нужную ли статью он зашел. Изначально подобного функционала у нас не было. Но за несколько часов у нас появилась возможность добавлять подобные вставки при помощи такого форматирования:

.. admonition:: summary

Hello world!

Собираем HTML и видим вот такое:

Какой язык разметки используется в Plesk? Мы подумали и решили:

Это не шутка мы действительно используем на нашем портале документации и reStructuredText и Markdown. Зачем? Все просто: мы используем разные языки разметки для решения разных задач с разными требованиями:

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

  • Markdown используется для написания release notes. Мы пишем их много и часто, а требования к форматированию минимальны - болд/италик/моноспейс/кодблок/ссылки. Для этой задачи нам важнее всего простота и скорость использования.

Чтобы понять, какой язык разметки лучше подходит для ваших нужд, можно начать с этой статьи в Wikipedia. В ней рассматриваются сравнительные характеристики различных легковесных языков разметки, а также примеры синтаксиса.

Выберите инструмент для публикации

Вы определились с языком разметки. Пора выбрать инструмент, при помощи которого вы будете документацию публиковать. Вариантов несколько, но в этой статье для начинающих я хотел бы сфокусировать внимание на четырех: Hugo, Jekyll, Sphinx и MkDocs. По сути, все они являются генераторами статических сайтов. Hugo и Jekyll больше ориентированы на блоги, а Sphinx и MkDocs специально заточены для создания документации и обладают большим количеством полезных в этом деле фич из коробки. Все четыре инструмента популярны, широко используются, поддерживаются и имеют активное комьюнити.

Если выбор вас пугает, не переживайте. На самом деле, часть опций вы отсекли еще на предыдущих шагах. Генераторы статических сайтов поддерживают, как правило, один-два языка разметки. Если на предыдущем шаге вы выбрали reStructuredText (расширяемость наш выбор, а синтаксис выучим), то ваш главный кандидат Sphinx. И ваш выбор инструментов будет куда шире, если вы проголосовали за Markdown (мы не хотим возиться с reStructuredText и разбираться, почему после трех коммитов, призванных исправить ошибки форматирования, HTML собирается вкривь и вкось).

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

В Plesk для сборки документации мы используем Sphinx, а для сайта портала документации целиком - Jekyll. Это позволяет расцепить механизмы обновления непосредственно руководств и других страниц, размещенных на портале документации, например, чейнджлога или FAQ. Благодаря этому публикация release notes для новых версий продукта и его расширений занимает меньше минуты.

Сделайте красиво

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

Что насчет существующего контента?

Возможно, у вас уже есть сайт с документацией. Что же, при выборе Docs as code вам придется выбросить его или заново набивать руками? Не обязательно. Существуют решения для конвертации текстов из одного формата в другой, но с ними тоже придется разбираться. Как тут поступить зависит от объема существующей документации. Если у вас есть десяток-другой документов, возможно, будет проще, скрепя сердце, набрать их заново в выбранном языке разметки. В Plesk массив документации насчитывал приблизительно четыре с половиной тысячи документов, поэтому для нас подобный вариант не был реалистичным. В итоге мы без потерь сконвертировали всю существующая документацию из .html в .rst при помощи инструмента Pandoc.

Определитесь с версионированием

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

Дешевое решение паковать собранную документацию для старых версий продукта в архивы и делать их доступными для скачивания. Мы так поступаем с документацией для ушедших в EOL много лет назад версий Plesk, которыми уже почти никто не пользуется. Но это неудобно для пользователя. Клиент на старой версии продукта вряд ли сможет найти вашу документацию при помощи Google или другой поисковой системы (для справки: на docs.plesk.com органический поисковый трафик составляет более половины посетителей).

Нам было важно дать клиентам доступ к документации последней и предпоследней версий Plesk (Onyx и Obsidian) и сделать так, чтобы отдельная страница со своим контентом и URL была у обеих версий. Мы реализовали это следующим образом: в каждом репозитории Git, содержащем исходники того или иного руководства, есть несколько веток. Каждая ветка содержит исходные файлы для той или иной версии продукта, что позволяет вносить изменения в документацию, например, для Plesk Obsidian, при этом никак не затрагивая документацию для Plesk Onyx. Есть и недостаток: когда нужно обновить документацию для всех версий продукта сразу, приходится делать коммиты в каждую ветку по очереди, что тоже занимает время.

Ду ю спик инглиш?

Возможно, вам понадобится переводить вашу документацию на иностранные языки для ваших клиентов. Если так, то стоит заранее подумать о том, как вы будете работать с переводами.

Самый простой в реализации вариант создать отдельную ветку или репозиторий, сделать в нем копию исходников на языке, на котором вы пишете, а затем в этой же ветке или репозитории переводить. И так для каждого языка, отличного от исходного. На практике такой подход вряд ли практичен он требует от переводчиков навыков работы с Git и знания синтаксиса .rst. К тому же, если вы планируете работать со сторонними переводчиками, нужно будет внимательно настроить им права доступа, чтобы они не могли видеть, например, исходный код продукта. Вдобавок, это создаст постоянную головную боль процессного плана: обновили документацию нужно дать знать переводчикам, что они должны отразить изменения и в своих исходниках.

Мы пошли более затратным в реализации, но куда более дешевым в использовании путем. Мы разбиваем исходные документы на английском языке на единицы перевода (заголовки, абзацы все, что с обеих сторон ограничено переносом строки). Переводы руководств на все языки хранятся в том же репозитории/ветке, что и само руководство в виде .po файлов. Содержимое их выглядит так:

#: ../../../../projects/administrator-guide/source/53231.rst:15

msgid "You can choose to:"

msgstr "Folgende Optionen stehen zur Verfgung:"

Здесь мы видим перевод единицы перевода из репозитория administrator-guide, документ 53231.rst, строка 15. В наличии как исходная строка, так и ее перевод на немецкий (всего в данном .po файле шесть таких единиц, некоторые поменьше, некоторые побольше). В итоге все содержимое документа на английском покрывается переводом. При сборке документации на немецком механизм берет исходный файл .rst и автоматически заменяет единицы перевода в нем на переведенные. Данный подход позволил нам интегрироваться с сервисом Crowdin, в котором работают наши переводчики. Они пользуются привычным им интерфейсом мы получаем переводы.

Автоматизируй это

Одно из основных преимуществ подхода Docs as code - возможность использовать инструменты непрерывного развертывания, чтобы передать связанные с публикацией рутинные операции на попечение роботов. Не пренебрегайте им. Чем чаще вы вносите изменения или публикуете новые документы, тем больше времени автоматика вам сэкономит. С тех пор, как мы внедрили автоматическую публикацию по слиянию, автоматика экономит нам минимум один-два (а зачастую и больше) человеко-часа каждую неделю, а также исключает подобные драматические сцены:

-Василий, почему релиз ноты еще не на продакшене? Два часа как вышло обновление, клиенты жалуются (у нас были подобные случаи и клиенты действительно жалуются)!

-А, черт, я закоммитил, а запустить сборку забыл :(

В Plesk мы реализовали непрерывное развертывание документации при помощи Jenkins - он уже используется для разработки и публикации самого продукта, и мы решили не изобретать велосипед. Для публикации документации и релиз нот используются разные пайплайны. Схематично выглядит это так:

  1. При слиянии ветки с изменениями в основную, сервер Jenkins запускает сборку гайда, в который были внесены изменения (.rst => .html), на всех языках, на которые он переведен, а также обновляет файлы .po, которые пойдут потом на перевод. Если мы публикуем релиз ноты, этот шаг пропускается.

  2. Пересобирается сам портал документации, включая релиз ноты, FAQ и все прочие находящиеся на нем страницы.

  3. Собранная документация разворачивается на сервере.

  4. Сети доставки содержимого подается команда сбросить кэш.

Здесь есть еще одна тонкость. Кроме Plesk, мы публикуем множество расширений к нему, и каждый новый выпуск каждого из расширений тоже сопровождается своими релиз нотами. Они становятся доступными к сборке документации как только попадают в основную ветвь, поскольку для них время публикации не особо критично. Но для обновлений самого Plesk релиз ноты должны появиться в публичном доступе одновременно с выходом обновления, иначе сразу начинают сыпаться запросы от клиентов ("Мой Plesk автоматически обновился, где я могу прочесть об изменениях?", "Я вижу на портале документации релиз ноты для обновления Plesk, как мне его поставить?"). Во избежание подобных ситуаций, релиз ноты для основного продукта становятся доступными к сборке документации и публикуются строго в рамках публикации обновления Plesk.

Заключение

Нужен ли вам Docs as code? Зависит от. Если у вас небольшая компания, несложный продукт, устоявшиеся процессы и дюжина страниц документации, которые вы обновляете раз в квартал пожалуй, выхлоп не окупит затрат на внедрение. Если же вас заинтересовали описанные в моей статье возможности, или вы просто любите быть на острие прогресса почему нет? Просто заранее вдумчиво спланируйте вашу будущую систему Docs as code исходя из ваших уникальных потребностей, и я уверен вы не пожалеете :)

Спасибо за внимание!

P.S. Хочу также сказать "спасибо" Николаю Волынкину, Дмитрию Ширяеву и Катерине Говердовской за участие в работе по созданию и наполнению нашего портала документации, а также за помощь в написании статьи.

Подробнее..

Оптимизация размера Go-бинарника

11.12.2020 08:05:27 | Автор: admin

image Если вы когда-нибудь писали на Go, то размер получающихся бинарников не мог пройти мимо вашего внимания. Конечно, в век гигабитных линков и терабайтных дисков это не должно быть большой проблемой. Но все-таки встречаются ситуации, когда хочется, чтобы размер бинарника был как можно меньше, и при этом вы не хотите расставаться с Go. О вариантах, как сделать так, чтобы Go-бинарник похудел, пойдет речь ниже.


Цель aka "жертва"


Для начала немного контекста. Есть демон (постоянно запущенный процесс), который выполняет некоторую весьма несложную работу. Близкими аналогиями по манере работы могут быть DigitalOcean Agent или Amazon CloudWatch Agent, которые собирают метрики с машин и засылают их в централизованное хранилище. Наш демон выполняет немного другую задачу, но это не принципиально.


Еще несколько фактов о демоне:


  • Написан на Go (и переписывать на другой язык желания нет);
  • Устанавливается на множество машин;
  • Периодически требует обновления.

На момент начала исследования размер Go-бинарника составлял 11 Мб.


Let Me See You Stripped


Скомпилированный бинарник содержит отладочную информацию. В моей ситуации она не нужна отлаживать на целевых машинах все равно возможности нет ввиду отсутствия доступа. Так что можно смело удалить ее, скомпилировав с указанием нужных флагов или воспользовавшись утилитой strip. Процесс называется стриппингом (stripping) и для любителей Linux должен быть весьма знаком (описание флагов можно поглядеть в выводе go tool link):


go build -ldflags "-s -w" ./...

После этой процедуры размер бинарника составил 8,5 Мб. То есть отладочная информация давала +30% к размеру в данном конкретном случае.


Сжатие


Следующий ход конем это использование компрессии. Можно просто попробовать сделать tar.gz-архив и распространять его. В целом, это рабочее решение. Возможность распаковать архив на целевых системах присутствует.


Другой вариант воспользоваться упаковщиком, который будет делать распаковку и запуск бинарника на лету. Пожалуй, самый известный в этой сфере это UPX. Первое мое знакомство с ним случилось, наверное, больше 20 лет назад, в эпоху dialup-модемов и crack/keygen-поделок. Несмотря на столь солидный возраст, UPX до сих пор находит своих пользователей и продолжает развиваться. Я пропустил момент эволюции, когда upx заработал из коробки для Go, но сегодня никаких дополнительных приседаний не требуется. Судя по истории, случилось это года 4 назад, так что все работает весьма стабильно.


Пробуем упаковать наш бинарник с помощью UPX:


upx agent

На упаковку потребовалось 1,5 секунды, и мы получили бинарник размером в 3,4 Мб! Отличный результат.


Поизучав немного опции упаковщика, можно обнаружить такие варианты, как --brute и --ultra-brute. Попробуем поиграться с первым:


upx --brute agent

Размер полученного бинарника составил 2,6 Мб, что в 4 раза меньше нашего первоначального варианта. Правда, процедура упаковки значительно замедлилась и заняла аж 134 секунды.


Ради любопытства пробуем и --ultra-brute:


upx --ultra-brute agent

Размер бинарника все те же 2,6 Мб (на самом деле, размер уменьшился, но всего на 8 Кб). К времени на упаковку добавилось еще 11 секунд, и суммарное время составило составило 145 секунд.


Мысль о том, что по скорости хочется как в первом варианте, а по размеру как во втором и третьем, не давала покоя и привела к следующей команде:


upx --best --lzma agent

В результате мы имеем все те же 2,6 Мб по размеру, но времени требуется всего лишь 4 секунды.


image

Тяжелые зависимости


Легкость добавления внешних зависимостей может иметь свои негативные последствия. Например, довольно просто добавить какой-то очень нужный модуль, который увеличит размер бинарника несоизмеримо приносимой пользы.


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


В моем случае к ожирению привела интеграция с Sentry. Если никогда не сталкивались с Sentry, то в двух словах, это сервис, собирающий информацию об ошибках, которые происходят в приложении. Такие штуки прикручивают в первую очередь для повышения качества и поиска проблем, возникающих в промышленной эксплуатации сервиса или продукта. Возвращаясь к проблеме ожирения, смотрим, что нам дает вариант без интеграции с Sentry. Упражнения опять начинаем с 11 Мб бинарника. Без стрипания после убирания интеграции размер составил 7,8 Мб, а после стрипания размер стал и вовсе 6,2 Мб. Почти в 2 раза меньше изначального!


Конечно, трекинг ошибок может хотеться сохранить. Но, в данном случае, мне дешевле организовать промежуточный сервис, куда отправлять сообщения об ошибках хоть по HTTP, а оттуда уже перенаправлять их в Sentry.


Еще раз про сжатие


После того, как разобрались с зависимостями пробуем еще раз воспользоваться upx:


upx --best --lzma agent

Результирующий размер бинарника: 1,9 Мб! Напомню, что путь начался с 11 Мб.


image

Платой за компактный размер будет время на запуск, так как предварительно требуется распаковка. Грубый замер с помощью утилиты time в моем случае показывал увеличение на 170-180 миллисекунд. В контексте демона, где время работы несоизмеримо больше накладных расходов на запуск, это совершенно не является проблемой. Но иметь ввиду этот аспект нужно.


Другие варианты


Куда идти, если хочется большего?


Один из вариантов по решению проблемы доставки обновлений минимального размера это бинарные патчи. Например, распространение обновлений Google Chrome использует эту концепцию. Есть утилиты bsdiff/bspatch, которые позволяют легко организовать такой процесс. В моем случае, утилита bspatch на целевых машинах отсутствует, поэтому пока для себя посчитал эти упражнения нецелесообразными. Хотя предварительные эксперименты показали весьма хорошие результаты в плане небольшого размера патчей.


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


Еще один любопытный вариант это gccgo. Если целевые машины более-менее однообразны, то можно воспользоваться этим способом и получить Go-бинарник с динамической линковкой. Размер бинарника сильно порадует.


Это не мой случай (ОСи самые разные), но эксперимент я тоже попробовал провести:


go build -compiler gccgo -gccgoflags "-s -w" ./...

Условия не совсем равные (это другая виртуалка и другая ОСь), но уже на старте мы получаем бинарник размером 1,8 Мб. Правда, с динамической линковкой. Применяем upx и получаем всего 284 Кб! Главное, при переносе в другое окружение не удивляться потом ошибкам следующего характера:


./agent: error while loading shared libraries: libgo.so.16: cannot open shared object file: No such file or directory

В копилку экзотических компиляторов можно добавить TinyGo. Данный проект у меня им собрать не получилось рассыпается с рядом ошибок на этапе компиляции. Но, в целом, успешные попытки уже были в контексте другого проекта (небольшого, но все-таки не Hello, World!). Бинарник будет с динамической линковкой, но количество зависимостей меньше, чем в варианте с gccgo (а значит, чуть меньше и проблем с портируемостью).


При наличии достаточного объема кода, зависящего от платформы, могут пригодиться build tags. Правила могут быть более хитрыми, чем просто именование файлов с суффиксами _windows.go или _linux.go. Размер экономии сильно зависит от конкретной ситуации. В моем случае экономии практически нет, так как основная целевая платформа это Linux x86_64, а поддержка Mac и ARM лишь эксперименты.


Docker


Нередко можно встретить, что Go-бинарник распространяется в виде Docker-контейнера. Например, для полной изоляции демона от хостовой системы и проброса только нужных файлов или директорий. В моей ситуации есть соседний демон, который распространяется именно так и используется на двух машинах. В этом случае более важны усилия по оптимизации размера не самого бинарника, а размера Docker-образа. Оптимальный по размеру Docker-образ создается с помощью довольно стандартного трюка с двухфазной сборкой:


FROM golang:1.15 as builderARG CGO_ENABLED=0WORKDIR /appRUN apt-get update && apt-get install -y upxCOPY go.mod go.sum ./RUN go mod downloadCOPY . .RUN make releaseFROM scratchCOPY --from=builder /app/server /serverENTRYPOINT ["/server"]

Каждая фаза начинается с директивы FROM. На первой фазе присутствуют все зависимости, необходимые для сборки, и формируется бинарник. А далее, с директивы FROM scratch, по сути с нуля формируется новый образ, куда копируется полученный ранее бинарник и определяется команда запуска.


Под make release скрываются вызовы go build и upx. Результирующий же размер образа составил всего 1,5 Мб (размер немного отличается в меньшую сторону, так как речь идет о похожем, но немного другом демоне). Если собирать все в одну фазу используя golang-образ в качестве базового, то результат будет 902 Мб.


Выводы


Итак, мы прошли путь с 11 Мб до 1,9 Мб, то есть сократили размер Go-бинарника практически в 6 раз! Стрипание бинарника с последующей упаковкой его с помощью upx очень эффективная мера по сокращению размера. Не стоит пренебрегать и убиранием лишних зависимостей. В моем случае, это приводило к очень заметному сокращению. Если нет особой вариативности в средах для запуска бинарника, то можно присмотреться к варианту с gccgo.

Подробнее..

Как я перестал превращать собес в экзамен оцениваем хард- и софт-скиллы за одно собеседование

19.04.2021 06:22:01 | Автор: admin

На волне последних обсуждений темы собеседований, хочу задать аудитории Хабра вопрос: вы помните, как писали в резюме: "коммуникабельный, инициативный, быстро обучаюсь"?

Я помню, и помню, что страшно гордился тем, как я хорош. Помню, как я читал эти слова в резюме кандидата, когда первый раз в жизни оказался в роли нанимающего менеджера. Много думал, после чего уже не так собой гордился.

Итак, меня зовут Алексей, я QA Lead одной из команд в Plesk. Хочу поговорить о том, как увеличить пользу от технического собеседования, или что означают софт скиллы, и как они проявляют себя в реальной жизни.

Добро пожаловать под кат.

  1. Про типовой технический собес

  2. А какие есть скрытые резервы в техническом собесе?

  3. А вдруг можно ещё лучше?

  4. Модель STAR(AR)

  5. Что все это дает нам на практике?

Про типовой технический собес

Давайте начнем с того, для чего вообще нужно техническое собеседование.

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

Наверняка, каждый хоть раз попадал в подобную ситуацию. Экзамен казался приемлемым в годы учебы, но во взрослой жизни это уже не выглядит, как что-то нормальное. А ведь ожидается, что люди, сидящие по разные стороны стола на собесе, должны будут каким-то образом потом вместе работать.

Но есть в этом и что-то хорошее для кандидата: если на собеседовании ты встречаешь въедливого и придирчивого садиста-экзаменатора, который в перспективе должен стать твоим руководителем, принять решение не в пользу этой компании очень легко.

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

С одной стороны, вы скорее всего увидите агрессивного и необщительного человека с нервным тиком; с другой стороны, вас будут считать садистом-маньяком с манией величия. Психотерапевты, прием которых включен в программу медицинского страхования, на этом моменте радостно потирают руки.

Типичное собеседование в компанию "Х"Типичное собеседование в компанию "Х"

Допустим, каким-то чудом вы смогли договориться и найти того самого, кто пойдет дальше технического собеседования на HR интервью. Не знаю точно, что там происходит, но вердикт HR-а для неподготовленного человека выглядит, как краткое описание тяговой лошади:

  • в меру весел,

  • морально неустойчив,

  • есть задел на лидерские качества,

  • при должном стимулировании обучаем,

  • зубы целые,

  • взгляд загадочен.

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

Думаю, основную идею вы уловили собеседование в виде экзамена не помогает ни компании, ни кандидату.

А какие есть скрытые резервы в техническом собесе?

Допустим, вы ищете инженера с опытом администрирования Linux, и вам будет достаточно следующих умений:

  • работать в консоли (команды навигации, работа с файлами);

  • уметь обращаться с логами;

  • менять настройки стандартных системных сервисов.

Теперь представим, что к вам на собеседование пришел кандидат, который утверждает, что все это умеет. Естественно, вы хотите это проверить и задаете вопросы, начиная с самых базовых. Какие это могут быть вопросы?

  1. Про стандартные консольные команды навигации и работы с файлами (cd, mkdir, cp, mv . плюс дежурная шутка про то, как выйти из vi);

  2. Про то, где находятся логи разных сервисов (syslog, error_log/error.log .);

  3. Про то, где находятся файлы конфигураций разных сервисов (httpd.conf/apache2.conf, php.ini, my.cnf и т.д.).

Таким образом, мы узнаем, что у кандидата есть, как минимум, теоретические знания по каждому пункту. В то же время, не факт, что знания подкреплены практикой, и он умеет ими пользоваться в реальных задачах. В каких-то случаях этого будет достаточно, но чаще мы ожидаем от кандидата знаний, подкрепленных практическим опытом.

Для связи теории и практики можно пойти другим, более прикладным путем. Попробуем дать задачку, решение которой так или иначе продемонстрирует нужные знания:

Пользователи вашего проекта на PHP жалуются, что не могут загрузить файлик размера больше двух мегабайт. Расскажите пошагово, как будете исследовать проблему и чинить её?

В ответ есть вероятность услышать что-то вроде:

Включу нужные опции в секции Error handling and logging файла конфига php.ini, там же посмотрю опцию error_log, чтобы найти, где хранятся логи.

В логе найду ошибку о том, что The uploaded file exceeds the upload_max_filesize directive in php.ini, после чего поправлю соответствующую опцию в php.ini, задав нужный разумный предел.

Таким образом, кандидат продемонстрировал, что кроме знания отдельных вопросов, умеет решать и более комплексные задачи.

Казалось бы, это то, что надо! Но

А вдруг можно ещё лучше?

Давайте зададим кандидату вопрос в следующем ключе:

Расскажите о ситуации из вашего опыта, когда вам понадобилось исследовать проблему и удалось исправить её, поменяв настройки системных сервисов.

Что это была за ситуация? Как сформулировали задачу? Как вы действовали и какой результат получили?

Пофантазируем, какой рассказ мы могли бы получить в ответ.

Проблема: Из отдела маркетинга пожаловались, что они не могут разместить на корпоративном сайте pdf с бренд-буком через стандартную форму загрузки файлов. Из-за этого приходится разбивать pdf на отдельные картинки и загружать их по одной.

Задача: Понять причину проблемы с загрузкой файлов в формате pdf, предложить способ её решения.

Решение: Путем курения логов наш кандидат выяснил, что виноват не формат файла, а его размер. Поразбирался в настройках php.ini и пришел к решению установить директивы upload_max_filesize = 20M и post_max_size = 20M. Это решило проблему. Поправленные настройки кандидат добавил в инструкции по деплою и настройке продакшн сервера.

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

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

Это ли не чудо?

В то же время, кто-то может справедливо заметить, что без спроса менять что-то на продакшн сервере это сомнительная инициатива. В некоторых ситуациях это даже может быть засчитано за безответственность.

Таким образом, помимо подтверждения технических навыков, мы коснулись и софт скиллов кандидата. Тот самый фидбек от HRов отзывчив, инициативен, проактивен обретает смысл и вполне реальные очертания. Становится намного проще ответить на вопрос:

Хотите ли вы, чтобы человек с таким набором знаний, умений и качеств работал с вами в команде?

А теперь давайте разберем, как мы это добились.

Модель STAR(AR)

Напомню, вопрос кандидату звучал как:

Расскажите о ситуации из вашего опыта, когда вам понадобилось исследовать проблему и удалось исправить её, поменяв настройки системных сервисов.

Что это была за ситуация? Как сформулировали задачу? Как вы действовали и какой результат получили?

Для вопроса мы использовали модель STAR(AR). Эта модель состоит из четырех (либо пяти) важных составляющих:

  • Situation (ситуация).

  • Task (задача).

  • Actions (действия).

  • Results (результаты).

  • Alternative Results (альтернативные результаты).

Схема позволяет как задать четкий вопрос, так и предлагает структуру, которая помогает кандидату дать ответ по существу.

Но и это ещё не все! Незаметные глазу нюансы вопрос, обращенный к реальному опыту с большей вероятностью покажет, как кандидат привык действовать в реальной жизни. А это как раз то, с чем вы столкнетесь, когда (и если) он перейдет из категории кандидат в категорию коллега.

Дополнительный приятный бонус скрывается в пункте Alternative Results. Вопрос как бы вы поступили в такой же ситуации сейчас? может показать, чему кандидат научился с тех пор, как рассказанная ситуация случилась в его жизни. А это уже намекнет вам на способность переосмысливать свой опыт, учиться и делать выводы, даже если изначальное решение было неоптимальным, а то и вовсе неправильным.

Давайте представим, как наш кандидат мог бы ответить на этот вопрос, пусть это будет:

Сейчас я бы установил директиву post_max_size = 60M, т.к. сама форма загрузки позволяла загружать до 3 файлов одновременно.

Готово, вы восхитительны! Похоже, что наш кандидат нам подходит.

Что все это дает нам на практике?

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

Даже если кандидат в своем ответе не покажет паттерн в явном виде, из ответа вы получаете больше контекста об опыте кандидата. А это позволяет задать нужные вам уточняющие вопросы.

Бонусный уровень

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

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

А как вы оцениваете софт скиллы? Какие техники или методы используете для этого?

Подробнее..

Хостинг статических сайтов на AWS

05.11.2020 08:17:48 | Автор: admin
В данной статье я хочу подробно разобрать тему хостинга статических сайтов на AWS. Тему нельзя назвать сильно сложной, но нюансов хватает. Для настройки вручную потребуется организовать взаимодействие 4-5 сервисов, а по дороге порой можно встретить весьма интересные грабли.

Некоторое время назад существовал официальный туториал по такой ручной настройке. Местами он мог показаться сложным, местами странным. Скорее всего, это была дань универсальности и необходимости продемонстрировать разные варианты хостинга. Однако сейчас туториал кардинально обновлен, и предлагает использовать сервис AWS Amplify для решения такой задачи. С одной стороны, это удобно, но с другой стороны, иногда необходимо разобраться, что же именно происходит под капотом. Поэтому здесь мы разберем, как все настроить руками.

Статические сайты


Для начала, в двух словах а почему статический сайт? Как ни странно, мода на статические сайты, вернувшаяся лет 8-10 назад, до сих пор не проходит. И речь не только об огромном количестве сайтов на GitHub Pages. Генераторы статических сайтов такие как Jekyll, Hugo или хипстерский Gatsby продолжают выпускать регулярно новые релизы и остаются более чем востребованными.

Проверка временем давно пройдена. Но чем же это круто? Когда у вас статический веб-сайт, на нем практически нечего ломать. Нет форм логина, админки, динамических скриптов, которые можно обмануть. Статический сайт это очень быстро. Вам не нужно грузить CPU обработкой тяжелого запроса. Содержимое можно кэшировать, начиная от CDNа и заканчивая браузером пользователя.

Хостинг сайта или почему AWS


На статическом сайте практически нечего ломать. Если нельзя ломать сайт, можно ломать, например, хостинг. Вы купили виртуальную машинку в DigitalOcean, поставили туда nginx и залили сайт. Но nginx и другие пакеты тоже надо периодически обновлять. Поэтому логичным выбором в пользу уменьшения забот (ака maintenance) является использование облаков, например, AWS. ОСь и веб-сервер никуда не денутся, но их обновление и защита перестанут быть вашей задачей.

Для примера я взял сайт, который мы (Plesk) используем в качестве промо наших open source проектов на GitHub.


Сайт статический. Состоит, по сути, из одной странички index.html, нескольких картинок, кастомного шрифта, css-стилей и некоторого количества JavaScriptа.

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


AWS S3


Для хостинга сайта мы воспользуемся сервисом AWS S3. Первое, что нам потребуется, это создать S3 bucket. По сути, это именованное место для хранения файлов. Имя должно быть глобально уникально. Сайт я планирую разместить по адресу tech.plesk.space, поэтому в качестве имени bucketа выбрал tech-plesk-space (можно было и с точками). Регион пусть будет Франкфурт, eu-central-1. Во Франкфурте расположена самая крупная в Европе точка обмена трафиком. В нашем случае я не планирую раздавать контент напрямую с S3, мы это сделаем с помощью CloudFront, поэтому выбор региона не сильно принципиален. Но, в целом, с точки зрения latency и connectivity для потребителей из Европы, Франкфурт это очень хорошая локация. Из скриншота ниже можно заметить, что выставлена галочка Block all public access. Все верно, раздавать контент мы будем не напрямую с S3, а через сервис CloudFront, который представляет собой Content Delivery Network от Amazon.


После создания bucket пуст, и нам нужно залить туда файлы, которые мы планируем раздавать. Можно сделать это через веб-интерфейс, но я воспользуюсь AWS CLI. Сделать это можно с помощью следующей команды из директории, где локально расположены файлы сайта:

aws s3 sync --delete . s3://tech-plesk-space

Что здесь происходит? Мы выполняем синхронизацию локальных файлов с S3 bucket с названием tech-plesk-space. Опция delete позволяет удалить файлы в bucket, если они отсутствуют локально.

Проверяем через веб-интерфейс файлы доступны:


Если бы мы не ограничили публичный доступ, то файлы можно было бы посмотреть через технический домен. Amazon для удобства создал нам tech-plesk-space.s3.eu-central-1.amazonaws.com. Как видно, доменное имя состоит из названия bucket, названия сервиса S3, региона eu-central-1 и суффикса для технических доменов: amazonaws.com.

Route 53


Прежде чем настраивать публичный доступ к сайту, давайте разберемся с доменным именем. В качестве такового я выбрал tech.plesk.space.

Отправляемся в консоль Amazon, открываем сервис Route 53 и создаем новую публичную зону.


После создания зоны мы получаем информацию об NS-записях. Это DNS-серверы, которые будут хранить информацию о нашей зоне. Если вы раньше работали с какими-нибудь небольшими провайдерами, то выглядело это примерно так: есть ns1, ns2, и на них хостятся все домены. В случае с AWS сказать какие DNS-серверы будут обслуживать зону заранее нельзя.

Итак, у нас есть список NS-записей, что с ним делать? Если вы купили домен, то далее идете в панель управления доменом и прописываете полученные записи. Вот так это выглядит, например, у GoDaddy:


В нашем случае домен tech.plesk.space является поддоменом plesk.space, а эта зона хостится в Digital Ocean DNS аккаунте. Для того, чтобы правильно выполнить делегирование, нам нужно прописать соответствующие glue records.


Проверяем с помощью digа:


Одних NS-записей для обслуживания сайта не достаточно. Нужна еще A-запись. Мы вернемся к этой теме немного позже, когда доберемся до CloudFront, но перед этим нам нужно сделать еще одно действие.

ACM


Современные тенденции говорят, что сайт должен быть доступен по HTTPS, и на нем должен присутствовать валидный сертификат. В AWS есть сервис по управлению сертификатами и называется он AWS Certificate Manager (или сокращенно ACM). Отправляемся туда для создания сертификата. Это абсолютно бесплатно, но секретную часть сертификата (ключ) вам не дадут. Так что этими сертификатами можно воспользоваться только внутри инфраструктуры Amazon.

Еще один любопытный момент: для нужд CloudFront сертификат нужно создавать в зоне us-east-1 (N. Virginia), иначе вы не сможете им воспользоваться в рамках CloudFront. Что ж, переключаем регион на us-east-1 и идем создавать сертификат. В качестве способа валидации выбираем DNS-валидацию. Так как зону мы разместили в Route53, есть удобная кнопочка создания валидационной записи:


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

Сертификат выдается сроком на 1 год и для его обновления дополнительно делать ничего не нужно.

CloudFront


Осталось буквально последнее действие настроить CloudFront, чтобы наш сайт стал доступным для пользователей.

Для этого отправляемся в интерфейс CloudFront и создаем новую сущность под названием Distribution. Выбираем в Origin Domain Name tech-plesk-space.s3.amazonaws.com. То есть S3 у нас будет выступать originом, а раздачу контента будет выполнять CloudFront. Кто не знаком с идеологией CDN, origin это хранилище оригинальных файлов, а edges это серверы, которые кэшируют данные originа и непосредственно раздают контент клиентам. Также для красоты можно еще изменить настройку Viewer Redirect Policy и выставить ее в положение Redirect HTTP to HTTPS.


В качестве Alternate Domain Names (CNAMEs) указываем tech.plesk.space. Не забываем и про SSL Certificate: там выбираем Custom SSL Certificate и из выпадашки (которая совершенно не выглядит выпадашкой) выбираем нужный нам сертификат.


Еще одна вещь, которую стоит сделать, это задать Default Root Object. Здесь мы укажем index.html. Без этого действия при обращении к сайту без указания файла (то есть написав в браузере просто https://tech.plesk.space/) мы получим 403 ошибку. В контексте веб-серверов такая настройка обычно называется Directory Index.


Жмем кнопку Создать и набираемся терпения. Процесс может занять минут 10.

После того, как Distribution был создан, нужно немного поправить доступ к origin. Для этого отправляемся на редактирование в соответствующую вкладку. Далее выбираем, что мы хотим ограничить доступ, настройка Restrict Bucket Access; хотим создать новую Access Identity и разрешаем обновить bucket policy. Выглядеть это должно, примерно, так:


Зачем было нужно действие выше? Вспоминаем, что при настройки S3 мы оставили опцию блокировать весь доступ по-умолчанию. Таким образом, CloudFront не получил бы возможность читать контент из bucketа.

Остается последний штрих: указать в Route53, что именно будет служить у нас A-записями для домена tech.plesk.space. Для этого идем в интерфейс Route53, выбираем Create New Record Set, выбираем тип A-запись, но вместо самой записи выбираем, что у нас Alias, а из выпадающего списка выбираем соответствующий CloudFront distribution. Выглядеть это должно, примерно, так:


Открываем браузер, вводим https://tech.plesk.space/ и видим наш сайт:


Для интереса смотрим A-записи:

Проверяем с помощью curl, что нас действительно обслуживает CloudFront:

Как видно из последних 5 заголовков, это действительно так.

На этом, в общем-то, и всё. Сайт запущен, работает и доступен клиентам.

Прочие моменты


Я не затрагивал тему логирования запросов. По-умолчанию оно выключено, но его можно настроить. Логи будут складываться в S3 bucket. Нужно учитывать специфику подхода к CDN (тут Amazon совершенно не уникален) о том, что такое логирование это не инструмент real time отладки. Логи доставляются с приличными задержками, а документация говорит, что такие задержки могут быть до 24 часов. Из практики могу сказать, что подключение Google Analytics почти всегда снимало вопросы про логирование для таких статических сайтов.

Еще один момент, который хотел кратко упомянуть, это цена. В случае free tier и небольшой нагрузки стоимость будет около 50 центов, и то только на Route53. Без free tier получалось где-то 1-2 доллара в месяц. В целом, наверное, может показаться, что это даже дорого для хостинга статического сайта, но, на самом деле, в случае с AWS, у нас огромный потенциал для развития проекта (масштабируемость, оплата по мере роста, глобальная доступность, огромное количество других удобных сервисов и многое-многое другое).

Заключение


Как я уже упоминал в начале, официальный туториал от Amazon теперь советует использовать сервис AWS Amplify. Он действительно удобней: тут и подключение Git-репозитория, и полуавтоматическая настройка ряда вышеописанных вещей. Но, порой, нужно разобраться с уже настроенной инфраструктурой или организовать некоторые вариации хостинга, из-за чего уже придется разбираться со всеми нюансами.

Еще один интересный взгляд на данную проблему это сервисы типа Netlify. Они еще сильнее упрощают некоторые вещи (правда, бывает и усложняют), но, конечно, и их использование будет стоить дополнительных денег.

Надеюсь, статья поможет сберечь время при настройке хостинга статического сайта в AWS.
Подробнее..

Выбор оптимальной платформы для веб приложения

29.03.2021 10:21:19 | Автор: admin

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

Проблемы внедрения

Как уже упоминалось выше, запустить веб-приложение можно на разных платформах. Можно на собственных серверах компании, можно использовать Shared Hosting провайдеров, можно приобрести VPS/VDS хостинг, например, у DigitalOcean, а можно для размещения вашего веб-приложения использовать облачную инфраструктуру от интернет гигантов -Amazon Web Services (AWS), Google Cloud, Microsoft Azure и так далее. Существуют также и специально ориентированные на хостинг веб-приложений решения вроде Pantheon или WP Engine.

Множество возможных решений вызывает головную боль у новичка. Что выбрать? Что дешевле? Что надежнее? Где лучше техподдержка? Где больше возможностей и где лучше перспектива роста? Давайте рассмотрим плюсы и минусы каждого из вариантов.

Dedicated server

Конечно, полная свобода действий при использовании собственного сервера подкупает. При единоличном использовании вы получаетеполное управление конфигурацией вашего сервера, root доступ и возможность самостоятельно обеспечить самый высокий уровень безопасности системы. Но за такую свободу нужно платить, и высокая стоимость выделенного сервера главный недостаток этого решения.Необходимость оплачивать амортизацию оборудования, серверного помещения и работу высококвалифицированных администраторов сводит на нет все несомненные преимущества такого решения для хостинга ваших веб-приложений. Кроме того нужно понимать, что под высокой стоимостью подразумеваются и затраты на поиск, найм и управление высококвалифицированным персоналом, а, например, для оборудования нужно составлять и придерживаться строгого плана замены комплектующих. Новичкам этот вариант точно не подходиттак как требует квалифицированной работы со многими техническими аспектами. Иногда для работы с выделенным сервером требуется целая команда. Но есть вариант использовать collocation - арендовать сервер из оборудования вашего сервис провайдера в его же датацентре и это может ощутимо снизить ваши затраты.

Shared Hosting

Если вы решили использовать Shared Hosting, то со стоимостью необходимых затрат наоборот, все хорошо. Это, пожалуй, самое дешевое решение. К тому же часто дополнительно вы получаете бесплатные доменные имена. Ваш сервер настроен и в общем-то не требует специальных технических знаний для использования. Все обслуживается и администрируется службой поддержки сервис провайдера. Но при этом вы крайне ограничены в добавлении и конфигурировании дополнительных возможностей для вашего проекта. Более того, производительность и стабильность вашего веб-приложения может серьезно пострадать из за внезапных и значительных потоков трафика ипотребления ресурсов сервера соседними сайтами и веб-приложениями. А таких прожорливых соседей у вас может быть несколько сотен! Оперативности технической поддержки при таком количестве клиентов скорее всего не следует ожидать. Кроме того, остро стоит вопрос безопасности shared hosting-а, ведь если хотя бы один из сайтов или веб-приложений будет взломан злоумышленниками, скорее всего они сумеют получить доступ и к ресурсам других проектов на этом сервере. По этим и другим причинам рынок shared hosting стагнирует в последние годы.

VPS Hosting

Одно из самых популярных решений. У многих на слуху компания DigitalOcean со своими популярными предложениями. Виртуальные приватные сервера дороже, чем Shared Hosting, на за эту разницу в цене вы получаете выделенные только для вас ресурсы на сервере, соседи по серверу не влияют на производительность вашего веб-приложения, конфигурируемость очень высокая поскольку вы имеете полный root доступ к вашей системе и тем самым имеете полное право навыполнение всех без исключения операций. Удобно вертикально масштабировать ваш VPS вручную и с даунтаймом. Достаточно остановить VPS, добавить ресурсов и снова запустить. С физическим сервером такое не пройдет. Но опять же, помимо достаточно ощутимой цены,тут требуется высокая квалификация и серьезные технические знания по управлению серверами. По сути, нужны специалисты такого же уровня, как и для управления физическими серверами, разница только в том, что нет проблем с hardware (не нужен план замен, закупок, монтажа и тому подобное), но инфраструктурно всё то же самое. Поэтому и для VPS hosting нужны высококвалифицированные администраторы.Чтобы сконфигурировать рабочее окружение для вашего веб-приложения и поддерживать его, вам потребуется немало времени.

Managed Hosting

Вариант хостинга, когда для вас запускают конкретное веб приложение, дают вам административный доступ в него, но непосредственное управление сервером осуществляется не вами. Таким образом, вы ограничены только вашим приложением. Управлять вы можете только тем, что оно позволяет делать в своих рамках. А поскольку таких как вы много на физическом сервере, то возникают все те же проблемы, которые характерны для Shared hosting -нестабильность объёма фактически доступных ресурсов, медленный ответ техподдержки и так далее.

Clouds

Давайте тут остановимся подробнее. Динамика роста популярности облачных решений в последние годы впечатляет. Аналитическая компания Gartner оценила объем мирового рынка публичных облачных сервисов в $242,7 млрд по итогам 2019 года. В 2021 году глобальный рынок внедрения облачных технологий превысит в общей сложности $306 млрд по данным той жеGartner. Решения на базе облачных технологий выбирают для себя компании и организации независимо от своего размера. Каждый находит в них для себя что-то свое, но общие преимущества облачных решений очевидны:

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

  • Капитальные расходы заменяются на операционные, поскольку вместо крупных авансовых платежей на приобретение и установку оборудования и ПО, вы осуществляете регулярные равномерные платежи за доступ своих сотрудников к нужным им ресурсам, причем только по факту их потребления.

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

  • Исчезает необходимость в собственном штате системных администраторов для обслуживания серверного оборудования.

  • Нет больше необходимости заботиться о регулярных обновлениях используемых систем - облачный провайдер делает это за вас и как правило, совершенно незаметно для пользователей.

Но при всех преимуществах облачных технологий, в процессе их внедрения в работу компании, неизменно возникает проблема высокого порога вхождения. Она заключается в сложности выбора облачной архитектуры. Например, непросто выбрать подходящий для вашего проекта AWS stack, который обеспечивал бы все потребности и его стоимость не выходила бы за рамки бюджета. Вообще, если мы говорить об AWS, то его можно представить себе в виде некого конструктора, изкоторого вы можете сделать много разного - главное уметь это делать. Организацию хостинга веб-приложения с помощью AWS порой сравнивают со сборкой компьютера (по сравнению с покупкой готового - заказа хостинга у провайдера):EC2-это материнская плата и память. Онпозволяет запускать instance на базе образа операционной системы.EBS-это как диск. Вы можете сказать: сделай мне диск размером в 45 гигабайт и подключи его к такому-то instance (созданный "диск" будет называться volume). В результате в вашей системе появляется новое устройство, которое вы можете монтировать, форматировать и работать с ним. Все, что было записано на него, сохраняется независимо от жизни instance.S3-это как внешнее хранилище. Туда можно сохранять большие файлы и хранить их там вечно. А есть еще сервисы для логирования, мониторинга, баз данных, DNS и множество других. Как собрать из этого набора комплектующих именно тот "компьютер", или AWS stack, который обеспечит оптимальную работу вашего приложения и при этом не переплатить?Новичку в облачных технологиях непонятно, какую конкретно схему AWS stack использовать, какие выбрать сервисы и компоненты, как их соединять между собой. Оценить сложность выбора можно по вот этой схемеCNCF Cloud Native Landscape.

Усложняет задачу выбора и тот факт, что для использования AWS Cost Forecast или калькулятора для расчета расходов от пользователя требуются специфические знания и навыки. Кроме того, весьма сложно создать описания процессов, структуры и необходимых скриптов. Все это требует наличия высококвалифицированных специалистов, глубоко разбирающихся в облачных технологиях Amazon, Google или Microsoft.

В общем, главный минус хостинга в облаках - он сложный.

App-specificproviders

Если рассматривать услуги App-specific providers, которые рассчитаны в первую очередь на разработчиков, то широко известными примерами таких сервисов являются Google AppEngine, VMWare Pivotal Cloud Foundry, Heroku, Pantheon и другие. Такиесервисы представляют наборы готовых компонентов для создания приложений, а также фреймворки для управления платформой. В данном случае компонентами будут являться сервисы баз данных, репозитории, инструменты автоматизированного деплоя, мониторинга, среды тестирования и тому подобные сервисы.

Уровень входа в эти сервисы ниже, чем в облачные, но тем не менее, для развертывания хостинга вашего приложения на таких системах, какHeroku или Pantheon требуется написание специального манифеста,разрабатывать и отлаживать который для новичков очень непросто.Недостатки напоминают таковые у Managed hosting - ты имеешь только то, что тебе дают. При этом часто чего-то не додают, например, нужную конкретную версию компонента. Кроме того, неудобны ценовые планы - вы либоне помещаетесь в план, либо платите за большие ресурсы, чем потребляет ваш проект. В итоге часто получается так, что в процессе роста ваше приложение начинает обходиться слишком дорого, но так как вы уже адаптировали его для конкретного PaaS, перейти на какое-то другое решение вам уже сложно.Но при этом у App-specific providers нет проблемы выбора и соединения множества компонентов, как у AWS или других облачных провайдеров.

Предлагаемое решение

Мыпредлагаем существенно снизить этот порог вхождения в облачные технологии для компаний при помощи своего нового разрабатываемого продукта WSP. По сути, порог вхождения снижается до наличия всего лишь трех необходимых компонентов:

  • AWS account

  • GIT account

  • Ваше приложение должно быть докеризируемым, то есть иметь возможностьработать в докер контейнереи собираться через docker build.

Кастомизация и отличия от конкурентов

После развертывания приложения с помощью WSP,вы можете впоследствии кастомизировать его с помощью собственных terraform скриптов, например, или другими методами. При этом те внесенные кастомизации, которые не управляются из WSP, не будут потеряны после последующих развертываний новых версий приложения.Другим преимуществом WSP перед его основными конкурентами, продуктами Pantheon и Heroku, является то, что в них требуется предварительно написать манифест для развертываемого приложения, что требует высокой квалификации и глубокого знания продукта. При этом приложения у конкурентов будут работать только на их собственной инфрастуктуре, а в случае WSP приложения работают на инфраструктуре Amazon и будут продолжать работать на ней даже в случае отказа от дальнейшего использования WSP. В качестве минуса WSP, можно назвать необходимость отдельно оплачивать использование аккаунтов WSP и AWS, тогда как вPantheon и Heroku вы оплачиваете только их аккаунты.

Масштабируемость

В отличие от решений масштабируемости, которые предлагают сервис провайдеры,WSP предоставляет возможность использовать autoscaling, или, иначе говоря, горизонтальнуюмасштабируемость. Autoscaling легко настраивается в зависимости от потребностей работы вашего приложения. Учитывая, что вы платите только за фактически используемые ресурсы, autoscaling становится очень выгодным решением. Если нагрузка снижается, избыточные серверные мощности высвобождаются, соответственно вы платите меньше.

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

Наскриншоте нижехорошо видно, как просто это можно настроить:

Мониторинг и логи

Настройка систем мониторинга и логирования крайне нетривиальная задача в AWS. В WSP логирование с помощью ELK stack (Elasticsearch, Logstash, Kibana) и мониторинг с использованием Prometheus или Grafana настраиваются и подключаютсяпредельно просто. То есть, ониподключаются автоматически к каждому приложению,если при регистрацииAWS аккаунта к WSP было выбрано использование этой функциональности. В то же время вы всегда можете отключить мониторинг и логи, например, для экономии. И наоброт, включить их, когда они потребуются.

Так как мониторинг и логирование разворачиваются в AWS аккаунте, то они входит в стоимость AWS. Следовательно эти функции не исчезают даже если вы отказались от использования WSP.

Управление затратами

WSP в процессе развертывания приложения производит детальную разбивку затрат, что позволяет вам сделать точный прогноз по расходам за облачные сервисы, используемые вашим приложением. Эту сформированную разбивку и остальные данные по управлению затратами вы можете посмотреть вAWS Cost Explorer. Там можно увидеть затраты по временным периодам (в день, в месяц, в год) и по сервисам.

Технические домены с сертификатами

Сейчас мы умеем автоматизировать создание зоны и делегирование её. Таким образом, если пользователя устраивает, что технический домен для его приложения будет являться сабдоменом нашего домена, то ему ничего делать не нужно - сабдомен создаётся (и работает) в его Route53 автоматически. Если пользователю нужен свой собственный домен, то он может это настроить, но тогда за прописывание NS отвечает он сам. Сертификаты для этих технических доменов выписываются и назначаются автоматически. Это полностью избавляет от необходимости заботиться о регистрации, настройке и защите доменов ваших приложений.

Автоматическое развертывание баз данных в Amazon RDS

WSP может автоматически разворачивать экземпляр базы данных типа PostgreSQL, MySQL или MariaDB для вашего приложения в Amazon RDS. Это настраивается непосредственно в "Environment settings" вашго приложения:

Zero downtime

Если в процессе работы с вашим приложением WSP производит развертывание новой версии приложения или откат на предыдущую версию, сессия работы переключается с текущей на новую версию приложения совершенно незаметно для вас. Реализован полный Zero Downtime для таких случаев.

One more thing!

  • Lift&Shift. Особенное внимание в разработке и концепции WSP уделяется тому, что вам совершенно не нужно как-то адаптировать и переделывать ваше приложение для его работы в облаке. С помощью WSP оно будет работать без каких то дополнительных усилий для его адаптации.

  • В WSP ограничение доступа к вашим приложениям обеспечивается с помощью Access Rules. Вы можете добавить в них те сети и адреса, с которых возможен доступ. Со всех иных сетей и адресов доступ будет закрыт.

  • WSP обеспечивает асинхронную работу. Вы можете одновременно выполнять инициализацию, сборку, развертывание приложений. Все будет работать одновременно. Даже закрыв сессию браузера вы не прервете выполнение уже запущенных задач.

  • Все используемые в продукте компоненты стандартные. Эти компоненты- признанный мировой стандарт индустрии, имеют открытый исходный код и бесплатны.Никакие проприетарные компоненты не используются. Например, для pipeline в WSP используется Tekton.

  • Все секретные данные, такие, например, как пароли, логины и т.д. шифруются.

  • Поддерживается непрерывное развертывание (Continuous Deployment (CD)). То есть, платформа может автоматически собирать и разворачивать приложение по коммиту в GIT репозитории.

  • В настоящее время в качестве поддержки концепции "Infrastructure as a code" WSP может считывать параметры приложения из специальных файлов из git-репозитория, то есть кроме задания параметров приложения из UI возможно задавать параметры в файле.

Планы дальнейшего развития

В настоящее время WSP работает только с облачной инфрастуктурой Amazon. В дальнейшем планируется расширить этот список облачными сервисами Google, Microsoft Azure и DigitalOcean. Для тех потребителей, кто использует инфрастуктуру на базе Kubernetes также планируется поддержка.

Другим интересным путем развития WSP видится использование готовых докер образов приложений непосредственно с DockerHub.

Заключение

Как видно из перечисленных выше преимуществ, главной ценностью проекта WSP является максимальное упрощение процесса вхождения в облачные технологии для желающих к ним приобщиться. Для мобильного разработчика, дата-аналитика, девопса, докопса и т.д. достаточно лишь сформулировать свою потребность и можно пробовать реализовать ее достаточно просто в облаке с использованием богатых возможностей WSP.

Проект находится еще в очень ранней стадии развития. Фаза активной разработки продолжается. В настоящее время команда Pleskуже использует WSP для наших собственных сервисов. Если вы хотите попробовать WSP, посмотреть, подходит ли он для вас, повлиять на развитие проекта путём обратной связи, поделиться вашими сценариями использования - welcome to closed alpha. Присоединиться можноздесь.

Подробнее..

Смена работы тимлидом как готовиться, как онбордиться, и что дальше

04.06.2021 08:06:10 | Автор: admin

Я тимлид вот уже десять лет. Год назад я получил предложение о работе, которое звучало как очень интересный вызов, но вместе с тем меня терзали сомнения, поскольку был разгар пандемии, и я понятия не имел, как стать лидером для новой команды в условиях удаленки. Не добавляли уверенности в успехе новый для меня стек и длинная 20-летняя история проекта.

Однако факторы в пользу успеха тоже были. Во-первых, предыдущий тимлид остается, вернувшись в роль разработчика. Во-вторых, по отзывам, в компании отлаженные и очень человечные процессы.

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

Содержание.

Что изучить еще до выхода на работу

Блог Уилла Ларсона

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

Книга Первые 90 дней Майкла Уоткинса

Основная идея данной книги на старте у нового руководителя есть кредит доверия, и его нужно оправдать за первые 90 дней, продемонстрировав существенные достижения.

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

Также я изучал отзывы на книгу, и нередко они сводятся к мысли: за первые 90 дней нужно показать успех любой ценой. Лично я такого посыла не увидел, но, даже если он есть, вот две статьи Уилла Ларсона для баланса:

  • The rush to "show value" поясняет, как не наломать дров в стремлении быстро показать результат.

  • Your first 90 days as CTO or VP Engineering статья для лидеров уровнем выше, но полезна как карта куда направить внимание в первую очередь.

С подготовкой закончили. Дальше я расскажу, что делал в первые дни на новом месте.

На старте. Собираем контекст и ожидания

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

Ниже я опишу, как на старте собирал контекст и устанавливал нужные коммуникации.

Сразу зарезервируйте время на обучение

Когда-то давно я прочитал про такое явление как спираль сделанной работы (к сожалению, не помню, где читал). Смысл этой спирали в том, что чем больше работы вы делаете, тем больше работы вам придется делать в дальнейшем.

Какие-то активности в принципе требуют постоянной поддержки. В других активностях мы с каждым шагом понимаем, как сделать еще лучше и, естественно, хотим продолжать. Наконец наше окружение (и мы сами) очень редко снижаем ожидания к себе после каждого успеха хочется продолжать с тем же или даже большим темпом.

Если мы не следим за балансом обязательств и копим незавершенку, то мы становимся все больше должны. Спираль может закрутиться до состояния, когда без нас уже ничего не может быть сделано, и мы вынуждены крутиться, как белка в колесе, чтобы поддержать хотя бы текущие обязательства. Еще это печальное состояние известно как bus factor = 1.

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

Понаблюдайте, как идет работа в компании

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

Первое время я решил побыть тихим наблюдателем, вникнуть в традиции компании и как люди взаимодействуют друг с другом. А к активным действиям переходить позже, когда сформируется понимание ситуации.

Надо сказать, что мне тут сильно повезло в первую неделю прошли даже те митинги, которые проходят лишь раз в квартал.Вот в каких митингах я поучаствовал в первую неделю и что на них делал

Daily sync с командой

Классический stand up meeting. Здесь я понял текущие боли проекта, настроение команды, кто в чем профи, есть ли тлеющие или явные конфликты.

Также этот митинг отличное время, чтобы легализовать себя в команде. Расскажите о своем прошлом опыте, чем вы увлекаетесь в жизни, как планируете действовать.Например, я рассказал, что не намерен крушить и строить заново, что сначала буду просто наблюдать. Что постепенно поговорю с каждым на 1-to-1, но только когда наберусь контекста, чтобы разговор был предметным.

Lead sync

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

Статус-митинг с PM и вице-президентом

Это митинг уже конкретно по нашему проекту как идут дела сейчас, и какие планы на ближайшие недели.Здесь я узнал про текущие вызовы проекта, "протокол" взаимодействия с топ-менеджментом, принятую степень открытости в обсуждении проблем. Открытость оказалась максимальной, и это очень помогло в дальнейшем действовать уверенно.

Meet & Greet

Это встреча всех сотрудников компании. Здесь я еще немного узнал про культуру, планы компании, новые продукты, насущные вопросы из повседневной работы. В середине 2020 года насущной темой ожидаемо были карантин и работа на удаленке.

Хорошо. Мы понаблюдали, изначальное представление о происходящем составили. Что дальше?

Проведите несколько встреч сами

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

Лучше всего провести встречи в режиме 1-to-1 это даст бОльшую открытость в разговорах. Также советую подготовить вопросы заранее, но на встрече не захватывать инициативу, а выслушать развернутые ответы. Не нужно сразу предлагать классные идеи как все изменить. Во-первых, может оказаться невпопад. Во-вторых, может прозвучать как обещание, а позже окажется, что это неисполнимо. У вас будет время, чтобы тщательно обдумать ситуацию и спланировать действия.

По ходу каждой встречи делайте заметки и поделитесь ими с собеседником, попросите проверить, что вы ничего не исказили. Потом извлеките из заметок действия, которые вам (возможно) предстоит сделать. Также проанализруйте заметки со всех встреч на предмет противоречий взглядов или потерь информации между разными сторонами. С этим тоже предстоит поработать.

Вот какие я провел встречи и что мы на них обсуждали.

1-to-1 с PM проекта

Эту встречу я провел в конце первой недели. Мы проверили мои первые предположения об основных вызовах на проекте и восполнили пробелы в моем понимании ситуации. Также советую обсудить с PM, кто из вас чем занимается в повседневной работе. Это поможет избежать двух ситуаций:

  • Вы оба не сделали что-то, ожидая, что это сделает другой.

  • Вы залезли на чужую территорию без спроса. Люди болезненно реагируют на такие ситуации. Особенно если вы станете менять или критиковать то, над чем ваш коллега уже давно и кропотливо работает.

Список вопросов, с которыми я пришел на встречу с PM.
  • Каков общий ландшафт проекта и ключевые ценности для бизнеса?

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

  • Какие компоненты системы критичны, и кто их стейкхолдер?

  • Могу ли я понаблюдать за работой конечных пользователей?

  • Какие у команды есть обряды? Синки, ретроспективы, планирование, backlog triage? Как проходят эти встречи, и есть ли замечания к их эффективности?

  • Почему выбрали именно kanban (scrum, lean, любую другую методологию)? Какие плюсы уже ощутили? Какие ожидали, но не получили?

  • Ключевые эпики, roadmap на год, интересы стейкхолдеров.

  • Какая сейчас температура в команде, на проекте, в отношениях со стейкхолдерами?

  • Какие с точки зрения PM планы по техдолгу, багам, внепроектным активностям?

  • Стоит ли нам общаться 1-to-1 регулярно или хватит рабочих встреч?

1-to-1 с непосредственным руководителем

Эту встречу мы провели в начале второй недели.

У нас в компании плоская структура, поэтому мой руководитель это вице-президент, то есть топ-менеджер. Это позволило убить сразу двух зайцев по части набора контекста.

Подход тот же: заранее подготовить вопросы, проверить гипотезы, пополнить контекст. После встречи извлечь список возможных действий.

Список вопросов, которые я обсудил с руководителем:
  • Общий ландшафт проекта и его ценность для бизнеса.

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

  • Как менялась динамика команды и ее отношения с бизнесом со сменой тимлидов в прошлом? Как давно это происходило?

  • Мой подход в целом, как планирую действовать в ближайшее время.

  • Какие планы у компании на этот год и глобальные планы?

  • Какие трансформации хочется провести в компании?

  • Есть ли подводные камни, о которых мне нужно знать?

  • Есть ли элементы культуры, которые стоит убрать? Что, наоборот, нельзя трогать?

  • Есть ли избыточные митинги или просадки в коммуникациях?

  • Какие основные риски в адаптации лида снаружи на твой взгляд?

По возможности договоритесь о регулярном общении с руководителем. Например, мы встречаемся раз в неделю по полчаса. Такие встречи отличный способ провалидировать ваши решения и собрать полную картину перед тем, как действовать.

Также очень рекомендую статью Уилла Ларсона Partnering with your manager. Она поможет построить с руководителем продуктивные отношения, а не просто приносить ему проблемы, с которыми он должен будет вам помогать.

1-to-1 с каждым участником команды

В отличие от предыдущих 1-to-1, с этими встречами торопиться не стоит. Вы будете иметь дело не только с проектными, но и с личными вопросами, поэтому важно приходить с максимумом контекста и минимумом домыслов и предвзятостей.

В моем случае предстояло провести девять встреч, и на них ушло полтора месяца.

Вот советы по подготовке к 1-to-1:

  • Прочитайте (или перечитайте) раздел про 1-to-1 в Team Lead Road Map.

  • Не стройте из себя супермена на встрече. Расскажите о своих прошлых провалах, не стесняйтесь говорить, что вам нужна помощь сейчас.

  • Записывайте любые положительные отзывы о коллегах. На 1-to-1 поделитесь с коллегой, что о нем говорит команда.

  • Запишите и негативные отзывы. Но в формате Вася считает, что Петя делает задачи медленно, а не Петя делает задачи медленно. На 1-to-1 предложите коллеге рассказать о той или иной ситуации, которую вы наблюдали и внимательно выслушайте. А потом извлеките действия, которые помогут снять напряжение сейчас и избежать подобных ситуаций в будущем.

  • До общения с коллегой не читайте его HR-карточку и историю решения сложных вопросов. Фрейминг существует и это штука очень сильная. Даже если вам кого-то представили как low performer-а, сначала поговорите с ним лично и разберитесь с его мотивацией.

  • На первый 1-to-1 заложите часа два и оставьте свободным календарь после. Мало что будет хуже, чем в разгар личной беседы убежать на другой митинг.

  • Декларируйте формат встречи. Например, я проговариваю, что этот митинг не для обсуждения текущих задач, а для личных вопросов. Что по умолчанию все приватно, и я попрошу разрешения, прежде чем что-то выносить наружу. Что мой ключевой принцип в работе безоценочность, и можно свободно высказывать свои мысли о любом человеке, включая меня самого, никаких наказаний или конфликтов не последует.

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

Список вопросов, которые я задавал

Конечно, список неполный, поскольку каждый 1-to-1 включал ряд личных вопросов.

  • Хочешь ли что-то обсудить прежде, чем мы перейдем к моим вопросам?

  • Каким ты видишь общий ландшафт проекта, ключевые ценности для бизнеса?

  • В каких частях проекта ориентируешься отлично? В каких хотел бы подкачаться?

  • Чем бы хотел заниматься? Хотел бы забрать на себя целиком какое-то направление? Какого плана задачи интересны (например, менторство)?

  • Как по-твоему идут дела на проекте?

  • Какие главные боли проекта?

  • Есть ли что-то, что мешает в работе лично тебе?

  • С кем тяжело работать в команде? А с кем хотел бы работать чаще?

  • Опиши идеального следующего кандидата в нашу команду?

  • Какие самые большие и интересные штуки стоит сделать? Что нужно сделать уже в этом году?

  • Есть ли у тебя долгосрочное видение себя? Хочешь составить план роста вместе? Что изменить, чтобы работа больше способствовала твоим целям?

  • Восхищаешься ли ты кем-то в компании?

  • Как чувствуешь себя на удаленке?

  • Что можно поменять в митингах?

  • Чувствуешь ли ты перегруз? Недогруз?

  • Что ты думаешь о фидбеке и его количестве? Как часто будем проводить 1-to-1 в будущем?

  • Хочешь ли что-то узнать обо мне?

  • Как настроение после беседы?

Итог по проведенным 1-to-1

Первая польза от этих встреч представление всех сторон о ситуации на проекте и в компании. Местами эти представления противоречивы, и это абсолютно нормально. Данные противоречия стали основой для моей дальнейшей работы.

Вторая польза я собрал список ожиданий от меня как от тимлида. Но его тоже стоит обдумать, прежде чем взять под козырек и ринуться исполнять. Детальнее об этом ниже.

Записи с митингов сохраните, они помогут вспомнить детали в будущем. Детали точно вывалятся из головы, ведь на испытательном сроке новой информации много. Также записи помогут отслеживать прогресс и начинать каждый следующий 1-to-1 предметно.

Что полезного сделать, пока вы собираете контекст

Как я писал выше, я не сторонник идеи врываться с первого дня с революционными идеями сначала стоит собрать контекст, чтобы действовать более взвешенно и точно.

Однако это не значит, что в первые неделю-две нельзя сделать ничего полезного. Это отличное время, чтобы зачистить все, обо что вы сами споткнулись.

Запишите, как проходил ваш найм

Комфортны ли были интервалы между собеседованиями и их количество? Было ли по ходу собеседований понятно, какой и когда следующий шаг? Получили ли вы оффер в виде красивого брендированного письма или это был просто неформатированный текст? Легко ли было найти офис и кабинет HR в первый день?

Запишите все, что было неудобно или вызвало вопросы. Оформите список идей и поделитесь в виде фидбека с HR и руководителем. Но именно в виде фидбека, а не критики. Не касайтесь личностей. Вместо что плохо, опишите как можно сделать хорошо.

Запишите, как проходили первые дни в компании

Был ли у вас buddy? Достаточно ли было информации о компании на старте? Может, слишком много информации, и голова пухла? Как быстро вы получили технику? Был ли полезен корпоративный мерч, который вам выдали в первый день? Запишите все, за что зацепился ваш мозг, каждую мелочь.

Моя адаптация была очень комфортной, но через три недели я отправил коллегам из HR список из 30 небольших идей. Большинство они воплотили в жизнь, а позже, на Новый Год, подарили мне крутой рюкзак :)

Автоматизируйте/задокументируйте первые шаги на проекте

Вы впервые настраиваете рабочее место, впервые собираете и запускаете проект, впервые читаете рабочую документацию. Автоматизируйте то, что еще не автоматизировано. Проясните и задокументируйте все, что было непонятно. Поправьте каждую битую ссылку в документации и удалите устаревшие разделы.

Составьте видимый план себя как лидера

Я решил сделать это в виде mindmap в miro, который базируется на Team Lead Road Map, но дополнен следующими моментами:

  • Моим опытом тимлида и пониманием, что важно в этой роли.

  • Ссылками на любимые статьи, курсы, книги.

  • Ссылками на документы и инструкции компании, релевантные роли тимлида.

  • Какие обязанности я забрал с предыдущего лида, а что еще предстоит забрать.

  • Какие из лидерских активностей я делегировал.

  • Какие активности относятся к категории muda, и я их постепенно истребляю.

Далее я поделился этим mindmap со всеми тимлидами, с нашим тим-коучем (да, у нас есть такой человек) и с вице-президентом. Также я делюсь им со всеми, кому интересна прокачка в тимлида, как инструкцией: что есть тимлид, что можно прокачать и где взять информацию для прокачки.

Приступаем к действиям

Итак, прошли первые недели. Теперь у нас есть некоторое понимание проекта, список ожиданий от нас, противоречия сторон в понимании проекта и вашей роли.

Это уже хорошие ориентиры для дальнейших действий. Вот еще парочка:

  • Статья Work on what matters поможет определить, куда направить свои усилия после того, как вы снимете все низко висящие фрукты. Как избежать жевания чипсов, то есть выполнения легкой и видимой, но не особо полезной работы.

  • Статья Good process is evolved, not designed в паре со статьей Managing technical quality in a codebase помогают постепенно вывести оптимальный процесс для команды и проекта, вместо декларирования с завтрашнего дня мы Agile и затевания революций.

И еще один совет. Чтобы помочь самому себе в будущем, систематизируйте весь получаемый сейчас опыт. Записывайте, что сработало, а что нет. Как вы внедряли изменения, с каким сопротивлением сталкивались. Например, можно вести brag document. Вот чем он будет полезен:

  • Систематизация полученного опыта

  • Если вдруг загрустили перечитаете и вспомните, сколько всего вы уже сделали

  • Можно найти темы для статей или докладов из своего же опыта - эта статья так и родилась.

  • Поможет при пересмотре зарплаты это готовый список ваших достижений

  • Поможет в подготовке резюме в следующий раз

В общем, практика полезная и непыльная.

А мы переходим к списку того, что я делал в первые месяцы.

Станьте клеем

Метафора с клеем, на мой взгляд, очень удачна и выражает собой 90% ценности лидера в команде и компании. Очень рекомендую посмотреть доклад Tanya Reilly на эту тему. Здесь же приведу примеры того, что можно и нужно склеить, придя в новую команду.

Склейте развалившиеся коммуникации

Например, когда-то топ-менеджмент ожидал, что наш проект поедет в облако. Но команда этим не занималась и выглядела как прокрастинаторы. На самом же деле команда давно взвесила все за и против, после чего приняла аргументированное решение не переезжать в облако. Но с руководителями это явно не проговорили.

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

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

Сформулируйте единое понимание, зачем существует ваш проект

На каждом 1-to-1 я задавал один и тот же вопрос: Каков общий ландшафт проекта и ключевые ценности для бизнеса?. И я получил очень разные ответы.

Позже мы с командой сформулировали нашу ценность следующим образом:

Мы поставляем данные для принятия стратегических решений, поэтому наши данные должны быть абсолютно корректны, и система должна работать 24x7, чтобы избежать потерь. Сейчас с этой формулировкой знакомы все: ребята в команде, кандидаты на собеседованиях, даже CEO.

Зачем это нужно? Имея емкую и понятную цель, мы легко решаем, куда прокачивать архитектуру, какой технический долг устранять сейчас, какие задачи имеют право растолкать другие и получить внимание вне очереди.

Отдайте процедурные долги

Тут примеры простые:

  • Согласуйте закупки железа или лицензий, которые давно нужны.

  • Обновите зарплаты тем, кому их давно не обновляли.

  • Согласуйте найм специалистов, которых не хватает в команде.

  • Поймите кого из ребят в команде не должен сбить автобус, кто перегружен. Верните им возможность сосредоточенно работать и спокойно ходить в отпуск, распределив "басфакторные" задачи по всей команде. Выделите время на шаринг уникальных знаний коллеги любыми способами: от написания документации до парного программирования.

Все это стоит сделать пока у вас есть свободное время, и это поможет оживить много инициатив.

Выгоните призраков

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

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

Ниже примеры того, каких призраков мы с командой разогнали в начале работы:

Нам нужно лучше оценивать задачи

Это самый частый призрак, которого мне доводилось встречать. Тема оценок бесконечна. Да, потому что мы часто с ними ошибаемся.

Если у вас не аутсорс и не fixed price проекты, попробуйте понять: а бизнесу вообще нужны точные оценки в часах? По моим наблюдениям, чаще нужно четкое понимание как идут дела сейчас, примерные сроки и понимание следующих шагов. Говоря проще, бизнесу нужна уверенность, что вы делаете то, что надо. Чтобы дать такую уверенность, нужны не высеченные в камне оценки, а постоянная коммуникация и выравнивание ожиданий если обстоятельства изменились. И бизнес отлично понимает, что обстоятельства просто не могут не меняться.

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

Бизнес не дает нам заниматься техдолгом, мы постоянно загружены задачами

Еще один классический призрак.

Дэвид Аллен в книге Getting things done очень удачно сравнивает обязательства, которые мы берем на себя, с кредитной картой. Если мы берем новую задачу не зная, где граница наших возможностей это все равно, что сделать покупку в кредит, не зная ни кредитного лимита, ни текущего баланса.

Очевидно, что если мы сами не чувствуем границу наших возможностей, то бизнес ее тем более не может чувствовать. Он не стоит у нас за спиной и не видит нашу повседневную деятельность.

На момент моего прихода команда была в очевидном перегрузе, и мы начали с поиска границы наших возможностей (см. раздел Визуализация загрузки команды ниже).

Определив наш WIP limit и показав его топ-менеджменту, я получил очень прямой и честный ответ Вы сами следите за своей нагрузкой. И вы не можете, а должны заниматься техническим долгом. Довод про перегрузку бизнес-задачами это просто нелепая отмазка. Если задач больше, чем вы можете сделать за раз, просто сообщайте об этом, и будем договариваться.

Так мы изгнали призрака бизнес плохой, и не дает нам делать работу хорошо.

Устраните болевые точки и незавершенку

Почти на каждом проекте есть застарелые боли, которые команда уже привыкла терпеть.В каждой команде есть классные начинания и идеи, которые почему-то завалились на полпути.

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

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

Это было болью, поскольку мы теряли данные, и это ставило под угрозу основную цель существования нашего проекта консистентные данные в режиме 24x7.

Решив вылечить проблему навсегда, мы собрались командой и через 10 минут поняли, что зеркало это вообще пережиток прошлого. В итоге мы перенесли пару микросервисов во второй датацентр, а зеркало убрали вообще.

Конечно, этот пример не единственный. Но я ограничусь одним, поскольку у каждого проекта свои уникальные болячки. И они очень заметны, так что вы найдете точки приложения усилий без труда сами.

Главная мысль приложите с командой сознательные усилия для завершения, а не терпите проблемы, которые давно пора решить.

Создайте общедоступные артефакты

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

Проект с высоты птичьего полета

Какое место мы занимаем в бизнесе компании, в чем наше назначение, какие у нас основные челленджи. Мы сделали это в формате презентации, Miro так умеет. С этой презентацией я рассказывал про проект нашему CEO и ее же показываю новым сотрудникам при онбординге.

Высокоуровневая архитектура проекта

Она была и раньше, но мы кардинально ее переработали. Сейчас диаграмма проще, но содержит гораздо больше информации. Используется как в команде, так и за ее пределами, иногда даже топ-менеджерами. Также после доработки диаграммы мы удалили целый ворох статей в confluence.

Хорошую помощь в построении понятных и простых диаграмм может оказать нотация C4 Model, статья Thinking Like An Architect Part 5 и опыт в прохождении system design interview.

Технический роадмап проекта

По сути это временная шкала, отражающая что мы уже сделали, что в фокусе прямо сейчас, что планируем следующим шагом. Отдельным "облаком" - что будем делать дальше, но еще не проработали в деталях (unshaped).Мы не планируем дальше пары шагов вперем, не тратим время на декомпозицю и проработку архитектуры далекого будущего - это наша реализация принципа defer commitment. Засчет этого мы всегда сфокусированы на том, что делаем сейчас и действительно заканчиваем большие задачи, а не попеременно хватаем и бросаем самые горячие картошки.

Визуализация стратегических задач (эпиков)

Есть особый класс задач: большие, с множеством рисков, с вовлечением нескольких команд, несущие большую пользу и кровно интересные бизнесу. Это задачи настолько важные, что на ежегодном собрании инвесторов они будут обсуждаться. Мы называем такие задачи эпиками.

Для эпиков недостаточно разбивки на подзадачи в виде одномерного списка задач в трекере это не отражает все детали, сложности, риски.Поэтому для каждого эпика мы создаем визуализацию, на которой слева направо идут все завершенные/текущие/предстоящие активности, открытые вопросы, артефакты (дизайн-макеты, наброски алгоритмов) и т.д.

С помощью этих визуализаций мы проводим синки и внутри, и вне команды.

Визуализация загрузки команды

Выше я уже рассказывал, что команда на момент моего прихода была в перегрузе.

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

  • Зеленый задачи долгосрочного технического развития. Снижение/предотвращение рисков, снижение operational costs, прокачка observability, testability и прочих ...ility

  • Желтый бизнес-задачи со стандартным приоритетом.

  • Оранжевый те самые эпики, упомянутые выше. Работая с такими задачами, мы находимся в режиме выталкивания задач вместо затягивания новых. То есть если к нам сейчас прийти с еще одним эпиком, он встанет в очередь пока мы не закончим.

  • Красный авария, например, падение на проде. Мы не берем ничего, пока не разберемся с текущей ситуацией.

Этих артефактов достаточно, чтобы сделать работу вашей команды видимой и понятной.

Впрочем, не факт, что другие команды и стейкхолдеры будут смотреть сюда. Но формирование новых коллективных привычек это тема отдельной статьи. А артефакты в любом случае помогут вам и команде.

Что шло не по плану

Я все еще не пишу код

На эту тему я переживал еще на этапе собеседования. Я привык работать, не отрывая руки от кода. Тут же выглядело так, что будет не до кода, поскольку много высокоуровневых задач и people management да еще и новый стек надо освоить.

В итоге я решил переобуться на ходу. Да, я привык работать, не отрывая руки. Но, вообще, это плохая привычка для руководителя. И я отлично понимал, что за мной привычка нырять в текучку с головой еще как водится. Поэтому я решил воспользоваться сдерживающей меня кривой обучения и избавиться от вредной привычки.

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

Однако со временем это становится проблемой команде трудно видеть лидера в человеке, который принимает лишь отстраненные решения и не в состоянии впрягаться в решение проблем вместе со всеми (могу поделиться на эту тему интересным исследованием).

Сейчас я близок к тому, чтобы взяться за код. Вот что я могу посоветовать здесь:

  • Устраняйте муду, которая пожирает ваше время. Заменяйте митинги на общедоступные артефакты. Устраняйте ручные действия, вызванные несовершенством процессов и инструментов. Очень много работы можно просто взять и выбросить.

  • Делегируйте. Например, найм, онбординг, коммуникации со стейкхолдерами. Многое из того, что для вас рутина, для вашего коллеги будет точкой роста.

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

Мою систему работы с задачами разнесло в щепки

Да, это был момент настоящей паники

В один вовсе не прекрасный день я понял, что моя система работы с задачами перестала работать. Изначально она базировалась на техниках Максима Дорофеева, и я не один год ее дотачивал. Она идеально работала больше пяти лет, но с текущим количеством и уровнем задач мою систему разнесло в щепки. Я потерял контроль над происходящим.

Дело оказалось, ожидаемо, не в задачах, а в подходе. Чтобы выстроить новую систему, я прочитал несколько книг:

  • Джедайские техники Максима Дорофеева. Эту книгу я читал и раньше, но перечитать оказалось совсем не лишним.

  • "Антитайм-менеджмент" Николая Додонова. На эту книгу очень много отсылок в Джедайских техниках, и эта книга двано была у меня в списке на чтение. Но я прокрастинировал, пока не "прижало". Прочтя могу сказать, что это отличная книга, которая раскрывает, как работает наш мозг в условиях перегрузки, и как построить постоянный продуктивный ритм работы.

  • Getting Things Done Дэвида Аллена. Еще одна книга, чтение которой я откладывал несколько лет. Исчерпывающее, хотя и сухое, руководство о том, как быть готовым к любой нагрузке. Вероятно, большинству система покажется слишком изощренной, но эта книга больше всего помогла справиться с нагрузкой. А со временем некоторые куски этой системы начали отваливаться сами собой, когда наплыв задач уменьшился. Некоторые практики становятся ненужными, когда вместо вороха дел у вас появляется долгосрочный горизонт и понимание, что важно. Эта книга помогает их найти.

  • То, как мы работаем не работает Тони Шварца. Книга про базовую гигиену труда и отдыха. Рекомендую прочитать ее всем, кто чувствует перегруз на работе и всем, у кого есть подчиненные.

По мере чтения книг я перестраивал систему, пока она не дошла до нужной отказоустойчивости. Но больше всего помогла смена отношения к задачам, в чем помогли "Антитайм-менеджмент" и То, как мы работаем не работает.

Выводы

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

Позже я осознал, что даже в лучших компаниях есть проекты на грани и есть разорванные коммуникации. Говоря проще, в каждой компании есть проблемы. Если проблемы не видны - это не само так работает, это кто-то очень хорошо делает свою работу. И в том числе роль кого-то исполняет тимлид.

Понимание этого момента помогло мне закрыть для себя переживания, что тимлид это не недоменеджер. Наоборот, это очень сложная и интересная работа. Команда это нечто лучшее и более сложное, чем группа людей, сидящих в одном кабине и пилящих задачи поодиночке. Межкомандные проекты сами собой, без усилий, могут только упасть.

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

Статья получилась огромной, но надеюсь она поможет лидерам в адаптации на новой работе, потому что это дело не такое уж простое. Успехов вам!

Список материалов

Подробнее..

Залечь на дно в Кельне жизнь и работа в Германии во время пандемии и локдауна

09.03.2021 12:08:26 | Автор: admin

Так получилось, что наша с мужем ИТ-эмиграция пришлась на непростой период - только мы начали привыкать к новой жизни в центре Европы, как наступила весна 2020 года со всеми вытекающими последствиями. В итоге вместо путешествий без границ мы увидели совсем другую сторону жизни в Германии - тот самый немецкий орднунг. На практике это означает, что какими бы неоднозначными ни казались меры, принимаемые правительством, - если их всё же приняли, придется им следовать. У некоторых экспатов это вызывает фрустрацию и даже разочарование от переезда. В этой статье я поделюсь своими впечатлениями от текущей обстановки в Германии в целом и расскажу, как это отразилось на нашей жизни в частности - может быть, кому-то это поможет определиться, готовы ли вы к такой жизни или стоит рассмотреть альтернативные направления для переезда (а еще оценить плюсы жизни на родине!).

Первый локдаун пришел в нашу немецкую жизнь год назад, в середине марта. Ктому моменту мы жили в Кёльне чуть больше полугода, совершив релокейт из новосибирского офиса Plesk в немецкий. В одночасье захлопнулись границы - мы успели вернуться из отпуска за три дня до того, как авиакомпания Победа приостановила рейсы Москва-Кёльн, - опустел офис, закрылись рестораны и магазины. Прилетевшие на неделю в командировку коллеги выбирались обратно в Россию уже с приключениями.

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

Летом казалось, что вернулась почти нормальная жизнь - снова заработал общепит, открылись отели и музеи, а также границы с другими странами Евросоюза. Даже перелёты в Россию как-то стабилизировались, и нам удалось слетать домой. Но в октябре началась вторая волна коронавируса, и меры снова ужесточили.

Ограничения

UPD Дисклеймер - здесь и далее речь пойдет о нашем опыте в земле Северный Рейн-Вестфалия по состоянию на начало марта 2021, что может отличаться от правил в других федеральных землях.

В двух словах текущие ограничения состоят в следующем: закрыто почти всё - а то немногое, что открыто, посещать можно только в маске. Маски в Германии ввели не сразу - сначала эта мера показала хороший результат в одной из федеральных земель, и в конце апреля ношение масок в общественном транспорте, магазинах и других закрытых помещениях стало обязательным по всей стране. До недавнего времени годилась любая маска или даже шарф, закрывающий нос и рот, но с 20 января разрешены только респираторы FFP2 или, как ни странно, обычные одноразовые медицинские маски. Считается, что такие лучше защищают, плотнее прилегают и закрывают большую часть лица. Штош. Красивые корпоративные масочки пока пришлось отложить в комод.

А жаль!А жаль!

Это сделали не только мы - буквально в первый день действия новых правил 99% всех пассажиров нашей электрички были уже в масках нужного типа. Это очень показательно, хотя и ожидаемо: немцы (как впрочем и все те, кто давно живет в Германии)) в большинстве своем правила выполняют четко. При этом я ни разу не видела ни одного масочного рейда или чего-то в этом духе. Знаю, что в Берлине и других крупных городах уже неоднократно проходили акции протеста, но в быту - в магазинах, общественном транспорте, - маски носят все. Единственный раз, когда кому-то при мне сделали замечание, произошел с молодым человеком в автобусе, спустившим маску на подбородок - из-за стеклянной перегородки сразу же выглянул водитель со словами: Молодой человек, ваша маска, парень вернул маску на место и мы мирно поехали дальше.

Из других немногочисленных мер контроля - на входе в гипермаркет у нашего дома весной поставили специального дядечку, который следил не только за наличием маски, но и за тем, чтобы каждый покупатель был с тележкой (видимо, так считали заполняемость). Летом дядечка исчез, но правило с телегами во многих магазинах осталось.

Почти полгода автобусы запускали пассажиров только через среднюю дверь, а не через переднюю, как раньше, чтобы минимизировать риски для водителя. Недавно вход через переднюю дверь всё-таки вернули. Наверное, слишком многие пользовались тем, что не надо прикладывать карточку к валидатору :) Почти полгода автобусы запускали пассажиров только через среднюю дверь, а не через переднюю, как раньше, чтобы минимизировать риски для водителя. Недавно вход через переднюю дверь всё-таки вернули. Наверное, слишком многие пользовались тем, что не надо прикладывать карточку к валидатору :)

В остальном соблюдать ограничения в общем-то несложно - пойти всё равно некуда. С середины декабря в Германии действует второй жесткий локдаун, который только-только планируют начать ослаблять. Закрыто практически все - торговые центры, театры, музеи, бассейны и бани (парикмахерские открылись 1-ого марта, и это было самое первое послабление текущих ограничений). Рестораны закрылись еще в ноябре, и последние 4 месяца работают только на вынос. Некоторые магазины, кстати, тоже освоили такой формат и открыли точки выдачи товаров, купленных через интернет. Работодателям было рекомендовано перевести всех, кого только возможно, на удаленку. Школы и детские сады тоже были закрыты вплоть до конца февраля - дети учились дома, а в садиках работали только дежурные группы для тех, чьи родители не могут работать удаленно. Социальные контакты сведены к минимуму - встречаться можно не более чем с одним человеком из другого домохозяйства (UPD с 8 марта можно собираться по 5 человек). Утешает одно - пока обошлось без комендантского часа.

H&M стоит закрытым уже почти 2 месяца - видимо, после открытия перейдет сразу к летней коллекцииH&M стоит закрытым уже почти 2 месяца - видимо, после открытия перейдет сразу к летней коллекции

Хоум-офис

Офис Plesk в Кельне официально не закрывался, но с первой же недели локдауна сотрудникам было рекомендовано по возможности перейти на работу из дома. С тех пор в офисе пусто - регулярно появляется лишь человек 5-6, и это ребята из России :) немецкие коллеги приходят редко.

По виду из офиса я немного скучаю :) По виду из офиса я немного скучаю :)

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

Еще один плюс - гигантская экономия времени, которое раньше уходило на дорогу. Мы живем в пригороде Кельна, и каждый день тратили около часа на то, чтобы добраться в одну сторону. Теперь это время можно посвятить самообразованию, прогулкам, приготовлению вкусняшек или просто два часа тупить в инстаграм.

Конечно, кроме плюсов, есть и минусы. Во-первых, мы почти не практикуем язык. Рабочие вопросы и так обсуждаются по-русски или по-английски, а теперь, с уходом из офиса, с немцами не поболтаешь даже на кухне за кофейком. Другой значительный минус - необходимость обустраивать постоянное рабочее место дома. Сидеть вдвоем за одним столом (который к тому же не офисный, а обеденный) было неудобно, и нам пришлось докупить компьютерный стол и кресло. К счастью, государство решило поддержать работающих из дома - за каждый день работы из дома можно будет вернуть до 5 евро налогов (максимум 600 евро в год). Правда, для этого придется доказать, что вы действительно не могли работать в офисе, у вас была отдельная комната для работы и эту комнату вы не использовали ни для каких других целей (UPD как подсказывает @0sya, пункт с отдельной комнатой не обязателен - good news). Нам этот челлендж только предстоит, поэтому если вы живете в Германии и уж провернули что-то подобное, поделитесь этим бесценным опытом!

Вакцинация

27 декабря в Германии началась вакцинация от коронавируса. Она будет проводиться в несколько этапов: сначала высший приоритет (люди старше 80 лет, а также медперсонал и работники домов престарелых), высокий приоритет (70+ лет), повышенный приоритет (60+) и только потом все остальные. Сначала предполагалось, что до всех остальных дело дойдет уже к началу лета, но постепенно сроки сдвинулись, и теперь речь идет уже об осени. Сдвиг сроков объясняют задержками производства и поставок вакцины. Поставить прививку можно будет бесплатно. В нашем городке место для вакцинации оборудовали в местном торговом центре.

Переход в онлайн

Тем временем вся общественная и культурная жизнь продолжается в интернете. Образование тоже перешло в онлайн - например, языковая школа, в которую я ходила учить немецкий, в середине марта в одночасье перевела все уроки в Zoom. Общеобразовательные школы тоже научились работать дистанционно - для Германии это новый опыт, до пандемии учиться дома (кроме случаев с показаниями по здоровью) было нельзя. Как мы поняли из разговоров с немецкими коллегами, у которых есть дети-школьники, онлайн-обучение организовано попроще, чем в России - например, ничего похожего на Дневник.Ру нет, и во время первого локдауна (весной) дети просто повторяли материал за весь учебный год, без сложностей с проверкой домашки через вотсап и т.п. Коллеги с детьми, поправьте в комментариях, если это не так :)

Всевозможные ивенты тоже перебрались в сеть - в частности, знаменитый кельнский карнавал. В этом году он прошел с 11 по 17 февраля - без перекрытых улиц, разбрасывания конфет с грузовиков, безумных костюмов и танцев в барах до упаду, но с трансляцией шествия кукольного карнавального поезда по центральному каналу телевидения и многочисленными стримами из радиостудий, оперного театра и концертных площадок (концерты записывались, естественно, без зрителей). Я ожидала появления какой-то социальной рекламы с напоминаниями не собираться и не нарушать изоляцию - но, кажется, все и так уже всё поняли и никаких дополнительных призывов не потребовалось

Так сейчас выглядит привокзальная площадь Кёльна - до пандемии здесь всегда было очень оживленноТак сейчас выглядит привокзальная площадь Кёльна - до пандемии здесь всегда было очень оживленно

Итог и субъективные впечатления

Вот и всё, чем я хотела поделиться с вами в этой статье. Надеюсь, что картинка получилась не слишком мрачной. В общем и целом жить можно - особенно если ты IT-специалист с гибким графиком работы и привычкой сидеть дома как сыч. Лично наш образ жизни и до локдауна был довольно пенсионерским, поэтому мы не очень страдаем. Больше всего не хватает путешествий - но когда-нибудь они обязательно вернутся. Медленно, но верно обстановка налаживается - тем не менее, власти предпочитают действовать осторожно и ограничительные меры, судя по всему, с нами еще надолго. На последнем совещании канцлера и глав федеральных земель локдаун продлили до 28 марта.

Можно относиться к этому по-разному, но если оставить в стороне эмоции, локдаун стал для нас и, думаю, многих других экспатов очень показательным экспериментом по погружению в среду. Здесь все играют по правилам, даже если они не всем нравятся - и ситуация с пандемией еще раз это доказала.

Плакат Вместе мы сильны. Завтра наступит - мы освободим ему дорогуПлакат Вместе мы сильны. Завтра наступит - мы освободим ему дорогу
Подробнее..

Разные типы IT-текстов о чем стоит помнить переводчику

24.02.2021 18:11:35 | Автор: admin

Для того, чтобы программным продуктом могли пользоваться люди в разных странах, нужно адаптировать его для них, то есть локализовать. И одним из важнейших этапов локализации всегда был и остается перевод. Я работаю в Plesk переводчиком с английского на русский язык и в этой статье хочу рассказать об особенностях работы IT-переводчика, а именно, о том, какие типы текстов мы переводим и с какими подводными камнями порой сталкиваемся в каждом из них. Надеюсь, мой опыт окажется полезным тем, кто переводит или собирается переводить IT-контент с английского на русский язык.

Содержание:

Трудности IT-перевода в целом

В IT я работаю уже 15 лет, но большую часть этого времени я была техническим писателем, то есть писала документацию к ПО на английском языке. Четыре года назад, когда у нас в компании появилась вакансия переводчика на русский язык, мне стало интересно сменить направление и попробовать себя в другой области так я начала заниматься переводами. Вообще, технический писатель и IT-переводчик профессии, на мой взгляд, родственные, потому что в обоих случаях нужно быть частично технарём, частично гуманитарием, и это как раз мой случай.

Сначала мне казалось, что переводить IT-тексты будет легко, ведь я владела темой и терминологией на английском, а русский мой родной язык. Что тут может быть сложного? Но довольно скоро я столкнулась с рядом подводных камней:

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

  • Поскольку IT-сфера развивается стремительно, в ней постоянно появляются новые термины и понятия, для которых ещё нет устоявшихся русских названий. И их приходится придумывать.

  • Границы между терминами и сленгом в русскоязычном IT довольно размыты. Если на профессиональных форумах вполне уместно использовать сленг, то в официальной документации для пользователей это чаще всего неприемлемо. Поэтому постоянно приходится искать баланс и подбирать нужные термины: не канцелярские, но и не сленговые, а более человеческие и при этом верно передающие смысл.

Ну и, помимо этого, свои особенности обнаружились у каждого из типов контента, которые мне приходилось переводить. Именно о них я расскажу ниже.

Коротко о процессе перевода в Plesk

В компании Plesk уже давно существует отдел локализации, который занимается переводом с английского на другие языки (сейчас на 31 язык). Количество продуктов, которые локализуются в нашей компании, периодически меняется. В течение нескольких лет это был единственный продукт платформа веб-хостинга Plesk и несколько её расширений. В последние годы к списку продуктов, которые мы локализуем, добавилось много новых расширений Plesk, новый продукт SolusIO, а также cPanel ещё одна популярная платформа веб-хостинга, широко используемая во многих странах.

У нас есть менеджеры по локализации (к их функциям относится организация процесса переводов, в частности, прием материалов на перевод и распределение их между переводчиками, контроль работы переводчиков и отправка готовых переводов в продукт) и штатные переводчики на русский, испанский и каталонский языки. Перевод на остальные языки выполняют outsource переводчики и агентства.

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

Итак, что же именно мы переводим? И, главное, как?

Перевод UI: "попробуйте еще раз позже"

Основная и наиболее приоритетная часть нашей работы перевод сообщений пользовательского интерфейса Plesk и других продуктов. Что такое UI-сообщения? Как правило, это короткие фразы для взаимодействия с пользователем инструкции, предупреждения, вопросы и названия элементов управления, которые, на первый взгляд, не составляет труда перевести. Но чтобы после перевода они смотрелись естественно для носителя другого языка, нужно учитывать несколько моментов.

Контекст это важно

Русский язык отличается от английского большим количеством различных форм слова: необходимо учитывать падеж, род, часть речи и так далее. И если, к примеру, сообщение состоит из одного слова Open, мы можем перевести его в зависимости от контекста разными способами: Открыть, Откройте, Открыто, Открыт, Открыта, Открыты. Поэтому необходимо понимать, в каком месте интерфейса и в какой момент оно отображается. Если же переводить в лоб, возможны подобные ситуации:

В момент перевода было неизвестно, что "Open" относится к числу открытых задач. В момент перевода было неизвестно, что "Open" относится к числу открытых задач.

Как узнать контекст? В идеале получить доступ ко всему интерфейсу продукта или набор всех его скриншотов. Теоретически это, конечно, возможно, но на практике не всегда получается сделать это быстро, так как, например, часть расширений Plesk платные, а для работы других расширений может потребоваться учетная запись в сторонней системе, например, в облачном хранилище. Более того, даже если переводчику удалось получить доступ к всему интерфейсу, есть ещё сообщения об ошибках, которые не всегда просто воспроизвести. Поэтому неизбежная часть работы переводчиков задавать вопросы другим участникам команды (ПМ-ам, разработчикам, тестировщикам, техническим писателям). В программе Crowdin для этого есть удобная функция: оставить к сообщению комментарий с вопросом и там же получить на него ответ. Более того, нам видны вопросы других переводчиков и ответы на них, а значит, дублировать вопрос не нужно.

Глоссарий нам поможет

В каждом продукте есть своя терминология. И переводить её нужно единообразно, чтобы не называть одни и те же сущности по-разному. Соответственно, для каждого продукта нужен свой глоссарий. Большинство программ перевода поддерживают импорт глоссариев и при переводе показывают термины и их перевод, что очень удобно.

Иногда мы получаем глоссарии от менеджеров продукта: в этом случае у терминов есть пояснения на английском языке, а переводы на свой язык мы добавляем сами. А иногда составляем глоссарий самостоятельно. В любом случае, переводы в глоссарии мы согласовываем с менеджером продукта или другим участником команды. Бывает, например, что для одного продукта термин snapshot просят переводить как снимок, а для другого как снапшот. Или название отдельных функций продукта просят оставить без перевода. Все это необходимо учитывать.

Как быть с числительными?

В русском языке больше форм существительных, зависящих от числительных, чем в английском: 1 элемент, 2 элемента, 5 элементов. Если не учитывать форму слова, то, например, сообщение %%total%% items total (где %%total%% переменная, означающая число) может после перевода выглядеть так:

Слово "элементов" используется с любым числом.Слово "элементов" используется с любым числом.

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

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

То, что не выделено цветом, переводится. В поле "Preview" можно подставить число и проверить.То, что не выделено цветом, переводится. В поле "Preview" можно подставить число и проверить.

Однако если в вашем арсенале пока нет никаких специальных инструментов для работы с числительными (а так было и у нас, пока мы не начали использовать синтаксис ICU), могу порекомендовать воркэраунд: перенести аргумент числа в конец сообщения и использовать общую форму для всех существительных. То есть фразу %%total%% items total при переводе меняем следующим образом: Всего элементов: %%total%%. На мой взгляд, такой вариант вполне работает в большинстве случаев.

О различиях языков

Бывает, что видишь интерфейс программы на русском языке, и вроде бы всё понятно, но сразу чувствуется, что он переведен. Это становится видно по стилистическим различиям языка и разным традициям написания. Об этих различиях нам также приходится помнить, чтобы переведенный текст читался легко и естественно.

Английский язык более эмоционален. В английском интерфейсе нередко можно встретить сообщения с восклицательным знаком. В русском же языке это будет выглядеть слишком эмоционально и ассоциироваться с криком. А ещё в английских сообщениях часто используется слово Please (Пожалуйста), которое в русском языке, как правило, неуместно. Например, фраза Please try again later! в английском интерфейсе выглядит вполне приемлемо и звучит по-дружески. Но переведенная дословно фраза Пожалуйста, попробуйте ещё раз позже! звучит как-то тревожно. Поэтому переводим спокойнее, без пожалуйста и восклицательного знака: Попробуйте ещё раз позже.

Названия разделов меню: капитализация и кавычки. В русском языке не используется капитализация названий разделов меню по первым буквам каждого слова, принятая в английском языке. У нас в названиях заглавная буква используется только в первом слове. То есть, например, название раздела Change Password переводится как Изменить пароль. Кроме того, внутри предложения названия элементов интерфейса используются в английском языке без кавычек, а в русском в кавычках. Например: "Go to Change Password" Перейдите в раздел "Изменить пароль".

Другой порядок слов. В английском языке порядок слов строго фиксирован: подлежащее-сказуемое-второстепенные члены предложения. В русском же языке порядок слов может варьироваться в зависимости от того, на чём вы хотите сделать смысловой акцент. Поэтому, чтобы перевод выглядел естественно, не переводим дословно, а думаем, какая часть фразы самая важная, и помещаем её в конец предложения. Например: The certificate cannot be issued Выпустить сертификат не удалось (при этом дословный перевод Сертификат не может быть выпущен звучит понятно, но не совсем по-русски.)

Больше о стилистических различиях английского и русского языков можно прочитать, например, в Microsoft Russian Style Guide.

Перевод документации для пользователей: "флажок" или "чекбокс"?

Документация для пользователей другая большая и важная часть контента, который мы переводим. Здесь уже с контекстом дело обстоит гораздо лучше, так как на перевод к нам приходят целые осмысленные куски текста: предложения и абзацы. Кроме того, доступ к англоязычной документации у нас есть практически всегда, так что мы можем прочитать всю главу на английском языке и, если что-то непонятно, задать вопрос техническим писателям. Однако и тут есть свои особенности.

Стиль надо быть проще

Техническая документация у многих ассоциируется с сухим канцелярским стилем и ГОСТами. Действительно, в русскоязычной документации долгое время был принят такой стиль (а в некоторых технических областях, например, в описании промышленного оборудования, он принят до сих пор). Что касается стиля документации в IT, в последние годы он, к счастью, становится всё более человеческим. Крупные IT компании в своих руководствах по стилю призывают писать более естественно и менее формально. Например, вот основные принципы Microsoft's brand voice:

  • Warm and relaxed (Дружелюбный и естественный)

  • Crisp and clear (Четкий и понятный)

  • Ready to lend a hand (Предлагающий помощь)

В Plesk мы пишем документацию в таком же дружелюбном и естественном стиле и сохраняем его при переводе. Избегаем канцелярских слов и оборотов, например:

  • Вместо данный лучше этот

  • Вместо выполнить удаление лучше удалить

  • Вместо в данный момент лучше сейчас

  • Такие слова как операция, процедура, действие в большинстве случаев можно опустить

Терминология как в UI

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

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

В интерфейсе тип резервной копии называется "Инкреметный".В интерфейсе тип резервной копии называется "Инкреметный".А в документации тот же тип был назван "Добавочным". А в документации тот же тип был назван "Добавочным".

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

Как назвать главы

Во всех гайдах ко всем продуктам мы используем одни и те же названия типовых глав. Благодаря этому документация становится более узнаваемой, и пользователям легче в ней ориентироваться. Например:

  • Getting Started Начало работы

  • About О <название продукта>

  • Appendix Приложение

  • Troubleshooting Решение проблем

  • FAQ Ответы на часто задаваемые вопросы

Лучше всего список типовых названий внести в руководство по стилю (Style guide) для соответствующего языка. Style guide для документации на исходном языке обычно пишут технические писатели, а вот составить аналогичные руководства для других языков задача переводчиков.

Как назвать элементы и действия

Ещё один момент, который стоит отразить в руководстве по стилю стандартный перевод названий самих элементов интерфейса и действий с ними. Вот несколько примеров переводов, которые мы используем:

  • check box флажок (а не чекбокс)

  • icon значок (а не иконка)

  • click нажать (а не кликнуть)

  • select the check box установите флажок (также возможен вариант выберите опцию)

  • go to перейдите в раздел

Вы можете выбрать и другие варианты перевода тех же терминов, так как однозначно правильного перевода, как правило, нет. Главное, чтобы на протяжении всей документации использовался один и тот же перевод.

Ориентироваться можно, например, на терминологию Microsoft или просто гуглить тот или иной термин, чтобы понять, какой перевод встречается чаще.

Перевод документации для разработчиков: "обработчик" или "хук"?

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

Нужно ли переводить?

Многие считают, что документацию для разработчиков вообще не нужно переводить, ведь она состоит в основном из примеров кода и понятна и так. Отчасти это справедливо, но всё же зависит от документа. Например, это верно для справочников по API или CLI у нас эти документы не переводятся. Но другой документ, Руководство по разработке расширений Plesk, мы всё же перевели на русский язык, и некоторые наши разработчики уже это оценили (хотя и удивились). Это руководство представляет собой по сути учебник по созданию расширений, и читают его как наши разработчики, так и сторонние (написать расширение для Plesk может любой желающий). В этом учебнике есть описания всех шагов работы с расширением, упражнения, примечания в общем, не только код, но и много полезного текста, читать который удобнее на своем родном языке.

Переводить нужно, но не всё

В документах для разработчиков есть части, которые ни в коем случае переводить не нужно:

  • Примеры кода (в них можно перевести только комментарии)

  • Названия функций, методов, переменных и т.д. в тексте

  • Названия команд и их аргументов

О том, какие части переводить не нужно, мы узнаём по разметке и подсветке, которую нам показывает программа переводов:

Названия метода и аргумента не переводятся.Названия метода и аргумента не переводятся.

Уточняем термины

Насколько мне известно, среди IT-переводчиков инженеры и разработчики встречаются довольно редко. И это нормально, так как для перевода обычно требуются другие умения и навыки. Но если вы IT-переводчик и переводите для разработчиков, нужно очень внимательно отнестись к терминам и переводить их так, как разработчики привыкли, даже если эти переводы кажутся сленговыми. Придумывая более литературные названия, мы порой только усложняем их понимание.

Поэтому я бы рекомендовала советоваться с разработчиками по поводу каждого термина, по которому есть сомнения. Можно спрашивать на специальных форумах или в группах соцсетей. Например, помню, что мне пришлось довольно долго искать адекватный перевод термина hook, и я советовалась в специальной группе Фейсбука и с разработчиками, и с переводчиками. Советы мне давали разные: были варианты перехватчик и обработчик, но всё же большинство разработчиков написали, что самым понятным переводом будет просто хук. На этом варианте я и остановилась.

Перевод маркетинговых текстов: "well give you peace of mind"

Маркетинговые тексты в чистом виде мы переводим нечасто. Но время от времени они встречаются нам прямо в интерфейсе: это описания наших платных функций и расширений (например, в Каталоге расширений Plesk можно выбрать и купить то или иное расширение). И этот тип контента стоит отметить отдельно, поскольку он заметно отличается по стилю от технического. Ведь его цель не столько объяснять, сколько продавать.

Эмоциональность это хорошо!

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

Маркетинговые тексты эмоциональны.Маркетинговые тексты эмоциональны.

Не переводим дословно

Дословный перевод маркетингового текста может выглядеть неестественно. Нужно настроиться на маркетинговый лад, поймать нужную идею и интонацию и передать её на своем языке своими словами, искренне и убедительно. Некоторые метафоры типа peace of mind вообще почти нереально перевести напрямую, и нужно тщательно выбирать наиболее уместные выражения. Скажу прямо, это достигается не сразу, и тут нужна практика. Могу порекомендовать искать похожие тексты на русском языке и ознакомиться с основами копирайтинга.

Проговариваем текст

Когда человек читает рекламу или другой маркетинговый текст, задействованы все каналы восприятия. Текст должен легко проговариваться, быть певучим, не содержать много шипящих и т.д. Поэтому после перевода проговариваем его вслух если он звучит приятно и легко, а язык ни обо что не запинается, значит мы на верном пути.

Выводы

Подводя итог, могу сформулировать такие общие рекомендации, основанные на моем опыте перевода:

  • Всегда нужно помнить о том, для кого написан текст. Отсюда выбираем необходимый стиль и подход. Например, для пользователей и разработчиков пишем по-разному.

  • Задаем вопросы специалистам и обращаемся к признанным руководствам по стилю. Например, к Microsoft Russian Style Guide.

  • Просматриваем переведенные тексты и интерфейс после публикации, чтобы убедиться, что в них нет ошибок. Например, неподходящих форм слова или расхождений в терминах.

  • Читаем как можно больше русскоязычных IT-текстов и набираем словарный и терминологический запас.

И еще я перечислила лишь основные, на мой взгляд, моменты по переводу каждого типа IT-контента. Если у вас есть желание узнать о каком-то из них поподробнее, пишите в комментариях!

Подробнее..

Как писать хорошую документацию

16.06.2021 06:09:59 | Автор: admin

Несколько лет назад я услышал от одного коллеги историю. Он в то время работал начальником отдела технической документации в IT компании. Дело было на собрании, посвященном знакомству с новым техническим директором. Тот, пожав моему коллеге руку и узнав о его роли, пошутил: Документация? Так ее же не читает никто! Двадцать первый век на дворе.

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

Возможно, что-то из того, что написано в моей статье, покажется вам капитанским. Ничего страшного! Это значит, что вы уже владеете лучшими практиками написания документации. Статья в первую очередь адресована людям, недавно пришедшим в профессию, поэтому, коллеги, если я что-то упустил, или если у вас есть свой взгляд на вещи пожалуйста, отпишитесь в комментариях.

Что такое хорошая документация?

Итак, начнем. Что же вообще такое хорошая документация? Подробная? Или написанная с юмором, чтобы было не скучно читать? Для кого-то самая лучшая документация толстый том, который можно подложить под ножку стола, чтобы не шатался. На мой взгляд, хорошая документация такая, которая выполняет свою задачу.

А в чем задача документации? Ответов на этот вопрос может быть много. Документация может использоваться для обучения, для справки, или даже служить своего рода рекламой. Я слышал от коллеги историю о том, как менеджер по продукту просил ее написать документацию для нового продукта за три дня, делая упор на том, что все равно какую, ее никто читать не будет, она нужна только чтобы проект сдать. И это тоже задача, хоть и очень грустная.

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

Хорошо, допустим. А что позволяет документации выполнять задачу? Какая она, хорошая документация, и как ее создавать? Есть ряд практик, которым мы следуем, когда пишем документацию в Plesk, и сегодня я хотел бы о них рассказать. Итак...

Хорошую документацию легко найти

Времена, когда лежащий в коробке с программой мануал был единственным источником информации для пользователя, ушли безвозвратно. В наши дни каждый имеет доступ к практически неограниченному количеству информации, и у технических писателей больше нет монополии на внимание пользователя. Как бы ни была хороша ваша документация, если она занимает низкую позицию в выдаче поисковых систем, ее просто никто не прочтет. Чтобы ваша документация приносила пользу, позаботьтесь о ее находимости (findability).

Более половины трафика нашего портала документации приходит из органического поиска. Вот как мы представляем себе сценарий, в результате которого пользователь (возможно) открывает нашу документацию:

  1. Человек начинает пользоваться Plesk.

  2. Человек сталкивается с затруднением.

  3. Человек пытается разобраться с затруднением самостоятельно.

  4. Когда желание преодолеть затруднение пересиливает нежелание тратить время на поиск помощи, человек вводит запрос в Google и открывает первую ссылку в выдаче.

Замечу, что по данным Google Search Console запросы пользователей не включают слово документация. Люди ищут plesk login, plesk install, plesk ftp и так далее. Скорее всего, запросы, по которым пользователи находят документацию вашего продукта, выглядят похоже. Чтобы пользователям было проще найти вашу документацию, важно использовать те термины и формулировки, которые они используют. Это особенно важно в случае если поисковая система на вашем сайте документации не очень хорошо производит нечеткий поиск.

Раз уж мы заговорили о находимости, я хотел бы также познакомить вас с терминами информационное фуражирование и информационный запах. Поведение человека, ищущего информацию, похоже на поведение зверя в поисках пищи. Зверь хочет получить максимум калорий, затратив минимум сил. Разыскивая пищу, зверь полагается на запах, который говорит ему, насколько велики шансы найти пропитание там, где он сейчас находится.

Так же и человек хочет получить максимально полезный и информативный ответ на вопрос, затратив минимум усилий и времени. Попадая на новую страницу в Интернете, человек пробегает по ней глазами в поиске свидетельств того, что здесь он сможет найти ответ на интересующий его вопрос. Ключевые слова, заголовки, ссылки, и так далее и формируют тот самый информационный запах. Компания Nielsen Norman Group провела исследование среди пользователей и выяснила, что если в течение первых десяти секунд посетитель не обнаруживает на странице сильный информационный запах, он скорее всего уйдет с нее и продолжит поиск в другом месте.

Как же привлечь внимание пользователя за те десять секунд, что у нас есть? Отличная практика разместить в самом начале каждого раздела краткое (не больше трех-четырех предложений) описание его содержания, в идеале оформив его так, чтобы оно визуально отличалось от остального текста и бросалось в глаза. Сюда же можно добавить ссылки на схожие по смыслу разделы, чтобы облегчить дальнейший поиск пользователям, оказавшимся не там, где они планировали. Вот как может выглядеть такое описание:

В этом разделе вы узнаете, как создать новый FTP аккаунт в Plesk. Если вы хотите узнать, как изменить логин или пароль существующего FTP аккаунта, пройдите по ссылке.

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

Хорошую документацию легко понять

Цель технического писателя не в том, чтобы впечатлить читателя богатым словарным запасом и способностью конструировать сложносочиненные предложения, а в том, чтобы максимально быстро передать читателю знания, необходимые ему для того, чтобы выполнить операцию, вызвавшую у него затруднение, закрыть документацию и продолжить заниматься своими делами.

В работе я руководствуюсь высказыванием Антуана де Сент-Экзюпери: Совершенство достигнуто не тогда, когда нечего добавить, а тогда, когда нечего убрать. Когда готов первый черновик документации для новой фичи, первое, на что я смотрю можно ли сделать текст проще и короче. Что помогает в этом?

  • Часто употребляемые слова. Избегайте канцелярита, не пишите произвести манипуляцию с элементом управления когда хотите сказать нажать кнопку.

  • Простые предложения.

  • Короткие (4-6 предложений) абзацы.

Впрочем, здесь же я хочу упомянуть и еще одно правило, которым руководствуюсь: Пиши так коротко, как возможно, но не короче. Не нужно выплескивать ребенка вместе с водой и приносить полноту и ясность в жертву краткости.

От одной коллеги я слышал о таком любопытном юзкейсе: в ее организации документацию пишут на английском языке, но клиенты пользуются ей по всему миру. Поэтому технические писатели намеренно используют максимально простой английский, чтобы встроенные в современные браузеры автоматические переводчики могли как можно более точно выполнить перевод. Таким образом, клиенты по всему миру могут читать документацию на родном языке, а организация не платит за перевод. Это было бы невозможно без осознанных усилий, направленных на то, чтобы сделать текст документации максимально простым и понятным.

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

Некоторое время назад я искал технического писателя в свою команду. В тестовом задании, предлагавшемся соискателям, была просьба написать короткую инструкцию, объясняющую, как установить расширение в Chrome. Один из кандидатов снабдил каждый шаг полноразмерным снимком экрана, что раздуло небольшую инструкцию на пару страниц. Чем это плохо? Напомню, что попадая на новую страницу, человек не начинает вдумчиво читать, он пробегается по ней глазами. Большой объем вкупе с обилием иллюстраций отпугивает, несложная процедура кажется чем-то сродни запуску ядерного реактора. Сложилось ощущение, что у соискателя были какие-то установки ("снимки экрана это хорошо"), но не было понимания, что любым инструментом нужно пользоваться к месту и в меру. Отбор он не прошел.

Хорошая документация описывает сценарии

Классический подход к документированию интерфейсов подразумевает последовательное описание индикаторов и элементов управления, размещенных на том или ином экране. Типичный пример снимок экрана с цифрами-выносками, а под ним нумерованный список, перечисляющий все, что пользователь и так видит. Введите имя пользователя в поле Имя пользователя. Нажмите Ok, когда захотите закончить операцию.

Проблема этого подхода в том, что он не отражает то, как люди пользуются документацией. Если когда-то и были времена, в которые человек, купив программу, внимательно читал от корки до корки лежащий в коробке мануал, они остались в прошлом. Никто не читает документацию, чтобы узнать, что делают все кнопки на экране Создать домен. Пользователи обращаются к документации, когда у них возникают затруднения с выполнением какого-то реального сценария, связанного с использованием продукта (создать почтовый ящик, защитить сайт SSL сертификатом, и так далее).

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

  • Пользователю приходится тратить время и усилия на то, чтобы сконструировать процедуру.

  • Сконструированная пользователем процедура может быть неполной или вовсе неверной.

  • Каждому пользователю приходится конструировать процедуру самостоятельно. Таким образом, чем больше у вас посетителей, тем больше времени они совместно потратят.

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

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

  • Как мне создать почтовый ящик?

  • Как мне поменять пароль?

  • Как мне удалить базу данных?

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

Хорошая документация самодостаточна

При написании документации в Plesk мы руководствуемся принципом Every page is page one (EPPO) почерпнутым из одноименной книги Марка Бейкера. Чтобы понять его суть, давайте подумаем о том, как люди читают печатные книги, и как ищут информацию в Интернете:

  • Человек, читающий печатную книгу, начинает чтение с первой страницы и читает последовательно, постепенно создавая контекст. В пятой главе нет нужды расшифровывать термин, с которым читатель познакомился во второй.

  • В случае с документацией в Интернете, любая страница может стать первой, так как пользователи приходят по ссылкам. Мы не можем контролировать то, где они окажутся, и мы не можем предполагать, что у них есть некий определенный контекст.

Таким образом, суть принципа EPPO можно выразить так: каждая страница документации в Интернете должна быть самодостаточной и содержать всю необходимую информацию или ссылки на нее.

Приведу пример. Некоторое время назад для того, чтобы защитить сайт SSL сертификатом, нужно было выполнить в панели Plesk следующие действия:

  1. Сгенерировать запрос на подпись сертификата (certificate signing request) и купить сертификат в центре сертификации (certificate authority).

  2. Загрузить полученный сертификат в хранилище.

  3. Выбрать загруженный сертификат в настройках веб сервера.

Номинально, каждый из приведенных выше пунктов можно рассматривать как отдельный сценарий, но подобный подход может ввести пользователя в заблуждение, так как для достижения цели (сайт защищен SSL сертификатом) нужно выполнить все вышеприведенные действия в правильной последовательности.

В согласии с принципом EPPO, нужно либо объединить все необходимые процедуры в один раздел, либо сделать несколько разделов, связав их ссылками. Например, в начале раздела, описывающего сценарий загрузить полученный сертификат в хранилище в Plesk нужно сослаться на раздел о сценарии сгенерировать в Plesk запрос на подпись сертификата, а в конце на раздел о том, как выбрать загруженный сертификат в настройках веб сервера. Благодаря этому, где бы посетитель ни оказался, он сможет сориентироваться, пройти сценарий от начала до конца и добиться желаемого результата.

Хорошая документация достоверна

Иными словами, она точно отражает то, как продукт выглядит и работает прямо сейчас, а не полгода назад. В наше время SaaS-продуктов, коротких релиз циклов и принудительных автоматических обновлений это правило, к сожалению, нарушается все чаще. Как ни странно, этим нередко грешит документация гигантов индустрии, таких как Microsoft или Google.

Думаю, не нужно объяснять, почему это вдвойне плохо, когда официальная документация содержит недостоверные сведения. Логотип компании на странице документации внушает уверенность, и посетитель тратит время попусту, пытаясь найти кнопку, которую убрали из интерфейса три релиза назад. Когда он понимает, что инструкции неверны, это действует как ушат холодной воды на голову и подрывает доверие и к документации, и к продукту, и к бренду. Единожды солгавший, кто тебе поверит?

Для того, чтобы подобного не происходило, команда технических писателей должна иметь следующее:

  • Выстроенные процессы, позволяющие получать информацию обо всех влияющих на опыт пользователя изменениях в продукте до того, как они станут доступны публике.

  • Достаточно ресурсов, чтобы своевременно отражать эти изменения в документации.

  • Механизм сбора обратной связи, который позволит получать сигналы о тех неточностях, которые закрались в документацию несмотря на два предыдущих пункта. В Plesk мы получаем такую обратную связь от инженеров технической поддержки, а также от самих пользователей благодаря нашей форме обратной связи.

Хорошая документация пишется для определенной аудитории

Еще одно явление, о котором нужно знать, чтобы писать хорошую документацию это проклятие знания (curse of knowledge). Под таким зловещим именем скрывается когнитивное искажение, заключающееся в том, что человеку информированному сложно встать на место человека неосведомленного и увидеть ситуацию его глазами. Если вы когда-нибудь произносили или думали про себя Ну-у, да это все знают, вероятно, вы были под воздействием этого искажения.

К счастью, с этим искажением можно справиться. Достаточно помнить о нем и знать, кто целевая аудитория документации, которую вы пишете, и каким багажом знаний обладает ее среднестатистический представитель. Например, если вы документируете клиент Git, можно предположить, что представителю целевой аудитории не нужно рассказывать, что такое система управления версиями или как сделать коммит, но стоит задокументировать, как настроить доступ в репозиторий по SSH ключу. А если у вас в голове возникает мысль Это, наверное, всем известно, напомните себе, что вы пишете документацию не для всех, а для конкретной аудитории с конкретными знаниями и потребностями.

Проиллюстрирую этот пункт следующим примером: несколько лет назад я получил обратную связь от двух разных пользователей на один и тот же раздел. Она звучала примерно так:

  • Пользователь А: Что вы пишете, как для дураков? Разжевываете вещи, которые любому известны!

  • Пользователь Б: Вы знаете, не каждый из нас гений. Пожалуйста, пишите яснее, мне ничего не понятно.

Как вы думаете, кто из них был прав? На самом деле, правы оба. Судя по всему, раздел, на который они жаловались, как раз и был написан для всех, но в итоге не смог сослужить службу никому. Он был слишком сложен для новичка, но не содержал подробностей, интересных эксперту. Как избежать подобных ситуаций? Знать, кто целевая аудитория, и писать с учетом ее потребностей. Ничего страшного, если вы получаете обратную связь только одного типа (слишком сложно или слишком просто) это означает, что жалуются люди, не входящие в ЦА (конечно, если подобных обращений не десять штук за неделю).

Хорошая документация оказывает поддержку

Один из верных признаков плохой документации она разжевывает очевидное, но не оказывает поддержки там, где это нужно. Не всегда достаточно просто перечислить шаги, которые необходимо пройти для достижения цели. Если в процессе того или иного сценария пользователю нужно сделать выбор, последствия которого не каждому могут быть очевидны, документация может и должна облегчить принятие решения, дав дополнительную информацию. Это называется "помощь в принятии решения" (decision support).

Приведу пример. В Plesk для защиты от спама используется программа под названием SpamAssassin. Одна из доступных пользователю настроек (spam filter sensitivity) управляет тем, насколько строго фильтр отсеивает входящие письма с подозрением на спам. Работает она просто: пользователь задает значение, выраженное положительным числом не больше 127. Чем меньше число, тем строже фильтр. Вот как могла бы быть описана эта настройка в плохой документации:

Введите желаемое число в поле Spam filter sensitivity и нажмите Ok.

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

Введите желаемое число (больше 0 и не больше 127) в поле Spam filter sensitivity и нажмите Ok. Чем меньше число, тем меньше вероятность того, что в ваш ящик попадет спам, и тем больше вероятность ложного срабатывания, и наоборот.

А можно ли сделать еще лучше? Как насчет такого:

Введите желаемое число (больше 0 и не больше 127) в поле Spam filter sensitivity и нажмите Ok. Чем меньше число, тем меньше вероятность того, что в ваш ящик попадет спам, и тем больше вероятность ложного срабатывания, и наоборот. Рекомендуемое значение 7, оно обеспечивает надежную защиты от спама с минимальной вероятностью ложного срабатывания и подойдет большинству пользователей.

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

Как еще можно облегчить жизнь пользователя? Не превращать его в Буриданова осла. Если продукт позволяет добиться того или иного результата несколькими путями, я не описываю их все. Я выбираю оптимальный (самый простой, самый быстрый и так далее) и рассказываю только о нем. Если же между этими путями есть разница (скажем, один быстрее, но подразумевает действия, требующие технических навыков или потенциально рискованные, например, выполнение запросов INSERT или UPDATE в базе данных), я описываю все варианты, эксплицитно указывая на различия между ними, чтобы помочь пользователю выбрать оптимальный для него вариант.

Ну и, конечно же, не забудьте предупредить пользователя в случае если его действия могут привести к неочевидным последствиям, особенно если они необратимы. Нет нужды писать о том, что удалить домен можно при помощи кнопки Удалить домен. Это очевидно. Что не очевидно, так это то, что при удалении домена, например, будут автоматически удалены и все резервные копии, или что пользователь лишится доступа в панель, если его учетная запись заблокирована. Налево пойдешь коня потеряешь куда полезнее и информативнее, чем просто поворот налево.

Заключение

Теперь вы знаете, как писать хорошую документацию по версии Plesk. Прежде чем откланяться, я хотел бы рассказать еще об одном принципе, который я также позаимствовал у Марка Бейкера. Он звучит просто Напиши одну хорошую страницу (Write one good page). Почему он кажется мне очень важным: если у вас уже есть массив документации, написанный по старинке и не соответствующий лучшим практикам, велик соблазн опустить руки. Переписать все с нуля это целый подвиг! У нас нет столько времени и ресурсов! Но это не обязательно.

Наверняка среди вашей документации есть более посещаемые разделы и менее посещаемые (а если вы не знаете, сколько посетителей читает вашу документацию, то это отличный повод настроить веб аналитику). Переработайте ваш самый посещаемый раздел. Проследите за реакцией пользователей. Сделайте выводы, внесите коррективы, возьмитесь за второй по популярности раздел. И, возможно, пожимая вам руку, новый технический директор скажет Документация? Это же очень важно! Загляну к вам в три часа, хочу узнать, как вы работаете.

Спасибо за внимание!

P.S. Хочу сказать Спасибо! моим коллегам Катерине Говердовской и Владимиру Головизнину за помощь в подготовке статьи.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru