Monday, May 11, 2015

Шаги для установки redmine на ubuntu (14.04)


# Установка пакетов сервера HTTP apache2
sudo apt-get install apache2 libapache2-mod-fastcgi libapache2-mod-passenger

# При необходимости поменять дефолтный порт с 80 на подходящий, например 8088
sudo vim /etc/apache2/ports.conf

# Установка пакетов redmine
sudo apt-get install redmine redmine-sqlite redmine-apache

# Конфигурируем рубя в апаче
sudo vim /etc/apache2/mods-available/passenger.conf

[Содержимое passenger.conf]
  <IfModule mod_passenger.c>
    PassengerDefaultUser www-data
    PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
    PassengerDefaultRuby /usr/bin/ruby

  </IfModule>
# Линкуем ссылку для apache из рута на redmine (приложение будет доступно по адресу  http://yohost:port/redmine) 
sudo ln -s /usr/share/redmine/public /var/www/html/redmine
# Конфигурируем базовый путь для рубя CGI
sudo vim /etc/apache2/sites-available/000-default.conf

[Что добавил в 000-default.conf]
   RailsBaseURI /redmine
   PassengerResolveSymlinksInDocumentRoot on


# Открываем доступ к файлам из веб
sudo chown -R www-data /usr/share/redmine

# Конфигурируем метод оповещения
sudo vim /etc/redmine/default/configuration.yml

[configuration.yml]

production:
    email_delivery:
         delivery_method: :sendmail

default:
    email_delivery:
         delivery_method: :sendmail


# Перезапуск апач сервиса
sudo service apache2 restart


# Также если потребуется перезапуск redmine 
sudo -u www-data touch /usr/share/redmine/tmp/restart.txt

Tuesday, July 26, 2011

ubuntu server 11.04

играюсь с ubuntu server 11.04, конспектирую некоторые действия:

1. обновить/переконфигурировать установленные локали: sudo dpkg-reconfigure locales
2. установить новую локаль: sudo ./install-language-pack ru_RU
3. посмотреть/изменить текущую локаль: /etc/default/locale
4. замонтировать (с поддержкой русского языка) внешний диск, с FAT32: sudo mount -t vfat -o codepage=1251,iocharset=utf8 /dev/sdb1 tmp

5. посмотреть название текущей ос: /etc/issue
6. отменить таймаут для ssh-терминалов: /etc/ssh/ssh_config, добавить строку, если нет: KeepAlive yes
7. посмотреть, кто залогинен на машине в данный момент: who
8. изменение настроек vim (создаем файл настроек ./exrc)

cd
echo 'set tabstop=2' > .exrc
echo 'set shiftwidth=2' >> .exrc

Sunday, April 10, 2011

О безразмерном анализе модели

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

Tuesday, February 8, 2011

Оценка максимального абсолютного значения функции

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

Пример получения максимального абсолютного значения функции на отрезке [t0, T]:

(Вообще эта оценка используется для построения класса ограниченных на заданном отрезке [t0, T] функций)

Thursday, January 27, 2011

100 лет IBM

16-го июня будет 100 лет со дня основания IBM, хотя тогда компания называлась Computing Tabulating Recording Corporation.

Краткий исторический экскурс:

IBM Centennial Film: They Were There - People who changed the way the world works

IBM Centennial Film: 100 X 100 - A century of achievements that have changed the world

Включение поддержки HTTPS для Tomcat (v6.0)

В принципе ничего сложно в этом, нет, но как всегда пришлось немного повозиться.
[шаг 1] Первым делом я предлагаю перевести логгинг в режим отладки. Для этого в файле logging.properties (находится в ${CATALINA_HOME}/conf или если его там нет, то нужно создать этот файл и поместить в classpath, или добавить, например, в WEB-INF/) нужно установить консольный логгинг в отладку:

java.util.logging.ConsoleHandler.level = DEBUG
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

[шаг 2] Далее нужно сгенерировать ключи, это делается с помощью keytool, которая обычно входит в JDK:

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

По умолчанию файл ключей кладется в ${user.home} . Для того, чтобы сгенерировать ключи в заданный файл: \a\path\a\keystore, то это можно сделать так:

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA \
-keystore \a\path\a\keystore

