суббота, 30 октября 2010 г.

Субботний вечер пропаганды маргинальных технологий: hgsubversion

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

Сегодня хотел немного затронуть тему распределенных систем контроля версий. На самом деле, эта тема достаточно популярно, просто больших компаниях приживается очень плохо, некоторые, как я узнал, например в IBA, вообще cvs пользуются. Подробно рассказывать именно про DVCS не думаю, что есть смысл, материалов на всех языках мира хватает, как в общем про DVCS, так и про конкретные системы. Один из главных зачинатилей всего безобразия, это Линус, так что в качестве введения можно посмотреть его выступление в кампусе Google, где в его духе эмоционально рассказано кто не прав и почему :)

Я расскажу про немного другую проблему. Когда вы делаете не свой продукт, а под заказ или являетесь всего лишь небольшим подпроектом огромного проекта, часть технологий вы выбрать не можете и вынужденны использовать subversion. Но ведь хочется вкусненького, и это возможно. Почти все разработчики DVCS понимают, что все сейчас прям не бросятся переводить свои репозитории на новые рельсы. Поэтому присутствует интеграция с многими другими системами контроля версий. Например с subversion. Вот хотел бы рассказать про hgsubversion, проект, который позволяет интегрировать subversion и mercurial репозитории. Был опробован на реальном проекте и пока никаких проблем не возникло.

пятница, 29 октября 2010 г.

Требую больше immutability!

Вообщем тривиальная слоган, его можно прочитать даже в достаточно старой Joshua Bloch: Effective Java, Item 15: Minimize mutability.

Под катом чутка банальности, так как сегодня доделал и наболело.

пятница, 22 октября 2010 г.

Java сompile time annotations

Ох.. тут давече затеяли большой рефакторинг проекта в рамках которого я решил сделать пару классов immutable. Казалось бы, делаем все поля private + final и всё ок. Но нет, для ссылочных типов это не работает. Так как в этом случае мы не можем изменить ссылку на этот объект, которая храниться в поле, но за то можем изменить сам этот объект, например добавить в коллекцию ещё пару объектов. Тут есть два подхода, оба приводят к равно ценном результату (immutable классу):

  1. Требовать, чтобы все ссылочные типы также были immutable, как String например. Для коллекций можно использовать Collections.unmodifiableCollection метод.
  2. Второй способ заключается в основе ООП: инкапсуляции. Ни один метод не возвращает объект по ссылке, только его копию, например вместо возврата коллекции можно вернуть её неизменяемую копию с помощью описанного выше метода.
Вообщем то всё достаточно очевидно. Ввиду ряда особенностей и уменьшения последствий рефаторинга, посоветовавшись, я решил воспользоваться вторым способом. Но пока рассматривал первый метод, захотелось аннотацию, которая бы сигнализировала, что объект не изменяем и корректность класса проверялась на этапе компиляции. Если кого-то заинтересовала, краткое описание под катом.

четверг, 16 сентября 2010 г.

Log4j file header

Давно не писал, но тут накипело. Читал буквально позавчера статью Модульный дизайн, или «что такое DIP, SRP, IoC, DI и т.п.». Вот там говориться про великий Log4j, какой он распрекрасный. И вот понадобилось мне сделать header для файлов. Такой вот конфиг:
  1. <appender name="eventhistoryfile" class=" org.apache.log4j.RollingFileAppender">  
  2.     <param name="LogFileName" value="${log4j.file.name}"/>  
  3.   
  4.     <layout class="org.apache.log4j.PatternLayout">  
  5.         <param name="ConversionPattern" value="${log4j.pattern}"/>  
  6.     </layout>  
  7. </appender>  
Очень простой.. Как добавить хедер? Оказывается PatternLayout содержит пустую реализацию метода getHeader. Ну и как это называется??? Ладно, сделал свой, который добавляет эту функциональность, не сложно. Идём дальше. Запустил, работает. Вырубил приложение, запустил ещё раз появился ещё один header в файле О_о я нахожусь в шоке. Пришлось ещё наследоваться от RollingFileAppender и переопределять у него метод writeHeader, чтобы header в файл писался один раз (код взят в исходном FileAppender  только добавлена последняя проверка).
  1. @Override  
  2. protected void writeHeader() {  
  3.     if (this.layout == null) {  
  4.         return;  
  5.     }  
  6.     String header = layout.getHeader();  
  7.     if (header == null && this.qw == null) {  
  8.         return;  
  9.     }  
  10.     File f = new File(this.getFile());  
  11.     if (!f.exists() || (f.exists() && f.length() == 0)) {  
  12.         this.qw.write(header);  
  13.     }  
  14. }  
