Re: Codereview - подскажите что в методе можно улучшить?
От: bnk СССР http://unmanagedvisio.com/
Дата: 16.03.23 19:32
Оценка: 12 (3) +1
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?



Скорми ChatGPT:

В целом, ваш код выглядит неплохо, однако есть несколько замечаний и предложений по улучшению:

Имя метода ToHash не является самым информативным. Рекомендуется использовать более понятные имена, такие как GenerateUrlHashAsync или CreateUrlHashAsync.

Вместо InvalidEnumArgumentException лучше использовать ArgumentException или создать собственный класс исключения, например InvalidUrlException, так как InvalidEnumArgumentException обычно используется для проверки аргументов типа перечисления (enum).

В качестве CreatedBy используется пустая строка. Если это поле не является обязательным, возможно, стоит использовать null или добавить код для получения имени пользователя или системного аккаунта.

Добавьте XML-комментарии к методу, чтобы объяснить его назначение и параметры.

В блоке catch вы выбрасываете исключение снова, без всякой обработки. В зависимости от ситуации, вы можете добавить логирование или обработку ошибок.

Вот пример кода с учетом предложенных изменений:


/// <summary>
/// Generates a hash for the given URL, saves it to the database, and returns the hash.
/// </summary>
/// <param name="request">A CreateHashCommand containing the URL to hash.</param>
/// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
/// <returns>A Task that represents the asynchronous operation, containing the generated URL hash as a string.</returns>
public async Task<string> GenerateUrlHashAsync(CreateHashCommand request, CancellationToken cancellationToken)
{
    try
    {
        if (string.IsNullOrWhiteSpace(request.Url))
            throw new ArgumentException("Url cannot be null or empty.", nameof(request.Url));

        var urlInDb = new Url()
        {
            Created = DateTime.UtcNow,
            CreatedBy = null,
            OriginalUrl = request.Url
        };

        await _context.Urls.AddAsync(urlInDb, cancellationToken);
        await _context.SaveChangesAsync(cancellationToken);

        var urlHash = _hashgen.EncodeLong(urlInDb.Id);

        return urlHash;
    }
    catch (Exception ex)
    {
        // Add logging or error handling here.
        throw;
    }
}


Я в принципе согласен

Добавка насчет AddAsync — в данном контексте не имеет особого смысла (можно использовать Add), возможно дадут bonus point:
https://thesharperdev.com/ef-cores-addasync-v-add-method/

О еще нашел, вроде лежит на поверхности.
Какой смысл передавать весь request если из него используется только Url. Лишняя зависимость.
Не разумнее будет только Url и передать как параметр?
Отредактировано 17.03.2023 12:03 bnk . Предыдущая версия . Еще …
Отредактировано 16.03.2023 19:53 bnk . Предыдущая версия .
Отредактировано 16.03.2023 19:33 bnk . Предыдущая версия .
Re: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 16.03.23 22:14
Оценка: 15 (2) +1
- Плохой нейминг, последнее, чего ожидаешь от ToHash() — это то что он полезет в базу да еще и с апдейтом.
— если не используются nullable reference types, то request?.Url в обоих случаях а лучше var requestUrl = request?.Url и дальше юзать переменную.
— если _context EF, то последнее действие "сохранить все", соответственно предпоследнее достаточно просто обновить trackable пустем добавления в in-memory коллекцию, при правильной настройке Id будет заретрофичен после сохранения. В любом случае операции с _context нужно выносить в repository.
— выше писали про мутабельный Url — тут этого, конечно, нет, от силы плохие названия методов, хаш создается чтобы не светить Id наружу или что то в этом роде.
— если копать глубже, можно смотреть на single responsibility и сюда же idempotency метода, странновато добавлять Url без проверки на существование, нуждается в перепроверке, опять же вынос в репозиторий облегчает это.
Отредактировано 16.03.2023 22:23 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒ . Предыдущая версия .
Re[7]: SequenceHiLo
От: RushDevion Россия  
Дата: 19.03.23 19:07
Оценка: 13 (2) +1
Здравствуйте, Sharov, Вы писали:

S>Такой вопрос, а для кого эти стратегии расчитаны? Т.е. это должен быть один экземпляр приложения,

S>который работает с бд. Как множество микросервисов с SequenceHiLo не пересекутся тогда?
S>Т.е. в рамках одного процесса все это можно контролировать, а если процессов больше?

Нет, не пересекутся. Смотри.
 CREATE SEQUENCE [dbo].[MySequence] START WITH 1 INCREMENT BY 10;

 SELECT NEXT VALUE FOR [dbo].[MySequence]; -- (1) возвращается 1

 SELECT NEXT VALUE FOR [dbo].[MySequence]; -- (2) возвращается 11

Получение NEXT VALUE синхронизованы на уровне движка БД, т.е. там что-то типа такого:
lock(syncLock) {
  var old = current
  current += 10;
  return old;
}

В (1) мы получили значение 1. И мы знаем, что шаг sequence = 10.
Это значит, что значения 1,2,3...10 можно спокойно использовать в качестве идентификаторов, т.к. следующий кто вызовет sequence получит уже 11.
Аналогично после шага (2) можно использовать 11,12...20 и т.д.

Это, к слову, не класический алгоритм HiLo (класический можешь загуглить), но там смысл такой же.

