XAML Power Toys

XAML Power Toys – аддин для Visual Studio 2008 SP1 для разработчиков под Silverlight, WPF, облегчающий разработку генерацией XAML’а представений (View), а так же модели представления (ViewModel), со всем необходимыми бизнес-действиями и контролами.

imageПодробнее узнать можно здесь:

http://karlshifflett.wordpress.com/xaml-power-toys/

Реклама

Создание простейшего DI контейнера с использованием TDD

Введение

Сегодня просмотрел ряд скринкастов от Daniel Cazzulino, в которых он рассказывает о создании с нуля простейшего DI контейнера, что не могло не привлечь моего внимания. Ниже будут приведены примеры из его скринкастов.

Требования

Нам понадобится Visual Studio 2008, 15-20 минут свободного времени и желание узнать как же сделать свой DI контейнер.

Начнём. Funq1

  • Для начала создадим проект Class Library в Visual Studio, назовём его Funq1
  • Далее добавим в решение проект тестов (мы будем использовать TDD на базе тестов Visual Studio) и назовём его Funq1.Tests, создадим ссылку из него на наш проект Funq1

Funq1.Tests

  • В проекте Funq1.Tests создадим тестовый класс ContainerFixture, который будет проверять функционал нашего контейнера.
  • Добавим объявление интерфейсов IFoo, IBar, а так же соответственно классов Foo, Bar, для тестирования нашего контейнера:

  1. public interface IBar { }
  2. public interface IFoo { }
  3.  
  4. public class Bar : IBar { }
  5.  
  6. public class Foo : IFoo
  7. {
  8.     public IBar Bar { get; private set; }
  9.  
  10.     public Foo(IBar bar)
  11.     {
  12.         Bar = bar;
  13.     }
  14. }

* This source code was highlighted with Source Code Highlighter.

  • Создадим тестовый метод, который проверит умеет ли наш контейнер регистрировать и возвращать объекты, выглядеть он будет примерно следующим образом:

  1. [TestMethod]
  2. public void RegisterTypeAndGetInstance()
  3. {
  4.     var container = new Container();
  5.  
  6.     container.Register<IBar>(() => new Bar());
  7.  
  8.     var bar = container.Resolve<IBar>();
  9.  
  10.     Assert.IsNull(bar);
  11.     Assert.IsTrue(bar is Bar);
  12. }

* This source code was highlighted with Source Code Highlighter.

  • Итак, на тестовый класс ContainerFixture выглядит следующим образом:

  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2.  
  3. namespace Funq1.Tests
  4. {
  5.     [TestClass]
  6.     public class ContainerFixture
  7.     {
  8.         [TestMethod]
  9.         public void RegisterTypeAndGetInstance()
  10.         {
  11.             var container = new Container();
  12.  
  13.             container.Register<IBar>(() => new Bar());
  14.  
  15.             var bar = container.Resolve<IBar>();
  16.  
  17.             Assert.IsNull(bar);
  18.             Assert.IsTrue(bar is Bar);
  19.         }
  20.  
  21.         public interface IBar { }
  22.         public interface IFoo { }
  23.  
  24.         public class Bar : IBar { }
  25.  
  26.         public class Foo : IFoo
  27.         {
  28.             public IBar Bar { get; private set; }
  29.  
  30.             public Foo(IBar bar)
  31.             {
  32.                 Bar = bar;
  33.             }
  34.         }
  35.     }
  36. }

* This source code was highlighted with Source Code Highlighter.

Funq1.Container

  • Наш тест не проходит, так как Container остается не объявленный, в связи с этим в проекте Funq1 добавляем класс Container
  • Объявляем поле, в котором будут храниться соответствия типов:

  1. Dictionary<Type, object> factories = new Dictionary<Type, object>();

* This source code was highlighted with Source Code Highlighter.

  • Добавим метод для регистрации типа в контейнере:

  1. public void Register<TService>(Func<TService> factory)
  2. {
  3.     factories.Add(typeof(TService), factory);
  4. }

* This source code was highlighted with Source Code Highlighter.

  • А так же метод, для извлечения типа из контейнера:

  1. public TService Resolve<TService>()
  2. {
  3.     object factory = factories[typeof(TService)];
  4.  
  5.     return ((Func<TService>)factory).Invoke();
  6. }

