Как прокачать свой open-source проект, используя бейджики качества кода

Думаю, каждый, кто ищет что-то на GitHub, время от времени встречает репозитории, в которых в файле README после названия проекта идет куча разных бейджиков. Они выполняют роль приборной панели для репозитория и показывают, насколько далеко с таким кодом можно заехать. Когда пытаешься разобраться в этом разнообразии бейджиков — наступает хаос. Какие сервисы мне нужны? Что они делают? Как их подключить? Где взять рабочий конфиг? Где взять код для бейджика? Несколько раз наступив на одни и те же грабли, я решил потратить немного времени, чтобы в этом разобраться.

Исследование

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

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

Continuous integration (CI)

Их задача — каждый раз после коммита или пулл-реквеста (зависит от того, как настроите) собрать проект из всех его вендоров. После чего выполнить тесты (модульные, функциональные). Можно добавить еще запуск разных утилит, скриптов. Успешной считается сборка, если в результате выполнения всех команд каждая завершилась с exit 0. Код, отличный от нуля, указывает на ошибку. Результат может быть либо «зеленым» — все ок. Либо «красным» — сборка не удалась.

Code Coverage

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

Анализаторы кода

Призваны проверять код на best practice. Проверка copy-paste, code style, анализ архитектуры кода, подсказки по замене одних конструкций на другие, рекомендации к стандартным практикам разработки и т.д.

Количество установок

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

Лицензия

В мире open source очень важно соблюдать авторские права (да и не только в мире open source!). Поэтому знать, на каких условиях вы используете чужой код очень важно. Определяться с лицензий можно непосредственно перед выбором сторонней библиотеки. Но если проект у вас уже готов, и вы вдруг вспомнили про лицензирование, тогда можно воспользоваться специальными сайтами, которые собирают информацию о лицензиях разных пакетов. Подключив свой репозиторий к такому сервису, вы также можете защитить свой код и помочь другим разработчикам, которые желают его использовать. В процессе исследования разных библиотек, размещенных на GitHub, несколько раз я видел issue, в котором автора просили добавить в репозиторий файл с лицензией, чтобы была возможность использовать его в коммерческом продукте.

Все остальное

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

Travis CI

Travis CI добавился в список инструментов опенсоурс-разработчиков и стал де-факто стандартом. Он завоевал свою популярность потому, что он бесплатный, он легко добавляется в GitHub, достаточно гибкий для настройки. Бесплатная версия обслуживает публичные репозитории, поэтому лог выполнения каждого билда доступен всем желающим. Есть и платные тарифные планы с большими ресурсами.

Прокачай свой код с помощью бейджиков!

Travis CI можно настроить таким образом, чтобы он совершал сборку проекта как после каждого коммита, так и только для пулл-реквестов. Он интегрирован в GitHub и показывает статус сборки возле каждого пулл-реквеста. Если сборка сломана, то можно отправить фикс со следующим коммитом, Travis перепроверит пулл-реквест, и он станет «зеленым».

Прокачай свой код с помощью бейджиков!

Прокачай свой код с помощью бейджиков!

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

Прокачай свой код с помощью бейджиков!

Чтоб подключить свой репозиторий к Travis CI, нужно:

  • Создать в корне проекта файл .travis.yml и прописать в нем необходимые настройки;
  • Залогиниться на Travis с помощью аккаунта с GitHub и подключить свой репозиторий к сервису.

Travis позволяет назначить команды на разные события: до начала сборки, до запуска скриптов, после выполнения скриптов, только после успешного выполнения скриптов и т.д. Начать знакомство с документаций можно с этой страницы http://docs.travis-ci.com/user/getting-started. Travis поддерживает множество языков программирования, и если для сборки вашего проекта необходима какая-то сторонняя утилита, то ее можно доустановить консольной командой во время каждой сборки. Минимальный пример файла .travis.yml для проекта на PHP может выглядеть вот так:

language: php

php:
  - 5.4
  - 5.5
  - 5.6

before_script:
  - composer install

script:
  - phpunit

notifications:
  email:
    - your@mail.com

Указываем, что используется language: php. Перечисляем версии, для которых нужно сделать сборку — для каждой запустится свой независимый процесс сборки. В секции before_script подготавливаем систему, в данном примере подтягиваем зависимости проекта через Composer. В секции script перечисляем все скрипты, которые выполняют проверку нашего проекта. В данном случае выполняются модульные тесты. Ну, и отсылаем уведомления на email по завершению сборки.

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

