Saturday, 29 January 2011
Про установку Redmine
Compojure 0.6.0
Friday, 21 January 2011
Начало проекта с Scala, Vaadin и Circumflex ORM
Запустил Netbeans. Создал maven проект с Simple Vaadin Application archetype. Для теста запустил. Выключил. Полез в гугл за ответом на вопрос "как в приложение java внедрить scala". Нашел работающее решение на http://stuq.nl/weblog/2008-11-26/4-steps-to-add-scala-to-your-maven-java-projects. Взял конфиг, который умеет обрабатывать циклические ссылки со скалы на java и обратно.
Затем написал тестовый класс на scala.
import com.vaadin.Application
import com.vaadin.ui._
import ru.circumflex.orm._
import com.kitprof.soma.entity._
class MyVaadinApplication extends Application {
def init = {
val window = new Window("My Vaadin Application")
window.addComponent(new Button("Click Me"))
setMainWindow(window)
}
}
Все прекрасно работает.
Теперь мне нужна база данных. Для разработки, я думаю, подойдет и h2 (Легкая, быстрая СУБД). Открываю pom.xml и добавляю
com.h2database h2 1.3.149
В качестве ORM я решил попробовать Circumflex ORM. Для этого в pom.xml пишу
ru.circumflex circumflex-orm 2.0.RC3
Circumflex для работы требуется файл с настройками cx.properties. Его нужно создать вручную в папке src/main/resources. В моем случае он имеет следующее содержимое:
orm.connection.driver=org.h2.Driver
orm.connection.url=jdbc:h2:~/test
orm.connection.username=myuser
orm.connection.password=mypassword
Значения всех параметров, я думаю, интуитивно понятно.
В моем приложении будут пользователи. Они должны иметь возможность авторизоваться, поэтому мне нужно, как минимум, два поля: логин и пароль. Итак,
import ru.circumflex.orm._
class User extends Record[String, User]{
val login = "user_login".VARCHAR(50).NOT_NULL
val password = "user_password".VARCHAR(50).NOT_NULL
def PRIMARY_KEY = login
def relation = User
}
object User extends User with Table[String, User]
Теперь мне нужно создать в базе таблицу users с полями user_login и user_password. Как и любая серьезная ORM тулза, Circumflex умеет сам создавать схему базы данных. Для меня самым удобным представился вариант через написание кода, поэтому в методе init класса MyVaadinApplication я добавил следующие строки:
val ddl = new DDLUnit(User)
ddl.DROP_CREATE
Метод DROP_CREATE каждый раз удаляет и создает схему заново. При разработке приложения, когда поля и свойства полей (такие как длина) часто меняются это очень удобно. Однако при тестировании удобно, когда в базе уже есть некий набор тестовых данных. Например, в моем случае не плохо было бы иметь несколько пользователей и не создавать их каждый раз после регенерации схемы базы данных. Для меня самым удобным представляется вариант создания некоего класса Bootstrap (привет liftweb.net), где будет код вида
if (usersCount == 0) createTestUsersPlease()Да, кстати, нужно попробовать запустить приложение, нажимаю Run и вижу, что все работает. H2 при этом создает в пользовательской папке файл test.h2.db (помните параметр orm.connection.url).
Tuesday, 18 January 2011
Создал банальный бин UserEjb.
@Stateless
public class UserEjb{
@PersistenceContext(unitName="EjbPU")
private EntityManager em;
public User findById(Long id) {
return em.find(User.class, id);
}
public User create (User user){
em.persist(user);
return user;
}
public User findByLogin(String login){
return (User) em.createQuery("select user from User as user where user.login = :login").setParameter("login", login).getSingleResult();
}
public User edit(User user){
em.merge(user);
return user;
}
}
В классе vaadin он никак не хотел создаваться с помощью аннотации EJB, хотя все сделал как указано в из примере На сайте ваадин
В итоге пришлось написать такой код:
UserEjb userEjb = (UserEjb) new InitialContext().lookup("java:module/UserEjb");
Thursday, 6 January 2011
Rails на Clojure
По адресу https://github.com/macourtney/Conjure проживает Rails подобная библиотека для разработки веб приложений на языке Clojure. Из ее особенностей хочется отметить:
1. В качестве слоя доступа к базе данных (ActiveRecord в Rails) используется библиотека clj-record. Это позволяет удобно писать зависимости между сущностями бд, почти как в ActiveRecord, в стиле has_many, belongs_to.
2. Может работать на Google AppEngine. Для этого при создании проекта достаточно набратьlein conjure new -database google-app-engine. А затем с помощью lein uberwar создается веб архив.
3. Удобная работа с Ajax.
Пока из того, что не понравилось – при генерировании модели можно из числовых типов можно указать только integer. Может быть я чего-то не понял, нужно копать дальше. По завершению всех копательств нужно будет написать пост с полным описанием фреймворка.
Saturday, 20 November 2010
Monday, 30 August 2010
Программные ловушки
Вы знали что программа "Hello World!", которая обычно бывает первой написанной человеком на С программой, выявляет самые опасные моменты языка? Программа содержит следующее выражение: printf ("Hello World!\n"); Рассмотрим объявление функции printf: int printf (const char * restrict format, ...); (restrict - новое ключевое слово C.) Данная функция принимает переменное число аргументов. Количество и тип переменных указываются в строке форматирования. Когда производится проверка соответствия между форматом и списком аргументов? Не во время компиляции, т.к. компилятор понятия не имеет о строке форматирования (хотя некоторые компиляторы способны выдать предупреждение если строка статически известна). Тогда во время компиляции? Если программист сделал ошибку при вызове printf с меньшим числом аргументов, то он получит замечательный код ошибки или исключение. Вот что говорится об этом в стандарте языка С: если не достаточно аргументов для форматирования, то поведение не определено. Неопределенное поведение - это худшее, что может случится с программой. Если вам повезло, программа выкинет ошибку и остановится. Если вам не совсем повезло, то программа продолжит работу в неопределенном состоянии, и в худшем случае, он выполнит поврежденный код, который возмет полный контроль над компьютером. Другая опасность в функции printf заключается в использовании указателя. Программист сам должен проследить за тем, чтобы указатель адресовал правильное место в памяти. В примере "Hello World!" указатель адресует статическую заканчивающуюся завершающим нулем строку, так что проблем не возникает. Но вот эта программа так же успешно скомпилируется: char * format = 0; printf (format); Угадайте, что случится. Внутри printf указатель разыменовывается и все рушится. Снова, цитируя стандарт С: если указателю было присвоено неверное значение, то поведение унарного оператора * не определено. Каждый раз при выделении памяти возвращается верный адрес (пока у программы не закончится память). Вы можете подумать, что разыменование такого указателя может быть безопасным. Это верно лишь до того, пока ваша программа не будет эту память освобождать при окончании времени жизни объектов. После этого у вас окажется указатель с неверным адресом и пиши пропало. И снова стандарт языка не обнадеживает. Из тех значений указателя, которые не следует разыменовывать оператором * он указывает на null указатель, неправильно выравненный с началом объекта адрес, и адрес объекта, после того как последний был удален. Ясно, что C был создан не для слабонервных. Он является низкоуровневым и программисту нужно знать, что и зачем он делает, иначе будут проблемы. Но C++ же не такой? С момента создания C++ старался избавиться наследие C. В него было добавлено множество конструкций, которые закрывали небезопасные возможности языка С. Например, программа "Hello World!" может быть трансформирована в более безопасный вариант. std:cout << "Hello World!" <<> Здесь уже не требуется считать количество передаваемых аргументов, и std::cout достаточно умен, чтобы понять типы передаваемых ей аргументов (хотя множество программистов продолжают использовать printf в C++, из-за более простого написания). В отличие он С, выделение памяти в C++ типизировано и производится при выполнении конструктора объекта (если вы конечно не используете malloc и free). Это хорошая сторона. Однако объекты по прежнему должны быть явно удалены. И после удаления все еще остаются указатели, использование которых, как вы уже можете догадаться, приведет к неопределенному поведению. Когда как в C указатели были очень важны, то в C++ они являются основным механизмом Стандартной библиотеки. Алгоритмы STL используют итераторы, объекты, которые являются указателями сами или имитируют их поведение (и все опасные моменты в том числе). Как и в случае указателей, неправильное использование итераторов приведет к неопределенному поведению (см. пример с swap_range). В то время как в C/C++ имеются проблемы с безопасностью, в языках наподобие Java и C# пошли другим путем. Они либо вообще запретили использование указателей, либо выделили их в специальные блоки с меткой "небезопасный". Управление памятью, которое порождает риск обращения по неверным указателям, скрыт от программиста и производится автоматическая сборка мусора. Кроме этого в них есть еще множество упрощения и средств, повышающих безопасность. К несчатью, все они либо снижают мощность языка или его производительность.
Подмножество безопасного D (SafeD Subset)
В языке D, основная работа выполняется в безопасной области языка, которую мы называем SafeD. Безопасность и простота использования языка D в этом случае сравнима с Java. На самом деле программы на Java можно автоматически транслировать в безопасную часть D. SafeD легок в освоении и избавляет программиста от неопределенного поведения. И он очень эффективен в плане производительности. В SafeD вы не используете указатели, непроверенное приведение типа и union'ы. Управление памятью ложится на сборщик мусора. Объекты передаются с помощью идентификаторов. Выполняется проверка выхода за границы массивов и строк (можно отключить эту возможность с помощью ключа компиляции, но тогда вы уже не в SafeD). Вы можете писать код, который будет выкидывать исключения времени выполнения (т.е. ошибка выхода за границы массива, неинициализированный объект), но вы не сможете перезаписать память, которую выделили или уже освободили. Посмотрим на программу "Hello World!" на языке D. На первый взгляд, различий с C не много: writeln ("Hello Safe World!"); Функция writeln является эквивалентом printf в С (более точно, это представитель семейства функций для вывода, которое включает write и ее версии для форматированного вывода - writef и writefln). Так же как и printf, writeln принимает переменное число аргументов любого типа. Однако на этом сходство заканчивается. Пока вы будете передавать ей SafeD-аргументы, вы можете быть уверены, что не возникнет никакого неопределенного поведения. Здесь writeln вызван одним аргументом типа string. В отличие от C, D строки не являются указателями. Это массив char, и массивы находятся в безопасной части D. Вам может быть интересно, как осуществлена безопасность функции writeln. Один из возможных способов, это сделать функцию обрабатываемую компилятором, чтобы генерировался правильный код. Красота D в том, что он дает современные инструменты для подобных случаев. Из таких инструментов, которые использовались при написании этой функции нужно отметить: Генерирование кода во время компиляции с помощью шаблонов, и Безопасный механизм работы с переменным числом аргументов с помощью кортежей.
SafeD Библиотеки
Основное отличие между Java и D в том, что в D есть достаточно возможностей, чтобы создать бибиотеки для использования в SafeD. Большое количество возможностей D совместимы с SafeD. Например, в библиотеке может быть реализован типизированный список (generic list). Этот список может быть создан для любого типа, в том числе указателя. Список указателей не может быть безопасным по определению. Причем список целых чисел или объектов может и должен быть безопасным, поэтому в SafeD можно использовать списки таким образом, а использование вне безопасного Ди может быть небезопасным. Более того, может оказаться в плане эффективности лучше реализовать список через указатели. И если такая внутренняя реализация хорошо скрыта от пользователя, такая реализация может быть названа совместимой с безопасным Ди.
Опыт одного пользователя
Даже до того, как у меня в голове возникла идея о SafeD2, в своих проектах я пытался ограничивать себя безопасным в использовании подмножеством Ди. Я был удивлен, насколько многого можно при этом сделать и насколько возрастает продуктивность. Я также показал Ди знакомому по работе, программисту С++, и он смог освоить его за очень короткое время. Так по моему опыту можно было сказать, что если написанная на SafeD программа компилируется без ошибок, она будет и работать без ошибок и делать то, чего я от нее хочу. Это определенно не то, с чем я сталкивался при использовании C++. Что еще больше меня удивляет, как я умудрился все это сделать, не имея в наличии подходящего инструментария и получая непонятные сообщения от компилятора. Ди все еще не хватает инфраструктуры, но я могу представить, насколько легко будет на нем программировать, когда появится критическая масса инструментария для разработчика. В отличие от C++, D можно легко парсить и у него открытый фронт енд, что упрощает работу людям, пишущим инструментарий.
Заметки
Сейчас нет какого-либо органа, кто-бы занимался подобной сертификацией, каждый кто создает библиотеки устанавливает свой уровень доверия с клиентами. В частности, вам следует ожидать, что разработчик компилятора обеспечивает совместимость стандартной библиотеки с SafeD. Название SafeD было предложено David B. Held.
Благодарности
Огромное спасибо членам команды разработчиков языка D за ценный отклик и исправления в данной статье.
Оригинал: http://d-programming-language.org/safed.html
Это черновой перевод статьи. Буду еще дорабатывать. Если есть замечания и комментарии, прошу в комменты.