вторник, 14 декабря 2010 г.

5 правил для хороших тестов

В книге "Чистый код", красиво описываются требования к тестам.

Чистые тесты должны обладать пятью характеристиками, названия которых образуют приведенное сокращение FIRST

  • Быстрота (Fast). Тесты должны выполняться быстро. Если тесты выполняются медленно, вам не захочется часто запускать их. Без частого запуска тестов проблемы не будут выявляться на достаточно ранней стадии, когда они особенно легко исправляются. В итоге вы уже не так спокойно относитесь к чистке своего кода, и со временем код начинает загнивать.
  • Независимость (Independent). Тесты не должны зависеть друг от друга. Один тест не должен создавать условия для выполнения следующего теста. Все тесты должны выполняться независимо и в любом порядке на ваше усмотрение. Если тесты зависят друг от друга, то при первом отказе возникает целый каскад сбоев, который усложняет диагностику и скрывает дефекты в зависимых тестах.
  • Повторяемость (Repeatable). Тесты должны давать повторяемые результаты в любой среде. Вы должны иметь возможность выполнить тесты в среде реальной эксплуатации, в среде тестирования или на ващем ноутбуке во время возвращения домой с работы. Если ваши тесты не будут давать однозначных результатов в любых условиях, вы всегда сможете найти отговорку для объяснения неудач. Также вы лишитесь возможности проводить тестирование, если нужная среда недоступна.
  • Очевидность (Self-Validating). Результатом выполнения теста должен быть логический признак. Тест либо прошел, либо не прошел. Чтобы узнать результат, пользователь не должен читать журнальный файл. Не заставляйте его вручную сравнивать два разных текстовых файла. Если результат теста не очевиден, то отказы приобретают субъективный характер, а выполнение тестов может потребовать долгой ручной обработки данных
  • Своевременность (Timely). Тесты должны создаваться своевременно. Модульные тесты пишутся непосредственно перед кодом продукта, обеспечивающим их прохождение. Если вы пишете тесты после кода продукта, вы можете решить, что тестирование кода продукта создает слишком много трудностей, а все из-за того, что удобство тестирования не учитывалось при проектировании кода продукта.

среда, 24 ноября 2010 г.

Создание пользовательского логотипа в SSRS отчете.

Недавно передо мной встала задача вместо статического логотипа в SQL server reporting service сделать показ лого, которое храниться базе. Следует отметить, что отчет хранится внутри приложения, не на сервере SSRS.

Погуглив я нашел три способа сделать это:
1) Передавать картинку в параметрах
2) Использовать дополнительный DataSource к базе в отчете
3) Создать SubReport с лого и включать его во все репорты.

По идее наиболее просто это создать сабрепорт и использовать его во всех отчетах, но оказалось, что его нельзя вставить в header отчета.

С DataSource тоже не сразу получилось, оказывается контрол Image в заголовке не может ссылаться на DataSource. MSDN подсказал финт ушами - создаем невидимый textbox, он вычитывает данные из DataSource, а картинка в заголовке уже берет данные из textbox. Реализовал эту стратегию, но кода получилось довольно много.

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

Формируем параметр:

byte[] logo = GetLogoFromDB();
string paramLogo = Convert.ToBase64String(logo);

Передаем его в отчет:

ReportViewer.LocalReport.SetParameters(
new List<ReportParameter>()
{
new ReportParameter("logo", paramLogo )
});

В самом отчете создаем параметр "logo" а для картинки ставим
value=System.Convert.FromBase64String(Parameters!logo.Value)

В итоге кода не очень много и получаем наше кастомное лого в отчете.

Описание решений по работе с картинками в SSRS:
Images (Report Builder 3.0 and SSRS)
http://technet.microsoft.com/en-us/library/dd239394.aspx

пятница, 25 июня 2010 г.

Базовые знания Javasript необходмые для использования JQuery

Одно из главных премуществ применения jQuery в веб-приложениях - возможность выполнять много сценариев без необходимости писать эти сценарии. jQuery позволяет нам сконцентрироваться на создании своих приложений и заставлять их делать то, что они должны делать!
Чтобы писать и понимать селекторы jQuery достаточно было лишь самых элементарных навыков работы c Java-Script и CSS. Для более сложных задач, таким как обра-ботка событии, анимация и Ajax, требуется понимать основные концепции JavaScript, направленные на эффективное использование библиотеки jQuery.
Наиболее важные из этих концепций касаются того, как JavaScript определяет и работает с функциями, а именно - подхода, при котором функции являются обычными объектами JavaScript. Чтобы понять, как функция может быть объектом, мы должны прежде всего убедиться в понимании того, что представляет из себя собственно объект JavaScript. Итак, приступим.