Бейджик Трэвиса бывает двух цветов, в зависимости от результата сборки.

Прокачай свой код с помощью бейджиков! Прокачай свой код с помощью бейджиков!

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

Честно говоря, сложно представить себе open source проект, который разрабатывался бы без Travis CI. На первый взгляд не увидишь ошибок, которые пришли в новом пулл-реквесте. Но если перед этим Travis CI прогнал все тесты, вы уже будете знать, в каком состоянии проект после внедрения новой фичи. Вывод — использовать Travis CI обязательно!

Scrutinizer

Scrutinizer — сервис предназначен для оценки качества кода. Пока Scrutinizer ограничен поддержкой PHP, Python и Ruby, планируется поддержка Java и Scala. Основные фичи этого сервиса:

  • Выставляет оценку вашему коду на основе показателей, собранных от разных анализаторов;
  • Сохраняет историю изменения качества кода, можно на графике посмотреть как развивался проект;
  • Сигнализирует о проблемах в вашем коде с объяснением, к чему это может привести. База знаний довольно широкая;
  • Также проверяет вендоры, которые используются в вашем проекте, на наличие известных security issue;
  • Настройка автоматических отчетов. Может срабатывать как на push или pull-request, также можно задать периодические автоматические сборки;
  • Сервис также интегрирован в GitHub и показывается в пулл-реквестах наряду с Travis (конечно же, после дополнительной настройки).

Прокачай свой код с помощью бейджиков!

Для каждого языка программирования существуют инструменты для анализа кода. Например, для PHP самые популярные — это:

  • PHP Code Similarity Analyzer
  • PHP Code Sniffer
  • PHP CS Fixer
  • PHP Mess Detector
  • PHP Analyzer
  • Security Advisory Checker

PHP Analyzer — мощный инструмент, вот список проверок, которые выполняет Scrutinizer https://scrutinizer-ci.com/docs/tools/php/php-analyzer/checks.

Достаточно некоторое время попользоваться этим сервисом и вы уже перестанете делать типичные ошибки, которые постоянно находит Scrutinizer в вашем коде. Чтобы начать пользоваться этим сервисом, во-первых, нужно на нем зарегистрироваться с помощью гитхаба. В личном кабинете подключить свой репозиторий с GitHub. Разместить в корне вашего репозитория файл .scrutinizer.yml. По умолчанию большинство утилиты уже подключено. Scrutinizer предлагает вам стартануть с таким конфигом, в него уже включен джентльменский набор анализаторов:

checks:
  php:
    code_rating: true
    duplication: true