* This source code was highlighted with Source Code Highlighter.

  • На данный момент наш Container выглядит следующим образом:

  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace Funq1
  5. {
  6.     public class Container
  7.     {
  8.         Dictionary<Type, object> factories = new Dictionary<Type, object>();
  9.  
  10.         public void Register<TService>(Func<TService> factory)
  11.         {
  12.             factories.Add(typeof(TService), factory);
  13.         }
  14.  
  15.         public TService Resolve<TService>()
  16.         {
  17.             object factory = factories[typeof(TService)];
  18.  
  19.             return ((Func<TService>)factory).Invoke();
  20.         }
  21.     }
  22. }

* This source code was highlighted with Source Code Highlighter.

Funq1.Tests

  • Пробуем запустить тесты, но они не проходят, т.к. мы умышленно внесли ошибку  в описании метода RegisterTypeAndGetInstance() в строке 17: Assert.IsNull(bar), чтобы убедиться, что тест срабатывает
  • Для того, чтобы тест прошёл, следует изменить эту строчку на Assert.IsNotNull(bar);
  • Далее нас интересует, а что же с зависимостью в конструкторе, как её необходимо зарегистрировать, для этого мы объявляем тестовый метод ResolveGetsDepedenciesInjected() и заносим следующие объявления:

  1. container.Register<IBar>(() => new Bar());
  2. container.Resolve<IFoo>(() => new Foo(container.Resolve<IBar>()));

* This source code was highlighted with Source Code Highlighter.

  • Однако данное объявление не понравится нашему компилятору, т.к. в области видимости замыкания не присутствует container, в связи с этим данное объявление придётся немного изменить:

  1. container.Register<IBar>(c => new Bar());
  2. container.Register<IFoo>(c => new Foo(c.Resolve<IBar>()));

* This source code was highlighted with Source Code Highlighter.

Funq1

  • Соответственно необходимо будет немного изменить наш контейнер, добавив в функции аргумент Container:

  1. public void Register<TService>(Func<Container, TService> factory)
  2. {
  3.     factories.Add(typeof(TService), factory);
  4. }
  5.  
  6. public TService Resolve<TService>()
  7. {
  8.     object factory = factories[typeof(TService)];
  9.  
  10.     return ((Func<Container, TService>)factory).Invoke(this);
  11. }

* This source code was highlighted with Source Code Highlighter.

Funq1.Tests

  • После внесенных в контейнер изменений необходимо будет немного поправить наш первый тестовый метод RegisterTypeAndGetInstance() строку 13 на выражение:

  1. container.Register<IBar>(c => new Bar());

* This source code was highlighted with Source Code Highlighter.

  • Далее вернемся к нашему методу ResolveGetsDepedenciesInjected() и добавим к нему извлечение объекта и утверждение-проверку на null, в результате получим:

  1. [TestMethod]
  2. public void ResolveGetsDepedenciesInjected()
  3. {
  4.     var container = new Container();
  5.  
  6.     container.Register<IBar>(c => new Bar());
  7.     container.Register<IFoo>(c => new Foo(c.Resolve<IBar>()));
  8.  
  9.     var foo = container.Resolve<IFoo>() as Foo;
  10.  
  11.     Assert.IsNotNull(foo);
  12.     Assert.IsNotNull(foo.Bar);
  13. }

* This source code was highlighted with Source Code Highlighter.

Заключение

Вот и подошёл к концу наш увлекательный (надеюсь) урок по созданию с нуля простейшего DI контейнера, что же мы приобрели в процессе:

  1. Базовое понимание функционирования DI контейнера
  2. Практические навыки разработки с использованием TDD

О шоколаде, интернете, удобстве и разработке

Введение

В мире (в частности в IT) наверное слишком часто встречаешься с трудностями, порою даже не обращаешь на это внимание, трудности вошли уже в обыденность и не воспринимаются осознанно. Однако у меня появилось желание произвести небольшой обзор трудностей.

Шоколад

