Pull to refresh
199
0
Максим Аршинов @marshinov

В саббатикале

Send message

Деревья выражений в enterprise-разработке

Reading time19 min
Views40K
Для большинства разработчиков использование expression tree ограничивается лямбда-выражениями в LINQ. Зачастую мы вообще не придаем значения тому, как технология работает «под капотом».

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

Вы узнаете, как пользоваться expression tree напрямую, какие подводные камни приготовила технология и как их обойти.



Под катом — видео и текстовая расшифровка моего доклада с DotNext 2018 Piter.
Читать дальше →
Total votes 45: ↑45 and ↓0+45
Comments11

Доступ к данным в многопользовательских приложениях

Reading time4 min
Views8.3K
Вопрос ограничения доступа к данным встает при разработке многопользовательских систем почти всегда. Основные сценарии следующие:

  1. ограничение доступа к данным для пользователей не прошедших аутентификацию
  2. ограничение доступа к данным для аутентифицированных, но не обладающих необходимыми привелегиями пользователей
  3. предотвращение несанкционированного доступа с помощью прямых обращений к API
  4. фильтрация данных в поисковых запросах и списковых элементах UI (таблицы, списки)
  5. предотвращение изменения данных, принадлежащих одному пользователю другими пользователями

Сценарии 1-3 хорошо описаны и обычно решаются с помощью встроенных средств фреймворков, например role-based или claim-based авторизации. А вот ситуации, когда авторизованный пользователь может по прямому url получить доступ к данным «соседа» или совершить действие в его аккаунте случаются сплошь и рядом. Происходит это чаще всего из-за того что программист забывает добавить необходимую проверку. Можно понадеяться на код-ревью, а можно предотвратить такие ситуации применив глобальные правила фильтрации данных. О них и пойдет речь в статье.
Читать дальше →
Total votes 19: ↑17 and ↓2+15
Comments16

О декораторах, сквозной функциональности, CQRS и слоеной архитектуре

Reading time5 min
Views29K
Разработчик SimpleInjector очень любит «декораторы», особенно в сочетании с дженериками вида
QueryHandler<TIn, TOut>, CommandHanler<TIn, TOut>.

Такой подход позволяет «навешивать» на обработчики то, что принято называть cross-cutting concerns без регистрации и смс interception и особой уличной магии вроде Fody или PostSharp.

CQRS не top level architecture, поэтому хочется иметь такие-же декораторы и для классических Application Service. Под катом я расскажу как это сделать.
Читать дальше →
Total votes 12: ↑11 and ↓1+10
Comments21

Domain Driven Design на практике

Reading time12 min
Views267K
Эванс написал хорошую книжку с хорошими идеями. Но этим идеям не хватает методологической основы. Опытным разработчикам и архитекторам на интуитивном уровне понятно, что надо быть как можно ближе к предметной области заказчика, что с заказчиком надо разговаривать. Но не понятно как оценить проект на соответствие Ubiquitous Language и реального языка заказчика? Как понять, что домен разделен на Bounded Context правильно? Как вообще определить используется DDD в проекте или нет?

Последний пункт особенно актуален. На одном из своих выступлений Грег Янг попросил поднять руки тех, кто практиукует DDD. А потом попросил опустить тех, кто создает классы с набором публичных геттеров и сеттеров, располагает логику в «сервисах» и «хелперах» и называет это DDD. По залу прошел смешок:)

Как же правильно структурировать бизнес-логику в DDD-стиле? Где хранить «поведение»: в сервисах, сущностях, extension-методах или везде по чуть-чуть? В статье я расскажу о том, как проектирую предметную область и какими правилами пользуюсь.
Читать дальше →
Total votes 32: ↑28 and ↓4+24
Comments18

CQRS. Факты и заблуждения

Reading time10 min
Views187K

CQRS — это стиль архитектуры, в котором операции чтения отделены от операций записи. Подход сформулировал Грег Янг на основе принципа CQS, предложенного Бертраном Мейером. Чаще всего (но не всегда) CQRS реализуется в ограниченных контекстах (bounded context) приложений, проектируемых на основе DDD. Одна из естественных причин развития CQRS — не симметричное распределение нагрузки и сложности бизнес-логики на read и write — подсистемы Большинство бизнес-правил и сложных проверок находится во write — подсистеме. При этом читают данные зачастую в разы чаще, чем изменяют.

Не смотря на простоту концепции, детали реализации CQRS могут значительно отличаться. И это именно тот случай, когда дьявол кроется в деталях.
Читать дальше →
Total votes 31: ↑30 and ↓1+29
Comments108

Про ошибки и исключения

Reading time7 min
Views17K


В прошлый раз я разобрал два примера (раз, два), как можно перейти от императивной валидации входных значений к декларативной. Второй пример действительно «слишком много знает» про аспекты хранения и имеет подводные камни (раз, два). Альтернатива – разбить валидацию на 3 части:

  1. Модел байндинг: ожидали int, пришел string – возвращаем 400
  2. Валидация значений: поле email, должно быть в формате your@mail.com, а пришло 123Petya – возвращаем 422
  3. Валидация бизнес-правил: ожидали что корзина пользователя активна, а она в архиве. Возвращаем 422

К сожалению стандартный механизм байндинга ASP.NET MVC не различает ошибки несоответствия типа (получили string вместо int) и валидаци, поэтому если вы хотите различать 400 и 422 коды ответа, то придется это сделать самостоятельно. Но речь не об этом.

Как слой бизнес-логики может вернуть в контроллер сообщение об ошибке?


Самый распространенный по мнению Хабра способ (раз, два, три) – выбросить исключение. Таким образом между понятием «ошибка» и «исключение» ставится знак равно. Причем «ошибка» трактуется в широком смысле слова: это не только валидация, но и проверка прав доступа и бизнес-правил. Так ли это? Является ли любая ошибка «исключительной ситуацией»? Если вы когда-нибудь сталкивались с бухгалтерским или налоговым учетом, то наверняка знаете, что существует специальный термин «корректировка». Он означает, что в прошлом отчетном периоде были поданы неверные сведения и их необходимо исправить. То есть в сфере учета, без которой бизнес не может существовать в принципе, ошибки – объекты первого класса. Для них введены специальные термины. Можно ли назвать их исключительными ситуациями? Нет. Это нормальное поведение. Люди ошибаются. Программисты — просто чересчур оптимистичный народ. Мы просто никогда не снимаем розовых очков.
Читать статью полностью желаешь
Total votes 16: ↑15 and ↓1+14
Comments21

Еще немного о валидации в ASP.NET

Reading time3 min
Views11K
В прошлый раз я перенес часть императивного кода в атрибут. Есть еще одна проверка, кочующая из одного файла в другой:

public class MoveProductParam
{
   public ProductId {get; set; }

   public CategoryId {get; set; }
}

//...
if(!dbContext.Products.Any(x => x.Id == par.ProductId))
    return BadRequest("Product not found");

if(!dbContext.Categories.Any(x => x.Id == par.CategoryId ))
    return BadRequest("Category not found");

Мы достойны лучшего
public class MoveProductParam
{
   [EntityId(typeof(Product))]
   public ProductId {get; set; }

   [EntityId(typeof(Category))]
   public CategoryId {get; set; }
}
Читать дальше →
Total votes 13: ↑10 and ↓3+7
Comments53

Избавляемся от boilerplate для валидации в ASP.NET MVC

Reading time2 min
Views11K
В большинстве примеров проверка входных данных ASP.NET MVC осуществляется следующим образом:

        [HttpPost]
        public IActionResult Test(SomeParam param)
        {
            if (!ModelState.IsValid)
            {
                return View(param);
                // return Json({success: false, state: ModelState});
            }
            
            dbContext.UpdateData(param);

            return RedirectToAction("index");
            // return Ok({success: true});
        }

Этот код можно улучшить:

  1. вынести валидацию из тела метода и избавиться от дублирования if (!ModelState.IsValid)
  2. вернуть код ответа 422
Читать дальше →
Total votes 22: ↑18 and ↓4+14
Comments39

Шаблон проектирования «состояние» двадцать лет спустя

