powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Тестовое задание
25 сообщений из 153, страница 6 из 7
Тестовое задание
    #39481290
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttПарамонЭто сложно понять из названия, оно слишком общее.

В контексте букинга, сложно придумать другой смысл :)
Ну да. Accomodation - это размещение, или проживание.
Хотя можно и уточнить: HotelAccomodation (размещение в гостинице).
...
Рейтинг: 0 / 0
Тестовое задание
    #39481344
Парамон
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttПарамонЭто сложно понять из названия, оно слишком общее.

В контексте букинга, сложно придумать другой смысл :)
Пытался понять зачем мне искать название методу, который по сути просто поиск по параметрам. :) bookingService.FindHotels(searchModel) как вариант. Но, как понял передают спецификацию на прямую из контроллера.
...
Рейтинг: 0 / 0
Тестовое задание
    #39481352
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Парамон,

Твой вариант потребует изменять интерфейс и реализацию сервиса, когда понадобится добавить новое условие. Если условие надо будет изменить или расширить, ты рискуешь сломать вызовы. Спецификации могут находиться в разных сборках и использоваться без изменения или перекомпиляции репозитория. Букинг сервис действительно может выглядеть как ты описал, а он может использовать спецификацию для репозитория.
...
Рейтинг: 0 / 0
Тестовое задание
    #39482818
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопросы по спецификации. Такой интерфейс

Код: c#
1.
2.
3.
4.
public interface ISpecification<T> where T : BaseEntity
{
        Expression<Func<T, bool>> IsSatisfied();
}



предполагает, что эта спецификация будет воткнута до

Код: c#
1.
...select new {a, b, c }



а если надо после в виде
Код: c#
1.
q = q.Where(mySpecification.IsSatisfied())



как быть ???
...
Рейтинг: 0 / 0
Тестовое задание
    #39482937
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_taskкак быть ???

Например, так:

Код: c#
1.
2.
3.
4.
public interface ISpecification<T> where T : BaseEntity
{
        IQueryable<T> Specify(IQueryable<T> source);
}




test_taskа если надо после в виде
Код: c#
1.
q = q.Where(mySpecification.IsSatisfied())



Получится так:

Код: c#
1.
q = mySpecification.Specify(q);



Такая спецификация может не только отфильтровать, но и отсортировать, или сделать подвыбоку.
...
Рейтинг: 0 / 0
Тестовое задание
    #39482946
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostttest_taskкак быть ???

Например, так:

Код: c#
1.
2.
3.
4.
public interface ISpecification<T> where T : BaseEntity
{
        IQueryable<T> Specify(IQueryable<T> source);
}




test_taskа если надо после в виде
Код: c#
1.
q = q.Where(mySpecification.IsSatisfied())



Получится так:

Код: c#
1.
q = mySpecification.Specify(q);



Такая спецификация может не только отфильтровать, но и отсортировать, или сделать подвыбоку.

тут
Код: c#
1.
2.
3.
4.
public interface ISpecification<T> where T : BaseEntity
{
        IQueryable<T> Specify(IQueryable<T> source);
}


имеем ограничение
Код: c#
1.
where T : BaseEntity



а фильтровать надо "по анонимному типу"
Код: c#
1.
new {a, b, c }
...
Рейтинг: 0 / 0
Тестовое задание
    #39483237
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_task,

Спецификации изначально не расположены для работы с анонимными типами, по тому факту, что анонимные типы закрыты в том участке кода, где они используются, а дальше только рефлексией, что уже хуже, чем ADO-шные DataTable/DataSet. Убирай анонимные типы и заменяй на DTO-классы. С ними хотя бы протестировать можно твой код и писать обвязку.
...
Рейтинг: 0 / 0
Тестовое задание
    #39483362
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
повносил некоторые изменения
https://github.com/fiqwenbv/ParrotWings
...
Рейтинг: 0 / 0
Тестовое задание
    #39483378
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_task,

Код: c#
1.
repository.SaveChanges();



У тебя не поймёшь, сделай нормально SaveChanges() это задача UnitOfWork, а не IRepository, сам посмотри какой бардак: ISettingsRepository settingsRepository, IBaseRepository<Account> accountRepository... и IRepository.

