На языке C++. Некоторые аспекты применения::Приложение к журналу СА №3(2010)
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Наука и технологии
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Событие  

В банке рассола ждет сисадмина с полей фрактал-кукумбер

Читайте впечатления о слете ДСА 2024, рассказанные волонтером и участником слета

 Читать далее...

Организация бесперебойной работы  

Бесперебойная работа ИТ-инфраструктуры в режиме 24/7 Как обеспечить ее в нынешних условиях?

Год назад ИТ-компания «Крок» провела исследование «Ключевые тренды сервисного рынка 2023». Результаты

 Читать далее...

Книжная полка  

Читайте и познавайте мир технологий!

Издательство «БХВ» продолжает радовать выпуском интересных и полезных, к тому же прекрасно

 Читать далее...

СУБД PostgreSQL  

СУБД Postgres Pro

Сертификация по новым требованиям ФСТЭК и роль администратора без доступа к данным

 Читать далее...

Критическая инфраструктура  

КИИ для оператора связи. Готовы ли компании к повышению уровня кибербезопасности?

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

 Читать далее...

Архитектура ПО  

Архитектурные метрики. Качество архитектуры и способность системы к эволюционированию

Обычно соответствие программного продукта требованиям мы проверяем через скоуп вполне себе понятных

 Читать далее...

Как хорошо вы это знаете  

Что вам известно о разработках компании ARinteg?

Компания ARinteg (ООО «АРинтег») – системный интегратор на российском рынке ИБ –

 Читать далее...

Графические редакторы  

Рисование абстрактных гор в стиле Paper Cut

Векторный графический редактор Inkscape – яркий представитель той прослойки open source, с

 Читать далее...

День сисадмина  

Учите матчасть! Или как стать системным администратором

Лето – время не только отпусков, но и хорошая возможность определиться с профессией

 Читать далее...

День сисадмина  

Живой айтишник – это всегда движение. Остановка смерти подобна

Наши авторы рассказывают о своем опыте и дают советы начинающим системным администраторам.

 Читать далее...

Виртуализация  

Рынок решений для виртуализации

По данным «Обзора российского рынка инфраструктурного ПО и перспектив его развития», сделанного

 Читать далее...

Книжная полка  

Как стать креативным и востребованным

Издательский дом «Питер» предлагает новинки компьютерной литературы, а также книги по бизнесу

 Читать далее...

Книжная полка  

От создания сайтов до разработки и реализации API

В издательстве «БХВ» недавно вышли книги, которые будут интересны системным администраторам, создателям

 Читать далее...

Разбор полетов  

Ошибок опыт трудный

Как часто мы легко повторяем, что не надо бояться совершать ошибки, мол,

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 6195
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 6903
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 4188
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 2989
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 3795
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 3805
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 6299
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 3152
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 3446
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 7263
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 10628
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 12352
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 13982
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 9110
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 7064
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 5375
Комментарии: 3
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 4604
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 3414
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 3145
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 3392
Комментарии: 0
Рецензия на книгу «MongoDB в действии»

 Читать далее...

02.12.2013г.
Просмотров: 3013
Комментарии: 0
Не думай о минутах свысока

 Читать далее...

Друзья сайта  

 На языке C++. Некоторые аспекты применения

Архив номеров / 2010 / Выпуск №3 (3) / На языке C++. Некоторые аспекты применения

Рубрика: Программирование /  Теория

Андрей Чинков АНДРЕЙ ЧИНКОВ, разработчик в Kaspersky Lab. Область интересов – OOP/OOD

На языке C++
Некоторые аспекты применения

Программист на С++ – это комбинатор, как Остап Бендер. Читатель вправе поспорить со мной, так как по большей части мои доводы имеют научно-популярный характер

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

С++ – мощный язык программирования с широкими возможностями, и для эффективного их использования надо немножко изменить способ мышления. Это еще один плюс, который привлекает меня в С++. Давайте вернемся на студенческую скамью и вспомним, как начиналось знакомство с этим языком – кто-то кусал локти, не зная, как сдать очередную «мучительную» лабораторную работу, а у кого-то горели глаза от осознания того, что тут не просто «Си c классами».

Итак, сегодня С++ – это язык программирования, основанный на нескольких парадигмах. Своего рода конгломерат процедурного, функционального, объектно-ориентированного и обобщенного программирования. Найти смысл в таком языке просто, если понимать как правильные, так и ошибочные аспекты его применения. Всем известно, что cтандартная библиотека шаблонов (STL) – это хорошо, Boost (набор библиотек, невообразимо широко расширяющих возможности стандартного С++) – тоже, а глобальные переменные и аргументы по умолчанию в виртуальной функции – это зло. Что const – это наш помощник, что исключения генерируются по значению, а перехватываются по константной ссылке. И еще десяток таких основных утверждений. Что же еще нужно, чтобы написать хорошую программу?

Цель программирования – не предоставить средства для решения задачи, а обеспечить возможность достижения цели существующими способами, комбинируя их. Программист на С++ – это комбинатор, с позволения сказать, Остап Бендер. В его распоряжении мегабайты денег (читать – памяти) и множество помощников. Хороший комбинатор доберется до солнечной Бразилии, плохой – будет задержан на границе. Итак, давайте прорываться.