Keytool запросит пароль (пишут, что по умолчанию Tomcat использует changeit, но мне пришлось задавать его явно в описателе коннектора), запросит ФИО издателя ключей, отдел, компанию и т.д.
[шаг 3] Правим server.xml, который обычно находится в ${CATALINA_HOME}/conf. Нужно раскомментировать описание для SSL HTTP/1.1 Connector и добавить туда соотв. атрибуты:

<connector
port="8443"
maxthreads="150"
algorithm="SunX509"
scheme="https"
secure="true"
sslenabled="true"
keystorepass="changeit" clientauth="false"
keystorefile="${user.home}/.keystore"
sslprotocol="TLS">
</connector>

Расположение файла с ключами и пароль пришлось задавать явно. Алгоритм можно не задавать. Замечу, что для Oracle/Sun JVM алгоритм будет SunX509. Для IBM JVM значение скорее всего будет IbmX509. Как следствие, сгенерированные ключи могут быть не совместимы. Так ключи, сгенерированные с помощью Oracle/Sun JVM, у меня не сработали для IBM JVM.

Если все ок, то https://localhost:8443 должно привести к открытию страницы приветствия Tomcat. Если уже есть какие-то приложения, то ничего менять не надо. Они должны также запускаться под https по 8443 порту.

Примечание: если менять серверные настройки в eclipse, нужно убедиться, что файл настроек в рабочей области действительно синхронизирован с файлом на диске. Иначе все изменения в рабочей области никак не скажутся на работе сервера.

Подробнее можно посмотреть здесь и здесь.

Tuesday, January 18, 2011

Выбор ORM.

Так получилось, что рано или поздно нужно использовать persistence, что привело к необходимости искать подходящую ORM-технологию. PM предложил использовать openJPA. Но, думаю, будет полезно разместить здесь небольшой обзор существующих ORM-решений. Скорее всего буду возвращаться к этому посту и периодически обновлять его.

1. Чистый SQL. Есть люди, которые утверждают, что никакой ORM не нужен, что чистый SQL работает намного быстрее. На мой взгляд, утверждение весьма спорное в силу того, что:
a) не у всех есть достаточный опыт в SQL для разработки устойчивых, масштабируемых систем.
b) ряд ORM технологий допускают native - запросы к базам.
c) ряд ORM технологий инкапсулируют многочисленные native настройки, а также возможность эти самые native настройки менять напрямую.
d) в ряде случаев, опять-таки если не знать некоторые тонкие настройки производительность будет даже хуже, чем при использовании ORM-решения.

2. Hibernate: пишут, что это де-факто стандарт. Хорошая документация. Есть порт для .NET. Пока не проверял, но пишут, что Hibernate одно из наилучших в плане производительности решений. Опыт работы с Hibernate часто является ключевым требованием при приеме на работу. Распостраняется согласно LGPL.

3. Apache openJPA. Открытая реализация JPA стандарта от Apache. На удивление хорошая и своевременная документация. Есть много примеров.

4. Apache iBatis. Вообще не имеет ничего общего со стандартом JPA. Хороший выбор для фанатов SQL.

5. Apache Cayenne. Еще одно JPA-решение. Пока не выяснил, в чем принципиальное отличие от openJPA.

Линки по теме:
1. Сравнение Hibernate, OpenJPA и EclipseLink.
2. Stackoverflow тред по теме.

Tuesday, November 2, 2010

Редактор UML-диаграмм

