День двести сорок восьмой. #BestPractices

Разработка для Расширяемости

Базовые классы для реализации абстракций

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

Они служат помощниками для реализации абстракций. Например, одной из абстракций .Net Framework для упорядоченных коллекций элементов является интерфейс IList<T>. Реализация IList<T> не тривиальна, и поэтому фреймворк предоставляет несколько базовых классов, таких как Collection<T> и KeyedCollection<TKey, TItem>, которые служат помощниками для реализации пользовательских коллекций.

Базовые классы обычно не подходят для использования в качестве абстракций, потому что они, как правило, содержат слишком много реализованной функциональности. Например, базовый класс Collection<T> содержит множество реализаций, например, необобщённого интерфейса IList (для лучшей интеграции с необобщёнными коллекциями), а также функционал управления коллекцией элементов, хранящихся в памяти в одном из полей класса.

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



⚠️ РАССМОТРИТЕ возможность сделать базовые классы абстрактными, даже если они не содержат абстрактных членов. Это ясно сообщает пользователям, что класс предназначен исключительно для наследования.

⚠️ РАССМОТРИТЕ возможность размещения базовых классов в пространстве имен отдельном от основных вариантов использования. По определению базовые классы предназначены для сценариев расширяемости, что является продвинутым уровнем использования фреймворка, и поэтому не интересно большинству пользователей.

ИЗБЕГАЙТЕ именования базовых классов с суффиксом «Base», если этот класс предназначен для использования в общедоступных API.



Источник: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/