Если бы сервисы не занимались построением запросов, ты бы убрал их, инкапсулировал в IQuery<TResult> (например Query<AccountDTO>), чтобы в сервисах только была логика, стало бы чище и лучше. А сейчас грязно, понамешано всего в кучу, сам попробуй свой код прочитать отстранённо, очень тяжело.
...
Рейтинг: 0 / 0
Тестовое задание
    #39483384
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_task,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public class AmountTransactionQuery
    {
        public IQueryable<AmountTransactionDTO> Get(IQueryable<AmountTransaction> queryable1,
            IQueryable<Account> queryable2,
            IQueryable<User> queryable3)
        {
            return (from t in queryable1
                    join a in queryable2 on t.AccountId equals a.Id
                    join ac in queryable2 on t.СorrespondentAccountId equals ac.Id
                    join uc in queryable3 on ac.UserId equals uc.Id
                    select new AmountTransactionDTO()
                    {
                        Id = t.Id,
                        DateTransaction = t.DateTransaction,
                        Amount = Math.Round(t.Amount, 2),
                        Balance = t.Balance,
                        CorrespondentAccountUserName = uc.UserName,
                        UserId = a.UserId,
                        СorrespondentAccountId = t.СorrespondentAccountId,
                        СorrespondentAccountUserId = uc.Id
                    });
        }
}



Не особо это улучшает ситуацию, ты возвращаешь живой и ленивый IQueryable от провайдера, потом начинаешь на нём достраивать запрос. Это даже хуже, чем если бы ты сразу всё в сервисе сделал.

Попробуй так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
// нужные интерфейсы

public interface IQuery {}
public interface IQuery<TResult> : IQuery {}
public interface IQueryHandler<TQuery> where TQuery : IQuery
{
   IEnumerable<TResult> Handle(TQuery query);
}
public interface IQueryProcessor
{
   IEnumerable<TResult> Process<TResult>(IQuery<TResult> query);
}

// вот что должно быть в итоге:

