Идиомы C++
Гомон Сергей, Siarhei.Homan@regula.by
Обо мне
Опыт разработки ПО: 4.5 года
Основной язык: C++
Осановные сферы интересов:
▧ Сетевая разработка
▧ Защита информации
▧ Обработка изображений
2
Siarhei.Homan@regula.by
Содержание
▧ Что такое идиомы в лингвистике
▧ Что такое идиомы в программировании
▧ Почему существуют идиомы в программировании
▧ Что такое идиомы в C++
▧ Примеры идиом в C++
▧ Заключение
3
Идиомы в лингвистике
4
Идиомы в программировании
5
Идиома - это паттерн
Идиома - это использование
.each to do вместо for loop
Почему существуют идиомы
▧ Помогают выразить “невыразимое”
▧ Лаконичнее других подходов
6
Как отличить идиому
▧ Позволяют выразить задуманное элегантно
▧ Имеют смысл только для конкретного языка
▧ Требуют глубокого понимания особенностей
языка
▧ Легко подхватываются другими
7
Что такое идиомы в C++
▧ Не связаны напрямую с проектированием
▧ Относятся к уровню языка
программирования
▧ Имеют большую специфичость для C++
8
Примеры идиом
C++
9
RAII
Цель:
▧ Очистка ресурсов
▧ Basic exception safety
10
void bad() {
m.lock();
f(); // can throw!
if(!everything_ok()) return;
m.unlock();
}
void good() {
std::lock_guard<std::mutex> lk(m);
f();
if(!everything_ok()) return;
}
RAII
11
RAII в других языка
▧ C# - using
▧ Java - try with resources
▧ Python - with
12
Smart Pointer
Цель:
▧ Сымитировать поведение обычного указателя
▧ Добавить дополнительные возможности
13
void Foo() {
Bar* pBar = new Bar();
pBar->init();
LegacyApi(pBar);
NewApi(*pBar);
// Don't forget to delete!
delete pBar;
}
void Foo() {
auto pBar =
std::make_shared<Bar>();
pBar->init();
LegacyApi(pBar.get());
NewApi(*pBar);
}
Smart Pointer
14
Smart Pointer
Так это же идиома RAII!
Именно! Но с дополнительными плюшками.
15
Smart Pointer
Типы умных указателей в STL:
▧ unique_ptr
▧ shared_ptr
▧ weak_ptr
16
Pointer To Implementation (pImpl)
Также известен как:
▧ Opaque pointer
Цель:
▧ Скрыть детали реализации класса
17
// Class.h
class Class {
public:
Class();
~Class();
void method();
private:
class ClassImpl;
// We can use SmartPointer
ClassImpl* m_pImpl;
};
// Class.cpp
Class::Class() {
m_pImpl = new ClassImpl();
}
Class::~Class() {
delete m_pImpl;
}
void Class::method() {
m_pImpl->method();
}
void Class::ClassImpl::method() {
cout << "Implementation method"
<< endl;
}
Pointer To Implementation
18
Curiously Recurring Template Pattern
Цель:
▧ Специализировать шаблонный базовый класс классом-
наследником
class T : public X<T> {…};
19
Статический полиморфизм
template <class Derived> struct base {
void interface(){
static_cast<Derived*>(this)->implementation(); //Not a virtual call
}
static void static_interface() {
Derived::static_implementation();
}
};
struct derived_1 : base<derived_1> {
static void static_implementation(); //Static function overload
};
struct derived_2 : base<derived_2> {
void implementation();
};
20
Универсальный singleton
template <class ActualClass>
class Singleton {
public:
static ActualClass& GetInstance() {
if(p == 0) p = new ActualClass;
return *p;
}
protected:
static ActualClass* p;
private:
Singleton() {}
Singleton(Singleton const &);
Singleton& operator = (Singleton const &);
};
template <class T> T* Singleton<T>::p = 0;
21
Счетчик объектов
template <typename T>
struct counter {
static int objects_created, objects_alive;
counter() {
++objects_created; ++objects_alive;
}
counter(const counter&) {
++objects_created; ++objects_alive;
}
protected:
~counter() { --objects_alive; }
};
template<typename T> int counter<T>::objects_created(0);
template<typename T> int counter<T>::objects_alive(0);
22
CRTP в библиотеках
▧ std::enable_shared_from_this
▧ boost.operators
23
Clear-and-minimize
Цель:
▧ Очистить контейнер и освободить зарезервированную
память
std::vector<char> bigVector(1024);
bigVector.clear();
// capacity 1024
std::vector<char> bigVector(1024);
std::vector<char>().swap(bigVector);
// capacity 0
24
Concrete Data Type
Цель:
▧ Выбрать тип области видимости и времени жизни объекта
25
Запретить создание объекта на стеке
class EventHandler {
public:
virtual ~EventHandler() {}
};
class MouseEventHandler : public EventHandler {
protected:
~MouseEventHandler() {}
public:
MouseEventHandler() {}
};
int main() {
MouseEventHandler m; // We can’t do it
EventHandler *e = new MouseEventHandler (); // We can do it
delete e; // Polymorphic delete call
}
26
Запретить создание объекта на стеке
class MouseEventHandler {
protected:
MouseEventHandler() {}
~MouseEventHandler() {}
public:
static MouseEventHandler *instance () {
return new MouseEventHandler();
}
void destroy() {
delete this;
}
};
27
Запретить создание объекта в куче
class ScopedLock {
private:
static void *operator new(size_t size);
static void *operator new(size_t, void * mem); // placement new
};
int main() {
ScopedLock s; // We can do it
ScopedLock *sl = new ScopedLock(); // We can’t do it
void * buf = ::operator new(sizeof(ScopedLock));
ScopedLock *s2 = new(buf) ScopedLock; // We can’t do it
}
28
Другие идиомы
▧ Copy-on-write
▧ Interface Class
▧ Member Detector
▧ Named Constructor
▧ Scope Guard
▧ Runtime Static Initialization Order Idioms
Книга про идиомы C++:
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms
29
Итоги
Преимущества:
▧ Лаконичность и простота
▧ Единый словарь
Недостатки:
▧ Код трудно понять программисту на другом языке
▧ Использование старых идиом может усложнять понимание
кода
30
Спасибо за внимание!
Гомон Сергей, Siarhei.Homan@regula.by

