Do you want an easy way to boost productivity on your .NET projects in minutes? Applinate!

Use five Applinate conventions to achieve breakthrough results in ten minutes or less

Do you want an easy way to boost productivity on your .NET projects in minutes? Applinate!

Do you want an easy way to boost productivity on your .NET projects in minutes? Applinate!

Use five Applinate conventions to achieve breakthrough results in ten minutes or less

Introduction

Learn how five Applinate conventions help you achieve breakthrough results in ten minutes or less.

Do you want to get a jump start on creating enterprise-class .NET applications right away?

Get your hands on Applinate, a complete and robust.NET development framework that can reduce your workload by up to 80%.

Want to know how?

Applinate takes care of the plumbing code, so you can focus on delivering high-value features to your customers faster.

You’ll have more faith in your code because it will contain fewer bugs. You’ll add more features faster. And with Applinate’s conventions, you’ll spend less time figuring out infrastructure and more time writing your business code.

Try it today atapplinate.com. Building top-quality software has never been more straightforward.

Want the details in ten minutes?

Let’s get started!

Why Applinate?

“If our designs are failing due to the constant rain of changing requirements, it is our designs that are at fault. We must somehow find a way to make our designs resilient to such changes and protect them from rotting.” – Robert C. Martin

Applinate is an method-informed open-source framework that helps your teams follow best practices in service-oriented architecture (SOA) system design. It is also made to speed up development, streamline future change, and give you a tool belt full of resources to help you succeed.

  • Boost development efficiencies with complete separation of your business and plumbing code, which means you can develop higher quality features faster with more confidence in your code.
  • The Applinate conventions are designed to help you write cleaner code with a clear separation of concerns. This means your code will be easier to understand, which means you’ll spend more time building value and less time debugging.
  • Bypass 80% of what you usually have to build if starting from scratch. You’ll save time and money while building fast, scalable, and secure applications.
  • Optimal development experience while harnessing the power of microservices. This means you’ll be able to focus on building features that matter instead of spending time writing boilerplate infrastructure code and dealing with the overhead of managing microservices.
  • Conventionalized guidelines to keep your code SOLID. This means you’ll be able to develop and easily maintain, modify, and extend applications over time while quickly automating tests to verify each module and integration in your code works as expected. This means you’ll be able to maintain confidence in the quality of your software releases while reducing testing overhead.
  • A modular, pluggable, and loosely coupled foundation means you won’t get locked into past decisions and can easily replace parts of your system in the future. This means you’ll easily integrate new technologies and keep up with the latest trends in software development by using simple and intuitive conventions that are easy to learn and understand.

Applinate’s five core conventions

Let’s take a quick tour of the core Applinate conventions over the next few minutes, giving you a tremendous productivity boost with a minimal learning curve.

The following are the five core Applinate conventions for accelerating.NET development.

1. Assembly naming conventions

“If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it.”– Richard Pattis

In Applinate, the convention is to use assemblies to model different services.

Applinate keeps it simple. There are only three types of assemblies for your business logic in the Applinate taxonomy.

Protect your code base from fragility by installing shock absorbers around things that change at different rates.

Any good design promotes a supple code base, making future changes easier. Applinate helps keep orchestration, calculation, and integration concerns separate because these aspects almost always change at different rates.

Use Applinate to encapsulate.

Orchestrator service assemblies encapsulate workflow, which is the vast majority of most systems, so they’ll house most of your code. They coordinate all other application services to meet a use case.

Calculator service assemblies are responsible for encapsulating reusable domain-specific calculations so that changes don’t blow up and damage your orchestrations.

Integrator service assemblies are responsible for encapsulating all outside system consumption. They help ensure database refactoring or external service surface changes don’t blow up through your calculator or orchestrator code.

Conventions

All of your assemblies must be named starting with your company name, followed by ‘orchestrate’, ‘calculate’ or ‘integrate’ followed by the business aspect.

Template:


[Company Name].Orchestrate.[Aspect]

Example:


Acme.Orchestrate.Accounts

The important thing to keep in mind is that Applinate looks for “.orchestrate.”, “.calculate.”, or “.integrate.” when initializing to wire up integrations automatically.

Why?

Using conventions, Applinate automatically wires up all implementations by analyzing assemblies following this convention.

2. Message Conventions