public class AmountTransactionService : BaseService, IAmountTransactionService
{
   ...
   public AmountTransactionService(..., IQueryProcessor queryProcessor,...)
   {
       ...
       _queryProcessor = queryProcessor;
       ...
   }
   ...
   public IEnumerable<AccountDTO> GetListCorrespondentAccount(long userId)
        {
            
            //  вместо этой фигни
            //

            AmountTransactionQuery amountTransactionQuery = new AmountTransactionQuery();
            var qb = amountTransactionQuery.Get(amountTransactionRepository.GetList(),
                accountRepository.GetList(),
                userRepository.GetList()).Where(t => t.UserId == userId);

            var q = from t in qb
                    group t by new { t.СorrespondentAccountId, t.CorrespondentAccountUserName, t.UserId } into grp
                    orderby grp.Max(t => t.DateTransaction) descending
                    let maxDateTransaction = grp.Max(t => t.DateTransaction)
                    select new AccountDTO()
                    {
                        Id = grp.Key.СorrespondentAccountId,
                        UserId = grp.Key.UserId,
                        UserName = grp.Key.CorrespondentAccountUserName,
                        MaxDateTransaction = maxDateTransaction
                    };

            return q.ToList();

            // вот так правильно и красиво

            // получаем уже материализованные данные, а не IQueryable
            var result = _queryProcessor(new CorrespondentAccountQuery(userId));
            // делаем чо надо, отдаём результат. всё красиво и понятно, вся логика запроса инкапсулирована
            // внутри соответствующего QueryHandler, он же получает нужные зависимости и там только запрос
            // никакой логики 
            return result;
}
...
Рейтинг: 0 / 0
Тестовое задание
    #39483393
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostttest_task,

Код: c#
1.
repository.SaveChanges();



У тебя не поймёшь, сделай нормально SaveChanges() это задача UnitOfWork, а не IRepository, сам посмотри какой бардак: 1. ISettingsRepository settingsRepository, IBaseRepository<Account> accountRepository... и 2. IRepository .

Если бы сервисы не занимались построением запросов, 3. ты бы убрал их, инкапсулировал в IQuery<TResult> (например Query<AccountDTO>), чтобы в сервисах только была логика, стало бы чище и лучше. А сейчас грязно, понамешано всего в кучу, сам попробуй свой код прочитать отстранённо, очень тяжело.
1. Это да, согласен, тут по предложению твоему и skyANA добавил декоратор. сделал так, чтобы проще было с неимплементированными методами
2. Так заканчивается работа UoW - repository.SaveChanges() - дергается из сервисов.
3. А в чем профит? на мой взгляд: не единообразно, IQuery<TResult> уже сервиса, сервис может что-то там добавить, например, какую-то пост обработку
...
Рейтинг: 0 / 0
Тестовое задание
    #39483400
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostttest_task,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public class AmountTransactionQuery
    {
        public IQueryable<AmountTransactionDTO> Get(IQueryable<AmountTransaction> queryable1,
            IQueryable<Account> queryable2,
            IQueryable<User> queryable3)
        {
            return (from t in queryable1
                    join a in queryable2 on t.AccountId equals a.Id
                    join ac in queryable2 on t.СorrespondentAccountId equals ac.Id
                    join uc in queryable3 on ac.UserId equals uc.Id
                    select new AmountTransactionDTO()
                    {
                        Id = t.Id,
                        DateTransaction = t.DateTransaction,
                        Amount = Math.Round(t.Amount, 2),
                        Balance = t.Balance,
                        CorrespondentAccountUserName = uc.UserName,
                        UserId = a.UserId,
                        СorrespondentAccountId = t.СorrespondentAccountId,
                        СorrespondentAccountUserId = uc.Id
                    });
        }
}



Не особо это улучшает ситуацию, ты возвращаешь живой и ленивый IQueryable от провайдера, потом начинаешь на нём достраивать запрос. Это даже хуже, чем если бы ты сразу всё в сервисе сделал.

Попробуй так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
// нужные интерфейсы

public interface IQuery {}
public interface IQuery<TResult> : IQuery {}
public interface IQueryHandler<TQuery> where TQuery : IQuery
{
   IEnumerable<TResult> Handle(TQuery query);
}
public interface IQueryProcessor
{
   IEnumerable<TResult> Process<TResult>(IQuery<TResult> query);
}

// вот что должно быть в итоге:

public class AmountTransactionService : BaseService, IAmountTransactionService
{
   ...
   public AmountTransactionService(..., IQueryProcessor queryProcessor,...)
   {
       ...
       _queryProcessor = queryProcessor;
       ...
   }
   ...
   public IEnumerable<AccountDTO> GetListCorrespondentAccount(long userId)
        {
            
            //  вместо этой фигни
            //

            AmountTransactionQuery amountTransactionQuery = new AmountTransactionQuery();
            var qb = amountTransactionQuery.Get(amountTransactionRepository.GetList(),
                accountRepository.GetList(),
                userRepository.GetList()).Where(t => t.UserId == userId);

            var q = from t in qb
                    group t by new { t.СorrespondentAccountId, t.CorrespondentAccountUserName, t.UserId } into grp
                    orderby grp.Max(t => t.DateTransaction) descending
                    let maxDateTransaction = grp.Max(t => t.DateTransaction)
                    select new AccountDTO()
                    {
                        Id = grp.Key.СorrespondentAccountId,
                        UserId = grp.Key.UserId,
                        UserName = grp.Key.CorrespondentAccountUserName,
                        MaxDateTransaction = maxDateTransaction
                    };

            return q.ToList();

            // вот так правильно и красиво

            // получаем уже материализованные данные, а не IQueryable
            var result = _queryProcessor(new CorrespondentAccountQuery(userId));
            // делаем чо надо, отдаём результат. всё красиво и понятно, вся логика запроса инкапсулирована
            // внутри соответствующего QueryHandler, он же получает нужные зависимости и там только запрос
            // никакой логики 
            return result;
}



спасибо. подумаю над этим
...
Рейтинг: 0 / 0
Тестовое задание
    #39483401
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_task2. Так заканчивается работа UoW - repository.SaveChanges() - дергается из сервисов.

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


test_task3. А в чем профит? на мой взгляд: не единообразно, IQuery<TResult> уже сервиса, сервис может что-то там добавить, например, какую-то пост обработку

Пост-обработку делай. Но там и запросы колбасишь. У тебя всё в куче. Сервис не должен знать о подробностях того, как ты запросы делаешь. LINQ, или SQL собираешь из кусочков, или вообще через веб-сервис данные запрашиваешь. Смешиваешь одно с другим, из-за этого тебе будет крайне тяжело тестировать свой код и сопровождать проблематично.
...
Рейтинг: 0 / 0
Тестовое задание
    #39483413
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttСервис не должен знать о подробностях того, как ты запросы делаешь. LINQ, или SQL собираешь из кусочков, или вообще через веб-сервис данные запрашиваешь.

разве это выполнимо? при использовании поддерживающих LINQ ОРМ - еще куда не шло (тот же NH при ICriteria - уже выбывает из фэншуя, вернее там свой фэншуй). но если RAW SQL - там "своя атмосфэра", про внешние веб-сервисы тоже самое.

я про то, что абстракции дырявые. для меня пока интересно чтобы работало для EF и NH
...
Рейтинг: 0 / 0
Тестовое задание
    #39483415
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_taskразве это выполнимо?

Что выполнимо? У тебя некий чёрный ящик, ты отдаёшь в него параметры запроса, получаешь результат. Как это произошло не важно. Может там использовались ICriteria для NH, или LINQ для EF, или SQL, или ещё что-то. Своя атмосфера, ок. Нам знать этого не надо. Нам нужны данные.


test_taskя про то, что абстракции дырявые. для меня пока интересно чтобы работало для EF и NH

ИМХО не вижу смысла тратить время на NH, хотя на удивление там 4-ую версию пилят.
Нафига, непонятно :)

Что до абстракций, ну надо знать меру. Надо понимать, зачем ты абстрагируешься. Что тебе это даёт. Когда ты в сервис запихал и логику и выполнение запросов, через LINQ-абстракцию, вот у тебя и она и потекла. А что, если нужно сделать запрос, не реализуемый на LINQ? Например, CTE? На самом деле CTE можно сделать через вью, но это костыль. Напрямую нельзя. Придётся втыкать какие-то распорки.
...
Рейтинг: 0 / 0
Тестовое задание
    #39483423
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttУ тебя некий чёрный ящик, ты отдаёшь в него параметры запроса, получаешь результат. Как это произошло не важно. Может там использовались ICriteria для NH, или LINQ для EF, или SQL, или ещё что-то. Своя атмосфера, ок. Нам знать этого не надо. Нам нужны данные.

для меня это проблема, может, и надуманная (я же не могу в сервисах использовать ICriteria, это прибиваться к реализации ОРМ). корень - фильтрация, проекции..., это же обязанность бизнес уровня, вроде. если не так, не получится никаких спецификаций, проекций, агрегаций. да и репозиторий теряет свою значимость.

или я чего-то не знаю...
...
Рейтинг: 0 / 0
Тестовое задание
    #39483441
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_task,

Фильтры реализуются спецификациями. По сути те же яйца как ICriteria, только чуть более высокоуровневые, они для NH могут конвертится в ICriteria, а для EF в LINQ и т.д. Но это если ты хочешь получить объекты ORM (сущности).

Запрос с параметрами и динамические фильтры -- это не одно и то же. Одним из параметров запроса может быть фильтр.

У тебя из-за этого и протекает в сервисы какой-нибудь LINQ, а если бы не LINQ, то ошмётки ICriteria. В общем, ORM тебе только мешает в данном случае :) Если не сможешь просто разделить понятия.
...
Рейтинг: 0 / 0
Тестовое задание
    #39483519
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostttest_task,

