Where do you store "generic" class methods? - c#

So let's say I have an Person entity:
PERSON
ID
FirstName
LastName
SSN
LastModifiedDate
After this table exists in the database, and is part of my .edmx file, I usually create a partial class for the entity to use to perform some object-specific work. For example, with the Person entity I might have an UpdateLastModifiedDate() method which would simply set the value for the LastModifiedDate field to the present date and time for the selected object.
My question, however has to do with more "generic" methods, that don't relate to any specific object. For example, let's say I wanted to create a GetPersonBySSN() method which would accept a SSN and return the Person object with that SSN (if it exists). Where would I store this method?
I couldn't store it in the partial class (could I?) because I would have to do something odd like this:
Person myPerson = db.Person.where(u => u.ID = 12345);
Person myPerson2 = myPerson.GetPersonBySSN(123456789);
It just doens't make sense to do it this way.
Also, I am reluctant to create a second static class to store these "generic" methods (like maybe a PersonGenericMethods class) because it feels like I should be able to do this with only the main class, Person.
Where would you store these "generic" methods?
Edit: I am using ASP.NET MVC and would like recommendations on how to best build using this.

Also, I am reluctant to create a second class to store these "generic" methods (like maybe a PersonGenericMethods class) because it feels like I should be able to do this with only the main class, Person.
How a bout a PersonRepository class? That class would be responsible for interacting with the underlying Person data store - getting, updating, deleting, etc.
What you seem to want is called the Active Record Pattern
where entity classes are responsible for creating, updating, and deleting themselves. While that's more common in other platforms like Ruby, in most .NET architectures the separation of the entity from the repository is more common.
The more separation you have (entities, repositories, business logic, UI logic, etc.) the more flexibility and re-usability you have. That comes, however, at the price of additional complexity.

The repository-pattern is perfect for this.
Do keep in mind that you are programming OO. It is strange to get the person from 'itself'.
A repository will get your data and return your desired result.
on a side-note:
Person myPerson = db.Person.where(u => u.ID = 12345);
Person myPerson2 = myPerson.GetPersonBySSN(123456789);
Is strange, first, you get the person where ID = ... and then as function on the person you want to make sure that ssn is the same number?
your repo would look like this:
public class PersonRepository
{
private readonly DBContext _myContext'
public PersonRepository(DBContext myContext)
{
_myContext = myContext; //<== Dependency INjection
}
public function Person GetBySSN(int ssn)
{
return _myContext.FirstOrDefault(p => p.ssn = ssn);
}
}
take a look at:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
just gives a good basis.
and then for later improvements: can you look into Maybe and Results types, but if your new to this, forget it :)
enjoy!

Related

Inheritance: why is changing an object's type considered bad design?