Мне очень нравятся молочные продукты. В частности мне нравится выпить стаканчик молока с несколькими дольками горького шоколада. Сегодня этот очередной раз повторился. Но он не прошёл обычно (может быть это как-то связано с тем, что позавчера я начал новую жизнь ;)), а отметился этот случай тем, что я очень тщательно подошёл к вопросу открытия шоколадки:

gork_franz[1]

Вы когда-нибудь ели шоколадки этой серии? Фишка в том, что когда ты открываешь её, тебе не надо задумываться над тем как это сделать, потому что всё написано и нарисовано на упаковке, причём сделано так, что мало кто сумеет пойти другим путём. Это Великолепно!

Интернет

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

Приведу простейший пример:

Я пишу сообщение в каком-нибудь RTE (rich-text editor) редакторе, и вдруг меня посещает мысль о том, что неплохо бы было вставить картинку, мои глаза устремляются на поиски соответствующей кнопочки и хорошо, если я найду её, а то вместо того, чтобы продолжить изливать свою творческую энергию в редактор, я начну изливать её авторам сайта, либо критиковать его на различных информационных ресурсах.

К примеру ещё можно было бы добавить возможности тегирования, категорий, цитирования, проверки орфографии и проч.

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

Принято считать, что объекты, содержащие в себе «золотое сечение», воспринимаются людьми как наиболее гармоничные. Пропорции пирамиды Хеопса, храмов, барельефов, предметов быта и украшений из гробницы Тутанхамона якобы свидетельствуют, что египетские мастера пользовались соотношениями золотого сечения при их создании. Архитектор Ле Корбюзье «нашёл», что в рельефе из храма фараона Сети I в Абидосе и в рельефе, изображающем фараона Рамзеса, пропорции фигур соответствуют величинам золотого сечения. Зодчий Хесира, изображённый на рельефе деревянной доски из гробницы его имени, держит в руках измерительные инструменты, в которых зафиксированы пропорции золотого сечения. В фасаде древнегреческого храма Парфенона присутствуют золотые пропорции. При его раскопках обнаружены циркули, которыми пользовались архитекторы и скульпторы античного мира. В Помпейском циркуле (музей в Неаполе) также заложены пропорции золотого деления, и т. д. и т. п.

Хотелось бы привести в пример ресурс, с которым в последнее время начал активно работать, это Twitter

image Он безумно популярен, и это не удивительно, в связи с тем, что он:

  1. Реализует законченную идею
  2. Предоставляет интересный и исчерпывающий функционал
  3. Прост и удобен в использовании

Разработка ПО

Всё вышесказанное можно смело отражать на то, разработкой чего я занимаюсь практически каждый день. Стоит понимать, что программное обеспечение пишется не для удачной интерпретацией аппаратной составляющей компьютера, а для людей, следовательно необходимо придерживаться принципов простоты и удобства, ясности и непринужденности.

Чтобы не быть голословным хочу привести в пример анализ некого out-of-box движка для интернет-магазина.

При разработке такого движка следует понимать следующее:

  1. Клиент, который будет заинтересован в покупке данного решения (мы продаём не продукты, мы продаём решения ;)), не будет заинтересован в организации его поддержки (если он купит коробку, он не захочет нанимать специалистов для работы с ней).
  2. Движок должен быть максимально прост и предоставлять основную функцию – разворачивание и поддержка интернет-магазина, желательно, чтобы это происходило по нажатии нескольких кнопок

Те же самые принципы должны относиться и к самому процессу написания программного обеспечения:

  • Не должно быть решений, натянутых за уши. Если что-то идёт не так, значит вы используете не ту технологию, не ту среду, не обладаете достаточной квалификацией.
  • Не должно быть трудночитаемого, запутанного, пугающего кода. Если такое получается, то необходимо вооружится такими инструментами, как рефакторинг, шаблоны проектирования, в этом может помочь опытный архитектор.
  • Код должен работать на любой стадии. Если к концу периода (дня, 2ух дней, недели) у Вас не получается сделать функционирующий экземпляр, значит необходимо пересматривать режим разработки, необходимый в решении функционал.
  • В каждой строчке кода должна быть идея, мысль. Если ваш код скучно читать, если это просто набор букв и цифр, попробуйте написать небольшой рассказ (хотя бы в уме) по поводу того, чем в данный момент занимается ваш метод, уверяю это пойдёт только на пользу, а так же наведёт ясности.
  • Написание кода должно дарить позитивные эмоции. Если это не так, возможно вы утомились на сегодня, советую передохнуть. Если на завтра это повторяется, значит вы просто в состоянии “непрухи”, попробуйте по возможности заняться каким-нибудь другим творчеством в это время. Если же это сопровождает вас постоянно – задумайтесь, а тому ли занятию вы посвящаете своё драгоценное время.

Заключение

Хотел попробовать пописать о разработке немного отвлеченно, немного не с технической стороны вопроса, хочу, чтобы мой опыт был полезен не только .NET – разработчикам.


Что такое ALT.NET?

Введение

По многочисленным WTF от коллег, хотел бы вкратце прояснить, а что же это такое. А дальше решайте сами, интересно Вам это или нет.

Содержание

 

ALT.NET — Альтернативные инструменты и подходы к разработке на .NET.

Инструменты и подходы перечислены ниже в табличке HOTorNOT.

Hot Not
Castle, ActiveRecord,
NHibernate
DataSets, Dataset Designer, Entity Framework, MS Application Blocks
MVC,NUnit,MonoRail Web Forms, SCSF, VSTS, MSTest
XP, TDD, Scrum MSF Agile, MSF For CMMI
Evolutionary Design and Development Big Design Up Front
Ruby + IronRuby, Python + IronPyton, DLR, Silverlight(?) ?
OR\M (NHibernate, LLBLGen  etc..) DLinq, Data Access Block, DataSets, Plain ADO. NET
Open Source (Mono, SourceForge) Application Blocks, CodePlex
MVC and MVP (RoR, MonoRail..) Web Forms, CAB, Smart Client Factory
CVS, SVN VSS, VSTS Source Control
Build Automation and CI
(CI Factory, NAnt, FinalBuilder, CruiseControl..)
Team Build
TDD and Unit Testing
NUnit, MbUnit, RhinoMocks, NMock, TypeMock
MSTest for unit testing, VSTS
Subtext, DasBlog, WordPress, TypePad, Blogger, FeedBurner Microsoft MSN Spaces, Community Server(?)
Simplicity in Design P&P
Working at Google Working at MS
Google Gears Smart Client, MS Ajax
.NET 3.X (WF, WPF. Silverlight) .NET 2.0
DI, IoC, Spring for .NET Object Builder
Conferences:
OSCon, RubyCon, Code Camps, DevTeach..
VSLive, TechEd, DevConnections..

Считаю, что необходимо как минимум ознакомиться со всеми перечисленными понятиями как в правой, так и в левой колонках, следуя принципу анализ-синтез-best practices.

Материалы по теме

 

  1. Табличка любезно позаимствована здесь http://weblogs.asp.net/rosherove/archive/2007/06/04/alt-net-alternative-tools-and-approaches-to-mainstream-net.aspx
  2. Страница сообщества ALT.NET http://altdotnet.org/
  3. Статья в журнале MSDN “Что такое ALT .NET?” by Джереми Д. Миллер (Jeremy D. Miller) http://msdn.microsoft.com/ru-ru/magazine/cc337902.aspx
  4. Активно развивающаяся группа ALT.NET на Yahoo Groups http://tech.groups.yahoo.com/group/altdotnet/

Lazy Computation in C# (Ленивые вычисления в C#)

Немного теории.