Спецификации изначально не расположены для работы с анонимными типами, по тому факту, что анонимные типы закрыты в том участке кода, где они используются, а дальше только рефлексией, что уже хуже, чем ADO-шные DataTable/DataSet. Убирай анонимные типы и заменяй на DTO-классы. С ними хотя бы протестировать можно твой код и писать обвязку.
с чего эт гости понаехали? Какая такая рефлексия?
...
Рейтинг: 0 / 0
Тестовое задание
    #39483533
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВс чего эт гости понаехали? Какая такая рефлексия?

А что ты будешь делать с объектом, не зная его типа?

return IEnumerable<anonymous type>

дальше что по твоему? без рефлексии?
...
Рейтинг: 0 / 0
Тестовое задание
    #39483606
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кому вернуть и как использовать?
hVostt
return IEnumerable<anonymous type>
...
Рейтинг: 0 / 0
Тестовое задание
    #39483659
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВКому вернуть и как использовать?
hVosttreturn IEnumerable<anonymous type>


Я хз, с чем ты не согласен, и что ты хочешь узнать. Вернуть тому, кому нужно, использовать так, как хочется использовать. В чём проблема? По существу будет?
...
Рейтинг: 0 / 0
Тестовое задание
    #39484124
test_task
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
реализовал, согласно рекомендациям hVostt, Query object
https://github.com/fiqwenbv/ParrotWings
...
Рейтинг: 0 / 0
Тестовое задание
    #39484129
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test_task,

Стало намного лучше
...
Рейтинг: 0 / 0
Тестовое задание
    #39484317
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,
Если есть
Код: c#
1.
return IQueryable<что то там>

, то это так же хорошо, как например что
Код: c#
1.
Queryable.FirstOrDefault


может принимать в качестве аргумента
Код: c#
1.
Expression<Func<TSource,&#8194;bool>> predicate


Написанный фик знает кем.

На крайняк есть картежи.
...
Рейтинг: 0 / 0
Тестовое задание
    #39484320
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ,

С анонимным типом ты за рамки метода не выйдешь, значит тебе придётся сосредоточить всю логику и запрос внутри. И получится каша. Чем тут помогут кортежи? Кортежи придётся строго типизировать в контрактах, это не лучше, чем отдельный класс.
...
Рейтинг: 0 / 0
25 сообщений из 153, страница 6 из 7
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Тестовое задание
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]