Overall Architecture
In these sections of the nopCommerce Developer Documentation, we will broadly cover the overall architecture of nopCommerce. Detailed descriptions of each component will be described in later sections of the developer guide. Note that this part is an introductory overview. A more detailed discussion will come later in the guide. Depending on your experience level, these overviews may be enough to get you going!
Services
The heart of nopCommerce is embodied its many service classes (more than 70), located in the solution folder “Libraries,” in a single project named “Nop.Services.” Almost all important / complex business logic is in the service layer or is in a plugin. Some service classes have thousands of lines of code, many have fewer than 100 lines. Most services ultimately map to a related set of database tables, but some are “infrastructure” services. Some notable types include:
- Formatting “services” (
PriceFormatter
,ProductAttributeFormatter
) - Calculation services (
PriceCalculationService
,OrderTotalCalculationService
) - Database configuration, installation, and maintenance tasks (FullText setup,
MaintenanceService
, import/export) - Event publishing/subscription (
EventPublisher
,SubscriptionService
, event consumer interface) - Email notification and workflow (Wrapper for SMTP communication, Email formatting and “mail merge” fields)
- Scheduled task engine
- Various extension methods on domain objects (
Customer.GetFullName()
,IList<ShoppingCartItem>.RequiresShipping()
) - Miscellaneous request/response classes (
ChangePasswordRequest
,PlaceOrderResult
)
Each service implements a corresponding service interface. The service classes almost always depend on one or more Repository<T>
or on other services, which are injected into the class constructors. For example, here are the first few lines of OrderService
.
public partial class OrderService : IOrderService
{
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<OrderItem> _orderItemRepository;
private readonly IRepository<OrderNote> _orderNoteRepository;
private readonly IRepository<Product> _productRepository;
private readonly IRepository<RecurringPayment> _recurringPaymentRepository;
private readonly IRepository<Customer> _customerRepository;
private readonly IRepository<ReturnRequest> _returnRequestRepository;
private readonly IEventPublisher _eventPublisher;
...
}
As you might guess from the above, a service class has the following features:
- Responsible for a broad area of functionality (Orders)
- Usually coordinates between more than one repository (Orders, OrderItems, Customers, etc)
- Publishes events (“Order updated” event, “return request created” event)
- Is NOT directly responsible for website / web server concerns such as MVC controller actions, views, file operations, and routing. (Some possible exceptions include SEO, sitemaps generation, and website permissions)
Some of the largest concerns are split into multiple service classes. For example,
- Customer functionality is split into
CustomerActivityService
,CustomerAttributeService
,CustomerRegistrationService
,CustomerReportService
, andCustomerService
- Order functionality is split into
OrderProcessingService
,OrderReportService
,OrderService
, andOrderTotalCalculationService
The MVC layer (the Nop.Web project) has controllers that in turn depend on these service classes. We’ll go into more depth regarding SOA and nopCommerce’s services later in this guide.
A Note on "Services-Oriented Architecture"
The term Services-Oriented Architecture (SOA) is not well-defined. Some sources say that services should be discoverable web services, or that services should be out-of-process, or that each service should be versioned and deployable independently. None of these is the case with nopCommerce.