What Is the Proper Way to Handle Calculated Properties in an Object? - class

From what I can tell, there are two main ways to accomplish this:
Option 1: Calculate each property "on demand" via their getter method (e.g.
getTotal()).
Option 2: Populate all calculated properties on construction and any time a public property changes by using a
generic calculate() method.
I created two examples using a simple insurance policy object. Each class initializes with a few properties like premiumRateBase, brokerFee, termYears, effectiveDate, and agentCommissionRate. The calculated columns would be things like the prorated premiumRate, total, or agentCommission.
Here's an example of option 1:
component {
// public properties (getters + setters)
property name="premiumRateBase";
property name="brokerFee";
property name="effectiveDate";
property name="termYears";
property name="agentCommissionRate";
function init(
required numeric premiumRateBase,
required numeric brokerFee,
required date effectiveDate,
required numeric termYears,
required numeric agentCommissionRate
) {
// setters
...
return this;
}
function getExpirationDate() {
return dateAdd( 'yyyy', effectiveDate, termYears );
}
function getPremiumRate() {
// run proration and calcuation determination
// based on premiumRateBase, getExpirationDate(), and maybe a few other methods
...
return premiumRate;
}
function getTotal() {
return getPremiumRate() + brokerFee;
}
function getAgentCommission() {
return getPremiumRate() * agentCommissionRate
}
function getAgentCompensation() {
return getAgentCommission() + brokerFee
}
}
In the above example, the calculations are run any time you call a method like getTotal(). The advantage of this approach is that the code is pretty straightforward. The disadvantage of this approach is that if needed to run getTotal(), getAgentCommission() and then getAgentCompensation(), you wind up running a lot of redundant math. For this example, it wouldn't equate to much additional processing time, but in a more complex example, I could see this adding up.
Here's an example of option 2:
component {
// public properties (getters + setters)
property name="premiumRateBase";
property name="brokerFee";
property name="effectiveDate";
property name="termYears";
property name="agentCommissionRate";
function init(
required numeric premiumRateBase,
required numeric brokerFee,
required date effectiveDate,
required numeric termYears,
required numeric agentCommissionRate
) {
// setters
...
// run the calculation
calculate();
return this;
}
// primary calculation method which sets all private properties
function calculate() {
variables.expirationDate = calculateExpirationDate();
variables.premiumRate = calculatePremiumRate();
variables.total = calculateTotal();
variables.agentCommission = calculateAgentCommission();
}
/***************************
Public Getters
***************************/
function getExpirationDate() {
return expirationDate;
}
function getPremiumRate() {
return premiumRate;
}
function getTotal() {
return total;
}
function getAgentCommission() {
return agentCommission;
}
/***************************
Private Calculations
***************************/
private function calculateExpirationDate() {
return dateAdd( 'yyyy', effectiveDate, termYears );
}
private function calculatePremiumRate() {
// run proration and calcuation determination
// based on premiumRateBase, expirationDate and maybe a few other variables
...
return premiumRate;
}
private function calculateTotal() {
return premiumRate + brokerFee;
}
private function calculateAgentCommission() {
return premiumRate * agentCommissionRate;
}
private function calculateAgentCompensation() {
return agentCommission + brokerFee;
}
}
In the second example, we only run a generic calculate() method after the constructor method init() fires. I didn't include this, but you would also need to run calculate() again if you ever update any of the public properties through their setter methods. The advantage of this approach is that the calculation math only occurs when the properties change. The downside is that the code seems a little more convoluted and harder to read.
What is the best-practices or proper approach to solving this type of problem?

It is a common dilemma and ultimately it resolves to the cost of recalculating the property every time. If it is cheap, I would always prefer getter approach.
Another dimension to think about is staleness of calculated property. Option #2 performs calculation only upon initialisation and possibly the properties involved in calculation may change afterwards. The calculated metric will be stale now. You can fix it by recalculating metrics on modification. This will further increase the complexity of code. If this modification isn't well encapsulated, recalculation responsibility will be shared with caller too!
In summary, for cheap calculations I would prefer option #1 and for complex calculations, I would first encapsulate modifications to ensure recalculation on each update.

Related

Why use setter when you can assign massively using a method?