S> Если короче-- каковы сценарии hilo?


Минимизировать взаимодействие в БД при вставке графа объектов.
Если все ID уже назначены на клиентской стороне, то можно открыть транзакцию отправить все SQL INSERT и быстренько закомититься.
Не нужно после каждой вставки получать обратно SCOPE_IDENTITY(), как в случае с IDENTITY-столбцом.
В итоге вставка быстрее, транзакция короче, локов/дедлоков меньше.

Плюс, например, в логи можно писать ID-сущностей, не делая каждый раз SaveChanges.

Или иногда бывает нужна сквозная идентификация всех объектов в БД и поэтому отдельный IDENTITY на каждой таблицы не подходит.
Re: Codereview - подскажите что в методе можно улучшить?
От: yenik  
Дата: 16.03.23 19:41
Оценка: +3
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?


Метод удалить как страшный сон, запросить требования, ознакомиться с проектом, реализовать требуемую функциональность по-людски.
Re: Codereview - подскажите что в методе можно улучшить?
От: Ночной Смотрящий Россия  
Дата: 16.03.23 19:32
Оценка: +2
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?


В дополнение к уже сказанному метод нужно назвать ToHashAsync.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re: ненавижу такие угадайки
От: Quebecois Канада https://www.canada.ca/
Дата: 17.03.23 03:48
Оценка: +2
Здравствуйте, Glestwid, Вы писали:

Здесь можно прикопаться к:

Интервьюер, скорее всего, имеет в виду некоторое подмножество из этих пунктов, и других впридачу. Если вы назовете меньше — посчитает лентяем, больше — занудой.
Если очень хочется там работать, то можно позадавать кучу вопросов, зачем делается то, зачем это, и что хотим поймать через code review — это даст какие-никакие подсказки к содержимому чёрного ящика в голове спрашивающего, но это может не сработать.
Re[5]: Codereview - подскажите что в методе можно улучшить?
От: RushDevion Россия  
Дата: 17.03.23 14:07
Оценка: 5 (1)
G>Т.е. AddASync таки лезет в базу, и именно так мне назначенный ID и прилетает до SaveChanges?

Лезет AddAsync в БД или нет зависит от того, как настроен DB-контекст.
В частности, от выбранной стратегии установки identity для сохраняемой entity.
Если используется генерация на уровне БД (например, IDENTITY column в MS SQL), то похода в БД не будет, но Id будет 0 до вызова SaveChanges.
Если используется SequenceHiLo или просто Sequence, то поход в БД может быть, а может не быть. Если, например, шаг sequence = 5, то первые пять вызовов пройдут без похода в БД, затем будет один поход для получения текущего значения sequence и следующие 5 вызовов снова будут без похода в БД.
Если же ID назначается пользовательским кодом (например это Guid или какой-то глобальный shared счетчик или какая-то еще кастомная стратегия), то похода в БД опять же не будет.
Re: Codereview - подскажите что в методе можно улучшить?
От: _FRED_ Черногория
Дата: 17.03.23 15:30
Оценка: 5 (1)
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?

  Код спрятал
G>    public async Task<string> ToHash(CreateHashCommand request, CancellationToken cancellationToken)
G>    {
G>        try
G>        {
G>            if (string.IsNullOrWhiteSpace(request.Url))
G>                throw new InvalidEnumArgumentException();
G>            var urlInDb = new  Url()
G>            {
G>                Created = DateTime.UtcNow,
G>                CreatedBy = "",
G>                OriginalUrl = request.Url
G>            };
G>            await _context.Urls.AddAsync(urlInDb, cancellationToken);
G>            await _context.SaveChangesAsync(cancellationToken);
G>            var urlHash = _hashgen.EncodeLong(urlInDb.Id);

G>            return urlHash;
G>        }
G>        catch (Exception ex)
G>        {
G>            throw;
G>        }
G>    }


В целом о ревью. Коллеги выше предлагают чуть ли не предложить всё переделать. Это, несомненно, возможно, но не интересно. На "ревью" во время собеседования, когда вам, зачастую, не говорят, что же хотелось сделать и, учитывая, что вы, скорее всего не знаете, как и что организовано там, откуда этот код, мне кажется полезнее не делать безосновательных догадок о том, чего вы не знаете и больше опираться на то, что есть в коде. Например, в коде есть сохранение контекста после добавления строки. Значит, скорее всего, так и нужно. Нет логирования. Значит, скорее всего так и нужно: возможно, логирование ошибок есть где-то выше, а логирование запросов и параметров, наоборот, ниже). Если у вас есть, допустим, код всего класса и в других похожих методах логирование сделано вот так вот, в try/catch-е на всё тело тогда есть о чём поговорить, но вот по одному методу судить о нужности логирования именно тут чего-то мне кажется преждевременно.

Зато тут вот есть пустой catch. Вот такое вот совершенно точно бесмысленно и если его убрать, то станет намного лучше без потери вообще чего бы то ни было.

И по мелочи:

Совсем не ясны пляски с _hashgen.EncodeLong(urlInDb.Id) Это такая попытка замаскировать от пользвателя сгенерированный идентификатор?
Help will always be given at Hogwarts to those who ask for it.
Re[9]: SequenceHiLo
От: RushDevion Россия  
Дата: 20.03.23 11:02
Оценка: 5 (1)
S>Ага, ясно, благодарю. Собственно, я на хабре нашел статью, где обсуждался этот механизм, и там соотв. таблица
S>(sequence) генерится EF на уровне бд. Соотв. вопрос -- значит при создании контекста бд\сессии он, вновь
S>созданный контекст, будет неявно ходить в бд для получения нужной последовательности? Иначе как мы узнаем hilo?

Ну да. Контекст ходит в БД для получения текущего значения sequence (или текущего Hi-значения в случае HiLo).
Смысл в том, что он ходит раз в N (e.g. 10-100) вставок, а не каждый раз.

S>Кстати, не факт -- получить мы получили, но может быть проблема сохранить все это в бд. Таким образом

S>у нас появляется неконсистентность -- типа пишем, что есть ид от бд, хотя его в реальности еще нету.
S>Ну т.е. при попытке сохранить данные может что-то пойти не так.

Ну и что? В логах ты это увидишь примерно такое:
[Info] Order #100 created
[Info] Order item #101 for Order #100 added
[Info] Order item #102 for Order #100 added
[Info] Saving order #100 to DB
[Error] Db unavailable exception

Смотришь лог. Понимаешь, что БД была недоступна, записи по факту не вставились. Ну бывает, чо.
Это ничем не отличается от случая, если бы вместо int'овых Id ты использовал, скажем, Guid.

> А что это такое? Типа общий, уникальный id для всех объектов в бд?

Да. Для аудита такое иногда просят: чтобы любой объект в БД глобально-уникально идентифицировался по Id.
Codereview - подскажите что в методе можно улучшить?
От: Glestwid  
Дата: 16.03.23 18:08
Оценка: -1
Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?



    public async Task<string> ToHash(CreateHashCommand request, CancellationToken cancellationToken)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(request.Url))
                throw new InvalidEnumArgumentException();
            var urlInDb = new  Url()
            {
                Created = DateTime.UtcNow,
                CreatedBy = "",
                OriginalUrl = request.Url
            };
            await _context.Urls.AddAsync(urlInDb, cancellationToken);
            await _context.SaveChangesAsync(cancellationToken);
            var urlHash = _hashgen.EncodeLong(urlInDb.Id);

            return urlHash;
        }
        catch (Exception ex)
        {

            throw;
        }
    }
c# codereview
Re: Codereview - подскажите что в методе можно улучшить?
От: GarryIV  
Дата: 16.03.23 19:28
Оценка: +1
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?



G>

G>    public async Task<string> ToHash(CreateHashCommand request, CancellationToken cancellationToken) // вы там определитесь command у вас или request
G>    {
G>        try
G>        {
G>            if (string.IsNullOrWhiteSpace(request.Url))
G>                throw new InvalidEnumArgumentException(); // не соответствует проверке
G>            var urlInDb = new  Url()
G>            {
G>                Created = DateTime.UtcNow,
G>                CreatedBy = "", // эм, запашок
G>                OriginalUrl = request.Url
G>            };
G>            await _context.Urls.AddAsync(urlInDb, cancellationToken); // AddAsync должен таки возвращать что-то
G>            await _context.SaveChangesAsync(cancellationToken); // хочется запустить оба и ждать только потом. хотя тут вообще хрень какая-то с этим Add&Save
G>            var urlHash = _hashgen.EncodeLong(urlInDb.Id); // жесть, мутабельный урл. 

G>            return urlHash; // можно и без urlHash обойтись, но это придирки 
G>        }
G>        catch (Exception ex)
G>        {
G>            throw; // нахрена ловили? тем более Exception
G>        }
G>    }

G>
WBR, Igor Evgrafov
Re[5]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 15:00
Оценка: +1
M>Здесь на мой взгляд понятно, что в БД кладутся не URL, а запросы, каждый со своим timestamp и соответственно ID (и hash).
M>И никакой идемпотентности тут не предполагалось: повторное обращение к методу приводит к новой записи в БД.
M>Чтобы не было путаницы, я бы предложил переименовать метод (SaveRequestToDb).

мне ничего не понятно. в рестуфул сервисах вы много информации из Request Url — выудите кроме как для гетов да и то не всегда? Если это аудит траил — правильнее использовать fire&forget. Мы гадаем на кофейной гуще, друг мой.
Re[4]: Codereview - подскажите что в методе можно улучшить?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.03.23 15:13
Оценка: +1
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:

尿Ǥ푙>Как я сказал ранее, скорее всего первый await не нужен, достаточно простого добавлению в коллекцию trackable entities. Два раза базу дергать не надо.

Скорее всего, не нужен второй.
Я бы на месте пользователя этого кода крайне бы удивился тому, что у меня метод по генерации хеша для запроса вдруг закоммитит транзакцию в базу.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Codereview - подскажите что в методе можно улучшить?
От: RushDevion Россия  
Дата: 17.03.23 16:19
Оценка: +1
尿Ǥ푙>абсолютно верно. теоретически это может быть нужно и параллелить это вряд ли можно.

А параллелить при всем желании не получится.
DbContext (если речь про EF Core) не потокобезопасен.
Если память не изменяет, там InvalidOperationException стреляет, когда обнаружен параллельный доступ из нескольких потоков.
Re[7]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 16:29
Оценка: +1
M>Ко всему выше сказанному добавлю, что в условиях задачи (у топикстартера) нигде не сказано, что используется EF.
M>Это уже в комментариях предположили.
M>(я например, в разработке никогда с EF на практике не сталкивался, так что вообще не подумал бы в эту сторону )

