Общее именование классов, работающих с бизнес-сущностями?
От: D.Lans Россия  
Дата: 22.02.17 08:31
Оценка: 1 (1)
Есть сайт. В нём классы бизнес-моделей, кладущиеся на таблицы БД: User, Configuration и т.д.

И у каждой такой модели есть сопряжённый класс, который содержит ряд функций бизнес-логики. Каждая такая функция работает с БД-контекстом (создаваемым и убиваемым в её рамках), кроме того некоторые функции используют сопряжённые классы других сущностей.

Вопрос на засыпку: какой суффикс выбрать для таких классов?
Конечно есть классический менеджер: UserManager, ConfigurationManager.
Но это вроде как моветон
https://blog.codinghorror.com/i-shall-call-it-somethingmanager/

UserService? Но сервисы в данном проекте уже заняты за классами, время жизни которых превышает жизнь контроллеров, они долгое время висят в памяти, в отдельном потоке, и общаются с другими через многопоточные очереди/сеть.
UserHelper? Но хелперы в данном проекте эти легковесные классы, чаще всего даже статические, содержащие "несерьёзный" вспомогательный код (в противовес сабжевым классам с их "серьёзным", незаменимым кодом).

Нужно что-то ещё.

Нашёл список наиболее часто употребимых вариантов
http://stackoverflow.com/questions/1866794/naming-classes-how-to-avoid-calling-everything-a-whatevermanager

Coordinator
Builder
Writer
Reader
Handler
Container
Protocol
Target
Converter
Controller
View
Factory
Entity
Bucket

Но среди них не нахожу ничего подходящего.

Как бы вы назвали?
Re: Общее именование классов, работающих с бизнес-сущностями?
От: Sinix  
Дата: 22.02.17 09:04
Оценка: +1
Здравствуйте, D.Lans, Вы писали:

DL>Вопрос на засыпку: какой суффикс выбрать для таких классов?


DL>Конечно есть классический менеджер: UserManager, ConfigurationManager.

DL>Но это вроде как моветон
Моветон — это если применяется бессистемно. А если в проекте есть строгие соглашения по именованию, то хоть фубарами обзывать можно. Главное, чтоб путаницы не было.


DL>UserService? Но сервисы в данном проекте уже заняты за классами, время жизни которых превышает жизнь контроллеров, они долгое время висят в памяти, в отдельном потоке, и общаются с другими через многопоточные очереди/сеть.

В большинстве проектов под сервисами понимаются именно локальные сервисы. Которые (в идеале) stateless и не имеют разделяемого состояния.

А вот это "общаются с другими через многопоточные очереди/сеть" обзывают по-разному. В зависимости от того, какую книжку читал проектировщик, это actors/grains/pipes/channels/nodes/servicepoints/microservices. Именно чтоб не путать с локальными сервисами.
Re: Общее именование классов, работающих с бизнес-сущностями?
От: Vladek Россия Github
Дата: 22.02.17 09:07
Оценка:
Здравствуйте, D.Lans, Вы писали:

DL>Есть сайт. В нём классы бизнес-моделей, кладущиеся на таблицы БД: User, Configuration и т.д.


Я их называю DbUser, DbConfiguration. Это никакая не бизнес-модель, это просто классы для маппинга сырых данных на БД.

DL>И у каждой такой модели есть сопряжённый класс, который содержит ряд функций бизнес-логики. Каждая такая функция работает с БД-контекстом (создаваемым и убиваемым в её рамках), кроме того некоторые функции используют сопряжённые классы других сущностей.

Я предполагаю, вот это и есть настоящая модель предметной области. Эти классы будут называться User, Configuration и так далее, причём они не обязательно будут совпадать с классами маппинга Db*. Они содержат конкретные методы и свойства, реализующие пресловутую бизнес-логику, они могут быть полу-абстрактными и в наследниках уже использовать классы маппинга БД, когда наступает момент по бизнес-логике что-то поменять в БД.

DL>Вопрос на засыпку: какой суффикс выбрать для таких классов?

DL>Конечно есть классический менеджер: UserManager, ConfigurationManager.
DL>Но это вроде как моветон
DL>https://blog.codinghorror.com/i-shall-call-it-somethingmanager/

DL>Как бы вы назвали?


Ну вот — никаких суффиксов.

Кстати, для простого чтения данных из БД и отображения их на экране я использую другие классы: UserModel, ConfigurationModel. Эти классы сразу содержат много ненормализованных данных, которые нужно отобразить. Естественно, чтение из БД — это довольно простой и быстрый код.

А модель предметной области используется только для записи в БД, но не для чтения.
Re[2]: Общее именование классов, работающих с бизнес-сущностями?
От: D.Lans Россия  
Дата: 22.02.17 09:32
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>Я их называю DbUser, DbConfiguration. Это никакая не бизнес-модель, это просто классы для маппинга сырых данных на БД.


V>Кстати, для простого чтения данных из БД и отображения их на экране я использую другие классы: UserModel, ConfigurationModel.


Можете привести пример DbUser и UserModel, в котором бы была видна причина разделения их на два класса?
Re: Общее именование классов, работающих с бизнес-сущностями?
От: Blazkowicz Россия  
Дата: 22.02.17 09:43
Оценка: +1
Здравствуйте, D.Lans, Вы писали:

DL>И у каждой такой модели есть сопряжённый класс, который содержит ряд функций бизнес-логики. Каждая такая функция работает с БД-контекстом (создаваемым и убиваемым в её рамках), кроме того некоторые функции используют сопряжённые классы других сущностей.

То есть Transaction Script? Обычно сервисом и кличут. Если они более БД ориентированы, то Repository?

DL>UserService? Но сервисы в данном проекте уже заняты за классами, время жизни которых превышает жизнь контроллеров, они долгое время висят в памяти, в отдельном потоке, и общаются с другими через многопоточные очереди/сеть.

И ни слова о том что они делают и для чего нужны.
Re[2]: Общее именование классов, работающих с бизнес-сущностями?
От: D.Lans Россия  
Дата: 22.02.17 10:35
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>То есть Transaction Script?

Да, что-то в этом роде.

B>Если они более БД ориентированы, то Repository?

Тоже сначала думал над репозиторием, но, насколько я понимаю, этот паттерн содержит только простейшие методы для работы с БД с минимумом логики: добавить, отредактировать, удалить, найти. Всё что сверх этого — уже в понятие "репозиторий" не попадает. А в данном случае как раз таки полно "сверх этого" — сложных методов, содержащих кучу логики.

B>И ни слова о том что они делают и для чего нужны.

На стороне сайта такой "сервис", висящий в отдельном потоке, получает от контроллеров запросы по Queue и отправляет их по WebSockets в виндовую службу (которая кстати тоже содержит в имени злополучный Service), в которой аналогичный "сервис" в своём потоке эти запросы принимает и перенаправляет дальше по очереди в другой поток-"сервис" (назовём его ключевым).
В службе висят ещё несколько "сервисов", время от времени собирающих информацию из внешней среды (базы данных, файловая система) и сохраняющих в кеш, которым и пользуется "ключевой сервис" для подготовки ответов и возврата обратно по цепочке на сайт в его кеш.
Re[3]: Общее именование классов, работающих с бизнес-сущностями?
От: Vladek Россия Github
Дата: 22.02.17 11:40
Оценка: 1 (1)
Здравствуйте, D.Lans, Вы писали:

DL>Здравствуйте, Vladek, Вы писали:


V>>Я их называю DbUser, DbConfiguration. Это никакая не бизнес-модель, это просто классы для маппинга сырых данных на БД.


V>>Кстати, для простого чтения данных из БД и отображения их на экране я использую другие классы: UserModel, ConfigurationModel.


DL>Можете привести пример DbUser и UserModel, в котором бы была видна причина разделения их на два класса?


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

Не буду далеко ходить и приведу конкретный пример из приложения клиента для RSDN: первый класс содержит минимум полей, необходимых для сохранения поста в БД, второй класс содержит всю информацию, необходимую для отображения поста на экране в составе целого треда. Две роли, два класса, а класс для БД вообще internal в отдельной сборке.

  DbPost