“Conceptual integrity is the most important consideration in system design.”–Fred Brooks, “The Mythical Man-Month”

Applinate follows a message-based design paradigm for calling your orchestrations.

All communications in Applinate are a simple request-response pair defined as follows:

  • A request class
    • a ServiceRequest attribute
    • implements IReturn<T> with the return type
    • optional payload for all request parameters
  • A response class
    • Implements IHaveResponseStatus
    • optional payload for all response state

Example:


/// REQUEST /////////////////////////////////////
[ServiceRequest(ServiceType.Orchestration)]
public sealed class MyRequest:IReturn<MyResponse>
{
    public MyRequest(int requestPayload)
    {
        RequestPayload = requestPayload;
    }

    public int RequestPayload { get; }
}

/// RESPONSE /////////////////////////////////////
public sealed class MyResponse : IHaveResponseStatus
{
    public MyResponse(ResponseStatus status, int responsePayload)
    {
        Status = status;
        ResponsePayload = responsePayload
    }

    public ResponseStatus Status { get; }
    public int ResponsePayload { get; }
}

Why?

A request-based paradigm makes separating commands from queries simple, giving you a clean foundation for a CQRS (Command Query Responsibility Segregation) implementation.

In CQRS, commands and queries have different fundamental run-time behavior: Commands update the state of a system asynchronously, while queries read data synchronously.

  • Applinate queries follow the more traditional RPC (remote procedure call) request-response interaction, where you wait for the query results. On the other hand, commands follow an event notification communication style or fire-and-forget.
  • Applinate commands are a special type of request because we don’t wait for a response but instead just wait for an ACK (acknowledgment) that the command has successfully dispatched.

Therefore, Applinate provides an even simpler command syntax.

Example


/// COMMAND /////////////////////////////////////
[ServiceRequest(ServiceType.Orchestration)]
public sealed class MyCommmand:ICommand
{
    public MyCommmand(int payload)
    {
        Payload = payload;
    }

    public int Payload { get; }
}

Applinate uses CQRS when calling your orchestrations. But once a request gets to an orchestrator, the orchestration process should not use events to implement the workflow because it would make things too complicated.

Instead, orchestration services just use a standard request-response RPC pattern to provide workflow logic and coordinate the other services.

3. Implementation conventions

“The hardest part of design … is keeping features out.” –Donald Norman

With Applinate, you have an architecture and plumbing code completely isolated from business logic and features. Features are encapsulated in orchestration services.

In addition, Applinate helps you follow SOLID design principles.

For example, to follow the DIP (Dependency Inversion Principle), Applinate allows you to separate interface and implementation concerns completely. The recommendation is to create a separate ‘abstractions’ assembly to hold your messages and service definitions. Then, you create a separate implementation assembly where EVERY class is internal. This makes it impossible for leaky abstractions to decay your code base.

“Depend on abstractions, not on concretions” - Dependency Inversion Principle - Robert Martin

With Applinate, you have two options to implement your request-response message pair.

Option 1. Implement an individual request.


internal sealed class MyHandler : 
    IRequestHandler<MyRequest, MyResponse>
{
    public Task<MyResponse> ExecuteAsync(
        MyRequest arg, 
        CancellationToken cancellationToken = default)
    {
        var response = new MyResponse(
          ResponseStatus.Success, 
          arg.Arg1 + arg.Arg2);

        return Task.FromResult(response);
    }
}

Option 2. Use an interface to organize your service code.


internal sealed class MyOrchestrationService : IMyOrchestrationService
{
    public Task<MyResponse> ExecuteMyRequestAsync(
      MyRequest request, 
      CancellationToken cancellationToken)
    {
        var response = new MyResponse(
          ResponseStatus.Success, 
          request.Arg1 + request.Arg2);

        return Task.FromResult(response);
    }
}

In addition, you have two calling conventions

Option 1. Execute a request.


var request = new MyRequest(1);
var response = await request.ExecuteAsync();

Option 2. Use an interface to organize your service code.


var request = new MyRequest(1);
var service = ServiceProvider.Locate<IMyOrchestrationService>();
var response = await service.ExecuteMyRequestAsync(request, CancellationToken.None);

4. Initialization conventions (bootstrapping)

“If you think good architecture is expensive, try bad architecture.”– Brian Foote and Joseph Yoder

