Created
February 18, 2016 00:32
-
-
Save Bio2hazard/71c58c97a60a1d1b794f to your computer and use it in GitHub Desktop.
Composition? Inheritance? Best approach?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pro: | |
- Least amount of code. | |
- Least amount of mapping. | |
- Least amount of repeated boilerplate code. | |
- Has "AddContents" method. | |
- "GetFriendlyString" functionality is available to ShoppingCartWithContents. | |
Con: | |
- It is not very clear what properties this tree of composed classes contains. To get to the Cart Id you have to dig through cartWithContents.ShoppingCart.Id. | |
- If something is composed using ShoppingCartWithContents we'd look at something like: premiumShoppingCartWithContents.ShoppingCartWithContents.ShoppingCart.Id. | |
Other: | |
- Does not have the ability to change, override or otherwise mess with "GetFriendlyString", which can be a good thing or a bad thing. | |
*/ | |
void Main() | |
{ | |
var source = new ShoppingCartDatabaseModel | |
{ | |
Id = 1, | |
OwnerName = "Test", | |
Value = 1.21M | |
}; | |
var cart = new ShoppingCart(source); | |
var contents = new ShoppingCartContent | |
{ | |
ItemId = 1, | |
Quantity = 3 | |
}; | |
var cartWithContents = cart.AddContents(contents); | |
cartWithContents.ShoppingCart.GetFriendlyString().Dump(); | |
Debug.Assert(cartWithContents.Content != null && cartWithContents.ShoppingCart.OwnerName != null); | |
} | |
public class ShoppingCart | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public ShoppingCart(ShoppingCartDatabaseModel source) { | |
Id = source.Id; | |
OwnerName = source.OwnerName; | |
Value = source.Value; | |
} | |
public ShoppingCartWithContents AddContents(ShoppingCartContent content) | |
{ | |
return new ShoppingCartWithContents(this, content); | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value}"; | |
} | |
} | |
public class ShoppingCartWithContents | |
{ | |
public ShoppingCart ShoppingCart { get; set; } | |
public ShoppingCartContent Content { get; set; } | |
public ShoppingCartWithContents(ShoppingCart shoppingCart, ShoppingCartContent content) | |
{ | |
ShoppingCart = shoppingCart; | |
Content = content; | |
} | |
} | |
public class ShoppingCartDatabaseModel | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
} | |
public class ShoppingCartContent | |
{ | |
public int ItemId { get; set; } | |
public int Quantity { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pro: | |
- Not too much code. | |
- Properties are surfaced directly. | |
- Has "AddContents" method. | |
Con: | |
- "GetFriendlyString" ( stand in for business logic ) is not available to ShoppingCartWithContents, meaning business logic would have to be repeated. | |
- This con is big enough to make this unusable in my opinion. | |
*/ | |
void Main() | |
{ | |
var source = new ShoppingCartDatabaseModel | |
{ | |
Id = 1, | |
OwnerName = "Test", | |
Value = 1.21M | |
}; | |
var cart = new ShoppingCart(source); | |
var contents = new ShoppingCartContent | |
{ | |
ItemId = 1, | |
Quantity = 3 | |
}; | |
var cartWithContents = cart.AddContents(contents); | |
cartWithContents.GetFriendlyString().Dump(); | |
Debug.Assert(cartWithContents.Content != null && cartWithContents.OwnerName != null); | |
} | |
public interface IShoppingCart | |
{ | |
int Id { get; set; } | |
string OwnerName { get; set; } | |
decimal Value { get; set; } | |
string GetFriendlyString(); | |
} | |
public class ShoppingCart : IShoppingCart | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public ShoppingCart(ShoppingCartDatabaseModel source) { | |
Id = source.Id; | |
OwnerName = source.OwnerName; | |
Value = source.Value; | |
} | |
public ShoppingCartWithContents AddContents(ShoppingCartContent content) | |
{ | |
return new ShoppingCartWithContents(this, content); | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value}"; | |
} | |
} | |
public class ShoppingCartWithContents : IShoppingCart | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public ShoppingCartContent Content { get; set; } | |
public ShoppingCartWithContents(IShoppingCart shoppingCart, ShoppingCartContent content) | |
{ | |
Id = shoppingCart.Id; | |
OwnerName = shoppingCart.OwnerName; | |
Value = shoppingCart.Value; | |
Content = content; | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value} With Items!"; | |
} | |
} | |
public class ShoppingCartDatabaseModel | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
} | |
public class ShoppingCartContent | |
{ | |
public int ItemId { get; set; } | |
public int Quantity { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pro: | |
- Properties are surfaced directly. | |
- "GetFriendlyString" business logic is a modular piece that can be re-used, modified and expanded. | |
Con: | |
- Lots of code. | |
- Id, OwnerName and Value properties are repeated 6 times, not counting the DB Model. | |
- 4 Identical mapping code blocks, this id = that id, this ownername = that ownername etc. | |
- No "AddContents" method. | |
*/ | |
void Main() | |
{ | |
var source = new ShoppingCartDatabaseModel | |
{ | |
Id = 1, | |
OwnerName = "Test", | |
Value = 1.21M | |
}; | |
var cart = new ShoppingCart(source); | |
var contents = new ShoppingCartContent | |
{ | |
ItemId = 1, | |
Quantity = 3 | |
}; | |
var cartWithContents = new ShoppingCartWithContents(cart, contents); | |
cartWithContents.FriendlyStringCreator.GetFriendlyString().Dump(); | |
Debug.Assert(cartWithContents.Content != null && cartWithContents.OwnerName != null); | |
} | |
public interface IShoppingCart | |
{ | |
int Id { get; set; } | |
string OwnerName { get; set; } | |
decimal Value { get; set; } | |
IFriendlyStringCreator FriendlyStringCreator { get; set; } | |
} | |
public interface IFriendlyStringCreator | |
{ | |
int Id { get; set; } | |
string OwnerName { get; set; } | |
decimal Value { get; set; } | |
string GetFriendlyString(); | |
} | |
public class FriendlyStringCreator : IFriendlyStringCreator | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public FriendlyStringCreator(int id, string ownerName, decimal value) | |
{ | |
Id = id; | |
OwnerName = ownerName; | |
Value = value; | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value}"; | |
} | |
} | |
public class FriendlyStringCreatorForContents : IFriendlyStringCreator | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public FriendlyStringCreatorForContents(int id, string ownerName, decimal value) | |
{ | |
Id = id; | |
OwnerName = ownerName; | |
Value = value; | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value} With Items"; | |
} | |
} | |
public class ShoppingCart : IShoppingCart | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public IFriendlyStringCreator FriendlyStringCreator { get; set;} | |
public ShoppingCart(ShoppingCartDatabaseModel source) { | |
Id = source.Id; | |
OwnerName = source.OwnerName; | |
Value = source.Value; | |
FriendlyStringCreator = new FriendlyStringCreator(Id, OwnerName, Value); | |
} | |
} | |
public class ShoppingCartWithContents : IShoppingCart | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public IFriendlyStringCreator FriendlyStringCreator { get; set;} | |
public ShoppingCartContent Content { get; set; } | |
public ShoppingCartWithContents(IShoppingCart shoppingCart, ShoppingCartContent content) | |
{ | |
Id = shoppingCart.Id; | |
OwnerName = shoppingCart.OwnerName; | |
Value = shoppingCart.Value; | |
Content = content; | |
FriendlyStringCreator = new FriendlyStringCreatorForContents(Id, OwnerName, Value); | |
} | |
} | |
public class ShoppingCartDatabaseModel | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
} | |
public class ShoppingCartContent | |
{ | |
public int ItemId { get; set; } | |
public int Quantity { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pro: | |
- Properties are surfaced directly. | |
- "AddContents" method. | |
- "GetFriendlyString" business logic is a modular piece that can be re-used, modified and expanded. | |
- IShoppingCartWithItems and IShoppingCartWithoutItems can be used to target specific cart implementations | |
Con: | |
- Ungodly amount of code. | |
- Id, OwnerName and Value properties are repeated 6 times, not counting the DB Model. | |
- 4 Identical mapping code blocks, this id = that id, this ownername = that ownername etc. | |
*/ | |
void Main() | |
{ | |
var source = new ShoppingCartDatabaseModel | |
{ | |
Id = 1, | |
OwnerName = "Test", | |
Value = 1.21M | |
}; | |
var cart = new ShoppingCart(source); | |
var contents = new ShoppingCartContent | |
{ | |
ItemId = 1, | |
Quantity = 3 | |
}; | |
var cartWithContents = cart.AddContents(contents); | |
cartWithContents.FriendlyStringCreator.GetFriendlyString().Dump(); | |
Debug.Assert(cartWithContents.Content != null && cartWithContents.OwnerName != null); | |
} | |
public interface IShoppingCart | |
{ | |
int Id { get; set; } | |
string OwnerName { get; set; } | |
decimal Value { get; set; } | |
IFriendlyStringCreator FriendlyStringCreator { get; set; } | |
} | |
public interface IFriendlyStringCreator | |
{ | |
int Id { get; set; } | |
string OwnerName { get; set; } | |
decimal Value { get; set; } | |
string GetFriendlyString(); | |
} | |
public class FriendlyStringCreator : IFriendlyStringCreator | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public FriendlyStringCreator(int id, string ownerName, decimal value) | |
{ | |
Id = id; | |
OwnerName = ownerName; | |
Value = value; | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value}"; | |
} | |
} | |
public class FriendlyStringCreatorForContents : IFriendlyStringCreator | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public IFriendlyStringCreator FriendlyStringCreator { get; set;} | |
public FriendlyStringCreatorForContents(int id, string ownerName, decimal value) | |
{ | |
Id = id; | |
OwnerName = ownerName; | |
Value = value; | |
} | |
public string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value} With Items"; | |
} | |
} | |
public interface IShoppingCartWithoutContents : IShoppingCart | |
{ | |
IShoppingCartWithContents AddContents(IShoppingCartContent content); | |
} | |
public interface IShoppingCartWithContents : IShoppingCart | |
{ | |
IShoppingCartContent Content { get; set; } | |
} | |
public class ShoppingCart : IShoppingCartWithoutContents | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public IFriendlyStringCreator FriendlyStringCreator { get; set;} | |
public ShoppingCart(ShoppingCartDatabaseModel source) { | |
Id = source.Id; | |
OwnerName = source.OwnerName; | |
Value = source.Value; | |
FriendlyStringCreator = new FriendlyStringCreator(Id, OwnerName, Value); | |
} | |
public IShoppingCartWithContents AddContents(IShoppingCartContent content) | |
{ | |
return new ShoppingCartWithContents(this, content); | |
} | |
} | |
public class ShoppingCartWithContents : IShoppingCartWithContents | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public IFriendlyStringCreator FriendlyStringCreator { get; set;} | |
public IShoppingCartContent Content { get; set; } | |
public ShoppingCartWithContents(IShoppingCart shoppingCart, IShoppingCartContent content) | |
{ | |
Id = shoppingCart.Id; | |
OwnerName = shoppingCart.OwnerName; | |
Value = shoppingCart.Value; | |
Content = content; | |
FriendlyStringCreator = new FriendlyStringCreatorForContents(Id, OwnerName, Value); | |
} | |
} | |
public class ShoppingCartDatabaseModel | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
} | |
public interface IShoppingCartContent | |
{ | |
int ItemId { get; set; } | |
int Quantity { get; set; } | |
} | |
public class ShoppingCartContent : IShoppingCartContent | |
{ | |
public int ItemId { get; set; } | |
public int Quantity { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pro: | |
- Not too much code. | |
- Properties are surfaced directly. | |
- "AddContents" method. | |
- "GetFriendlyString" business logic can be overriden. | |
Con: | |
- "GetFriendlyString" business logic is tied directly to ShoppingCartBase and can not be re-used in other scenarios that require the same business logic. | |
- ShoppingCartBase needs to know about ShoppingCartDatabaseModel. | |
*/ | |
void Main() | |
{ | |
var source = new ShoppingCartDatabaseModel | |
{ | |
Id = 1, | |
OwnerName = "Test", | |
Value = 1.21M | |
}; | |
var cart = new ShoppingCart(source); | |
var contents = new ShoppingCartContent | |
{ | |
ItemId = 1, | |
Quantity = 3 | |
}; | |
var cartWithContents = cart.AddContents(contents); | |
cartWithContents.GetFriendlyString().Dump(); | |
Debug.Assert(cartWithContents.Content != null && cartWithContents.OwnerName != null); | |
} | |
public class ShoppingCart | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public ShoppingCart(ShoppingCartDatabaseModel source) { | |
Id = source.Id; | |
OwnerName = source.OwnerName; | |
Value = source.Value; | |
} | |
public ShoppingCart(ShoppingCart shoppingCart) | |
{ | |
Id = shoppingCart.Id; | |
OwnerName = shoppingCart.OwnerName; | |
Value = shoppingCart.Value; | |
} | |
public ShoppingCartWithContents AddContents(ShoppingCartContent content) | |
{ | |
return new ShoppingCartWithContents(this, content); | |
} | |
public virtual string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value}"; | |
} | |
} | |
public class ShoppingCartWithContents : ShoppingCart | |
{ | |
public ShoppingCartContent Content { get; set; } | |
public ShoppingCartWithContents(ShoppingCart shoppingCart, ShoppingCartContent content) : base(shoppingCart) | |
{ | |
Content = content; | |
} | |
public override string GetFriendlyString() | |
{ | |
return string.Format("{0} With Items", base.GetFriendlyString()); | |
} | |
} | |
public class ShoppingCartDatabaseModel | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
} | |
public class ShoppingCartContent | |
{ | |
public int ItemId { get; set; } | |
public int Quantity { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pro: | |
- Not too much code. | |
- Properties are surfaced directly. | |
- "AddContents" method. | |
- "GetFriendlyString" business logic can be overriden. | |
- ShoppingCartBase does not need any knowledge of ShoppingCartDatabaseModel. | |
Con: | |
- "GetFriendlyString" business logic is tied directly to ShoppingCartBase and can not be re-used in other scenarios that require the same business logic. | |
*/ | |
void Main() | |
{ | |
var source = new ShoppingCartDatabaseModel | |
{ | |
Id = 1, | |
OwnerName = "Test", | |
Value = 1.21M | |
}; | |
var cart = new ShoppingCart(source); | |
var contents = new ShoppingCartContent | |
{ | |
ItemId = 1, | |
Quantity = 3 | |
}; | |
var cartWithContents = cart.AddContents(contents); | |
cartWithContents.GetFriendlyString().Dump(); | |
Debug.Assert(cartWithContents.Content != null && cartWithContents.OwnerName != null); | |
} | |
public abstract class ShoppingCartBase | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
public ShoppingCartBase(int id, string ownerName, decimal value) | |
{ | |
Id = id; | |
OwnerName = ownerName; | |
Value = value; | |
} | |
public ShoppingCartBase(ShoppingCartBase shoppingCartBase) | |
{ | |
Id = shoppingCartBase.Id; | |
OwnerName = shoppingCartBase.OwnerName; | |
Value = shoppingCartBase.Value; | |
} | |
public virtual string GetFriendlyString() | |
{ | |
return $"{Id}: {OwnerName} {Value}"; | |
} | |
} | |
public class ShoppingCart : ShoppingCartBase | |
{ | |
public ShoppingCart(ShoppingCartDatabaseModel source) : base(source.Id, source.OwnerName, source.Value) { } | |
public ShoppingCartWithContents AddContents(ShoppingCartContent content) | |
{ | |
return new ShoppingCartWithContents(this, content); | |
} | |
} | |
public class ShoppingCartWithContents : ShoppingCartBase | |
{ | |
public ShoppingCartContent Content { get; set; } | |
public ShoppingCartWithContents(ShoppingCartBase shoppingCart, ShoppingCartContent content) : base(shoppingCart) | |
{ | |
Content = content; | |
} | |
public override string GetFriendlyString() | |
{ | |
return string.Format("{0} With Items", base.GetFriendlyString()); | |
} | |
} | |
public class ShoppingCartDatabaseModel | |
{ | |
public int Id { get; set; } | |
public string OwnerName { get; set; } | |
public decimal Value { get; set; } | |
} | |
public class ShoppingCartContent | |
{ | |
public int ItemId { get; set; } | |
public int Quantity { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment