C++ / [Из песочницы] Тонкости реализации кода библиотеки. Часть первая

в 9:49, , рубрики: библиотека, С++, метки: ,

C++ / [Из песочницы] Тонкости реализации кода библиотеки. Часть первая
При написании библиотеки на C++ многие сталкиваются с определенными трудностями при написании и организации кода. У некоторых уже есть готовые решения, у других их нет и они пытаются найти эти решения.
Некоторые трудности при написании кода библиотеки, в большей степени касающиеся «самодокументирования», можно решить с помощью «рабочих» пространств имен.
Для начала, опишем эти трудности и представим обычные способы решения.
Предположим, что библиотека реализует некоторую сущность some_class, которую она предоставляет пользователю библиотеки. Определение some_class зависит от другой сущности библиотеки detail_class, которая является частью реализации и пользователю не предоставляется. Библиотека поставляется только в виде заголовочных файлов.
Распределение кода по файлам в данном топике не рассматривается.
Стандартное решение 1

namespace lib_namespace
{
class detail_class
{
};

class some_class
{
public:
// открытый интерфейс
private:
detail_class a_;
// другие члены класса
};
}

Плюс данного решения:
1) минимальное количество кода, необходимого для его реализации.
Минусы:
1) Плохое «самодокументирование» кода. Не всегда по имени классов реализации в данном случае можно определить пользовательские они или нет.
2) Захламление пространства имен библиотеки. Некоторые среды разработки при использовании данного пространства имен, будут отображать то, что пользователю библиотеки не нужно:
Стандартное решение 2

namespace lib_namespace {
namespace impl
{
class detail_class
{
};
}}

namespace lib_namespace
{
class some_class
{
public:
// открытый интерфейс
private:
impl::detail_class a_;
// другие члены класса
};
}

Данное решение полностью убирает недостатки предыдущего подхода, но добавляет свои:
1) введение дополнительного пространства имен;
2) В любом библиотечном классе, предоставляемом пользователю и размещенном в lib_namespace, необходимо для всех элементов реализации указывать префикс impl::.
Достоинства:
1) хорошее «самодокументирование» кода.
Решение на основе «рабочих» пространств имен

namespace work_lib_namespace
{
class detail_class
{
};

class some_class
{
public:
// открытый интерфейс
private:
detail_class a_;
// другие члены класса
};
}

namespace lib_namespace
{
using ::work_lib_namespace::some_class;
}

Весь код библиотеки размещается в рабочем пространстве имен work_lib_namespace. Все сущности, которые библиотека предоставляет пользователю, добавляются в основное пространство имен библиотеки посредством using.
Недостаток данного подхода:
1) введение дополнительного пространства имен.
Достоинства:
1) «самодокументирование» кода;
2) возможность использования using namespace some_ns внутри рабочего пространства имен (даже в тех заголовочных файлах библиотеки, которые пользователь непосредственно подключает):
namespace work_lib_namespace
{
using namespace std;

class detail_class
{
public:
// интерфейс
private:
vector data_;
};
}

Заключение

Представленный способ организации библиотеки позволяет с одной стороны добиться хорошего «самодокументирования» кода, а с другой — позволить разработчикам библиотеки использовать using namespace не только в файлах реализации сpp, но и в заголовочных файлах.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js