Вообщем, негодую.

вторник, 22 июня 2010 г.

Crash Racing

Для получения Диплома осталось только подписать обходной лист. Вот разбирал архивы, чтобы всё накопленное записать на dvd и сдать в архив, и наткнулся на прикольный проект. На втором курсе у нас Java вёл очень хороший преподаватель Гафуров Сергей Владимирович. И в конце курса  мы разбились на команды и где-то недели две писали сетевую игру на Java. Мы выбрали гоночки и как видно из заголовка поста - разрушительные гоночки. Это был невероятный проект и очень полезный, заставил по другому взглянуть на программирование. Всё таки работа в команде, это работа в команде :) Где-то в середине проекта стало понятно, что мы не успеваем и пришлось перебороть юношеский максимализм и волевым усилием отказаться от оружия. Зато к сроку у нас был работающий проект, хоть и разрушать ничего нельзя было. Вот на память записал видео сражения 4х ботов на моей любимой карте, за ними наблюдать иногда веселее чем самому играть, а благодаря Диме Гончарову выиграть у них практически не возможно =DD это удавалось только Диме Хоревичу. Кстати да, о лицах :) Первый Дима как не сложно догадаться работал над физикой и ИИ, второй над UI, Катя Цвирко сделала потрясающие карты и работала с панелью игрового поля. А я скромно писал сетевое взаимодействие. Играть можно было по сети. Так как ботов было трудно победить - сражались между собой :) Игра не поражает воображение, но это всё таки учебный проект второкурсников, причём в жатые сроки, мне нравиться ^__^



Код не покажу, стыдно :)

Upd: Видео уже лень делать, вот скриншоты :)

воскресенье, 16 мая 2010 г.

Прикольный workaround для деплоя репортов в Reporting Services

Reporting Services штука полузная. Сделаные в VS репорты для него можно деплоить по разному. Через web интерфейс, с помощью SQL Server Management Studio. Но иногда нужны автоматические скрипты. Для этого есть утилитка rs.exe.
rs.exe -i MyReportScript.rss -s http://localhost/reportserver
MyReportScript.rss - это скрипт на VB, который и загружает репорт или репорты.
Вот так примерно выглядит код загрузки:

  1. Try
  2.   Dim stream As FileStream = File.OpenRead(reportName + ".rdl")
  3.   definition = New [Byte](stream.Length) {}
  4.   stream.Read(definition, 0, CInt(stream.Length))
  5.   stream.Close()
  6.   Catch e As IOException
  7.   Console.WriteLine (e.Message)
  8. End Try
  9.  
  10. Try
  11.   warnings = rs.CreateReport(reportName, reportsPath, True, definition, props)
  12.   Console.WriteLine("Upload Report: {0}.", reportName)
  13.   Catch e As Exception
  14.   Console.WriteLine (e.Message)
  15. End Try

Репорты делал не я и делались они 2005 студии. У меня стоит 2008, после пары изменений, я получаю вот такое сообщение:
System.Web.Services.Protocols.SoapException: The report definition is not valid.  Details: '.', hexadecimal value 0x00, is an invalid character. Line 4334, position 10.
Через Management Studio загружается нормально.
Конечно же файл репорта представляет из себя просто ужасный xml. И что мы видем в строчке 4334? Заключительный закрывающийся тэг:
Становится совсем не понятно, но всемогущий гугль легко находит линку:
RS.EXE fails to deploy a report upgraded from SQL Server 2005 Reporting Services - "report definition is not valid"
Предложенное решение проблемы меня просто поставило в тупик

  1. Replacing
  2.      My_Byte_Array = New [Byte](stream.Length) {}
  3. With
  4.      My_Byte_Array = New [Byte](stream.Length - 1) {}

Вообщем даже не представляю как это у них получилось cгенерировать такую проблему в новой студии, вообщем просто в шоке =D
Хотя я иногда и по круче отжиги делаю :)