В плане соотношения простоты и удобства понравился редактор диаграмм Dia (http://live.gnome.org/Dia, LGPL), есть порты под Linux, Win, OSX. Проект активно развивается, пока UML поддерживается в довольно упрощенном варианте: но в целом можно изобразить диаграммы последовательностей (хотя время жизни объекта редактируется не оч. удобно: используются 2 параметра - частота точек привязки и расстояние между ними), диаграммы развертывания, static-диаграммы, диаграммы пакетов и т.д. Поддерживает скриптинг на python, что тоже делает редактор любопытным для меня, так как это возможно понадобится для написания различного рода reverse-инструментов. Dia использует свой переносимый формат (пока глюков при переносе обнаружено не было).

Sunday, August 29, 2010

Softncoffee goes mobile

Поставил себе на кпк moBlog блоггинг-клиент. Собственно это первый пост с него. По эргономике moBlog оказался вполне приемлемым. Все что потребовалось: в настройках создать профиль, выбрать блоггинг сервис из списка, задать свои логин и пароль.

Friday, August 27, 2010

Ликбез по Linux за август

Короткое резюме за август.

1. подключение общих папок под Oracle Virtual Box:

Win32 guest: net use x:\\vboxsvr\host_shared_dir

Linux guest: sudo mount -t vboxsf host_shared_dir guest_mount_point

2. монтирование IMG-файла:

sudo mount -o loop linux-0.2.img mount_point

3. ssh: для работы потребуется openssh-client и openssh-server. Соотв. на target-машине должен быть поднят openssh-server.

ssh user@11.22.33.44 - наиболее простой вариант залогиниться в target- машину.
sftp user@11.22.33.44 - удобный ftp-client поверх ssl.

4. быстрый способ получить данные по некоторому url с помощью python:

tim@epsilon:~$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> data = urllib.urlopen("http://google.com").read()
>>> print "Read data: %s"%(data)


Отличная книга по python, к тому же бесплатная - здесь.

5. получение софтовых пакетов установленных на машину:

RHEL: rpm -qa
Ubuntu: dpkg-query -l
AIX: lslpp -L all

6. grep - очень мощный инструмент для поиска и фильтрации нужной информации:

получить все строки файла somewhere, в которых содержится aword:
grep aword somewhere.txt

пример: получить все пакеты, которые имеют в названии слово python:
dpkg-query --show | grep python


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

7. общие команды:

получение справки по команде, например для rpm: man rpm
удаление каталога рекурсивно, без подтверждения: rm -r -f your_dir
создание нового каталога: mkdir your_dir
перемещение/переименование файлов: mv source target
соединение файлов с их послед. выводом в стандартный поток: cat file1 file2 file3, можно использовать для вывода одного файла, в частности: cat file1

Friday, August 6, 2010

Знакомьтесь, антипаттерн double-checked locking

На днях размышлял, как можно было бы ускорить следующую конструкцию:
Конструкция 1. Известная всем реализация ленивого синглтона.

public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static synchronized Singleton getInstance()
{
if (INSTANCE == null)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
return INSTANCE;
}
}

Основным недостатком является наличие synchronized, которое по-хорошему нужно
только при инициализации экземпляра объекта singleton, а не при каждом доступе к нему.
Таким образом, сразу же напрашивается мысль, а что если попробовать использовать критическую секцию только при инициализации объекта:
Конструкция 2. Первая попытка сделать короче время доступа к INSTANCE.

public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static Singleton getInstance()
{
if (INSTANCE == null)
{
synchronized(Singleton.class)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
}
return INSTANCE;
}
}

Теперь инициализация объекта будет происходить при первом доступе к объекту, но, к сожалению, данная конструкция не спасает от конкурентного доступа. Так как может получиться так, что конкурирующие процессы после проверки INSTANCE на null последовательно войдут в критическую секцию и проинициализируют Singleton несколько раз. Тут же придумал workaround: поставить проверку на null после входа в критическую секцию, сказано - сделано:
Конструкция 3. Вторая попытка или double-checked locking антиппатерн.
public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static Singleton getInstance()
{
if (INSTANCE == null)
{
synchronized(Singleton.class)
{
if (INSTANCE == null)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
}
}
return INSTANCE;
}
}

Полученная конструкция в теории должна работать, но так ли это? Довольный своим открытием, я решил посмотреть, что пишут эксперты о такой конструкции, есть ли какие-то другие, более эффективные варианты ускорения реализации паттерна singleton. Очень быстро обнаружил, что такая конструкция действительно используется и называется она double-checked locking (в некоторых источниках такую конструкцию называют даже антипаттерном [2]). Действительно она применяется для ускорения singleton, но имеет ряд неочевидных недостатков для некоторых языков.

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

