In the domain that i'm trying to model, there are 2 classes: ClothingType and TreatmentType
public class ClothingType : Entity<Guid>
{
public string Name { get; protected set; }
public ClothingType(Guid id, string name)
: base (id)
{
Name = name;
}
}
public class TreatmentType : Entity<Guid>
{
public string Name { get; protected set; }
public TreatmentType(Guid id, string name)
: base(id)
{
Name = name;
}
}
A ClothingType (t-shirt, pant, etc) support many kinds of TreatmentType's (wash, iron, etc). And one kind of TreatmentType can be supported by many ClothingType's. But, the price of a specified TreatmentType varies according to ClothingType.
Imagine two kinds of treatments: wash and iron. In t-shirts, washing costs $20, in pants costs $35, and so on. How to model this?
Thanks in advance.
Clothing type and Entity Type are probably values, rather than entities.
There might be a product catalog, or some analog to it, with query methods that take a clothing type and an entity type as inputs and provide a pricing estimate as an output. If you needed that pricing estimate in your domain logic, then you would likely achieve that via a domain service that allowed the model to access a recent copy of the product catalog to look up the pricing.
Check out Alberto Brandolini's Event Storming approach so you could discover the domain you're dealing with. Is billing part of your core bounded context?
If it's just a usual ecommerce product with a price, you should definetly start with defining ClothingType and TreatmentType as Value Objects. I'm no Java expert but in PHP it would look like this:
class Cloth {
/** #var ClothingType */
private $type;
/** #var TreatmentType[]|array */
private $treatments;
...
}
Also check the Money pattern cause it might come in handy when creating your ValueObjects.
I would suggest not diving into DDD (especially in the tactical phase) without a slight understanding of it's principles. At least try to read Vaughn's DDD Distilled.
EDIT: Giving it a second thought I would design more or less it like this:
class Treatment {
/** #var TreatmentId */
private $treatmentId;
/** #var TreatmentType */
private $type;
/** #var Money */
private $price;
//constructor, getters, etc.
public function modifyPrice(int $amount)
{
$this->price = new Money($amount);
}
}
class Cloth {
/** #var ClothType */
private $type;
/** #var Treatment[]|array */
private $treatments;
public function addTreatment(Treatment $aTreatment)
{
array_push($this->treatments, $aTreatment);
}
}
Related
I am building a Web API using Dapper for .NET Core and trying to adhere to Clean Architecture principles. The API is consumed by an external Angular front-end.
I have repositories that use Dapper to retrieve data from the database, and this data then passes through a service to be mapped into a DTO for display to the user.
It is my understanding that an entity should be an exact representation of the database object, with no extra properties, and that I should use DTOs if I require some additional properties to show the user (or if I wish to obscure certain properties from the user too).
Suppose I have a DTO:
public class StudentDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<Assignment> Assignments { get; set;}
}
and its corresponding Entity:
public class Student
{
public Guid Id { get; set; }
public string Name { get; set; }
}
With this model, should I want to get a student with all of their assignments, I'd need to have two repository calls, and do something like this in the service:
public StudentDTO GetById(Guid id)
{
var student = this.studentRepository.GetById(id);
var assignments = this.assignmentRepository.GetByStudentId(id);
return SomeMapperClass.Map(student, assignments);
}
But this seems inefficient and unnecessary. My question is, should I not just retrieve the Assignments when I get the student entity in the repository, using a JOIN? Or would this violate what an entity is supposed to be?
I apologise, I do realise this is a rather simple question, but I'd really like to know which method is the best approach, or if they both have their use cases
I think it would be more efficient, since map uses reflections, that is slower tens times
public StudentDTO GetById(Guid id)
{
var student = this.studentRepository.GetById(id);
student.Assignments = this.assignmentRepository.GetByStudentId(id);
return student;
}
but the common way is
return _context.Students.Include(i=>i.Assignments).FirstOrDefault(i=> i.Id==id);
This is why the generic repository is a bad idea in the most casses, since it is hard to guess what set of data you will need.
When we search "Don't repeat yourself" on Wikipedia, the first sentence is:
In software engineering, don't repeat yourself (DRY) is a principle of
software development aimed at reducing repetition of software
patterns, replacing them with abstractions...
I know that abstractions in software engineering mean hiding implementation complexity of how the behaviors of an API are realized, but it seems that "abstractions" in this sentence is not what I know before. Could someone explain to me what abstraction means here? It would be better if you could give me an example.
I know that abstractions in software engineering mean hiding
implementation complexity of how the behaviors of an API are realized
Yes it means that (absstraction#wikipedia) and very same concept can also be leveraged to reduce repetitions! Or in other words, it can be used to practice DRY.
Let me try to explain that with an example. First I'll show non DRY code (without abstraction), then with use of abstraction I'd try to reduce repetitions.
Let's assume that you wanted to build an email view model based on application form details filled out by applicant and there is an email view class which consumes this emailViewModel to show all non-null details from application form. You could write it like in below example (first attempt)
public class ApplicationForm
{
public AddressDetail AddressDetail { get; set; }
public CustomerDetail CustomerDetail { get; set; }
public ProductDetail ProductDetail { get; set; }
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
Address = GetAddressDetail(applicationForm.AddressDetail);
Customer = GetCustomerDetail(applicationForm.CustomerDetail);
Product = GetProductDetail(applicationForm.ProductDetail);
}
public string Address { get; set; }
public string Customer { get; set; }
public string Product { get; set; }
}
//view code assume razor view
#if(Model.Address!=null)
{
// method for showing address
}
#if(Model.Customer!=null)
{
// method for showing customer
}
//and other properties
I've kept above code quite simple; only three properties and haven't showed declaration for conversion methods. What if there were 50 properties! In this first approach it would be cumbersome changes that you'd be making in three places. Now I'll show you second example code of how you could create an interface (a way of abstraction) implement DRY.
interface IFormDetail
{
IFormDetailView GetDetail();
}
interface IFormDetailView
{
string ShowView();
}
public class ApplicationForm
{
public List<IFormDetail> FormDetails {get;set;}
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
if(applicationForm.FormDetails!=null)
{
FormDetails = new List<IFormDetailView>();
foreach(var detail in applicationForm.FormDetails)
{
FormDetails.Add(detail.GetDetail());
}
}
}
public List<IFormDetailView> FormDetails { get; set; }
}
//view code assume razor view
#f(Model.FormDetails!=null)
{
foreach(var detail in Model.FormDetails){
detail.ShowView();
}
}
In this second code example , when you've a new property, you'll only make one change when a new application form property is created.
So while we are hiding complexity of how detail is presented etc., we are also leveraging it to reduce repetition.
Let's assume we have a simple payment feature on an online shop. We want to manage different transactions with different processors of transactions:
A transaction can be a payment or a refund.
A processor of transactions can be Paypal or Payplug.
So we have the following classes:
class PaymentTransaction implements Transaction {
}
class RefundTransaction implements Transaction {
}
class PaypalProcessor implements Processor {
}
class PayplugProcessor implements Processor {
}
What should be a good understanding of OOP?
Processor.process(transaction);
or
Transaction.process(processor);
For example, if we take the example 1, how to avoid the following switch statement?
class PaypalProcessor {
function process(Transaction transaction) {
switch(transaction.getType()) {
case payment:
//..
break;
case refund:
//..
}
}
In all cases, how to manage a "nested" polymorphism, a strategy or something else to be able to manage the different transactions with the different processors?
PS: if the title is not appropriate, tell me I will edit it.
You seem to be on the right track. What you need is a third class for performing the operations (sample code in Java for the sake of discussion) :
class PaymentProcessor {
private Processor processor;
private Transaction transaction;
public PaymentProcessor(Processor processor, Transaction transaction) {
this.processor = processor;
this.transaction = transaction;
}
public void processPayment() {
processor.process(transaction);
}
}
You can then inject the appropriate implementation of Processor and Transaction into the PaymentProcessor :
PaymentProcessor paymentProcessor = new PaymentProcessor(new PayPalDepositProcess(),new PaypalDepositTransaction());
PaymentProcessor refundProcessor = new PaymentProcessor(new PayPalRefundProcess(),new PayPalRefundTransaction());
Notice how you're PaymentProcessor can be passed different combinations of a Processor and Transaction without the need to have a switch statement.
Note that processor.process(transaction); sounds more intuitive than transaction.process(processor). Also note that you can consider using the Abstract Factory pattern here since you seem to be creating a family of related objects (different types of processors that process different types of transactions)
I would make transaction object responsible for both processing payment and refunds.
interface Transaction
{
public function pay();
public function refund();
}
Then you'd have concrete ones like this:
class PaypalTransaction implements Transaction
{
public function pay()
{
//process payment in a paypale way
}
public function refund()
{
//process refund in a paypale way
}
}
class PayplugTransaction implements Transaction
{
public function pay()
{
//process payment the way Payplug do
}
public function refund()
{
//process refund the way Payplug do
}
}
Client code that would process transaction payment might look like this:
$customer = new Customer();
//concrete factory producing an abstract product (transaction)
$transaction = $customer->prepareTransaction('100 USD');
//process payment
$transaction->pay();
//in a similar fashion you would go about processing a refund
$transaction->refund();
Notice how the client code is kept in the dark about the concrete way money is transferred (implementation details, paypal or payplug). In other words the client is processing transactions polymorphically because it is coded to an abstract rather than a concrete object.
Customer in this example is the concrete factory for the client code:
class Customer implements Shopper
{
/**
* #param string $amount
* #return Transaction
*/
public function prepareTransaction($amount)
{
//use either paypal or payplug depending on the customer's preference
}
}
if the client was coded in a way it expects to work with an abstract object (e.g. "Shopper") then we'd have an appearance of an Abstract Factory pattern.
interface Shopper
{
/**
* #param string $amount
* #return Transaction
*/
public function prepareTransaction($amount);
}
I just recently became aware of the Law of Demeter.
Like a lot of things, I realized that it was something that I was already doing but did not have a name for. There are a few places though that I seem to violate it.
For example...
I might have an Address object:
public class Address : IAddress
{
public string StreetAddress { get; set; }
public string City { get; set; }
public int Zip { get; set; }
}
and a Customer object:
public class Customer : ICustomer
{
private IAddress address;
Customer()
{
Address = null;
}
public string Name { get; set; }
public IAddress
{
get
{
if (address == null)
{
address = new Address();
}
return address;
}
set
{
address = value;
}
}
}
Ok, this is fake code so you probably do not have to jump on me to use IoC to eliminate the new Address() or anything but it is pretty much an example of what I am doing. I did not include the interfaces as I am hoping they are obvious.
I would then use it in my code for stuff like int zip = customer.Address.Zip; and customer.Address.City = "Vancouver";
As I understand it, I am violating the Law of Demeter by manipulating details of Address from Customer.
Then again, it seems like the framework does as well. After all, wouldn't address.City.Length be a violation? Should I be adding methods to Address to handle accessing string properties? Probably not. So, why clutter up Address?
I cannot really just add methods to Address that relate only to customer. I have Member, Employee, Dependent, Vendor, Employer, etc. objects that all have addresses too.
Is there a better way to handle this? What kinds of problems am I risking if I use Address the way I am now?
For the Java folks, the Address class might look something more like the following if it helps:
public class Address extends AddressInterface
{
private String m_city;
public String getCity() { return m_city; }
public void setCity(String city) { m_city = city; }
}
I must admit that customer.getAddress().setCity("Vancouver"); rings more alarms than customer.Address.City = "Vancouver"; did for me. Maybe I should switch to Java for a while.
This article: http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx has a great explanation of the issues you are discussing.
As he notes it's not a dot counting exercise, it's a coupling issue. Currently your Customer and Address classes are too tightly coupled. For starters, Customer shouldn't be making new addresses, perhaps pass an Address in using a constructor. As to whether you should be using multiple dots to access parts of the address, read the article ...
Martin Fowler: "I'd prefer it to be called the Occasionally Useful Suggestion of Demeter."
Violations of the Law of Demeter are instances of a code smell named Inappropriate Intimacy. To remove this smell, you can refactor your code by hiding the internals of address and implementing methods in Customer that delegate to address. This way, you respect the encapsulation on the address inside the Customer.
Example:
public class Customer extends ICustomer{
private Address address;
....
public void setCity(String city){
address.setCity(city);
}
public String getCity(){
return address.getCity();
}
}
Hope this helps.
The problem here is that Address is a ValueObject. You would never change the city without changing the zip.
public class Customer extends ICustomer{
private Address address;
....
public void setAddress(String street, String city, int zip){
address = Address.new(street, city, zip);
}
// or even better but i'm not sure if it's valid C#
public void setAddress(int zip){
address = Address.lookup(zip);
}
}
I'm testing how difficult it is to use NHibernate with a domain that is completely unaware of it and isn't bent to accodomate any limitations.
On many examples I found on the web the domain being mapped is yet another example of an anemic domain, where objects don't go far from being simple data holders. Sure, this makes the mapping simple and all and it might appeal to data-centric persons/situations, but I don't like hearing the voices in my head that say "C has structs too, you know?", "Classes are not just fancy namespaces, you know?", or "Why don't you use CREATE TABLE instead?".
But back to NHibernate. NHibernate forces me to make properties virtual to be able to proxy them for lazy loading. This is something I don't mind, as I might need them as virtual for some AOP stuff too.
The limitations I'm not happy with are the need for an empty constructor and the need for setters/properties. I want my entities to be created in a valid state, and most of the time that means no empty constructor.
I also don't want to expose setters for collection properties, for the usual reasons. Oh, and setters for attributes that are not supposed to be changed directly.
Consider this simplified and contrived aggregate in a domain model somewhere:
public class ShoppingCartItem
{
private readonly Product product;
public ShoppingCartItem(Product product, int quantity)
{
if(quantity <= 0)
throw new ArgumentOutOfRangeException("quantity");
this.product = product;
this.quantity = quantity;
}
public virtual Product Product
{
get { return product; }
}
private int quantity;
public virtual int Quantity
{
get { return quantity; }
set
{
if(value <= 0)
throw new ArgumentOutOfRangeException("value");
quantity = value;
}
public virtual Money TotalPrice
{
get { return product.Price * quantity; }
}
}
public class ShoppingCart : Entity
{
private readonly IDictionary<Product, ShoppingCartItem> items =
new Dictionary<Product, ShoppingCartItem>();
private readonly ISet<DiscountCoupon> discountCoupons =
new HashSet<DiscountCoupon>();
public virtual IEnumerable<ShoppingCartItem> Items
{
get { return items.Values; }
}
public virtual IEnumerable<DiscountCoupon> DiscountCoupons
{
get { return discountCoupons; }
}
public virtual void AddProduct(Product product)
{
ShoppingCartItem item;
if(items.TryGetValue(product, out item))
item.Quantity++;
else
items.Add(product, new ShoppingCartItem(product, 1));
}
public virtual void RemoveProduct(Product product)
{
ShoppingCartItem item;
if(!items.TryGetValue(product, out item))
throw new ArgumentException("product");
if(item.Quantity == 1)
items.Remove(product);
else
item.Quantity--;
}
public virtual int AddDiscountCoupon(DiscountCoupon coupon)
{
discountCoupons.Add(coupon);
}
public virtual int RemoveDiscountCoupon(DiscountCoupon coupon)
{
discountCoupons.Remove(coupon);
}
public virtual Money CalculatePrice()
{
// Missing complex discount logic
return items.Values.Sum(item => item.TotalPrice);
}
}
Most properties have no setter, and there are no empty constructors in sight. Collections are not meddled with directly, but through specialized methods. Can I make use of NHibernate's extensibility to map this? Or am I trying to hammer a screw again? Or both?
Well you can put private/internal/protected setters on properties/collections and nhibernate will load them up properly (chapter 4.1.1)
The constructor has to be there but you are not obliged to make it a public one (chapter 4.1.2)
chapter ref from the latest http://sourceforge.net/projects/nhibernate/files/NHibernate/2.1.2GA/NHibernate-2.1.2.GA-reference.zip/download
First off you can make the empty constructor private so that nobody else can access it. NH will still be able to get to it.
Second off NH can access your properties however you want.
access="backfield" is used for public virtual Product Product { get; private set; }
access="field.pascalcase-m-underscore" for m_Product
access="field.pascalcase-underscore" for _Product
There are other access strategies and I'm pretty sure you can even create your own if need be.