З.Ы.: Сорри за не самую красивую подсветку, просто мой любимый Online syntax highlighter что-то с VB на отрез отказался работать, а HTML Source Code Syntax Highlighter хоть и подсвечивает код, но не очень красиво.

З.Ы.Ы.: Катя подсказала более крутой сервис для подсветки кода, так как ей нужен был Object C, то она нашла вот этот, количество языков поражает. Только надо выбрать опцию Combine Style and HTML, чтобы он не генерировал отдельно css стиль, а всё выдавал html кодом. Качество подсветки хорошее.

воскресенье, 18 апреля 2010 г.

Java - отличная платформа, но слишком неповоротливый язык.

Хотел поделится порцией очевидностей. Java - это действительно отличная платформа для разработки, с больших комьюнити, огромным числом Open Source библиотек, инструментов и т.п. Но вот язык Java этой платформы слишком устарел. Лично я не поклонник нагромождения синтаксического сахара, как например в Ruby. Но я сравниваю с C# и там есть много действительно полезных плюшек, практически полезных (я вообще пишу только о том, с чем лично столкнулся).
Вот два небольших примера.
1. Есть очень популярная задача, организовать конвейер для обработки документов, которые по сути из себя представляют Map или, если говорим о C#, Dictionary. К Dictionary в дот нете, у меня есть одна большая претензия, он слишком часто кидает исключения. Но речь не об этом. Вот так выглядит простой документ, я добавил в него метод AddProperty, с помощью которого можно не только добавить элемент, но и перезаписать старый:
  1. public class Document : Dictionary<stringobject>  
  2.     {  
  3.         public Document AddProperty(string name, object value)  
  4.         {  
  5.             if (ContainsKey(name))  
  6.                 Remove(name);  
  7.   
  8.             Add(name, value);  
  9.             return this;  
  10.         }  
  11.     }  
Собственно ничего интересно, за исключение полезной штучки, метод возвращает не void, а самого себя.
API конвейера тоже простое:
  1. public class Pipeline  
  2. {  
  3.     public void AddProccessor(Func<Document, Document> proccessor)  
  4.     {  
  5.     }  
  6.   
  7.     public void Execute()  
  8.     {  
  9.     }  
  10. }  
Вот тут почти самый главный момент. Делегаты это хорошо, мне надоели в том же свинге листенеры с одним методом, это ужас какой-то.
Но самое интересное теперь. Иногда требуется добавить очень простую обработку, которая просто добавляет пару полей к документу. В java пришлось бы поступить как в свинге, анонимный класс с реализацией метода интерфейса листенера. Но в C# коллега подсказал очень и очень красивое решение:
  1. var pipeline = new Pipeline();  
  2. pipeline.AddProccessor(record => record.AddProperty("NewProp""Value").AddProperty("AnotherProp", 1));  
Действительно в одну строчку.
2. На эту тему копий сломано не мало, перегрузка методов или параметры по умолчанию. Кто бы, что ни говорил, но C# 4.0 c параметрами по умолчанию плюс именование параметров, лично для меня, отличное, красивое и удобно решение.
Вот есть метод:
  1. public static string format(string value,   
  2.             bool option1 = falsebool option2 = false)  
  3. {  
  4.     return value;  
  5. }  
Параметры по умолчанию позволяют не забивать и так не маленькие исходные тексты кучей не нужного текста. Но к сожалению они не идеальны без одной маленькой штучки. Вот скажите, что надо сделать, чтобы вызвать описанный метод, но чтобы option2 был true. Придется или перегружать метод, или при вызове передавать false для option1. Но проблема решена в C# 4.0. При вызове метода передаваемые параметры можно именовать, так что теперь можно не беспокоиться об очерёдности параметров, а также решить указанную выше проблему простым способом:
  1. format("test", option2: true);  
Да, для JVM есть много интересных альтернативных языков, например мне нравится Clojure. Но например у него есть проблемы с производительности и вообще, его активно портируют на CLR. Хотелось бы, чтобы и основной язык платформы более активно развивался.

Ну и так, ещё одна рабочая мысль за сегодня: парное программирование - это не только весело, но и действительно продуктивно.

И совсем напоследок цитата дня (которую правда уже постил в Buzz'е, но уж больно понравилась):
  1. select fun, profit from real_world where relational=false