While modelling my domain classes, I found that Entity Framework lets you model inheritance relationships, but doesn't support promoting a base type instance to its derived type, i.e. changing an existing Person row in the database to an Employee, which derives from Person.
Apparently, I wasn't the first to wonder about this, because this question has been asked and answered on Stack Overflow multiple times (e.g. see here and here).
As indicated in these answers, Entity Framework doesn't support this because this isn't allowed in Object-Oriented Programming either: once an instance is created, you cannot change its run-time type.
Fair enough, from a technical perspective I can understand that once a single block of memory is allocated for an object, tacking on a few extra bytes afterwards to hold the derived type's fields in will probably require the entire memory block to be reallocated, and as a consequence, will mean that the object's pointer has now changed, which in turn introduces even more problems. So I get that this would be difficult to implement, and therefore not supported in C#.
However, aside from the technical component, the answers (and here too, see final paragraph on page 1) also seem to imply that it is considered bad design when you want
to change an objects run-time type, saying that you shouldn't need this kind of type-changing and should use composition for these situations instead.
Frankly, I don't get why - I'd say its perfectly valid to want to work Employee instances in the same way as you would with a Person instance (i.e. by inheriting Employee from Person), even if at some point in time a Person will be hired as an Employee, or an Employee quits and becomes a Person again.
Conceptually, I don't see anything wrong with this?
Can anyone explain this to me?
--Edit, to clarify, why is this considered bad design:
public class Person
{
public string Name { get; set; }
}
public class Employee: Person
{
public int EmployeeNr { get; set; }
public decimal Salary { get; set; }
}
...but this isn't?
public class Person
{
public string Name { get; set; }
public EmployeeInfo EmployeeInfo { get; set; }
}
public class EmployeeInfo
{
public int EmployeeNr { get; set; }
public decimal Salary { get; set; }
}
Frankly, I don't get why - I'd say its perfectly valid to want to work
Employee instances in the same way as you would with a Person instance
(i.e. by inheriting Employee from Person), even if at some point in
time a Person will be hired as an Employee, or an Employee quits and
becomes a Person again. Conceptually, I don't see anything wrong with
this?
I understand this as Person -> Employee -> Person? IE it is still a person but he/she/it gets attributed with "employment" and then "downgraded" to just a person?
Inheritance is very useful when the object does not change type during runtime, for example when you create an equity-object you can be quite sure you do not want to turn it into an FRA, even though both are subclasses of securities. But whenever something might change during runtime, such as behaviour, try using composition instead. In my previous example, the security subclasses might inherit from a top-level asset class, but the methods used for putting a market value on an asset should be put there by a behavioral pattern, such as the strategy pattern, since you might want to use different methods during one runtime.
For the case you are describing you should not use inheritance. Always favor composition over inheritance whenever possible. If something changes during runtime, it should definitely not be put there by inheritance!
You could compare it to lives, a human is born a human and dies a human, a cat is born a cat and dies a cat, an object of a certain type should be created as one type and garbage collected as the same type. Don't change what something is, change how it behaves or what it knows, through behavioral composition.
I would recommend you to have a look at Design Patterns: Elements of Reusable Object-Oriented Software which quite thoroughly covers some very useful design patterns.
Consider this code:
Person person = new Person { Name = "Foo" };
Person employee = new Employee { Name = "Bar", EmployeeNr = 42 };
However employee is declared as Person, the actual instance it is referring to is of type Employee. This means you can cast it to that:
Employee employee2 = (Employee)employee;
When you try that with person:
Employee employee3 = (Employee)person;
You'll get an exception in runtime:
Unable to cast object of type 'Person' to type 'Employee'.
So you're right in that this is a technical impossibility, as C# is implemented. You can work around it though, by creating a constructor in Employee:
public Employee(Person person, int employeeNr, decimal salary)
{
this.Name = person.Name;
EmployeeNr = employeeNr;
Salary = salary;
}
As you see, you'll have to instantiate the Person part of the Employee yourself. This is tedious and error-prone code, but now we come to your actual question: why could this be considered a inferior design?
The answer lies in favoring composition over inheritance:
Composition over inheritance (or Composite Reuse Principle) in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes that implement the desired functionality instead of through inheritance.
The essence:
To favor composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long term. In other words, HAS-A can be better than an IS-A relationship.
To keep in the terms of your real-world example: in the future, we might have to employ Androids, who definitely don't inherit from Person, but could use a EmployeeInfo record.
As for your Entity Framework specific question:
I'd say its perfectly valid to want to work Employee instances in the same way as you would with a Person instance (i.e. by inheriting Employee from Person), even if at some point in time a Person will be hired as an Employee, or an Employee quits and becomes a Person again.
If, for now, you know you're only going to employ humans (don't forget YAGNI), I cannot imagine an example where this issue would come up. When you want to show all persons, you iterate that repository:
using (var context = new MyContext())
{
foreach (var person in context.Persons)
{
PrintPerson(person);
}
}
And when you want to list all employees, you do exactly the same, but with the Employee repository:
using (var context = new MyContext())
{
foreach (var Employee in context.Employees)
{
PrintEmployee(Employee);
}
}
And if in some cases you want to know whether someone is an employee, you'd have to hit the database again:
public Empoyee FindEmployeeByName(string name)
{
using (var context = new MyContext())
{
return context.Employees.FirstOrDefault(e => e.Name == name);
}
}
Which you can then call using a Person instance:
Empoyee employee = FindEmployeeByName(person.Name);
You are over-analyzing this. Polymorphism is very well supported in .NET and there's never any way that you can unsafely upcast, a friendly InvalidCastException is always there to remind you that you got it wrong. It can even be safely done in C++ (dynamic_cast<>), not exactly a language well-known for a lack of ways to shoot your leg off.
The runtime support for it is the key. Dbase engines don't have any.
It was the playground for venture capital around the turn of the century. Already flowing freely thanks to the dot com boom. Objected oriented databases where promised as jet-packs for everybody. But that busted too, none of them ever close to being dominant. Ever heard of Gemstone, db4o, Caché, odbpp? Competing with existing engines is a tall task, performance and reliability is everything in that market segment and it is very hard to catch up to 20 years of fine-tuning. So there was just no point in adding support for it in a data access layer.

