I have a group of POCO classes:
class ReportBase
{
public string Name { get; set; }
public int CustomerID { get; set; }
}
class PurchaseReport : ReportBase
{
public int NumberOfPurchases { get; set; }
public double TotalPurchases { get; set; }
public bool IsVip { get; set; }
}
class SaleReport : ReportBase
{
public int NumberOfSales { get; set; }
public double TotalSales { get; set; }
}
I have a web method to return ReportBase. The caller uses the return value to update UI(WPF) based on the actually type by downcasting and checking the type (one grid for sale and one for purchase). Someone suggested to use three web methods and each return the specific type.
I understand that downcast is in general against design principle by introducing if/else. Instead we should use virtual functions. But in POCO class, we don't really have virtual behaviors (only extra fields).
Are you for or against downcast in this case, why?
IMO it's all about intention. Returning just the base class doesn't say anything, especially as you return it only to save some key strokes. As a developer what do you prefer?
ReportBase GetReport() // if type==x downcast.
//or
PurchaseReport GetPurchaseReport()
SaleReport GetSalesReport()
What approach would you want to use to make the code more maintainable? Checking type and downcasting is an implementation detail after all and you probably have a method like this
public void AssignReport(ReportBase report)
{
//check, cast and dispatch to the suitable UI
}
What's wrong with this? It's lacking transparency, and this method should always know about what reports are needed by what UI elements. Any time you add/remove an element you have to modify this method too.
I think is much clear and maintainable something like this
salesGrid.DataSource=repository.GetSalesReport();
purchaseGrid.DataSource=repository.GetPurchaseReport();
than this
var report=repository.GetReport();
AssignReport(report); //all UI elements have their data assigned here or only 2 grids?
So I think that, POCO or not, I will favour the three web methods approach.
Related
I have 3 classes
public class ActivityLog
{
// The activity log affects an employee
public int EmployeeID { get; set; }
public Employee Employee { get; set; }
// The activity log affects a department
public int DepartmentID { get; set; }
public Department Department { get; set; }
}
In this example there are two different object types that could be displayed on the view, but in reality there are much more types that differ and for which it doesn't seem sensible to move it to its own inheritance model.
I would like to be able to do the below:
public class ActivityLog<T>
{
// The activity log affects an unknown type
public T ConcernedObjectID { get; set; }
public T ConcernedObject { get; set; }
}
Right now we have a lot of null checks in our view (if employee is null then use department).
Is this something that entity framework can help with somehow, or would it be best to implement a code only solution (e.g. Interfaces)?
I think you have a design problem here. The ActivityLog class tries to do too much. Its both an entry in the log for an employee and for a department. Which are completely different things. The only thing they have in common is that they can be put into an activity log.
I would either use a common interface or an abstract base class. You can then use the asp.net equivalent of data templates to visualize the data.
So something like this:
public abstract class ActivityLogEntry
{
int Id { get; }
}
public EmployeeActivityLogEntry : ActivityLogEntry
{
Employee Employee {get;}
}
public DepartmentActivityLogEntry : ActivityLogEntry
{
Department Department {get;}
}
Another thing that can help you with null checks is to make it explicit that something can be null. I use the Optional NuGet package for that. This gives you something like this
Option<Employee> Employee {get; }
public string ToString()
{
return this.Employee.Match(e => e.Name, () => "");
}
In this case you cannot directly access the Employee that is captured in the Option. Instead you have to provide a Func for what to do when there is an Employee (its not null) and for when there isn't. There are a lot more helper functions in the optional library. It makes it a lot clearer that you need to handle both cases. You can no longer be surprised by something begin null.
(Of course you should not use Option<T> for everything. Only use it on properties that can sometimes be null. Not on properties that should never be null, or you start hiding bugs from yourself).
I am struggling to adhere to Liskov substitution principle when creating my class structure. I want to have a Collection of calendar items stored within a Day class. There need to be several different type of CalendarItems e.g:
AppointmentItem
NoteItem
RotaItem
they all share some common functionality which is presnt in the abstract base class CalendarItem:
public abstract class CalendarBaseItem
{
public string Description { get; private set; }
public List<string> Notes { get; private set; }
public TimeSpan StartTime { get; private set; }
public TimeSpan EndTime { get; private set; }
public int ID { get; private set; }
public DateTime date { get; private set; }
code omitted...
}
but then for example RotaItem has some extra functionality:
public class RotaItem : CalendarBaseItem
{
public string RotaName { get; private set; }
private bool spansTwoDays;
public bool spanTwoDays()
{
return this.spansTwoDays;
}
}
the other classes also add there own logic etc.
I have a collection of CalendarBaseItem for my day class:
List<CalendarBaseItem> calendarItems;
but on reviewing this I can see that I am breaking LSP principles as I have to check and cast each concrete type to get at the functionality that I desire for each subclass.
I would be grateful if someone could advise how to avoid this problem. Should I use a composition approach and add a CalendarItem class to each of the final classes e.g
public class RotaItem
{
private CalendarBaseItem baseItem;
public string RotaName { get; private set; }
private bool spansTwoDays;
public RotaItem(baseArgs,rotaArgs)
{
baseItem = new CalendarBaseItem(baseArgs);
}
public bool spanTwoDays()
{
return this.spansTwoDays;
}
}
The only problem here is that I will then need a seperate collection for each Concrete CalendarItem in my Day class?
I think what you're encountering is not so much a Liskov Substitution Principle violation as you are encountering a polymorphism limitation in most languages.
With something like List<CalendarBaseItem> the compiler is inferring that you're only dealing with CalendarBaseItem which obviously can't be true if CalendarBaseItem is abstract--but that's what a strongly-typed language does: It's only been told about CalendarBaseItem so that's what it limits usage to.
There are patterns that allow you to deal with this sort of limitation. The most popular is the double-dispatch pattern: a specialization of multiple dispatch that dispatches method calls to the run-time type. This can be accomplished by providing an override, that when dispatched, dispatches the intended method. (i.e. "double dispatch"). It's hard to associate exactly to your circumstances because of the lack of detail. But, if you wanted to do some processing based on some sort of other type for example:
public abstract class CalendarBaseItem
{
abstract void Process(SomeData somedata);
//...
}
public class RotaItem : CalendarBaseItem
{
public override void Process(SomeData somedata)
{
// now we know we're dealing with a `RotaItem` instance,
// and the specialized ProcessItem can be called
someData.ProcessItem(this);
}
//...
}
public class SomeData
{
public void ProcessItem(RotaItem item)
{
//...
}
public void ProcessItem(NoteItem item)
{
//...
}
}
which would replace something like:
var someData = new SomeData();
foreach(var item in calendarItems)
someData.ProcessItem(item);
Now, that's the "classical" way of doing in in C#--which spans all versions of C#. With C# 4 the dynamic keyword was introduced to allow run-time type evaluation. So, you could do what you want without having to write the double-dispatch yourself simply by casting your item to dynamic. Which forces the method evaluation to occur at run-time and thus will chose the specialized override:
var someData = new SomeData();
foreach(var item in calendarItems)
someData.ProcessItem((dynamic)item);
This introduces potential run-time exceptions that you'd likely want to catch and deal with--which is why some people don't like this so much. It's also currently very slow in comparison, so it's not recommended in tight loops that are performance sensitive.
I'm writing some code for importing files which will import either delimited or fixed width files based on a template that describes the file layout.
I've created an interface IFileTemplate:
public interface IFileTemplate
{
string Name { get; set; }
bool IgnoreEmptyLines { get; set; }
}
which is used by a DelimitedFileTemplate class and a FixedWidthFileTemplate class.
I also have an interface for specifying each of the columns that make up a template:
public interface IFileTemplateColumn
{
int ID { get; set; }
string Name { get; set; }
bool Ignore { get; set; }
}
This interface is then used by a DelimitedTemplateColumn class and a FixedWidthTemplateColumn class.
As both the DelimitedFileTemplate and FixedWidthFileTemplate classes will have a list of columns I've made the list a member of the IFileTemplate column:
List<IFileTemplateColumn> Fields { get; set; }
My problem is when I've come to implement the list in the DelimitedFileTemplate and FixedWidthFileTemplate classes, for example:
public class FixedWidthFileTemplate : IFileTemplate
{
public int ID { get; set; }
public string Name { get; set; }
public List<FixedWidthFileTemplateColumn> Fields { get; set; }
}
If I try and implement List<IFileTemplateColumn> with List<DelimitedFileTemplateColumn> or List<FixedWidthFileTemplateColumn> then the compiler complains that they don't match List<IFileTemplateColumn>.
I can understand this but it seems wrong not to have the column list in the ITemplateInterface. The only get around I can think of is to have the Delimited and FixedWidth classes use List<IFileTemplateColumn> and have the property getter cast the list to the delimited or fixed width column list but there seems a bit of code smell to that. Can anyone suggest a better way for doing this?
A suitable and not smelly solution to this design problem are generics:
interface IFileTemplate<T> where T : IFileTemplateColumn
{
List<T> Fields { get; set; }
}
DelimitedFileTemplate implements IFileTemplate<DelimitedFileTemplateColumn> and so on.
Perhaps all the differences between the file templates could be sensibly defined by IFileTemplateColumn only and you could simplify things with FileTemplate<IFileTemplateColumn> insted of one FileTemplate class per one FileTemplateColumn class relation.
Update
As for the factory method: IFileTemplate<IFileTemplateColumn> Create: if the consumers of this method are supposed to be able to access the list of columns, the method signature will have to contain the concrete ColumnTemplate. For example:
DelimitedFileTemplate Create
or
interface IFactory<T> where T : IFileTemplateColumn
{
IFileTemplate<T> Create();
}
class DelimitedFactory : IFactory<DelimitedFileTemplateColumn>
{
IFileTemplate<DelimitedFileTemplateColumn> Create()
{
return new DelimitedFileTemplate();
}
}
If the consumers of the method won't be interested in the list, introduce a more general interface (much like IEnumerable<T> : IEnumerable):
interface IFileTemplate { ... }
interface IFileTemplate<T> : IFileTemplate where T : IFileTemplateColumn
{
List<IFileTemplateColumn> Columns { get; set; }
}
Then your IFileTemplate Create() method could return any of the concrete FileTemplate regardless of the column.
I've worked with this kind of generics usage and they might tend to propagate (in this example Column hierarchy will be duplicated in FileTemplate hierarchy and might be duplicated in the factory hierarchy). Sometimes this reveals some flaws in the design. If you were able to sensibly cut the IFileTemplate hierarchy to one base parametrized FileTemplate class, this was certainly the way to go. This is how I often use this: define the smallest parts, if the hierarchy tends to duplicate, some parts of the algorithms can be perhaps moved to the 'smallest-parts-classes'.
I am trying to work out the best way to approach the following ..
i need to pass AvailabilityOption/LimitedAvailabilityOption types to - well a service as it happens, and then get back BookingOption types.
I have routines which will generate the availability types, but am unsure if i need to go through each of my Option objects effectively duplicating versions of them inheriting from BookingOption and AvailabilityOption in turn. or can I do some sort of 'Decoration' of the simple options with the availability classes and then cast them back down to booking ones when i pass them back again.
I know there is a decoration pattern but having read a bit about this it appears that it is more about decorating at runtime.. I may well be misunderstanding.
I suspect I havent explained this very well but here is some code..
EDIT: effectively the option is a base for a number of possible options on a booking - such as an excursion or some other extra, of which there are quite afew. the availability extends that to determine what space there is on any option, but it is just extending the option itself, with the price and possibly the numbers already booked on that option.
the BookingOption is there to be returned from the routine that effectively chooses from the options based on their price and availability. I am just trying to return the bare minimum at the booking point, which is really the date when the option is required and which option it is. the availability at this point is moot..
public abstract class Option{
public int OptionID { get; set; }
public OptionType OptionType { get; set; }
public string EqtCode { get; set; }
public string CentreCode { get; set; }
public virtual string Description { get; set; }
}
public abstract BookingOption : Option{
public DateTime WeekStartDate{get;set;}
}
public abstract class AvailabilityOption : BookingOption {
public decimal Price{get;set;}
public override string Description{
get{return string.format("{0} # {1}", base.Description, Price.ToString());
set{ base.Description = value;}
}
}
public abstract class LimitedAvailabilityOption : AvailabilityOption{
public int MinNumber { get; set; }
public int MaxNumber { get; set; }
public int TotalBooked { get; set; }
public int TotalRemaining { get; set; }
public override string Description
{
get
{
return string.Format("{0} ({1} # {2})",
base.Description, TotalRemaining.ToString(), Price.ToString());
}
set { base.Description = value;}
}
}
public class Option1 : Option{
public Option1(){}
}
public class Option2 : Option{
public Option2(){}
}
public List<BookingOption> BookWithAvail(List<AvailabiliyOption> options){
//pick options based on avail and pass back the booking versions so write away...
}
It looks like answer depends on how you plan to use Availability and Limited availabilitty qualities of essences. If those availability-qualities are only applicable to LimitedAvailabilityOption and AvailabilityOption classes - than it does not seems there is a big need of implementation Availability or LimitedAvailability in separate classes, as each of those classes will be used to distinguish only one kind of other essences (LimitedAvailabilityOption and AvailabilityOption respectively). It would make sense to use decoration pattern and implement classes for Availability and Limited availability qualities only if you plan assign each of them to multiple essences that are not connected with inheritance relationship (including inheritance through intermediate classes). And if you plan to spread usage of availability-qualities across multiple classes that are not supposed to have any inheritance connection via common ancestor that has availability property - then the only choice is to extract those availability qualities into separate classes.
I have inherited the following (terrible) code and am wondering how best to refactor it.
There are large if/else clauses all over the codebase, one of which is similar to below :
public class BaseResultItem
{
public int Property1 { get; set; }
}
public class ResultItem1 : BaseResultItem
{
public int Property2 { get; set; }
}
public class ResultItem2 : BaseResultItem
{
public int Property3 { get; set; }
}
public class BaseHistoryItem
{
public int Property1 { get; set; }
}
public class HistoryItem1 : BaseHistoryItem
{
public int Property2 { get; set; }
}
public class HistoryItem2 : BaseHistoryItem
{
public int Property3 { get; set; }
}
public class HistoryBuilder
{
public BaseHistoryItem BuildHistory(BaseResultItem result)
{
BaseHistoryItem history = new BaseHistoryItem
{
Property1 = result.Property1
};
if (result is ResultItem1)
{
((HistoryItem1)history).Property2 = ((ResultItem1)result).Property2;
}
else if (result is ResultItem2)
{
((HistoryItem2)history).Property3 = ((ResultItem2)result).Property3;
}
return history;
}
}
Note that this is a simplified example and there are many more classes involved in the actual code. There are similar if/else clauses all over the place.
I have been looking at the abstract factory pattern but I am having some problems.
Basically I am assuming that to avoid the if/else problems I need to pass the actual dervied types around. So BuildHistory should not use base types and maybe there should be multiple methods, one per derived type?
If you can't change the DTO classes perhaps you can try to subclass HistoryBuilder to deal with the different subclasses. Then you use the appropriate HistoryBuilderX to create a HistoryItem from a ResultItem. Then the question is how to get the appropriate HistoryBuilderX for the ResultItem supplied.
Still, if you can't change the BaseResultItem class to include a GetBuilder function you need to use some if..else if.. construct that inspects the classtypes of your ResultItems.
Or you create a Registry where every ResultItem class is registered with its corresponding HistoryBuilderX class. But that might be overkill.
The general 'design pattern' is simply to use object orientation with polymorphism instead of type checks. Thus: a BuildHistory method inside BaseResultItem, overridden by descendants.
Any code which checks the concrete type of an object smells (in a refactoring sense). Supporting different behaviours for different types is what OO is about.
Use polymorphism to remove the type checks.
if (result is ResultItem1)
{
((HistoryItem1)history).Property2 = ((ResultItem1)result).Property2;
}
Becomes then something like
result.addToHistory( history );
If for some reason, you don't want to scatter the logic in the item classes, have a look at the visitor pattern. In this case, you have something like:
public class Visitor {
History history;
public visit ( ResultItem1 item ) { ... }
public visit ( ResultItem2 item ) { ... }
...
}
public class ResultItem1 {
public accept( Visitor v ) { v.visit( this ); }
}
The typecheck is removed by the double-dispatch in the visitor, which is slightly more elegant.
I didn't understood exactly how the various kind of history relates to the various kind of items. So this is just a sketch of possibles direction to follow.