Показаны сообщения с ярлыком Паттерны. Показать все сообщения
Показаны сообщения с ярлыком Паттерны. Показать все сообщения

пятница, 10 сентября 2010 г.

JavaScript - есть и хорошие стороны

JS такой загадочный язык, который никто не учит, однако все на нем программируют. Я не исключение, но я чувствую себя некомфортно, когда не понимаю, по каким правилам мне приходиться играть.

Скопипастив очередной кусок JS, я вспомнил слова Мартина Фаулера (интересное интервью - хоть посмотрите, как он выглядит), что для расширения кругозора надобно учить хотя бы по одному новому языку в год. Полиглоты, называет он таких программистов :) Я же подумал - надоело мне мучаться с JS, хочу научиться писать на нем нормально.

В общем, я чуть-чуть попытался разобраться (ниже со ссылками), по-моему, очень даже интересно.

среда, 1 сентября 2010 г.

Singleton in .NET 4 - вопрос снят?

Так как у нас на проекте есть открытые вакансии, то приходится активно участвовать в собеседованиях джаверов. В связи с этим хочется поделиться мыслями по одному из часто задаваемых вопросов - многопоточная реализация Singleton. Не смотря на то, что уже много копий сломано и много написано, редко когда удается услышать четкий и правильный ответ.

С моей точки зрения этот вопрос не так уж много показывает (скажем так, он кажется обманчиво интересным), но ответы на сопутствующие вопросы (более интересные) сами его провоцируют. Например, на вопрос "Какие вы знаете шаблоны проектирования", ответ обычно начинается с "Singleton, Factory..."

понедельник, 19 июля 2010 г.

Round Robin

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

В нашей команде за этим понятием прочно закрепился и другой смысл – честное распределение рутинной работы между членами команды.

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

Data Quality

Читаю сейчас Adrenaline Junkies and Template Zombies: Understanding Patterns of Project Behavior. Интересная книга, советую.

Книга

Книга состоит из 86 эссе про хорошие и плохие вещи, повсеместно происходящие на проектах. Это скорее эссе, а не паттерны, к которым мы привыкли по GoF. Точнее мы приближаемся ближе к первоначальному значению слова "паттерн" - в данном контексте нечто повторяющееся от одного проекта к другому, неважно - плохо это или хорошо.

К слову, "плохих" историй больше, чем хороших. Оно и понятно, ведь по Chaos Report, заваленных проектов больше, чем успешных. С хорошими паттернами все ясно - бери и пользуй. Плохие скорее похожи на диагнозы без четко определенного курса лечения. В некоторых случаях прямо в лоб нам сообщают, что не лечится, иногда все же есть анализ и советы, как избежать таких ситуаций. Хотя в большинстве случаев просто объясняются возможные причины - а решение проблемы остается за вами.

Data Quality

Один из (анти)паттернов, очень близкий к моим профессиональным интересам, - Data Quality.

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

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

Это сложно

Именно так:
0. Сложно определить - правильные данные или нет
1. Исправить неправильные данные сложно
2. Еще сложнее сделать это автоматически
3. Правильно исправить неправильные данные - совсем тяжело
4. Правильно исправленные данные скоро могут стать неправильными
5. Если вы исправляете данные за ваших поставщиков, поставщики данных поставляют вам все более неправильные данные
6. Если вы исправляете данные в принципе, то все неправильные данные, которые приходят из вашего приложения - это ошибки в вашем приложении

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

Медвежья услуга

Это похоже на глотание exceptions. Если вы проглотили exception, то вы спрятали ошибку. Ошибка все еще существует. Когда к вам придут и скажут - у вас здесь неправильно, то вы только можете надеяться, что сможете когда-либо выйти на истинную причину ошибки. Ведь вы её сами же маскируете, проглатывая некорректные данные.

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

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

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

четверг, 13 мая 2010 г.

State machine CSV parser

Понадобилось нам парсить CSV файлы.

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

Задача стандартная, возник запрос, зачем делать самим. Быстрый поиск по интернету готовой версии выдал несколько левеньких вариантов со своими проблемами, а также более серьезные версии типа FileHelpers. Более серьезные версии как выяснилось не очень вписываются в нашу структуру классов. К примеру, FileHelpers как бы десериализует запись в объект класса. Звучит неплохо, однако для каждой колонки в целевом классе нужно было поле. А у нас файлы по 200-400 колонок.

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

Конечный автомат – это по сути набор состояний системы и переходов из одного состояния в другое. Паттерн State эксплуатирует это математическое понятие. У каждого состояния есть свой способ обработки этого состояния и свои правила перехода в другие состояния. Конечный автомат также легко визуализируется при помощи UML State Chart диаграммы (ниже можно увидеть упрощенный пример).

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

Основная задача - распарсить одну строку файла:
private string[] SplitCsvLine(string line)
Идея в том, что мы пробегаемся по символам в строке и при встрече какого-либо специального символа мы переходим в новое состояние. В разных состояниях один и тот же символ переводит в различные состояния. Пример:


Код перехода из состояний в состояние:

CsvStateHandler currentState = HandleValueStart;

for (int i = 0, lineLength = line.Length; i < lineLength; i++)
{
       currentState = currentState(line[i], currentValue, values);
}
CurrentState – это делегат вида:

private delegate CsvStateHandler CsvStateHandler(
     char currentChar, 
     StringBuilder currentValue, 
     List<string> values);

Пример обработчика состояний:
private CsvStateHandler HandleValueStart(
        char currentChar, 
        StringBuilder currentValue, 
        List<string> values)
{
        currentValue.Clear();

        if (currentChar == quoteChar)
        {
            return HandleQuotedValue;
        }

        if (currentChar == delimiter)
        {
            values.Add(String.Empty);
            return HandleValueStart;
        }

        currentValue.Append(currentChar);

        return HandleSimpleValue;
}
Таким образом сложные многоэтажные ифы превратились в одноуровневые простые и целиком распределелись по простым компактным методам. Изменение логики и добавление очередного перехода стало простым и быстрым. Код стал понятен и поддерживаем.