Are row constants limited?

It's easy to lose the track of odd numbers like 0 , 1 or 5 . I used to be very strict when I wrote low-level code. Since I work more with all the string literals associated with XML and SQL, I often break the rule of embedding constants in the code, at least when it comes to string literals. (I'm still good at numerical constants.)

Lines do not match numbers. It seems tedious and a little silly to me to create a compile-time constant with the same name as its value (for example, const string NameField = "Name"; ), and although repeating the same string literal in many places seems risky, there is little chance of a typo thanks to copying and pasting, and when I refactor, I usually do a global search, which involves changing more than just the name of the thing, for example, how it is processed functionally with respect to the things around it.

So, let's say you don't have a good XML serializer (or you have no mood to configure it). Which one would you personally use (if you weren’t trying to bend down to peer pressure in some kind of code review):

 static void Main(string[] args) { // ...other code... XmlNode node = ...; Console.WriteLine(node["Name"].InnerText); Console.WriteLine(node["Color"].InnerText); Console.WriteLine(node["Taste"].InnerText); // ...other code... } 

or

 class Fruit { private readonly XmlNode xml_node; public Fruit(XmlNode xml_node) { this.xml_node = xml_node; } public string Name { get { return xml_node["Name"].InnerText; } } public string Color { get { return xml_node["Color"].InnerText; } } public string Taste { get { return xml_node["Taste"].InnerText; } } } static void Main(string[] args) { // ...other code... XmlNode node = ...; Fruit fruit_node = new Fruit(node); Console.WriteLine(fruit_node.Name); Console.WriteLine(fruit_node.Color); Console.WriteLine(fruit_node.Taste); // ...other code... } 
+4
source share
9 answers

A specific constant is easier to reorganize. If "Name" is ultimately used three times, and you change it to "FullName", changing the constant is one change instead of three.

+11
source

For something like this, it depends on how often the constant is used. If this is only in one place according to your example, then hard coding is fine. If it is used in many different places, definitely use a constant. One typo can lead to hours of debugging if you are not careful, because your compiler is not going to notice that you typed "Tsate" instead of "Taste", while it will be noticed that you typed fruit_node.Tsate instead of fruit_node. Taste.

Edit: Now I see that you mentioned copying and pasting, but if you do this, you can also lose the time you save by not creating a constant in the first place. With intellisense and autocompletion, you could have a constant value of a few keystrokes, instead of coping with the copy / paste problem.

+5
source

As you probably guessed. Answer: it depends on the context.

It depends on what the sample code is. If this is just a small outlier part of the system, then hard constant coding may be acceptable.

If part of a large, complex system and constants is used in files with several files, I would pay more to the second option.

0
source

As with many programming issues, this is a matter of taste. The "laws" of proper programming have been built on the basis of experience - many people have been burned by global variables that cause namespace or clarity problems, so global variables are evil. Many used magic numbers, but only later found out that the number was incorrect or needed to be changed. Text search is not suitable for changing these values, so the constants in the code are evil.

But both are allowed, because sometimes they are not evil. Do you need to make a decision yourself, which leads to a clearer code? What will be better for those accompanying? Is the argument for the original rule applicable to my situation? If I had to read or maintain this code later, how would I prefer it to be written?

There is no absolute law of a good coding style, because no programmer’s mind works the same way. The rule is to write the cleanest, cleanest code you can.

0
source

Personally, I loaded the fruits from the XML file in advance - something like:

 public class Fruit { public Fruit(string name, Color color, string taste) { this.Name = name; this.Color = color; this.Taste = taste; } public string Name { get; private set; } public Color Color { get; private set; } public string Taste { get; private set; } } // ... In your data access handling class... public static FruitFromXml(XmlNode node) { // create fruit from xml node with validation here } } 

Thus, the “fetus” is not really attached to the repository.

0
source

I would go with constants. This is a bit more work, but there is no impact on performance. And even if you usually copy / paste values, I probably had instances where I changed the code when I typed and did not understand that Visual Studio has focus. I would prefer this to lead to compilation errors.

0
source

In the above example, when strings are used as keys to a map or dictionary, I tend to use enum (or another object). You can often do much more with an enumeration than with a constant string. In addition, if any code is commented out, the IDE often skips this when refactoring. In addition, links to the String constant that are contained in comments may or may not be included in refactoring.

I will create a constant for the string when the string will be used in many places, the string is long or complex (for example, a regular expression), or when a constant with a named name will make the code more obvious.

I prefer my typos, incomplete refactoring and other errors of this type, so as not to compile, but just not work properly.

0
source

Like many other refactorings, this is probably an additional extra step that leaves you with code that is less risky to maintain and the next guy is more likely to trap it. If you are in a situation that rewards these kinds of things (most of which I am), go for it.

0
source

Yes, to a large extent.

I think that developers in statically typed languages ​​have an unhealthy fear of any dynamics. Almost every line of code in a dynamically typed language is actually a string literal, and they have been doing fine for years. For example, in JavaScript, technically this is:

 var x = myObject.prop1.prop2; 

This is equivalent to this:

 var x = window["myObject"]["prop1"]["prop2"]; // assuming global scope 

But for JavaScript, this is definitely not a standard practice:

 var OBJ_NAME = "myObject"; var PROP1_NAME = "prop1"; var PROP2_NAME = "prop2"; var x = window[OBJ_NAME][PROP1_NAME][PROP2_NAME]; 

That would be just ridiculous.

It all the same depends on how, for example, if a string is used in many places, and it is rather bulky / ugly to print ("name" or "my-custom-property-name-x"), then it’s probably worth it make a constant, even within the same class (at which point it is probably good to be internally consistent inside the class and do all the other string constants too).

In addition, if you really want other external users to interact with your library using these constants, then it would also be nice to define public constants and a document so that users can use them to interact with your library. However, a library that interacts through magic string constants is usually bad practice, and you should consider creating your own library in such a way that you do not need to use magic constants to interact with it in the first place.

I think in the specific example that you indicated where the strings are relatively easy to enter and there are apparently no external users of your API who would expect to work with it using these string values ​​(i.e. they are only for internal data manipulation), readable code is much more valuable than refactored code, so I would just put literals directly in line. Again, this assumes that I understand your specific use case for sure.

One thing that no one seemed to notice is that once you define a constant, its volume becomes something that needs to be maintained and thought. It really has value, it is not free, as it seems to everyone. Consider this:

Should it be private or public in my class? What if one other namespace / package needs one value, should I now extract the constant into some global static constant class? What if I need it in other assemblies / modules, will I extract it further? All this makes the code less comprehensible, harder to maintain, less enjoyable to work with, and harder. All in the name of refactorability?

Usually these "excellent refactorings" never occur, and when they do, they require a complete rewrite anyway with all the new lines. And if you used some general module before this big refactoring (as in the previous paragraph), which did not have these new lines that you now need, what then? You add them to the same general module of constants (what if you do not have access to the code for this general module)? Or do you keep them local to yourself, and in this case there are now several scattered repositories of string constants, all at different levels, at risk of duplicating constants throughout the code? Once you get to this point (and believe me I saw it), refactoring becomes controversial, because until you get all your habits of your constants, you will miss other people using their constants, although these constants have something same logical meaning as your constants, and you are actually trying to change them all.

0
source

Source: https://habr.com/ru/post/1285711/


All Articles