My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}
Related
I've been trying to figure out how to do the following (although my research did not help): I have the these three classes:
public abstract class Classifier
{
public int ClassifierId { get; set; }
public string ClassifierName { get; set; }
public DateTime DateAdded { get; set; }
}
public class ManualClassifier : Classifier
{
public int ManualClassifierId { get; set; }
public string user_name { get; set; }
public string userName { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string email { get; set; }
public string password { get; set; }
}
public class ToolClassifier : Classifier
{
public int ToolId { get; set; }
public string ToolName { get; set; }
}
Both the ManualClassifier and ToolClassifer inherit from Classifier. I'm using EF Core to map this to a database but the question is the following: I've already searched a bit and I must make use of a descriminator which basically is an implicitly created column that will say the type of, in this case, classifier. So far so good. The issue arises when I have a property called ManualClassifierId as well as a ToolId. I want this two properties to map to the ClassifierId property. So in the table representing the entity Classifier, the ClassifierId property will either be the ManualClassifierId or the ToolId.
How can I achieve this mapping? Also, this solution would mean that both child classes would both have empty fileds in the tables (due to inheriting the three properties from the Classifier class). Is there a better solution? Perhaps just erase the Id's from both child classes a let them inherit the parent one?
Thank you in advance!
To use the same column name in both classes, you can add a Column attribute to both properties. Then they will both use that column name in the database. See ColumnAttribute(String).
Use it like this:
public class ManualClassifier : Classifier
{
[Column(Name="ClassifierId")]
public int ManualClassifierId { get; set; }
...........
}
Do the same with ToolId.
We're attempting to build a somewhat basic reporting system for our analytics team to use. It's our third or fourth iteration of the same system, but we're doing a consolidation and rewrite of a large portion of the backend logic to make generating reports easier going forward.
One issue we're having is forming the interfaces that will be implemented by our reporting widgets in order to push them through to our ViewComponents.
An example of a couple widgets may look something like the following:
public interface IWidget<T>
{
WidgetType WidgetType { get; set; }
string WidgetName { get; set; }
T ViewModel { get; set; }
}
public class ChartWidget : IWidget<Chart>
{
public WidgetType WidgetType { get; private set; }
public string WidgetName { get; set; }
public Chart ViewModel { get; set; }
public ChartWidget() {
WidgetType = WidgetType.Chart;
}
}
public class HeadlineBarWidget : IWidget<HeadlineBarData>
{
public WidgetType WidgetType { get; private set; }
public string WidgetName { get; set; }
public HeadlineBarData ViewModel { get; set; }
public ChartWidget() {
WidgetType = WidgetType.HeadlineBar;
}
}
But the report will contain a collection of widgets, and that collection will need to be iterated over in the View in order to fetch the proper ViewComponents and supply them with the matching model that they expect. Unfortunately, it appears most collection types need to ensure type safety, and I need a way to make this a bit better. As it stands now, our IWidget object defines ViewModel as an object, and I don't think this is a good practice.
I'm unsure how to go about implementing this particular idea of I have a class lets call it EnhancedUserInput that will have some variables that all of the input types will have and a particular subclass depending on the need during operation so some extra variables and a list so for example sub classes of it would be MultipleChoice which would have MinSelection, MaxSelection and a list of a type called option with their own variables ect and then another possible sub class called ExplicitAgreement which would have the variables inputLabel1, inputLabel2 and a list of type BinaryInput which would have their own variables.
So far from what I understand the best way going about this would be to have some type of generic variable? I'll show some code to try and help get what it is I need across but was just wondering is there an easy way of doing this that I am unaware of?
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set}
// this is where I am unsure of how to go about it
public object inputType
{
MultipleChoice
ExplicitAgreement
}
}
public class MultipleChoice
{
public List<MultipleChoiceOption> Options { get; set; }
public int MinSelected { get; set; }
public int MaxSelected { get; set; }
}
public class ExplicitAgreement
{
public List<BinaryInputOption> Buttons { get; set; }
public string InputLabel1 { get; set; }
public string InputLabel2 { get; set; }
}
what would be the best path for this solution I can think of some possible ways but they would be a bit figity and was wondering if there are any simple ways?
Seems to me that you may have this the wrong way around. Maybe what you want is to just use class inheritance?
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set}
}
public class MultipleChoice : EnhancedCustomerInput
{
public List<MultipleChoiceOption> Options { get; set; }
public int MinSelected { get; set; }
public int MaxSelected { get; set; }
}
public class ExplicitAgreement : EnhancedCustomerInput
{
public List<BinaryInputOption> Buttons { get; set; }
public string InputLabel1 { get; set; }
public string InputLabel2 { get; set; }
}
Steve Harris's inheritance suggestion is good. Your original option to use Composition can work just fine, too:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public object InputData { get; set; }
}
The only problem is that consumers of your code need to know that InputData can be one of several different types, and you presumably need logic to switch on their type. You can add comments to the property to give people a hint, or you can use a library like LanguageExt, which provides an Either type:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public Either<MultipleChoice, ExplicitAgreement> InputData { get; set; }
}
This makes it much more obvious which types InputData can be, but would get very unwieldy if you have more than two possibilities.
You could also declare an interface that InputData must implement, which would make it easier for developers to find all the types that are intended to be used there. But an empty interface is considered to be a code smell because it indicates you're using interfaces for something they weren't really intended for.
Another option I've found to work well is to define an enum type to help identify which different types of input data you can have:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public InputType InputType { get; set; }
public object InputData { get; set; }
}
public enum InputType { MultipleChoice, ExplicitAgreement }
This gives your business logic a specific set of possible types that you can switch your logic on, and works particularly well when the class is going to be serialized and deserialized, because then you can tell the deserializer which specific type of object to deserialize InputData to.
There are lots of options, each with their advantages and disadvantages.
I am currently working towards learning "Domain Driven Design".
I'm wondering how someone would design these entities. I simplified the object model as it would take to long to explain the "REAL" application to highlight the area of the domain I'm having trouble with.
So a CustomerInfo aggregate contains a list of Entries. It's this "Entry" object I'm having trouble designing.
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
/* Other properties removed, to simplify question */
public List<Entry> Entries { get; set; }
}
The Entry object "can" be described by a few different lists of entities. The caveat here is the "Entry" can "ONLY" be described by one of these lists. In my domain it does not make sense for an entry to have a list of Widgets AND a list of ThisThings.
To complicate things.
The entities Trinket, ThatThing, ThisThing and TheOtherThing all have the same properties, but in the context of this domain their meaning is very different.
This is my current domain model. Which I do not like as I have all this validation to make sure only one of the lists are populated by the user
public class Entry
{
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
public List<Widget> Widget { get; set; }
public List<Trinket> Trinkets { get; set; }
public List<ThatThing> ThatThings { get; set; }
public List<ThisThing> ThisThings { get; set; }
public List<TheOtherThing> TheOtherThings { get; set; }
}
public class Widget
{
public Guid Widgetid { get; private set; }
public string Name { get; private set; }
public int Size { get; set; }
public string Color { get; set; }
}
public class Trinket
{
public Guid Trinketid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThatThing
{
public Guid ThatThingid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThisThing
{
public Guid ThisThingid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class TheOtherThing
{
public Guid TheOtherThingId { get; private set; }
public string Name { get; private set; }
public Construction Construction { get; private set; }
}
public class Construction : ValueObject<Construction>
{
public int Size { get; private set; }
public string Weight { get; private set; }
public string Unit { get; private set; }
public string Form { get; private set; }
}
What I'm struggling with is how to model this "Entry" entity properly.
1) Should I keep as designed and just rely on this crazy validation.
2) Should I be creating a polymorphic model to handle these?
public interface IWidget{
public Guid Widgetid { get; set; }
}
public interface IDifferentWidget:IWidget
{
public decimal Cost { get; set; }
public Construction Construction { get; set; }
}
public class Widget:IWidget
{
public Guid WidgetId { get; private set; }
public string Name { get; private set; }
public int Size { get; set; }
public string Color { get; set; }
}
public class Trinket : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThatThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThisThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class TheOtherThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
Then the Entry entity would look like, but does not prevent a ThisThing and ThatThing being added to the same Entry List.
public class Entry
{
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
public List<IWidget> Widgets { get; set; }
}
3) Should I create different Entry entities entirely like WidgetEntry, ThisThingEntry with a common interface so the Aggregate Root would look like so:
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
/* Other properties removed, to simplify question */
public List<IEntry> Entries { get; set; }
}
Considering the different options I've contemplated,the only solution that tackles this domain constraint "Entry" can "ONLY" be described by one of these lists is #3
Any guidance would be greatly appreciated, apologizes for the long winded question!
/*******************************REVISED DOMAIN DESIGN ***********************/
I still believe an CustomerInfo should be the aggregate because in my domain it makes sense to describe the CustomerInfo by the various entries users add to it to build a "CustomerInfo" entity.
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
public Guid CustomerId { get; private set; }
private List<Entry> _entries;
public IEnumerable<Entry> Entries => _entries;
private CustomerInfo(Guid customerId /* Other properties removed, to
simplify question */){ }
public CustomerInfo Create(/* Other properties removed, to simplify
question */) {
return new CustomerInfo(Guid.NewGuid());
}
/*This is how the entity will control the state of the various lists of
entities that describe it.*/
public Entry UpdateEntry(/* Parameters removed for simplicity */) {
}
public Entry AddEntry(/* Parameters removed for simplicity */) {
}
public Entry RemoveEntry(/* Parameters removed for simplicity */) {
}
}
public class Entry {
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
private List<Widget> _widgets;
public IEnumerable<Widget> Widgets => _widgets;
private List<Trinket> _trinkets;
public IEnumerable<Trinket> Trinkets => _trinkets;
private List<ThatThing> _thatThing;
public IEnumerable<ThatThing> ThatThings => _thatThing;
private List<ThisThing> _thisThings;
public IEnumerable<ThisThing> ThisThings => _thisThings;
private List<TheOtherThing> _theOtherThing;
public IEnumerable<TheOtherThing> TheOtherThings => _theOtherThing;
private Entry(guid EntryId /*This constructor will take more parameters,
it's simplified for my question*/) { }
//Create a new instance of a Entry entity
public Entry Create(/* Parameters removed for simplicity */) {
return new Entry(Guid.NewGuid());
}
//This is how the entity will control the state of the various lists of
entities that describe it.
public Widget UpdateWidget() {
}
public Widget AddWidget() {
}
public Widget RemoveWidget() {
}
private bool CanAddAWidget() {
/* Logic to prevent a widget from being add if any of the other
lists have items*/
}
public ThisThing UpdateThisThing()
{
}
public ThisThing AddThisThing()
{
}
public ThisThing RemoveThisThing()
{
}
private bool CanAddAThisThing()
{
/* Logic to prevent a widget from being add if any of the other lists
have items*/
}
}
The problem is that you haven't designed a proper Aggregate root - a tactical Domain driven design pattern.
In your case, Entry should be an Aggregate root that ensures its own invariants. The invariant that I've identified is that Entry should not have only one kind of Thing added to its internal list. So, your code should reflect that invariant.
That being said, the Entry should have an private list of things, implemented as separate lists or just one mixed list, depending on the list/lists usage. That will prevent the client code to add items to the list without any verification. Then the Aggregate should have a addThing public method (replace that name with a more proper name from your Ubiquitous language). This method must verify the said invariant and reject any duplicates.
To use or not an abstraction depends not on DDD but on the usage of the Things. Ask yourself: does this abstraction help me to follow the OOP principles (see SOLID)? In your case is not clear because I don't know how you use those things inside the Aggregate or in the client code.
The short answer is that you can't abstract away your question like this. For example what makes a Widget and a ThisThing so simmilar that they can be listed together but a ThatThing can't be?
Just consider it like this
class Dog: IMamal {
}
class Cat: IMamal {
}
interface IMamal : IAnimal {
}
class Chicken : IAnimal {
}
Here i found that Dogs and Cats are simmilar in that if i talk about animals that i would refer to those kind of animals as mamals.
So talk to your domain expert and try to figure out what certain groups of things are called. That way you can define an interface that groups certain things together but not others
If you can't find a way why they belong together in by talking to your domain expert then it's a good bet they should be 2 separate lists.
Polimorphism should really only follow if your domain really describes it that way. If i take my animal example a Mamal might have a Walk() method and a Bird might have a Fly() method and a Hop() method (if a birt doesn't fly)
There might not be polymorphic Move() method since no biologist would describe that an animal moves, they always refer to it as either walking or flying (just for the sake of argument here, it should be the domain expert who describes entities as all having a "Name" and not the programmer who sees that "Name" "Label" and "Description" are the same kind of fields. (As Mike pointed out conincidental coheision is the thing to avoid here)
I have four MVC model layer domain classes.
namespace MvcMobile.Models.BusinessObject
{
public class Speaker
{
public int SpeakerID { get; set; }
public string SpeakerName { get; set; }
}
public class Tag
{
public int TagID { get; set; }
public string TagName { get; set; }
}
public class Seminar
{
public string Seminar_Code { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Room { get; set; }
}
public class Seminar_Detail
{
public string Seminar_Code { get; set; }
public int SpeakerID { get; set; }
public int TagID { get; set; }
public string DateAndTime { get; set; }
}
}
I would like to make CRUD operation by using these classes. So I create two VeiwModel Classes.
namespace MvcMobile.ViewModel
{
public class Seminar_Root_ViewModel
{
public Seminar_Subsidiary_ViewModel Seminars { get; set; }
public List<Speaker> Speakers { get; set; }
public List<Tag> Tags { get; set; }
}
public class Seminar_Subsidiary_ViewModel
{
public Seminar Seminar { get; set; }
public List<Seminar_Detail> Seminar_Detail { get; set; }
}
}
For Controller layer, I consider that I will use Seminar_Root_ViewModel to make the whole CRUD operation processes.
What I would like to ask is that Is this proper way or correct way?
If you have more elegant way to make model layer and ViewModel layer, Please let me get suggestion.
Every suggestion will be appreciated.
[updated]
Let's assume that I make master-Detail form design.
Speaker and Tag are just look-up tables for dropdownlist or some controls like that.
Seminar is Master Data and Seminar_Detail will be Item Grid Data.
So As for this scenario, all of this classes are needed for this program.
Please let me know if my thinking is wrong.
The only thing I can see is if you are not going to re-use your Seminar_Subsidiary_ViewModel view model you could skip it.
If you are going to need those two properties Seminar and Seminar_Detail on another view or ajax call, it's perfectly fine to have that kind of separation.
Personally I'm not a huge fan of _ on class name, but that have nothing to do with the question.