A magic number overkill - coding-style

I have a piece of code in which I call a function with argument of a string value. The string value is taken from a string array using the index.
if (validateRejectionCategory(rejectionData[0])) {
......
}
In this case is 0 still considered a magic number? Should I abstract 0 to a variable like REJECTION_CATEOGRY_POSITION? Does the function name not make it clear enough that the value would be a rejectionCategory?
Let me know your thoughts please.

In general extracting every numerical value to a constant is a bad habit. You have to maintain balance as with all things in life. Here it's clear that you want to validate the first element of rejectionData. Most uses of 0, 1, 2 are not magic, but are used in an algorithm.
You usually want to extract numeric values that aren't easily explainable in the context of code.
E.g. if your code looks like this in some main-like file:
app.modalTimeooutSeconds = 3.0
it's not really more readable to rewrite it as
let timeoutSeconds = 3.0
app.modalTimeoutSeconds = timeoutSeconds
unless you want to have a config file that are constants are stored, but you may not have enough constants to support having such a file.
Everything is context dependent and there are no good answers.

Related

Freemarker: How to write a BigDecimal's value that can be used in a BigDecimal constructor

I would like to use freemarker to generate java code that instantiates a BigDecimal.
The value of the BigDecimal is present at generation time.
the BigDecimal API would work like this:
BigDecimal copy = new BigDecimal(original.toString());
Alas, the freemarker magic uses numeric conversion on my value of original, so this does not work (in a freemarkter template):
BigDecimal copy = new BigDecimal("${original?c}");
None of the numeric conversions (percent, number, computer, ...) works - c/computer most interestingly, because it outputs 0 if the value becomes too big.
With considerable pain, I might be able to wrap the BigDecimal in another Object that just gives me a toString and is not a number, so freemarker might leave its value untouched and my generated BigDecimal is correct, but that's only a last resort.
Maybe there is a way to invoke the toString() method and print the result into the target document?
ERRATUM:
because it outputs 0 if the value becomes too big should read because it outputs 0 if the value becomes too small (see #ddkany's answer)
Update: FreeMarker 2.3.32 now supports lossless formatting with ?c, which is not based on DecimalFormat, but mostly on toString. To use that, you have to set the c_format configuration setting to any other value than its backward compatible default, "legacy". Like setting it to "JavaScript or JSON" is fine for most projects (that's also the default if you just set the incompatible_improvements configuration setting to 2.3.32). See the fine details of how numers are formatted in the documentation of the c built-in: https://freemarker.apache.org/docs/ref_builtins_number.html#ref_builtin_c
Old answer, for 2.3.31 and before:
What FreeMarke does by default is whatever Java's DecimalFormat does (for the localized medium format by default, again defined by the Java platform).
?c uses new DecimalFormat("0.################") with fixed US locale (and some more symbol adjustments for INF and NaN). So I don't know how that gives 0 for a huge BigDecimal number. Are you sure about that? I guess it was actually a very small number, so it was rounded down. Well, switching to "scientific" format would make more sense then, though.
To have whatever formatting logic you need, you can register your own number formatter like, in this case, configuration.setCustomNumberFormats(Map.of("toString", new MyToStringTemplateNumberFormatFactory()), and then you can use ${original?string.#toString}. Or rather, you can set the number_format to #toString, and then just use ${original}.

Why are there no custom default values in proto3?

The proto2 version of Protocol Buffers allows to specify default values for message elements:
optional double scaling_factor = 3 [default = 1.0];
Why is this no longer possible in proto3? I consider this a neat feature to save additional bytes on the wire without the need of writing any wrapper code.
My understanding is that proto3 no longer allows you to detect field presence and no longer supports non-zero default values because this makes it easier to implement protobufs in terms of "plain old structs" in various languages, without the need to generate accessor methods. This is perceived as making Protobuf easier to use in those languages.
(I personally think that languages which lack accessors and properties aren't very good languages and protobuf should not design down to them, but it's not my project anymore.)
This is a work around instead of a direct answer to your question, but I've found myself using wrappers.proto optional values and then setting the default value myself programatically when I absolutely must know if this was a default value or a value that was explicitly set.
Not optimal that your code has to enforce the value instead of the generated code itself, but if you own both sides, at least it's a viable alternative versus having no idea if the value was the default or explicity set as such, especially when looking at a bool set to false.
I am unclear how this affects bytes on the wire. For the instances where I've used it, message length was not a design constraint.
Proto File
import "google/protobuf/wrappers.proto";
google.protobuf.BoolValue optional_bool = 1;
Java code
//load or receive message here
if( !message.hasOptionalBool() )
message.setOptionalBool( BoolValue.newBuilder().setValue( true ) );
In my autogenerated file .pb.cc I see few places like this:
if (this->myint() != 0) {
and few like this:
myint_ = 0;
So, why not to enable default value and generate
static ::google::protobuf::int32 myint_defaultvalue = 5;
...
if (this->myint() != myint_defaultvalue) {
...
...
myint_ = myint_defaultvalue;
...
instead?

Protobuf: enum with default value

In google's Protocol Buffers, I use large enums and I have to assign each integer value explicitly:
enum Function {ProcessLibrary=0;
RotateLeft=1;
RotateRight=2;
...}
This is very annoying and ugly. Is there a way to avoid these integer values in the code?
something like:
enum Function {ProcessLibrary;
RotateLeft;
RotateRight;
...}
No, basically. This is deliberate to prevent huge errors when adding / removing enums, and to allow for non-contiguous enums.
In most real-world cases where the list of names is already defined elsewhere, you can write a 5 line script to add =n onto each - heck, a spreadsheet calculation and "fill down" would go a long way to it - paste names into the first column, copy the generated lines out of the second.

SPMETAL / LINQ to SharePoint Decimal Types

I've hit a pretty major snag with the entities generated by spmetal / linq to sharepoint. I am hoping someone has dealt with this before.. or maybe I am missing something obvious.
Let's say we have a list with a number field. The field will be expected to hold reasonably precise values.. for example, 0.0000451. Once the value is in the list- SharePoint is fine with it. It displays in the list and display/edit views correctly.
Now if we generate entities based on this list with spmetal, we will get..
//...
private System.Nullable<double> _number;
//..
[Microsoft.SharePoint.Linq.ColumnAttribute(Name="Number", Storage="_number", Required=true, FieldType="Number")]
public System.Nullable<double> Number {
get {
return this._number;
}
set {
if ((value != this._number))
{
this.OnPropertyChanging("Number", this._number);
this._number= value;
this.OnPropertyChanged("Number");
}
}
}
//...
Since the type determined by spmetal is doublewe get notation when trying to retrieve it.. for example:
var number = (from x in myDc.MyList select x.Number).First();
number would actually result in a double of 4.51E-05, not 0.0000451.
I am assuming this can be fixed by using a decimal. If I change the types throughout the generated entities to System.Nullable<decimal> I get type conversion failures.
How should I fix this?
EDIT I think maybe it is better to ask "how should I deal with this"? for example, I can simply convert my double values to decimal later on down the line.. my linq query, for example. If I do that, the example case would return the expected result. That seems clunky, though, and I'd like to correct this at the source.
There are several cases like this where SPMetal will give you clunky code. You can, and sometimes have to, fix that. And I admit, it definitely feels better to do it at the source.
But there is a downside.
When your data model changes you will have to re-run SPMetal to incorporate your new entities. Any changes you made to the generated file will have to be carefully documented and re-done, or your code will be broken. Therefore, I would advise to leave the generated code alone if you can work with it.
If you can write a wrapper around the objects/methods it would of course be preferable to just converting the types at the end-point, but that's general good programming practice.
4.51E-05 actually equals 0.0000451 so there is nothing wrong with your code.
In other words 4.51E-05 means 4.51 times ten to the minus five power, or 0.0000451

Verifying enum value is valid in VB.NET

My English may not be very good, so please excuse me if I don't make sense.
I am tasked with verifying an Enum contains a incrementing value.
The code looks like this:
Public Enum AccountMessageDescriptor
AccountInvalid = 1001
AccountReviewPending=1002
...
InvalidOperationOnAccount=1382
End Enum
Each Enum value has a description (Custom) attribute also. The file and description attribute is used elsewhere... It looks like the programmers update the enums and use the custom attribute for help messages instead of resource files etc with a new integer value...
For example, another error may be added as:
NewEnumItem=1383
I need to make sure (during build time we have a custom MSBuild task that does lots of other processing) if the enum is incrementing sequentially and that its not already in use.
Someone suggested using a collection, check if the enum value already exists and if not insert it.
I was thinking of just iterating through and checking if the current value is +1 the previous value (so its sequential and it can't be already in use because it has to always be +1). Does this seem flawed or am I not understanding something about .NET enums?
Emmi
If you set the first value and then exclude all following values they will be incremental. eg...
Public Enum testenum
first = 1001
second
third
End Enum
So second will be 1002 third will be 1003 etc etc...
If for some reason you do need to skip certain values then you can force the increment to start at a higher value eg..
Public Enum testenum
first = 1001
second
third
fourth = 2000
fifth
End Enum
So in this example fourth will be 2000 and fifth will be 2001
To iterate through an enum, you could try the following:
For Each amd As AccountMessageDescriptor In [Enum].GetValues(GetType(AccountMessageDescriptor))
'Do your thing here
Next
I'm not enterily sure if this way the values are sequential, but a quick test could sort this out for you.
Or you can store all the values in an array and check if the values are sequential:
Dim allAMD As AccountMessageDescriptor() = DirectCast([Enum].GetValues(GetType(AccountMessageDescriptor)), AccountMessageDescriptor())
'Loop through array and check with previous

Resources