Reading time5 min
Views26K
Состояние — поведенческий шаблон проектирования. Используется в тех случаях, когда во время выполнения программы объект должен менять своё поведение в зависимости от своего состояния. Классическая реализация предполагает создание базового абстрактного класса или интерфейса, содержащего все методы и по одному классу на каждое возможно состояние. Шаблон представляет собой частный случай рекомендации «заменяйте условные операторы полиморфизмом».

Казалось бы, все по книжке, но есть нюанс. Как правильно реализовать методы не релевантные для данного состояния? Например, как удалить товар из пустой корзины или оплатить пустую корзину? Обычно каждый state-класс реализует только релевантные методы, а в остальных случаях выбрасывает InvalidOperationException.

Нарушение принципа подстановки Лисков на лицо. Yaron Minsky предложил альтернативный подход: сделайте недопустимые состояния непредставимыми (make illegal states unrepresentable). Это дает возможность перенести проверку ошибок со времени исполнения на время компиляции. Однако control flow в этом случае будет организован на основе сопоставления с образцом, а не с помощью полиморфизма. К счастью, частичная поддержка pattern matching появилась в C#7.
Альтернативная реализация шаблона
Total votes 21: ↑17 and ↓4+13
Comments26

О пользе лаконичности

Reading time8 min
Views9.4K


С одной стороны, программисты – мягко говоря не самые общительные люди на свете. Это нормально, ведь если разработчики вдруг станут разговорчивыми кто будет писать код? С другой – время одиночек прошло. Современное ПО разрабатывается командами и даже самые консервативные компании, вроде Сбербанка внедряют Agile. Agile manifest пропагандирует определенные ценности, в том числе: «Люди и взаимодействие важнее процессов и инструментов». Так что общение с коллегами – не прихоть, а потребность. Эта статья ориентирована на гибкие команды разработки: разработчиков, тим-лидов, аналитиков, тестировщиков и т.д.

Профессиональные PM вряд ли найдут здесь что-то новое. Если вы – «технарь» и хотите, чтобы вас как можно меньше отвлекали от основного вида деятельности и вам интересно при чем здесь Спарта, добро пожаловать под кат.
Читать дальше →
Total votes 17: ↑12 and ↓5+7
Comments2

Железнодорожно-ориентированное программирование. Обработка ошибок в функциональном стиле

Reading time11 min
Views20K

Как пользователь я хочу изменить ФИО и email в системе.

Для реализации этой простой пользовательской истории мы должны получить запрос, провести валидацию, обновить существующую запись в БД, отправить подтверждение на email пользователю и вернуть ответ браузеру. Код будет выглядеть примерно одинаково на C#:

string ExecuteUseCase() 
{ 
  var request = receiveRequest();
  validateRequest(request);
  canonicalizeEmail(request);
  db.updateDbFromRequest(request);
  smtpServer.sendEmail(request.Email);
  return "Success";
}

и F#:

let executeUseCase = 
  receiveRequest
  >> validateRequest
  >> canonicalizeEmail
  >> updateDbFromRequest
  >> sendEmail
  >> returnMessage
Читать дальше →
Total votes 18: ↑16 and ↓2+14
Comments15

OO VS FP

Reading time4 min
Views25K
Мой перевод, как и оригинальный доклад вызвали неоднозначную реакцию в комментариях. Поэтому я решил перевести статью-ответ дяди Боба на оригинальный материал.
Множество программистов на протяжении последних лет утверждают, что ООП и ФП — являются взаимоисключающими. С высоты башни из слоновой кости в облаках, ФП-небожители иногда поглядывают вниз на бедных наивных ООП-программистов и снисходят до надменных комментариев. Приверженцы ООП в свою очередь косо смотрят на «функционыльщиков», не понимая, зачем чесать левое ухо правой пяткой.

Эти точки зрения игнорируют саму суть ООП и ФП парадигм. Вставлю свои пять копеек.
Читать дальше →
Total votes 25: ↑20 and ↓5+15
Comments67

«Паттерны» функционального программирования

Reading time10 min
Views70K

