msysGit + Plink

SET GIT_SSH=%ProgramFiles%\TortoiseGit\bin\TortoiseGitPlink.exe

Connascence

Для меня это очень странно, но данный термин или практика не получили широкого распространения в рускоязычном мире разработки ПО, и, видимо, по-этому данный термин даже не имеет перевода. Подсмотрим в The Free Dictionary что же это слово означает:

Con`nas´cence, существительное



1.  Одновременное рождение двух или более; одновременное производство двух и более вместе.
2.  То, что было рождено или произведено вместе с другим.
3.  Акт совместного взросления.

Я позволю себе перевести термин Connascence как "близнецовая связь" (может быть есть более подходящий перевод?). Итак, далее будет приблизительный перевод статьи из англоязычной Википедии.

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

Connascence – это метрика качества программного обеспечения разарботанная Меилиром Пейдж-Джонсом (Meilir Page-Jones) чтобы разрешить рассуждения о сложности, вызванные отношениями зависимости в объектно-ориентированном дизайне, подобно тому, как это делает связанность (coupling) в структурном дизайне. В дополнение, к возможности категоризировать отношения, "близнецовая связь" также предоставляет систему для сравнения различных типов зависимостей. Такое сравнение часто подсказывает пути улучшения качества программного обеспечения.

Метрики

Сила

Форма "близнецовой связи" считается более сильной, если требует больших компенсационных изменений в связанных элементах. Чем сильнее связь, тем сложнее и затратнее совершить изменения в связанных компонентах.

Степень

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

Локальность

Локальность имеет значение при анализе "близнецовой связи". Сильные формы "близнецовой связи" приемлемы, если связанные элементы расположены достаточно близко. Например, некоторые языки используют позиционные аргументы для вызова функций или методов. Эта "близнецовая связть по месту" приемлема из-за близкого расположения вызвающего и вызываемого кода, но вызов веб сервиса с использованием позицонных аргументов неприемлео, из-за достаточной отдаленности и несвязанности компонентов. "Близнецовые связи" с теми же силой и степенью будут иметь большую сложность и стоимость изменений, чем дальше связанные компоненты расположены.

Типы "близнецовых связей"

Далее представлен список близнецовых связей , остортированный приблизительно, от слабых до сильных.

Близнецовая связь по имени (Connascence of Name – CoN)

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

Близнецовая связь по типу (Connascence of Type – CoT)

Близнецовая связь по типу возникает, когда несколько компонентов должны согласовать тип сущности. В статически типизированных языках программирования, тип аргументов метода может являтся образцом такой связи. Например, если метод изменит тип принимаемого аргумента с целого (integer) на строку (string), то вызывающий код должен быть изменен, так, чтобы отразить эти изменения.

Близнецовая связь по смыслу (Connascence of Meaning – CoM)

Близнецовая связь по смыслу возникает, когда несколько компонентов должны согласовать смысл каких-то значений. Например, возврашение из метода 0 и 1 для обозначения true и false соответсвенно.

Близнецовая связь по месту (Connascence of Position – CoP)

Близнецовая связь по месту (по позиции, по расположению) возникает, когда несколько компонентов должны согласовать порядок значений. Примером близнецовой связи по месту могут служить позиционные аргументы в методе. Вызвающий и вызываемый код должны согласиться с семантикой первого, воторого и т.д. параметров.

Близнецовая связь по алгоритму (Connascence of Algorithm – CoA)

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

Близнецовая связь по исполнению (Connascence of Execution – CoE)

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

Близнецовая связь по времени (Connascence of Timing – CoT)

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

Близнецовая связь по значениям (Connascence of Values – CoV)

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

Близнецовая связь по идентификатору (Connascence of Identity – CoI)

Близнецовая связь по идентификатору возникает, когда несколько компонетов должны ссылаться на какую-то сущность.

Уменьшение "близнецовой связи"

Уменьшение "близнецовой связи" будет уменьшать стоимость изменения программной системы. Один из путей уменьшения "близнецовой связи" - это замена более сильных связей более слабыми. Другой путь - это уменьшение степени и увеличение локальности связанных элементов.

Блог переехал на Jekyll и GitHub Pages

Перевел блог с tumblr на Jekyll и GitHub Pages. Вроде-бы миграция прошла отлично, и все работает.

Некоторые причны этого.

  1. Хотел писать посты в markdown. По этой же причине в прошлый раз перешел на Tumblr.
  2. Бесплатный хостинг)
  3. Полный контроль над блогом. Tumblr любит добавлять всякие свои виджеты. Бррр.
  4. Блог по-умолчанию под контролем версий. Tumblr грешил с тем, что иногда верстка постов слетала и приходилось все исправлять.
  5. Если нашли ошибку, то можете послать мне pull-request (Для этого нужно нажать на иконку с карандашом рядом с заголовком поста).

RSS/Atom

Если вы читали меня через RSS (надеюсь, что кто-то еще читает меня и ждет, когда я тут что-нибдуь напишу), но не через feedburner.com, то пожалуйста, обновите свои закладки на blog.hazzik.ru/atom.xml.

PS

Надеюсь, что буду писать чаще. Честно-честно.

Читайте меня на английском

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

Вычисляемые поля для любого LINQ-провайдера

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

Зачем это может понадобиться - под катом.

Intro

В жизни случается, что в LINQ нужно использовать вычисляемое поле, к примеру у нас есть класс Employee с вычисляемым полем FullName

class Employee
{
    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }

    public string LastName { get; set; }

    public string FirstName { get; set; }
}

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

var employees = (from employee in db.Employees
                 where (employee.FirstName + " " + employee.LastName) == "Test User"
                 select employee).ToList();

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

public class WayPoint 
{
    // все остальное опущено в целях наглядности
    public virtual bool IsValid
    {
        get 
        {
            return (Account == null) ||
               (Role == null || Account.Role == Role) &&
               (StructuralUnit == null || Account.State.StructuralUnit == StructuralUnit);
        }
    }
}

С этим сложнее. Итак, приступим. Что же у нас есть для решения таких задач?

<formula> в NHibernate

Если вы используете NHibernate, то можете замапить данное поле как формулу, но этот путь не очень дружелюбен к рефакторингу, к тому же <formula> поддерживает только sql, и если вы пишете приложение, которое планируется использовать с разными базами данных, то здесь вам нужно быть особенно осторожными.

Поддреживается только в NHibernate.

Microsoft.Linq.Translations

Для этого необходимо переписать наш класс и запрос следующим образом:

class Employee 
{
    private static readonly CompiledExpression<Employee,string> fullNameExpression
     = DefaultTranslationOf<Employee>.Property(e => e.FullName).Is(e => e.FirstName + " " + e.LastName);

    public string FullName 
    {
        get { return fullNameExpression.Evaluate(this); }
    }

    public string LastName { get; set; }

    public string FirstName { get; set; }
}

var employees = (from employee in db.Employees
                 where employee.FullName == "Test User"
                 select employee).WithTranslations().ToList()

Все хорошо, запрос выглядит красиво, а вот объявление свойства - просто ужасно. К тому же Evaluate компилирует ?-выражение в момент исполнения, что, на мой взгляд не менее ужасно, чем задание вычисляемого поля.

И, наконец, мы подошли к моему творениею - DelegateDecompiler

DelegateDecompiler

Все что нужно, это вычисляемое поля пометить атрибутом [Computed], а запрос преобразовать с помощью метода .Decompile()

class Employee 
{
    [Computed]
    public string FullName 
    {
        get { return FirstName + " " + LastName; }
    }

    public string LastName { get; set; }

    public string FirstName { get; set; }
}

var employees = (from employee in db.Employees
                 where employee.FullName == "Test User"
                 select employee).Decompile().ToList()

По-моему изящно (сам не похвалишь - никто не похвалит)

При вызове .Decompile() декомпилятор найдет все свойства и методы, помеченные атрибутом [Computed] и развернет их. Т.е. запрос будет преобразован к виду, из первоначального примера:

var employees = (from employee in db.Employees
                 where (employee.FirstName + " " + employee.LastName) == "Test User"
                 select employee).ToList();

Библиотечка в качестве декомпилятора использует Mono.Reflection (GitHub, NuGet) от Jean-Baptiste Evain - создателя Mono.Cecil. Сама Mono.Cecil не используется из-за ее громоздкости.

PS: Естественно, то что внутри вычисляемого поля должно поддерживаться вашим LINQ-провайдером. PPS: Это альфа-версия очень далекая от релиза - используйте на свой страх и риск.

Ссылки