I have an order edit and quote edit screen that are very similar. I want to try to avoid code like this:
if (order is Order)
SetupScreenForOrder();
if (order is Quote)
SetupScreenForQuote();
But maintaining two screens is not good either. If I create some common interface between a Quote and Order then how do you deal with fields like OrderNumber or QuoteDate?
What's the best way to handle this?
Foo foo = GetFoo();
if (foo is Order)
...
if (foo is Quote)
...
If you don't want to write these conditionals, avoid referring to Order instances and Quote instances by their common parent type (if any).
Order order = GetOrder()
SetupScreen(order); // resolves to void SetupScreen(Order order)
Quote quote = GetQuote()
SetupScreen(quote); //resolves to void SetupScreen(Quote quote)
Often if the display screens for two classes are similar, it's because they have fields that are similar in function, even if they don't have the same name.
For example, it might be that each instance (of an order or a quote) will have a date displayed with it. So you might have an interface:
interface displayableInOrderAndQuoteList {
Date getDisplayDate();
}
public class Order {
private Date orderDate;
public Date getOrderDate() { //used only when treating object as an order
return orderDate;
}
public Date getDisplayDate() {//used when displaying object via interface
return orderDate;
}
}
public class Quote {
private Date quoteDate;
public Date getQuoteDate() { //used only when treating object as a quote
return quoteDate;
}
public Date getDisplayDate() {//used when displaying object via interface
return quoteDate;
}
}
In other words, the interface represents questions you want to ask the object in order to build the screen. Each object decides how to answer those questions.
If the display is different enough that you need to ask the objects totally different questions, then you probably should have two screens.
I think a common interface between the two objects would be a good idea.
Perhaps define the uncommon fields as nullable and have the screen check for null and determine how to display those fields.
int? OrderNumber {get;set;}
DateTime? QuoteDate {get;set;}
EDIT: in response to JC's comment
Perhaps consider trying to take it a step further and, at least logically, consider an Order and a Quote to be the same kind of object but at different stages in the "Order lifecycle". I.e. a "Quote" is an order at the beginning of the lifecycle, whereas an "Order" is an order at the middle or end of the lifecycle.
You could have an OrderState property defined on your interface, and then your UI could use the OrderState property to decide how the quote/order should be displayed, rather than checking each piece of data individually.
If you feel that the problem is more that you have too many if statements in your UI, then perhaps consider creating small user controls to handle displaying chunks of the UI for either a quote or for an order. You could then either dynamically add the appropriate control (a quote control or an order controL) to your UI, or have both controls already added and just show/hide them as appropriate. I would caution, though, that this sounds like it could be a messy approach, so just be careful that the solution doesn't end up being more complicated than the problem that you're trying to solve.
Related
To give some background on what I am doing:
I have a program that allows a user to modify and create a general calibration. Inside this calibration includes groups. Groups differ by the type of analysis they perform. These groups also included spectral sets with each set containing data for only one molecule. Inside these sets also includes spectral data at varying concentrations. Each spectra data is a discrete set of data which is specified by its resolution (x-axis space between each point) and its spectral range (x axis range).
One of the main aspects of building these calibration files is to keep the resolution and spectral range consistent in all spectral data in each set. This means that spectral data cannot be added unless it matches the spectral data of the rest. Also, if the user deletes all spectral data the resolution and range is reset allowing Spectra data of any range or resolution to be added to the calibration.
The question is: How can I provided an effective way to prevent adding spectral data to the calibration that doesn't match the current resolution and spectral range???
Below is a general description of a calibration class. This is a very general description and contains the only info needed to explain what I am trying to do.
class calibration
{
List<Group> groups;
}
class Group
{
List<SpectralSet> sets;
}
class SpectralSet
{
List<SpectraData> spectras;
}
class SpectraData
{
double firstXPoint;
double lastXPoint;
double resolution;
double[] Ypoints;
}
I'm sure you could apply all sorts of fancy design patterns to enforce the rules you mention.
However, for the sake of simplicity, I would just encapsulate the logic in the calibration class with an AddGroup method which validates the added group conforms to the calibration's requirements. Similarly, I would create an AddSpectralSet method to the group class as a gate keeper into the sets collection.
At that point, depending on how often these things change, I would think about exposing the groups collection and sets collection as ReadOnlyCollection to ensure code doesn't try to add items without using the prescribed methods.
Hope this helps.
Your approach will probably vary a bit, but here's an outline of how you could achieve this. You need to do the following:
Only expose immutable public collection properties, along with an Add method, so that you can do your own validation.
For example, you don't want to do:
class Group
{
public List<SpectralSet> sets;
}
Because then anyone can just do myGroup.sets.Add(mySet), without you getting a chance to do any validation on the set. One common pattern to achieve this is as follows:
class Group
{
private List<SpectralSet> _sets;
public IEnumerable<SpectralSet> Sets { get { return _sets; } }
public void Add(SpectralSet set)
{
//Do validation here, throw an exception or whatever you want to do if the set isn't valid
_sets.Add(set);
}
//Have a similar Remove method
}
Store the criteria that the data must match
I'm not quite sure what a spectral range is, so I'll just use the resolution as an example. You can extend this to whatever the range criteria is simply. There's at least three possible ways you could do this:
When you construct a class, pass it the resolution that it's allowed in the constructor, and make this immutable.
When adding and removing, update the allowed resolution as necessary.
Don't store the resolution explicitly, calculate it every time you add or remove.
Out of those, option 1 is by far the simplest. Life is always much easier when you can keep things as immutable as possible. So you'd do something like:
class Group
{
private List<SpectralSet> _sets;
public IEnumerable<SpectralSet> Sets { get { return _sets; } }
public readonly double Resolution;
public Group(double resolution)
{
Resolution = resolution;
}
public void Add(SpectralSet set)
{
if(set.Resolution != resolution)
//Throw an Exception here, or however you want to handle invalid data
_sets.Add(set);
}
//Have a similar Remove method
}
Following this example, each of the classes you included would need a Resolution parameter with the same kind of logic, just checking the Resolution of any direct child you tried to add. Likewise with whatever you use for spectral range.
You also want to be able to change the resolution allowed if all data is cleared. The simplest way to do this is just create new objects whenever the data is cleared, rather than just clearing out the collections in existing objects.
Make SpectraData immutable
All this is useless if you can get a SpectraData out of one of the carefully gated collections and change it arbitrarily. Make anything that needs to be validated immutable, only allowing it to be set on construction. If you have a requirement not to do that, you need to think very carefully about how you will allow it to be changed.
I have object that is serialized into db.
The question is where to keep run-time properties (like last run time, etc.), in same class or separate class or derived class? What should be the best practices in this scenario?
Updated: For example: Object Train
properties: type, weight, height, speed etc
run-time: travel start date, travel end date
Looking at the example now added I would say that you should move those out, and instead use encapsulation - i.e. A TrainJourney class that has the "runtime" properties (that really isn't the right term here) and a reference to a Train instance that is your data entity.
Adding extra properties (commonly in a partial class) to a data entity is OK as long as they tie directly to the data entity. This typically means calculated values, deferred/cached values, interpretations (IsOpen rather than Status==Status.Open etc).
In your case, the extra properties relate to unrelated concepts; by separation of concerns you are confusing things by mixing that into your Train class. So: don't.
I assume that you are using some kind of standard serializer. They do often provide the possibility to mark what properties are serialized through the use of attributes. Mark only those that should be persisted as part of the serialization.
Besides that I think that a solution where you use serialization for saving to database should be really thought through. There are some cases where it is relevant, but it is often much better to have the objects' properties mapped to columns in the database.
I would use the following class structures: ("public / private" and properties excluded for brevity)
// describes the run schedules
class RunSchedule {
int RunScheduleId; // only used by DB to uniquely identify record, never seen by user
int RunId;
DateTime StartTime;
}
// describes the runs, so repeat runs do not duplicate this information
class Run {
int RunId; // only used by DB to uniquely identify record, never seen by user
string Name; // unique run name as known by everyone, eg. "Chicago express"
Train Train;
string StartLocation;
string EndLocation;
TimeSpan Duration;
}
// describes the train-specific information, without duplicating anything
class Train {
int TrainId; // only used by DB to uniquely identify record, never seen by user
string Name; // unique train identifier as known by everyone
TrainType Type;
}
// describes the train-common information, shared across trains of the same type
class TrainType {
int TypeId; // only used by DB to uniquely identify record, never seen by user
string Description;
double WeightMetricTonnes;
double HeightMetres;
double SpeedKms;
}
Also, as I've shown, when talking about things like length, speed, weight etc, please make sure you state the unit.
I'd probably also add a status to these, so obsolete runs, trains, etc, can be hidden during data entry.
I have two tables in the database that are used almost for the same thing, but the tables don't have exactly the same structure.
Lets say I have one table for manual requests and another table for automatic requests. I have to load both tables into the same GridView and I'm using custom business objects.
To illustrate the question I'll call TManualReqTable and TAutomaticReqTable.
TManualReqTable
- ID
- Field1
- Field2
- Field3
- Field4
and
TAutomaticReqTable
- ID
- Field1
- Field3
In the code, I'm using the same object for these two tables. I have an interface with all the properties of both tables and I'm checking if the field exists when I'm loading the data to the object.
But I'm thinking this should be created with two objects and one superclass with abstracts methods.
What is your opinion about it?
I would create an interface IRequest that describes the fields & methods common to both, and then interfaces & classes for ManualRequest and AutomaticRequest that implement IRequest and also add the methods/fields unique to each of them.
You can use IRequest as the type for something that incorporates either one. When iterating through something that can include data from either, you can check whether each object implements the interfaces:
foreach (IRequest obj in RequestList) {
// do stuff that uses the common interface
if (obj is IManualRequest) {
// do stuff specific to manual requests
} else if (obj is IAutomaticRequest) {
// likewise
}
}
I follow a general rule to avoid creating base classes unless:
I've already designed or discovered sufficient commonality to give sufficient substance to the base class.
I have a use case for consuming the classes as the base class; if I don't have anything that can operate on the common functionality of the classes, there's little value in having a base class (can achieve the same functionality through composition of a class implementing the common behaviors.)
The requirements are sufficiently stable that I believe the base class abstraction will hold without significant modification in the future. Base classes become increasingly difficult to modify over time.
IMO, forget how the database looks like for a minute or two.
Think of how it should be structured as an object.
Think of how you would like to use that object. If you need to visualize, write some code of that yet non-existing object and tweak it until it looks elegant.
Think of how to make it happen.
model first development
Hope it helps.
well, there are a few assumptions i'm making here, so let me make them explicit...
given:
this is primarily a difference in query/display logic
the display logic can already handle the nulls
the underlying object being represented is the same between the two items
there's a simple way of determining whether this was a 'manual' or an 'automatic' call
i would say that inheritance is not the way i would model it. why? because it's the same object, not two different kinds of object. you're basically just not displaying a couple of the fields, and therefore do not need to query them.
so, i would probably try to accomplish something that makes clear the nature of the difference between the two (keep in mind that i intend this to show a way of organizing it so that it's clear, any particular implementation might have different needs; the main idea to glean is treating the differences as what they are: differences in what gets queried based upon some sort of condition.
public enum EQueryMode
{
Manual,
Automatic
}
public class FieldSpecification
{
public string FieldName { get; set; }
public bool[] QueryInMode { get; set; }
public FieldSpecification
(
string parFieldName,
bool parQueryInManual,
bool parQueryInAutomatic
)
{
FieldName = parFieldName;
QueryInMode = new bool[] { parQueryInManual, parQueryInAutomatic };
}
}
public class SomeKindOfRecord
{
public List<FieldSpecification> FieldInfo =
new List<FieldSpecification>()
{
new FieldSpecification("Field1", true, true),
new FieldSpecification("Field2", true, false),
new FieldSpecification("Field3", true, true),
new FieldSpecification("Field4", true, false)
};
// ...
public void PerformQuery(EQueryMode QueryMode)
{
List<string> FieldsToSelect =
(
from f
in FieldInfo
where
f.QueryInMode[(int)QueryMode]
select
f.FieldName
)
.ToList();
Fetch(FieldsToSelect);
}
private void Fetch(List<string> Fields)
{
// SQL (or whatever) here
}
}
edit: wow i can't seem to make a post today without having to correct my grammar! ;)
I'm new to the .NET world having come from C++ and I'm trying to better understand properties. I noticed in the .NET framework Microsoft uses properties all over the place. Is there an advantage for using properties rather than creating get/set methods? Is there a general guideline (as well as naming convention) for when one should use properties?
It is pure syntactic sugar. On the back end, it is compiled into plain get and set methods.
Use it because of convention, and that it looks nicer.
Some guidelines are that when it has a high risk of throwing Exceptions or going wrong, don't use properties but explicit getters/setters. But generally even then they are used.
Properties are get/set methods; simply, it formalises them into a single concept (for read and write), allowing (for example) metadata against the property, rather than individual members. For example:
[XmlAttribute("foo")]
public string Name {get;set;}
This is a get/set pair of methods, but the additional metadata applies to both. It also, IMO, simply makes it easier to use:
someObj.Name = "Fred"; // clearly a "set"
DateTime dob = someObj.DateOfBirth; // clearly a "get"
We haven't duplicated the fact that we're doing a get/set.
Another nice thing is that it allows simple two-way data-binding against the property ("Name" above), without relying on any magic patterns (except those guaranteed by the compiler).
There is an entire book dedicated to answering these sorts of questions: Framework Design Guidelines from Addison-Wesley. See section 5.1.3 for advice on when to choose a property vs a method.
Much of the content of this book is available on MSDN as well, but I find it handy to have it on my desk.
Consider reading Choosing Between Properties and Methods. It has a lot of information on .NET design guidelines.
properties are get/set methods
Properties are set and get methods as people around here have explained, but the idea of having them is making those methods the only ones playing with the private values (for instance, to handle validations).
The whole other logic should be done against the properties, but it's always easier mentally to work with something you can handle as a value on the left and right side of operations (properties) and not having to even think it is a method.
I personally think that's the main idea behind properties.
I always think that properties are the nouns of a class, where as methods are the verbs...
First of all, the naming convention is: use PascalCase for the property name, just like with methods. Also, properties should not contain very complex operations. These should be done kept in methods.
In OOP, you would describe an object as having attributes and functionality. You do that when designing a class. Consider designing a car. Examples for functionality could be the ability to move somewhere or activate the wipers. Within your class, these would be methods. An attribute would be the number of passengers within the car at a given moment. Without properties, you would have two ways to implement the attribute:
Make a variable public:
// class Car
public int passengerCount = 4;
// calling code
int count = myCar.passengerCount;
This has several problems. First of all, it is not really an attribute of the vehicle. You have to update the value from inside the Car class to have it represent the vehicles true state. Second, the variable is public and could also be written to.
The second variant is one widley used, e. g. in Java, where you do not have properties like in c#:
Use a method to encapsulate the value and maybe perform a few operations first.
// class Car
public int GetPassengerCount()
{
// perform some operation
int result = CountAllPassengers();
// return the result
return result;
}
// calling code
int count = myCar.GetPassengerCount();
This way you manage to get around the problems with a public variable. By asking for the number of passengers, you can be sure to get the most recent result since you recount before answering. Also, you cannot change the value since the method does not allow it. The problem is, though, that you actually wanted the amount of passengers to be an attribute, not a function of your car.
The second approach is not necessarily wrong, it just does not read quite right. That's why some languages include ways of making attributes look like variables, even though they work like methods behind the scenes. Actionscript for example also includes syntax to define methods that will be accessed in a variable-style from within the calling code.
Keep in mind that this also brings responsibility. The calling user will expect it to behave like an attribute, not a function. so if just asking a car how many passengers it has takes 20 seconds to load, then you probably should pack that in a real method, since the caller will expect functions to take longer than accessing an attribute.
EDIT:
I almost forgot to mention this: The ability to actually perform certain checks before letting a variable be set. By just using a public variable, you could basically write anything into it. The setter method or property give you a chance to check it before actually saving it.
Properties simply save you some time from writing the boilerplate that goes along with get/set methods.
That being said, a lot of .NET stuff handles properties differently- for example, a Grid will automatically display properties but won't display a function that does the equivalent.
This is handy, because you can make get/set methods for things that you don't want displayed, and properties for those you do want displayed.
The compiler actually emits get_MyProperty and set_MyProperty methods for each property you define.
Although it is not a hard and fast rule and, as others have pointed out, Properties are implemented as Get/Set pairs 'behind the scenes' - typically Properties surface encapsulated/protected state data whereas Methods (aka Procedures or Functions) do work and yield the result of that work.
As such Methods will take often arguments that they might merely consume but also may return in an altered state or may produce a new object or value as a result of the work done.
Generally speaking - if you need a way of controlling access to data or state then Properties allow the implementation that access in a defined, validatable and optimised way (allowing access restriction, range & error-checking, creation of backing-store on demand and a way of avoiding redundant setting calls).
In contrast, methods transform state and give rise to new values internally and externally without necessarily repeatable results.
Certainly if you find yourself writing procedural or transformative code in a property, you are probably really writing a method.
Also note that properties are available via reflection. While methods are, too, properties represent "something interesting" about the object. If you are trying to display a grid of properties of an object-- say, something like the Visual Studio form designer-- then you can use reflection to query the properties of a class, iterate through each property, and interrogate the object for its value.
Think of it this way, Properties encapsulate your fields (commoningly marked private) while at the same time provides your fellow developers to either set or get the field value. You can even perform routine validation in the property's set method should you desire.
Properties are not just syntactic sugar - they are important if you need to create object-relational mappings (Linq2Sql or Linq2Entities), because they behave just like variables while it is possible to hide the implementation details of the object-relational mapping (persistance). It is also possible to validate a value being assigned to it in the getter of the property and protect it against assigning unwanted values.
You can't do this with the same elegance with methods. I think it is best to demonstrate this with a practical example.
In one of his articles, Scott Gu creates classes which are mapped to the Northwind database using the "code first" approach. One short example taken from Scott's blog (with a little modification, the full article can be read at Scott Gu's blog here):
public class Product
{
[Key]
public int ProductID { get; set; }
public string ProductName { get; set; }
public Decimal? UnitPrice { get; set; }
public bool Discontinued { get; set; }
public virtual Category category { get; set; }
}
// class Category omitted in this example
public class Northwind : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
You can use entity sets Products, Categories and the related classes Product and Category just as if they were normal objects containing variables: You can read and write them and they behave just like normal variables. But you can also use them in Linq queries, persist them (store them in the database and retrieve them).
Note also how easy it is to use annotations (C# attributes) to define the primary key (in this example ProductID is the primary key for Product).
While the properties are used to define a representation of the data stored in the database, there are some methods defined in the entity set class which control the persistence: For example, the method Remove() marks a given entity as deleted, while Add() adds a given entity, SaveChanges() makes the changes permanent. You can consider the methods as actions (i.e. you control what you want to do with the data).
Finally I give you an example how naturally you can use those classes:
// instantiate the database as object
var nw = new NorthWind();
// select product
var product = nw.Products.Single(p => p.ProductName == "Chai");
// 1. modify the price
product.UnitPrice = 2.33M;
// 2. store a new category
var c = new Category();
c.Category = "Example category";
c.Description = "Show how to persist data";
nw.Categories.Add(c);
// Save changes (1. and 2.) to the Northwind database
nw.SaveChanges();
I've got some entities which have decimal properties on them. These entities' properties are displayed in multiple places throughout my UI.
Currently I'm finding myself doing:
litWeight.Text = person.Weight.ToString("0.00");
all over the place.
Now I know for a fact that in several instances, and am suspicious of many others that the client is likely to want the values to 3d.p. in the future.
Is there some pattern I can employ to handle the formatting of this Weight property (and other properties; not just decimals, perhaps dates etc.) so that I can have this formatting in a single place?
I know could use a formatstring in the webconfig, or write some extension methods in the UI but these don't seem very elegant solutions.
It would be nice to have some formatting objects which are tied to my entities, so its inherently obvious which formatter to use.
Thanks,
Andrew
The simplest solution would be to make a utility class with static methods that appropriately format different types of values and call them. For example:
litWeight.Text = Utility.FormatWeight(person.Weight);
Can you not add a method to the entities for formatting themeslves? Then each object can delegate to a 'strategy' object to do the actual formatting.
A reason for this is both to be able to change the decimal places etc, but also to allow things like internationalisation - decimal formatting is locale-dependent; some countries use decimal commas instead of points, or group digits in sets other than threes etc.
EDIT: The comment was this puts presentation code in the domain layer. True, so apply the standard fix for all design problems; add one more layer of indirection :)
You may not want to have the full MVC, but the concept of View and Model still seem appropriate. Perhaps, for each entity, define a View class, so PersonView which keeps a reference to a Person object and has properties called format_weight etc for each property of Person that is of interest? It should still use a Strategy pattern for the actual formatting.
So your example would be
PersonView pv = new PersonView(person)
litWeight.Text = pv.format_weight();
(please excuse syntactical errors, I don't speak C#)
If you want, you could make PersonView drop in replacement for Person, either by reimplementing the methods/properties and delgating to the referenced Person, or by inheriting from Person when making PersonView?
You could create a very basic user control - deriving from label or similar - that is responsible purely for displaying a weight string so you then have:
weightValue.DisplayValue(person.Weight);
and the setter formats the decimal as required. If this is used whenever you display a weight then you only have to alter the user control to change all displays of weight.
A basic version could be:
public void DisplayValue(decimal weight)
{
this.Text = weight.ToString("0.00");
}