CQRS und Microservices in der Produktentwicklung

Wie man ein Produkt entwirft, um kein Geld in den Boden zu stecken


In welchem ​​Stadium der Erstellung eines Produkts oder Systems, um das architektonische Design des Systems so zu verbinden, dass es für das ausgegebene Geld nicht unerträglich schmerzhaft ist? So entscheiden Sie, ob CQRS und Microservices kombiniert werden sollen.


Dieser Artikel richtet sich an Unternehmensvertreter, die die Entwicklung einer IT-Lösung anfordern. Wir zeigen Ihnen, wie Sie ein Produkt auf den Markt bringen und ungerechtfertigte Kosten im Zusammenhang mit der Architektur vermeiden. Und sehen Sie auch, wie die Verwendung von CQRS bei der Implementierung von Funktionen in verschiedenen Anwendungsclients hilft und ob Microservices das Allheilmittel sind.


Kurz ĂĽber CQRS


CQRS (Command-Query Responsibility Segregation) - eine Vorlage, die bei der Entwicklung von Systemen verwendet wird und angibt, dass jede Methode des Systems entweder eine Anforderung (ohne Änderung des Systemstatus) oder ein Befehl (Änderung des Systemstatus) sein kann. Wie die Praxis zeigt, ist dies eines der am häufigsten verwendeten Muster in der Softwareentwicklung. Es kann auf verschiedenen Ebenen und in verschiedenen Situationen eingesetzt werden. Beispielsweise ist die klassische Unterteilung von Systemen in OLTP / OLAP, wenn Daten häufig in das OLTP-System geschrieben und aus dem OLAP-System gelesen werden, nichts anderes als die Verwendung der CQRS-Vorlage in der Datenbankarchitektur.



“” ( 2000 ) CQRS. , Interbase/FirebirdSQL . . , , Query-, CRM- Command. CQRS JS . , JS … , , .



: A Big Ball of Mud



. , MVP , . , . — , . , . , .


, . , . , . .


: “ . , ”. , , , . “ ” . . . - , .



. , , . , . .


. , , . , . (Elastic ), - . , , - . , .


, , , . , - , - , . , . , , , .. 1 . - . , .


, , , , , . , . — . , , CAP-. , , .



—


/ . : , . .


/ , . . , , , .



, -, , , , . , -, (.. -), , , - .


, , . (.. ), , CRM- , . , , ..


?


- , , low-fidelity . Business Canvas ( ) , . , : -, . , . , . — ? : 2 . , , .


, . - - . , . , , (, COVID-19 !). CQRS .



- . CQRS .


:



, SOLID, Dependency Inversion Dependency Injection, , . , .


3 , :


  1. (Admin office Desktop App)
  2. (Ship Desktop Mechanic app)
  3. (SyncService)

, , , , . , Offline- , , . ? , , , . , — . - .


,


C#, .


/// <summary>
///       .
///       Composition Root(web api ,     ..)
/// </summary>
    public interface IHandlersFactory
    {
        IQueryHandler<TQuery, TResult> CreateQueryHandler<TQuery, TResult>();

        IAsyncQueryHandler<TQuery, TResult> CreateAsyncQueryHandler<TQuery, TResult>();

        ICommandHandler<TCommand> CreateCommandHandler<TCommand>();

        IAsyncCommandHandler<TCommand> CreateAsyncCommandHandler<TCommand>();
    }
/// <summary>
///       
/// </summary>
 public interface ICommandHandler<TCommand>
    {
        void Execute(TCommand command);
    }
/// <summary>
///       
/// </summary>

public interface IQueryHandler<TQuery, TResult>
    {
        TResult Execute(TQuery query);
    }

/// <summary>
///     Ninject,     
/// </summary>
public class NinjectFactory : IHandlersFactory
    {
        private readonly IResolutionRoot _resolutionRoot;

        public NinjectFactory(IResolutionRoot resolutionRoot)
        {
            _resolutionRoot = resolutionRoot;
        }

        public IAsyncCommandHandler<TCommand> CreateAsyncCommandHandler<TCommand>()
        {
            return _resolutionRoot.Get<IAsyncCommandHandler<TCommand>>();
        }

        public IAsyncQueryHandler<TQuery, TResult> CreateAsyncQueryHandler<TQuery, TResult>()
        {
            return _resolutionRoot.Get<IAsyncQueryHandler<TQuery, TResult>>();
        }

        public ICommandHandler<TCommand> CreateCommandHandler<TCommand>()
        {
            return _resolutionRoot.Get<ICommandHandler<TCommand>>();
        }

        public IQueryHandler<TQuery, TResult> CreateQueryHandler<TQuery, TResult>()
        {
            return _resolutionRoot.Get<IQueryHandler<TQuery, TResult>>();
        }
    }

Ninject


public override void Load()
        {
            // queries
            Bind<IQueryHandler<GetCertificateByIdQuery, Certificate>>().To<GetCertificateByIdQueryHandler>();
            Bind<IQueryHandler<GetCertificatesQuery, List<Certificate>>>().To<GetCertificatesQueryHandler>();
            Bind<IQueryHandler<GetCertificateByShipQuery, List<Certificate>>>().To<GetCertificateByShipQueryHandler>();
…………
}

IHandlerFactory :


:


Ship ship = mHandlersFactory.CreateQueryHandler<GetShipByIdQuery, Ship>().Execute(new GetShipByIdQuery(id));

:


mHandlersFactory.CreateCommandHandler<DeleteReportCommand>()
                    .Execute(new DeleteReportCommand(report));

, :


  1. , , .
  2. , , .
  3. , . /, . .
  4. , !

. . 300 . , 3 :


  1. - ? ?
  2. , ?
  3. ?

Bounded Context . , . .


CQRS


: MVVM, SOLID, CQRS .. . , .


, . : . , .



Agile- “ , , — ”. , — . , — . , , .


, . . -, . -, , . -, . , , .


All Articles