Появления TR1 разрешило стандарту С++ использовать некоторые компоненты Boost. Среди них интеллектуальные (умные) указатели и функторы, которые уже пронизывают имплементации многих коммерческих продуктов.

Умный указатель – это не только гарантия не забыть освободить ресурс при выходе из области, в которой данный ресурс необходим. На мой взгляд, это скорее просто бонус. Гораздо более важной возможностью при использовании RAII представляется реализация безопасного кода, в котором можно легко вовремя уступить дорогу какому-то событию (например, возникновению исключения) так, чтобы сохранить объекты и программу в корректном состоянии не только на этапе выполнения, но и при разработке кода.

Что такое корректность? Простые указатели грешны в том плане, что они напрямую работают с памятью. Умные указатели – самостоятельные объекты, которые кроме решения этой проблемы, как часто получается, содействуют написанию безопасного кода путем разделения управления и владения ресурсом. Принцип «разделяй и властвуй» в С++ проявляется очень хорошо. Зачем вообще думать о корректности? Работает – и ладно? Я отвечаю себе так: сделать корректную программу быстрой легко, наоборот – очень трудно.

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

Как правило, это что-то обязательно потеряется по дороге. Результат – баг, который трудно найти. Поэтому необходим рефакторинг. Если бы я изначально работал с такими понятиями, как самостоятельные объекты, и использовал бы STL, то, кроме уменьшения размера функции и улучшения ее читабельности, получился бы более масштабируемый продукт.

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

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

Существует такое понятие, как «утиная типизация», то есть если крякает, значит, утка. Поэтому не будем злоупотреблять трехэтажными std::tr1::bind’ами, а рассмотрим применение паттерна «Команда».

Цель абстрактного интерфейс Command состоит в отделении объекта, посылающего запрос, от объекта, который знает, как ее выполнить. Интерфейс Command может содержать операции Execute(), Prepare() и/или Commit(), в то время как потребовалось бы несколько отдельных функторов для каждой их этих операций. С++ – строго типизированный язык программирования, типы – наши помощники. Потому что лучше заставить компилятор ошибиться на этапе компиляции, чем уронить программу на этапе выполнения.

Интерфейс Command явно говорит нам, что тот, кто за него себя выдает, умеет выполнять команды. Дополнительно, например, интерфейс AsyncCommand конкретизирует, что команда будет выполняться параллельно. Функторы в этом плане более грубы, так как за ними можно спрятать что угодно, даже то, что совсем не предусматривалось быть использованным как команда.

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

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

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

Давайте покритикуем нарушение инкапсуляции не с точки зрения того, что это просто нарушение чего-то, а с точки зрения архитектуры. Как нарушение инкапсуляции информации может сказаться на проектировании системы в целом?

Интуитивный подход говорит нам, что каждый объект должен выполнять только те операции, для выполнения которых он имеет достаточно информации. Это поведение предполагает наличие так называемого Information Expert’a для выполнения операции. Однако если объект будет распылять содержащуюся внутри него информацию, ничего хорошего не получится. Потому что трудно будет организовать распределение обязанностей между Information Expert’ами.

Приведу пример из реального мира. Когда мы садимся за руль, мы являемся Information Expert"ами в том плане, что знаем, куда ехать. Машина является Information Expert"ом потому что знает, как ехать. Было бы нелогично требовать от объекта «машина» реализации операции «GetПриводКоленвала()», а от водителя машины – операции «КрутитьПриводКоленвала». Машина предоставляет только необходимый интерфейс (руль и рычаги) для того, чтобы ею можно было пользоваться.

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

Например, показать это можно на классе MyDataBase, работающим с базой данных, хранящейся на диске, посредством SQL-запросов. Написав программу работы с базой данных, использующей этот класс, мы заметили, что она работает слишком медленно, постоянно «хрустит» жестким диском. Покопавшись в коде и немного «подебажив», мы обнаружили, что в каком-то цикле очень часто происходят SQL-запросы к базе данных. Немного поразмыслив, можно неверно решить реализовать в этом классе MyDataBase функцию GetAll(), которая возвращает вызывающей стороне всю таблицу – “SELECT * FROM TABLE”. Вызывающая сторона кэширует эти данные, тем самым минимизировав обращения к жесткому диску и увеличив скорость работы программы. На самом деле такой подход хорош только при близком рассмотрении.

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

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

Тем более – изменять интерфейс MyDataBase ради решения проблемы в бизнес-логике программы категорически неприемлемо. MyDataBase – это Information Expert в том плане, что только он знает, как работать с базой данных. MyDataBase должен предоставлять интерфейс, состоящий из набора элементарных функций, а не GetAll().

Необходимо выяснить общую причину, заставляющую клиента MyDataBase в цикле производить обращения к базе данных. Исправив ситуацию на уровне бизнес-логики, мы как минимум решим поставленную задачу. А как максимум предотвратим появление десятка других потенциальных ошибок и  вариантов некорректного поведения программы в будущем.

***

Целью данной статьи было обсудить некоторые наболевшие проблемы программирования. Если вдобавок получилось заставить читателя улыбнуться пару раз, то цель перевыполнена.


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru