Skip to content

Instantly share code, notes, and snippets.

@Bio2hazard
Created February 18, 2016 00:32
Show Gist options
  • Save Bio2hazard/71c58c97a60a1d1b794f to your computer and use it in GitHub Desktop.
Save Bio2hazard/71c58c97a60a1d1b794f to your computer and use it in GitHub Desktop.
Composition? Inheritance? Best approach?
/*
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; }
}
/*
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; }
}
/*
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; }
}
/*
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; }
}
/*
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; }
}
/*
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