30 апр. 2014 г.

Стамбул день 1



 Удалось выбраться в Стамбул на выходные. Поездку планировали давно, но до последнего момента (политическую обстановку в стране - все знают) - было все под вопросом. Вообщем - слетали. Под катом немного текста и чуток фото, в самом конце поста - ссылка на весь альбом + гео на фото.

3 февр. 2014 г.

MemcacheDB и логи

Сегодня дошли руки до memcachedb. Оказывается - логи растут там бешено 8(. У меня было 26Гб логов.
Немного погуглив - нашел решение, коннектимся телнетом и выполняем комманду db_archive.
После этого папка с данными не превышает 30Мб.

Автоматизируем это дело:
Создаем файл:
[root@server3 ~]# cat /opt/memcachedb/bin/db_archive 
db_archive
quit
[root@server3 ~]# 
Запихнем в крон это дело:
0 * * * * /usr/bin/telnet 127.0.0.1 11211 < db_archive > /dev/null 2> /dev/null

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

7 февр. 2013 г.

Создание maven web проекта

Описывать буду, как создать WEB проект в Eclipse, с установленным m2e. В качестве контейнера будет служить нам tomcat.
Статья написана для тех кто впервые работает с мавеном, кому лень гуглить, и хочет быстро создать простой web проект с помощью maven'а...

12 авг. 2012 г.

Поездка в Волгоград

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

Интересные данные:
Монумент «Родина-Мать Зовет» – одна из самых высоких статуй в мире (85 метров) – входит в состав историко-мемориального комплекса «Героям Сталинградской битвы» на Мамаевом Кургане. К ней ведут 200 ступеней – именно столько дней длилась Сталинградская битва.

15 мар. 2012 г.

ubuntu + vim и стрелки управления

При использовании бубунты, возникла "проблемка", я везде привык пользоваться vi редактором, но в бубунте по какой-то причине, после чистой установки - не работает управление стрелочками...
Немного погуглив решение нашлось быстро:
sudo apt-get install vim

28 февр. 2012 г.

Если долго подключаетесь по SSH

Давно столкнулся с проблемой, на некоторые сервера по ssh подключаюсь быстро (счет на миллисекунды), на другие сервера - долго, до 10 секунд бывает... решил все таки потратить время, и погуглить в чем собственно проблема.

Итак, в итоге у Вас может быть 2 проблемы:

Проблема на сервере
Проблема в том что сервак долго резолвит IP того, кто подключается. Правим /etc/ssh/sshd_config:
UseDNS no


Проблема в клиенте
Вторая проблема в GSS-API, его можно отключить, создаем если нету файл ~/.ssh/config:
GSSAPIAuthentication no

Как говорится - радуемся... ;)

9 дек. 2011 г.

советы тем кто подрастает

Хотел называть “крик души”, но потом в конце написания поста, решил изменить название на “советы тем кто подрастает”.

В общем есть у меня знакомый, который около двух месяцев назад, попросил поревьювить их код. Код не замысловатый, молодой проект, так что посмотреть все это дело не заняло много времени... Замечания в основном были по архитектуре, о том как код упростить, ну и как сторонник TDD, естественно был у меня главный вопрос - “а где тесты?”.
Естественно о TDD они слышали. В просторах сети читали, вроде бы даже смотрели видео, якобы даже пробовали использовать, но как это применить на конкретно ихнем примере - тут уже сложнее. У меня ушло около недели (это где-то 3-4 часа моего времени), за которое я внес изменение в их базовые классы и естественно написал базовые тесты, так сказать на примере показать, что есть TDD. В качестве напутствия приложил файлик с книгой “Мартин Р. - Чистый код. Создание, анализ и рефакторинг”.

Результат - сегодня на почте я нашел письмо, с примерным содержанием “переделали, посмотри, мы растем, ждем ответ”, полез смотреть... начал писать ответ в письме, но вместо этого решил написать заметку в блог, что бы и другие не наступали на эти грабли.
Повторяю, прошло около двух месяцев, за это время проект не сдвинулся со своего места... т.е. целая команда, полностью перестала развивать проект, они остановили всю разработку ради того что бы внедрить TDD и переписать код, причем код проекта, который еще не запущен - смысл?
Совет 1: Любые нововведения не должны останавливать процесс разработки продукта, Ваша задача делать продукт, а не код. Как бы нам не хотелось сделать все по уму, этого не получится, любой код должен эволюционировать, старые куски должны переписываться (это не сомненно). Код который Вы сейчас пишите, используя все Ваши знания, через некоторое время, для Вас покажется устаревшим, и возникнет желание переписать. Но тогда у нас будет не разработка и улучшение конкретного продукта, а улучшение кода. А кому кроме программиста этот код нужен? Хорошо написанный код может доставить эстетическое удовольствие только тому программисту, который его написал, т.к. для других он будет либо слишком тривиален, либо слишком сложным. Единственное что волнует заказчика/начальника/клиента - код работает согласно требованию.

Едем дальше. Начал просматривать тесты, беглый осмотр и очередная ошибка, её сотню раз обсуждали, во всех статьях это описано, но почему-то многие эту ошибку допускают.
например (пример утрированный):
package ua.lg.moon;
public class MyClass {
 public static int sum(int a, int b){
  return a+b;
 }
 public static int diff(int a, int b){
  return a-b;
 }
}
package ua.lg.moon;
import static org.junit.Assert.*;
import org.junit.Test;
public class MyClassTest {
 @Test
 public void testSum() {
  assertEquals(4, MyClass.sum(2, 2));
  assertEquals(6, MyClass.sum(4, 2));
 }
 @Test
 public void testDiff() {
  assertEquals(MyClass.sum(2, 2), MyClass.diff(6, 2));
  assertEquals(MyClass.sum(4, 2), MyClass.diff(10, 4));
 }
}
Вопрос на засыпку: что мы получим, когда у нас в методе sum будет ошибка?
Ответ: Мы получим 2 не рабочих теста. Это не проблема, когда у нас один класс и два метода-теста, а возьмем реальную систему, где в сотнях, а иногда даже тысячах классов-тестов есть по более десятка методов. И кто-то допускает ошибку в коде, аналогичному методу sum, который используется для сравнения, или предполагается что он “уже проверен и работает”. Результат у нас куча провалившихся тестов.
Совет 2: Каждый тест должен проверять только свою часть. Он не должен зависеть от тех классов которые проверяются в других тестах и которые могут работать не верно. В коде который я ревьювил, я сделал специально ошибку, в классе который получает игрока (в поле игрока, его номер всегда возвращался 1), я получил 80% не рабочих тестов, и если бы я эту ошибку не допустил специально, то найти что ж в коде пошло не так - это уже проблема. Т.е. если мы проверяем в тесте “игровую доску”, и классу “доски”, что бы тест прошел нам нужно передать двух игроков - их лучше создать с нужными параметрами, а не использовать общее хранилище для получения - т.к. при проверке доски мы будем зависеть от работоспособности хранилища пользователей (не важно виртуальное оно или реально). А при поломке хранилища пользователей - у нас так же не проходит тест по “игровой доске” и все остальные тесты.

Совет 3: Называйте тесты так, что бы из названия сразу было видно - что этот метод проверяет. Когда падает тест test32 - “expected:<...> but was:<...>”, то в любом случае придется “заходить” в тест, хорошо если в нем есть комментарии, намного удобнее писать имя теста так - что бы было понятно что он проверяет. Хотя бы так: testPlayerBoardNotNull - уже большинству будет понятно, что этот тест проверял. А вообще есть много способов, некоторые пишут should, или expect и т.д. - тут уже дело каждого, как Вы будете именовать Ваши тесты, сам факт в том - что бы если тест упал - можно было как можно быстрее понять - что упало.

Совет 4: Прочесть книгу “Совершенный код. С. Макконел”. Не важно на каком языке Вы пишете, к любому языку можно отнести то что там написано. Вроде бы код работает, но с первого раза глядя на функцию, понять что он делает - практически не реально, благо хотя бы многие функции имеют описание и достаточно в IDE на функцию навести мышь - что бы узнать “что она делает”. Перечислять постулаты книги смысла нету, так что по коду это извечная проблема многих команд. Прочесть и понять.

Совет 5: Предполагайте, что ваш “движок” может поменяться. Практически все системы что я видел очень сильно связаны с конкретной базой данных, либо некой внешней библиотекой, пример будет про хранение. Обычно после того как людям рассказываешь базовые вещи по архитектуре, для чего все таки нужны абстрактные классы, интерфейсы, как применить это в TDD, то через время у них получается примерно следующее. Есть некий абстрактный класс, например Players у которого есть методы list, get, add, edit и т.д... а затем у них есть PlayersImplMemory и PlayersImplMySql
Соответственно первый хранит все в хешмапе и используется для тестов, а второй уже в промо. Люди которые вроде бы знают что такое “дублирование кода”, сами же его допускают, в обоих классах у них в методе add идет валидация входных данных. Соответственно если я проверяю в тесте валидацию или получение для Memory модели, это не значит что это будет “справедливо” для MySql модели. Более логично - создать класс который будет иметь в себе валидацию, все что общее, например Players, а использовать уже абстрактный класс или интерфейс для хранения, например PlayerStorage. Storage - принимает “сырые данные” и надеется что они будут “правильными” и сохранять их уже в конкретной ситуации либо в памяти, либо в конкретной БД или в шарде, тут уже можно в любой момент поменять направление.

Ну и на последок, самое главное: ваша программа должна быть как конструктор. Каждый кубик - это класс/интерфейс, и если смотреть “сверху” - все должно сводится к “передал параметры”, “получил результат”... если Вы сначала подумаете о том, какие у Вас будут входные параметры, и какие результаты Вы хотите получить, то реализовать это уже вопрос времени. Любую даже самую казалось бы сложную и громоздкую задачу, можно описать нормально и реализовать. Как пример: мне нужно было в уже существующей системе переделать отчеты. В БД лежат данные, в варианте “до меня” был класс и метод, у которого порядка 5-10 параметров передавалось на вход, на выходе String. Нужно генерировать 3-4 типа отчетов и каждый из них должен быть либо в HTML либо в том же HTML но для печати...
В том классе который существовал, там было порядка 4-5 методов приватных, в среднем класс был на 300-400 строк. Тот кто писал - постарался, повыносил все дубликаты формирования в методы и т.д... но меня не устроило - то что в одном месте были собраны как логика получения - так и логика формирования...
После моей переделки у меня получился 1 абстрактный класс TableDataSource, который умел формировать данные из БД, собрать три листа, для thead, body и tfoot. И соответственно под каждый отчет был написан свой наследник, и что бы не запоминать их имена, я создал еще “фабрику”, где были методы getMonthReport, getYearReport и т.д. Соответственно так же у меня получился 1 абстрактный класс TableRender, который в качестве параметра принимал TableDataSource и возвращал String. И уже два наследника TableRenderHtml, TableRenderPrintHtml. После чего добавление нужного отчета сводилось к созданию нового TableDataSource.

В общем как-то так...