idioms C++

  • 1.
  • 2.
    Обо мне Опыт разработкиПО: 4.5 года Основной язык: C++ Осановные сферы интересов: ▧ Сетевая разработка ▧ Защита информации ▧ Обработка изображений 2 Siarhei.Homan@regula.by
  • 3.
    Содержание ▧ Что такоеидиомы в лингвистике ▧ Что такое идиомы в программировании ▧ Почему существуют идиомы в программировании ▧ Что такое идиомы в C++ ▧ Примеры идиом в C++ ▧ Заключение 3
  • 4.
  • 5.
    Идиомы в программировании 5 Идиома- это паттерн Идиома - это использование .each to do вместо for loop
  • 6.
    Почему существуют идиомы ▧Помогают выразить “невыразимое” ▧ Лаконичнее других подходов 6
  • 7.
    Как отличить идиому ▧Позволяют выразить задуманное элегантно ▧ Имеют смысл только для конкретного языка ▧ Требуют глубокого понимания особенностей языка ▧ Легко подхватываются другими 7
  • 8.
    Что такое идиомыв C++ ▧ Не связаны напрямую с проектированием ▧ Относятся к уровню языка программирования ▧ Имеют большую специфичость для C++ 8
  • 9.
  • 10.
  • 11.
    void bad() { m.lock(); f();// can throw! if(!everything_ok()) return; m.unlock(); } void good() { std::lock_guard<std::mutex> lk(m); f(); if(!everything_ok()) return; } RAII 11
  • 12.
    RAII в другихязыка ▧ C# - using ▧ Java - try with resources ▧ Python - with 12
  • 13.
    Smart Pointer Цель: ▧ Сымитироватьповедение обычного указателя ▧ Добавить дополнительные возможности 13
  • 14.
    void Foo() { Bar*pBar = new Bar(); pBar->init(); LegacyApi(pBar); NewApi(*pBar); // Don't forget to delete! delete pBar; } void Foo() { auto pBar = std::make_shared<Bar>(); pBar->init(); LegacyApi(pBar.get()); NewApi(*pBar); } Smart Pointer 14
  • 15.
    Smart Pointer Так этоже идиома RAII! Именно! Но с дополнительными плюшками. 15
  • 16.
    Smart Pointer Типы умныхуказателей в STL: ▧ unique_ptr ▧ shared_ptr ▧ weak_ptr 16
  • 17.
    Pointer To Implementation(pImpl) Также известен как: ▧ Opaque pointer Цель: ▧ Скрыть детали реализации класса 17
  • 18.
    // Class.h class Class{ public: Class(); ~Class(); void method(); private: class ClassImpl; // We can use SmartPointer ClassImpl* m_pImpl; }; // Class.cpp Class::Class() { m_pImpl = new ClassImpl(); } Class::~Class() { delete m_pImpl; } void Class::method() { m_pImpl->method(); } void Class::ClassImpl::method() { cout << "Implementation method" << endl; } Pointer To Implementation 18
  • 19.
    Curiously Recurring TemplatePattern Цель: ▧ Специализировать шаблонный базовый класс классом- наследником class T : public X<T> {…}; 19
  • 20.
    Статический полиморфизм template <classDerived> struct base { void interface(){ static_cast<Derived*>(this)->implementation(); //Not a virtual call } static void static_interface() { Derived::static_implementation(); } }; struct derived_1 : base<derived_1> { static void static_implementation(); //Static function overload }; struct derived_2 : base<derived_2> { void implementation(); }; 20
  • 21.
    Универсальный singleton template <classActualClass> class Singleton { public: static ActualClass& GetInstance() { if(p == 0) p = new ActualClass; return *p; } protected: static ActualClass* p; private: Singleton() {} Singleton(Singleton const &); Singleton& operator = (Singleton const &); }; template <class T> T* Singleton<T>::p = 0; 21
  • 22.
    Счетчик объектов template <typenameT> struct counter { static int objects_created, objects_alive; counter() { ++objects_created; ++objects_alive; } counter(const counter&) { ++objects_created; ++objects_alive; } protected: ~counter() { --objects_alive; } }; template<typename T> int counter<T>::objects_created(0); template<typename T> int counter<T>::objects_alive(0); 22
  • 23.
    CRTP в библиотеках ▧std::enable_shared_from_this ▧ boost.operators 23
  • 24.
    Clear-and-minimize Цель: ▧ Очистить контейнери освободить зарезервированную память std::vector<char> bigVector(1024); bigVector.clear(); // capacity 1024 std::vector<char> bigVector(1024); std::vector<char>().swap(bigVector); // capacity 0 24
  • 25.
    Concrete Data Type Цель: ▧Выбрать тип области видимости и времени жизни объекта 25
  • 26.
    Запретить создание объектана стеке class EventHandler { public: virtual ~EventHandler() {} }; class MouseEventHandler : public EventHandler { protected: ~MouseEventHandler() {} public: MouseEventHandler() {} }; int main() { MouseEventHandler m; // We can’t do it EventHandler *e = new MouseEventHandler (); // We can do it delete e; // Polymorphic delete call } 26
  • 27.
    Запретить создание объектана стеке class MouseEventHandler { protected: MouseEventHandler() {} ~MouseEventHandler() {} public: static MouseEventHandler *instance () { return new MouseEventHandler(); } void destroy() { delete this; } }; 27
  • 28.
    Запретить создание объектав куче class ScopedLock { private: static void *operator new(size_t size); static void *operator new(size_t, void * mem); // placement new }; int main() { ScopedLock s; // We can do it ScopedLock *sl = new ScopedLock(); // We can’t do it void * buf = ::operator new(sizeof(ScopedLock)); ScopedLock *s2 = new(buf) ScopedLock; // We can’t do it } 28
  • 29.
    Другие идиомы ▧ Copy-on-write ▧Interface Class ▧ Member Detector ▧ Named Constructor ▧ Scope Guard ▧ Runtime Static Initialization Order Idioms Книга про идиомы C++: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms 29
  • 30.
    Итоги Преимущества: ▧ Лаконичность ипростота ▧ Единый словарь Недостатки: ▧ Код трудно понять программисту на другом языке ▧ Использование старых идиом может усложнять понимание кода 30
  • 31.
    Спасибо за внимание! ГомонСергей, Siarhei.Homan@regula.by

Editor's Notes

  • #3 Здравствуйте! Меня зовут Гомон Сергей. Я являюсь сотрудником компании Regula. У меня примерно 4.5 года опыта разработки на C++. В основном приходилось заниматься сетевой разработкой. В настоящее время пытаюсь заниматься новой для себя областью - обработкой изображений.
  • #4 Сегодня я бы хотел обсудь с вами тему “Идиомы C++”. В докладе будут рассмотрены следующие вопросы: Что такое идиомы в лингвистике Что такое идиомы в программировании Почему сущесвуют идиомы в программировании Что такое идиомы в C++ Примеры идиом в C++ В конце мы подведем краткий итог.
  • #5 Итак, начнем с идиом в лингвистике. Идиома (или фразеологические сращения) - это присущий только данному языку и не переводимый на другие языки устойчивый оборот речи, значение которого не вытекает из суммы значений составляющих его элементов. Из-за того, что идиому невозможно перевести дословно (теряется смысл) часто возникают трудности перевода и понимания. С другой стороны такие фразеологизмы придают языку яркую эмоциональную окраску. На картинке можно увидить пример буквального понимания идиомы I’ve got your back. Дословный перевод на русский данной идиомы не имеет большого смысла. Идиома означает, что за тобой кто-то приглядывает, чтобы ты был в порядке. Подразумевается, что человеку сложно следить за тем, что происходит у него за спиной, и чтобы быть в безопасности, за ней нужно приглядывать. Стоит отметить, что некоторые идиомы имеют смысл как в английском, так и врусском языках, например идиома “ветер перемен”. В данном случае приведенное определение не является точным в том смысле, что идиома может быть присуща не только одному языку, но и нескольким языкам.
  • #6 Теперь рассмотрим вопрос, что же подразумевают, когда говорят об идиомах в контексте языков программирования. Определение из википедии звучит следующим образом: Программная идиома — способ выражения некой не-элементарной конструкции, типичный для одного или нескольких языков программирования. Идиома представляет собой типовой способ выразить задачу, алгоритм или структуру данных, не встроенные в язык на уровне примитивов, либо наоборот, нетривиальный способ использования встроенных элементов языка. Термин часто используется в широком смысле, в том числе в качестве синонима термина шаблон проектирования, и знание идиом в этом случае часто служит показателем свободного владения этим языком. Среди программистов часто наблюдается путаница в понимании того, что является идиомами. Как следует из определения, идиомы иногда путают с паттернами проектирования. От паттернов проектировани идиомы отличаются своей специфичностью для языка. Трудудно их применить на этапе проектирования системы, в отличии от паттернов. Также в интернетах можно найти статьи, в которых утверждается, что в языках программирования идиом не сущесвует. Это также происходит от неправильного понимания смысла идиом. Иногда говорят об идиоматичном использовании конструкций языков программирования. Например, в ruby использование циклов .each to do вместо циклов foor loop, является идиоматичным. Это значит, что для опытного разработчика на ruby увидеть использование цикла foor loop будет непривычным. Он, конечно, поймет написанный код, но так обычно не делают. То же самое с генерацией списков в Python. Иногда можно услышать фразу типа “Pythonc way”, что подразумевает использование чегото идиоматически для питона. Если проводить аналогии с естественным языком, то это как спросить “сколько времени”, чтобы выяснить “который час”. Скорее всего вас поймут, но люди, которые хорошо владеют языком, обычно так не говорят.
  • #7 Почему же сущесвуют идиомы в языках программирования? Ни один язык не может содержать достаточно средств для выражения всего. Когда появляется необходимость выразить какой-то аспект, для которого язык не имеет прямых средств, на помощь приходят идиомы. С развитием языка в нем могу появляться новые средства, которые могут позволять выражать новые аспекты, в этом случае необходимость в некоторых идиомах может исчезать. Например, благодаря появлению enum class в C++11 отпадает необходимость в использовании идиомы Type Safe Enum. Также зачастую идиомы являются лаконичнее других подходов для выражения задуманного, при отсутвии прямой поддержки от языка программирования.
  • #8 Нет единого критерия для того, чтобы определить, содержит написанный код идиомы или нет. Тем не менее, можно ориентироваться не некоторые признаки. Например: Часто идиомы позволяют выразить задуманную идею элегантно по сравнению с другими доступными решениями Часто идиомы имееют смысл только для конкретного языка программирования Часто идиомы требуют глубокого понимания особенностей языка программирования (но чтобы их использовать, глубоких знаний языка не нужно. Например, я знаю, что означает “бить баклуши”, но я не знаю, что такое “баклуши” и почему данная идиома означает “ничего не делать”) Часто идиомы легко используются другими программистами, которые о них узнали (их использование не нужно навязывать, как и идиомы в естественном языке, которые сами случайно вырываются при появлении нужных условий) Эти признаки не являются 100% способом отличить идиому от чего-то другого, например от паттернов. Однако, на мой взгялд, в большинстве случаев их хватает. Также стоит понимать, что конкретная идиома необязательно должна удовлетворять всем этим требованиям. Есть идиомы, которые не требуют глубокого понимания языка программирования. Есть идиомы, которые не очень-то и подхватываются другими программистами. А некоторые идиомы имеют смысл для большого количества языков программирования.
  • #9 Теперь перейдем непосредственно к C++. Под идиомами C++ будем понимать такие приемы программирования на C++, которые: Решают задачу, которая не связана напрямую с проектированием Решают задачу, которая должна быть решена на уровне языка программирования Имеют большую специфичность для C++ и вряд ли будут полезны для других языков (но могут быть и полезны!)
  • #11 Цели у данной идиомы следующие: Гарантировать очисту ресурсов в конце области видимости Гарантировать basic exception safety (no-leak guarantee) Basic exception safety - гарантия отсутсвия утечер ресурсов. Частичное выполнение или ошибка выполнения операции может привести к побочным эффектам, но все инварианты остаются верны и не происходит утечки ресурсов. Все хранимые данные имеют валидные значения, но могут отличаться от тех, которые были перед выполнением операции.
  • #12 Рассмотрим небольшоей пример использования RAII. Из-за наличия условий в функции, нам нужно дублировать очистку ресурсов в каждой ветке с return. Также есть опасность, что вызовы функций бросят исключения. Попытки предусмотреть все возможные выходы из функции могут сделать код сложным для понимания и очень запутанным. В свою очередь использование RAII позволяет не беспокоится об очистке ресурсов. ВАЖНО!!! Деструктор не должен бросать исключений, так как нам нужно обеспечить basic exception safety. Если бросить исключение в деструкторе, то появляется большая вероятность, что некоторые ресурсы будут не очищены. В C++ данная идиома испольуезтся крайне широко: ее используют контейнеры (удаляют за собой память), потоки (закрывают за собой файлы), умные указатели (удаляют память, когда на нее никто не ссылается). Большое количество идиом и паттернов реализованы с ипользованием идиомы RAII.
  • #13 В языках программирования со сборщиком мусора RAII также часто имеет смысл, сборщик мусора не закрывает открытые файлы. Отсутсвие деструкторов у классов делает идиому RAII не родной для данных языков. Часто для этого используется блок try-finally (иногда это единственный способ). Иногда для подобной конструкции в языке добавляют синтаксический сахар типа using в C# и with в Python. В целом деструкторы в C++ позволяют добиться большей гибкости, RAII для C++ - это что-то естественное, не доставляющее дискомфорта и даже наоборот, делающее жизнь лучше, в то время как в языках со сборщиком мусора его использования выглядит чужиродно.
  • #14 Данная идиома приследует 2 основные цели: Сымитировать поведение обычного указателя Добавить дополнительные фунеции к указателю: проверка выхода за границы массива, автоматическое удаление памяти и т. п. Smart Pointer позволяет создавать объекты в куче, при этом избежать большого количества проблем, связанных с работой с сырыми указателями, в частности, с проблемой удаления памяти. Однако злоупотребление умными указателями может привести к появлению трудноуловимых багов.
  • #15 Рассмотрим небольшой пример. Экземпляр класса Bar создается в куче через оператор new. Память очищается в конце метода. К сожалени, есть очень много факторов, которые могут привести к тому, что выполнение программы никогда не попадет в конец функции, и память останется неочищенной. Чтобы не беспокоится о вызове оператора delete, можно не использовать оператор new. Это становится возможможным, если соединить идиому SmartPointer вместе с шаблонной магией. В примере память под объект выделяется вызовом функции make_shared. Возвращаемый объект имеет семантику указателя. При этом нам не нужно беспокоится об удалении памяти, вызов деструктора нам гарантирован.
  • #16 Сейчас вы можете заметить, что Smart Pointer - это идиома RAII. Это действительно так. Но в отличии от RAII идиома Smart Pointer призвана решать немного другие проблемы. Это пример того, как одни идиомы могут реализовываться через использование других.
  • #17 В STL уже реализован набор умных указателей: unique_ptrs - для единоличного владения объектом shared_ptrs - для совместного владения объектом weak_ptrs - для проверки существования объекта перед его использованием. Этот умный указатель реализует невладеющую семантику, его можно использовать вместо сырых указателей для решения циклических ссылок. В этой ситуации использование владеющих указателей может приводить к утечке ресурсов.
  • #18 Очень мощная и полезная идиома.
  • #19 Преимущества: Инкапсуляция всех деталей реализации: легко читать заголовочный файл, легко поддерживать бинарную совместимость при изменении реализации, можно скрыть реализацию от пользователей Ускоряется компиляция (в больших проектах - значительно ускоряется) Недостатки: Дополнительное выделение памяти Косвенный вызов методов класса Проблемы с использованием inline методов Много дополнительного кода Очень ярким и удачным примером использования идиомы является библиотека Qt. В Qt Wiki данную идиому называют d-pointer. Также на нее ссылкаются как на паттерн проектирвоания. Это связано с тем, что паттерн проектирования “Bridge” реализуется через идиому pImpl. В Qt pImpl используется для двух основных целей: Обеспечение бинарной совместимости между версиями библиотек Закрыть реализацию Также pImpl позволяет упростить реализацию implicit-sharing (Copy-on-write)
  • #20 Идиома немного выносит мозг. Не смотря на это является одной из самых распространенных и полезных.
  • #21 Идиому CRTP можно использовать для реализации статического полиморфизма. Статический полиморфизм подразумевает, что во время компиляции мы точно знаем у какого объекта будет вызван метод, поэтому нет необходимости тратиться на виртуальный вызов. Также данный подход позволяет делать некоторое подобие перегрузки статических методов.
  • #22 CRTP позволяет унаследовать реализацию. Написав такой класс, мы можем легко сделать другой класс синглетоном, просто отнаследовавшить. Не стоит забывать, что для C++ паттерн singleton является антипаттерном, что требует особой осторожности при его использовании.
  • #23 Еще один пример унаследования реализации. Таким образом можно легко добавить счетчик объектов в любой класс, который отнаследуется от counter. Для идиомы SmartPointer похожим образом можно реализовать счетчик ссылок.
  • #24 В стандартной библиотеке std::enable_shared_from_this. Позволяет классам наследникам создавать std::shared_ptr на самих себя. В boost.operators реализуя один из операторов и унаследовав один из классов представленных в operators мы получаем весь спектр необходимых операторов. Данная идиомя очень широко распространена, поэтому примеры ее реализации и использования можно найти почти где угодно.
  • #25 Небольшая но полезная идиома. При удалении элементов из вектора, он автоматически не очищает зарезервированную память при вызове метода clean(). Чтобы освободить память, можно воспользоваться данной идиомой.
  • #26 Данная идиома может пригадиться для создателей библиотек. Она позволяет предотвратить некоторые варианты неправильного использования классов библиотеки.
  • #27 При помощи данного приема можно запретить создание объектов на стеке. Однако это не мещает нам создавать объект в куче.
  • #28 Еще один способ запретить создание объектов на стеке.
  • #29 А данный способ позволяет запретить создание объекта в куче через использование операторов new и placement new. В частости приведен пример использование данной идиомы для класса ScopedLock, создание объектов которого на стеке не имеет смысла.
  • #30 Copy-on-write - широко используется в Qt. Контейнеры в Qt могут передаваться по значению, при это не будет происходит копирования данных, если нет их модификации. Interface Class - позволяет отделить интерфейс класса от его реализации. Member Detector - позволяет получить метоинформацию о классе во время выполнения. Named Constructor - позволяет создавать объекты класса осмысленным способом. Scope Guard - позволяет очищать ресурс только в случае, если произошло исключение, и оставлять его занятым, если исключения не было. Runtime Static Initialization Order Idioms - позволяет задать порядок инициализации статических переменных.
  • #31 Преимущества использования идиом: Лаконичность и простота кода по сравнению с доступными альтернативами Единый словарь среди разработчиков Недостатки: Код трудно понять программисту на другом языке Использование старых идиом при наличии средств в языке программирования может неоправданно усложнять понимание кода