Q: `Can Model Classes contain Methods, and Constructor ?" [BEST PRACTICE]
I have an employee Model class which consists of the Employee's name, age, salary etc...
public class Employee
{
public string Name { get; set; }
public int Age { get; set; }
public int Salary { get; set; }
}
so can the above Model Class contain some self updating methods [like updating the employee's age every 1 hour with a timer or something] and\or constructors or it is better to handle all that things from the executer ?
Why couldn't they? The real answer is: it depends on your use case. Patterns, such as something being a model class, are recommendations, common ways of doing things, not unbreakable dogmas.
Note: The example “updating the employee's age every 1 hour with a timer or something” is fundamentally wrong. Storing age is fundamentally wrong, unless you are storing a snapshop to some moment in time. A much better solution would be to store date of birth, and compute the age. For example, by defining an Age property with a getter only.
A model should contain all logic related to the model (this is DSL) so, yes it can update itself each hour. and when u define auto properties, it's same as defining setters and getter, so of course you can add methods, and constructors as well.
Let me put my 2 cents here.
I will start with this: It can be dangerous
There is nothing wrong with adding simple CRUD-like methods in your models, but... it thins the layer of separation between your model and your business logic.
I've many times witnessed these methods getting 'enhanced' over time and at some point ending up with logic which does not fit the purpose of a model. The result: hard dependency between your 'model' and your 'controller'.
It's not that it is wrong, but it opens 'portals' which someone can abuse.
If you want to have a more strict architecture, you can consider adding your operations in a 'Manager-like' class:
Car {
string type;
int price;
}
CarManager {
public CarManager(Car car) {...}
public ChangePrice(...) {...}
public ChangeType(...) {...}
}
... the manager class can now apply validations, exception handling, logging etc, without the concern that it violates your architecture.
Conclusion:
Yes, you can add simple CRUD operations in your model.
Concern: mind their usage.
Edit:
Missed that there is an ask to "updating the employee's age every 1 hour with a timer or something".
In my book this is a no no :). The model's purpose should be limited to data storage only. Periodically updating information is a pure business logic operation.
It all depends on how the class is being used.
There is nothing in the language that does not allow it. But depending on what frameworks you are using and how you are using the classes in your code as to where to put different pieces of functionality.
There is no best answer for every situation.
Related
This problem is a bit hard to expose via the title so I hope the following clarifies my intentions a bit.
Suppose you have the following data classes:
class abstract Employee {
string ID;
}
class FullTimeEmployee : Employee {
string schedule;
}
class PartTimeEmployee : Employee{
string schedulePartTime;
}
class WheelsSpecialist : Employee{ }
class InteriorsSpecialist : Employee{ }
class Workshop {
WheelsSpecialist wheely_guy;
InteriorsSpecialist interiors_guy;
}
Now, suppose that I instantiate my workshop as follows:
var Workshop = new Workshop{
wheely_guy = new PartTimeEmployee(),
interiors_guy = new FullTimeEmployee();
}
Please assume that the structure / inheritance and instantiations here provided are immutable.
What I'd like is to generate an ID set on Employee.ID that survives the runtime and is consist and independent from class properties / developer implementation.
Understand also that: The path of each object property in the workshop instantiation is guaranteed to be UNIQUE.
As so, a good ID for the WheelsSpecialist in Workshop.wheely_guy would be "Workshop.wheely_guy". (for example) because no path will ever be the same when I'm instantiating the workshop.
When I access the object "Workshop.wheely_guy.ID" I'd like to have "Workshop.wheely_guy" there or something analogous.
I imagine something like this would work (non valid C#, logic intact):
class PartTimeEmployee {
//instantiationPath is for example, "Workshop.wheely_guy"
onCreate(string instantiationPath){
this.ID = instantionPath;
}
}
I've tried this with StackTrace and whatnot, but couldn't find a way of doing it right.
Whether this instantiationPath method is used or not, the solution requires that:
I get to keep my structure as is in the example EXCEPT for properties. Those can change.
When I want to add a new dimension to my workshop variable I CAN'T, as a developer, be responsible for awarding a class it's own unique property.
As so, doing something like "this.ID = wheels" manually is not an option (also, depending this ID on properties that the developer must implement is also not viable).
Can this be done some way that meets my demands?
Thank you!
The provided code does not compile, and the object design/inheritance used seems a bit off. You probably want to work on the abstractions themselves. But that is not what you asked (mainly). It's kind of hard to figure out what exactly you asked, but I will do my best to answer what I think you asked (mostly):
"I want a field of an object instance to contain an automatically calculated navigation path by which it is accessible in some collection or composite object unrelated to the object itself" -> while close to impossible in C#, this might be entirely/easily possible in other languages. Still, the concept itself seems a little off.
The premise here is that the Employee object does not and should not know about the Workshop object Think about part-time employees trying to work separate shifts in separate workshops at the same time, and other possible changes in the business logic regarding Employees and Workshops.
Let's walk through some of the possibilities, ordered by viability:
Doing some magic at constructor/instantiation time in the abstract constructor code (Stack Frame walking, callerMember tricks, Reflection?, AST parsing?)
At instantiation, in a constructor, the stack trace does not contain information about which property/field it is about to be assigned to (if at all for that matter, it might just need to be instantiated, not assigned to anything). So there is no way to set such an id at constructor time.
Doing some magic in the Id property getter
There is no way to pass in parameters to a property getter, so we run into the same type of problem as with option 1: the stack trace contains no useful information by the time the getter is accessed.
Make the Employee object know about Workshop
No, just no.
Some weird runtime/weaving magic to "calculate" these paths when they are accessed?
Maybe, but how much effort to put in and to what purpose?
Expression parsing in a separate method:
//Left out the non-compiling code.
public static void Main(string[] args)
{
var Workshop = new Workshop
{
WheelsGuy = new PartTimeEmployee(),
InteriorsGuy = new FullTimeEmployee()
};
Console.WriteLine(GetObjectAccessPath((_) => Workshop.WheelsGuy));
}
public static string GetObjectAccessPath(Expression<Func<Workshop, Employee>> member)
{
string body = member.Body.Reduce().ToString();
// the line below might take some tweaking depending on your needs
return body.Substring(body.IndexOf($"{nameof(Workshop)}"));
}
// Output: Workshop.WheelsGuy
Use Reflection in a separate method to "get" a list of properties that are of any type derived from Employee and based on that Generate a list of ids with something like properties.Select(p => $"Workshop_{p.Name}");
Most viable: Re-design the object model:
(This is my opinion, and the requirements of your project might be different. Even if I am speculating here, the same principles presented here would apply in many other ways).
Extract more abstractions, like Position, Role, and Schedule. Part-time would be a schedule. Wheels guy would be a role. Position would be "an employee that fulfills the role of wheels guy at a workshop." There might be more examples (pay by hour/week/month, tax exemption, etc.).
As a rule, holding too many concerns in one class is a code smell and will get you in trouble quick. You can choose to carve up the classes however you want, but for what you "seem" to want, this part is important: have a class that represents the relationship between employee and workshop.
For example, instead of the Workshop holding instances of Employees: the Position class would hold/know about an Employee, his Role, his Schedule, and the Workshop he works at. The Position's Id could then easily be Id => $"Workshop_{Role}"; or Id => $"{WorkShop}_{Role}", etc. As a bonus, you get the design bonus of the Workshop being free from knowing which types of employees it might hold.
In general, I'd suggest you look into SOLID principles, it's an eye opener.
Consider below class being updated in database
public class ProductionLineItem
{
public int Id { get; set; }
public DateTime ProductionDate { get; set; }
public string HandledBy { get; set; }
public DateTime DateToMarket { get; set; }
}
void UpdateProductionRecord(ProductionLineItem existingRecord, ProductionLineItem modifiedRecord)
{
existingRecord.Id = modifiedRecord.Id;
existingRecord.ProductionDate = modifiedRecord.ProductionDate;
existingRecord.HandledBy = modifiedRecord.HandledBy;
existingRecord.DateToMarket = modifiedRecord.DateToMarket;
}
Customer wants to keep a log of all changed properties in dedicated table.
I should be doing something like this:
void UpdateProductionRecordWithLog(ProductionLineItem existingRecord, ProductionLineItem modifiedRecord)
{
existingRecord.Id = modifiedRecord.Id;
if (existingRecord.ProductionDate != modifiedRecord.ProductionDate)
{
existingRecord.ProductionDate = modifiedRecord.ProductionDate;
//Log: productionDate update form xyz to abc
}
if (existingRecord.HandledBy != modifiedRecord.HandledBy)
{
existingRecord.HandledBy = modifiedRecord.HandledBy;
//Log: HandledBy updated from Mr. John to Mr. Smith
}
if (existingRecord.DateToMarket != modifiedRecord.DateToMarket)
{
existingRecord.DateToMarket = modifiedRecord.DateToMarket;
//Log: DateToMarket updated form 2013 to 2014
}
}
For small number of properties it should be fine, but if properties goes beyond 15-20. I believe this would not be best way to do it.
Can I make my code more clean? I am open to use any framework like AutoMapper or so, If needed.
There are multiple elegant solutions to your problem, some of those include:
You could use Aspect Oriented Programming (AOP, for frameworks see this answer) to capture every modification to a property. You could save those changes for later retrival or invoke events which are then logged.
You could put Reflection (e.g. PropertyInfo) to good use here and iterate over all properties and compare the current value. This will spare you from writing all properties by hand.
Reflection and Attributes in conjunction with the Properties which are needed to be logged will work too. Using Attributes as a kind of post-it note on those properties which are important to be logged.
Be aware that Reflection might impose some performance penalities.
Do you use Entity Framework? It supports INotifypropertychanged, which could be used:
How to raise an event on Property Change?
If not, your classes could implement INotifyPropertyChanged() themselves - while not great (you have to write geteers / setters explicitly), it provides a better decoupling than invoking a loggin facility in the Properties directly (what if, if your logging is not available).
I would be worried about performance issues, so I might store logs and only write once in a while...
Well first you've done more than the requirement, in that you are only changing Existing item's properties if they are different.
Adding some new method to your class e.g. LogDifferences(ProductLineItem old, ProductLineItem new) and calling it from UpdateProductionItem would be good.
Personally I'd being going back to the Customer and saying what are you really trying to do and why, what they asked for smacks more of solution than requirement.
E.g. just log old record new record, like a DB transaction log. Do the an analysis of what changed when it's required.
One last possiblilty, that admittedly might cause more problems than it solves, is storing the values of the properties in say a Dictionary<String,dynamic> instead of discrete members.
Then logging changes based on Existing["ChangedToMarket"] = Modified["ChangedToMarket"] is fairly trival.
I'm trying to port a years old MS Access app with spaghetti VBA code to C# and OOP, and I'm struggling to find the best way to put domain logic in my domain classes.
I'll use a Country class as a simple example. It has three properties with different business rules:
CountryCode can't be changed anymore once the country is created, because that would cause issues with a 3rd party app that uses the countries
CountryName can be changed anytime, without any underlying logic or business rules
IsoCode can be changed anytime, but must be exactly 2 characters long
(IsoCode has actually more rules, but in this example let's just assume that "must be exactly 2 characters" is the only rule, for the sake of simplicity)
I created two slightly different versions of the class.
I'm quite inexperienced in object-oriented programming, so I need help deciding:
does it matter which approach I use?
does one of them (or both) have issues that I don't see?
is there a different way that's even better?
Both of my approaches look good to me now, but I don't know if maybe they will cause problems later (the app in question is ten years old, and will probably live on for a long time).
Version 1:
public class Country1
{
public string CountryCode { get; private set; }
public string CountryName { get; set; }
public string IsoCode { get; private set; }
public Country1(string countryCode, string countryName, string isoCode)
{
this.CountryCode = countryCode;
this.CountryName = countryName;
SetIsoCode(isoCode);
}
public void SetIsoCode(string isoCode)
{
if (isoCode.Length != 2)
{
throw new ArgumentException("must be exactly 2 characters!");
}
this.IsoCode = isoCode;
}
}
Version 2:
public class Country2
{
public Country2(string countryCode, string countryName, string isoCode)
{
this.countrycode = countryCode;
this.CountryName = countryName;
this.isocode = isoCode;
}
private readonly string countrycode;
private string isocode;
public string CountryCode
{
get { return this.countrycode; }
}
public string CountryName { get; set; }
public string IsoCode
{
get { return this.isocode; }
set
{
if (value.Length != 2)
{
throw new ArgumentException("must be exactly 2 characters!");
}
this.isocode = value;
}
}
}
Some more background about why I'm asking this and what I want to know:
I have read lots of different opinions about the "right OOP way".
Some say that you shouldn't expose getters and setters at all. I understand why this is a bad idea with setters, that's why CountryCode can only be set from the constructor.
Some say that instead of using any getters and setters, you should use GetXXX and SetXXX methods. I can see that this makes sense in some cases (for example, a SetXXX method with several parameters when you have several values that need to be set together).
But often there are simple values like the CountryName in my example, which is a "dumb" value without any logic. When I have ten of these things in one class, I don't want to create GetXXX and SetXXX methods for each of them.
Then there's stuff like the IsoCode, which has no connection to any of the other properties either (so no need to use a SetXXX method to set it together with another property). But it contains some validation, so I could either make a SetXXX method, or just do the validation (and throw an exception when something is wrong) in the setter.
Is throwing an exception even the best way to notify the caller of an error? Some say it's fine, and some say that you should throw exceptions only for "exceptional" cases.
IMO it's not really exceptional when someone enters an invalid ISO code, but how else should I get the information that an error occured (including a human readable error message!!) to the client? Is it better to use a response object with an error code and a ErrorMessage string property?
Personally I don't think there is much difference between the property and method implementation. I have a preference for using properties when the values can be set independently. I use setter methods to force more than one value to be provided to your model at the same time when the values depend on each other in some way (e.g. you are setting integers x and y and y cannot be larger than x).
It makes a lot of sense to have simple validation logic (e.g. required fields, fields lengths) in your view-model because this allows you to tie the validation more closely to the user interface (e.g. you could highlight the field that was invalid after it had been filled in).
For WPF Validation see: http://www.codeproject.com/Articles/97564/Attributes-based-Validation-in-a-WPF-MVVM-Applicat
For MVC Validation see: http://www.codeproject.com/Articles/249452/ASP-NET-MVC3-Validation-Basic
I'd strongly recommend this article by Eric Lippert about what kind of condition makes a good candidate for throwing/catching an exception:
http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx
I tend to use properties for single value changes and SetXXX methods rarely when I have some rule that involve more than one value that must be set at a time too (just like Andy Skirrow said).
SetXXX methods for everything are a common "Javaish" convention (althrough its used in many languages that don't have setters and getters like C#).
People try to force some good practices they learned for some language into every language they can, even if it did not fit necessarily well or the language have better alternatives for that.
Try not to be an "OOP maniac". This will only cause you pain in the head. OOP is not a religion (and even religion should not have fanatics IMHO, but this is another story).
Back to the point
The two approaches makes no functional difference and will not cause any harm in the future. Take the way you fill its more readable and pleasant to code. This will count much more than "the correct OOP way", cause many people have its own definition for the "better way" of doing things.
Validation
If you are using some structural or architectural pattern like MVC, you can use Data Annotation Attributes to enforce validation and, depending on the framework, use it to enforce client side validation as well.
See #Andy Skirrows's answer for links.
I've built an open source application, and I'd be curious to know how others are handling customer-specific requests. It's important to me to keep the app simple; I'm not trying to make it all things for all people. Apps can get bloated, complex, and just about unusable that way. However, there are some customer-specific options that would be nice (it just wouldn't apply to all customers). For example...
Say we have a domain entity called Server. In the UI, we let a customer pick from a list of servers. For one company, it's helpful to filter the servers by location (US, Germany, France, etc...). It would be easy enough to add a server property like this:
public class Server
{
public Location Location { get; set; }
// other properties here
}
My concern is that Server could become bloated with properties over time. And even if I only add location, not all customers would care about that property.
One option is to allow for user-defined fields:
public class Server
{
public string UserField1 { get; set; }
public string UserField2 { get; set; }
public string UserField3 { get; set; }
// etc...
// other properties here
}
Is that the best way to handle this? I don't like the fact that type safety is gone by making everything a string. Are there other/better ways that people are handling issues like this? Is there even a design pattern for something like this?
In my opinion, a good design pattern for something like this is to use schemas at the database level and then basic inheritance at the class level.
CREATE TABLE dbo.A (
ColumnA INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
ColumnB VARCHAR(50),
ColumnC INT,
etc.
)
And now we have a client who needs some specific functionality, so let's create an extension to this table in a different schema:
CREATE TABLE CustomerA.A (
ColumnA INT NOT NULL PRIMARY KEY,
Location VARCHAR(50)
)
But now we have another client who needs to extend it differently:
CREATE TABLE CustomerB.B (
ColumnA INT NOT NULL PRIMARY KEY,
DataCenterID INT
)
Though the fields may not be relevant, you get the idea, and so now we need to build the customer specific domain models here:
public abstract class A
{
public int ColumnA { get; set; }
public string ColumnB { get; set; }
public int ColumnC { get; set; }
}
public class CustomerA_A : A
{
public string Location { get; set; }
}
public class CustomerB_A : A
{
public int DataCenterID { get; set; }
}
And so now when we need to build something for Customer A, we'll build their subclass, and for Customer B theirs, and so on.
Now, FYI, this is the beginnings of a very dynamic system. I say that because the piece that's missing, that's not yet dynamic, is the user-interface. There is a significant number of ways that can be accomplished, but way outside the scope of this question. That is something you'll have to consider. I say that because the way you manage the interface will determine how you even know to build which subclass.
I hope this has helped.
The usual approach early on is to use the config XML files for this sort of thing. But programming for client-specific needs requires a whole mindset around how you program. Refer to this answer to a similar question.
Of course it always depends on how much customization you want to allow. In our product we went as far as enabling users to completely defined their own entities with properties and relations among them. Basically, every EntityObject, as we call our entities, in the end consists of a value collection and a reference to a meta-model describing the values within them. We designed our own query language that allows us to query the database and use expressions that are translate-able to any target language (although we currently only do SQL and .net).
The game does not end there and you quickly find that things like validation rules, permissions, default values and so on become a must have. Of course all of this then requires UI support, at least for the execution of the meta-model.
So it really depends on the amount of adjustment a end-user should be able to perform. I'd guess that in most cases simple user fields, as you described, will be sufficient. In that case I would provide a single field and store JSON text within that. In the UI you can then provide at least a semi-decent UI allowing structure and extensibility.
Option 1: Say "no". :-)
And while I say that (half) jokingly, there is some truth to it. Too often, developers open themselves up to endless customization by allowing one or two custom features, setting the snowball in motion.
Of course, this has to be balanced, and it sounds like you may be doing this to an extent. But if you truly want to keep your app simple, then keep it simple and avoid adding customizations like this.
Option 2: Inheritance.
If you really need to add the customization, I would lean the way of building a base class with all "standard" options, and then building customer-specific classes containing customer-specific optimizations.
For example:
public class Server
{
// all standard properties here
}
Then for Joe's Pizza, you can have:
public class JoesPizzaServer : Server
{
public Location Location { get; set; }
}
The side-benefit to this is that it will allow you to base your presentation views off of the client-specific (or base) models.
For example, in MVC you could set up your view models like this, and then you could have specific views for each customer.
For example, Bob's Burgers would have its own view on the base model:
#model MyApp.Server
#* implement the base form *#
And Joe's Pizza's view would use the custom model:
#model MyApp.JoesPizza
#* implement the base form -- a partial view -- with addtional custom fields
MVC does a really good job of supporting this type of pattern. If you're not using MVC (maybe WPF or Web Forms), there are still ways to leverage partial "view" files for accomplishing something similar.
Of course, your database can (and probably should) support a similar inheritance model. Entity Framework even supports various inheritance models like this.
I may be wrong here, but it looks like you want to handle different versions of your software with the same code base. I can think of two approaches for this:
Actually define different versions for it and handle changes for each client. This won't give you problems from the domain-modeling point of view, but will require a supporting infrastructure, which will have to scale according to your client requirements. There are some related questions out there (e.g. this, this and this).
Handle this at the domain-model level, as a user-defined configuration. The advantage of this approach is that you don't have to incorporate multiple versions of your software, but this comes at the expense of making your model more generic and potentially more complex. Also your tests will surely have to be adapted to handle different scenarios. If you are going in that direction I would model an object representing the attribute (with a name and a value) and consider the Server class as having a collection of attributes. In that way your model still captures your requirements in an OO style.
HTH
I approach from Python that I think would work rather well hear is a dictionary. The key is your field name, the value is the, errrrr... value ;)
It'd be simple enough to represent in a database too.
I'm new to domain driven design and would like to hear your thoughts on a design decision:
In my domain, I have the entities "voyage" and "booking".
The constructor for voyage looks like this:
public Voyage(VoyageNumber voyageNumber,
Schedule schedule,
IList<VoyagePrice> voyagePrices,
Location location,
Capacity capacity)
The value objects "voyagePrices" contain information about the price for a certain person type (child, adult, etc.). The capacity contains the maximum number of persons allowed on the voyage.
The constructor for the "Booking" looks like this:
public Booking(BookingNumber bookingNumber,
Customer customer,
Voyage voyage,
IList<ConfirmedPerson> confirmedPersons)
confirmedPersons contains the list of persons one customer wants to book (i.e. 2 adults, 1 child). Now, it is of course required to check the capacity of the voyage before allowing the booking to be saved. I dont think that "voyage" should contain a list of all the bookings made. Would it be okay to check the capacity in a BookingService or in a BookingFactory? Do you have any suggestions, maybe with a small code snippet? Thank you!
It completely possible and valid to have an available capacity be part of a Voyage or a boolean encapsulation like
Voyage.isFull()
Upon retrieval of a specific voyage aggregate from a VoyageRepository this information could be obtained.
However it's not enough, there's always a chance the voyage fills up after you've retrieved it from the VoyageRepository. So you will need to handle that exceptional case, maybe like
public interface BookingService {
Booking book(BookingRequest br) throws VoyageIsFullException;
}
And you'd probably want a BookingRequestFactory
public class BookingRequestFactory {
public static BookingRequest create(Voyage v, Customer c, IList<Person> travelers)
}
BookingRequestFactory can do some basic validation but not all cause the logic of whether it's full or not will probably require collaboration beyond what'd you'd want in a Object Factory, and is probably best handled by a BookingService.
if i anderstood you right you have to connect the two entities. I would suggest you do it just like it would be done in a relational database. Browse to this link: relational database design and read the paragraph: "Many-to-Many Relationships", i think this could be a solution :-)