namespace Rsdn.Client.Data.Storage
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using SQLite;

    [Table("Post")]
    internal class DbPost
    {
        [PrimaryKey]
        public int Id { get; set; }

        public int? ThreadId { get; set; }

        public int? SubthreadId { get; set; }

        [NotNull]
        public int ForumId { get; set; }

        [NotNull]
        public string Title { get; set; }

        [NotNull]
        public string Message { get; set; }

        [NotNull]
        public int UserId { get; set; }

        [NotNull]
        public string Username { get; set; }

        [NotNull]
        public DateTime Posted { get; set; }

        public DateTime? Updated { get; set; }

        [NotNull]
        public bool IsClosed { get; set; }
    }
}


  PostDetails
namespace Rsdn.Community.Interaction
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;

    public class PostDetails : IIdentifiable, IVotes
    {
        public int Id { get; private set; }

        public int? ThreadId { get; private set; }

        public int? SubthreadId { get; private set; }

        public string Title { get; private set; }

        public string Message { get; private set; }

        public DateTime? Updated { get; private set; }

        public DateTime Posted { get; private set; }

        public string Username { get; private set; }

        public int? InterestingCount { get; private set; }
        public int? ThanksCount { get; private set; }
        public int? ExcellentCount { get; private set; }
        public int? AgreedCount { get; private set; }
        public int? DisagreedCount { get; private set; }
        public int? Plus1Count { get; private set; }
        public int? FunnyCount { get; private set; }

        public int Position { get; internal set; }

        public int Level { get; internal set; }

        public bool IsNew { get; internal set; }
    }
}


Более того, одна и та же информация отображается по разному в разных контекстах, вот класс для отображения текущих тредов в отдельном форуме:
  ThreadDetails
namespace Rsdn.Community.Interaction
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;

    public class ThreadDetails : IIdentifiable, IVotes
    {
        public int Id { get; private set; }

        public string Title { get; private set; }

        public string Excerpt { get; private set; }

        public string Username { get; private set; }

        public DateTime Updated { get; private set; }

        public DateTime? Viewed { get; private set; }

        public int NewPostCount { get; private set; }

        public int PostCount { get; private set; }

        public int? InterestingCount { get; private set; }
        public int? ThanksCount { get; private set; }
        public int? ExcellentCount { get; private set; }
        public int? AgreedCount { get; private set; }
        public int? DisagreedCount { get; private set; }
        public int? Plus1Count { get; private set; }
        public int? FunnyCount { get; private set; }

        public bool IsNew { get; internal set; }
    }
}


И все три класса представляют разные роли для одной и той же сущности.
Re[3]: Общее именование классов, работающих с бизнес-сущностями?
От: Kolesiki  
Дата: 22.02.17 11:46
Оценка: +1
Здравствуйте, D.Lans, Вы писали:

DL>Можете привести пример DbUser и UserModel, в котором бы была видна причина разделения их на два класса?


Ровно про это и хотел сказать: вы же сами их и разделили! (см. начальное сообщение) Вопрос: а зачем? Ну есть класс PurchaseOrder — в нём куча полей для мэппинга в БД. Нужны бизнес-функции? Да ради бога, создавай! Что мешает-то? Нужны "бизнес-проперти" — тоже не проблема, "субдшные" поля помечаем атрибутами, остальное — наши полезные члены. Аналогично создаются проперти для удобного view (например, код валюты -> её название). В результате, из этой белиберды MVVM остаётся только Business-Database-Entity — ОДИН класс и его хватает за глаза на всё, включая тесты.
Возможно, где-то есть суперзадачи, где "одноклассовая" модель не подходит, но у меня таких не встречалось.
Re[4]: Общее именование классов, работающих с бизнес-сущностями?
От: Kolesiki  
Дата: 22.02.17 11:55
Оценка: -1
Здравствуйте, Vladek, Вы писали:

V>И все три класса представляют разные роли для одной и той же сущности.


Вот именно. Сущность — одна, а её представителей АЖ ТРИ. Причём с кучей пересекающихся членов. Мне кажется, в наш век безразмерной памяти, уже можно не экономить десяток байт и совместить все три сущности в одну. Причём специфичные (но не нужные сейчас) поля просто не заполнять.

