Часто, при роботі над великими проектами, виникає необхідність злити зміни від кількох людей в один файл. Як правило, якщо зміни робилися в різних частинах файлу, з цим проблем нема. Але часто виникають проблеми, коли незалежні зміни зачіпають один і той же ж шматок. Для прикладу, двоє програмістів додали у кінець файлу по новому методу класу. Система контролю версій побачить тут конфлікт, який не зможе розв’язати автоматично.
Така сама проблема виникає, коли потрібно внести зміни у версію, яка значно відрізняється від тієї, для якої була зроблена латка. Великі зсуви у номерах рядків заплутують СКВ.
Але програмісти, як правило, успішно розв’язують такі конфлікти в багатьох випадках. Вони читають латки по іншому, ніж це робить СКВ. Наприклад, там де система бачить тільки вставки нових рядків, програміст прочитає «доданий новий метод X до класу Y», або «додано виклик методу X в тілі методу Y у класі Z».
Було б добре, якби якась програмна система змогла скомпілювати обидві версії коду а потім, проаналізуваши код, видала звіт по змінам в програмному інтерфейсі і у графі викликів.
Тобто потрібна програмa «api-diff», яка зможе видати різницю між двома версіями програми на рівні змін у API а не лише на рівні змін у рядках коду. Тобто замість +/-, програма має видати коротке резюме: напр. «Додано: клас X, метод Y у класі Z. Видалено: тег F у файлі foo.xml. Змінено: методи A і B у класі C.» для змін у API (це легко, див. JDiff напр.), та/або «Додано: виклик foo з методу bar у класі Baz. Видалено: виклик foob з методу barb у класі Bazb».
PS.
Ще було б добре мати «api-patch», яка зможе спробувати накласти латку, створену «api-diff» та звичайним diff, на програмний код.
Вирішив перейменувати те що я називав "Літературним" програмуванням в "Документарне" програмування, так як воно ближче відповідає суті: результатом роботи програміста повинен бути зрозумілий людині документ, на основі якого в автоматичному режимі і створюється програма.
Як я пам’ятаю, раніше документація на програму, як правило, йшла в паперовій формі, тому було очевидним розділення: паперові носії для документації, яку ніхто не читає, і електронні носії для програмного коду.
Зараз, мені не здається таке розділення коду та документації нормальним. Всі давно згодилися, що, напр., для генерації сторінок якогось тексту чи розмітки часто краще за все використовувати шаблон — тобто пуста сторінка з вбудованими шматками коду. Чому такий підхід не застосовувати для документації?
Напр., гарно задокументований конфігураційний файл чи конфігураційна форма вважається нормою, а програмний код часто поставляється взагалі без будь-якої документації. І не тому, що її не було, просто документація залишилася за межами коду — в системі керування проектом, в поштових повідомленнях, в журналах чатів, на дошках у кімнаті нарад, у звітах тестувальників, у коментарях комітів у системі контролю версій, і т.д.
Зараз мови програмування просто не розраховані на нормальну роботу з документацією в програмному коді. Потрібно все поставити з ніг на голову — документація повинна стояти на першому місці, а програмний код повинен виводитися з неї.
Програма повинна бути і дошкою заявок, і системою обміну повідомленнями, і дошкою для презентацій, і системою контролю версій.
Коротко нагадаю про що взагалі мова: мені не подобається, що в сучасних мовах програмування треба
Моя ідея полягає в тому, щоб з’єднати між собою документацію по коду (коментарі, довідка) і сам код в єдине ціле. На відміну від літературного програмування Дональда Кнута, який вважав що програма має бути складена так, щоб можна було згенерувати книгу по програмі, я вважаю що документація має бути складена так, щоб можна було згенерувати програму по документації.
Найпростіший приклад документації, який ілюструє ідею, по програмі з кодом, який збирає і виконує програму по документації:
#!/bin/bash
FILES=( `grep -Eo 'див\. "[^"]+"' "$0" | cut -d '"' -f 2` )
# Create all files, which are mentioned in the documentation
#touch "${FILES[@]}"
# Output all files, which are mentioned in the documentation
#cat "${FILES[@]}"
for FILE in "${FILES[@]}"
do
source "$FILE" || {
echo "ERROR: Non-zero exit code from \"$FILE\": $?." >&2
exit 1
}
done
exit 0
Програма складається з таких основних компонент:
* початок, див. "00-begin.sh";
* визначення змінних, див. "10-variables.sh";
* розбір параметрів командного рядка, див. "20-options.sh";
* основний код, див. "50-main.sh";
* завершення програми, див. "90-end.sh";
Це так би мовити програмування на виворіт, коли документація не вважається непотрібом а є невід’ємною частиною програми. Ніякого спеціального синтаксису при цьому не використовується, використовується звичайна мова. Це завдання програми, а не програміста, перевести документацію у виконуваний код.
Я вирішив відмовитися від ідеї коли кожен файл в системі є "коробкою". Виходить не простіше а складніше, якщо все робити тільки через "коробки". Наскільки я бачу, в реальному житті, коли пишуть документацію, такий підхід, коли кожна окрема деталь документації лежить у окремому файлі, використовують надзвичайно рідко, хоча був випадок коли для одного великого проекту створили дуже ефективну систему документації на основі подібного підходу.
Для прикладу, візьмемо документацію по параметрам комадного рядка для якоїсь програми:
foobar [OPTIONS] [FILE]... Options: --help, -h Display this help screen. --man Display manual. --foo, -f Doo foo.
Класти кожен окремий параметр у окремий файл, тим більше класти назву параметра у один файл а опис у інший — не розумно з точки зору затрат людських зусиль, хоча і значно спростить автоматичну кодогенерацію і перевикористання коду. Краще покласти це завдання на автоматичну експертну систему, яка розбере опис параметрів командного рядка і зробить набір фактів/коробок, придатний для автоматичної обробки.
Перевикористання коду, як правило, роблять таким чином:
foobar [OPTIONS] [FILE]... Options: STANDARD_OPTIONS_DESCRIPTION --foo, -f Doo foo. Where: * STANDARD OPTIONS DESCRIPTION - list of standard options described in [this document: xttp://foo.bar/baz]
Я думаю, що такий підхід найбільш зручний для написання документації і, відповідно, для написання програм.
Вирішив зв’язати свій ноутбук (Acer Aspire 5315) з Андроїдом по WiFi. Реалізувати це не складно: поставив hostapd, дозволив форвардування пакетів в /etc/sysctl.conf, прописав статичну адресу для wlan0 (запускайте system-config-network під англійською локаллю, там якісь глюки з перекладом — в конфіги пишеться "Авто" замість "Auto").
Все працює чудово, але лише після перезавантаження. Після відновлення зі сплячки, зв’язок кудись зникає. Лампочка на ноуті не світиться, Менеджер Мереж не дружить з hostapd і не показує наявність вайфаю взагалі. Як це вирішити — не знаю до сих пір. :-( Видно потрібно якось дозволити використання вайфаю після відновлення зі сплячки, і це не "ifup wlan0". Після якогось шаманства з мережею і "iw" зв’язок часом встановлюється, але яка саме команда це робить ("iw dev wlan0 scan"?) — сказати важко. :-/
I prepare example how to implement integration testing of web application using maven/testng/htmlunit/Tomcat6. See example application in attachment. Unarchive it then use <code>mvn verify</code> to test project.
I also plan to implement parallel headless execution of Selenium test cases using HTMLUnit and adapter.
Приповз мій Андроїд: HTC G1 з прошивкою версії 1.6. Місяць повз пріоритетною поштою і ще хтось відкривав коробку на пошті — напевно вкрасти хотіли але побачили що екран битий. :-)
Тепер буду розбиратися з розробкою під Андроїд. :-)
Більшість слів, які ми вживаємо, є просто мнемоніками для якихось предметів чи явищ чи навіть цілих класів таких предметів таких явищ. Зв’язок між словом і об’єктом приблизно такий самий як між назвою змінної та її значенням.
Існуючі системи розпізнавання звичайної мови намагалися по тексту створити модель, яку описує цей текст. Це приблизно те саме, як по тексту програми пробувати написати текст бібліотек, яку ця програма використовує. Так, частково це вдається — я сам таки займався коли потрібної бібліотеки не було. Але в загальному, такий підхід не правильний.
В загальному випадку, треба розуміти різницю між мітками/тегами/мнемоніками/іменами і конкретними значеннями. Звичайна мова оперує мнемоніками. Імперативні мови програмування можуть оперувати і мнемоніками і реальними об’єктами. Наприклад, шматок пам’яті — це реальний об’єкт. Назва вказівника на шматок пам’яті — це мнемоніка для програміста, щоб не забутися, що саме він туди поклав.
Декларативні мови програмування оперують мнемоніками. Наприклад тег <h1> — це мнемоніка. Як саме він буде представлений в пам’яті програми — невідомо.
Тепер є питання — чим саме має оперувати літературна мова програмування?
Факти є реальними об’єктами (файлами, шматками коду).
Назви фактів та зв’язки між фактами є мнемоніками.
В програмі можна використовувати як факти (об’єкти) так і посилання на інші факти(мнемоніки).
Посилання (залежності) можуть бути як однозначними, так і вказувати на цілий клас фактів (будь-яка версія foo не менша за 2.5, напр.).
Слова звичайної мови відповідають посиланням у літературній мові програмування. Для того, щоб з усієї множини доступних фактів, які мають однакову мнемоніки, відібрати тільки той, який підходить, потрібно накладати обмеження, напр. обмежувати по номеру версії чи по якомусь іншому тегу факта. Для того, щоб не вказувати ці обмеження кожен раз, їх потрібно виносити за межі програми у певний словник. Наприклад у мавені, назви артефактів та їх версії вказуються у pom.xml — мавен сам знає як їх знайти і під’єднати.
PS.
Lisp, Prolog, apt, maven, rpm, ... — всюди є частини того, що мені потрібно. Чому ще досі ніхто не додумався згрести все це до купи? Наприклад мавен значно прискорив розробку програм на Яві, але заодно і зробив декілька великих кроків у сторону.
Ніби потрібен зовсім невеликий крок — замість одноразових шаблонів зробити систему, яка може як і генерувати код так і ВИДАЛЯТИ його, але чомусь до них не доходить. Системи контролю версій дозволяють відкочувати зміни, але не підтримують ЗАЛЕЖНОСТЕЙ і змінних шляхів. І т.д. Ніби все є, а автоматизувати не можливо. :-(
Сьогодні приїхали відеокуляри (за три дні зі Штатів добралися найдешевшою поштою :-/ ), цього разу в повному складі. Я зміг спробувати прототип свого тренажеру — портативна бездротова камера + портативний приймач + окуляри або програвач відео + окуляри.
Якість зображення в першому варіанті просто жахлива після подвійного перекодування, але тренуватися досить зручно. Залишилося купити ще декілька залізяк і замінити вибувші з ладу (з двох моїх недавно куплених бездротових адаптерів згоріли обидва), а також долатати MLT...
Є такий чудовий фреймворк: MLT (Media Lovin' Toolkit). Він підтримує практично все що мені потрібно для роботи з камерою, але мою камеру не підтримує ffmpeg. :-( Точніше ffmpeg підтримує мою камеру, якщо запускати його так:
LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so ffmpeg -f video4linux -s 320x240 -r 15 -i /dev/video0 -f avi -y tvffmpeg.avi
або так:
LD_PRELOAD=/usr/lib/libv4l/v4l2convert.so ffmpeg -f video4linux2 -s 320x240 -r 15 -i /dev/video0 -f avi -y tvffmpeg.avi
Треба або вертатися на старе ядро (до 2.6.27), де був драйвер для v4l першої версії, який вмів перекодовувати з пропрієтарного формату відео у нормальний, або латати ffmpeg чи mlt. :-(
Останні коментарі
1 тиждень 2 дні тому
2 тижня 6 днів тому
3 тижня 4 дні тому
7 тижнів 19 годин тому
8 тижнів 4 дні тому
12 тижнів 5 днів тому
14 тижнів 3 години тому
14 тижнів 1 день тому
26 тижнів 3 дні тому
26 тижнів 4 дні тому