Здравствуйте, 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;
}
}
О еще нашел, вроде лежит на поверхности.
Какой смысл передавать весь request если из него используется только Url. Лишняя зависимость.
Не разумнее будет только Url и передать как параметр?
- Плохой нейминг, последнее, чего ожидаешь от ToHash() — это то что он полезет в базу да еще и с апдейтом.
— если не используются nullable reference types, то request?.Url в обоих случаях а лучше var requestUrl = request?.Url и дальше юзать переменную.
— если _context EF, то последнее действие "сохранить все", соответственно предпоследнее достаточно просто обновить trackable пустем добавления в in-memory коллекцию, при правильной настройке Id будет заретрофичен после сохранения. В любом случае операции с _context нужно выносить в repository.
— выше писали про мутабельный Url — тут этого, конечно, нет, от силы плохие названия методов, хаш создается чтобы не светить Id наружу или что то в этом роде.
— если копать глубже, можно смотреть на single responsibility и сюда же idempotency метода, странновато добавлять Url без проверки на существование, нуждается в перепроверке, опять же вынос в репозиторий облегчает это.
Здравствуйте, Sharov, Вы писали:
S>Такой вопрос, а для кого эти стратегии расчитаны? Т.е. это должен быть один экземпляр приложения, S>который работает с бд. Как множество микросервисов с SequenceHiLo не пересекутся тогда? S>Т.е. в рамках одного процесса все это можно контролировать, а если процессов больше?
Нет, не пересекутся. Смотри.
CREATE SEQUENCE [dbo].[MySequence] START WITH 1 INCREMENT BY 10;
SELECT NEXT VALUE FOR [dbo].[MySequence]; -- (1) возвращается 1SELECT 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 - подскажите что в методе можно улучшить?
Здравствуйте, Glestwid, Вы писали:
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
Метод удалить как страшный сон, запросить требования, ознакомиться с проектом, реализовать требуемую функциональность по-людски.
Re: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, Glestwid, Вы писали:
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
В дополнение к уже сказанному метод нужно назвать ToHashAsync.
Command vs request в названиях
Странному исключению при проверке URL (у которого может быть разумное объяснение)
Тому, что проверка должна быть в конструкторе Url, а может и не должна, если он больше нигде не вызвается
Тому, что значения для Created/CreatedBy похожи на дефолтные, которые надо выставлять в инициализаторах полей, или конструкторе (в зависимости от пожелания левой пятки тимлида)
Тому, что new Url можно переместить в Context.Urls
Тому, что SaveChangesAsync() и AddAsync() логично бы иметь на одном уровне (или на нескольких, в зависимости от того, что еще есть в _context)
Тому, что считать string-хэш от ulong довольно странно
Тому, что сохранять изменения после каждого добавления может быть жутко неоптимально (а может быть, оптимально, по куче причин, которые мы никогда не угадаем)
Тому, что делать catch и тут же throw как-то странно (а может и не странно, если автор любит ставить там breakpoint)
Пустой строке перед throw
Интервьюер, скорее всего, имеет в виду некоторое подмножество из этих пунктов, и других впридачу. Если вы назовете меньше — посчитает лентяем, больше — занудой.
Если очень хочется там работать, то можно позадавать кучу вопросов, зачем делается то, зачем это, и что хотим поймать через code review — это даст какие-никакие подсказки к содержимому чёрного ящика в голове спрашивающего, но это может не сработать.
Re[5]: Codereview - подскажите что в методе можно улучшить?
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 - подскажите что в методе можно улучшить?
Здравствуйте, Glestwid, Вы писали: G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
В целом о ревью. Коллеги выше предлагают чуть ли не предложить всё переделать. Это, несомненно, возможно, но не интересно. На "ревью" во время собеседования, когда вам, зачастую, не говорят, что же хотелось сделать и, учитывая, что вы, скорее всего не знаете, как и что организовано там, откуда этот код, мне кажется полезнее не делать безосновательных догадок о том, чего вы не знаете и больше опираться на то, что есть в коде. Например, в коде есть сохранение контекста после добавления строки. Значит, скорее всего, так и нужно. Нет логирования. Значит, скорее всего так и нужно: возможно, логирование ошибок есть где-то выше, а логирование запросов и параметров, наоборот, ниже). Если у вас есть, допустим, код всего класса и в других похожих методах логирование сделано вот так вот, в try/catch-е на всё тело тогда есть о чём поговорить, но вот по одному методу судить о нужности логирования именно тут чего-то мне кажется преждевременно.
Зато тут вот есть пустой catch. Вот такое вот совершенно точно бесмысленно и если его убрать, то станет намного лучше без потери вообще чего бы то ни было.
И по мелочи:
…, CancellationToken cancellationToken = default) — так обычно удобнее объявлять CancellationToken-параметры.
Если CreateHashCommand это ссылочный тип, то аргумент не мешало бы проверить на null.
Вместо InvalidEnumArgumentException уместнее бросать ArgumentException или ArgumentNullException, как это делается, например, здесь.
С сущностью (Url). Я б спросил, а это так и нужно, что CreatedBy = "" или это ошибка? Если это ошибка, то что там должно быть? Если это не ошибка и так и нужно, чтобы ORM сам подставил это поле нужное значение, возможно, ORM сам мог бы подставлять и Created?
_context мне кажется лучше заводить локальный, раз уж мы его сохраняем здесь же.
Подумать и решить, не нужно ли нам добавить .ConfigureAwait(continueOnCapturedContext: false). Скорее всего, нужно.
Совсем не ясны пляски с _hashgen.EncodeLong(urlInDb.Id) Это такая попытка замаскировать от пользвателя сгенерированный идентификатор?
Help will always be given at Hogwarts to those who ask for it.
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, Вы писали:
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 - подскажите что в методе можно улучшить?
M>Здесь на мой взгляд понятно, что в БД кладутся не URL, а запросы, каждый со своим timestamp и соответственно ID (и hash). M>И никакой идемпотентности тут не предполагалось: повторное обращение к методу приводит к новой записи в БД. M>Чтобы не было путаницы, я бы предложил переименовать метод (SaveRequestToDb).
мне ничего не понятно. в рестуфул сервисах вы много информации из Request Url — выудите кроме как для гетов да и то не всегда? Если это аудит траил — правильнее использовать fire&forget. Мы гадаем на кофейной гуще, друг мой.
Re[4]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали:
尿Ǥ푙>Как я сказал ранее, скорее всего первый await не нужен, достаточно простого добавлению в коллекцию trackable entities. Два раза базу дергать не надо.
Скорее всего, не нужен второй.
Я бы на месте пользователя этого кода крайне бы удивился тому, что у меня метод по генерации хеша для запроса вдруг закоммитит транзакцию в базу.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Codereview - подскажите что в методе можно улучшить?
尿Ǥ푙>абсолютно верно. теоретически это может быть нужно и параллелить это вряд ли можно.
А параллелить при всем желании не получится.
DbContext (если речь про EF Core) не потокобезопасен.
Если память не изменяет, там InvalidOperationException стреляет, когда обнаружен параллельный доступ из нескольких потоков.
Re[7]: Codereview - подскажите что в методе можно улучшить?
M>Ко всему выше сказанному добавлю, что в условиях задачи (у топикстартера) нигде не сказано, что используется EF. M>Это уже в комментариях предположили. M>(я например, в разработке никогда с EF на практике не сталкивался, так что вообще не подумал бы в эту сторону )
основываясь на коде мы можем предположить это с высокой степенью вероятности
Re[6]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали: 尿Ǥ푙>к SaveChanges() столько же претензий сколько и плюсов, но это это конвенциональных способ сохранения измений в базу.
Это я как раз понимаю. Претензии не к SaveChanges, а к методу, который слишком много себе позволяет.
Он явно служебный, вызывается в рамках какого-то контроллера. Вот тот и должен решать, когда сделать SaveChangesAsync(), а не какой-то там вычислитель хеша. Может там кто-то потом отмену изменений запросит.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Codereview - подскажите что в методе можно улучшить?
Типично это решается путем создания link table. то есть Urls отдельно, Users отдельно использование UserUrlClick. При этом совершенно непонятно почему createdby пустой, если это конечно, не TODO.
Re: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, Glestwid, Вы писали:
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
1. Разнести все по слоям — хоть и спорно, но как минимум 2 слоя напрашивается. Соответственно как минимум отдельные методы по созданию сущности и сохранению
2. Работа с ошибками — зачем пользователю АПИ видеть, что там именно БД накрылась медным тазом? Должны быть скорее всего иные ошибки.
3. Трейсинг.
4. Очень странная ошибка на пустой урл. Я бы вообще валидатор прикрутил бы с нормальной проверкой на то, что это именно урл, а не три буквы.
5. Непонятно, что будет если урл уже в базе? В чем бизнес-цель метода?
Здравствуйте, 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 - подскажите что в методе можно улучшить?
Здравствуйте, Glestwid, Вы писали:
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
Опять же, выше хорошее замечания как про SRP. так и про идемпотентность. По уму, метод должен получть
urlInDb на вход как параметр и вызывать hashgen.EncodeLong. И все, не более.
Кодом людям нужно помогать!
Re[2]: Codereview - подскажите что в методе можно улучшить?
尿Ǥ푙>- если копать глубже, можно смотреть на single responsibility и сюда же idempotency метода, странновато добавлять Url без проверки на существование, нуждается в перепроверке, опять же вынос в репозиторий облегчает это.
Судя по типу Url в БД не url, а запросы, каждый со своим timestamp. Так что проверка на существование url вряд ли тут нужна.
Re[2]: Codereview - подскажите что в методе можно улучшить?
尿Ǥ푙>- если _context EF, то последнее действие "сохранить все", соответственно предпоследнее достаточно просто обновить trackable пустем добавления в in-memory коллекцию, при правильной настройке Id будет заретрофичен после сохранения. В любом случае операции с _context нужно выносить в repository.
Кстати,Url.Id назначается еще до SaveChanges, сразу при вызове Add(). А с двумя await что-то можно улучшить?
Re[3]: Codereview - подскажите что в методе можно улучшить?
Мы обсуждаем вещи, сути которых не знаем. Обычно "hash" — это то что решает, нужно ли что то делать или нет на основании того если что то еще уже или нет. Если этот hash не идемпотентен, то возможно одна из ветвей логики, посвященная существующему хашу в приложении, никогда не будет выполняться, мне это кажется странным вот моя логика.
Re[3]: Codereview - подскажите что в методе можно улучшить?
это такая игра/процесс, лучше пройти ее на берегу для обеих сторон. Предложение дефолтить значния в конструкторе немного "странные", а с датами так и прсто некорректные.
Re[4]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали:
尿Ǥ푙>Как я сказал ранее, скорее всего первый await не нужен, достаточно простого добавлению в коллекцию trackable entities. Два раза базу дергать не надо.
Он же базу дернет один раз, при save changes. Как без обращения к базе получить Id, разве просто add будет достаточно?
это такая игра/процесс, лучше пройти ее на берегу для обеих сторон. Предложение дефолтить значния в конструкторе немного "странные", а с датами так и прсто некорректные.
Re[5]: Codereview - подскажите что в методе можно улучшить?
может и так но зачем await при первом вызове _context.? они меняют постоянно все, я не уверен на 100%,
похоже, что на уровне интента, человек, который писал это, думал, что едиственным способ получить обратно identity — дернуть базу, что не так. я так это понял
Re[3]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали:
尿Ǥ푙>похоже, что на уровне интента, человек, который писал это, думал, что едиственным способ получить обратно identity — дернуть базу, что не так. я так это понял
Факт добавления в trackable entities Id не даст, Id даст бд. Без await в Id будет какой-нибудь 0.
Кодом людям нужно помогать!
Re[7]: Codereview - подскажите что в методе можно улучшить?
S>Факт добавления в trackable entities Id не даст, Id даст бд. Без await в Id будет какой-нибудь 0
это понятно, зачем await при добавлении в in-memory, надо понять, знает ли человек что savechanges также осуществляет адиз бак пропагейшн
Re[3]: Codereview - подскажите что в методе можно улучшить?
был отачсти неправ, 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 - подскажите что в методе можно улучшить?
尿Ǥ푙>был отачсти неправ, 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 - подскажите что в методе можно улучшить?
В целом да, но видимо так поставлена задача у ТС
尿Ǥ푙> Обычно "hash" — это то что решает, нужно ли что то делать или нет на основании того если что то еще уже или нет. Если этот hash не идемпотентен, то возможно одна из ветвей логики, посвященная существующему хашу в приложении, никогда не будет выполняться, мне это кажется странным вот моя логика.
Здесь на мой взгляд понятно, что в БД кладутся не URL, а запросы, каждый со своим timestamp и соответственно ID (и hash).
И никакой идемпотентности тут не предполагалось: повторное обращение к методу приводит к новой записи в БД.
Чтобы не было путаницы, я бы предложил переименовать метод (SaveRequestToDb).
Re[6]: Codereview - подскажите что в методе можно улучшить?
G>>Т.е. AddASync таки лезет в базу, и именно так мне назначенный ID и прилетает до SaveChanges? RD>Лезет AddAsync в БД или нет зависит от того, как настроен DB-контекст.
Ко всему выше сказанному добавлю, что в условиях задачи (у топикстартера) нигде не сказано, что используется EF.
Это уже в комментариях предположили.
(я например, в разработке никогда с EF на практике не сталкивался, так что вообще не подумал бы в эту сторону )
Re[6]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 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 - подскажите что в методе можно улучшить?
такова суть EF — SaveChanges() коммитит все неизмененное для контекста, жалобы — к майкрософту выяснилось, что первый awaitable инициирует тракинг, и асинхронность нужна ему тех стратегий генерации ключа, что требуют запроса к базе хайло и все такое.
к SaveChanges() столько же претензий сколько и плюсов, но это это конвенциональных способ сохранения измений в базу.
Re[5]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали: 尿Ǥ푙>>к SaveChanges() столько же претензий сколько и плюсов, но это это конвенциональных способ сохранения измений в базу. S>Это я как раз понимаю. Претензии не к SaveChanges, а к методу, который слишком много себе позволяет. S>Он явно служебный, вызывается в рамках какого-то контроллера. Вот тот и должен решать, когда сделать SaveChangesAsync(), а не какой-то там вычислитель хеша. Может там кто-то потом отмену изменений запросит.
такое же ощущение, кусок чего то бОльшего. Я бы оставил как есть и попросил бы человека покрыть этот код юнит тестами, думаю в сл. раз был бы и репозиторий и интерфейс работы с базой более строгий.
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали:
尿Ǥ푙>это такая игра/процесс, лучше пройти ее на берегу для обеих сторон. Предложение дефолтить значния в конструкторе немного "странные", а с датами так и прсто некорректные.
??? 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.
1. Даты могут привязаны к бизнес процессу а не ко времени создания объекта, а могут — нет.
2. Вы можете быть удивлены, но юзер в современных сервисах часто представлен токеном неизвестным (и не должным быть известным) на момент создания моделей. Если по-простому, для работы с секьюрити объектами наши бизнесс объекты должны иметь exposure на объекты секьюрити, что не есть хорошо. Это, конечно, больше вопрос дизайна, но это тоже надо учитывать. Сценарии типа — выполнить от лица и так далее, да много чего еще будут имет более простую реализацию если мы придерживаемся простого принципа — объекты отдельно, секьюрити — отдельно. Мой тейк таков — если уж и иметь секьюрити частью домена в качестве "карго компромиса", то по крайней мере не давать домену управлять ими.
Здравствуйте, RushDevion, Вы писали:
RD>Если используется SequenceHiLo или просто Sequence, то поход в БД может быть, а может не быть. Если, например, шаг sequence = 5, то первые пять вызовов пройдут без похода в БД, затем будет один поход для получения текущего значения sequence и следующие 5 вызовов снова будут без похода в БД.
Такой вопрос, а для кого эти стратегии расчитаны? Т.е. это должен быть один экземпляр приложения,
который работает с бд. Как множество микросервисов с SequenceHiLo не пересекутся тогда?
Т.е. в рамках одного процесса все это можно контролировать, а если процессов больше?
Или там при создании db контекста, он(контекст) лезет в базу (один раз как минимум) и резервируют
себе соотв. HiLo? .
Здравствуйте, Glestwid, Вы писали:
_FR>>Совсем не ясны пляски с _hashgen.EncodeLong(urlInDb.Id) Это такая попытка замаскировать от пользвателя сгенерированный идентификатор?
G>Нет, это пример сервиса short url. Там юзеру выдают хеш реального урла.
Тогда я б ещё вынес сохзранение данных в БД в отдельный метод, который возвращало бы, допустим, айдишник. А в этом самом методе получал бы айдишник и возвращал хеш.
Help will always be given at Hogwarts to those who ask for it.
Re: Codereview - подскажите что в методе можно улучшить?
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
убрать лишний пробел перед Url, и пустую строку перед throw
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 - подскажите что в методе можно улучшить?
Здравствуйте, Glestwid, Вы писали:
G>Вот, на интервью скинули такой метод на ревью. Что в нем можно улучшить и(или) ускорить, помимо добавления логирования ошибок ?
Здравствуйте, Ночной Смотрящий, Вы писали: НС>Судя по коду — нужно. По логике, гипотетически, лучше наверное расшаривать.
Там вопросы не только к логике. Это же, по идее, торчит в виде веб-сервиса. А это, в свою очередь, означает возможные глюки с потерей ответов.
Неудачно написанный клиент к такому веб-сервису в считанные часы за конечное время переполнит базу данных дубликатами.
Унификация хешей для одного и того же URL решает, в том числе, и эту проблему.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Codereview - подскажите что в методе можно улучшить?
НС>>Судя по коду — нужно. По логике, гипотетически, лучше наверное расшаривать. S>Там вопросы не только к логике. Это же, по идее, торчит в виде веб-сервиса. А это, в свою очередь, означает возможные глюки с потерей ответов. S>Неудачно написанный клиент к такому веб-сервису в считанные часы за конечное время переполнит базу данных дубликатами. S>Унификация хешей для одного и того же URL решает, в том числе, и эту проблему.
Полагаю, что уникальная ссылка для каждой конвертации это by design.
Чтобы отслеживать переходы по этим ссылкам и пр.
Поле CreatedBy там не просто так.
Посмотрите, как https://tinyurl.com/ работает.
Для нового пользователя (без cookies) новый короткий url.
?G?>Типично это решается путем создания link table. то есть Urls отдельно, Users отдельно использование UserUrlClick.
Ты не понял о чем речь. Есть некий url. Пользователь А хочет считать клики по своей короткой ссылке на этот url, а пользователь В — по своей. Единственный способ различить чья ссылка — сделать для каждого из пользователей уникальный хеш.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[10]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 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 - подскажите что в методе можно улучшить?
Здравствуйте, Ночной Смотрящий, Вы писали: НС>Ты не понял о чем речь. Есть некий url. Пользователь А хочет считать клики по своей короткой ссылке на этот url, а пользователь В — по своей. Единственный способ различить чья ссылка — сделать для каждого из пользователей уникальный хеш.
Тогда у нас в поле CreatedBy будут различные значения, и это будет две разных строки в таблице с разными ID.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Codereview - подскажите что в методе можно улучшить?
Здравствуйте, 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ, Вы писали:
尿Ǥ푙>if (string.IsNullOrWhiteSpace(requestUrl)) return String.Empty;
尿Ǥ푙>так лучше не делать, ибо это узаконивает недокументированное поведение, которе рано или поздно пораждает легенды — типа так то оно так, но вот если...
Почему же?
> null |> hash;;
val it: int = 0
можно для пустой строки создать специальный ресурс. пусть ходят кому интересно))
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: Codereview - подскажите что в методе можно улучшить?
вопрос больше акедемический, но мы байпассим логику аппликации без последствий для вызывающего компонента, это не есть хорошо. если и делать такое коротокое замыкание, то перед вызовом.