I started writing this as a real question, but I kept thinking of answers along the way, thought I would post it anyway to see if there were any other solutions
I can think of two examples in which generics become an unecessary pain, and I wonder if there is a solution.
Example 1
public class SomeClass<TDbConnection, TDbTransaction>
{
}
Now for any of us it's obvious - The DbTransaction, and DbConnection implementations will always be used in pairs - be it SqlConnection and SqlTransaction or OracleConnection and OracleTransaction
besides the fact that there is no way to make sure that the types make sense (nothing stops me from creating SomeClass<SqlConnection, OracleTransaction> when SomeClass uses three or four arguments that there types are inferable by context*, it becomes an unnecessary waste of time to instantiate each type.
*in this example, I am not sure how the framework can know, but you get my point? anyway the next example is more relevant
Example 2
public interface IPoco<TKey>
{
public TKey Id { get; set; }
}
public class SomePOCO : IPoco<int>
{
public int Id { get; set; }
}
public class SomeClassUsingPOCOAndId<TPoco, TKey>
where TPoco : IPoco<TKey>
{
}
In this example I managed to force the use of the correct TKey in instantiation, but why can't I just call new SomeClass<IPoco<int>>() or new SomeClass<SomePoco>() I mean the TKey is inferable.
Possible Solutions
I could drop the Generics, and in some cases it makes sense (like the first example). In others not so much, and creates either a memory or runtime overhead (unnecessarily creating of fields, or casting) or unnecessary code repeat.
The other solution I thought of was creating something like this
public interface IPoco<TKey>
{
public TKey Id { get; set; }
}
public class SomePOCO : IPoco<int>
{
public int Id { get; set; }
}
public class PocoContext<TPoco, TKey>
where TPoco : IPoco<TKey>
{
TKey Key { get; set; }
TPoco Poco { get; set; }
public PocoContext(TPoco poco)
{
Key = poco.Key;
Poco = poco;
}
}
public class SomeClassUsingPOCOAndId<TPocoContext>
{
}
This allows me to reduce the amount of code required for instantiation - but depending on my usage of the pocos - it could become really time consuming to create a context for each type.
Now I am wondering - isn't there a way to simplify this process? maybe by some sort of synthetic sugar? What would it take to implement it on C# 7 or 8?
Related
Starting with the use case.
Let's consider the base for this questions is a big framework and implementations of business objects of some software.
This software hast to be customized quite regularly, so it would be preferred that most of the C# objects are extendable and logic can be overriden. Even "model data".
The goal would be to be able to write code, create objects with input parameters - that may create more objects etc - and you don't have to think about whether those objects have derived implementations in any way. The derived classes will be used automatically.
For ease of uses a typesafe way to create the objects would be preferred as well.
A quick example:
public class OrderModel
{
public int Id { get; set; }
public string Status { get; set; }
}
public class CustomOrderModel : OrderModel
{
public string AdditionalData { get; set; }
}
public class StockFinder
{
public Article Article { get; }
public StockFinder(Article article)
{
Article = article;
}
public virtual double GetInternalStock() { /*...*/ }
public virtual double GetFreeStock() { /*...*/ }
}
public class CustomStockFinder : StockFinder
{
public bool UsePremiumAvailability { get; }
public CustomStockFinder(Article article, bool usePremiumAvailability)
: base(article)
{
UsePremiumAvailability = usePremiumAvailability;
}
protected CustomStockFinder(Article article) : this(article, false) { } // For compatibility (?)
public override double GetFreeStock() { /*...*/ }
}
In both cases I wanna do stuff like this
var resp = Factory.Create<OrderModel>(); // Creates a CustomOrderModel internally
// Generic
var finderGeneric = Factory.Create<StockFinder>(someArticle);
// Typesafe?
var finderTypesafe1 = Factory.StockFinder.Create(someArticle); // GetFreeStock() uses the new implementation
var finderTypesafe2 = Factory.StockFinder.Create(someArticle, true); // Returns the custom class already
Automatically generating and compiling C# code on build is not a big issue and could be done.
Usage of Reflection to call constructors is okay, if need be.
It's less about how complicating some code generation logic, written code analyzers, internal factories, builders etc are, and more about how "easy" and understandable the framework solution will be on a daily basis, to write classes and create those objects.
I thought about tagging the relevant classes with Attributes and then generating a typesafe factory class automatically on build step. Not so sure about naming conflicts, or references that might be needed to compile, as the constructor parameters could be anything.
Also, custom classes could have different constructors, so they should be compatible at each place in default code where they might be constructed already, but still create the custom object. In the custom code then you should be able to use the full custom constructor.
I am currently considering several different cases and possibilities, and can't seem to find a good solution. Maybe I am missing some kind of design pattern, or am not able to look outside of my bubble.
What would be the best design pattern or coding be to implement use cases like this?
I have a set of interfaces using each others like this:
public interface IModel
{
string Name { get; }
IModelParameters Parameters { get; }
}
public interface IModelParameter
{
int Value { get; }
}
public interface IModelParameters: IList<IModelParameter>
{
void DoSomething();
}
And to implement those interfaces, I have defined those classes:
public class Model: IModel
{
string Name { get; internal set; }
public ModelParameters Parameters { get; private set; }
IModelParameters IModel.Parameters { get { return Factors; } }
}
public class ModelParameter: IModelParameter
{
int Value { get; internal set; }
}
public class ModelParameters: List<ModelParameter>, IModelParameters
{
void DoSomething()
{
// actual code
}
}
This does not compile because List<ModelParameter> implements IList<ModelParameter> and not IList<IModelParameter> as required by IModelParameters
Changing ModelParameters to be List<IModelParameter> fixes the compilation but it breaks Entity Framework migration generation because it no longer recognizes the list as a navigation property because the type parameter is an interface, not a regular class.
I could also have ModelParameters not implement IModelParameters and declare a second class that gets instantiated and filled directly in the IModelParameters.Factors getter inside Model
But this feels inefficient as it effectively creates two instances of the same list, one for Entity framework and a temporary one for use by the rest of the application. And because this temporary is filled at runtime, it introduces another potential point of failure.
This is why I'm trying to find a way to express the fact List<ModelParameter> implements IList<IModelParameter> just fine because ModelParameter implements IModelParameter itself.
I have a feeling that covariance/contravariance might be of help here, but I'm not sure how to use that.
You cannot do this. It it was possible to cast a List<ModelParameter> to IList<IModelParameter> you could try adding a object of another type to the list, i.e. class MyOtherModelParam : IModelParameter. And that is a contradiction since the type system guarantees that the list only contains ModelParameter objects.
You could replace it with IReadOnlyList<T>, since this interface do not expose any add or set methods it is safe to cast a List<ModelParameter> to IReadOnlyList<IModelParameter>.
Another possible solution would be to just remove the interface. If you intend to have only one implementation of IModelParameter, the interface serves little purpose, and you might as well just remove it.
Every time I talk to experienced programmers, they talk about having global variables being a bad practice because of debugging or security exploits. I have a simple List of strings I want to load from a a textfile and access across different methods in my form. Before, I would simply initialize said variable at the top, inside of my form class and use it across methods. I always try to reduce that practice when I can and only initialize those variables when I really need them. Is it a bad practice to do this or do more experienced programmers do this too? Is there a standard design pattern method of doing this so you don't have to use "global variables" at the top of your form?
As you're talking about C# and it's a fully-object-oriented programming language, there's no way to declare global variables.
In an OOP language like C#, a bad practice can be simulating global variables using static classes:
public static class Global
{
public static string Value1 { get; set; }
public static int Value2 { get; set; }
}
...to later get or set these values from other classes. Definitely, this a bad practice because state should be held by specific and meaningful objects.
Usually, in a perfect/ideal OOP solution, you should pass such values from class to class using constructors:
public class X
{
public int Value1 { get; set; }
public void DoStuff()
{
Y y = new Y(this);
y.DoChildStuff();
}
}
public class Y
{
public class Y(X parent)
{
Parent = parent;
}
public X Parent { get; }
public void DoChildStuff()
{
// Do some stuff with Parent
}
}
Or also, you might pass states providing arguments to some method:
public class Y
{
public void DoChildStuff(X parent)
{
// Do some stuff with "parent"
}
}
Since you're passing states with reference types, if any of the methods in the chain decide to change Parent.Value1 with another value, all objects holding a reference to the same X object will get the new X.Value1.
Some fellows might argue that we usually build configuration objects which own a lot of properties accessed by other arbitrary objects, right? BTW, configuration is a concept per se, isn't it? And we usually categorize configuration values using composition:
public class ApplicationConfiguration
{
public DatabaseConfiguration Database { get; } = new DatabaseConfiguration();
public StorageConfiguration Storage { get; } = new StorageConfiguration();
}
public class DatabaseConfiguration
{
public string ConnectionString { get; set; }
}
public class StorageConfiguration
{
public string TemporalFileDirectoryPath { get; set; }
public string BinaryDirectoryPath { get; set; }
}
So later we inject the application configuration wherever we need it:
// Please note that it's a VERY hypothetical example, don't take
// it as an actual advise on how to implement a data mapper!!
public class DataMapper
{
public DataMapper(ApplicationConfiguration appConfig)
{
AppConfig = appConfig;
}
public ApplicationConfiguration AppConfig { get; }
private IDbConnection Connection { get; }
public void Connect()
{
// We access the configured connection string
// from the application configuration object
Connection = new SqlConnection(AppConfig.Database.ConnectionString);
Connection.Open();
}
}
In summary, and since I love comparing real-world and programming use cases, imagine that you never clean your room and you would use a single box to store every tool you might need some day. One day you need a screwdriver from the whole box, and you know that's inside it... But you need to throw everything in the box to the ground and work out the mess prior to find the priceless screwdriver to complete some home task.
Or imagine that you've bought a toolbox to store your tools in order, and once you need a screwdriver, you know that's in the toolbox and in the section where you store your screwdrivers.
You know that the second approach is the most mind-friendly. That is, when you develop software, you need to design mind-friendly architectures rather than a big mess of unrelated data and behaviors working together.
I've read this question about using Clone() and want to know if what I'm after will be achieved. My understanding from reading that question is that Clone() does a shallow copy, however reading elsewhere led me to believe differently, and now I'm confused.
Our project has a class Rule that has an ICollection<ICondition> Conditions. We'd like to provide users with a shortcut method to duplicate an existing Condition and modify it rather than start from scratch. To that end, we're providing a Copy To New button.
ICondition looks like this:
interface ICondition
{
long ID { get; set; }
string Description { get; set; }
DateTime EffectiveDate { get; set; }
string IfStatement { get; set; }
string PriceVersion { get; set; }
PriceDetail Pricing { get; set; }
bool StandardOption { get; set; }
}
Given what I've read about Clone(), I'm fairly confident it would work the way I expect by using ICondition newCondition = conditionToCopy.Clone(), though I'm unsure if Pricing would be duplicated correctly, since it's a complex data type.
So, the first part of my question is, "will this work?" I would just try it and see, however ICondition (or really its underlying Condition) doesn't seem to provide a method for Clone(), which leads me to the second part of my question: can I leverage IClonable to enable this functionality? If so, where?
Is this the way?
public static class Condition : IClonable
{
...
public Condition Clone(Condition conditionToClone)
{
return new Condition
{
Description = this.Description,
EffectiveDate = this.EffectiveDate,
IfStatement = this.IfStatement,
PriceVersion = this.PriceVersion,
Pricing = this.Pricing,
StandardOption = this.StandardOption
}
}
}
And, given that as the answer, is there any utility to declaring IClonable as the interface? Does it add any value?
Update:
Based on the below answer, I decided to do this, which at least builds (and hopefully runs; haven't tried it yet):
public class Condition
{
...
public Condition Clone()
{
return (Condition)base.MemberwiseClone();
}
}
I still don't see the need for ICloneable, so have left it out. The compiler was complaining about it anyway, something about the base class not being object.
There are couple of things. First Condition class should not be static. Second, PriceDetail class [Property pricing], Also need to impleemnt ICloneable. Instance class will allow base.MemberWiseClone() method.
public class Condition : ICloneable
{
public object Clone()
{
base.MemberwiseClone();
}
}
I have a company entity
public class Company : Entity<Company>
{
public CompanyIdentifier Id { get; private set; }
public string Name { get; private set; }
..............
..........
}
A company can be a agent or supplier or both or none. (There are more types) Its behaviour should be change based on types. Agent can get commission and supplier is able to invoice.
What will be the best way to design the entity or entities or value objects? I have an option to add some boolean types and check those values inside methods,
public class Company : Entity<Company>
{
public CompanyIdentifier Id { get; private set; }
public string Name { get; private set; }
public bool IsAgent { get; private set; }
public bool IsSupplier { get; private set; }
..........
public void Invoice()
{
if(!IsSupplier)
{
throw exception.....;
}
//do something
}
public void GetCommission(int month)
{
if(!IsAgent)
{
throw exception.....;
}
//do something
}
..........
}
To be honest, I do not like this. Is there any design pattern which might help to overcome this scenerio? What will you do and why to design this scenerio?
Implement interfaces explicitly, then override the cast operator to only cast to that interface when valid.
public class Company : ...., IAgentCompany, ISupplierCompany ... {
public double IAgentCompany.GetCommission(int month) {
/*do stuff */
}
public static explicit operator IAgentCompany(Company c) {
if(!c.IsAgent)
throw new InvalidOperationException();
return this;
}
}
Explicit implementations of interfaces must be called through their interface, not the concrete type:
// Will not compile
new Company().GetCommission(5);
// Will compile
((IAgentCompany)new Company()).GetCommission(5)
But, now we've overloaded the explicit cast operator. So what does that mean? We can't call GetCommission without casting to IAgentCompany, and now we have a guard to prevent that cast for a company that isn't marked as an agent.
Good things about this approach:
1) You have interfaces that define the aspects of different types of companies and what they can do. Interface segregation is a good thing, and makes the abilities/responsibilities of each type of company clear.
2) You've eliminated a check for every function you want to call that is not "global" to all companies. You do one check when you cast, and then as long as you have it in a variable typed as the interface, you can happily interact with it without any further checking. This means less places to introduce bugs, and less useless checks.
3) You are leveraging the languages features, and exploiting the type system to help make the code more bullet-proof.
4) You don't have to write tons of subclasses that implement the various combinations of interfaces (possibly 2^n subclasses!) with NotImplementedExceptions or InvalidOperationException everywhere in your code.
5) You don't have to use an enum or a "Type" field, especially when you are asking to mix and match these sets of abilities (you'd don't just need an enum, but a flag enum). Use the type system to represent different types and behaviors, not an enum.
6) It's DRY.
Bad things about this approach:
1) Explicit interface implementations and overriding explicit cast operators aren't exactly bread and butter C# coding knowledge, and may be confusing to those who come after you.
Edit:
Well, I answered too quickly without testing the idea, and this doesn't work for interfaces. However, see my other answer for another idea.
I would look into separating the implementation for all those types in different classes. You could start doing this by using an enum to represent the company type.
public enum CompanyType
{
Agent = 0,
Supplier
}
public abstract class Company : Entity<Company>
{
public CompanyIdentifier Id { get; private set; }
public string Name { get; private set; }
public CompanyType EntityType { get; private set; }
public abstract void Invoice();
public abstract void GetCommission(int month);
...
This way you get less public properties.
Next, I'd implement specialized classes for supplier and agent (and then for both and none). You can make Company abstract and any specialized methods abstract as well.
This will allow you to separate the distinct behaviors of each type of entity. Comes in handy when you get back to it for maintenance. It also makes the code easier read/understand.
public class SupplierCompany : Company
{
public SupplierCompany()
{
EntityType = CompanyType.Supplier;
}
public override void Invoice()
{...}
public override void GetComission(int month)
{...}
}
public class AgentCompany : Company
{
public AgentCompany()
{
EntityType = EntityType.Agent;
}
public override void Invoice()
{...}
public override void GetComission(int month)
{...}
}
With this you can eliminate testing for various types in methods like Invoice and GetComission.
As with most DDD questions, it usually boils down to Bounded Contexts. I'd guess you're dealing with some distinct bounded contexts here (this is most obvious from your statement "A company can be a agent or supplier or both or none."). In at least one context you need to consider all Company entities equally, regardless of whether they are Agents or Suppliers. However I think you need to think about whether or not your Invoice or GetCommission operations are applicable in this broader context? I'd say those will apply in more specialized contexts, where the distinction between an Agent and a Supplier is much more crucial.
You may be running into trouble because you're trying to create an all encompassing Company entity which is applicable in all contexts... this is almost impossible to achieve without weird code constructs & fighting against the type system (as is being suggested in your other answers).
Please read http://martinfowler.com/bliki/BoundedContext.html
As a rough idea of how your contexts might look:
Broad "Company" Context
{
Entity Company
{
ID : CompanyIdentifier
Name : String
}
}
Specialized "Procurement" Context
{
Entity Supplier
{
ID : CompanyIdentifier
Name : String
Invoice()
}
}
Specialized "Sales" Context
{
Entity Agent
{
ID : CompanyIdentifier
Name : String
GetComission()
}
}
Does it make sense to try and use the same object in both Procurement and Sales contexts? These contexts have very different requirements after all. One of the lessons of DDD is that we split the domain into these bounded contexts, and do no try to make "God" objects which can do everything.