V> public int? InterestingCount { get; private set; }

V> public int? ThanksCount { get; private set; }
V> public int? ExcellentCount { get; private set; }
V> public int? AgreedCount { get; private set; }
V> public int? DisagreedCount { get; private set; }
V> public int? Plus1Count { get; private set; }
V> public int? FunnyCount { get; private set; }

Боже, ну и маразм!... РСДН не хочет слегка умерить гамму эмоций по отн. к посту? Бред же — интересно, спасибо, пажалуста, плюс, согласен.... это делал гуманитарий?

V>Более того, одна и та же информация отображается по разному в разных контекстах


Вот это и есть повод объединить всё в одно. Данные — они одни, показывать из по-разному — задача UI.
Re[4]: Общее именование классов, работающих с бизнес-сущностями?
От: Sinix  
Дата: 22.02.17 12:09
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Не буду далеко ходить и приведу конкретный пример из приложения клиента для RSDN: первый класс содержит минимум полей, необходимых для сохранения поста в БД, второй класс содержит всю информацию, необходимую для отображения поста на экране в составе целого треда. Две роли, два класса, а класс для БД вообще internal в отдельной сборке.


Угу, это отличное решение для случая, когда весь код работает как подай-принеси, без особой логики.

У топикстартера, как я понял, биз-логики достаточно много. Настолько, что её в отдельный слой оформляют.
Как мне кажется, в этом случае держать несколько разных типов для представления несколько накладно. Проще работать напрямую с моделью, а viewmodel оставить как dto для фронтэнда.
Re[3]: Общее именование классов, работающих с бизнес-сущностями?
От: Blazkowicz Россия  
Дата: 22.02.17 12:49
Оценка:
Здравствуйте, D.Lans, Вы писали:

DL>Тоже сначала думал над репозиторием, но, насколько я понимаю, этот паттерн содержит только простейшие методы для работы с БД с минимумом логики: добавить, отредактировать, удалить, найти. Всё что сверх этого — уже в понятие "репозиторий" не попадает. А в данном случае как раз таки полно "сверх этого" — сложных методов, содержащих кучу логики.

Нет. Задача репозитория как раз инкапсулировать сложные запросы, а не CRUD.

DL>На стороне сайта такой "сервис", висящий в отдельном потоке, получает от контроллеров запросы по Queue и отправляет их по WebSockets в виндовую службу (которая кстати тоже содержит в имени злополучный Service), в которой аналогичный "сервис" в своём потоке эти запросы принимает и перенаправляет дальше по очереди в другой поток-"сервис" (назовём его ключевым).

"Диспетчер" это, а не сервис. Или "брокер" какой-нибудь.
Re: Общее именование классов, работающих с бизнес-сущностями?
От: Sharov Россия  
Дата: 22.02.17 18:31
Оценка:
Здравствуйте, D.Lans, Вы писали:

DL>Есть сайт. В нём классы бизнес-моделей, кладущиеся на таблицы БД: User, Configuration и т.д.


DL>И у каждой такой модели есть сопряжённый класс, который содержит ряд функций бизнес-логики. Каждая такая функция работает с БД-контекстом (создаваемым и убиваемым в её рамках), кроме того некоторые функции используют сопряжённые классы других сущностей.


DL>Вопрос на засыпку: какой суффикс выбрать для таких классов?

DL>Конечно есть классический менеджер: UserManager, ConfigurationManager.
DL>Но это вроде как моветон
DL>https://blog.codinghorror.com/i-shall-call-it-somethingmanager/

DL>Как бы вы назвали?


Либо Controller (модель у нас имеется, а без V можно жить), либо Manager.
Кодом людям нужно помогать!
Re: Общее именование классов, работающих с бизнес-сущностями?
От: sgrape Россия  
Дата: 23.02.17 05:33
Оценка:
Здравствуйте, D.Lans, Вы писали:

DL>Есть сайт. В нём классы бизнес-моделей, кладущиеся на таблицы БД: User, Configuration и т.д.

DL>И у каждой такой модели есть сопряжённый класс, который содержит ряд функций бизнес-логики.
DL>Как бы вы назвали?

UserLogic, ConfigurationLogic, etc.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.