I found out that I can assign data to a property using set or a method.
class Human {
String name, address;
set rewriteName(String name) {
this.name = name;
}
set rewriteAddress(String address) {
this.address = address;
}
void rewrite(String name, String address) {
this.name = name;
this.address = address;
}
String introduction() => "Name is $name. I live in $address";
Human(this.name, this.address);
}
I tried to assign some data using both way, and method looks more efficient than using setter, since its only need just one call to change everything:
Human human = Human('stacker', 'baghdad');
// using method
human.rewrite('overflow', 'new york');
// using setter
human.rewriteName = "Hooman";
human.rewriteAddress = "jakarta";
my question is why using a setter instead of method?
Typically, the targets of getters and setters are made private so they're not directly accessible from outside of the file or library.
class Business {
String name, _address;
double lat, long;
bool coordsCalculated = false;
Map propertyRecords = {};
get address {
return _address;
}
set address(String address) {
if (address == _address) return; // Nothing changed;
_address = address;
// API call to calculate lat/log
APICall(onSuccess: (data) {
lat = data.lat;
long = data.long;
coordsCalculated = true;
});
}
void rewrite(String name, String address) {
this.name = name;
this.address = address;
}
String summary() {
if (coordsCalculated) return "Business name is $name, here's a link to the map!";
return "Business name is $name, at $_address.";
}
Human(this.name, String address) {
this.address = address;
}
}
The user of the class feels like they're using a normal property, but it does other silent things.
Methods can do this too, yes, but this can feel cleaner.
Importantly, getters and setters cannot be asynchronous which definitely can give methods an advantage, but there are plenty of valid uses.
Getters and setters are also easier to read, when being used. Less parentheses are always a good thing.
You certainly don't need to always use them, or use them when they do nothing but set the variable, but they can be nice.
In one of my Widgets, I have a getter that looks something like
FileState get fileState => FileUploaderKey.currentState!. widget.file.state;
It's so much easier to read this way. It gets the current state of the file, always, whereas
FileState fileState = FileUploaderKey.currentState!.widget.file.state;
Only saves the current state, but doesn't change with it.
It's basically about what the usage looks like, a method call with a parameter vs. what looks like an assignment to a property. From Dart.dev's Effective Dart: Design
DO use setters for operations that conceptually change properties.
Linter rule: use_setters_to_change_properties
Deciding between a setter versus a method is similar to deciding between a getter versus a method. In both cases, the operation should be “field-like”.
For a setter, “field-like” means:
The operation takes a single argument and does not produce a result value.
The operation changes some state in the object.
The operation is idempotent. Calling the same setter twice with the same value should do nothing the second time as far as the caller is concerned. Internally, maybe you’ve got some cache invalidation or logging going on. That’s fine. But from the caller’s perspective, it appears that the second call does nothing.
In your example you're comparing a method that changes two properties with two separate setters. You'd use the method if it's essential that the two properties both be updated at the same time, as a single conceptual operation. If the properties are independent (and otherwise meet the criteria above), you might use setters instead (if you need to do something when they're set; otherwise, simple data fields might make more sense).

Set new value in computed property

I declared a variable to be settable and gettable. In its getter, I have some logic, but not in setter. I decided to use computed property:
var product: Product? {
// setter
set(newProduct) {
// COMPILER WARNING: Attemping to modify 'product' within its own setter
product = newProduct
}
// getter
get {
let price = SOME_EQUATION
return Product(price)
}
}
The issue is in setter, compiler is warning me Attemping to modify 'product' within its own setter. But I do want to set the newProduct to the product instance variable. What is the correct way to do that?
I assume that SOME_EQUATION is using the value from the product, right? If not, then the setter is not needed at all.
Also, there's a side effect to the way you wrote the code: every time you get the value of the product property, you'll get a new instance.
But answering your question: for computed properties, there's no storage in the instance. So what you might want to do is to create a private property and store value into it instead:
private var _product: Product?
var product: Product? {
// setter
set(newProduct) {
// COMPILER WARNING: Attemping to modify 'product' within its own setter
_product = newProduct
}
// getter
get {
let price = SOME_EQUATION(_product)
return Product(price)
}
}
In your example you will always return Product(SOME_EQUATION). If this equation do not depend on the class containing the product property maybe consider moving this as a factory method in the Product.
Note that setting value in its' set is recursion.
To achieve real computed property:
var product: Product? {
return Product(SOME_EQUATION)
}
Note that let product = Product(SOME_EQUATION) is actually better than computed property if it is suitable in your case, because this equation will be executed only once.
Edit:
Computed properties are not used for what you are describing. Having no logic in the setter, and not using directly the value that you have set is wrong.
As I have described above, you need to create factory method in your Product class as:
static func create(for someEquation: YourType) -> Product {
return Product(someEquation)
}
And in your class you use it as:
Product.create(for: SOME_EQUATION)
More info on computed properties: you use them when you already have dependancies in your class, and you want to extract some point of your data for convenience.
If you depend on some parameter, and not dependancy, you would better make function, taking parameter!

GWT-Charts ColumnFunction not working?

