Я для себя использую гибрид так как обычно пишу бэк для Single Page Application У меня все запросы POST (кроме аутентификации, там GET по стандарту) Ошибки делятся на инфраструктурные и ошибки бизнес логики (инфраструктурные - это те которые можно описать на уровне middleware для всех запросов например 401, 403) такие ошибки обрабатываются на фронте так же на уровне всего приложения В отличии от JsonRpc статус success или error пишу в хедере, чтобы тело запроса можно было сразу десериллизовать в нужный тип, traceId так же в хедере, нет params так как не требуются batch запросы, зато можно результат возвращать стримом по мере поступления данных и сваггер выглядит нормально, да и в Google Chrome Developer путь запроса нормально отображается и не приходится гадать, а какой там метод вызывался с фронта
Это не так, тут почти всё как в вашем примере, IAction - это ваш IBusinesOperation, просто букв меньше, и он параметризирован, чтобы можно было указать входные и выходные параметры, а не просто void и без входных параметров, из контейнера мы получаем sp.GetRequiredService<GetUserAction>() а не sp.GetRequiredService<IAction<Guid, UserDto>>()
Нас не интересует получение по IAction<,>, он только как интерфейс маркер для того чтобы получить все классы которые его реализуют, чтобы можно было их зарегистрировать, ну и чтобы название метода строго задать, чтобы всё вразнабой не было
Работаем с Actions так
public record GetUserRequest(Guid Id);
public class GetUserEndpoint(GetUserAction getUserAction): IEndpoint<GetUserRequest, UserDto>
{
public Task<UserDto> Handle(GetUserRequest request, CancellationToken cancellationToken)
=> getUserAction.Execute(request.Id, cancellationToken);
}
Идея хорошая, мы тоже к такой пришли, но вот реализация как тут совсем не гибкая, нет особого смысла разделять Command и Query, к этому даже в MediatR пришли, не хотите ничего возвращать, верните Unit
public interface IAction<in TRequest, TResponse>
{
Task<TResponse> Execute(TRequest request, CancellationToken cancellationToken)
}
public class GetUserAction(AppDbContext dbContext, IMapper mapper): IAction<Guid, UserDto>
{
public virtual Task<UserDto> Execute(Guid request, CancellationToken cancellationToken)
{
return dbContext.Users
.Where(u => u.Id == request)
.ProjectTo<UserDto>(mapper.ConfigurationProvider)
.FirstOrDefaultAsync(cancellationToken) ?? throw new NotFoundException("User not found")
}
}
Нет смысла инжектить его потом по интерфейсу, для тестов метод можно сделать virtual тогда бизнес логику можно мокать
Так же мы у себя ввели правило, что мы не вызываем dbContext.SaveChangesAsync() в Action, только на уровне эндпоинта
По сути это похоже на медиатор, но медиатор - это сервис локатор, нам нужно погрузиться в бизнес логику, чтобы понять какие хендлеры он вызывает, тут же мы инжектим Action по имени класса, поэтому мы понимаем какие Action будут вызваны внутри и их можно замокать в тестах
Она была в начале, но потом было подписано соглашение о неразмещении вооружения на орбите. Собственно реклама о том что они собираются размещать вооружение может привести в к тому, что их объекты будут уничтожать сразу после вывода на орбиту. Поэтому этим никто и не занимается
Вроде виден намёк на размещение вооружения на орбите, но по идее это запрещено. Если нарушить этот запрет то ни о каком росте обороноспособности США нельзя будет говорить, так как вооружение появится на орбите и у других стран
Вот кстати непонятно, так ли это на самом деле. В классическом случае да, но вот при работе с многопоточкой совсем не факт что работает одинаково. Вот в С# я могу написать так
_ = Task.Run(() => DoSomething());
Тут я просто запущу таск и выйду и выполняться он будет, но если метод DoSomething() выбросит исключение, то оно нигде не обработается. Вот в этом случае кажется panic в go будет работать иначе
Ну "всё есть файловый дескриптор" это не совсем верно, да, при работе с файлами используются файловые дескрипторы, но у файла есть ещё данные права доступа и т. п. Файловый дескриптор бесполезен без самого файла, поэтому выражение "всё есть файл" или "всё есть поток" всё таки более верно имхо
Думаю тут скорее речь о гарантиях доставки, когда очередь в redis, совсем не факт что сообщение будет доставлено. Но по идее та же kafka решила бы эту проблему. Не понятно почему для очередей не использовать решение для очередей
Мне вот интересно, а если немного изменить условия? Допустим у нас есть листы А4 но писать и читать мы можем точками 1х1 мм, так же мы можем класть листы сбоку и снизу а так же вверх на другой лист, тем самым организуя трёхмерный массив точек, сколько бумаги потребуется чтобы сохранить 1 террабайт данных в этом случае?
Мне кажется лучшее решение которое я видел - сделали в vlang
fn print_sum(a string, b string) ! {
x := strconv.atoi(a)!
y := strconv.atoi(b)!
println('result: ${x+y}')
}
fn main() {
print_sum('a', '456') or { println(err) }
}
Похоже на предложение Яна Тейлора, но тут более лаконично в целом Мы видим что функция может вернуть ошибку так как она помечена ! Мы видим что происходит проброс ошибки на уровень выше так как при вызове функции используется тоже используется ! Если нужно обработать ошибку используется ключевое слово or Да есть неявная переменная err но так как это механизм языка то в целом это не важно, это часть стандартного механизма обработки ошибок
Кстати механизм работает точно так же и для опциональных результатов (которые могут возвращать none)
fn do_something(s string) !string {
if s == 'foo' {
return 'foo'
}
return error('invalid string')
}
a := do_something('foo') or { 'default' }
fn do_something(s string) ?string {
if s == 'foo' {
return 'foo'
}
return none
}
a := do_something('foo') or { 'default' }
Делал как то нечто подобное на C# нужно было добавить realtime обновления для AgGrid. Получилось что-то типа гугл таблиц. Но на C# это просто, берёшь SinnalR и всё
Ну не совсем, тут дело больше про отношение к работе, о внутренней культуре, а уже как это будет реализовано в техническом плане вопрос десятый. Но посыл совершенно правильный, на другой стороне сидит человек у которого проблема и ему нужно помочь с решением данной проблемы, и у специалиста техподдержки есть необходимый доступ до других специалистов в компании, тут важно не просто перевести заявку на нужного специалиста, а так же отслеживать статус решения проблемы и быть в контакте с клиентом
Я для себя использую гибрид так как обычно пишу бэк для Single Page Application
У меня все запросы POST (кроме аутентификации, там GET по стандарту)
Ошибки делятся на инфраструктурные и ошибки бизнес логики (инфраструктурные - это те которые можно описать на уровне middleware для всех запросов например 401, 403) такие ошибки обрабатываются на фронте так же на уровне всего приложения
В отличии от JsonRpc статус success или error пишу в хедере, чтобы тело запроса можно было сразу десериллизовать в нужный тип, traceId так же в хедере, нет params так как не требуются batch запросы, зато можно результат возвращать стримом по мере поступления данных и сваггер выглядит нормально, да и в Google Chrome Developer путь запроса нормально отображается и не приходится гадать, а какой там метод вызывался с фронта
у США и России есть противоспутниковое вооружение
Это не так, тут почти всё как в вашем примере, IAction - это ваш IBusinesOperation, просто букв меньше, и он параметризирован, чтобы можно было указать входные и выходные параметры, а не просто void и без входных параметров, из контейнера мы получаем
sp.GetRequiredService<GetUserAction>()а неsp.GetRequiredService<IAction<Guid, UserDto>>()По классу регистрация
Нас не интересует получение по
IAction<,>, он только как интерфейс маркер для того чтобы получить все классы которые его реализуют, чтобы можно было их зарегистрировать, ну и чтобы название метода строго задать, чтобы всё вразнабой не былоРаботаем с Actions так
Выглядит отвратительно же, как это читать вообще, вместо нормальной всем понятной логики сплошной бойлерплейт
Идея хорошая, мы тоже к такой пришли, но вот реализация как тут совсем не гибкая, нет особого смысла разделять Command и Query, к этому даже в MediatR пришли, не хотите ничего возвращать, верните Unit
Нет смысла инжектить его потом по интерфейсу, для тестов метод можно сделать virtual тогда бизнес логику можно мокать
Так же мы у себя ввели правило, что мы не вызываем dbContext.SaveChangesAsync() в Action, только на уровне эндпоинта
По сути это похоже на медиатор, но медиатор - это сервис локатор, нам нужно погрузиться в бизнес логику, чтобы понять какие хендлеры он вызывает, тут же мы инжектим Action по имени класса, поэтому мы понимаем какие Action будут вызваны внутри и их можно замокать в тестах
Она была в начале, но потом было подписано соглашение о неразмещении вооружения на орбите. Собственно реклама о том что они собираются размещать вооружение может привести в к тому, что их объекты будут уничтожать сразу после вывода на орбиту. Поэтому этим никто и не занимается
Вроде виден намёк на размещение вооружения на орбите, но по идее это запрещено. Если нарушить этот запрет то ни о каком росте обороноспособности США нельзя будет говорить, так как вооружение появится на орбите и у других стран
Рутуб на самом деле стал довольно приятным, особенно по подписке, стоит не дорого, но без рекламы, контента довольно много
Тут ведь профиль нагрузки в основном диски, а не процессор и gpu, кодирование видео происходит не так часто думаю тут выходит 10-12 киловатт где-то
Контур talk самое восхитительное из всего, чем пользовался.
https://kontur.ru/talk
Вот кстати непонятно, так ли это на самом деле. В классическом случае да, но вот при работе с многопоточкой совсем не факт что работает одинаково. Вот в С# я могу написать так
Тут я просто запущу таск и выйду и выполняться он будет, но если метод
DoSomething()выбросит исключение, то оно нигде не обработается. Вот в этом случае кажется panic в go будет работать иначеНу "всё есть файловый дескриптор" это не совсем верно, да, при работе с файлами используются файловые дескрипторы, но у файла есть ещё данные права доступа и т. п. Файловый дескриптор бесполезен без самого файла, поэтому выражение "всё есть файл" или "всё есть поток" всё таки более верно имхо
Думаю тут скорее речь о гарантиях доставки, когда очередь в redis, совсем не факт что сообщение будет доставлено. Но по идее та же kafka решила бы эту проблему. Не понятно почему для очередей не использовать решение для очередей
Почти 8кб можно организовать базу данных на листочках типа SQLite
Мне вот интересно, а если немного изменить условия? Допустим у нас есть листы А4 но писать и читать мы можем точками 1х1 мм, так же мы можем класть листы сбоку и снизу а так же вверх на другой лист, тем самым организуя трёхмерный массив точек, сколько бумаги потребуется чтобы сохранить 1 террабайт данных в этом случае?
Мне кажется лучшее решение которое я видел - сделали в vlang
Похоже на предложение Яна Тейлора, но тут более лаконично в целом
Мы видим что функция может вернуть ошибку так как она помечена
!Мы видим что происходит проброс ошибки на уровень выше так как при вызове функции используется тоже используется
!Если нужно обработать ошибку используется ключевое слово or
Да есть неявная переменная
errно так как это механизм языка то в целом это не важно, это часть стандартного механизма обработки ошибокКстати механизм работает точно так же и для опциональных результатов (которые могут возвращать none)
Ну как аналог meet есть talk от Контура. Кстати zoom после него стал казаться каким то неудобным
Делал как то нечто подобное на C# нужно было добавить realtime обновления для AgGrid. Получилось что-то типа гугл таблиц. Но на C# это просто, берёшь SinnalR и всё
Ну не совсем, тут дело больше про отношение к работе, о внутренней культуре, а уже как это будет реализовано в техническом плане вопрос десятый. Но посыл совершенно правильный, на другой стороне сидит человек у которого проблема и ему нужно помочь с решением данной проблемы, и у специалиста техподдержки есть необходимый доступ до других специалистов в компании, тут важно не просто перевести заявку на нужного специалиста, а так же отслеживать статус решения проблемы и быть в контакте с клиентом