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

воскресенье, 9 марта 2014 г.

Stroustrup и 16 способов положить кота в стек

Прочитал статью Страуструпа о стеках и кошках: 
http://isocpp.org/blog/2014/03/sixteen-ways

Казалось бы, написана она ещё в 1990 - что нового можно в ней почерпнуть?.. 
В целом, этот материал сейчас смотрится довольно предсказуемо и подкупает меня, скорее, своей академичностью и полнотой рассмотрения вопроса. 
Но, при внимательном прочтении, начинаешь замечать мелочи, которые играют важную роль. Для меня такой мелочью стал внутренний класс stack_id: 

class stack
{
public:
    class id
    {
        friend stack;
    private:
        int i;
    };
    ...
}; 

Казалось бы мелочь, а ведь сколько проблем доставляли мне в свое время типы идентификаторов, определённые через typedef базовых типов... 
А тут:
  • раз, и логическая привязка к основному классу;  
  • два, и неприводимость к базовому типу(int/string/etc); 
  • три, и неизменяемость его наружными классами, а только передача между различными функциями.  
Красиво же!  

понедельник, 17 октября 2011 г.

TDD в условиях плотного использования ATL/COM

Попытки внедрить TDD для проектов, которые активно используют ATL/COM, очень часто заканчивались для меня неудачно из-за сложности задачи, которая приводит к тому, что просто опускались руки из-за того что не знал как подступится к задаче и гугл с яндексом в те моменты молчали и не желали делится мудростью других людей.

И проблема была даже не в том "как протестировать сам COM-компонент?" - это не представляло особой проблемы, потому что был и есть явно заданный интерфейс класса, единственной особенностью которого является то, как создаётся объект этого класса. Дальше всё сводилось к классическому подходу для TDD.
Основной проблемой являлся вопрос "как протестировать класс, который уже активно использует COM-компоненты?"

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

И корень проблемы был даже не в том, что приходилось создавать эти классы-заглушки - это то как раз было довольно просто и входило для меня в область допустимых накладных расходов от применения TDD. Проблема была в том как обеспечить создание и использование классов-заглушек не изменяя кучи кода.

Подсказкой к решению является скрытая причина этой ситуации - у нас уже по всему коду протянута неявная зависимость от реестра системы. Соответственно для удобства в написании тестов я должен обеспечить единую точку доступа и контроля этой зависимости. Что привело меня к следующей идее: введём дополнительный архитектурный слой с единичным контейнером, который контролирует процесс создания COM-компонентов (по аналогии с слоем работы с объектами базы данных).

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

Архитектурная идея с подобными контейнерами не сильно распространена в C++, но она решает свою задачу.

P.S.
Я таки дописал хоть один пост за прошедший год.

пятница, 3 декабря 2010 г.

Вопрос об интерфейсах

Похоже, что я нашёл самый сложный вопрос для собеседований по C++ - полностью правильного ответа ещё ни разу не слышал, а ведь не junior'ов собеседую...
Звучит он приблизительно так:
Есть такие понятия в ООП как "наследование реализации" и "наследование интерфейса"... Как Вы понимаете "наследование интерфейса" и есть ли оно в C++?

Т.е. вопрос вроде бы простой...
И вот самое странное, что почти у всех кандидатов при ответе обнаруживается некая каша из ключевого слова interface, понятия абстрактного класса, понятия класса реализующего некий интерфейс, собственно понятия интерфейса и иногда даже COM-интерфейса. Т.е. каждый приходит со своими ингридиентами к каше :) В таких условиях ожидать идеально правильного ответа невозможно, зато это позволяет "залезть в голову" кандидату.

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

 
А теперь доберёмся до приблизительно правильного ответа как его вижу я.

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

Null Object и проблемы, которые он может принести

У Степанова в его лекциях по программированию мимоходом рассказывается о проблеме, которую привносит в template algorithm'ы STL'я и в обобщённое программирование на C++, требование IEEE стандарта к наличию специального значения в диапазонах double/float( NaN - Not a Number).

Подробности можно прочитать в Notes from the lectures of Programming by Alexandr Stepanov, но суть проблемы следующая:

Любая операция сравнения, которая выполняется с NaN, должна возвращать false. Такое требование закладывает мину практически во все алгоритмы из библиотеки STL, которые опираются на операции сравнения.

Степанов заявляет, что так как это случай редкий и касается только 1 типа, то можно его проигнорировать. Но здесь на сцену выходят Фаулер и Кириевски с их идеей рефакторинга "Introduce Null Object", и мы по сути получаем проблему, которую Степанов считал малозначащей, только перенесённую уже и в другие языки программирования, а не только на C++.

Дальше чуть более подробно мои размышления на эту тему...