ServiceStack: business logic that depends on the database itself - servicestack

I'm exploring ServiceStack and I'm not sure what is the best way to implement some business logic.
Using the "Bookings CRUD" example I would like to enforce the following rule:
a given Booking can only be saved (either created or updated) if the hotel has enough free rooms for the particular dates of that booking
Please note that I'm not asking how to calculate "free rooms".
What I'm asking is, from the architectural point of view, how should this be done.
For example, one way would be:
create a request DTO to query the number of configured rooms (lets call it "QueryRooms")
use the existing "QueryBookings" to query current bookings present in database
create a " : Service" class to customize the Booking Service, in order to intercept the "CreateBooking" and "UpdateBooking" requests
inside the custom methods for "CreateBooking" and "UpdateBooking", somehow get the results of "QueryRooms" and "QueryBookings", check if there are enough free rooms for the current request, and proceed only if so
This doesn't look very clean, because the service "CreateBooking" and "UpdateBooking" would depend of "QueryRooms" and "QueryBookings".
What would be an elegant and effcient solution, using ServiceStatck?

You can override AutoQuery CRUD operations with your own Service implementation using the AutoQuery DTO.
Where you can use the Service Gateway to call existing Services which you can use to perform any additional validation & modify the request DTO before executing the AutoQuery operation to implement the API, e.g:
public class MyCrudServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
public object Post(CreateBooking request)
{
var response = Gateway.Send(new QueryRooms
{
From = request.BookingStartDate,
To = request.BookingEndDate,
});
if (response.Results.Count == 0)
throw new Exception("No rooms available during those dates");
request.RoomNumber = response.Results[0].Id;
return AutoQuery.Create(request, base.Request);
}
}
Note: calling in-process Services with the Service Gateway is efficient as it calls the C# method implementation directly, i.e. without incurring any HTTP overhead.

Related

Azure Insights: tracking custom property through the chain of function executions

I have Azure Function1->Function2->Service flow of calls in my Azure app. There are multiple concurrent calls of Function1 and each could be identified by some unique input Document Id. I wonder how in c# code I can set something in Azure Insight context to that document id in the beginning of Funciton1, so that any [traces] or [exceptions] or [dependencies] logged to Azure Insights in any of the follow up calls contains the document id. I noticed all of them have customDimension nested list of properties, so maybe somehow add one more property to there. Also if Function1 runs multiple times in parallel, I do not want these document id to be mixed up.
Goal is to be able to track this document id in all kinds of logs with min amount of additional c# code, avoid passing the document id from function to other functions and other services, so looking into any type of log (wheatear it's traces or exceptions or other) I'm able to immediately identify document the execution belonged to. Is it possible?
To attach a custom property to all logs whithin an azure function is not that diffucult, one could simply use a telemetry initializer to do that:
public class TelemetryEnrichment : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
if (!(telemetry is ISupportProperties item)) return;
// Demonstrate static property
item.Properties["Environment"] = "Production";
}
}
If it is an http triggered function you can enricht the request telemetry like this:
var requestTelemetry = req.HttpContext.Features.Get<RequestTelemetry>();
requestTelemetry.Properties.Add("aProp", "aValue");
You also want to have to property logged by other functions that are called by the entry function. This is not easy doable: you will need to pass the id to the other function manually, for example by passing it using the url of that function.
However, if you have to Id attached to the logs of the entry function you can easily create a query to correlate the logs. Based on the operation id you can get the whole picture of the communication flow between the functions and services, see the docs:
That way, you do not need to include the Id as a custom property to each and every telemetry item.

Why is data access tightly coupled to the Service base in ServiceStack

I'm curious why the decision was made to couple the Service base class in ServiceStack to data access (via the Db property)? With web services it is very popular to use a Data Repository pattern to fetch the raw data from the database. These data repositories can be used by many services without having to call a service class.
For example, let's say I am supporting a large retail chain that operates across the nation. There are a number of settings that will differ across all stores like tax rates. Each call to one of the web services will need these settings for domain logic. In a repository pattern I would simply create a data access class whose sole responsibility is to return these settings. However in ServiceStack I am exposing these settings as a Service (which it needs to be as well). In my service call the first thing I end up doing is newing up the Setting service and using it inside my other service. Is this the intention? Since the services return an object I have to cast the result to the typed service result.
ServiceStack convenience ADO.NET IDbConnection Db property allows you to quickly create Database driven services (i.e. the most popular kind) without the overhead and boilerplate of creating a repository if preferred. As ServiceStack Services are already testable and the DTO pattern provides a clean endpoint agnostic Web Service interface, there's often not a lot of value in wrapping and proxying "one-off" data-access into a separate repository.
But at the same time there's nothing forcing you to use the base.Db property, (which has no effect if unused). The Unit Testing Example on the wiki shows an example of using either base.Db or Repository pattern:
public class SimpleService : Service
{
public IRockstarRepository RockstarRepository { get; set; }
public List<Rockstar> Get(FindRockstars request)
{
return request.Aged.HasValue
? Db.Select<Rockstar>(q => q.Age == request.Aged.Value)
: Db.Select<Rockstar>();
}
public RockstarStatus Get(GetStatus request)
{
var rockstar = RockstarRepository.GetByLastName(request.LastName);
if (rockstar == null)
throw HttpError.NotFound("'{0}' is no Rockstar".Fmt(request.LastName));
var status = new RockstarStatus
{
Alive = RockstarRepository.IsAlive(request.LastName)
}.PopulateWith(rockstar); //Populates with matching fields
return status;
}
}
Note: Returning an object or a strong-typed DTO response like RockstarStatus have the same effect in ServiceStack, so if preferred you can return a strong typed response and avoid any casting.

Domain driven design external systems and technical dependencies

I am designing a system using domain driven design concepts and I am struggling with a few things. The "domain" is essentially a business system for the company I work for. I am also using dependency injection. So, in my model I have things related to any typical business system (Employee, Order, Invoice, Deposit, etc..). Right now I am trying to create a cash posting application in which users (aka Employees) can create deposits and apply them to unpaid invoices. The problem that I am having is that we are also using an external business system (Microsoft Dynamics Nav) to handle our accounting transactions. So essentially I am dealing with two different databases. So, for the cash posting application I have modeled the domain objects Deposit and DepositLine. I also have in my domain an IDepositRepository interface that is responsible for persisting the deposits. To get a deposit from the system I just want to grab it directly from the database. However, in order to create a deposit I have to use the Dynamics Nav web services because there is certain logic that gets executed behind the scenes that I don't know about. I started looking at the concept of an Anti Corruption layer in which I could translate my version of the deposit object into a deposit object suitable for the web service. So here is what I am envisioning right now:
Domain Layer
- Models
- Deposit
- DepositLine
- Repositories
- IDepositRepository
Infrastructure Layer
- Data
- Repositories
- DepositRepository
- DynamicsNav
- Services
- INavCashManagementService
- Translators
- IDepositTranslator
- Adapters
- INavAdapter
Now I thought i might implement the DepositRepository like so:
public class DepositRepository
{
private INavCashManagementService navCashManagementService;
public DepositRepository(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public Deposit GetDeposit(int id)
{
// use nhibernate to get directly from the database
}
public void SaveDeposit(Deposit deposit)
{
this.navCashManagementService.CreateDeposit(deposit);
}
}
First of all, is this an appropriate design? My next problem is that users are also going to have to "Post" deposits. The Nav web services will also have to be used to run the posting routine. But, this is more of a business process rather than a persistence issue, so I don't see it fitting into the repository. So I am wondering how/where I should call the posting routine. Should I create a domain service like this:
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
public CashPostingDomainService(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
}
}
One confusion I have with domain driven design is external dependencies. Doesn't the CashPostingDomainService class now have an external dependency on Nav? I know the implementation isn't in the domain layer, but doesn't the interface itself make it a dependency? The same goes with other technical concerns like sending emails. If I have an IEmailService interface and want to send an email once the deposits are posted, would I inject the interface into the CashPostingDomainService class? Or would that be part of the application workflow? So which one of these options make the most sense (if any):
1
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
private IEmailService emailService;
public DepositController(
ICashPostingDomainService cashPostingDomainService,
IEmailService emailService)
{
this.cashPostingDomainService = cashPostingDomainService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
2
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
public DepositController(
ICashPostingDomainService cashPostingDomainService)
{
this.cashPostingDomainService = cashPostingDomainService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
}
}
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
private IEmailService emailService;
public CashPostingDomainService(
INavCashManagementService navCashManagementService,
IEmailService emailService)
{
this.navCashManagementService = navCashManagementService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
Thanks for the help!
is this an appropriate design?
It seems fine to me. The important thing is for your Repository to stay oblivious of the Nav side of things and let the anticorruption layer handle that. You might want to have a look here for a similar example.
I know the implementation isn't in the domain layer, but doesn't the
interface itself make it a dependency?
You may have that feeling because the name of your (supposedly agnostic) service interface contains "Nav". To reflect a service abstraction that could have Nav or any other ERP as an implementation, you should rename it to ICashManagementService.
If I have an IEmailService interface and want to send an email once
the deposits are posted, would I inject the interface into the
CashPostingDomainService class? Or would that be part of the
application workflow?
It's your architectural decision to choose one or the other.
Option 1. means that sending an email is an intrinsic part of the deposit posting domain operation. If you take your domain module and reuse it in another application, posting deposits will automatically result in sending an email whatever that application is about. This might be the right thing to do in your context, or you might want to make things a little more generic (like, sending feedback after the operation but not deciding in the domain service whether this feedback should be mail, a log file, etc.)
Option 2. means that the sequence of events that happen after posting the deposits is application specific, that is at the use case level rather than business/domain level. It is up to the Controller (or Application Service) to decide which actions to take -send an email or anything else. Consequently, different applications based around your domain layer could decide to take different actions. This also means possible code duplication between these applications if several of them chose to send mails.

Injecting infra layer interface in app service

I have two aggregates, Advertiser and Payment.
I am using Paypal and Authorize.net payment gateway. So i created interface in infra layer.
interface IPaymentMethod
{
void ProcessPayment(PaymentInfo paymentInfo);
}
and implemented it again in infra layer.
Public class PaypalPaymentGateway : IPaymentMethod
{
public void ProcessPayment(PaymentInfo paymentInfo)
{
// call Paypal api and pass paymentinfo
}
}
//same for authorize.net payment gateway
Below is my app service class
public class PaymentGatewayService : IPaymentGatewayService
{
IPaypalMethod paypalMethod;
public PaymentGatewayService(IPaypalMethod paypalMethod)
{
this.paypalMethod = paypalMethod;
if (paypalMethod == null)
throw new Exception("PaypalMethod not initialized");
}
public void DepositFundInAdvertiser
(PaymentInfo paymentInfo, RegistrationID advertiserRegistrationID)
{
if (paymentMethod != null)
throw new Exception("PaymentMethod empty.");
PaymentResult paymentResult=
paymentMethod.ProcessPayment(paymentInfo);
Advertiser advertiser = advertiserRepository
.Find(advertiserRegistrationID);
advertiser.AddAdvertiserFund(paymentInfo.PaymentTotal);
advertiserRepository.Save(advertiser);
}
}
In App layer - can I inject PaypalMethod interface in App layer constructor and do the following in DepositFundInAdvertiser method?
Remember IPaypalMethod is created and implemented in infra layer.
Your approach seems good enough.
Only I would define IPayer abstraction inside domain layer instead of infrastructure layer.
Because it's (most likely) responsibility of domain model to decide how to react if payment is [un]successful.
//in domain model
public class IPayer{
bool Pay(Money amountToBePaid, BankAccount account);;
}
public class Payment{
public void Pay(IPayer payer){
EnsurePaymentCanBePaid();
IsPaid=payer.Pay(AmountToBePaid,Account);
if(!IsPaid) throw new Exception("Payment failed!");
}
}
//in infrastructure layer
public class PayPalPayer:IPayer{
public bool Pay(Money amountToBePaid, BankAccount account){
//bla bla
}
}
To follow up on my comment. I would also put the PaymentService in infrastructure layer as an infrastructure service. But as Arnis said you should also reflect ho the model respond to this action - Pay.
I (not sure) would probably have some kind of PaymentService in applicaion service layer that works with both entities Advertiser and Payment (through IAdvertiserRepository and IPaymentRepository injected through constructor).
In method (writing this method in memcode):
PaymentService.PayAdvert(Advertiser advertiser, Advert advert, Payment paymentInfo)
{
advertiser.BuyAdvertising(AdvertPayment.Create(advert,paymentInfo))
}
BuyAdvertising method takes both Advert and Payment into AdvertPayment class (which has a static create method for ctor itself. This class can be handy if you want a PaymentHistory collection for Advertiser that contains AdvertPayments in date order. But
BuyAdvertising raises a domain event BuyAdvertisingEvent that triggers a eventhandler in application layer, BuyAdvertisingEventHandler.
This Eventhandler has your IPaypalGatewayService injected in constructor. With the event we have Payment info. If Payment is a success the EventHandler can also have IAdvertiserRepository injected in ctor and save the AdvertPayment into Advertiser payment history collection.
then BuyAdvertising can determine the outcome of payment transaction by checking if advert is paid and added to history collection.
I hope you get the picture. This way you have several tools like an event which is declared in domain model and triggered from the entity advertiser. The model takes action and you have moved out the infra tech logic against PayPal through DomainEventHandler an still, you have not located the logic entirely in application layer. The control is in the domain, but details that domain don't care about is placed in infra layer.
My experience is that these scenarios are common for me and you usually go the easy way, letting the application service do all talking to infralayer. But then you're closingin on a anemic model design, because what is left for the model to do? Just validation properties? Just managing aggregates and collections? I think there is more to it. It should also contains a lot of entity action methods (I call them so... :)) like BuyAdvertisment.
/Cheers

Interface with service layer or domain objects themselves? (DDD)

I'm still learning about DDD and I have these two (probably simple) questions:
If a Factory creates new object/graph/aggregate instances, but also "reconstitutes" objects/graphs from the Repository, then:
(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioural method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.
(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?
You can see I'm all over the place. Please help.
(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioral method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.
Usually - top level retrieves necessary aggregate root and calls a function on it. Sometimes top level retrieves multiple aggregate roots and pass them to domain service, but not often because domain service is a quite strong sign that there is unrecognized aggregate root. At the end - top level ensures aggregate root is persisted.
(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?
Yes, they do. Domain model should be aware of it's state changes. And that's much more beneficial as it seems at first. Great thing about this is that You gain extensibility point. If client will walk week later to You and say that he wants system to check additional things when user updates post - instead of searching every line of post.bodyText="new value", You will be able to go straight to post.UpdatePost method and attach necessary things there.
On the other hand - CRUD is not mutually exclusive with domain driven design. E.g. - in my application, management of users and their roles is uninteresting enough that I'm not even trying to model it granularly. You need to recognize parts what matters in business Your application is describing and working with.
Keep in mind that domain driven design makes sense for complex applications only. Simple blog application doesn't need it.
(3) Am I wrong in assuming that a service layer (not Domain Services) should encapsulate how an interface interacts with the Domain Layer?
As I see it - application services are more for orchestrating infrastructure. If there is no infrastructure involved - then application service loses value:
Application services basically are just facades. And every facade is bad if complexity it adds overweights problems it solves.
Inside domain:
//aggregate root is persistence ignorant.
//it shouldn't reference repository directly
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
//here it's aware of state changes.
//aggregate root changes it's own state
//instead of having state changed from outside
//through public properties
this.Name=name;
}
}
//domain model contains abstraction of persistence
public interface ICustomerRepository{
void Save(Customer customer);
}
Outside of domain:
public class CustomerRepository:ICustomerRepository{
//here we actually save state of customer into database/cloud/xml/whatever
public void Save(Customer customer){
//note that we do not change state of customer, we just persist it here
_voodoo.StoreItSomehow(customer);
}
}
//asp.net mvc controller
public class CustomerController{
public CustomerController(ICustomerRepository repository){
if (repository==null)throw new ArgumentNullException();
_repository=repository;
}
public ActionResult Register(string name){
var customer=Customer.Register(name);
_repository.Save(customer);
}
}

Resources