Architectural Guidance
*A one-size-fits-all architecture is never optimal as there are many ways to skin the proverbial cat.
This guide describes types of systems based on their particular "special requirements", and then types of architectures and technologies to consider using when designing the solution for those systems.
NML Preferred Technology Stack
Development Languages
- C# 7+
- Typescript 3+
- TSQL
- HTML5 / JSX
- CSS 2+
UX
- HTML5
- SASS
- React (Hooks)
Motivation:
Existing NML skillset. Good available tooling in NML IDEs. Component nature of React allows for UX composition, which makes design and implementation easier.- Redux
- Redux Saga
Motivation:
Simplified implementation for handling asynchronous side-effects
- redux-thunk
Motivation:
Best known implemantation for handling asychronous side effects
- React RxJS
Motivation:
Powerful but complicated implementation for handling asynchronous side effects
- Redux Saga
- Final Form
Motivation:
Easier form state and validation management for react forms.
- Webpack
Motivation:
The most popular JavaScript bundler that therefore also has the most online help available
- ASP.Net Core MVC / ASP.Net Core SPA
Web Server
Transactional Applications
- ASP.Net 5+
Motivation:
Microsoft stack aligns with NML technologies. Well established and stable platform- If .Net 5 cannot be used: ASP.Net Core 3.1 or ASP.Net Framework 4.6.1+
- MVC 5+
- Razor Views if React is not used
- Web API for REST API implementations
Caching
- Azure Redis Cache
Motivation:
Redis cache is an industry leading caching implementation and available as SaaS on Azure.
Static Sites
CMS
- Netlify CMS
Motivation:
Simple and easy to get started, although it's ruby/jenkins based and does not easily integrate with other NML technology stack items
- Piranna CMS
Motivation:
Well supported open source headless CMS that can be used as a service but also integrated directly with ASP.Net Core MVC.
Back-ends
Data
- Azure SQL / MS SQL Server
Motivation:
Aligns with the NML technology stack and is available as SaaS on Azure.
- Cosmos DB
Motivation:
Flexible document DB availble as SaaS on Azure.
- Entity Framework Core / Entity Framework
Motivation:
Widely accepted and Microsoft support ORM that support SQL Server and CosmosDB. Allows for code-first database design and has schema migrations and data seeding.
Messaging
- Azure ServiceBus
Motivation:
Fast, flexible reliable messaging platform that supports Queues and Topics for various messaging patterns, like pub/sub. Available as SaaS on Azure
- Azure Storage Queues
- RabbitMQ / CloudAMQP
Motivation:
Fast flexible reliable messaging platform that support various messaging patterns, like pub/sub. Availble as SaaS on CloudAMQP.
- NServiceBus
Motivation:
Messaging patterns abstraction that enforces best practice asynchronous messaging architectures. Available as a licenced NuGet package.
Processing
- Azure Logic Apps
Motivation:
Flexible control flow with integration connectors to many systems. Visual designer for developing flows. SaaS on Azure.
- Azure Functions
Motivation:
Serverless execution that is easily scaled and support various triggering mechanisms, like schedules or REST calls.
- Azure API Manager / Azure Front-door
Motivation:
API consolidation and standardization from disparate sources.
- Azure Traffic Manager
- Helps with load balancing and/or fail-over configurations
- Windows Services on VMs
General Preferred Dependencies
NPM
- react-redux
- redux-saga / redux-thunk / React RxJS
- Final Form
- miragejs
Motivation:
Browser based mock REST service for unit testing or local environments.
- date-fns
Motivation:
Various date related functions that make working with dates in JavaScript/Typescript much easier.
NUGET
General
- Autofac for Dependency Injection
Motivation:
Eases object lifetime management and allows for more flexible code.
- Automapper for model mapping
Motivation:
Allows for clean model separation between architectural boundaries.
Unit testing
- NUnit
Motivation:
NUnit is the community standard on unit testing in .Net.
- Fake Data Generation
- AutoBogus & Bogus
Motivation:
It is an anti-pattern to hard-code test data of any sort as it can lead the passing unit tests because of developer bias.
- AutoFixture
Motivation:
It is an anti-pattern to hard-code test data of any sort as it can lead the passing unit tests because of developer bias.
- AutoBogus & Bogus
- Fluent Assertions
Motivation:
Allows for more readable test assertions.
Technologies to avoid and replace
- .Net Core 2.1, 2.2, 3.1
- .Net Framework 4.8<
- Unity dependency injection
- jQuery
- React alternatives (Vue.js, Preact.js, Angular)
- JavaScript (over Typescript)
Motivation:
Typescript produces code that is less likely to produce runtime errors.
Architectural guidance
Complex business rules
Requirement: Application with complicated business rules, especially business rules that may change often.
Consider using DDD architecture.
- Review The Onion Architecture by Jeffrey Palermo.
- Work through this informative 6-part series on a practical DDD implementation in .NET.
Event stream processing
Requirement: the system needs to take action based on a large number of inter-related events. For example, thousands of "person location update" events need to be processed in order to determine if two "friends" are close to one another.
- Consider using Azure Event Hubs.
Workflow with user-interaction
Requirement: the system has complicated workflows that include user interaction, for example: "Loan" message arrives at service, service calls another service to do a credit check, then a person has to review the request and "approve" or "deny" it.
- Consider Azure Logic Apps and Functions, Power Automate
- Unsure. Is there any good workflow technology out there?
- Nasty option nr 1: BizTalk orchestrations
- Nasty option nr 2: K2
- Workflow Foundation with custom code to handle user interaction.
- Custom implementation from scratch.
High load website
Requirement: public-facing website must be able to handle thousands of requests per minute. Data does not change frequently (i.e. a news site).
Remember, accessing data from the database or from a web service is slow. Often implementing these strategies make a big difference:
- Azure Web App with a scaled App Service Plan and increased number of instances.
- Azure Redis Cache
- In memory caching
- Azure Traffic Manager configured for load, with multiple Azure WebApps
Reliable messaging
Requirement: the system must accept messages and return messages in a reliable way, ensuring no messages get lost, and ensuring that the system can endure temporary internet outages.
- Consider using Azure Service Bus Queues (more feature-rich) or Azure Storage Queues (faster and simpler, but less features).
- Use NServiceBus to get auto-retries, error queue monitoring and much more useful reliability, maintenance and monitoring features.
- On VMs, consider using message queues instead of calling web services directly (the simplest kind is MSMQ built into Windows).
High availability
Requirement: Application must always be online.
- Consider hosting in Azure (i.e. Azure Web Apps), but keep in mind that even Azure only has a 99.9% uptime guarantee, meaning as much as 40 minutes downtime per month.
- Leverage Azure Traffic Manager configured for fail-over across multiple Azure Web Apps.
- Use a load-balanced architecture with multiple servers, when one goes down, the other servers can pick up the slack. This requires a load balancer or use of the Azure Traffic Manager.
- Have a hot-standby server ready to switch over to in-case the main server is unavailable. This can be triggered by an automated DNS switch-over.
- Geo-replication: replicate the system to more than one physical location, and use DNS fail-over to switch to another location if the primary location becomes unavailable.
Strict security requirements
Requirement: Application is used in a Banking environment, and as such must be very secure.
- Use HTTPS for all communications, do not allow HTTP.
- Protect against cross-site forgery (XSRF) by using a XSRF-token on all HTML Forms.
- Get a security audit from a company like Sensepost. They test software for vulnerabilities.
- Do not allow common passwords (i.e. anything that contains the word "Password"). Check against a list like the following: 500 most common passwords.
- Ensure authentication and authorization is done on all REST endpoints. This can be easy to overlook.
Very simple requirements
Requirement: Application is very simple, minimal business logic, mostly saving/loading of simple entities.
In this case, simpler architectures can be used to save time, but beware that these architectures generally don't "scale" well when the system gets more complex, so make extra sure that the system probably won't get more complicated in future.
- Consider using a micro ORM, like Dapper or PetaPoco.
- Consider using Active Record instead of a full-featured ORM.
- For smaller projects, consider the NML repository pattern.
Cross-platform app
Requirement: Application must be available on many platforms including, i.e. Mac, PC, Android, iPhone and Windows Phone devices.
- First choice is Progressive Web Apps.
- Consider a technology like Ionic (cross platform ReactJS + Typescript)
- Refer the client to an NML partner for native mobile application development.