1. Основные сведения об объекте Object языка JavaScript
Большинство объектно-ориентированных (ОО) языков определяют базовый тип Object, как порождающий все другие объекты. В языке JavaScript тоже есть базовый объект Object, который служит основой для всех других объектов, но этим сходство и ограничивается. По сути, у объекта Object мало общего с базовыми объектами, определяемыми в родственных объектно-ориентированных языках.
На первый взгляд. Object - скучный и обыденный элемент. После создания он не содержит никаких данных и предоставляет минимум семантических действий. Но такая ограниченная семантика в действительности дает ему большой потенциал.
Давайте посмотрим, каким образом.

1.1. Как создаются объекты
Новый объект создается с помощью оператора new в паре с конструктором Object. Объект создается просто:
    var shinyAndNew = new Object();
Можно сделать это еще проще (как мы вскоре увидим), но пока будем поступать именно так.
Но что можно сделать с этим новым объектом? У него, казалось бы, ничего нет: ни информации, ни сложной семантики, ничего. Наш совершенно новый, чистый объект не представляет интереса до тех пор, пока мы не начнем добавлять к нему некоторые атрибуты, называемые свойствами.

1.2. Свойства объектов
Подобно своим серверным аналогам, объекты JavaScript могут содержать данные и обладать методами (например, сортировки, но не будем спешить). В отличие от своих серверных собратьев, эти элементы в объекте заранее не объявлены, мы создаем их динамически, по мере необходимости.
Взгляните на следующий фрагмент:
    var ride = new Object();
    ride make = 'Yamaha';
    ride model = 'V-Star Silverado 1100';
    ride year = 2005;
    ride purchased = new Date(2005,3,12);
Мы создаем новый экземпляр Object и присваиваем его переменной ride. Затем наполняем эту переменную рядом свойств различных типов: два строковых свойства, числовое свойство и свойство типа Date.

Нам не надо объявлять эти свойства до операции присваивания, они появляются автоматически, в момент присваивания им значений. Это чрезвычайно мощная особенность, дающая нам большую гибкость. Но не будем слишком легкомысленными, помня о том, что за гибкость придется платить!
Предположим, нам требуется изменить значение даты покупки:
    ride purchased = new Date(2005,2,1);
Ничего страшного... если мы случайно не сделаем опечатку, например:
    ride purcahsed = new Date(2005,2,1);
Здесь нет компилятора, который предупредил бы вас о сделанной ошибке; новое свойство с именем purcahsed, с готовностью созданное по вашему требованию, позже заставит задуматься о том, почему вы не получили новую дату, обратившись к свойству с правильно указанным именем.
С большими возможностями приходит большая ответственность (вы уже слышали об этом?), так что печатайте внимательно!

Из этого примера мы узнали, что экземпляр Object в языке JavaScript, который мы далее будем называть просто объект, - это набор свойств, каждое из которых состоит из имени и значения. Имя свойства - это строка, а значение может быть любым объектом JavaScript, таким как Number, String, Date, Array, Object или любой другой тип JavaScript (в том числе и функция, как мы увидим ).
Таким образом, основная цель экземпляра Object заключается в том, чтобы служить контейнером для именованных наборов других объектов. Это может напомнить концепции других языков, например отображение (тар) в языке Java или словари и хеши в других языках.
Обращаясь к свойствам, мы можем по цепочке ссылаться на свойства объектов, выступающих в качестве свойств родительского объекта. Предположим, мы добавили к нашему объекту ride новое свойство, описывающее владельца транспортного средства. Это свойство - еще один объект JavaScript, который в свою очередь содержит такие свойства, как имя и профессия владельца:
    var owner = new Object();
    owner name = 'Spike Spiegel';
    owner occupation = 'bounty hunter';
    ride owner = owner;


Обращение к вложенным свойствам можно описать так:
    var ownerName = ride.owner.name
Здесь нет никаких ограничений на глубину вложенности (за исключением здравого смысла).
Между прочим, нет никакой необходимости создавать промежуточные переменные (такие как owner) - мы создали их в этих фрагментах программного кода исключительно для наглядности. Далее вы увидите более эффективные и компактные способы объявления объектов и их свойств.
До этого момента мы ссылались на свойства объекта с помощью оператора «точка» (символ точки), но, как выясняется, это синоним более общего оператора для выполнения ссылок на свойства.
Что если, к примеру, у нас есть свойство с именем color scheme? Заметили точку в середине имени? Это портит все дело, потому что интерпретатор JavaScript будет пытаться найти scheme как вложенное свойство color.
«Тогда просто не делайте так!» - скажете вы. Но как быть с пробельными символами? Как быть с другими символами, которые могут восприниматься как разделители, а не как часть имени? И, что самое главное, мы даже не знаем, чем является это свойство - значением другой переменной или результатом выражения.
Для всех этих случаев оператор «точка» не подходит, и для доступа к свойствам мы должны выбрать более общее обозначение. Вот более общий формат обращения к свойствам:
   object[propertyNameExpression]