getter , setter c#

i have got various custom datatypes in my web application to map some data from the database.
something like:
Person
Id
Name
Surname
and i need a List of persons in most of my application's pages
i was thinking to create a getter property that gets the list of persons from the database and store into cache in this way i do not have to call the database each time
something Like (pseudo code)
public List<Person> Persons
{
get { return if cache != null return List of Persons from cache else get from the database;}
}
Where shall i put this getter? in my Person class definition or into my base page( page from which all the others pages inherit)
Thanks
I think putting it in your base page would be better option.
Depending on your application architecture, putting process related code in your domain classes might be an issue. Some use it in DDD (domain-driven design) type applications though.
Better even, I usually try to hide those implementation details in a service class. You could have a PersonService class that would contain your above method and all person related operations. This way, any page requiring person information would simply call the PersonService; and you can concentrate your page code on GUI related code.
I don't think that you should put it in your Person class since it accesses the database and HttpContext.Current.Cache. Furthermore I think you should make it a method and not a property, to imply that this may be a "lengthy" operation. So, of the two options, I would put it on the base Page class.

Constructive criticism on this class

I've just reviewed some code that looked like this before
public class ProductChecker
{
// some std stuff
public ProductChecker(int AccountNumber)
{
var account = new AccountPersonalDetails(AccountNumber);
//Get some info from account and populate class fields
}
public bool ProductACriteriaPassed()
{
//return some criteria based on stuff in account class
//but now accessible in private fields
}
}
There has now been some extra criteria added which needs data not in the AccountPersonalDetails class
the new code looks like this
public class ProductChecker
{
// some std stuff
public ProductChecker(int AccountNumber)
{
var account = new AccountPersonalDetails(AccountNumber);
var otherinfo = getOtherInfo(AccountNumber)
//Get some info from account and populate class fields
}
public bool ProductACriteriaPassed()
{
//return some criteria based on stuff in account class
// but now accessible in private fields and other info
}
public otherinfo getOtherInfo(int AccountNumber)
{
//DIRECT CALL TO DB TO GET OTHERINFO
}
}
I'm bothered by the db part but can people spell out to me why this is wrong? Or is it?
In a layered view of your system, it looks like ProductChecker belongs to the business rules / business logic layer(s), so it shouldn't be "contaminated" with either user interaction functionality (that belongs in the layer(s) above) or -- and that's germane to your case -- storage functionality (that belongs in the layer(s) below).
The "other info" should be encapsulated in its own class for the storage layers, and that class should be the one handling persist/retrieve functionality (just like I imagine AccountPersonalDetails is doing for its own stuff). Whether the "personal details" and "other info" are best kept as separate classes or joined into one I can't tell from the info presented, but the option should be critically considered and carefully weighed.
The rule of thumb of keeping layers separate may feel rigid at times, and it's often tempting to shortcut it to add a feature by miscegenation of the layers -- but to keep your system maintainable and clean as it grows, I do almost invariably argue for layer separation whenever such a design issue arises. In OOP terms, it speaks to "strong cohesion but weak coupling"; but in a sense it's more fundamental than OOP since it also applies to other programming paradigms, and mixes thereof!-)
It seems like the extra data grabbed in getOtherInfo should be encapsulated as part of the AccountPersonalDetails class, and thus already part of your account variable in the constructor when you create a new AccountPersonalDetails object. You pass in AccountNumber to both, so why not make AccountPersonalDetails gather all the info you need? Then you won't have to tack on extra stuff externally, as you're doing now.
It definitely looks like there might be something going haywire with the design of the class...but it's hard to tell without knowing the complete architecture of the application.
First of all, if the OtherInfo object pertains to the Account rather than the Product you're checking on...it's introducing responsibilities to your class that shouldn't be there.
Second of all, if you have a Data Access layer...then the ProductChecker class should be using the Data Access layer to retrieve data from the database rather than making direct calls in to retrieve the data it needs.
Third of all, I'm not sure that the GetOtherInfo method needs to be public. It looks like something that should only be used internally to your class (if, in fact, it actually belongs there to begin with). In that case, you also shouldn't need to pass around the accountId (you class should hold that somewhere already).
But...if OtherInfo pertains to the Product you're checking on AND you have no real Data Access layer then I can see how this might be a valid design.
Still, I'm on your side. I don't like it.
considering that an accountNumber was passed into the constructor you shouldn't have to pass it to another method like that.
A few points
The parameter names are pascal case, instead of camel (this maybe a mistake)
getOtherInfo() looks like it's a responsibility of AccountPersonalDetails and so should be in that class
You may want to use a Façade class or Repository pattern to retrieve your AccountPersonalDetails instead of using a constructor
getOtherInfo() may also be relevant for this refactor, so the database logic isn't embedded inside the domain object, but in a service class (the Façade/Repository)
ProductACriteriaPassed() is in the right place
I would recommend this:
public class AccountPersonalDetails
{
public OtherInfo OtherInfo { get; private set; }
}
public class ProductChecker
{
public ProductChecker(AccountPersonalDetails) {}
}
// and here's the important piece
public class EitherServiceOrRepository
{
public static AccountPersonalDetails GetAccountDetailsByNumber(int accountNumber)
{
// access db here
}
// you may also feel like a bit more convinience via helpers
// this may be inside ProductCheckerService, though
public static ProductChecker GetProductChecker(int accountNumber)
{
return new ProductChecker(GetAccountDetailsByNumber(accountNumber));
}
}
I'm not expert in Domain-Driven Design but I believe this is what DDD is about. You keep your logic clean of DB concerns, moving this to external services/repositories. Will be glad if somebody correct me if I'm wrong.
Whats good. It looks like you have a productChecker with a nice clear purpose. Check products. You'd refactor or alter this because your have a need to. If you don't need to, you wouldn't. Here's what I would probably do.
It "feels" clunky to create a new instance of the class for each account number. A constructor argument should be something required for the class to behave correctly. Its a parameter of the class, not a dependency. It leads to the tempation to do a lot of work in the constructor. Usage of the class should look like this:
result = new ProductChecker().ProductACriteriaPassed(accountNumber)
Which I'd quickly rename to indicate it does work.
result = new ProductChecker().PassesProductACriteria(accountNumber)
A few others have mentioned that you may want to split out the database logic. You'd want to do this if you want unit tests that are fast. Most programs want unit tests (unless you are just playing around), and they are nicer if they are fast. They are fast when you can get the database out of the way.
Let's make a dummy object representing results of the database, and pass it to a method that determines whether the product passes. If not for testibility, this would be a private. Testability wins. Suppose I want to verify a rule such as "the product must be green if the account number is prime." This approach to unit testing works great without fancy infrastructure.
// Maybe this is just a number of items.
DataRequiredToEvaluateProduct data = // Fill in data
// Yes, the next method call could be static.
result = new ProductChecker().CheckCriteria(accountNumber, data)
// Assert result
Now we need to connect the database. The database is a dependency, its required for the class to behave correctly. It should be provided in the constructor.
public class ProductRepository {} // Define data access here.
// Use the ProductChecker as follows.
result = new ProductChecker(new ProductRepository()).CheckCriteria(accountNumber)
If the constructor gets annoyingly lengthy (it probably has to read a config file to find the database), create a factory to sort it out for you.
result = ProductCheckerFactory().GimmeProductChecker().CheckCriteria(accountNumber)
So far, I haven't used any infrastructure code. Typically, we'd make the above easier and prettier with mocks and dependency injection (I use rhinomocks and autofac). I won't go into that. That is only easier if you already have it in place.