filter:
  excluded_paths:
    - vendor/*

before_commands:
  - "composer install --prefer-source"

Для проектов на Symfony я подключаю дополнительно еще пару утилит, которые требуют явного включения:

checks:
  php:
    code_rating: true
    duplication: true

filter:
  excluded_paths:
    - vendor/*
    - app/*
    - bin/*
    - web/*
    - spec/*

before_commands:
  - "composer install --prefer-source"

tools:
  php_code_sniffer:
    config:
      standard: "PSR2"
  php_cs_fixer: true
  sensiolabs_security_checker: true

Сервис предоставляет три типа бейджиков. Но, по сути, значимым является только первый, который показывает оценку кода. Code coverage с помощью Scrutinizer я не советую вам делать, лучше использовать другой специализированный сервис (далее в статье). Код бейджика можно взять на странице репозитория в личном кабинете, нужно кликнуть по иконке (i). Так как Scrutinizer предназначен в первую очередь для open source, вы сможете просмотреть список замечаний к любому публичному репозиторию, который настроен на работу с этим сервисом.

Прокачай свой код с помощью бейджиков!

Очень рекомендую использовать Scrutinizer для open source разработки.

Packagist

Packagist — список библиотек/фреймворков PHP, которые могут быть установлены через менеджер пакетов Composer. Интересная для нас информация, которую предоставляет этот сервис — это количество установок и последняя стабильная версия пакета. Это все доступно на самом сайте, но было бы хорошо добавить эту информацию в свой репозиторий, чтоб на страничке репозитория в GitHub уже увидеть интересную статистику. Packagist не предоставляет своих бейджиков для этого. Бейджики можно взять на стороннем сервисе Badge Poser. Выбираем пакет и получаем код всех доступных бейджиков.

Прокачай свой код с помощью бейджиков!

Какие именно бейджики вы хотите добавить для отображения — ваше дело. Зачастую выставляют бейджики: общее количество установок, последняя стабильная версия и лицензия. Лицензия определяется из файла composer.json либо из файла LICENSE. Мой совет всегда добавлять три перечисленных бейджика, они несут самую полезную информацию.

VersionEye

Сервис VersionEye предоставляет возможность следить за версиями библиотек, размещенных на гитхабе. На самом деле можно подключить и приватные репозитории с гитхаба, и работать через API. Сейчас сервис поддерживает следующие языки программирования: Java, Ruby, Python, Node.JS, PHP, JavaScript, Objective-C, R, Clojure.

Вариантов использования сервиса два. Можно зарегистрироваться на этом сайте, найти репозитории, которые вас интересуют, и зафоловить их. После выхода новых версий вам будут приходить оповещения на email. Так вы будете следить за обновлениями нужных вам библиотек. Мой опыт показывает, что от этого сайта уведомление приходят раньше, чем от официальных источников. Например, о выходе новой версии PHP я узнаю еще до того, как новость появляется на php.net. Также на этот сервис можно добавить свой публичный репозиторий. Это даст вам возможность следить за тем, как обновляются библиотеки и фреймворки, от которых зависит ваш код.

Объясню на примере PHP. Чтобы ваш репозиторий мониторился с помощью VersionEye, в корне вашего проекта должен быть файл composer.json. Если это не библиотека или бандл, а, например веб-приложение — в большинстве случаев в репозиторий также попадает файл composer.lock, в котором замораживаются версии используемых библиотек. VersionEye на основе этих двух файлов проанализирует ваши зависимости, сопоставит версии, которые используете вы, с актуальными версиями, и покажет вам всю статистику. А также будет уведомлять каждый раз, когда в вашем проекте обновляются внешние библиотеки. Зачем это нужно? Ну, например, в зависимостях в composer.json вы указали "symfony/symfony": "~2.5", что означает, что ваш код должен работать с Symfony 2.5, 2.6, 2.7 и т.д. но не с 3.0 и выше. Когда выходит новая минорная версия, вам, конечно, может быть все равно, до тех пор, пока вы не получите issue на гитхабе, что с новой версией ваш бандл перестал работать. Ну, а если вы альтруист, то подсуетитесь, проверите ваш код на совместимость с новой версией, подправите, что надо, и зарелизите фикс. Пользователи будут счастливы, даже сами того не зная.

Также если вы проганяете тесты через Travis, то можно добавить конфиги для тестирования на новой версии Symfony, от которой зависит ваш код. Проверка проектов на других языках также осуществляется через менеджеры пакетов. Поддерживаются: Composer, Bundler, PIP, NPM, Bower, Leiningen, CocoaPods, Maven, SBT, Gradle. Еще одна фича этого сервиса — он позволяет посмотреть, сколько других репозиториев указали ваш в качестве зависимости. Главное, чтоб они тоже были добавлены в VersionEye. Разве вам не интересно, кто и где использует ваш код? Вот пример из странички Symfony версии 2.6.4.

Прокачай свой код с помощью бейджиков!

По клику на References можно увидеть список проектов, которые зависят от Symfony. Этот сервис предоставляет два бейджика (привожу бейджики для Symfony):

Прокачай свой код с помощью бейджиков!

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

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

CodeCov

CodeCov — сервис, который предоставляет красивые отчеты по покрытию вашего кода тестами. Чтоб работать с этим сервисом, нужно немного изменить конфиги в файле .travis.yml. Вот как может выглядеть конфиг:

language: php

php:
  - 5.4
  - 5.5
  - 5.6

before_install:
  - sudo pip install codecov

before_script:
  - composer install --dev

script:
  - phpunit --coverage-clover=coverage.xml

after_success:
  - codecov

Добавляются секции before_install и after_success, а PHPUnit нужно запустить с параметром --coverage-clover=coverage.xml. После прогонки Travis CI с обновленным конфигом должно пройти некоторое время, пока отчет появится в вашем аккаунте на CodeCov. На странице просмотра статистики вашего репозитория в пункте меню Features можно найти код для бейджика, сам он выглядит так:

Прокачай свой код с помощью бейджиков!

Еще одна прикольная фича CodeCov — это интерактивный граф коммитов с показателем code coverage каждого:

Прокачай свой код с помощью бейджиков!

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

Coveralls

Coveralls — сервис, аналогичный предыдущему. Чтоб его использовать, нужно добавить в сomposer.json:

{
    "require-dev": {
        "satooshi/php-coveralls": "dev-master"
    }
}

и изменить конфиг .travis.yml:

language: php

php:
  - 5.4
  - 5.5
  - 5.6

before_script:
  - composer install --dev

script:
  - phpunit --coverage-clover build/logs/clover.xml

after_script:
  - php vendor/bin/coveralls -v 

PHPUnit нужно запустить с опцией --coverage-clover build/logs/clover.xml, и указать в after_script, что после его выполнения нужно выполнить скрипт coveralls, который передаст файл отчета на сервер Coveralls. Перед этим также не забудьте в своем дашборде в Coveralls подключить ваш репозиторий с гитхаба.

Мое личное мнение, что в целом этот сервис красивее показывает отчеты по code coverage. Не вижу смысла использовать Coveralls и CodeCov одновременно, можете попробовать оба и выбрать по вкусу.

Gitter

Сервис Gitter недавно запустился и представляет собой чат для GitHub. Для каждого репозитория на гитхабе можно создать отдельный публичный чат. Вещь хорошая, ведь не всё и не всегда хочется обговаривать через пулл-реквесты. Иногда хочется поофтопить ^_^ или задать вопрос большому количеству человек и получить быстрый ответ. Ограничение бесплатной версии в том, что история сообщений будет хранится максимум две недели, и можно создать только один приватный чат на организацию, созданную в GitHub. Бейдж выглядит так:

Прокачай свой код с помощью бейджиков!

А найти его код можно на страничке канала:

Прокачай свой код с помощью бейджиков!

Прокачай свой код с помощью бейджиков!

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

CoderWall

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

Прокачай свой код с помощью бейджиков!

Для того, чтоб получить бейдж, нужно добавить свой навык в профиль, например: php, open source. Главное правильно написать название технологии, если сомневаетесь — посмотрите профили других участников, как написано у них. Далее раз в неделю (информация с сайта) сервис сопоставляет ваши навыки с профиля с вашей деятельностью на гитхабе. Если вы указали навык PHP и у вас есть репозиторий на гитхабе, в котором основной язык программирования — это PHP, тогда вы получите бейджик «паук». За три PHP-репозитория — вы получите бейдж «тройной паук». Но эти бейджики пока что будут видны только на страничке вашего профиля в CoderWall. Чтоб они были видны на GitHub, нужно подключить свой GitHub-аккаунт в профиль CoderWall. Через некоторое время CoderWall пригласит вас в свою организацию, и вы получите бейдж ни гитхабе. Вот пример бейджиков с моего профиля.

Прокачай свой код с помощью бейджиков!

Кому интересно - исходный код CoderWall доступен на GitHub, сам сайт написан на Ruby. Вот пример профиля команды GitHub.

SensioLabs Insight

Очень люблю компанию SensioLabs за то, что она разрабатывает полезные вещи для мира PHP. SensioLabs Insight — еще один сервис для анализа кода, но только PHP. Точнее не только PHP, там есть возможность указания, что именно находится в вашем репозитории: Symfony-бандл, Symfony-проект, модуль для Drupal и т.д.

Прокачай свой код с помощью бейджиков!

В зависимости от типа репозитория, Insight дополнительно проверит конфиги в XML и YAML файлы, Twig шаблоны, зависимости композера.

Список проблем, которые проверяет SensioLabs Insight просто внушительный. И синтаксические ошибки, и инструкции, которые могут сделать ваш код небезопасным, и использование версий библиотек, в которых есть известная уязвимость, и еще куча-куча всего. Всего делается больше сотни различных проверок. В результате проверок ваш код может получить медаль за отвагу!!! Если бы код был живим существом, то он бы поблагодарил своего создателя :)

Прокачай свой код с помощью бейджиков!

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

Прокачай свой код с помощью бейджиков! Прокачай свой код с помощью бейджиков! Прокачай свой код с помощью бейджиков!

Получить код для любого вашего репозитория, подключенного к SensioLabs Insight, можно на странице вашего аккаунта. Также можно настроить автоматическую проверку ваших репозиториев на гитхабе через web-hook. Адрес, который должен дернуть гитхаб, чтоб запустить очередную проверку, берется на странице API/SDK вашего аккаунта. После чего заходите в настройки вашего репозитория на гитхабе в меню Webhooks & Services и создаете новый хук.

Прокачай свой код с помощью бейджиков!

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

KnpBundles

Если вы Symfony-разработчик, то конечно вы знаете о сайте knpbundles.com. На этом сайте собраны популярные бандлы для Symfony2. Если вы разработали бандл и хотите, чтоб он там появился, то вам придется сделать это самостоятельно. Залогиниться с помощью гитхаба и добавить ссылку на ваш репозиторий. Т.е. если вы не хотите публиковать свой бандл на сайте, то он там не появиться! На этом сайте существует система рейтинга. Оценка для бандла считается так:

  • 1 балл за каждого фоловера на гитхабе;
  • 5 баллов за README файл, если в нем больше чем 300 символов;
  • 5 баллов если бандл подключен к Travis CI;
  • Еще 5 баллов дается за последний успешный билд на Travis CI;
  • 5 баллов, если в бандле есть файл composer.json и репозиторий добавлен на packagist.org;
  • 5 баллов за каждую рекомендацию бандла на сайте knpbundles.com (рекомендовать могут только зарегистрированные пользователи сайта).
  • Бонус за активность последние 30 дней. Формула (30 — количество дней с последней активности) / 5. Минусовые значения не считают, но могут быть дробные значения.

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

Сайт предоставляет два вида бейджиков (их код можно найти на странице бандла в сайдбаре). Для примера возьмем самый популярный бандл FOSUserBundle и его варианты бейджиков:

Прокачай свой код с помощью бейджиков!

Мои рекомендации: однозначно добавлять свой бандл на этот сайт и вставлять код бейджика. Ведь если вы его выставили в open source, значит хотите, чтоб им пользовались. Расскажите о нем сообществу!

HHVM

Если вы хотите проверить свой код на совместимость с HHVM, вам нужно добавить несколько строк в .travis.yml это можно сделать вот так:

language: php

php:
  - 5.3
  - 5.4
  - 5.5
  - 5.6
  - hhvm

matrix:
  allow_failures:
    - php: hhvm

before_script:
  - composer install --dev

script:
  - phpunit --coverage-text tests

Нужно добавить --hhvm в версии PHP. Если ваш код не может выполнится на HHVM, то сброка будет помечена, как провалившаяся. Если вы хотите просто мониторить совместимость с HHVM, но при этом не фейлить билд, то нужно добавить опцию allow_failures. Бейджик, который будет показывать поддержку HHVM, можно взять на сайте http://hhvm.h4cc.de/.

Прокачай свой код с помощью бейджиков!

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

Shields.io

Shields.io — сайт, на котором бейджики от разных сервисов приведены к одному стандартному виду. Список довольно большой, тут собраны самые популярные сервисы для разных языков программирования. Я недавно только узнал о таком сборнике, и он мне сразу понравился. Есть три шаблона бейджиков:

Shields.io badges

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

Было:

Прокачай свой код с помощью бейджиков!

Стало

Прокачай свой код с помощью бейджиков!

Чтоб получить код в формате Markdown, нужно кликнуть на бейдже из списка. Единственный минус, что прописывать путь к своему репозиторию на нужном сервисе придется самому. Бывает, нужно просто указать ник и название репозитория. А бывает, вместо этого нужно указать хеш-код, например, https://img.shields.io/sensiolabs/i/45afb680-d4e6-4e66-93ea-bcfa79eb8a87.svg. В таком случае нужно идти в личный кабинет и там искать...

Заключение

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

Об авторе

Back-end разработчик
Артем работает с PHP с 2010 года и участвовал в разработке MeinFernbus. На ты с фреймворком Symfony2 и 3. Вносит вклад в развитие open source.

Похожие статьи

Вернуться к списку записей К списку записей