propertyNaweExpression - выражение JavaScript, которое определяется как строка, формирующая имя свойства, к которому происходит обращение. Например, все три следующие ссылки эквивалентны:
    ride.make
    ride['make']
    ride['m'+ a'+'k +'e']
Также как:
    var p = 'make';
    ride[p];
Применение общего оператора ссылки - единственный способ обратиться к свойствам, имена которых не являются допустимыми идентификаторами JavaScript, например:
    ride["a property name that's rather odd'']
Такие имена содержат символы, недопустимые для идентификаторов JavaScript, или являются значениями других переменных.
Построение объектов путем создания новых экземпляров с помощью оператора new и присваивание значений каждому свойству с помощью отдельных операторов - утомительное занятие. В следующем разделе мы рассмотрим более компактные и удобочитаемые способы объявления объектов и их свойств.

1.3. Литералы объектов
в предыдущем разделе мы создали объект, моделирующий некоторые свойства мотоцикла, и присвоили его переменной с именем ride. Мы сделали это с помощью двух операторов new, промежуточной переменной с именем owner и тучи операторов присваивания. Это утомительно, кроме того, приходится вводить с клавиатуры много текста, что способствует появлению ошибок и делает затруднительным визуальное восприятие структуры объекта при просмотре кода.
К счастью, мы можем использовать более компактную и удобную для визуального восприятия запись.
Рассмотрим инструкцию:
var ride = {
make: 'Yamaha',
model: 'V-Star Silverado 1100',
year: 2005,
purchased: new Date(2005,3,12),
owner: {
    name:  'Spike Spiegel',
    occupation: 'bounty hunter'
    }
};

в этом фрагменте с помощью литерала объекта создается тот же самый объект ride, который в предыдущем разделе мы создали с помощью операторов присваивания.

Большинство авторов страниц отдают предпочтение такой форме записи, называемой JSON (JavaScript Object Notation), когда при построении объекта приходится использовать множество операций присваивания. Структура этой формы записи очень проста - объект обозначается парой фигурных скобок, внутри которых через запятую перечислены свойства. Каждое свойство обозначается путем записи его имени и значения, разделенных символом двоеточия.
Как видно из объявления свойства owner, объявления объектов могут быть вложенными.
Кстати, точно так же в формате JSON можно описывать массивы, поместив список элементов, разделенных запятыми, в квадратные скобки:
    var someValues = [2,3,5,7,11,13,17,19,23,29,31,37];
Как показано в примерах этого раздела, ссылки на объекты часто хранятся в переменных или в свойствах других объектов. Рассмотрим особый случай последнего сценария.

1.4. Объекты как свойства объекта window
До этого момента мы видели два способа хранения ссылок на объекты JavaScript - в переменных и в свойствах. Эти два способа хранения ссылок записываются по-разному, как показано в следующем фрагменте:
    var aVanable = 'Before I teamed up with you, I led quite a normal life. ';,
    someObject.aProperty = 'You move that line as you see fit for yourself. ';
В этих двух инструкциях два экземпляра String (созданные с помощью литералов) присваиваются переменной и свойству объекта соответственно, с помощью операторов присваивания.

Но действительно ли эти инструкции выполняют разные операции? Как выясняется - нет!
Когда ключевое слово var используется на глобальном уровне, за пределами какой-либо функции, эта удобная для программиста форма записи является всего лишь ссылкой на свойство предопределенного объекта JavaScript window. Любая глобальная ссылка неявно превращается в свойство объекта window.
Это означает, что эквивалентны все следующие инструкции:
    var foo = bar;
и
    window.foo = bar,
и
   foo = bar;
Независимо от формы записи во всех трех случаях создается свойство объекта window с именем foo (если оно еще не существовало), и ему присваивается значение bar. Кроме того, поскольку идентификатор bar никак не квалифицирован, предполагается, что он представляет собой имя свойства объекта window.
Надеемся, вы не подумали, что глобальная область видимости - это область видимости объекта window, потому что любые неквалифицированные глобальные ссылки подразумевают ссылки на свойства объекта window. Правила области видимости еще усложнятся, когда мы углубимся в изучение тел функций, причем сильно усложнятся, и случится это достаточно скоро.
На этом обзор объекта Object в языке JavaScript можно считать практически завершенным. Здесь были рассмотрены следующие важные понятия:

  • Объект в языке JavaScript - это неупорядоченный набор свойств.
  • Свойство состоит из имени и значения.
  • Можно объявлять объекты посредством литералов объектов.
  • Глобальные переменные являются свойствами объекта window.

Теперь посмотрим, что имелось в виду под словами «функции в JavaScript - это обычные объекты».

2. Функции как обычные объекты
Во многих традиционных объектно-ориентированных языках объекты могут содержать данные и обладать методами, В этих языках данные и методы, как правило, - не одно и то же, но язык JavaScript пошел другим путем.

В языке JavaScript функции считаются объектами, подобно объектам любого другого типа, определенного в JavaScript, например String, Number или Date. Как и другие объекты, функции определяются конструктором JavaScript, в данном случае - Function, и могут:

  • присваиваться переменным;
  • присваиваться свойствам объектов;
  • передаваться в виде параметров;
  • возвращаться как результат других функций;
  • создаваться с использованием литералов.

Поскольку в некоторых случаях функции рассматриваются как объекты, мы говорим, что функции - это обычные объекты.
Вы могли бы подумать, что функции кардинально отличаются от объектов других типов, таких как String или Number, потому что они обладают не только значением (тело функции, если речь идет об экземпляре Function), но еще и именем.
Не спешите с выводами!

2.1. Что есть имя?
Большинство программистов JavaScript напрасно полагают, что функции являются именованными сущностями. Это не так. Если вы один из таких программистов, то вас сбили с толку искусно замаскированные уловки. Как и в случае с экземплярами других объектов, будь то String, Date или Number,- на функции ссылаются, только когда они присваиваются переменным, свойствам или параметрам.
Рассмотрим объекты типа Number. Мы часто описываем экземпляр Number буквенным обозначением, таким как 213. Инструкция
    213;
вполне правильна, но совершенно бесполезна. Экземпляр Number не всегда полезен, если не присваивается свойству или переменной или не связан с именем параметра. В противном случае, мы не сможем обратиться к такому экземпляру.
Это же относится и к экземплярам объектов Function.
«Стоп-стоп-стоп, - скажете вы. - А как насчет следующего фрагмента программного кода?»
    function doSomethingWonderful() {
        alert('does something wonderful');
    }
«Разве такое объявление не создает функцию с именем doSomethingWonderful
Нет, не создает. Несмотря на то что запись может показаться знакомой и часто используется для создания глобальных функций, это тот же самый синтаксический подсластитель, который использует ключевое var для создания свойств window. Ключевое слово function автоматически создает экземпляр Function и присваивает его свойству window, имя которого совпадает с «именем» функции (то, что мы ранее назвали искусно замаскированными уловками), как показано в следующем примере:

    doSomethingWonderful = function() {
       alert('does something wonderful');
    }
Если это объявление выглядит странным, взгляните на другую инструкцию, где используется точно такой же формат, за исключением того, что здесь участвует литерал Number:
     aWonderfulNumber = 213;
Здесь нет ничего странного, и инструкция присваивания функции глобальной переменной (свойству объекта window) ничем не отличается - литерал функции используется для создания экземпляра Function, а затем присваивается переменной doSomethingWonderful так же, как литерал 213 объекта Number был использован для присваивания экземпляра Number переменной aWonderfulNumber.
Если вы никогда раньше не встречались с синтаксисом литерала функции, это может показаться странным. Он состоит из ключевого слова function, за которым идет список параметров, заключенный в круглые скобки, и далее следует тело функции.
Когда мы объявляем глобальную именованную функцию, создается экземпляр Function и присваивается свойству объекта window, которое создается автоматически, на основе так называемого имени функции. Сам по себе экземпляр Function не имеет имени, как литерал Number или String.
Помните, что, когда в HTML-странице создается глобальная переменная, она создается как свойство объекта window. Поэтому все следующие инструкции эквивалентны:
    function hello(){ alert('Hi there!');  }

    hello = function(){ alert('Hi there!');   }
    window.hello = function(){ alert('Hi there!');  }
Хотя все это может показаться синтаксическими манипуляциями, очень важно понять, что экземпляры Function являются значениями, которые можно присвоить переменным, свойствам или параметрам, а также экземплярам объектов других типов. И подобно этим объектам других типов безымянные экземпляры нельзя использовать, если они не связаны с переменными, свойствами или параметрами, через которые на них можно сослаться.
Мы посмотрели примеры присваивания функций переменным и свойствам - а как насчет передачи функции в качестве параметра? Давайте посмотрим, зачем и как можно это сделать.

2.2. Функции обратного вызова
Глобальные функции хороши, когда наш программный код следует красивым и упорядоченным синхронным потоком, но характерной чертой HTML-страниц сразу после загрузки является асинхронность. Будь то обработка событий, установка таймеров или выполнение запросов Ajax, программный код веб-страницы по своей природе является асинхронным. И одно из самых распространенных понятий в асинхронном программировании - понятие функции обратного вызова.
Возьмем в качестве примера таймер. Мы можем заставить таймер сработать, например, через пять секунд, передав соответствующее значение длительности методу window.setTimeout(). Но каким образом этот метод сообщит нам о том, что время таймера истекло, чтобы мы могли выполнить необходимые действия по истечении времени ожидания? Делается это путем вызова функции, которую мы предоставим.
Рассмотрим следующий программный код:
    function hello() { alert('Hi there!'); }
    setTimeout( hello, 5000);

Мы объявляем функцию с именем hello и устанавливаем таймер на 5 секунд, заданных во втором параметре как 5000 миллисекунд. В первом параметре мы передаем методу setTimeout() ссылку на функцию. Передача функции в виде параметра ничем не отличается от передачи любого другого значения - точно так же мы передали во втором параметре значение типа Number.
Когда время таймера истечет, будет вызвана функция hello. Поскольку метод setTimeout() делает обратный вызов функции в нашем собственном программном коде, эту функцию называют функцией обратного вызова.
Этот пример программного кода покажется наивным большинству опытных программистов JavaScript, поскольку создание имени hello не является необходимостью. Если функцию не требуется вызвать где-нибудь в другом месте страницы, нет никакой необходимости создавать свойство hello в объекте window, чтобы на мгновение сохранить экземпляр Function и потом передать его в качестве параметра.
Вот более изящный способ записи этого фрагмента:
    setTimeout(function() { alert('Hi there' ); },5000);
Здесь мы определяем функцию непосредственно в списке параметров в виде литерала, и нет никакой нужды создавать имя. Это - идиома, которая часто будет нам встречаться в программном коде jQuery, когда нет необходимости присваивать экземпляр функции глобальному свойству.
Функции, которые мы до сих пор создавали в примерах, - это либо глобальные функции (которые, как мы знаем, являются свойствами объекта window), либо параметры других функций. Мы также можем присваивать экземпляры Function свойствам объектов, и эта возможность действительно представляет интерес.

2.3. К чему это все?
Объектно-ориентированные языки программирования автоматически предоставляют средства для получения ссылки на текущий экземпляр объекта внутри метода. В таких языках, как Java и C++, на текущий экземпляр указывает переменная с именем this. В JavaScript тоже есть подобное понятие и даже используется то же самое ключевое слово this, которое обеспечивает доступ к объекту, связанному с функцией. Но будьте внимательны! Реализация this в JavaScript отличается от аналогов других объектно-ориентированных языков едва различимым, но существенным образом.
В объектно-ориентированных языках, основанных на классах, указатель this, как правило, ссылается на экземпляр класса, в пределах которого был объявлен метод. В JavaScript, где функции являются обычными объектами, они не объявляются как часть чего-либо. Объект, на который ссылается this, называется контекстом функции и определяется не тем, как функция объявляется, а тем, как она вызывается.

Это означает, что одна и та же функция может иметь различный контекст в зависимости от того, как она вызывается. На первый взгляд, это кажется странным, но может оказаться весьма полезным.
По умолчанию контекст (this) функции - это объект, свойство которого содержит ссылку для вызова функции. Давайте вернемся к нашему примеру с мотоциклом и изменим создание объекта (дополнения выделены жирным шрифтом):
    var ride = {
     make: 'Yamaha',
     model: 'V-Star Silverado 1100',
     year: 2005,
     purchased: new Date(2005,3,12),
     owner: {name: 'Spike Spiegel', occupation: 'bounty hunter' },
     whatAnI: function() {
       return this.year + '  '+ this.make + '  ' + this.model;
    }
  };
К первоначальному коду примера мы добавили свойство с именем WhatAmI, которое ссылается на экземпляр Function.
Если функция вызывается через свойство
    var bike = ride.whatAml();

то в качестве контекста функции (ссылка this) устанавливается экземпляр объекта, на который указывает ride. В результате в переменную bike записывается строка 2005 Yamaha V-Star Silverado 1100, потому что функция выбирает с помощью this значения свойств объекта, посредством которого она была вызвана.
То же справедливо и для глобальных функций. Помните, что глобальные функции являются свойствами объекта window, поэтому контекстом таких функций при их вызове как глобальных функций является
объект window.
Хотя такое неявное поведение вполне обычно, JavaScript позволяет нам четко установить, что будет использоваться в качестве контекста функции. Мы можем передать в контексте функции все, что угодно, вызвав функцию с помощью метода са11() или apply() экземпляра Function.
Кроме того, будучи обычными объектами, даже функции имеют методы, определяемые конструктором Function.
Метод call() вызывает функцию, передавая в качестве первого параметра объект, который является контекстом функции, а в качестве остальных параметров передаются параметры вызываемой функции - вторым параметром метода са11() становится первый аргумент вызываемой функции и т. д. Метод арр1у() работает аналогично, за исключением того, что вторым параметром он ожидает получить массив объектов, которые становятся аргументами вызываемой функции.
Запутались? Пришло время для более обстоятельного примера. Рассмотрим следующую странцу:
 <html>
  <head>
   <title>Function Context Example</title>
   <script>
    var o1 = {handle   o1 };
    var o2 = {handle   o2 };
    var o3 = {handle   o3 };
    window.handle = 'window';

    function whoAml() {
      return this handle,;
   }

   o1.identifyMe = whoAmI;

   alert(whoAmI());
   alert(o1.identifyMe());
   alert(whoAmI.call(o2));
   alert(whoAmI apply(o3));
  </script>
 </head>
 <body>
 </body>
</html>

в данном примере мы определяем три простых объекта, у каждого из которых есть свойство handle, позволяющее легко идентифицировать объект по ссылке на него. Мы также добавляем свойство handle в экземпляр объекта window, чтобы его тоже можно было легко идентифицировать.
Затем мы определяем глобальную функцию, которая возвращает значение свойства handle для любого объекта, используемого в качестве контекста функции в, и присваиваем ту же самую функцию свойству identifyMe объекта о1. Можно сказать, что тем самым был создан метод объекта о1 с именем identifyMe, хотя важно отметить, что функция объявляется независимо от объекта.

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

  • Если функция вызывается как глобальная функция, контекстом функции является экземпляр объекта window.
  • Если функция вызывается как свойство объекта (о1 в данном случае), контекстом функции становится этот объект. Мы могли бы сказать, что функция действует как метод этого объекта - аналогично объектно-ориентированным языкам. Но не слишком радуйтесь этой аналогии. Вы можете сбиться с пути, если не будете осторожны, что показывает оставшаяся часть этого примера.
  • Использование метода са11() объекта Function приводит к тому, что контекстом функции становится любой объект, полученный методом са11() в качестве первого параметра, - в данном случае, о2. В этом примере функция действует как метод объекта о2 при том, что она никак не связана с объектом о2, даже как свойство.
  • Как и в случае с методом са11(), при использовании метода арр1у() контекстом функции становится любой объект, переданный в качестве первого параметра. Разница между этими двумя методами становится существенной, только когда параметры передаются функции (чего мы в этом примере не делали для простоты).

Этот пример страницы явно свидетельствует о том, что контекст функции определяется способом вызова и что одна и та же функция может быть вызвана с любым объектом, выступающим в качестве ее контекста. Поэтому, скорее всего, будет ошибкой сказать, что функция является методом объекта. Гораздо правильнее сказать так:
Функция f действует как метод объекта о, когда объект о выступает в качестве контекста функции при вызове функции f.
В качестве дополнительной иллюстрации данной концепции рассмотрим результат добавления к нашему примеру следующей инструкции:
    alert(o1.identifyMe.call(o3));
Даже при том, что мы ссылаемся на функцию как на свойство объекта о1, роль контекста функции в этом вызове играет объект оЗ. Далее подчеркнем еще раз, что дело не в том, как функция объявляется, а в том, как она вызывается, что и определяет контекст функции.
При использовании команд и функций jQuery применяются функции обратного вызова, что доказывает важность этой концепции.

Теперь, когда мы понимаем, каким образом функции могут действовать в качестве методов объектов, перейдем к другой достаточно сложной теме, важной для эффективного использовании jQuery, - к замыканиям.

2.4. Замыкания
Для авторов страниц, пришедших из традиционного объектно-ориентированного или процедурного программирования, замыкания часто являются странным понятием, тогда как для тех, кто знаком с функциональным программированием, замыкания являются знакомым и удобным понятием. Что же такое замыкания?

Сформулируем просто, насколько это возможно: замыкание (closure) -это экземпляр Function вместе с локальными переменными из его окружения, необходимыми для выполнения.
При объявлении функция может ссылаться на любые переменные, находящиеся в ее области видимости на момент объявления. Эти переменные достижимы для функции даже после того, как текущее положение в объявлении выйдет из области видимости, замыкая объявление.
Возможность для функций обратного вызова ссылаться на локальные переменные, действующие на момент объявления, - важный инструмент создания эффективного программного кода JavaScript. Воспользовавшись таймером еще раз, посмотрим наглядный пример: получение доступа к окружению функции,
существовавшему на момент объявления, через замыкания
<html>
 <head>
  <title>Closure Example</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
   <script> $(function(){
    var local = 1;
    window.setInterval(function(){
     $('#display').append('<div>At '+new Date()+' local='+local+'</div>');
     local++;
   },3000);
});
</script>
</head>
<body>
 <div id='display'></div>
</body>
</html>


в данном примере мы определяем обработчик события готовности документа, который запускается после загрузки дерева DOM. В этом обработчике мы объявляем локальную переменную с именем local и присваиваем ей числовое значение 1. Затем с помощью метода window.setlnterval() взводим таймер, который будет срабатывать каждые 3 секунды. В качестве функции обратного вызова для таймера мы определяем встроенную функцию, которая ссылается на переменную local и показывает текущее время и значение переменной local, добавляя элемент <div> в элемент с именем display, определенный в теле страницы. Кроме того, внутри функции обратного вызова значение переменной local увеличивается.
Если бы мы были незнакомы с замыканиями, то до запуска этого примера могли бы заметить в его коде некоторые проблемы. Мы могли бы предположить, что поскольку функция обратного вызова запустится через три секунды после загрузки страницы (что произойдет далеко не сразу после того, как обработчик события готовности документа закончит выполняться), то во время выполнения функции обратного вызова значение переменной local окажется неопределенным. В конце концов, блок, в котором объявляется переменная local, выходит из области видимости, когда обработчик события готовности документа заканчивает работу, правильно?
Но после загрузки страницы, позволив ей отработать, через короткий промежуток времени мы увидим изображение:
AtTue Oct 23 2007 14:00:11 GMT-0500 (CDT) local=1
AtTue Oct 23 2007 14:00:14 GMT-0500 (CDT) local=2
AtTue Oct 23 2007 14:00:17 GMT-0500 (CDT) local=3
At Tue Oct 23 2007 14:00:20 GMT-0500 (CDT) local=4
At Tue Oct 23 2007 14:00:23 GMT-0500 (CDT) local=5
At Tue Oct 23 2007 14:00:26 GMT-0500 (CDT) local=6
At Tue Oct 23 2007 14:00:29 GMT-0500 (CDT) local=7
At Tue Oct 23 2007 14:00:32 GMT-0500 (CDT) local=8
At Tue Oct 23 2007 14:00:35 GMT-0500 (CDT) local=9

Она работает! Но каким образом?
Несмотря на то что блок, в котором объявляется переменная local, действительно выходит из области видимости, когда обработчик события готовности документа завершит работу, замыкание, созданное в объявлении функции, включающее в себя переменную local, остается в области видимости функции на протяжении всего жизненного цикла.
Стоит отметить, что это замыкание, как и все замыкания в JavaScript было создано неявно, поскольку нет необходимости явного синтаксиса, как это требуется в некоторых других языках, поддерживающих замыкания. Это обоюдоострый меч - с его помощью легко создать замыкание (предполагаете вы это или нет!), но он может и усложнить их реализацию в программном коде.
Непредусмотренные замыкания могут вызвать непредвиденные последствия. Например, циклические ссылки могут привести к утечкам памяти. Классический пример этого - создание элементов DOM, которые ссылаются на переменные в замыканиях, препятствуя удалению этих переменных.
Еще одна важная особенность замыканий заключается в том, что контекст функции никогда не является частью замыкания. Например, следующий фрагмент кода не будет выполняться, как можно было бы ожидать:
this id =  'somelD';
$('*').each(function(){
  alert(this.id);
});
Помните, что у каждого вызова функции собственный контекст функции, поэтому в приведенном выше программном коде контекст функции внутри функции обратного вызова, передаваемый методом each(), является элементом обернутого набора jQuery, а не свойством внешней функции, установленным в значение 'somelD'. Каждый вызов функции обратного вызова в свою очередь отображает окно предупреждения, где выводится значение атрибута id каждого элемента обернутого набора.
Получить доступ к объекту, выступающему в качестве контекста внешней функции, можно с помощью общей идиомы создания копии этой ссылки в локальной переменной, которая будет включена в замыкание. Рассмотрим следующие изменения в нашем примере:
this id = 'somelD';
var outer = this; 
$('*').each(function(){
alert(outer.id),
});
Локальная переменная outer, которой присваивается ссылка на контекст внешней функции, становится частью замыкания и будет доступна внутри функции обратного вызова. Теперь измененный программный код будет выводить предупреждение со строкой 'somelD' столько раз, сколько элементов в обернутом в наборе.

Замыкания действительно незаменимы для создания элегантного программного кода с применением команд jQuery, использующих асинхронные обратные вызовы, что особенно актуально в случае применения Ajax-запросов и обработки событий.

Заключение
JavaScript - это язык, широко распространенный в Сети, но многие авторы страниц, создающие веб-приложения, зачастую используют далеко не все его возможности. В этом Приложении мы представили часть глубинных аспектов языка, которые необходимо понимать, чтобы эффективно применять jQuery на своих страницах.
Мы увидели, что объект Object в языке JavaScript в первую очередь нужен затем, чтобы служить контейнером для других объектов. Если вы знакомы с объектно-ориентированным программированием, понимание экземпляра объекта как неупорядоченного набора пар имя/значение может оказаться далеким от того, что вы представляете себе под термином объект, но эта концепция важна при создании программного кода JavaScript, даже умеренной сложности.
Функции в JavaScript являются обычными объектами, которые могут быть объявлены и описаны таким же образом, как и объекты других типов. Мы можем объявлять их как литералы, сохранять в переменных и в свойствах объектов и даже передавать их другим функциям в виде параметров для использования в качестве функций обратного вызова.
Термин контекст функции описывает объект, на который указывает ссылка this внутри функции. Хотя функция может играть роль метода объекта, для чего объект должен быть определен как контекст функции, тем не менее функции не объявляются методами какого-то отдельного объекта. Контекст функции определяется способом вызова (возможно, под явным управлением вызывающей программы).
Наконец, мы видели, как объявление функции и ее окружение образуют замыкание, позволяющее функции при последующих вызовах получить доступ к локальным переменным, которые становятся частью замыкания.
Твердо усвоив эти понятия, можно решать задачи, стоящие перед нами при создании в наших страницах эффективных сценариев JavaScript с применением jQuery.

четверг, 18 марта 2010 г.

Настройка оповещений в MS Outlook

Давно пользуюсь Outlook для чтения корпоративной почты. Для личной переписки вполне хватает веб интерфейса Gmail + оповещение о новых письмах в браузере. Т.е. о получении новых личных писем я узнаю быстро.

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

Почему разработчики Outlook реализовали такое поведения не знаю, но достает это реально. Раньше все мои попытки, что либо настроить терпели неудачу. Все что удавалось это показывать оповещения о новых письмах, обработанных правилами в модальном окне, что не совсем удобно. И вот я наконец нашел решение, оказалось, что все таки нужно донастроить правила.

Допустим у нас есть набор готовых правил сортировки писем.

  1. Открываем Outlook, выбираем в меню Сервис -> Правила и оповещения
  2. Выбираем вкладку "Правила для электронной почты"
  3. Выбираем правило и в меню "Изменить параметры правила"
  4. Пропускаем "Какие сообщения следует отбирать?" и жмем "Далее"
  5. В разделе "Что следует сделать с сообщениями?" находим действие "вывести оповещение на рабочий стол", у меня это в самом низу списка
  6. Жмем "Готово"
В результате при получения сообщений, которые обрабатываются этим правилом, мы получим маленькое всплывающее окно с информацией о письме. Это позволит реагировать на письма быстрее.

среда, 3 марта 2010 г.

Руководство Microsoft по проектированию архитектуры приложений

Недавно был на конференции Microsoft посвященной VS2010 там порекламировали перевод руководства по проектированию архитектуры приложений.

Ребята из PATTERNS & PRACTICES выпустили новую версию, а наши перевели его на русский. Начал его читать и всем советую.

Цель данного руководства – помочь разработчикам и архитекторам решений создавать эффективные высококачественные приложения на платформе Microsoft и .NET Framework в более сжатые сроки и с меньшими рисками благодаря использованию проверенных и снискавших доверие архитектурных принципов и шаблонов проектирования.
В руководстве предлагается обзор основных принципов и шаблонов,
которые обеспечивают прочную базу для создания хорошей архитектуры и дизайна
приложения. В дополнение к этой базе даются общеприменимые рекомендации по
разделению функциональности приложения на слои, компоненты и сервисы. Далее приводятся советы по определению и реализации ключевых характеристик дизайна, основных атрибутов качества (таких как производительность, безопасность и масштабируемость) и сквозной функциональности (такой как кэширование и протоколирование). В завершение руководство предлагает рекомендации по архитектуре и дизайну наиболее общих типов приложений, таких как Веб-приложения, насыщенные Интернет-приложения (RIA), насыщенные клиентские приложения, сервисы и мобильные приложения.
Руководство разделено на части соответственно основным аспектам архитектуры и дизайна. Оно скомпоновано таким образом, чтобы могло использоваться и как справочник, и как учебное пособие.

Скачать его можно тут:

среда, 17 февраля 2010 г.

Преобразование Website в Web Application Projects

С появлением ASP.NET 2.0 и VS 2005 у разработчиков веб приложений появился новый тип проектов Website, который позволял изменять динамически не только дизайн страниц, но и  c# код. Этой возможностью многие стали пользоваться, но все это удобство достигается за счет того, что каждая страница и контрол компилируются по отдельности. При довольно большом размере проекта, компиляция занимает очень много времени. К тому же модель Website по умолчанию не добавляет namespace для страниц, что ведет к путанице и даже странным ошибкам компиляции.

У нас на проекте решили преобразовать существующий огромный Website в Web Application Projects. На первый взгляд казалось, что достаточно будет запустить визард конвертации, немного протестировать и все будет в порядке.
Открываю проект и ищу что то типа "Convert to web application", но не нахожу. Оказывается все намного сложнее.

Решение я нашел тут:
MSDN: Converting a Web Site Project to a Web Application Project in Visual Studio

Converting VS 2008 Website to Web Application

пятница, 5 февраля 2010 г.

Работа с Visual Studio 2008 на windows 7.

Пришлось переустановить window и опять встала проблема доустановки компонентов системы, которые нужны для разработки asp.net и wcf приложений.

1) Нужно установить компоненты для IIS 7
Подробней можно почитать тут
http://learn.iis.net/page.aspx/387/using-visual-studio-2008-with-iis-70/
Теперь наши веб проекты будут работать

2) Для wcf нужно же поставить еще и другие компоненты.
Все там же в разделе Microsoft .Net Framework выбираем Windows Communication  Foundation

А теперь уже заработает WCF и можно работать дальше.