If I have a class defined as:
public class Car{
public int doors {get;set}
public int wheels {get;set}
public string make {get;set}
public string model {get;set}
public Car(){}
}
And I want to create a collection of this class. In the past I have understand it was acceptable to create a collection class:
public class CarCollection{};
That would return a collection of Cars.
With Generic List now I understand that we should not be creating collection classes, but instead creating generic list of the object inheriting some collection type.
My question is where should this code go, and what definition should the method have? For example should I just add a public method to my car class:
public List<Car> GetAllCars()
{
...
}
If so, it seems weird to instantiate a Car Class to get a collection of cars, but I know declaring it as a shared class isn't the right option either. How should we be designing our collections of classes, and where should we be including them?
It all depend how you want to use the collection of the cars. But in the scenario you mentioned in the comment, I would suggest looking into repository pattern, which would be an intermediate layer between the business logic and database.
So you would have you Car class as a model, and a repository e.g.: CarRepository. This repository would have a method for returning the list of all your cars. All the logic for populating this list would be in that class, and it would not pollute other places of the application and increase maintainability of the code.
public class CarRepository {
public List<Car> GetAllCars() {
// read data from DB and return list
}
public Car GetSingle(int carId) {
// here you just return single car
}
}
This is just to give you an idea how this might be done. Going further you can extend this concept introducing interfaces for easy testing and swapping implementations for the repository. You could then have single interface, with multiple implementations - one for reading from DB and e.g. second one for reading from XML file.
There is a lot of reading material regarding that on the Internet.
Related
Let's say I have an interface like this:
public interface IUser
{
int Id { get; }
string Name { get; }
List<IMonthlyBudget> MonthlyBudget { get; }
}
and then I have a model that implements this:
public class User : IUser
{
public int Id { get; set; }
public string Name { get; set; }
public List<IMonthlyBudget> MonthlyBudget { get; set; }
}
and here I have the IMonthlyBudget:
public interface IMonthlyBudget
{
int Id { get; }
float MonthlyMax { get; }
float CurrentSpending { get; }
float MonthlyIncome { get; }
}
Now I have my models. But the issue comes with using SQLite. SQLite can't understand what is the real implementation of IMonthlyBudget. I understand why, but I really don't want remove the interface and expose the real implementation to all the clients that use these models. In my project structure I have a Core project that has all the model interfaces, and the model implementation are in a data access project.
Is there something wrong with how I'm approaching this problem? I assume i'm not the first one to run into a issue like this. Isn't it completely normal practice to keep model interfaces (what repositories etc then use as their return types, parameters and stuff like that) and implement the actual concrete models in a data access project?
And can someone explain why I can't do this:
public class User : IUser
{
public int Id { get; set; }
public string Name { get; set; }
public List<MonthlyBudget> MonthlyBudget { get; set; }
}
MonthlyBudget implements IMonthlyBudget, shouldn't it be completely fine to use the concrete model as the type instead of the the interface when the concrete model actually implements the interface?
A few questions here, so I'll break it down into sections:
Use of Interfaces
It is definitely good practice to interface classes that perform operations. For example, you may have a data service (i.e. data access layer) interface that allows you to do operations to read and modify data in your persistent store. However, you may have several implementations of that data service. One implementation may save to the file system, another to a DBMS, another is a mock for unit testing, etc.
However, in many cases you do not need to interface your model classes. If you're using an anemic business object approach (as opposed to rich business objects), then model classes in general should just be containers for data, or Plain Old CLR Objects (POCO). Meaning these objects don't have any real functionality to speak of and they don't reference any special libraries or classes. The only "functionality" I would put in a POCO is one that is dependent only upon itself. For example, if you have a User object that has a FirstName and LastName property, you could create a read-only property called FullName that returns a concatenation of the two.
POCOs are agnostic as to how they are populated and therefore can be utilized in any implementation of your data service.
This should be your default direction when using an anemic business object approach, but there is at least one exception I can think of where you may want to interface your models. You may want to support for example a SQLite data service, and a Realm (NoSQL) data service. Realm objects happen to require your models to derive from RealmObject. So, if you wanted to switch your data access layer between SQLite and Realm then you would have to interface your models as you are doing. I'm just using Realm as an example, but this would also hold true if you wanted to utilize your models across other platforms, like creating an observable base class in a UWP app for example.
The key litmus test to determining whether you should create interfaces for your models is to ask yourself this question:
"Will I need to consume these models in various consumers and will those consumers require me to define a specific base class for my models to work properly in those consumers?"
If the answer to this is "yes", then you should make interfaces for your models. If the answer is "no", then creating model interfaces is extraneous work and you can forego it and let your data service implementations deal with the specifics of their underlying data stores.
SQLite Issue
Whether you continue to use model interfaces or not, you should still have a data access implementation for SQLite which knows that it's dealing with SQLite-specific models and then you can do all your CRUD operations directly on those specific implementations of your model. Then since you're referring to a specific model implementation, SQLite should work as usual.
Type Compatibility
To answer your final question the type system does not see this...
List<IMonthlyBudget> MonthlyBudget
as being type-compatible with this...
List<MonthlyBudget> MonthlyBudget
In our minds it seems like if I have a list of apples, then it should be type-compatible with a list of fruit. The compiler sees an apple as a type of fruit, but not a list of apples as a type of a list of fruit. So you can't cast between them like this...
List<IMonthlyBudget> myMonthlyBudget = (List<IMonthlyBudget>) new List<MonthlyBudget>();
but you CAN add a MonthlyBudget object to a list of IMonthlyBudget objects like this...
List<IMonthlyBudget> myMonthlyBudget = new List<IMonthlyBudget>();
myMonthlyBudget.Add(new MonthlyBudget());
Also you can use the LINQ .Cast() method if you want to cast an entire list at once.
The reason behind this has to do with type variance. There's a good article on it here that can shed some light as to why:
Covariance and Contravariance
I hope that helps! :-)
I've been working on learning how to use interfaces correctly in c# and I think I mostly understand how they should be used but still feel confused about certain things.
I want to create a program that will create a CSV from Sales Orders or Invoices. Since they are both very similar I figured I could create an IDocument interface that could be used to make a CSV document.
class Invoice : IDocument
{
public Address billingAddress { get; set; }
public Address shippingAddress { get; set; }
public Customer customer { get; set; }
public List<DocumentLine> lines { get; set; }
// other class specific info for invoice goes here
}
I can create a method CreateCSV(IDocument) but how would I deal with the few fields that differ from Sales Orders and Invoices? Is this a bad use of interfaces?
You don't inherit interfaces, you implement them; and in this case the interface is an abstraction; it says "all things that implement this interface have the following common characteristics (properties, methods, etc)"
In your case, you have found that in fact Invoices and Sales Orders don't quite share the exact same characteristics.
Therefore from the point of view of representing them in CSV format, it's not a great abstraction (although for other things, like calculating the value of the document, it's an excellent one)
There are a number of ways you can work around this though, here are two (of many)
Delegate the work to the classes
You can declare an ICanDoCSVToo interface that returns the document in some kind of structure that represents CSV (let's say a CSVFormat class that wraps a collection of Fields and Values).
Then you can implement this on both Invoices and Sales Orders, specifically for those use cases, and when you want to turn either of them into CSV format, you pass them by the ICanDoCSVToo interface.
However I personally don't like that as you don't really want your Business Logic mixed up with your export/formatting logic - that's a violation of the SRP. Note you can achieve the same effect with abstract classes but ultimately it's the same concept - you allow someone to tell the class that knows about itself, to do the work.
Delegate the work to specialised objects via a factory
You can also create a Factory class - let's say a CSVFormatterFactory, which given an IDocument object figures out which formatter to return - here is a simple example
public class CSVFormatterLibrary
{
public ICSVFormatter GetFormatter(IDocument document)
{
//we've added DocType to IDocument to identify the document type.
if(document.DocType==DocumentTypes.Invoice)
{
return new InvoiceCSVFormatter(document);
}
if (document.DocType==DocumentTypes.SalesOrders)
{
return new SalesOrderCSVFormatter(document);
}
//And so on
}
}
In reality, you'd might make this generic and use an IOC library to worry about which concrete implementation you would return, but it's the same concept.
The individual formatters themselves can then cast the IDocument to the correct concrete type, and then do whatever is specifically required to produce a CSV representation of that specialised type.
There are other ways to handle this as well, but the factory option is reasonably simple and should get you up and running whilst you consider the other options.
I'm a relative newbie to C#, although I am a competent programmer, and I confess that I am totally confused as to whether or not it is a good idea to write custom collection classes. So many people seem to say "don't", yet there is a whole set of base classes for it in C#.
Here is my specific case. I have a timetable application. As part of that, I have a service class, and the service class contains collections of things service-y, such as route links. A route link is itself a custom class:
public class Service
{
public RouteLinks RL; // A collection of RouteLink types
...
}
public class RouteLink
{
public string FirstStopRef;
public string LastStopRef;
public Tracks RouteTrack; // Another collection, this time of Track types
}
So far I have looked at using Dictionary as the type for RouteLinks, because I need to be able to reference them. This is fine in principle. However, the process of adding a RouteLink to the RouteLinks collection involves checking to see whether it is already there, or whether it extends and existing route link, or... And for that, I need a custom Add function.
So why is is such bad practice to create custom collection classes? Why shouldn't I just inherit CollectionBase or DictionaryBase?
I should perhaps add that I am transferring this code from VBA [please don't shoot me :)] and there I HAD to implement custom collections.
Instead of having RouteLinks be a collection type, an easy solution would be to just define another class, let's say RouteLinksRepository. This class will contain a List<RouteLink> and the AddRoute(RouteLink) functionality as well as any other custom logic for interacting with this collection of RouteLink objects. Your service class will then just contain an instance of this repository class.
public class Service
{
public RouteLinksRepository RL; // A collection of RouteLink types
// ...
}
public class RouteLinksRepository
{
public List<RouteLink> RouteLinks;
public bool AddRoute(RouteLink linkToAdd)
{
//Custom logic on whether or not to add link
}
//Your other logic for the class
}
public class RouteLink
{
public string FirstStopRef;
public string LastStopRef;
public Tracks RouteTrack; // Another collection, this time of Track types
}
If the only need is to check on double entries, a HashSet will do (implement a GetHash and Equals). However I guess you are trying to save a route. A route has a order, which means you have a order and List<> garantees the order. Make the collection objects private to hide the implementation.
public class Service
{
private List<RouteLink> RL; // A collection of RouteLink types
...
}
public class RouteLink
{
public string FirstStopRef;
public string LastStopRef;
private List<Track> Tracks; // Another collection, this time of Track types
}
When a client application requests for a new object,
I let the Factory class create that new object for me.
public class CarFactory{
public Car CreateCar()
{
//create a new car object and send back
}
}
The properties of the car object are populated by calling stored procedures which are stored in the database. In the database, we store the default values which can change eachday. The default tables are populated by external systems.
public class Car {
public List<string> DefaultTyres {get;set;}
public List<string> DefaultPetrolSpec {get;set;}
}
So when the factory (which the service layer calls) creates the Car object, the factory class calls the repository class that then calls the DB to populate Car's properties...but the relation of these layers sounds a bit strange...
public Car CreateCar()
{
//create a new car object and send back
//Call CarRepository.GetDefaultTyres(), CarRepository.GetDefaultPetrolSpec() etc.
}
Because I think my factory implementation is doing a lot. May be it shouldn't call the repository layers (which then call the DB to get the data for the car object).
What do you guys think? Should Factory classes communicate with DB? Is it ok if they do? if not then whose responsibilities should it be?
The answer depends on whether there could be multiple (implementations of) repositories or multiple databases/other data stores involved. If the answer to the above is yes (even if it is just an anticipated need/possibility at this point), it is better to have a repository layer to insulate the Factory class from the above mentioned changes when/if those changes happen.
Think of it differently: it is the responsibility of the factory class to know how to create cars; it is not its responsibility to know what DB to connect to/when/how. It is usually better to kepp responsibilities simple to facilitiate change and modular design
One thing I've learned over time is that there may be 5 answers to your question. And, all of them would be right. The real question is: is what you are doing make sense? If your factory is on the server and the connection to the database is closest there, then that is where the calls should be.
Now I'd sometimes ask myself the same questions as well as others. For example, should the factory create the tyres and the Petrol for the car when creating the car, or should the car be the one to know how to create itself.
So you may want to consider this: if you have a vast array of objects that your factory is creating (which is usually why you have a factory pattern) then it may make sense that all of your elements have a base class / interface that exposes a Create method. (I'm posting a very quick and dirty example, doing reflection to create the type could keep the factory even more generic)
Example:
public interface FactoryObject
{
void Create();
void Destroy();
}
public class Car:FactoryObject
{
public void Create()
{
//TODO: Create my tyres and my petrol
//TODO: Create my fenders and body
}
}
public class Bicycle:FactoryObject
{
public void Create()
{
//TODO: Create my tyres but I do not need petrol
//TODO: Create my fenders but I have no body
}
}
public class Factory
{
public FactoryObject GetFactoryObject(Type type)
{
FactoryObject returnedObject = null;
if ( type is Car ) returnedObject = new Car();
elseif (type is Bicycle) returnedObject = new Bicycle();
if (returnedObject != null)
returnedObject.Create();
return returnedObject;
}
}
In this fashion your factory knows to create a FactoryObject, however it has no bound knowledge of HOW to build that object. More importantly it doesn't care.
If you have an additional class that handles the actual DB connection, I think it's fine. What I mean by such a class is one that performs the actual connection, handles some connection/query exceptions etc. The Factory class should not know DB-related stuff, it should delegate that to another class/object.
This abstraction layer to the DB can as well be a whole hierarchical tree of classes, not just a single class. Something like this:
Each of those subclasses knows how to handle a connection to that specific RDBMS.
PS: Note that this is just an example, you may not have to do it like this. Also, having such a hierarchy can complicate things a little, because it is possible that you need a Factory for these classes as well.
I am not sure if there is already a nomenclature for this, but for the sake of this question lets define two terms: peer implementation or nested implementation to illustrate how you implement collection classes in a data model that contains many parent/child entity relationships.
I use the term peer to describe the scenario where you implement the collection classes in your model layer along side with the entity classes essentially making them peers in your API like so:
public class ParentEntity
{
private ChildEntityCollection children;
}
public class ChildEntity
{
}
public class ChildEntityCollection : ICollection<ChildEntity>
{
}
The main advantage here is that you can reuse the collection class in other entity classes that happen to store children of the same type.
I use the term nested to describe the scenario where you implement them as a nested class like so:
public class ParentEntity
{
private ChildEntityCollection children;
public class ChildEntityCollection : ICollection<ChildEntity>
{
}
}
public class ChildEntity
{
}
The main advantage here is that each parent can implement their own collection class to store its children in manner that is most optimized for that specific parent. For example, one parent entity may find that an array data structure works well whereas another may use a splay tree (obscure I know, but it illustrates my point well).
I have noticed that Microsoft uses both idioms in the various .NET related frameworks. The System.Windows.Forms namespace seems to rely heavily on nested implementations. I tend to find myself prefering this method as well even though it requires more work.
Recommendations, comments, alternative ideas?
Regardless of what Microsoft might have done in the past, the current .NET API design guidelines discourage creation of nested classes that are visible outside their parent classes. See http://msdn.microsoft.com/en-us/library/ms229027.aspx for details.
Another option is to nest the collection class in the child class, and just name it Collection. That way, you always get Child.Collection as the name.
public class Child
{
public class Collection : ICollection<Child>
{
}
}
public class Parent
{
private Child.Collection children;
}
Personally I prefer the peer implementation, it promotes reuse of code which I don't think the nested implementation does. If another class needs to implement a different way of storing a collection of the same elements then another class can easily be implemented for that scenario without limiting code reuse.
A nested setup can also lead some developers to tightly couple their code to the parent class.
I also prefer the peer approach. There's really no reason to nest the collection unless you will never use it outside of its parent class (in that case, it should be a private nested class.)
I would only use the nested arrangement when there is only one Entity in the Domain model that can logically contain the child Entities.
For example if you had a PieceOfMail class and a MailPieces collection class
class PieceOfMail { }
class MailPieces: Collection<PieceOfMail> { }
then the ShipingCompany class, and the MailBox class, and the PostOffice Class, and the MailRoute class, and the MailManBag class, could ALL have a constituent property typed as MailPieces, so I'd use the "peer" technique.
But otoh, in the same Domain, if you had a class representing a type of PostageDiscount, and a collection class representing a set of discounts to be applied to a shipment, it might be the case that ONLY the ShipmentTransaction class could logically contain a collection of those discounts, then I'd use the nested technique...
Do you really need a ChildEntityCollection? Why not use a collection type that is provided?
//why bother?
//public class ChildEntityCollection : ICollection<ChildEntity>{}
public class ParentEntity
{
//choose one
private ChildEntity[] children;
private List<ChildEntity> childrenInList;
private HashSet<ChildEntity> childrenInHashSet;
private Dictionary<int, ChildEntity> childrenInDictionary;
// or if you want to make your own, make it generic
private Balloon<ChildEntity> childrenInBalloon;
}
public class ChildEntity
{
}
I generally try to avoid generating specific collection classes. Sometimes you may need a special class, but in many cases you can simply use generic classes like Collection<T> and ReadOnlyCollection<T> from the System.Collection.ObjectModel namespace. This saves a lot of typing. All your collections derive from IEnumerable<T> etc. and are easily integrated with LINQ. Depending on your requirements you could also expose your collections as ICollection<T> or another collection interface and then let classes with specific requirements use highly optimized generic collections.
public class ParentEntity {
Collection<ChildEntity> children = new Collection<ChildEntity>();
public Collection<ChildEntity> Children {
get {
return this.children;
}
}
}
You can also wrap an IList<T> like this:
public class ParentEntity {
// This collection can be modified inside the class.
List<ChildEntity> children = new List<ChildEntity>();
ReadOnlyCollection<ChildEntity> readonlyChildren;
public ReadOnlyCollection<ChildEntity> Children {
get {
return this.readOnlyChildren
?? (this.readOnlyChildren =
new ReadOnlyCollection<ChildEntity>(this.children));
}
}
}