основываясь на коде мы можем предположить это с высокой степенью вероятности
Re[6]: Codereview - подскажите что в методе можно улучшить?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.03.23 16:42
Оценка: +1
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:
尿Ǥ푙>к SaveChanges() столько же претензий сколько и плюсов, но это это конвенциональных способ сохранения измений в базу.
Это я как раз понимаю. Претензии не к SaveChanges, а к методу, который слишком много себе позволяет.
Он явно служебный, вызывается в рамках какого-то контроллера. Вот тот и должен решать, когда сделать SaveChangesAsync(), а не какой-то там вычислитель хеша. Может там кто-то потом отмену изменений запросит.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Codereview - подскажите что в методе можно улучшить?
От: Glestwid  
Дата: 17.03.23 20:49
Оценка: +1
_FR>Совсем не ясны пляски с _hashgen.EncodeLong(urlInDb.Id) Это такая попытка замаскировать от пользвателя сгенерированный идентификатор?

Нет, это пример сервиса short url. Там юзеру выдают хеш реального урла.
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: Ночной Смотрящий Россия  
Дата: 20.03.23 08:41
Оценка: +1
Здравствуйте, Glestwid, Вы писали:

G>Нет, это пример сервиса short url. Там юзеру выдают хеш реального урла.


Тогда метод следует назвать CreateHashAsync.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[4]: Codereview - подскажите что в методе можно улучшить?
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.03.23 11:37
Оценка: +1
НС>Тогда метод следует назвать CreateHashAsync.
Не очень понятны требования: нужно ли порождать разные хеши для одного и того же урла.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Codereview - подскажите что в методе можно улучшить?
От: Ночной Смотрящий Россия  
Дата: 20.03.23 13:31
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Не очень понятны требования: нужно ли порождать разные хеши для одного и того же урла.


Судя по коду — нужно. По логике, гипотетически, лучше наверное расшаривать.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 21.03.23 09:33
Оценка: +1
if (string.IsNullOrWhiteSpace(requestUrl)) return String.Empty;

так лучше не делать, ибо это узаконивает недокументированное поведение, которе рано или поздно пораждает легенды — типа так то оно так, но вот если...
Re[8]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 21.03.23 14:46
Оценка: +1
Типично это решается путем создания link table. то есть Urls отдельно, Users отдельно использование UserUrlClick. При этом совершенно непонятно почему createdby пустой, если это конечно, не TODO.
Re: Codereview - подскажите что в методе можно улучшить?
От: IncremenTop  
Дата: 16.03.23 19:04
Оценка:
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?


1. Разнести все по слоям — хоть и спорно, но как минимум 2 слоя напрашивается. Соответственно как минимум отдельные методы по созданию сущности и сохранению
2. Работа с ошибками — зачем пользователю АПИ видеть, что там именно БД накрылась медным тазом? Должны быть скорее всего иные ошибки.
3. Трейсинг.
4. Очень странная ошибка на пустой урл. Я бы вообще валидатор прикрутил бы с нормальной проверкой на то, что это именно урл, а не три буквы.
5. Непонятно, что будет если урл уже в базе? В чем бизнес-цель метода?
Отредактировано 17.03.2023 12:03 VladD2 . Предыдущая версия .
Re: Codereview - подскажите что в методе можно улучшить?
От: Sharov Россия  
Дата: 16.03.23 23:17
Оценка:
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?



G>

G>    public async Task<string> ToHash(CreateHashCommand request, CancellationToken cancellationToken)
G>    {
G>        try
G>        {
G >            if (string.IsNullOrWhiteSpace(request.Url))
G>                throw new InvalidEnumArgumentException();
);
>        }
G>    }

G>



Помимо бредового исключения, должно быть ArgNullExp, надо бы сам request на null проверить для начала.
+ Все сказанное выше.
Кодом людям нужно помогать!
Re: Codereview - подскажите что в методе можно улучшить?
От: Sharov Россия  
Дата: 16.03.23 23:24
Оценка:
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?



G>

G>    public async Task<string> ToHash(CreateHashCommand request, CancellationToken cancellationToken)
G>    {
G>        try
G>        {
G>            if (string.IsNullOrWhiteSpace(request.Url))
G>                throw new InvalidEnumArgumentException();
G>            var urlInDb = new  Url()
G>            {
G>                Created = DateTime.UtcNow,
G>                CreatedBy = "",
G>                OriginalUrl = request.Url
G>            };
G>            await _context.Urls.AddAsync(urlInDb, cancellationToken);
G>            await _context.SaveChangesAsync(cancellationToken);
G>            var urlHash = _hashgen.EncodeLong(urlInDb.Id);

G>            return urlHash;
G>        }
G>        catch (Exception ex)
G>        {

G>            throw;
G>        }
G>    }

G>