I just want to make sure I'm not doing something wrong before I file a bug/start digging in GWT-Charts code...
Trying to style a LineChart:
DataViewColumn ret = DataViewColumn.create(new ColumnFunction() {
#Override
public Object calc(DataTable dataTable, int row) {
if (dataTable.isValueNull(i, dataColumn)
|| dataTable.getValueNumber(i, dataColumn) < value) {
return "color: red";
}
return "color: green";
}
}, ColumnType.STRING);
ret.setRole(RoleType.STYLE);
(I had to add RoleType.STYLE myself, custom-built 0.9.11-SNAPSHOT off Master)
But adding that column results in (using new JSONObject(columns)):
{
"0":{"sourceColumn":0},
"1":{"sourceColumn":1, "label":"Data"},
"2":{"calc":{}, "type":"string", "role":"style"}
}
Note the empty set for "calc"?
I tried just doing a ColumnFunction for Data (returning a flat value) in case the "style" Role required more than just adding to the RoleType Enum, and that also doesn't seem to be getting passed through.
The JSNI in DataViewColumn.setCalc(ColumnFunction) seems to be right to me, so I'm not sure where the issue lies...
UPDATE:
Putting debugging statements in the ColumnFunction showed it to be running, but the output didn't seem to be getting used.
Turns out that DataViewColumn.setCalc was missing the return statement in its JSNI wrapper.
DataViewColumn.setCalc:
/**
* Sets a function that will be called for each row in the column to calculate a value for that cell.
*
* #param columnFunction a function for calculating each row value
*/
public final native void setCalc(ColumnFunction columnFunction) /*-{
this.calc = function(dataTable, row) {
columnFunction.#com.googlecode.gwt.charts.client.ColumnFunction::calc(Lcom/googlecode/gwt/charts/client/DataTable;I) (dataTable, row);
};
}-*/;
Was not returning the value calculated by the function, just calculating it.
Adding "return" to the line in the innermost block fixes the issue.

binding to constant values in mvvm

i have constant values (certain limits) i work with in the viewmodel but i need it in my view as well. what is the best way to do that?
constant:
private const int maxLevel = 4;
do i really need to make a property for each constant and bind to it like that:
private const int _maxLevel = 4;
public int MaxLevel
{
get { return _maxLevel; }
set
{
RaisePropertyChanged("MaxLevel");
}
}
maybe i could store all those values in a *.resx file like i do it with strings? what is the best practice here?
You can do:
namespace Foo.ViewModels
{
public class MainWindowViewModel{
public const int MaxLevel = 4;
...
}
}
and use it in the view:
<Label Content="{x:Static Foo.ViewModels:MainWindowViewModel.MaxLevel}"></Label>
Or generally speaking, bind to:
"{x:Static MyNameSpace:MyClass.MY_CONSTANT}"
Lose the setter. Property change notification is only needed to inform binding elements that the value has changed. Since MaxLevel is a constant its value never changes, thus you don't need it. You can't bind directly to a constant because in practice the compiler embeds the value into the code that accesses it at compile time, so for constant properties that are unlikely to need future modification I usually just do something like this:
public int MaxLevel { get {return 4;} }

How to parametrize my exports?

I'd like to be able to parametrize my exports not only with types (as in, generic exports), but also with values.
Something like:
class Greeter
{
readonly string _format;
public Greeter( string format ) { _format = format; }
public string Greet( string name ) { return string.Format( _format, name ); }
}
// ...
var e = new ExportProvider();
e.ExportParametrized<Greeter>( args: new[] { "Hi, {0}!" } );
e.ExportParametrized<Greeter>( args: new[] { "¡Hola, {0}!" } );
// And then:
[ImportMany] IEnumerable<Greeter> Greeters { get; set; }
foreach( var g in Greeters ) Console.WriteLine( g.Greet( "John" ) );
// Should print out:
// Hello, John!
// ¡Hola, John!
One might ask: why don't I simply export the value new Greeter( "Hello, {0}!" ) using ComposablePartExportProvider and CompositionBatch?
While this approach would work in this particular case, it has an important flaw: if the Greeter class had any imports of its own, they would not be satisfied.
The usual way I would go about this is to declare two classes - EnglishGreeter and SpanishGreeter, inherit them both from Greeter, and then provide the appropriate arguments in the call to base constructor.
But this doesn't work for two reasons:
This is a lot of noise to write. Not only do I have to type the whole shebang, I also have to come up with names for those classes, and it doesn't always make sense to have names. Not to mention the DRY principle. But even besides the noise...
Sometimes I don't know the parameters upfront. Say, for example, my greeting formats were coming from some kind of config file.
Here is another thought, to somewhat clarify what I'm looking for.
This problem is almost solved in the TypeCatalog. See, the TypeCatalog knows about the type and it calls the type's constructor to create the part on demand.
One can think of this process from another standpoint: the catalog has a factory function; using that function, it creates the part, then satisfies its non-prerequisite imports, and then returns the part back to the requestor.
Now, in the particular case of TypeCatalog, the factory function just happens to be the type's own constructor. If only I could hook in and replace the factory function with my own, but still leverage the rest of the machinery, that would be exactly what I'm looking for.
You can achieve this by using property exports. You could define a class specifically for those kinds of exports, and it will look like this:
class MyParameterizedExports
{
[Export(typeof(Greeter))]
private Greeter EnglishGreeter
{
get
{
Greeter g = new Greeter("Hi, {0}!");
container.SatisfyImportsOnce(g);
return g;
}
}
[Export(typeof(Greeter))]
private Greeter SpanishGreeter
{
get
{
Greeter g = new Greeter("¡Hola, {0}!");
container.SatisfyImportsOnce(g);
return g;
}
}
}
Here you export two separate Greeter instances without having to define a new class for each type of Greeter.