Software Architect / Microsoft MVP (AI) and Technical Author

Architecture, C#, General Development, Process Improvement

Simplify your architecture using the Orchestrator Pattern

Introduction

In this blog post I want to cover a pattern I’ve used in applications that’s helped me organise and leverage legacy code in new software projects.  It’s called the Orchestrator.

So, what is the Orchestrator, why would you implement this pattern in a .NET web application and how is it done?

Why?

I’ll move onto discussing how I’ve implemented this in an ASP.NET web application but before I delve into the architecture and components that make up the stack, it’s worth mentioning WHY I’ve used it.

Legacy Code

If you’re like most developers, you’ll work on a variety of applications.  Some will be greenfield applications; others will be brownfield and may have accumulated a level of technical debt.

It’s not always commercially viable to rewrite an existing product in the latest and greatest tech stack but you can leverage tried and tested code by building wrappers.

legacyCode

This was one of the appeals and cases for implementing the orchestrator pattern.  I could leverage existing WCF services, logic buried in legacy dlls and expose multiple data sources via a handful of consolidated orchestrator classes.  It helped me shift code from legacy web form applications to new MVC solutions too.

Bloated Controllers

We’re supposed to keep controllers light in MVC but as you implement requirements and deal with change they can end up housing code which breaks this practice.

Existing logic layers may return DTOs but these must be converted to View Models for binding to the View.  You can implement extension methods or use AutoMapper to reduce the lines of code further but soon, with all this going on, the controller can start to get a little bloated.

Code like this can be housed within an orchestrator class and keeps the controller doing the task it was meant to do, i.e. route the incoming traffic from the http request, invoke business rules and return the appropriate response back to the client.

Architecture

The following diagram illustrates where the orchestrator sits within an ASP.NET web application.  I’ve split the diagram out into 3 high-level components that contain sub components that may exist in a typical web application.

OrchestratorOverview

UI / Entry

Here we have a regular controller which accepts input from the view. We may also have a REST endpoint that allow 3rd party systems to consume logic in our application or return some JSON.

Let’s assume that we will be observing best practice and using view models in the view which will be getting passed to the controller.

Orchestrator

This may seem like we’re adding another layer of indirection and you could argue that a controller is a type of orchestrator but controllers are too tightly coupled with the ASP.NET runtime (http context for example) to be purely focussed on data.

The orchestrator is freed up from the ASP.NET http runtime and deals solely data and objects.  Given this nature makes it easier to unit test.  We assume the orchestrator will always receive its data and can, therefore, write logical unit test against each orchestrator method and run assertions.

In terms of inputs, we assume the orchestrator deals with either primitive types or view models.

These are converted to DTOs either by implementing Extension Methods or by using AutoMapper.

I had originally started off using Extension Methods such as this:

public static PersonViewModel ToViewModel(this Person person)
        {
            PersonViewModel PersonViewModel = new PersonViewModel
            {
                PersonId = person.PersonId,
                Firstname = person.Firstname,
                Lastname = person.Lastname,
                DateOfBirth = person.DateOfBirth,
                Middlename = person.Middlename,
                Title = person.Title,
                Active = person.Active
            };
            return PersonViewModel;
        }


public static Person ToDomainModel(this PersonViewModel personViewModel)
        {
            Person person = new Person();
            person.PersonId = personViewModel.PersonId;
            person.Firstname = personViewModel.Firstname;
            person.Lastname = personViewModel.Lastname;
            person.DateOfBirth = personViewModel.DateOfBirth;
            person.Middlename = personViewModel.Middlename;
            person.Title = personViewModel.Title;
            person.Active = personViewModel.Active;
            return person;
        }

I soon got tired of writing code like this as so opted for Auto Mapper in the end.

Encapsulation

Whenever I’m architecting an application I always try to build APIS to encapsulate functionality that I think has the potential to be reused.

For example on one project I built an API that sat behind a WCF Service.  The solution itself was service oriented in its architecture.  A requirement was introduced years later whereby the client asked me to build a Windows Service that would perform the same calculations and write the output to a staging table for reporting purposes.

This was trivial as the existing API could be extended and invoked directly from the Windows Service.

The orchestrator is similar in this respect as it groups logical components under one “umbrella” to achieve a use case.  It may need to call an external web service, call MSMQ or invoke a method on a proprietary dll.  It doesn’t matter, and the client invoking the orchestrator method doesn’t care providing the view model and/or respected response is returned.

logic

In most cases for a .NET web application that outcome being the return of a view model or the updating of a record in a backend system.

What kind of code lives in the Orchestrator?

It depends on your use cases.  It might just be regular line of business crud operations or calls to multiple logic layer classes in your solution that return many DTOs that get flattened into one view model.

Imagine we are selecting a person record in our contact management application to display further details for edit.

The controller method is simple and invokes a call to its respective orchestrator.  The following code snippets show sample code that might live in such an orchestrator.  The controller call has been included for completeness:

public ActionResult Edit(int id)
{
    var personViewModel = _personOrchestrator.GetPerson(id);
    return View(personViewModel);
}

The orchestrator method takes the id, makes a call to a specific logic layer class, converts the DTO to a view model, applies some checks and then return a fully populated view model to be sent back to the view.

public PersonViewModel GetPerson (int id)
{
        var personDTO = _personLogicLayer.LoadPerson(id);
    	PersonViewModel pvm = new PersonViewModel();
        …apply a conversion from the DTO to ViewModel
        …make call to another dll to determine if record can be updated                            
        …the viewmodel to be returned
        …return the personViewModel
        return pvm;
}

Data Access

Not too much to mention here as this will be your standard RDMS / NoSQL.  It’s abstracted by the logic layer.  The orchestrator class therefore doesn’t need to know where the data lives or which kind of data store is involved.  All that’s required is the database operation is executed successfully and any input or output is bubbled back up the stack for the orchestrator to deal with accordingly.

Summary

This pattern has helped me layer an application into logical components as well as leverage (tested) legacy code which saved development time.

The orchestrator is the first place I look when debugging logic errors as it’s responsible for the coordination of code and its execution.

It’s a simple enough pattern to understand and providing everyone follows it, is easy for developers to roll on/off a code base.

I hope this article has helped you understand the pattern and how I could leverage it and what I’ve found its benefits to be.

As often is the case, there’s always room for improvement.  If you have any comments or suggestions, then drop them in the comments box below.  Keen to hear your thoughts.

 

 

JOIN MY EXCLUSIVE EMAIL LIST
Get the latest content and code from the blog posts!
I respect your privacy. No spam. Ever.

5 Comments

  1. With:
    “This may seem like we’re adding another later of indirection and you could argue”

    you mean:

    “This may seem like we’re adding another laYer of indirection and you could argue”

  2. David

    With:
    “I hope this article has help you understand the pattern and how I’ve could leverage it and what I’ve found it’s benefits to be.”

    you mean:

    “I hope this article has helped you understand the pattern and how I could leverage it and what I’ve found its benefits to be.”

  3. George

    This sounds like the classic Service Layer pattern, isn’t?

Leave a Reply