Недостаток второй. Запись и чтение значений переменных в многопоточных программах на некоторых языках могут зависеть от реализации конкретной исполняющей среды/компилятора. Например, в JAVA используется кеширование переменных: из соображений эффективности каждый поток может хранить свою собственную приватную копию переменной. Эта копия может синхронизироватся с основной памятью в различные моменты, например, при входе в критическую секцию и при выходе из нее [3]. Как вариант, в Java можно использовать модификатор volatile для переменной INSTANCE, которое действительно гарантирует атомарный доступ к переменной. В таком случае переменная никогда не кешируется потоками и доступ к ней осуществляется, как если бы это происходило внутри критической секции (synchronize над этой переменной). Но по сути это приводит к тому же от, чего уходили - к наличию критической секции при доступе к переменной.

Таким образом, рекомендуется использовать конструкцию 1 [2], либо использовать факт о ленивой загрузке классов [1]: т.е. что сам класс Singleton будет загружен лишь при первом обращении к нему, соотв. будут проинициализированны все static-поля и секции:
Конструкция 4. Если быть проще...
public class Singleton
{
private static Singleton INSTANCE = new Singleton();

static
{
// further INSTANCE initialization
}

private Singleton()
{
// Singleton initialization
}

public static Singleton getInstance()
{
return INSTANCE;
}
}


Материалы.

[1] http://www.ibm.com/developerworks/java/library/j-dcl.html
[2] http://www.javamex.com/tutorials/double_checked_locking_fixing.shtml
[3] http://www.javamex.com/tutorials/synchronization_concurrency_synchronized1.shtml

Thursday, July 22, 2010

Переменные среды в Linux

Установка некоторых переменных среды через консоль:

export JAVA_HOME=/path/to/java/jdk1.6.0_20
export PATH=$JAVA_HOME:$PATH

export M2_HOME=/path/to/java/maven
export M2=$M2_HOME/bin
export PATH=$M2:$PATH

export используется, если задается глобальная переменная. Если переменная локальная (т.е. только для данного процесса), то export не требуется.
Посмотреть значение переменной можно, например, так:

echo $PATH

Кстати, в отличие от Windows, в PATH элементы разделяются двоеточием, а не точкой с запятой.
Для того, чтобы переменные среды устанавливались при загрузке пользовательского профайла рекомендуется использовать ~/.pam_environment для того, чтобы добавить туда скрипт с заданием переменных. Общие рекомендации по установке persistent environment variables можно узнать, набрав в консоли man pam_env, либо здесь.

Как оказалось, ~/.pam_environment не является скриптовым файлом, а представляет собой лишь список переменных среды. К тому же, у меня не получилось переопределить PATH, используя упомянутый файл. Такое переопределение приводило к тому, что в машину вообще нельзя было залогиниться. Пришлось войти в консольном режиме и с помощью vim удалять строки в ~/.pam_environment, отвечающие за переопределение PATH.

В конце концов, я взял и добавил нужные строки для определения переменных среды в ~/.profile. Сработало.

Tuesday, July 13, 2010

Использование system properties в eclipse.ini

Понадобилась небольшая кастомизация eclipse.ini.
Потребовалось уметь создавать свои параметры из eclipse.ini и уметь читать их внутри eclipse. Первый поиск практически ничего не дал конкретного по eclipse, но нашелся другой, более общий варинт: использование системных свойств (system properties) java. Системное свойство можно определить через eclipse.ini в качестве аргумента java-машины, например:

...
-vmargs
-Dfile.encoding=UTF-8
-Dosgi.requiredJavaVersion=1.5
-DMyCustomProperty=aPropertyValue
-Xms256m
...

Теперь в коде можно получить значение свойства MyCustomProperty следующим образом:

String value = System.getProperty("MyCustomProperty");

Friday, July 9, 2010

Создание архивов с помощью VBS

Есть, на мой взгляд, красивый способ создания архивов с помощью VB-скрипта, который хочу выложить (автор скрипта не я, но в своих скриптах использую эту рутину оч. активно). Грубо, идея в том, чтобы создать файл пустого архива, а потом в него добавить средствами Shell файлики.


';===================================
';
'; Simple zipping routine:
';
'; source is folder path to be zipped (recursive zip)
'; dest is file path for output zip archive
';
'; the main idea comes from here:
';
'; http://www.codecomments.com/archive299-2006-2-295877.html
'; http://forum.script-coding.info/viewtopic.php?id=1020
';
';===================================
sub zip(source, dest)
'
' wait operation delay
'
const dt = 1000
Set fso = CreateObject("Scripting.FileSystemObject")
Set ShellApp = CreateObject("Shell.Application")

With fso.CreateTextFile(dest, True)
.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, Chr(0))
.Close
End With

ShellApp.NameSpace(dest).CopyHere source

WScript.Sleep dt
'
' waiting for acrhive creation
'
On Error Resume Next
Do
fso.OpenTextFile dest, 1, False
If Err.Number = 0 Then Exit Do
Err.Clear
WScript.Sleep dt
Loop
end sub

Wednesday, July 7, 2010

Некоторые скриптинговые рутины на VBS

Давно хотел выложить код на VBScript, который я использовал в скрипте для публикации проекта (под публикацией понималось выкладывание сборки в базу данных Lotus Notes и рассылка уведомлений по списку).

Работа с Lotus Notes в vbs:

sub run()
' получить сессию (COM-объект, соотв. важно,
' чтобы объект был зарегистрирован в Win-реестре)
Set nSession = CreateObject("Notes.NotesSession")
' получить базу
Set db = nSession.GetDatabase(STORAGE_DATABASE_SRV,STORAGE_DATABASE_PATH)
if not db is nothing then
' какая-то работа с базой
'...
'...
end if
' освобождеине COM-объекта
nSession = null
end sub



Сниппет с приаттачиванием файлов к документу:


const EMBED_ATTACHMENT = 1454
';================================================
';
'; Simple file attach routine
';
'; @param doc is Notes Document
'; @param itemName is RTF item name
'; @param path is path to the file to be attached
';================================================
sub attach(doc, itemName, path)
Set item = doc.getFirstItem(itemName)
if not item is nothing then
call doc.removeItem(itemName)
end if
Set rti = doc.CreateRichTextItem(ItemName)
Set object = rti.EmbedObject(EMBED_ATTACHMENT, "", path)
end sub

Запуск bin-файлов в Linux

Вот уже несколько дней живу под Ubuntu, после WinXP немного непривычно.
Скачал brand new гелиос, скачал jdk. Поставить jdk оказалось довольно просто, достаточно было только bin-файлу, в котором лежит установщик jdk присвоить атрибут x (exetuable). После WinXP для меня это было не очевидно.

Вот сниппет, где я разрешаю выполнение bin-файла, после чего я его запускаю на выполнение:

tim@epsilon:~/works/downloads$ sudo chmod +x jdk-6u20-linux-i586.bin
tim@epsilon:~/works/downloads$ ./jdk-6u20-linux-i586.bin


Было забавно запускать установку jdk через консоль, так как пришлось долго и нудно проматывать лицензионное соглашение, прочитав которое, я должен был вбить заветное yes в ответ на запрос "Do you agree to the above license terms? [yes or no]".

Tuesday, July 6, 2010

Настройка прокси для SVN клиента

При подключении через svn к внешнему репозиторию получил сообщение "could not connect to server (http://eclipse.gwf.svn.sourceforge)". Задал прокси в настройках клиента - все заработало.

Шаблон для задания параметров в win-реестре:


Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Tigris.org\Subversion\Servers\global]
"http-proxy-host"="abcproxy"
"http-proxy-password"="pwrd"
"http-proxy-port"="8080"
"http-proxy-username"="ABCCORP\\usr"


Существует еще ряд других способов настройки конфигурации svn-клиента, о которых
можно подробно почитать в документации, гл. 7:

Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato: Version Control with Subversion For Subversion 1.5, Chapter 7. Customizing Your Subversion Experience

Tuesday, June 29, 2010

Перегрузка equals в Java

На днях проходил собеседование в одной компании, на котором попался вопрос про перегрузку equals в Java. Оказалось, что я был не в курсе довольно элементарного, в то же время важного правила: перегрузил equals - перегрузи и hashCode. В переводе это сводится к след. набору простых правил:
  • R1. если класс перегружает equals, то класс должен перегрузить и hashCode
  • R2. когда оба equals и hashCode перегружены, они должны использовать одинаковый набор свойств класса
  • R3. если оба объекта equals, то и значения их hashCode должны совпадать
  • R4. если объект не изменяется то hashCode является первым кандидатом на ленивую инициализацию и кеширование
  • R5. существует известное заблуждение, что hashCode предоставляет уникальный идентификатор для каждого объекта. Это не так.