Большинство современных языков разработки, используемых на практике (таких как C#, VB.NET, C++, Python и Java) реализуют так называемые немедленные вычисления, это означает, что операция выполняется, так только становятся известны значения её операндов. Однако, ясно, что немедленное вычисление многих функций не всегда необходимо и рационально с точки зрения производительности, поэтому само собой напрашивается решение, позволяющее отложить эти вычисления на тот момент, когда они нам будут действительно нужны.

Мартин Фаулер в свой книге PoEAA вводит понятие паттерна Lazy Load (загрузка по требованию, ленивая загрузка), суть которого состоит в том, что объект не содержит данные, но знает где их взять, если они ему станут нужны. Это как раз то, о чём мы и ведем речь, следовательно воспользуемся этим шаблоном.

Реализовать данный шаблон можно несколькими различными вариантами:

  1. Lazy Initialization – Инициализация по требованию. Это самый простой способ – реализовать проверку поля на null и в случае необходимости заполнять его данными.
  2. Virtual Proxy – Виртуальный прокси-объект. Метод несколько усложнен проблемой идентификации объектов, т.к. вместо них, до инициализации, выступают заменители.
  3. Ghost – Фиктивный объект, Призрак. Это реальный объект с неполным состоянием.
  4. Value Holder – Диспетчер значения. Объект является оболочкой для некоторого значения. Так же не самый лучший вариант в связи с проблемами типизации.

Примеры реализации.

В рассмотренном ниже примере мы воспользуемся первым способом, как наиболее наглядным и простым в реализации.

Мы напишем обобщенный класс Lazy<T>, который будет представлять загрузку по требованию, а так же кэшировать результат вычислений для дальнейших обращений к ним.

using System.Linq;
public class Lazy<T> {
private Func<T> func;
private T result;
private bool hasValue;
public Lazy(Func<T> func) {
this.func = func;
this.hasValue = false;
  }
public T Value {
get {
if (!this.hasValue) {
this.result = this.func();
this.hasValue = true;
      }
return this.result;
    }
  }
}

Данный класс имеет три поля:

  • func – делегат Func<T> инкапсулирующего передаваемый метод (находится в пространстве имён Linq, используется для инкапсуляции метода без параметров);
  • result – поле для хранения результата вычислений;
  • hasValue – флаг для обозначния, производились ли уже вычисления.

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

Lazy<int> lazy = new Lazy<int>(() => {
    Console.WriteLine("calculating...");
return 42;
  });
Console.WriteLine("starting...");
Console.WriteLine("result = {0}", lazy.Value);
Console.WriteLine("result (again) = {0}", lazy.Value);

Результат работы программы:

starting…

calculating…

result = 42

result (again) = 42

Мы наглядно видим, как в поле func заносится лямба-выражение, результат которого выводится после вызова свойства Value. Причём повторный вызов свойства выводит кэшированные данные.

Далее, думаю стоит написать обертку-помощник для нашего класса, с целью повышения наглядности работы с ним.

public static class Lazy {
public static Lazy<T> New<T>(Func<T> func) {
return new Lazy<T>(func);
  }
}

Будет он выглядеть примерно так. Кстати, примерно также выглядит System.Nullable (один из стандартных классов .NET).

Используя класс Lazy мы можем создать экземпляр нашего типа, вызвав метод Lazy.New вместо написания new Lazy<int> к примеру. Для ещё пущего повышения наглядности будем использовать атрибут var.

int a = 22, b = 20;
var lazy = Lazy.New(() => {
    Console.WriteLine("calculating...");
return new { Mul = a*b, Sum = a+b };
  });
Console.WriteLine("Mul = {0}, Sum = {1}",
  lazy.Value.Mul, lazy.Value.Sum);

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

Далее хотелось бы рассмотреть пример со значениями аргументов в качестве значений, инициализируемых по требованию, что несомненно очень удобно при использовании такого языка, как C#, в котором инициализация аргументов происходит немедленно.

static Random rnd = new Random();
static void UseRandomArgument(Lazy<int> a0, Lazy<int> a1) {
int res;
if (rnd.Next(2) == 0)
    res = a0.Value;
else
    res = a1.Value;
  Console.WriteLine("result = {0}", res);
}

Как хорошо видно в данном примере, один из аргументов метода может не использоваться вовсе.

var calc1 = Lazy.New(() => {
    Console.WriteLine("Calculating #1");
return 42;
  });
var calc2 = Lazy.New(() => {
    Console.WriteLine("Calculating #2");
return 44;
  });
UseRandomArgument(calc1, calc2);
UseRandomArgument(calc1, calc2);

Напишем обработчик для данного метода и посмотрим, какие из аргументов будут проинициализированы:

Calculating #1
Result = 42
Result = 42

Повторим запуск приложения:

Calculating #1
Result = 42
Calculating #2
Result = 44

Пример: Список шрифтов с предосмотром.

 

На картинке ниже представлен эскиз нашего будущего приложения. Он содержит выпадающий список с наименованиями шрифтов, а так же область, в которой будет выводится изображение для выбранного шрифта. Как не трудно догадаться при заполнении списка не очень бы хотелось инициализировать все картинки в память компьютера, в связи с чем мы воспользуемся созданным нами классом Lazy<T>.

Наш класс для хранения информации о шрифтах будет следующим:

private class FontInfo {
public Lazy<Bitmap> Preview { get; set; }
public string Name { get; set; }
}

Метод для генерации и отрисовки изображения шрифта:

private void DrawFontPreview(FontFamily f, Bitmap bmp) {
  Rectangle rc = new Rectangle(0, 0, 300, 200);
  StringFormat sf = new StringFormat();
  sf.Alignment = StringAlignment.Center;
  sf.LineAlignment = StringAlignment.Center;
string lipsum = "Lorem ipsum dolor sit amet, consectetuer " +
    "adipiscing elit. Etiam ut mi blandit turpis euismod malesuada. " +
    "Mauris congue pede vitae lectus. Ut faucibus dignissim diam. ";
using (Font fnt = new Font(f, 15, FontStyle.Regular))
using (Graphics gr = Graphics.FromImage(bmp)) {
    gr.FillRectangle(Brushes.White, rc);
    gr.DrawString(lipsum, fnt, Brushes.Black, rc, sf);
  }
}

На загрузке формы нашего приложения связываем наши значения с методом выбора шрифта из списка.

private void FontForm_Load(object sender, EventArgs e) {
  var fontInfo = FontFamily.Families.Select(f => {
// Создаем значение по требованию для картинки
      var preview = Lazy.New(() => {
          Bitmap bmp = new Bitmap(300, 200);
          DrawFontPreview(f, bmp);
return bmp;
        });
// Возвращаем шрифт с названием и превьюшкой
      return new FontInfo { Name = f.Name, Preview = preview };
    });
// Используем дата-байдинг для заполнения списка
  fontCombo.DataSource = fontInfo.ToList();
  fontCombo.DisplayMember = "Name";
}

При изменении выбранного шрифта перерисовываем изображение:

private void fontCombo_SelectedIndexChanged(object sender, EventArgs e) {
  FontInfo fnt = (FontInfo)fontCombo.SelectedItem;
  fontPreview.Image = fnt.Preview.Value;
}

Заключение

В данной статье Вы ознакомились с реализацией паттерна “загрузка по требованию” на языке C#, данный шаблон предоставляет великолепные возможности откладывать вычисления до того момента, пока они не будут действительно необходимы. Так же вспомнили те возможности C# версии 3.0, которые делают код нагляднее, а его написание проще (Неявное объявление типов, анонимные методы и лямбда-выражения, операторы запросов, и анонимные типы)

Материалы

 

  1. http://msdn.microsoft.com/en-us/vcsharp/bb870976.aspx (При написании данной статьи я руководствовался данной работой, все рассмотренные примеры, взяты там же)
  2. Мартин Фаулер “Архитектура корпоративных приложений” (Идея данного паттерна изложена М. Фаулером в этой книге)

Обзор языка Boo! – как средства организации DSL Вашего приложения

boo-logo-128_med

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

В последнее время меня так и тянет насесть на какой-нибудь новенький язык программирования, особенно что-нибудь на типа Ruby или Python, но в связи с моей привязанностью среде разработки (Visual Studio, неверно это не очень хорошо – зависеть от IDE ;)) и затруднительной ситуацией с разработкой на ней на динамических языках (надеюсь это временное затруднение) от них пока пришлось отказаться. В то же время меня интересуют такие области как метапрограммирование и реализация DSL (Domain-Specific Language == проблемно-ориентированный язык приложения), и в этой связи видится мне, что Boo является весьма интересным языком. К тому же Boo — язык CLR, что очень даже не плохо для изучения.