Creating an object that has all the properties of two other objects?

Consider a sports club situation.
A club can have a Club manager and 1 or more Coaches (1 coach per team)
So, here is an example of the Manager and Coach classes.
Class ClubManager
{
public void RegisterMember()
{
// code for registering a member..
}
}
Class Coach
{
public void DeviceTeamFormation()
{
// code for making a team formation..
}
}
My issue is, how can I have a Club manager who is also a Coach? because there are sports clubs with this situation.
Appreciate any and all help.
Thanks guys.
No, you cannot do this with classes. Interfaces however get you in that direction.
On the other hand, you may want to add another level of indirection and separate the manager and coach roles from persons, so that you can assign each role to a person (which may also be the same person).
Lucero's second paragraph is the correct approach. Coach and Manager are not kinds of people, they are roles that people play. Theoretically the same person could be a TeamPlayer, TeamCaptain, Coach, Manager, and WaterBoy!
So what you want is composition, not inheritance. For example:
SportsClub myClub = new SportsClub();
Person Bill = new Person();
myClub.Manager = new Manager(Bill);
myClub.Coach = new Coach(Bill);
Being a Coach and being a ClubManager are not inherent attributes of this person. They are roles that the person has taken on. As such I would say that the person object (or whatever it is you want to call it) should be assigned roles. Those role/ability objects would then delegate those methods.
So it might look like this:
Person joe = new Person("joe");
joe.setClubManager(true);
joe.getManagerAbilities().RegisterMember();
Hard to know what is right without a lot more information about your problem, but maybe this will get you thinking along some different line.
Multiple Inheritance is what you are looking for. Unfortunately, this is not currently supported in C#. I did not see it come up in the 2010 version either.
You can implement multiple interfaces, but you cannot inherit from multiple classes.
As Chinmay Kanchi noted, C# does not support multiple inheritance; however, you can inherit from a type and implement as many interfaces as you like.
public interface ICoach {
}
public class ClubManager : SomeType, ICoach {
}
I would use delegation rather than inheritance and use the Composite Pattern instead. (http://en.wikipedia.org/wiki/Composite_pattern)
you can do this but with following procedure as C# does not support Inheritance through classes
Interface IClubManager
{
public void RegisterMember();
}
Interface ICoach
{
// code for making a team formation..
}
class SomeDesignation : ICoach, IClubManager
{
}
As others have noted, you can't do that with classes, although you can do it with interfaces, which has the disadvantage that you have reimplement the interface each time. One way around that is with mixins: Is it possible to implement mixins in C#?.
You can not have exactly what you want - multiple inheritance is not supported in C#.
Along with the other proposals about using interfaces (with their limitations), you can possibly re-think the object model at all.
If you separate your data structure (classes), so the Coach class and the ClubManager class has property Person, they you will not "duplicate" the person's data. And you can have factory methods to create Coach out of person, and/or ClubManager out of person.
Another option would be to have "InRole" functionality, which says what role a person can have, and the Person class will have both methods you require, but each one of them may throw an exception if the person is not in the right role to perform the operation.
Or, you can inject "roles", and use some form of indirection to access the specific role's functionality.
Here's the first idea that popped into my head:
Create a ClubManagerCoach class, or something to that effect that has logic for both managers and coaches.
Create interfaces for IClubManager and ICoach. Use those interfaces in place of ClubManager and Coach.
Make ClubManagerCoach implement IClubManager and ICoach.
I think the best compromise you'll get in this case (and this is a debated topic, of course) is to create something along the lines of a ClubManagerCoach class that exposes ClubManager and Coach properties.

Should one extend or encapsulate ORM objects?

I'm having trouble understanding how to use ORM generated objects. We're using LLBLGen for mapping our database model to objects. These objects we encapsulate in another layer which represents our business model(I think).
Maybe this bit of code will explain this better.
public class Book { // The class as used in our application
private BookEntity book; // LLBLGen entity
private BookType bookType; // BookType is another class that wraps an entity
public Book(int Id) {
book = new BookEntity(Id);
}
public BookType BookType {
get { return this.bookType; }
set {
this.bookType = value;
this.book.BookType = new BookTypeEntity(value.ID);
this.book.Save();
}
}
public int CountPages() { } // Example business method
}
Exposing the entity's fields like properties feels awkward, since I'm mapping all over again. With list-types it's even much worse, since I have to write a "Add" and "Remove" method plus a property that exposes List.
In the above example in the BookType setter I need access to the BookTypeEntity object, I can get this object by instantiating a new one using the ID oh the BookType object. This also doesn't feel good.
I'm wondering if I shouldn't just extend the BookEntity object and add my business logic there? Or maybe use partials?
In the LLGLGen examples they use the entity objects directly, but this looks very messy to me. I want to have objects which can also have methods for my business logic(like CountPages) in the code above.
I've never used LLBLGen for mapping, but most of the ORM tools I've worked with generate partial classes. I then add any custom code/logic I'd like to add to those objects in a seperate file (so they don't get over-written if the partial classes are re-generated).
Seems to work pretty well. If you don't get partial classes from your ORM, I'd create a Facade which wraps your Data Object with your Business Logic...that way the two are seperated and you can re-gen one without overwriting the other.
UPDATE
Partial classes support implementing an Interface in one declaration of a partial class and not the other. If you want to implement an interface, you can implement it in your custom code partial file.
Straight from MSDN:
partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }
is equivilant to
class Earth : Planet, IRotate, IRevolve { }
Dunno if it's possible in LLGLGen, but what I generally do when working with ORMs is to create an interface to the persisted class, in your example IBook. I expose this interface via a public getter from the wrapping class. This way, if needs will be, you can extend you IBook the way you want if you need to add some custom behaviour to its fields.
Generally speaking, I think there's 3 ways of "mapping" your ORM-entities to your domain:
The way you've posted. Basically, remap everything again
The way I posted, expose the ORM-entity as an interface
Expose the ORM-entity directly
I don't like #1, cause I don't like to have 2 mappings in my application. DRY, KISS and YAGNI are all violated by this.
I don't like #3 cause it would make whatever consumer-layer of your domain-layer talk directly to the ORM layer.
.. So, I go with #2, as it seems to be the lesser of 3 evils ;)
[Update] Small code snippet :)
ORM-generated class in the data-layer:
public class Book : IBook
{
public string ISBN {get; private set;}
}
IBook is found in the business-logic layer, along with a book wrapper:
public interface IBook
{
string ISBN {get;}
}
public class BookWrapper //Or whatever you want to call it :)
{
//Create a new book in the constructor
public BookWrapper()
{
BookData = new Data.MyORM.CreateNewBook();
}
//Expose the IBook, so we dont have to cascade the ISBN calls to it
public IBook BookData {get; protected set;}
//Also add whichever business logic operation we need here
public Author LookUpAuther()
{
if (IBook == null)
throw new SystemException("Noes, this bookwrapper doesn't have an IBook :(")
//Contact some webservice to find the author of the book, based on the ISBN
}
}
I don't know if this is a recognizable design-pattern, but it's what I use, and so far it has worked quite well :)
You are feeling the pain of the mismatch between the different paradigms of relational data and objects.
By this, I mean that the worlds of relational data and objects are very, very different from each other. For example, in database-land all data is public. In object-land, data is encapsulated and very specifically not made public. In database-land, all relationships are bi-directional, whereas in object-land an object in a collection might not have any reference to its parent. In database-land, procedures are global. In object-land, procedures are local to the object which contains the acted-upon data.
For these reasons and more, an approach which creates objects that represent database tables is inherently going to be painful. While yes, technically they are objects, they have the semantics of database-land. Making them live in object-land, as you have experienced, is difficult if not impossible. This can be referred to as data-first.
A better approach (in my opinion) is to focus on mapping objects to the database, rather than mapping the database to objects. This can be referred to as object-first, and is supported very well by NHibernate. This approach emphasizes the fact that a database is an implementation detail of a system, not a design precept.
I realize this doesn't specifically answer your question, but I hope it provides some context as to why you are having a hard time conceptualizing your entities: they are tables first and entities second.

Categories

Resources