Nano Hash - криптовалюты, майнинг, программирование

Является ли вызов другого кода нарушением (SOLID) Принципов единой ответственности (SRP)?

Рассмотрим этот класс с бизнес-логикой:

public static class OrderShipper
{
    public static void ShipOrder(Order order) {
        AuthorizationHelper.AuthorizedUser();

        using (new PerformanceProfiler()) {
            OperationRetryHelper.HandleWithRetries(() => ShipOrderInTransaction(order));
        }
    }

    private static void ShipOrderInTransaction(Order order) {
        using (var transaction = new TransactionHelper()) {
            ShipOrderInternal(order);

            transaction.Commit();
        }            
    }

    private static void ShipOrderInternal(order) {
        // lots of business logic
    }
}

Класс содержит некоторую бизнес-логику, а также выполняет некоторые общие задачи. Хотя нет никаких сомнений в том, что этот класс нарушает принцип открытости / закрытости, нарушает ли этот класс принцип единой ответственности?

Я сомневаюсь, поскольку сам класс не отвечает за авторизацию пользователя, профилирование производительности и обработку транзакции.

Нет никаких сомнений в том, что это плохой дизайн, поскольку класс все еще (статически) зависит от этих пересекающихся проблем, но все же: нарушает ли он SRP. Если да, то почему?


  • Я бы сказал нет, если вы установите ответственность за доставку заказов. 10.04.2013

Ответы:


1

Хороший вопрос, заголовок немного вводит в заблуждение (маловероятно, что вы сможете создать приложение без «вызова другого кода»). Помните, что принципы SOLID - это скорее рекомендации, чем абсолютные правила, которым необходимо следовать; если вы доведете SRP до логического завершения, вы получите по одному методу на класс. Способ минимизировать влияние сквозных проблем - создать максимально простой в использовании фасад. В ваших примерах вы сделали это хорошо - каждая проблема пересечения использует только одну линию.

Другой способ добиться этого - использовать AOP, что возможно в C # с помощью PostSharp или через Перехват IoC

10.04.2013
  • И не забывайте, что вы можете добавить проблемы пересечения, используя старые добрые декораторы (например, показано в этой статье). 10.04.2013
  • MikeSW заявляет в своем ответе, что мой код действительно нарушает SRP. Что вы думаете об аргументах? 10.04.2013
  • Это зависит от того, как вы на это смотрите. Я думаю, что этот принцип можно зайти слишком далеко - на мой взгляд, вы не нарушили SRP, потому что фундаментальной причиной изменений в вашем классе является бизнес-логика отправки заказа. Остальные обязанности делегированы в другом месте. Единственное место, где я могу предложить улучшения здесь, - это использование фабрик для создания ваших объектов Profiler и Transaction - тогда вы привязаны только к интерфейсу для своих внешних зависимостей, и это нормально (предполагается, что интерфейсы не изменятся) 10.04.2013

  • 2

    Нет ничего плохого в том, что метод класса координирует действия некоторых других классов, не нарушая SRP. Вы нарушите его, если логика этих классов была частью OrderShipper.

    Я не уверен, что делает PerformanceProfiler, но это единственный компонент, который там выглядит странно.

    10.04.2013
  • MikeSW утверждает, что код фактически нарушает SRP. Что вы думаете о его заявлении? 10.04.2013

  • 3

    Сделаем его более заметным, преобразовав класс в команду:

    // Command pattern
    public class ShipOrder
    {
        ITransactionFactory _transactionFactory;
    
    
        public OrderShipper(ITransactionFactory factory)
        {
            if (factory == null) throw new ArgumentNullException("factory");
    
            _transactionFactory = factory;
        }
    
        [PrincipalPermission(Roles = "User")]
        public void Execute(Order order) 
        {
            if (order == null) throw new ArgumentNullException("order");
    
            using (new PerformanceProfiler()) 
            {
                HandleWithRetries(() => ShipOrderInTransaction(order));
            }
        }
    
        private void ShipOrderInTransaction(Order order) 
        {
            using (var transaction = _transactionFactory.Create()) 
            {
                ShipOrderInternal(order);
    
                transaction.Commit();
            }            
        }
    
        protected void ShipOrderInternal(order) 
        {
            // bussiness logic which is divided into different protected methods.
        }
    }
    

    Следовательно, вы можете вызвать его, используя:

    var cmd = new ShipOrder(transactionFactory);
    cmd.Execute(order);
    

    Это довольно солидно.

    10.04.2013
  • Вы не ответили на мой вопрос. Нарушает ли мой код SRP или нет? 10.04.2013
  • That's pretty solid был мой ответ. то есть да, ваш код надежен (ему просто нужна любовь). 10.04.2013
  • Я не понимаю, почему код OP SOLID. Ваше решение может напоминать, но для меня это явно другой подход, чем OP 10.04.2013
  • Я не знаю, что мой код ТВЕРДЫЙ. Это нарушает OCP, так как код необходимо изменять каждый раз, когда добавляется новая проблема пересечения. Но если я правильно понимаю, вы думаете, что это не нарушает SRP. 10.04.2013
  • ты прав. Мой код надежен, но OP - это просто SRP. OCP / LSP не очень хорошо работает со статическими классами. 10.04.2013
  • Кроме того, код OP также нарушает DIP, который также решает ваш код. 10.04.2013

  • 4

    Да, это нарушает SRP, по крайней мере, в соответствии с названием класса.

    сам класс не отвечает за авторизацию пользователя, профилирование производительности и обработку транзакции.

    Вы отвечаете сами, он должен содержать только логику доставки заказа. И он не должен быть статичным (почему он статичный ?!).

    Решение, предоставляемое @jgauffin, возможно, хотя я не совсем уверен, что OrderShipper должен знать о транзакции или должен быть только ее частью. Также профилировщик производительности IMO не имеет места в этом классе. Но имея только эту информацию, я не могу предложить решение. Однако профилирование - это комплексная проблема, и, возможно, лучше было бы обрабатывать его вне этого класса, возможно, с помощью атрибута.

    Кстати, используя подход, управляемый сообщениями (как предлагает jgauffin), он должен позволить инфраструктуре обеспечивать профилирование и поддержку надежности (HandleWithRetries)

    10.04.2013
  • В настоящее время вы единственный, кто заявляет, что мой код действительно нарушает SRP. Можете ли вы подкрепить это какими-нибудь доказательствами? Возможно, процитировав определение или другую ссылку? 10.04.2013
  • Lol, определение и ссылки ... Что этот класс должен делать? Отправлять заказы? Тогда это его ответственность. Если он занимается другими проблемами, помимо заказов на доставку, то на вас ложится более чем одна единственная ответственность. Например, этот класс никогда не должен обрабатывать авторизацию пользователя. О профилировании у меня недостаточно информации, но я уверен, что тот факт, что вы используете статический класс со статическими методами, имеет большое влияние. 10.04.2013
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..