На stackoverflow.com нашел алгоритм для вычисления hashCode, который считается наиболее эффективным (могу только предположить, что он дает более или менее равномерный разброс значений). Почти для всех классов приемлимо разумной является реализация, предложенная в 8-м разделе книги Джоша Блоха "Эффективная Java". Также эта реализация хороша тем, что автор в своей книге приводит объяснение почему данный подход приемлем.

Сам подход описывается следующим набором правил:

A1. Создать переменную result целого типа и присвоить ей ненулевое значение.
A2. Для каждого поля, которое используется при сравнении в equals, хеш-код k вычисляется след.образом:
  • если поле f имеет тип boolean, то исп.: k = f? 0:1;
  • если поле f имеет тип byte, short или int: k=(int)f;
  • если поле f имеет тип long, то: k = (int)(f ^ (f >>> 32)), где >>> - беззнаковый сдвиг;
  • если поле f имеет тип float, то: k = Float.floatToIntBits(f);
  • если поле f имеет тип double, то: Double.floatToIntBits(f), а полученное значение уже обрабатывается как long;
  • если поле f - объект, используйте в качестве результата его k = hashCode(), если f == null, то k = 0;
  • если поле f - массив, то рассматривается каждый объект как отдельный элемент и хеш вычисляется рекурсивно с комбинированием значений так, как показано в A3.
A3. Вычислить результат с использованием полученного значения k:

result = 37 * result + k;

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

Thursday, May 20, 2010

Использование скриптинга для выполнения рутинных операций. Первые шаги.

Прочитав книгу Эндрю Ханта и Дэвида Томаса "Программист-прагматик", я на какой-то момент стал одержим идеей использования скриптинга и использованием его в рутинных операциях. Как всегда пока сильно не хватает времени, чтобы взять и разобраться с maven, но было сильное желание быстро сделать что-то работающее. Сборка проекта начала занимать слишком много ценного времени, помимо того, нужно эту сборку закачать в базу данных, а также сделать "снимок" среды окружения проекта (например, дизайн бд, которая используется моей программой) и разослать всем заинтересованным лицам почтовые приглашения. Сначала я написал простой батник, который выполнял нужные процедуры по перемещению файлов и запускал NSIS. Позже получилось написать vbs скрипт, который делает все остальное.
Напишу о том, что было использовано в этом батнике.
На листинге1 пример организации цикла по набору, получаемому при вызове команды
dir, которая использует параметр /AD для того, чтобы получить только список каталогов и параметр /B, который нужен для того, чтобы выводились только имена файлов и ничего лишнего. Далее вызывается код по метке :dosub, в вызов которой передается значение переменной цикла %%а. При выполнении всего цикла скрипт завершает свою работу (команда exit).

Листинг 1. Пример цикла, который получает список папок по шаблону пути "releases\cobra_*"

for /f %%a in ('dir /AD /B releases\cobra_*') do (call :dosub %%a)
exit /B
:dosub
set release=%1
... некоторый скрипт, использующий переменную release


Команды, который использовались в скрипте:

rmdir /S /Q anydir - использовал для удаления иерархии папок без подтверждения, для того, чтобы очистить каталог, в котором происходит сборка от старых и посторонних файлов.

md - создание каталога
xcopy - копирование файлов, причем xcopy в моем случае просто необходимо, так как с помощью команды xcopy можно копировать целые каталоги с подкаталогами, в отличие от
copy. Параметры:
-D:m-d-y копировать файлы новее указанной даты,
если дата не указана, то копироваться будут более новые файлы.
-E - копировать все папки и подпапки, включая пустые.
-С - продолжить, даже, если произошла ошибка
-R - перезаписывать все файлы
-K - копировать атрибуты файла (просто xcopy сбрасывает признак "read only")
-Y - подавлять запросы о перезаписи существующий файлов

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