Многие люди представляют функциональное программирование как нечто очень сложное и «наукоемкое», а представителей ФП-сообщества – эстетствующими философами, живущими в башне из слоновой кости.

До недавнего времени такой взгляд на вещи действительно был недалек от истины: говорим ФП, подразумеваем Хаскель и теорию категорий. В последнее время ситуация изменилась и функциональная парадигма набирает обороты в web-разработке, не без помощи F#, Scala и React. Попробуем взглянуть на «паттерны» функционального программирования, полезные для решения повседневных задач с точки зрения ООП – парадигмы.

ООП широко распространено в разработке прикладного ПО не одно десятилетие. Все мы знакомы с SOLID и GOF. Что будет их функциональным эквивалентом?.. Функции! Функциональное программирование просто «другое» и предлагает другие решения.


Читать дальше →
Total votes 61: ↑56 and ↓5+51
Comments361

Архитектура модульных React + Redux приложений 2. Ядро

Reading time9 min
Views12K
В первой части я уделил внимание только общей концепции: редюсеры, компоненты и экшны чаще меняются одновременно, а не по отдельности, поэтому и группировать и их целесообразнее по модулям, а не по отдельным папкам actions, components, reducers. Также к модулям были предъявлены требования:

  1. быть независимыми друг от друга
  2. взаимодействовать с приложением через API ядра

В этой части я расскажу о структуре ядра, подходящей для разработки data-driven систем.
Читать дальше →
Total votes 18: ↑15 and ↓3+12
Comments3

Архитектура модульных React + Redux приложений

Reading time7 min
Views61K


Большинство разработчиков начинает знакомство с Redux с Todo List Project. Это приложение имеет следующую структуру:

actions/
  todos.js
components/
  todos/
    TodoItem.js
    ...
constants/
  actionTypes.js
reducers/
  todos.js
index.js
rootReducer.js

На первый взгляд такая организация кода кажется логичной, ведь она напоминает стандартные соглашения многих backend MVC-фреймворков:

app/
  controllers/
  models/
  views/

На самом деле, это неудачный выбор как для MVC, так и для React+Redux приложений по следующим причинам:

  1. С ростом приложения следить за взаимосвязью между компонентами, экшнами и редюсерами становится крайне сложно
  2. При изменении экшна или компонента с большой вероятностью потребуется внести изменения и в редюсер. Если количество файлов велико, скролить IDE вверх/вниз не удобно
  3. Такая структура потворствует копипасте в редюсерах

Не удивительно, что многие авторы(раз, два, три) советуют структурировать приложение по «функциональности» (by feature).
Читать дальше →
Total votes 16: ↑15 and ↓1+14
Comments41

Введение в React и Redux для бекенд-разработчиков

Reading time9 min
Views58K


Если вы как я долгое время считали, что JavaScript – это такой «игрушечный» язык на котором пишут анимашки для менюшек и падающие снежинки на форумах под новый год, а потом очнулись в 2016 году с мыслями WTF: react, flux redux, webpack, babel,… не отчаивайтесь. Вы не одиноки. Материалов по современному фронтенду в сети много, даже слишком много. Под катом еще одно альтернативное мнение о том, каково это учить JavaScript в 2016 году.
Стань модным
Total votes 45: ↑33 and ↓12+21
Comments182

Функциональный C#

Reading time5 min
Views25K
C# — язык мультипарадигмальный. В последнее время крен наметился в сторону функциональщины. Можно пойти дальше и добавить еще немного методов-расширений, позволяющих писать меньше кода, не «залезая» при этом на территорию F#.
Читать дальше →
Total votes 31: ↑28 and ↓3+25
Comments59

Шаблон проектирования «Спецификация» в C#

Reading time7 min
Views41K
«Спецификация» в программировании — это шаблон проектирования, посредством которого представление правил бизнес логики может быть преобразовано в виде цепочки объектов, связанных операциями булевой логики.

Я познакомился с этим термином в процессе чтения DDD Эванса. На Хабре есть статьи с описанием практического применения паттерна и проблем, возникающих в процессе реализации.

