Reputation: 17388
I have a generic model which is used to store all the data using an ORM technology. This model has to be occasionally transformed into another model to ‘do something’. At the moment I am using this (simplified) approach where the generic model stores weight in kilogram and the target model stores it in pounds:
public class GenericModelClassA
{
public virtual double Weight { get; set; }
}
public interface IModelX
{
double Weight { get; set; }
}
public class ModelXClassA : GenericModelClassA, IModelX
{
private const double WeightConversionFactor = 2.20462;
public override double Weight
{
set
{
base.Weight = value / WeightConversionFactor;
}
get
{
return base.Weight * WeightConversionFactor;
}
}
}
Is this a decent approach to the problem? I have heard about model driven transformation (MDT) languages to query/view/transform/operational (QVTO). Is my approach too naive? Would you recommend MDT languages? Any feedback/opinions would be very much appreciated.
Many thanks.
Christian
Upvotes: 0
Views: 1199
Reputation: 1693
From the OO point of view there are some concepts that are not explicitly model that may help in this situation. In this case you are representing and absolute amount and its unit of measure with a number (to which you can't delegate any responsibility, since it is not an object) and absorbing that conversion responsibility in your model object. In my opinion you should create a richer model that represents the situation:
I'm not familiar with C# so please bear with me here:
abstract public class WeightUnit
{
abstract public function convertValueToKilo(float value);
abstract public function convertValueToPounds(float value);
}
public class Kilo extends WeightUnit
{
public function convertValueToKilo(float value) {return value;}
public function convertValueToPounds(float value) {return value * 2.20462262;}
}
public class Pounds extends WeightUnit
{
public function convertValueToKilo(float value) {return value / 2.20462262;}
public function convertValueToPounds(float value) {return value;}
}
public class Weight
{
protected WeightUnit unit;
protected float value;
public function Weight(float value, WeightUnit unit)
{
//set the internal state
}
public function toKilo()
{
return new Weight(this.unit.convertValueToKilo(this.value), new Kilo());
}
public function toPounds()
{
return new Weight(this.unit.convertValueToPounds(this.value), new Pounds());
}
}
One of the issues with this implementation is that the amount of conversions explodes as more weigh unit you have. For those cases you generally select a "default" unit (e.g. Kilo) and all the other units know how to convert to/from kilo. In that case adding a new unit means adding one class and two methods. However some round errors may arise from doing this double conversion.
HTH
Upvotes: 1
Reputation: 16348
This is how I'd do it.
Domain
public class Weight
{
public Weight(decimal miligrams) { InMiligrams= miligrams;}
public decimal InMiligrams {get;private set;}
public decimal InGrams { get { return InMiligrams*1000; }}
/* other conversions as properties */
}
Persistence
public class StorageModel
{
public virtual decimal Weight {get;set;}
}
Mapping
Domain -> Persistence
storage.Weight = weight.InMiligrams;
Persistence -> Domain
weight = new Weight(storage.Weight);
The Persistence layer and the Domain layer know that internally all weights are expressed in miligrams (or whatever other unit of measure you want).
Upvotes: 1