Опять же, выше хорошее замечания как про SRP. так и про идемпотентность. По уму, метод должен получть
urlInDb на вход как параметр и вызывать hashgen.EncodeLong. И все, не более.
Кодом людям нужно помогать!
Re[2]: Codereview - подскажите что в методе можно улучшить?
От: m2user  
Дата: 17.03.23 00:03
Оценка:
尿Ǥ푙>- если копать глубже, можно смотреть на single responsibility и сюда же idempotency метода, странновато добавлять Url без проверки на существование, нуждается в перепроверке, опять же вынос в репозиторий облегчает это.

Судя по типу Url в БД не url, а запросы, каждый со своим timestamp. Так что проверка на существование url вряд ли тут нужна.
Re[2]: Codereview - подскажите что в методе можно улучшить?
От: Glestwid  
Дата: 17.03.23 07:33
Оценка:
尿Ǥ푙>- если _context EF, то последнее действие "сохранить все", соответственно предпоследнее достаточно просто обновить trackable пустем добавления в in-memory коллекцию, при правильной настройке Id будет заретрофичен после сохранения. В любом случае операции с _context нужно выносить в repository.


Кстати,Url.Id назначается еще до SaveChanges, сразу при вызове Add(). А с двумя await что-то можно улучшить?
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 10:20
Оценка:
Мы обсуждаем вещи, сути которых не знаем. Обычно "hash" — это то что решает, нужно ли что то делать или нет на основании того если что то еще уже или нет. Если этот hash не идемпотентен, то возможно одна из ветвей логики, посвященная существующему хашу в приложении, никогда не будет выполняться, мне это кажется странным вот моя логика.
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 10:23
Оценка:
Как я сказал ранее, скорее всего первый await не нужен, достаточно простого добавлению в коллекцию trackable entities. Два раза базу дергать не надо.
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 10:30
Оценка:
это такая игра/процесс, лучше пройти ее на берегу для обеих сторон. Предложение дефолтить значния в конструкторе немного "странные", а с датами так и прсто некорректные.
Re[4]: Codereview - подскажите что в методе можно улучшить?
От: Sharov Россия  
Дата: 17.03.23 10:36
Оценка:
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:

尿Ǥ푙>Как я сказал ранее, скорее всего первый await не нужен, достаточно простого добавлению в коллекцию trackable entities. Два раза базу дергать не надо.


Он же базу дернет один раз, при save changes. Как без обращения к базе получить Id, разве просто add будет достаточно?
Кодом людям нужно помогать!
Re[2]: ненавижу такие угадайки
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 10:37
Оценка:
это такая игра/процесс, лучше пройти ее на берегу для обеих сторон. Предложение дефолтить значния в конструкторе немного "странные", а с датами так и прсто некорректные.
Re[5]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 10:41
Оценка:
может и так но зачем await при первом вызове _context.? они меняют постоянно все, я не уверен на 100%,

похоже, что на уровне интента, человек, который писал это, думал, что едиственным способ получить обратно identity — дернуть базу, что не так. я так это понял
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 10:43
Оценка:
Как я сказал ранее, скорее всего первый await не нужен, достаточно простого добавлению в коллекцию trackable entities. Два раза базу дергать не надо.
Re[6]: Codereview - подскажите что в методе можно улучшить?
От: Sharov Россия  
Дата: 17.03.23 10:57
Оценка:
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:

尿Ǥ푙>похоже, что на уровне интента, человек, который писал это, думал, что едиственным способ получить обратно identity — дернуть базу, что не так. я так это понял


Факт добавления в trackable entities Id не даст, Id даст бд. Без await в Id будет какой-нибудь 0.
Кодом людям нужно помогать!
Re[7]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 11:03
Оценка:
S>Факт добавления в trackable entities Id не даст, Id даст бд. Без await в Id будет какой-нибудь 0
это понятно, зачем await при добавлении в in-memory, надо понять, знает ли человек что savechanges также осуществляет адиз бак пропагейшн
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 11:41
Оценка:
был отачсти неправ, AddAsync() начинает трачить previously untracked entity.

This method is async only to allow special value generators, such as the one used by 'Microsoft.EntityFrameworkCore.Metadata.SqlServerValueGenerationStrategy.SequenceHiLo', to access the database asynchronously. For all other cases the non async method should be used.
Re[4]: Codereview - подскажите что в методе можно улучшить?
От: Glestwid  
Дата: 17.03.23 12:30
Оценка:
尿Ǥ푙>был отачсти неправ, AddAsync() начинает трачить previously untracked entity.

尿Ǥ푙>This method is async only to allow special value generators, such as the one used by 'Microsoft.EntityFrameworkCore.Metadata.SqlServerValueGenerationStrategy.SequenceHiLo', to access the database asynchronously. For all other cases the non async method should be used.

尿Ǥ푙>



Т.е. AddASync таки лезет в базу, и именно так мне назначенный ID и прилетает до SaveChanges?
Re[4]: Codereview - подскажите что в методе можно улучшить?
От: m2user  
Дата: 17.03.23 13:03
Оценка:
尿Ǥ푙>Мы обсуждаем вещи, сути которых не знаем.

В целом да, но видимо так поставлена задача у ТС

尿Ǥ푙> Обычно "hash" — это то что решает, нужно ли что то делать или нет на основании того если что то еще уже или нет. Если этот hash не идемпотентен, то возможно одна из ветвей логики, посвященная существующему хашу в приложении, никогда не будет выполняться, мне это кажется странным вот моя логика.