Если коротко, основное преимущество от использования «спецификаций» в том, чтобы иметь одно понятное место, в котором сосредоточены все правила фильтрации объектов предметной модели, вместо тысячи размазанных ровным слоем по приложению лямбда-выражений.

Классическая реализация шаблона проектирования выглядит так:

public interface ISpecification
{
    bool IsSatisfiedBy(object candidate);
}

Что с ним не так применительно к C#?


  1. Есть Expression<Func<T, bool>> и Func<T, bool>>, сигнатура которых совпадает с IsSatisfiedBy
  2. Есть Extension-методы. alexanderzaytsev с помощью них делает вот так:

    public class UserQueryExtensions 
    {
      public static IQueryable<User> WhereGroupNameIs(this IQueryable<User> users,
    string name)
      {
          return users.Where(u => u.GroupName == name);
      }
    }
    

  3. А еще можно реализовать вот такую надстройку над LINQ:

    public abstract class Specification<T>
    {
      public bool IsSatisfiedBy(T item)
      {
        return SatisfyingElementsFrom(new[] { item }.AsQueryable()).Any();
      }
    
       public abstract IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates);
    }
    

В конечном итоге возникает вопрос: стоит ли в C# пользоваться шаблоном десятилетней давности из мира Java и как его реализовать?

Читать дальше →
Total votes 12: ↑9 and ↓3+6
Comments15

Union Type, TPT, DDD, ORM и RDBMS

Reading time7 min
Views7.4K

Объединения и pattern-matching широко используются в функциональном программировании для повышения надежности и выразительности программ.

Классический пример удачного использования объединений для моделирования бизнес-процессов – корзина и состояние заказа. Пользователь в праве добавлять и убирать товары, пока не оплатил заказ. Но сама операция модификации оплаченного заказа лишена смысла. Также лишена смысла операция Remove для пустой корзины. Тогда логично вместо общего класса Cart определить интерфейс ICartState и объявить по одной реализации для каждого состояния. Более подробно данный подход изложен текстом здесь и в видео-формате вот тут.

Недавно у нас возникла задача спроектировать структуру БД для специализированной CRM/ERP. Первый подход к моделированию договоров оказался не удачным, из-за того что сторонами договоров могут выступать как физические, так и юридические лица из России и других стран мира. ИНН необходим продавцу, чтобы получить оплату, но не всегда нужен полкупателю (для идентификации личности чаще используются паспортные данные). Форматы реквизитов отечественных и зарубежных юр.лиц не совпадают. Не помогало делу и то, что ИП являются физическими лицами, но «прикидываются» юридическими.

На ретроспективе мы разобрали ошибки первоначального дизайна и наметили направление рефакторинга. Всех, заинтересовавшихся нашей историей, прошу под кат.
Читать дальше →
Total votes 9: ↑8 and ↓1+7
Comments26

DotNext — Moscow 2016. Как это было

Reading time5 min
Views6.4K


Впервые я побывал на «Дотнексте» летом этого года в Питере. Тогда меня привлекли имена Дино Эспозито и Саши Гольдштейна в списке докладчиков. По книге Дино я когда-то давно осваивал ASP.NET. Pro .NET Performance не читал, но отзывы слышал лишь позитивные. Никогда не считал performance своей сильной стороной, а необходимость сталкиваться по работе с оптимизацией производительности стала возникать довольно часто. Вдобавок, на тот момент у меня были смешанные чувства по отношению к .NET Core. Хотелось узнать, что думают другие по этому поводу. Решающим фактором, конечно же, стало желание девушки съездить в Питер на пару деньков. Мы поехали и не пожалели:)

С Москвой все было сложнее – этот город я недолюбливаю примерно так-же, как зиму в России. Чашу весов на этот раз сдвинули доклады C++ через C#, Моя жизнь с актерами, Squeezing the Hardware to Make Performance Juice и присутствие на конференции сотрудника Stack Overflow. Каждый из них был интересен в практическом плане, так что поездка предстояла не увеселительная, а рабочая.

мои впечатления
Total votes 39: ↑36 and ↓3+33
Comments15

Information

Rating
Does not participate
Location
Казань, Татарстан, Россия
Works in
Date of birth
Registered
Activity