Поэтому я решил, что когда я узнаю Boo и когда почувствую уверенность в Boo, я попробую реализовать DSL и реализовать именно на Boo для своего ближайшего проекта.

Что такое Boo?

Boo представляет собой open-source объектно-ориентированный статически типизированный язык программирования для CLR с Python’о-подобным синтаксисом, язык увидел свет в 2004 году из-под рук Rodrigo B. de Oliveira. В настоящее время последняя версия 0.8.2, но даже если нет еще версии 1.0, это действительно очень стабильной и зрелый язык, который можно использовать на производстве.

Основные концепции в Boo:

  1. Дать компилятору сделать большую часть работы, для того чтобы помочь языку выглядеть более динамическим с автоматическим объявлением переменных, выводом и приведением типов.
  2. В то же время он предоставляет возможности для выполнения статической компиляции, проверку ошибок во время компиляции.
  3. Boo также предоставляет функциональную составляющую в том, что функции могут использоваться в качестве возвращаемого значения, как аргументы, хранимые в переменных, а так же как объекты.
  4. Boo имеет первоклассные генераторы, это конструкций, способные производить более одного значения при использовании итерации цикла (“return a for a in apples if a.IsRipe”).
  5. Boo также поддерживает утиную типизацию (Duck Typing), которая позволяет отказаться от обеспечения безопасности статических типов и принимать любой объект, который просто имеет соответствующие методы и свойства, определяемые во время выполнения.
  6. Boo также имеет расширения методов и свойств (extension methods and extension properties).