Здесь на мой взгляд понятно, что в БД кладутся не URL, а запросы, каждый со своим timestamp и соответственно ID (и hash).
И никакой идемпотентности тут не предполагалось: повторное обращение к методу приводит к новой записи в БД.
Чтобы не было путаницы, я бы предложил переименовать метод (SaveRequestToDb).
Re[6]: Codereview - подскажите что в методе можно улучшить?
От: m2user  
Дата: 17.03.23 14:28
Оценка:
G>>Т.е. AddASync таки лезет в базу, и именно так мне назначенный ID и прилетает до SaveChanges?
RD>Лезет AddAsync в БД или нет зависит от того, как настроен DB-контекст.

Ко всему выше сказанному добавлю, что в условиях задачи (у топикстартера) нигде не сказано, что используется EF.
Это уже в комментариях предположили.
(я например, в разработке никогда с EF на практике не сталкивался, так что вообще не подумал бы в эту сторону )
Re[6]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 15:03
Оценка:
Здравствуйте, RushDevion, Вы писали:

G>>Т.е. AddASync таки лезет в базу, и именно так мне назначенный ID и прилетает до SaveChanges?


RD>Лезет AddAsync в БД или нет зависит от того, как настроен DB-контекст.

RD>В частности, от выбранной стратегии установки identity для сохраняемой entity.
RD>Если используется генерация на уровне БД (например, IDENTITY column в MS SQL), то похода в БД не будет, но Id будет 0 до вызова SaveChanges.
RD>Если используется SequenceHiLo или просто Sequence, то поход в БД может быть, а может не быть. Если, например, шаг sequence = 5, то первые пять вызовов пройдут без похода в БД, затем будет один поход для получения текущего значения sequence и следующие 5 вызовов снова будут без похода в БД.
RD>Если же ID назначается пользовательским кодом (например это Guid или какой-то глобальный shared счетчик или какая-то еще кастомная стратегия), то похода в БД опять же не будет.

абсолютно верно. теоретически это может быть нужно и параллелить это вряд ли можно.
Re[5]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 16:25
Оценка:
такова суть EF — SaveChanges() коммитит все неизмененное для контекста, жалобы — к майкрософту выяснилось, что первый awaitable инициирует тракинг, и асинхронность нужна ему тех стратегий генерации ключа, что требуют запроса к базе хайло и все такое.

к SaveChanges() столько же претензий сколько и плюсов, но это это конвенциональных способ сохранения измений в базу.
Re[5]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 16:27
Оценка:
G>Т.е. AddASync таки лезет в базу, и именно так мне назначенный ID и прилетает до SaveChanges?

он лезет в базу но не за айди. указания на действие на тот момент просто нет, ему нужны данные для стратегий генерации ключа основанных на данных.
Re[7]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 17.03.23 17:13
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:

尿Ǥ푙>>к SaveChanges() столько же претензий сколько и плюсов, но это это конвенциональных способ сохранения измений в базу.
S>Это я как раз понимаю. Претензии не к SaveChanges, а к методу, который слишком много себе позволяет.
S>Он явно служебный, вызывается в рамках какого-то контроллера. Вот тот и должен решать, когда сделать SaveChangesAsync(), а не какой-то там вычислитель хеша. Может там кто-то потом отмену изменений запросит.

такое же ощущение, кусок чего то бОльшего. Я бы оставил как есть и попросил бы человека покрыть этот код юнит тестами, думаю в сл. раз был бы и репозиторий и интерфейс работы с базой более строгий.
Re[3]: ненавижу такие угадайки
От: Quebecois Канада https://www.canada.ca/
Дата: 18.03.23 05:05
Оценка:
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:

尿Ǥ푙>это такая игра/процесс, лучше пройти ее на берегу для обеих сторон. Предложение дефолтить значния в конструкторе немного "странные", а с датами так и прсто некорректные.


??? o_O ???

Почему они некорректные?
Вариант А:

class Url
{
  public Url()
  {
  }
}

...

var url = new Url{OriginalUrl = foo, Created = DateTime.Now);  //Повторяется 5 раз в разных местах


Вариант Б:

class Url
{
  public Url(string url)
  {
    Created = DateTime.Now;
    OriginalUrl = url;
  }
}

...

var url = new Url{foo);  //Повторяется 5 раз в разных местах


Второй вариант банально проще (меньше повторяющегося кода) и чище (разделено "что" и "как"). Ну и если URL добавляется ассоциативную таблицу, то релевантные поля должны быть readonly.
Re[4]: ненавижу такие угадайки
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 18.03.23 08:17
Оценка:
вообще шутил, но:

1. Даты могут привязаны к бизнес процессу а не ко времени создания объекта, а могут — нет.
2. Вы можете быть удивлены, но юзер в современных сервисах часто представлен токеном неизвестным (и не должным быть известным) на момент создания моделей. Если по-простому, для работы с секьюрити объектами наши бизнесс объекты должны иметь exposure на объекты секьюрити, что не есть хорошо. Это, конечно, больше вопрос дизайна, но это тоже надо учитывать. Сценарии типа — выполнить от лица и так далее, да много чего еще будут имет более простую реализацию если мы придерживаемся простого принципа — объекты отдельно, секьюрити — отдельно. Мой тейк таков — если уж и иметь секьюрити частью домена в качестве "карго компромиса", то по крайней мере не давать домену управлять ими.
Re[6]: SequenceHiLo
От: Sharov Россия  
Дата: 19.03.23 11:58
Оценка:
Здравствуйте, RushDevion, Вы писали:

