I am newbie to SOA though I have some experience in OOAD.
One of the guidelines for SOA design is “Use Abstract Classes for Modeling only. Omit them from Design”. The use of abstraction can be helpful in modeling (analysis phase).
During analysis phase I have come up with a BankAccount base class. The specialized classes derived from it are “FixedAccount” and “SavingsAccount”. I need to create a service that will return all accounts (list of accounts) for a user. What should be the structure of service(s) to meet the requirement?
Note: It would be great if you can provide code demonstration using WCF.
It sounds like you are trying to use SOA to remotely access your object model. You would be better of looking at the interactions and capabilities you want your service to expose and avoid exposing inheritance details of your services implementation.
So in this instance where you need a list of user accounts your interface would look something like
[ServiceContract]
interface ISomeService
{
[OperationContract]
Collection<AccountSummary> ListAccountsForUser(
User user /*This information could be out of band in a claim*/);
}
[DataContract]
class AccountSummary
{
[DataMember]
public string AccountNumber {get;set;}
[DataMember]
public string AccountType {get;set;}
//Other account summary information
}
if you do decide to go down the inheritance route, you can use the KnownType attribute, but be aware that this will add some type information into the message being sent across the wire which may limit your interoperability in some cases.
Update:
I was a bit limited for time earlier when I answered, so I'll try and elaborate on why I prefer this style.
I would not advise exposing your OOAD via DTOs in a seperate layer this usually leads to a bloated interface where you pass around a lot of data that isn't used and religously map it into and out of what is essentially a copy of your domain model with all the logic deleted, and I just don't see the value. I usually design my service layer around the operations that it exposes and I use DTOs for the definition of the service interactions.
Using DTOs based on exposed operations and not on the domain model helps keep the service encapsulation and reduces coupling to the domain model. By not exposing my domain model, I don't have to make any compromises on field visibility or inheritance for the sake of serialization.
for example if I was exposing a Transfer method from one account to another the service interface would look something like this:
[ServiceContract]
interface ISomeService
{
[OperationContract]
TransferResult Transfer(TransferRequest request);
}
[DataContract]
class TransferRequest
{
[DataMember]
public string FromAccountNumber {get;set;}
[DataMember]
public string ToAccountNumber {get;set;}
[DataMember]
public Money Amount {get;set;}
}
class SomeService : ISomeService
{
TransferResult Transfer(TransferRequest request)
{
//Check parameters...omitted for clarity
var from = repository.Load<Account>(request.FromAccountNumber);
//Assert that the caller is authorised to request transfer on this account
var to = repository.Load<Account>(request.ToAccountNumber);
from.Transfer(to, request.Amount);
//Build an appropriate response (or fault)
}
}
now from this interface it is very clear to the conusmer what the required data to call this operation is. If I implemented this as
[ServiceContract]
interface ISomeService
{
[OperationContract]
TransferResult Transfer(AccountDto from, AccountDto to, MoneyDto dto);
}
and AccountDto is a copy of the fields in account, as a consumer, which fields should I populate? All of them? If a new property is added to support a new operation, all users of all operations can now see this property. WCF allows me to mark this property as non mandatory so that I don't break all of my other clients, but if it is mandatory to the new operation the client will only find out when they call the operation.
Worse, as the service implementer, what happens if they have provided me with a current balance? should I trust it?
The general rule here is to ask who owns the data, the client or the service? If the client owns it, then it can pass it to the service and after doing some basic checks, the service can use it. If the service owns it, the client should only pass enough information for the service to retrieve what it needs. This allows the service to maintain the consistency of the data that it owns.
In this example, the service owns the account information and the key to locate it is an account number. While the service may validate the amount (is positive, supported currency etc.) this is owned by the client and therefore we expect all fields on the DTO to be populated.
In summary, I have seen it done all 3 ways, but designing DTOs around specific operations has been by far the most successful both from service and consumer implementations. It allows operations to evolve independently and is very explicit about what is expected by the service and what will be returned to the client.
I would go pretty much with what others have said here, but probably needs to add these:
Most SOA systems use Web Services for communication. Web Services expose their interface via WSDL. WSDL does not have any understanding of inheritance.
All behaviour in your DTOs will be lost when they cross the wire
All private/protected fields will be lost when they cross the wire
Imagine this scenario (case is silly but illustrative):
public abstract class BankAccount
{
private DateTime _creationDate = DateTime.Now;
public DateTime CreationDate
{
get { return _creationDate; }
set { _creationDate = value; }
}
public virtual string CreationDateUniversal
{
get { return _creationDate.ToUniversalTime().ToString(); }
}
}
public class SavingAccount : BankAccount
{
public override string CreationDateUniversal
{
get
{
return base.CreationDateUniversal + " UTC";
}
}
}
And now you have used "Add Service Reference" or "Add Web Reference" on your client (and not re-use of the assemblies) to access the the saving account.
SavingAccount account = serviceProxy.GetSavingAccountById(id);
account.CreationDate = DateTime.Now;
var creationDateUniversal = account.CreationDateUniversal; // out of sync!!
What is going to happen is the changes to the CreationDate will not be reciprocated to the CreationDateUniversal since there is no implementation crossed the wire, only the value of CreationDateUniversal at the time of serialization at the server.
Related
I'm starting to use ServiceStack to implement a web service API. I'm trying to follow the examples and best-practices as much as possible, but sometimes this is not that easy (it seems that many samples are not yet updated to follow the new API design).
What I currently have is something like this:
an assembly named MyApp.ServiceInterface containing the implementation of the services/methods
an assembly named MyApp.ServiceModel containing the request and response types and the DTOs
In the MyApp.ServiceModel assembly, I have for example:
namespace MyApp.ServiceModel
{
public abstract class ResponseBase
{
public ResponseStatus ResponseStatus { get; set; } // for error handling
}
[Route("/products/{Id}")] // GET: products/123
[Route("/products")] // GET: products?Name=...
public class ProductRequest : IReturn<ProductResponse>
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductResponse : ResponseBase
{
public Types.Product Product { get; set; }
}
}
namespace MyApp.ServiceModel.Types
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
// ...
}
}
Questions:
I have seen different ways of how to name the request types (e.g. GetProduct, ProductRequest or just Product). What is the recommended approach?
Does the naming somehow depend on whether the service is a REST-service or not?
Would it be a good idea to put the request and response types into seperate (sub-)namespaces (e.g. MyApp.ServiceModel.Requests and MyApp.ServiceModel.Responses)?
Why is the assembly containing the implementations named ServiceInterface (wouldn't ServiceImplementation fit better)?
API design is subjective so there's no recommended approach. Although I personally dislike appending 'Request' suffix on my Request DTOs since its effectively your Web Service Contract. I also dislike the use of inheritance in Service Models for trying to DRY properties which hides intent in your Service Layer which is your most important contract.
The name of the Request DTOs doesn't affect REST Apis with custom routes since there's no externally visible difference with different Request DTO's using the same custom route. Although it does affect the surface area when using the end-to-end typed clients since it forms the visible part of your typed API.
Here are a couple of answers which describe my preferences of how I would design service APIs:
Designing a REST-ful service with ServiceStack
How to design a Message-Based API
C# Namespaces in DTOs have no visible effect on your API. In ServiceStack Request DTOs map 1:1 with your Service so they must be unique which, if you append a 'Response' suffix for your Response DTOs, they will end up being unique as well. As a goal I ensure all my DTOs, both operations and types, are uniquely named so it doesn't matter what their physical layout is. As a convention I now like to place my operation DTOs (i.e. Request / Response) on the top-level of the Service Model assembly, with the Request / Response DTO in the same C# .cs file whilst all other 'DTO Types' in a Types folder, e.g:
/Products.cs (holds GetProduct and ProductResponse DTOs)
/Types/Product.cs
It's called Service Interface since it matches the Gateway Service pattern where your client is called a Client Gateway whilst your Server is called the Service Interface. The use of Interface here means service entry point and not C# Interface.
I have debated this for a while now and still have not come to a conclusion.
While most examples I see have the factories code in the application layer I tend to think it should be in the domain layer.
Reasons for this:
I sometimes have initial validation done in my factory where I want all creation of objects to go through.
I want this code to be used on all instantiates of my object.
Sometimes an operation requires parameter information which feels unnatural to pass to a constructor.
And a few more not as important reasons.
Are there reasons why this is a bad practice?
Does this break other patterns?
A factory in DDD is just an instance of the factory pattern and as such it should be used where it makes the most sense. Another principle to consider is the information expert pattern which essentially states that behavior should be assigned to classes closest to the information. Therefore, if you have some domain specific rules and logic you would like to enforce, place the factory in the domain layer - after all, the factory creates domain objects. Note however that you may have other types of factories in other layers.
From memory, Eric Evans' book has examples where object factories are very much part of the domain layer.
For me, it makes perfect sense to locate your factories here.
+1 for doing that. Accessibility would be a good reason, I would keep the creational code at least close to the domain model layer. Otherwise users of the domain model will get simply confused how to instantiate it specially when finding restricted access constructors. Actually one sound reason to separate it would be that you have different valid ways to create the same thing e.g. which is the case usually when employing the Abstract Factory.
If I had to separate it I would put it in e.g. a package (in the case of Java) at least the same level of the domain model and ship it always along with it e.g.
upper
--> domain
--> domain_factory
I prefer Factories in the Application Layer.
If you keep the Factories in the Domain Layer, they will not help you when you need complex types as parameters (C# code example):
Application Layer:
//this Factory resides in the Domain Layer and cannot reference anything else outside it
Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(
string name, string code, string streetName,...
and lots of other parameters...);
//these ones reside in Application Layer, thus can be much more simple and readable:
Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(CreatePersonCommand);
Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(PersonDTO);
Domain Layer:
public class Person : Entity<Person>
{
public Address Address {get;private set;}
public Account Account {get;private set;}
public Contact Contact {get;private set;}
public string Name {get;private set;}
public Person(string name, Address address,Account account, Contact contact)
{
//some validations & assigning values...
this.Address = address;
//and so on...
}
}
public class Address:Entity<Address>{
public string Code {get;private set;}
public string StreetName {get;private set;}
public int Number {get;private set;}
public string Complement {get;private set;}
public Address(string code, string streetName, int number, string complement?)
{
//some validations & assigning values...
code = code;
}
}
public class Account:Entity<Account>{
public int Number {get;private set;}
public Account(int number)
{
//some validations & assigning values...
this.Number = number;
}
}
//yout get the idea:
//public class Contact...
Also, there is no obligation on keeping Factories inside the Domain Layer (from Domain Driven Design Quickly):
Therefore, shift the responsibility for creating instances of complex
objects and Aggregates to a separate object, which may itself have
no responsibility in the domain model but is still part of the
domain design. Provide an interface that encapsulates all complex
assembly and that does not require the client to reference the
concrete classes of the objects being instantiated. Create entire
Aggregates as a unit, enforcing their invariants.
As I don't use Factories to load persisted objects into memory, they don't have to be accessible from other layers than Application's. Here's why (from Domain Driven Design Quickly):
Another observation is that Factories need to create new objects
from scratch, or they are required to reconstitute objects which
previously existed, but have been probably persisted to a
database. Bringing Entities back into memory from their resting
place in a database involves a completely different process than
creating a new one. One obvious difference is that the new
object does not need a new identity. The object already has one.
Violations of the invariants are treated differently. When a new
object is created from scratch, any violation of invariants ends
up in an exception. We can’t do that with objects recreated from
a database. The objects need to be repaired somehow, so they
can be functional, otherwise there is data loss.
If builders/factories only have dependencies on domain classes and primitives, place them in the domain layer, otherwise place them outside the domain layer.
CAREFUL with placing 'implementation' in the Domain Layer.
Your domain code doesn't have dependencies. So, you are in trouble if you need to have complex factories.
For example:
// DOMAIN LAYER
public interface IAggregateFactory<TAgg, in TInput>
{
Task<TAgg> CreateAsync(TInput input);
}
public class AvailabilityFactoryParameters
{
public string SomeInputParameter { get; set; }
public string ZipCode { get; set; }
}
// INFRASTRUCTURE/APPLICATION LAYER
public class AvailabilityFactory : IAggregateFactory<GamePredictorAggregate,
GamePredictorFactoryParameters>
{
private readonly HttpClient _httpClient;
public AvailabilityFactory(IHttpClientFactory factory)
{
_httpClient = factory.CreateClient("weatherApi");
}
public async Task<GamePredictorAggregate> CreateAsync(GamePredictorFactoryParameters input)
{
var weather = await _httpClient.GetFromJsonAsync<WeatherDto>($"/weather/{input.ZipCode}");
return new GamePredictorAggregate(weather.CurrentTemperature, input.SomeInputParameter);
}
}
public class WeatherDto
{
public double CurrentTemperature { get; set; }
}
As you can see, now you have a myriad of objects and dependencies available to enrich your factory experience.
So, when you use it in your Application Service, it is easy...
public class GamePredictionService : ApplicationService
{
private readonly IAggregateFactory<GamePredictorAggregate, GamePredictorFactoryParameters> _factory;
public GamePredictionService(IAggregateFactory<GamePredictorAggregate, GamePredictorFactoryParameters> factory)
{
_factory = factory;
}
public async Task CreateNewPredictor(string zipCode, int someOtherParamater)
{
var input = new GamePredictorFactoryParameters();
input.ZipCode = zipCode;
input.SomeInputParameter = someOtherParamater;
var aggregate = await _factory.CreateAsync(input);
// Do your biz operations
// Persist using repository
}
}
Now your application service doesn't need to worry about the internals, and your domain objects need to understand how the factory gives them 'birth.'
Summary: Having your implementation in the Domain layer makes only sense if your factory only needs primitive types and nothing else. In cases where you may need to gather data from external services or other application services' DTOs, you want to move the implementation outside.
The only 'drawback' is that you need to 'inject' the factory into your application service, but that's not a big deal.
I hope this answer helps to clarify 'where to place Factories.'
I've built a REST API with the WCF Web API Preview and I wanna build a library with the classes that you pass to this API (Just to make the .Net developers life easier). The should be simple POCO classes without much functionality.
But on the receiver side it would make sense for me to add some functionality to these classes. I have an example below:
[WebInvoke(UriTemplate = "", Method = "POST")]
public Supertext.API.Order Create(Supertext.API.Order apiOrder)
{
And this is an example POCO class:
public class Order
{
public string Service { get; set; }
public string OrderTitle { get; set; }
public string Currency { get; set; }
}
Now, what's a good way to extend this class on the server side?
I guess using a subclass would not work.
Delegates?
Actually have two different versions of the class? One for clients and one for the server?
What do other people do?
The problem with adding extra functionality to this POCO class is you are turning it into a domain object. The nature of this domain object will now be constrained by the fact that, essentially, this class acts as the definition of the interface into the operation. Changing details about this class will potentially break clients.
It is a far cleaner model to keep this class purely as a Data Transfer Object whose single responsibility is aiding the bridging of the wire format to objects and use a mapper such as AutoMapper to map the data from the DTO to a real domain object. The real domain object is fully under your control and you can happily refactor it without threatening a cascading effect to your service consumers
I have a new question for WCF gurus.
So, I have a class User which is close to the 'User' representation from the DB which I use for database operations. Now, I would like to have 2 different service contracts that use this class as data contract, but each in their own way... I mean,
public class DBLayer
{
void InsertUsers(List<User> userList)
{
// both 'PropertyVisibleForService1' and 'PropertyVisibleForService2'
// are used HERE to be inserted into their columns
}
}
[DataContract]
public class User
{
[DataMember] public string PropertyVisibleOnlyForService1{...}
[DataMember] public string PropertyVisibleOnlyForService2{...}
}
[ServiceContract]
public interface IService1
{
List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside
}
[ServiceContract]
public interface IService2
{
List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside
}
So, the idea is that each service will get a different kind of user, subset of 'User'. Keeping in mind that I want to use the 'User' as is for DB operations, what would be my options to achieve this? Do I really need to create different data contracts or is there another smarter way?
Best would be to not only give me the solution, but also to explain me some best practices and alternatives.
Thank you in advance.
EDIT1:
I added a dummy DBLayer class here for a better overview and why I think the inheritance may not be good in this case.
A solution would be of having another 'UserForService1' and 'UserForService2' as data contracts which would map at the end from/into an 'User' but I wanted some other points of view.
EDIT2: Very good article which helped me in this case: http://bloggingabout.net/blogs/vagif/archive/2009/03/29/iextensibledataobject-is-not-only-for-backward-compatibility.aspx
You could create separate DTO's for each service but your case would actually be ideal for a Decorator pattern:
[DataContract]
public class UserForService1 : User
{
private User mUser;
public UserForService1(User u)
{
mUser = u;
}
//expose only properties you'd like the user of this data contract to see
[DataMember]
public string SomeProperty
{
get
{
//always call into the 'wrapped' object
return mUser.SomeProperty;
}
set
{
mUser.SomeProperty = value;
}
}
// etc...
}
and for Service2 similar code, that exposes only what you care for there...
If they are designed to represent different types of users, they should be different classes. I agree with phoog in the comments, you should derive the type you want from the shared User class and add the specific service properties to the derived classes.
Why don't you think inheritance would be good in this case? If you give us some more details, we could try to revise the suggestions to suit your actual problem.
As suggested in the comment, you can have two classes deriving from a base User then using Data Contract Known Types, you can accomplish your desired goal. See the following links for more examples.
http://www.freddes.se/2010/05/19/wcf-knowntype-attribute-example/
http://footheory.com/blogs/bennie/archive/2007/07/28/handling-data-contract-object-hierarchies-in-wcf.aspx
If you don't want to use inheritance, something like:
[DataContract]
public class User
{
}
[DataContract]
public class Service1User : User
{
[DataMember] public string PropertyVisibleOnlyForService1{...}
}
[DataContract]
public class Service2User : User
{
[DataMember] public string PropertyVisibleOnlyForService2{...}
}
[ServiceContract]
public interface IService1
{
List<Service1User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside
}
[ServiceContract]
public interface IService2
{
List<Service2User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside
}
Then I'm not sure what you would do. Your sortof breaking the principals of an type declaration at that point. Think of it in a normal .NET way; if you define "User" in your application, then it is the same type everywhere. Some properties cant be hidden from certain other classes or methods.
WCF is also going to pack this type information into the generated WSDL, and it is only going to define the User type once, so it needs to know what properties are there.
Now, if all you care about is the actual SOAP message that is constructed, and you don't care about the WSDL or what any clients generated off the WSDL will see, then technically you can have it not emit that property into the SOAP message when it is null, by doing:
[DataMember(EmitDefaultValue=false)]
Then when that property is null, it wont be included in the serialization. That would make no real difference if the client was generated from the WSDL though, as its User type would still have to contain both properties. It would just change the serialization so that instead of sending the client something like:
<User>
<PropertyVisibleOnlyForService1 nil="true" />
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>
it would instead send:
<User>
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>
Is it possible to give different view of a Class . For example , i have Account class , i want expose this data using WCF. For different method call i want expose different property of Account class.Suppose for particular call i want expose only UserName and Password, for
another call i want expose Email and Address. Should i have to write different class or
i can expose needed property to client
If one usage is WCF and another usage is internal to your app, then you can annotate the class appropriately with [DataMember] such that only the desired properties are exposed. If you have two different WCF scenarios, then I would introduce a new class (or classes) to represent each set of return data, probably adding an implicit conversion operator (from the entity to the DTO), so that you can do:
public CustomerLite GetCustomer(int id) {
Customer cust = SomeTier.GetCustomer(id);
return cust; // note cust is Customer but we are returning CustomerLite
}
You could use a DataContract with DataMember attributes, but that allows you to produce only one serialised view of a class. You would probably want to create smaller ViewModel classes, possibly using AutoMapper to handle all the mapping code for you.
If you want to expose multiple views of the same Account class, the answer is no (that I'm aware of). Using the default DataContractSerializer, you can control which members are presented to the user only in a declarative manner. This would allow you to customize the user's view in one way, but not multiples.
Instead, you can create one individual data contract class (which might take an Account as a constructor argument) for each "view" you wish to expose.
You could achieve this using interfaces as "views". For example create a UsernamePassword interface with methods or properties to access username and password and have the Account class implement this interface. You can then pass this interface around and the users of it will be unaware of the other methods and properties in the account class.
interface IUsernamePassword
{
string Username { get; set; }
string Password { get; set; }
}
class Account : IUsernamePassword
{
public string Username { get; set; }
public string Password { get; set; }
}
Always, always, always use a message class (aka DTO) when using any service that is hosted outside of your app domain.
I use to have a slide in all my presentations on WCF that stated Message Classes != Business Classes, but I've since found a better way to explain it.
This isn't Star Trek people. You Can't Fax a Cat (a picture is worth a 1000 words).