One of Applinate’s strengths is a highly modular architecture. You just drop implementation assemblies in a folder, and you can change the behavior of your system.

However, this does come with a caveat because modules often have to be initialized.

Applinate provides a simple initialization structure. When starting your application, you have to call the following code to bootstrap your Applinate service assembles:


Applinate.InitializationProvider.Initialize();

If you need something initialized in an assembly (like data seeding, initialization notifications, IOC registration, etc), you just have to implement the Initialize interface. When you call InitializationProvider.Initialize() on application start, every implementation of IInitialize.Initialize() is called.

Contract:


public interface IInitialize
{
    bool SkipDuringTesting { get; }
    void Initialize(bool testing = false);
}

Example:


internal class Factory:IInitialize
{
    public bool SkipDuringTesting => false;

    [STAThread]
    public void Initialize(bool testing = false)
    {
        // ... bootstrap this assembly 
    }
}

Why?

Having a hook for assemblies to prepare themselves for execution and bootstrap state provides a powerful mechanism to modify your applications behavior just by dropping in an assembly that follows a convention because you avoid coupling that happens with other alternatives.

“software entities should be open for extension, but closed for modification” - Open-Closed Principle - Robert Martin

5. Interception conventions

“A good design is easier to change than a bad design”–Dave Thomas

The decorator pattern is a powerful way to extend a program that gives you much more freedom than static inheritance. It simplifies coding by allowing you to add behavior by adding new classes, rather than coding all the behavior into one object.

Applinate gives you two valuable decoration mechanisms.

Extending the behavior of a single orchestration request-response.


internal sealed class MyInterceptor 
    : RequestInterceptorBase<MyRequest, MyResponse>
{
    public MyHandlerInterceptor(
      ExecuteDelegate<MyRequest, MyResponse> core) 
      : base(core)
    {
    }

    protected override Task<MyRequest> PreProcessAsync(
      MyRequest request)
    {
        Console.WriteLine("modifying the request");

        var modifiedRequest = new MyRequest(request.Arg + 1);

        return base.PreProcessAsync(modifiedRequest);
    }

    protected override Task<MyResponse> PostProcessAsync(
      MyResponse response)
    {
        Console.WriteLine("modifying the response");

        var modifiedResponse = new MyResponse(response.Status, response.Value + 1);

        return base.PostProcessAsync(modifiedResponse);
    }
}

Extending the behavior of EVERY orchestration request-response.


internal sealed class MyMessageInterceptorFactory
    : InterceptorFactoryBase
{
    public override async Task<TResult> ExecuteAsync<TArg, TResult>(
      ExecuteDelegate<TArg, TResult> next, TArg arg, 
      CancellationToken cancellationToken)
    {
        Console.WriteLine($"intercepted a {typeof(TArg)} message");

        Console.WriteLine("pre-execution processing");

        var result = await next(arg, cancellationToken);

        Console.WriteLine("post execution processing");

        return result;
    }
}

Why?

This is the primary extensibility point of applinate. It allows for easily changing core behavior without touching your business code, aloowing you to make your code base rot-resistant.

For example: We’ll soon release a pub-sub extension you can drop in that will change the dispatch behavior from executing on a local thread to making a service call. This way you get all be benefits of efficient local development plus without the drawbacks of build a highly distributed and scalable microservice system. And you get all this without having to write a single line of code.

Not only that, using Applinate’s initialization and decoration patterns frees to update any aspect you want by writing your own implementations and swapping them out at any time without touching your business logic!

In conclusion

“How good the design is doesn’t matter near as much as whether the design is getting better or worse. If it is getting better, day by day, I can live with it forever. If it is getting worse, I will die.”– Kent Beck

  • Looking for a simple solution to boost.NET project productivity?
  • Want to start building enterprise-class.NET apps right away?
  • Want to avoid writing infrastructure code from scratch on every project?

Try Applinate, a complete and robust open-source .NET development framework. In the last ten minutes, we’ve covered how five Applinate conventions can help you reach breakthrough achievements.

Applinate handles plumbing code, so you can focus on providing customer-value features faster with fewer problems through road-tested architectural patterns for free.

Building great software has never been faster or easier.

Best wishes and warm regards –Matt


applinate.com | source | github c# demos | wiki | NuGet

LET'S WORK TOGETHER