RD>Если используется SequenceHiLo или просто Sequence, то поход в БД может быть, а может не быть. Если, например, шаг sequence = 5, то первые пять вызовов пройдут без похода в БД, затем будет один поход для получения текущего значения sequence и следующие 5 вызовов снова будут без похода в БД.


Такой вопрос, а для кого эти стратегии расчитаны? Т.е. это должен быть один экземпляр приложения,
который работает с бд. Как множество микросервисов с SequenceHiLo не пересекутся тогда?
Т.е. в рамках одного процесса все это можно контролировать, а если процессов больше?
Или там при создании db контекста, он(контекст) лезет в базу (один раз как минимум) и резервируют
себе соотв. HiLo? .

Если короче-- каковы сценарии hilo?
Кодом людям нужно помогать!
Отредактировано 19.03.2023 13:29 Sharov . Предыдущая версия .
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: _FRED_ Черногория
Дата: 20.03.23 07:17
Оценка:
Здравствуйте, Glestwid, Вы писали:

_FR>>Совсем не ясны пляски с _hashgen.EncodeLong(urlInDb.Id) Это такая попытка замаскировать от пользвателя сгенерированный идентификатор?


G>Нет, это пример сервиса short url. Там юзеру выдают хеш реального урла.


Тогда я б ещё вынес сохзранение данных в БД в отдельный метод, который возвращало бы, допустим, айдишник. А в этом самом методе получал бы айдишник и возвращал хеш.
Help will always be given at Hogwarts to those who ask for it.
Re: Codereview - подскажите что в методе можно улучшить?
От: denis.st Россия  
Дата: 20.03.23 07:42
Оценка:
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
убрать лишний пробел перед Url, и пустую строку перед throw
Re[8]: SequenceHiLo
От: Sharov Россия  
Дата: 20.03.23 10:06
Оценка:
Здравствуйте, RushDevion, Вы писали:


RD>Нет, не пересекутся. Смотри.

RD>
RD> CREATE SEQUENCE [dbo].[MySequence] START WITH 1 INCREMENT BY 10;

RD> SELECT NEXT VALUE FOR [dbo].[MySequence]; -- (1) возвращается 1

RD> SELECT NEXT VALUE FOR [dbo].[MySequence]; -- (2) возвращается 11
RD>

RD>Получение NEXT VALUE синхронизованы на уровне движка БД, т.е. там что-то типа такого:
RD>
RD>lock(syncLock) {
RD>  var old = current
RD>  current += 10;
RD>  return old;
RD>}
RD>

RD>В (1) мы получили значение 1. И мы знаем, что шаг sequence = 10.
RD>Это значит, что значения 1,2,3...10 можно спокойно использовать в качестве идентификаторов, т.к. следующий кто вызовет sequence получит уже 11.
RD>Аналогично после шага (2) можно использовать 11,12...20 и т.д.

Ага, ясно, благодарю. Собственно, я на хабре нашел статью, где обсуждался этот механизм, и там соотв. таблица
(sequence) генерится EF на уровне бд. Соотв. вопрос -- значит при создании контекста бд\сессии он, вновь
созданный контекст, будет неявно ходить в бд для получения нужной последовательности? Иначе как мы узнаем hilo?


S>> Если короче-- каковы сценарии hilo?

RD>Плюс, например, в логи можно писать ID-сущностей, не делая каждый раз SaveChanges.

Кстати, не факт -- получить мы получили, но может быть проблема сохранить все это в бд. Таким образом
у нас появляется неконсистентность -- типа пишем, что есть ид от бд, хотя его в реальности еще нету.
Ну т.е. при попытке сохранить данные может что-то пойти не так.

RD>Или иногда бывает нужна сквозная идентификация всех объектов в БД и поэтому отдельный IDENTITY на каждой таблицы не подходит.


А что это такое? Типа общий, уникальный id для всех объектов в бд?
Кодом людям нужно помогать!
Re: Codereview - подскажите что в методе можно улучшить?
От: vaa  
Дата: 21.03.23 06:48
Оценка:
Здравствуйте, Glestwid, Вы писали:

G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?



G>

G>    public async Task<string> ToHash(CreateHashCommand request, CancellationToken cancellationToken)
G>    {
G>        try
G>        {
G>            if (string.IsNullOrWhiteSpace(request.Url))
G>                throw new InvalidEnumArgumentException();
G>            var urlInDb = new  Url()
G>            {
G>                Created = DateTime.UtcNow,
G>                CreatedBy = "",
G>                OriginalUrl = request.Url
G>            };
G>            await _context.Urls.AddAsync(urlInDb, cancellationToken);
G>            await _context.SaveChangesAsync(cancellationToken);
G>            var urlHash = _hashgen.EncodeLong(urlInDb.Id);

G>            return urlHash;
G>        }
G>        catch (Exception ex)
G>        {

G>            throw;
G>        }
G>    }

G>


static Func<long,string> _hashgen = ....;
public static string ToHash(this Url url) => _hashgen.EncodeLong(url.Id);

