How SOA and DDD Combine to Build Robust Backend Systems
This article explores the definitions of SOA and DDD, explains DDD's layered architecture, demonstrates how business relationships become domain models, and provides concrete C# examples of repositories, services, and factories to illustrate the integration of service‑oriented architecture with domain‑driven design.
Introduction
This article draws on Martin Fowler's "Patterns of Enterprise Application Architecture" and Eric Evans' "Domain‑Driven Design", combined with the author’s practical experience developing SOA systems, to discuss the relationship between SOA and DDD. The focus is on the application layer and overall system architecture.
1. Definition of SOA and DDD
SOA (Service‑Oriented Architecture), proposed by Gartner in 1996, is a distributed software architecture that enables loosely‑coupled, coarse‑grained services to be deployed, composed, and used over a network, facilitating data exchange across multiple cores and platforms.
DDD (Domain‑Driven Design), introduced by Eric Evans in 2004, concentrates on mapping business domain concepts to software, emphasizing the power of a domain model to represent complex business processes.
SOA addresses the overall architecture of large systems, while DDD focuses on the development process of a single project; they are complementary rather than conflicting.
2. DDD Layered Structure
DDD typically consists of four conceptual layers: Infrastructure, Domain, Application, and Presentation.
Infrastructure layer provides technical capabilities such as persistence (Hibernate, LINQ, ADO.NET) and messaging.
Domain layer contains the core business logic and domain model, isolated from infrastructure changes.
Application layer coordinates the domain and presentation layers, acting as a bridge without containing business logic.
Presentation layer handles user interfaces (web pages, windows) and may expose web services, which in SOA are often placed in the application layer.
Example: an order‑management scenario illustrates how entities, value objects, and services are modeled.
3. Transforming Business Relationships into Domain Models
The core of DDD is Model‑Driven Design, which converts complex relationships into three model types: Entity, Value Object, and Service.
Entity : Has identity and lifecycle; its state can change based on events (e.g., Order entity affected by Person points and OrderItem prices).
Value Object : Immutable data without identity, usually embedded within an entity.
Service : Encapsulates operations that involve multiple entities; services exist in various layers (infrastructure, domain, application) and may be implemented as Web Services, sockets, or message queues.
4. Repository Details
A Repository abstracts persistence, allowing the application to remain independent of specific databases or ORM tools. It manages the lifecycle of root objects such as Person and Order.
Example code shows C# interfaces and implementations for IOrderRepository and IPersonRepository, including methods for CRUD operations and explicit loading of related entities.
namespace Business.DomainModel
{
public interface Root { }
public partial class Order : Root
{
private Guid _guid;
public Order() { _guid = System.Guid.NewGuid(); }
public Guid GUID => _guid;
}
public partial class Person : Root
{
private Guid _guid;
public Person() { _guid = System.Guid.NewGuid(); }
public Guid GUID => _guid;
}
} namespace Business.IRepository
{
public interface IOrderRepository
{
Order GetOrder(int id);
IList GetList();
IList GetListByPerson(int personID);
int AddOrder(Order order);
int DeleteOrder(int id);
int UpdateOrder(Order order);
int AddOrderItem(OrderItem orderItem);
int DeleteOrderItem(int id);
}
public interface IPersonRepository
{
int AddPerson(Person person);
int AttachPerson(Person person);
int UpdatePerson(Person person);
Person GetPerson(int id);
IList GetList();
}
}
namespace Business.Repository
{
public class OrderRepository : IOrderRepository
{
// Example of GetOrder with explicit loading of OrderItem
public Order GetOrder(int id)
{
BusinessContext _context = new BusinessContext();
Order order = null;
using (TransactionScope scope = new TransactionScope())
{
var list = _context.Order.Include("OrderItem")
.Where(x => x.ID == id);
order = list.FirstOrDefault() ?? new Order();
scope.Complete();
}
_context.Dispose();
return order;
}
// UpdateOrder demonstrates deleting existing OrderItems then re‑inserting
public int UpdateOrder(Order order)
{
int returnValue = -1;
BusinessContext _context = new BusinessContext();
using (TransactionScope scope = new TransactionScope())
{
var list = _context.Order.Include("OrderItem")
.Where(x => x.ID == order.ID);
if (list.Any())
{
Order _order = list.First();
// Update scalar properties
_order.Count = order.Count;
_order.Delivery = order.Delivery;
_order.Favorable = order.Favorable;
_order.Freightage = order.Freightage;
_order.OrderNumber = order.OrderNumber;
_order.PersonID = order.PersonID;
_order.Price = order.Price;
_order.TotalPrice = order.TotalPrice;
// Remove old OrderItems
foreach (var item in _order.OrderItem)
DeleteOrderItem(item.ID);
// Add new OrderItems
foreach (var item in order.OrderItem)
{
var _orderItem = new OrderItem();
_orderItem.Count = item.Count;
_orderItem.Goods = item.Goods;
_orderItem.OrderID = item.OrderID;
_orderItem.Price = item.Price;
AddOrderItem(_orderItem);
}
returnValue = _context.SaveChanges();
}
else
{
returnValue = 0;
}
scope.Complete();
}
_context.Dispose();
return returnValue;
}
// AddOrderItem, DeleteOrderItem omitted for brevity
}
}5. Domain Layer Services
Domain services encapsulate business logic that does not naturally belong to a single entity. In the order example, a service calculates total price, discounts, and freight based on product count, price, and customer points.
namespace Business.Service.DomainService
{
public class AccountManager
{
private Person _person;
private Order _order;
public AccountManager(Person person, Order order)
{
_person = person;
_order = order;
}
public void Account()
{
GoodsCount();
PriceAccount();
FavorableAccount();
double price1 = (_order.Price - _order.Favorable).Value;
FreightageAccount(price1);
_order.TotalPrice = price1 + _order.Freightage.Value;
}
private void GoodsCount()
{
_order.Count = 0;
foreach (var item in _order.OrderItem)
_order.Count += item.Count;
}
private void PriceAccount()
{
_order.Price = 0;
foreach (var item in _order.OrderItem)
_order.Price += item.Price * item.Count;
}
private void FavorableAccount()
{
int point = (int)_person.Point.GetInt();
if (point < 1000) _order.Favorable = _order.Price * 0.1;
else if (point < 2000) _order.Favorable = _order.Price * 0.2;
else _order.Favorable = _order.Price * 0.3;
}
private void FreightageAccount(double price)
{
_order.Freightage = price >= 98 ? 0 : 10;
}
}
}A separate PaymentManager service handles order finalization, generating an order number, setting the delivery date, and updating customer points.
namespace Business.Service.DomainService
{
public class PaymentManager
{
public void Payment(Order order, Person person)
{
order.OrderNumber = Guid.NewGuid().ToString();
order.Delivery = DateTime.Now;
if (person.Point.HasValue)
person.Point += (int)order.TotalPrice.GetValueOrDefault();
else
person.Point = (int)order.TotalPrice.GetValueOrDefault();
}
}
}Conclusion
Combining SOA with DDD allows developers to leverage the strengths of both architectures: SOA provides a scalable, service‑oriented backbone, while DDD supplies a rich domain model and clear separation of concerns, resulting in maintainable and adaptable backend systems.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITFLY8 Architecture Home
ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