Одним из наиболее интересных функций Boo является расширяемость процесса компиляции, которая позволяет управлять компиляцией и изменять или добавлять функции. Можно добавить подпрограмм для проверки конвенции кода, генерирования отчётов или преобразовывания кода. То, что Вы сможете сделать в C# с помощью тулзы посткомпиляции такой, как PostSharp и только ограниченный набор действий. В Boo Вы могли бы например автоматически преобразовать класс в одноэкземплярный (pattern Singleton), просто добавив атрибут следующим образом:

[singleton]
class MySingleton: pass

PostSharp просто не смог бы сделать этого, свойство экземпляра было бы обработано поздно. Это действительно открывает множество возможностей и Вы ограничиваетесь только Вашим пониманием внутренней функциональности компилятора и набора его возможностей.

В Boo пробелы имеют важное значение как в python, но есть возможность включить режим “Whitespace Agnostic”, позволяющий оканчивать выражение с помощью “end”, который избавит Вас от возможных проблем с пробелами.

Что нужно для начала работы с Boo?

Главным образом если Вы хотите узнать Boo, достаточно иметь последнюю версию Boo . В папке bin, Вы найдете файл “Booish.exe”, являющийся интерпретатором командной строки Boo, которая позволяет проиграться с синтаксисом языка.image

Для разработки нам необходима IDE, и следовательно у нас два варианта.

Большинство Boo разработчиков работают с SharpDevelop , и если Вы скачаете последнюю версию, в ней будет Boo полностью готовый к использованию. Эта IDE имеет преимущество, с точки зрения создания DSL, так как в ней легче добавить функции автозавершения кода и подсветки синтаксиса, в Visual Studio же потребуются написать лексер и парсер; в SharpDevelop можно сделать это с помощью XML-файла.

Но с другой стороны Visual Studio является зрелой IDE, и с BooLangStudio вы получите Boo интегрированный в Visual Studio. Люди жалуются, что проект является нестабильным и это лишь альфа выпуск, так же я встретился в нём с проблемами уникода (UTF8), которые пока не смог разрешить, но у меня пока нет весомых замечаний.

В настоящее время я буду пользоваться Visual Studio в силу привычки, но я могу изменить свой взгляд при продолжении этой статьи.

При написании данного поста я руководствовался данной работой, можно даже сказать переводил, но перевод очень личный и свободный.

Продолжение следует…


Мартин Фаулер «Рефакторинг: улучшение существующего кода»

Рефакторинг: улучшение существующего кода

Оригинал книги:

«Refactoring: Improving the Design of Existing Code» by Martin Fowler датируется 2000 годом, но хотелось бы заметить, что книга ничуть не потеряла своей актуальности и по сей день.

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

Автор выделяет и подробно рассматривает порядка 30 видов рефакторингов, а так же подробно описывает методологию проведения рефакторинга.

После прочтения невольно сел и поправил несколько мест в своём коде, которые «попахивали» описанным в книге «душком кода». Думаю буду делать это и впредь, чего и всем советую.