async Task<Url> SaveRequest(string requestUrl) 
{
     var urlInDb = new  Url()
            {
               Created = DateTime.UtcNow,
               CreatedBy = "",
               OriginalUrl = requestUrl
            };
           await _context.Urls.AddAsync(urlInDb, cancellationToken);
           await _context.SaveChangesAsync(cancellationToken);
         return urlInDb;
}

app.MapGet("/hash", async (string requestUrl) =>
{
    if (string.IsNullOrWhiteSpace(requestUrl)) return String.Empty;
    var url = await SaveRequest(requestUrl);
    return url.ToHash();
});
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[6]: Codereview - подскажите что в методе можно улучшить?
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.03.23 13:36
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Судя по коду — нужно. По логике, гипотетически, лучше наверное расшаривать.
Там вопросы не только к логике. Это же, по идее, торчит в виде веб-сервиса. А это, в свою очередь, означает возможные глюки с потерей ответов.
Неудачно написанный клиент к такому веб-сервису в считанные часы за конечное время переполнит базу данных дубликатами.
Унификация хешей для одного и того же URL решает, в том числе, и эту проблему.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Codereview - подскажите что в методе можно улучшить?
От: m2user  
Дата: 21.03.23 14:26
Оценка:
НС>>Судя по коду — нужно. По логике, гипотетически, лучше наверное расшаривать.
S>Там вопросы не только к логике. Это же, по идее, торчит в виде веб-сервиса. А это, в свою очередь, означает возможные глюки с потерей ответов.
S>Неудачно написанный клиент к такому веб-сервису в считанные часы за конечное время переполнит базу данных дубликатами.
S>Унификация хешей для одного и того же URL решает, в том числе, и эту проблему.

Полагаю, что уникальная ссылка для каждой конвертации это by design.
Чтобы отслеживать переходы по этим ссылкам и пр.
Поле CreatedBy там не просто так.

Посмотрите, как https://tinyurl.com/ работает.
Для нового пользователя (без cookies) новый короткий url.

https://tinyurl.com/27xwht42
https://tinyurl.com/2p9ct2ja

Судя по разделу My URLs в БД как раз url, timestamp и данные о пользователе.
В Pro плане — tracked clicks.
Отредактировано 21.03.2023 14:30 m2user . Предыдущая версия .
Re[9]: Codereview - подскажите что в методе можно улучшить?
От: Ночной Смотрящий Россия  
Дата: 21.03.23 14:59
Оценка:
Здравствуйте, ????????G???????, Вы писали:

?G?>Типично это решается путем создания link table. то есть Urls отдельно, Users отдельно использование UserUrlClick.

Ты не понял о чем речь. Есть некий url. Пользователь А хочет считать клики по своей короткой ссылке на этот url, а пользователь В — по своей. Единственный способ различить чья ссылка — сделать для каждого из пользователей уникальный хеш.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[10]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 21.03.23 15:04
Оценка:
OK. Согласен.
Re[8]: Codereview - подскажите что в методе можно улучшить?
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.03.23 15:38
Оценка:
Здравствуйте, m2user, Вы писали:
M>Поле CreatedBy там не просто так.
Поле CreatedBy там заполняется "". Это случай анонимного пользователя, для которого не будет никакого подсчёта ссылок, а также возможности удалить шорткат или изменить его назначение.

M>Для нового пользователя (без cookies) новый короткий url.

M>https://tinyurl.com/27xwht42
M>https://tinyurl.com/2p9ct2ja

M>Судя по разделу My URLs в БД как раз url, timestamp и данные о пользователе.

M>В Pro плане — tracked clicks.
Pro план противоречит идее анонимного пользователя.
Очевидно, нам не показали исходник метода, применяемого для аутентифицированного пользователя. Вот в нём вполне можно создавать дубликаты.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Codereview - подскажите что в методе можно улучшить?
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.03.23 16:31
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Ты не понял о чем речь. Есть некий url. Пользователь А хочет считать клики по своей короткой ссылке на этот url, а пользователь В — по своей. Единственный способ различить чья ссылка — сделать для каждого из пользователей уникальный хеш.
Тогда у нас в поле CreatedBy будут различные значения, и это будет две разных строки в таблице с разными ID.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Codereview - подскажите что в методе можно улучшить?
От: Ночной Смотрящий Россия  
Дата: 21.03.23 18:08
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Тогда у нас в поле CreatedBy будут различные значения, и это будет две разных строки в таблице с разными ID.


Если учитывать это поле, то да, надо один хеш выдавать.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Codereview - подскажите что в методе можно улучшить?
От: vaa  
Дата: 22.03.23 02:02
Оценка:
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒, Вы писали:

尿Ǥ푙>if (string.IsNullOrWhiteSpace(requestUrl)) return String.Empty;


尿Ǥ푙>так лучше не делать, ибо это узаконивает недокументированное поведение, которе рано или поздно пораждает легенды — типа так то оно так, но вот если...


Почему же?
> null |> hash;;
val it: int = 0


можно для пустой строки создать специальный ресурс. пусть ходят кому интересно))
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: Codereview - подскажите что в методе можно улучшить?
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 22.03.23 09:59
Оценка:
вопрос больше акедемический, но мы байпассим логику аппликации без последствий для вызывающего компонента, это не есть хорошо. если и делать такое коротокое замыкание, то перед вызовом.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.