29 марта 2013

Первый раз

Чего, думаю, стесняться. Первая коммерческая программа с нуля. Делал года три назад, в тесном сотрудничестве с директором автошколы.

Основная цель программы: учёт работы автошколы - успеваемость, время, планирование, топливо, деньги.

Ходил на собрание всех автошкол Минска, рассказывал презентацию. Вот файлик: https://www.dropbox.com/s/r62n19o32tnqpf5/pgbase_for_avtoschool.ppt

Техническая информация:

  • СУБД: Postgresql 9.1
  • Фронтенд: C++/Qt - формы ввода/вывода, MS Excell - отчётные таблицы, sbcl/html - отчет
Для C++/Qt были сгенерированы JavaScript биндинги, то есть по факту формоклёпство выполнялось на JavaScript'е. Агрегация данных была выполнена в хранимых процедурах или же в запросах. Оперативные отчёты (это те, которые не надо печатать) выводились через odbc в MS Excell, и скорость всего этого мне очень понравилась. Печатаемые отчёты через sbcl (postmodern, restas) в firefox.

Что я понял за это время:

  • C++/Qt для формоклёпства не подходят вообще.
  • Кроссплатформенности нет.
  • MS Excell очень-очень классный продукт.
  • Html и броузеры для отчетов тоже не подходят.
  • Графический интерфейс GUI часто-много используемого приложения это искусство.

04 марта 2013

Как создавать библиотеки в Common Lisp'е

Как-то на форуме писал пост, а получился небольшой туториал.

Итак у вас есть всякие переменные и функции в репле или лисп файле:

(defvar *who* "world")

(defun greetings ()
  (format t "Hello, ~a" *who*))
  1. Заверните это всё хозяйство в пространство имён. В коммон лиспе это называется пакет. Далее встречая слово пакет нужно думать о пространстве имён. Итак:
    1. Создайте, если ещё не создан файл utils.lisp.
    2. Сперва определите пакет с помощью defpackage. Импортируйте в него стандартный пакет common-lisp. Экспортируйте из него переменные и функции. Кстати в коммон лиспах переменные и функции адресуются с помощью символов. В нашем случае должно получится так:
      (defpackage utils
        (:use common-lisp)
        (:export *who* greetings))
      
    3. Затем перейдите в этот пакет командой in-package:
      (in-package utils)
      
    4. А затем уже разместите всё своё хозяйство:
      (defvar *who* "world")
      
      (defun greetings ()
        (format t "Hello, ~a" *who*))
      
  2. Теперь необходимо сообщить коммон лиспу о том, как всё это загрузить. Есть много способов, бла-бла-бла. Единственно мейнстримный asdf. Все его используют, все довольны. Следующий шаг создание пакета (в коммон лиспе это называется asdf-система). Теперь всегда встречая слово система, думайте о готовой к использованию библиотеке:
    1. Для этого создаётся файл utils.asd, и в нём с помощью макроса asdf:defsystem перечисляются коммон лисповые системы:
      (asdf:defsystem utils
        :licence "MIT"
        :version "1.0.0"
        :author "Your Name <yourname@email.com>"
        :depends-on ()
        :components ((:file "utils.lisp"))
        :description "Small library.")
      
      Как вы заметили в этот макрос передаются всякие списки. Первый важный :depends-on содержит другие asdf-cистемы, от которых зависит данная система. Все живое в мире друг от друга зависит, также и коммон лисповые системы могут друг от друга зависеть. Этот список для библиотеки cl-portaudio, которая позволяет играть/записывать звук в коммон лиспе выглядит так:
        :depends-on (:cffi :ffa)
      
      Далее идёт еще более хитрый параметр :components. В нем перечисляются а) модули (или же просто группы файлов, которые, например в одной папке лежат) б) эти самые файлы в) кого за кем грузить (или порядок загрузки файлов, или же зависимости между файлами). с) ещё пару параметров, сейчас их знать необязательно. Например, для cl-portaudio этот параметр выглядит так:
        :components ((:module src
                      :serial t
                      :components ((:file "package")
                                   (:file "portaudio"))))
      
      :module src означает, что файлы объеденены в модуль, и по-умолчанию находятся в одноимённой папке. :serial t означает, что файлы зависимы друг от друга в том порядке, в котором перечислены.
  3. Вуаля, библиотека на коммон лиспе готова. Допустим это папка myutils, c файлами utils.asd, utils.lisp. Теперь зайлейте это всё на github, ну или вообще на любой хостинг.
  4. В коммон лиспе стараниями Зака Бина появлися прекрасный менеджер библиотек, который позволяет одной командой скачать загрузить как саму библиотеку, так и все её зависимости. Например,
    (quicklisp:quickload '(:cl-gtk2-gtk :cl-portaudio))
    
    Загрузит cl-gtk2 и cl-portaudio со всеми зависимостями, так что можно писать теперь свой скайп со шлюхами и блекджеком. Для того, чтобы ваша библиотека попала в репозитарий quicklisp'а, просто оставьте на неё ссылку здесь. Внимание, соблюдайте традицию вежливости, начинайте заголовок со слова "Please"!:)
Теперь ещё большее внимание!!! Всё это можно было проделать за ДВЕ команды. Итак:
(ql:quickload :quickproject)

(quickproject:make-project "path/to/library" :depends-on '() :license "MIT" :author "Your name <your@email.com>" :name "utils")