rem
rem =============================
rem copy project files
rem =============================
rem
xcopy %inputDir%\cobra.ini %outputDir%
xcopy %inputDir%\artifacts.ini %outputDir%
xcopy %inputDir%\cobra.exe %outputDir%
md %outputDir%\plugins
xcopy %inputDir%\plugins %outputDir%\plugins /D /E /C /R /I /K /Y
md %outputDir%\p2
xcopy %inputDir%\p2 %outputDir%\p2 /D /E /C /R /I /K /Y
md %outputDir%\configuration
xcopy %inputDir%\configuration %outputDir%\configuration /D /E /C /R /I /K /Y


И вот пример вызова NSIS сборщика с использованием lzma-сжатия:

"c:\program files\nsis\makensis.exe" /X"SetCompressor /FINAL lzma" %installerDir%\intpc.installer.nsi

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

CScript -S _publish.vbs D:\projects\bpm\releases\%release%.exe
rmdir releases\%release% /S /Q

Какое-то время не знал, как сделать процесс сборки, так чтобы запустив экспорт rcp приложения, не нужно было дожидаться этой мучительно долгой процедуры, чтобы потом запустить батник, который отвечал за окончательную компоновку проекта. Оказалось, что можно подключить батник как внешний инструмент и запускать сразу же после запуска процедуры экспорта. Процедура экспорта rcp блокирует выполнение всех операций, до тех пор пока она не выполнится, а следовательно вызов внешнего инструмента сработает сразу после этой процедуры. Таким образом, при сборке я теперь экономлю около 30 минут, которые можно потратить на что-то действительно нужное и интересное. Хотя, конечно пока далеко до автоматических ночных сборок с запуском серий регрессионных тестов и интеграции с нормальной системой версионирования кода.

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

Monday, May 17, 2010

Весенняя школа ГУ-ВШЭ 2010 (продолжение)

Попробую вспомнить, что было дальше...

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

После обеда опять все общались, после чего началось case study, которым рулил Байрам. Бай перечислил основные принципы работы в команде:
1. А как ты это делаешь? Проверка исходных предпосылок.
2. Не зная вопроса, нельзя обсуждать что-либо. По этой теме сильно запомнился ролик Comedy Club "Что? Где? Когда?".
3. Не позволяйте проблемам накапливаться. Должна быть постоянная обратная связь.

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

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

Феномен 3. Опасение конформизма (характерно для новичков и неопытных членов группы). Люди опасаются противостоять сложившимся в команде взглядам. Для устранения феномена работают методы обезличивания: тайное голосование, planning poker, узнаются или метод Сурова: сначала узнаются мнения младших по статусу.

Феномен 4. Усиление групповых решений и суждений в результате дискуссий. Вообще, если о дискуссиях, то Байрам рекомендовал проводить definition dump, чтобы убедиться, в том, что под одними и теми же терминами подразумевается одни и те же значения (критерии и критериальные эквиваленты терминами НЛП), а также метод шести шляп.

Литература по психологии в командах, которую нам рекомендовали:
1. Chris Argyris "Organizational learning" (Double Loop Learn)
2. Рей Иммельман "Boss, Great Boss Dead Boss"
3. Скотт Беркун "Искусство управления IT-проектами"
4. Питер Друкер "Эффективный управляющий"
5. Том Демарко "Роман об управлении проектами"
6. Девид Майерс "Социальная психология"
7. Роберт Чалдини "Психология влияния"

После case study проводился практический тренниг. Нам раздали диалоги, по которым надо было поставить диагноз, определить - что не так? За тренингом нам немного поведали об элементах повседневной психологии: хорошие и плохие игры, кривые печали, вампиризм и как не стать его жертвой. Рассматривались наиболее частые паттерны, такие как:
1. не знаю, как это сделать...
2. обезьяна на спине..
3. Если бы не ты, то...

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

1. Эрик Берн "Игры, в которые играют люди"
2. Эдвард Йордан "Путь камикадзе"
3. Майстер Девид "Советник, которому доверяют"
4. Леннарт Дальгрен "Вопреки абсурду: как я покорял Россию, а она - меня" (впечатления о России директора российской IKEA)