02-24-2017 1:39 PM
We have about a dozen function groups and 30-40 function modules which all need to commonly reference upwards of 100 constants.
We currently do this:
include /namespace/constants
But, the extended code check tells me it is bad practice to have an include used in more than one function group.
We're not going to rewrite all of our code to sit in a single function group, like it proposes.
As we move to object oriented development, we face the same question.
Is it best to put all of the constants into a single class and then reference it in our code like this:
if ls_knvp-parvw = /namespace/cl_constant=>gc_soldto_function
That feels cumbersome, but manageable. Maybe we can alias it or something?
I'd like to use a type group, but we can't put it in a namespace and the usage seems to be deprecated?
Basically, I want something easy to use that can be referenced from multiple classes or function groups. Shorter naming is preferable. Passing the extended syntax check is very important.
Thanks for your suggestions!
02-24-2017 3:37 PM
Having all your constants in one place, no matter whether you're writing something for Finance or for HR, is not good practice. The idea should be to be as specific as possible. Personally, I don't see anything wrong with having e.g.
CONSTANTS c_end_of_time TYPE d VALUE '99991231'
defined multiple times. If I didn't do it in a class, then I'd do it in an interface - but one constants interface per application. Having your constants defined in one or a few different places, used by many applications, to my mind is close to defining a global variable v_count for all your integer needs. I.e. not a good idea.
Group your constants into related groups, define them in interfaces, then use aliases in the class definitions.
02-24-2017 3:37 PM
Having all your constants in one place, no matter whether you're writing something for Finance or for HR, is not good practice. The idea should be to be as specific as possible. Personally, I don't see anything wrong with having e.g.
CONSTANTS c_end_of_time TYPE d VALUE '99991231'
defined multiple times. If I didn't do it in a class, then I'd do it in an interface - but one constants interface per application. Having your constants defined in one or a few different places, used by many applications, to my mind is close to defining a global variable v_count for all your integer needs. I.e. not a good idea.
Group your constants into related groups, define them in interfaces, then use aliases in the class definitions.
02-27-2017 7:59 PM
I do agree with your statement that having all the constants in one place is a bad idea. But, I don't like the idea of having an interface per application, declaring constants for just that application. At that point you are just moving the program constants to a class (or interface) for no real gain and just another element to deal with.
Reading Horst Keller's blog about enumeration, in that example, the shirt sizes are something that I would like declared in one place for the entire project / dev class / package. First that would be the definition of code reuse. Second, think about refactoring, in his example if a size XS is added, it has to be done in one place only instead of trying to find every place it was declared. Third, if the XS wasn't supposed to be there, you don't want another developer accidentally adding it to just one application.
Personally I like keeping reusable ones in a properly marked globally accessible place for the dev class (as a class or interface) and application specific ones within the program. If my program is primarily class based, then it is an attribute - and if I don't anticipate any one else using it for the same purpose, I bury it in the Private section, so that any future refactoring won't impact inadvertent use in another program.
02-28-2017 6:23 AM
I was using the word application deliberately to mean "connected group of programs". If that's your entire project than fine. The point that if you have a program for shirts, and another for coal mining, they shouldn't share the constants interface. Depending on your package regime, it might make sense to have one interface per package. Or it might not. It all depends on the granularity. I'd hate to see a constants interface for, e.g. FI applications.
At some point "reusable" becomes "global" and global is bad!
Burying single use constants in private is what I do also. However, if the class is like an API, and will be used by many other classes, then obviously there will be public constants. And if the class has many subclasses, there will be protected ones as well. 🙂
02-28-2017 2:59 PM
Thanks for the clarification of "application" - you seem to follow the dictionary meaning 😉 In that case, we are both on the same page.
And really bad, while we are commenting on it - is carrying around an include with every alphabet declared c_a = 'A', c_b = 'B', etc.... I have been in situations where I was forced to toe that line just so that I don't use...
IF my_var = 'X'.
OR
IF my_var = c_sun_is_shining.
they want me to use
IF my_var = c_x.
02-28-2017 3:20 PM
You've seen the same code as I have. I always say a constant should describe it's meaning and not it's content. And anyway - what's wrong with Abap_True ? 😉
Rich
02-28-2017 3:58 PM
a constant should describe it's meaning and not it's content.
Thank you, I hope you don't mind me stealing this phrase!
I tend to forgive not using ABAP_TRUE because in past versions of ABAP, it was available only if you explicitly declared the type-pool. I guess that is not an excuse any more!
03-01-2017 8:09 AM
03-01-2017 8:12 AM
02-24-2017 3:42 PM
You can create instance of your "constant class". And it will shorten code for usage 🙂
Like this:
DATA: lo_cs1 TYPE REF TO /namespace/cl_long_class_name.
CREATE OBJECT lo_cs1.
IF l_variable = lo_cs1=>c_constant.
"TRUE
ENDIF.
02-27-2017 12:59 PM
02-27-2017 3:52 PM
I dislike it. An instantiation without reason. What if the constructor is resource intensive? You're relying on the developer checking/knowing. No - I don't think it is a good idea. It could be used to make the code more readable, but at the expense of meaning.
02-27-2017 8:03 PM
How about an interface? You aren't dealing with a constructor then.
DATA: lo_cs1 TYPE REF TO /namespace/if_long_interface_name.
CREATE OBJECT lo_cs1.
... lo_cs1=>constant.
02-28-2017 6:18 AM
You can't instantiate an interface. You won't get past the syntax check.
02-28-2017 6:37 AM
It was intended only for "constant class". But nevertheless I agree. It can be confusing or problem making
02-28-2017 6:49 AM
02-28-2017 7:20 AM
02-28-2017 2:52 PM
Sorry, my mistake... what caught me off guard was it did pass syntax check without the instantiation - but that doesn't work either!
02-24-2017 5:45 PM
The ABAP programming guidelines say: put'em to a class or interface. And hey, since 7.51 we have enumerations ...
02-27-2017 3:50 PM
02-27-2017 7:42 PM
I like your blog better https://blogs.sap.com/2016/10/10/abap-news-release-7.51-enumerations/ I guess I didn't dig hard enough on the help site 🙂
02-28-2017 1:05 PM
Hello Ray,
as a constant is constant, so you are free to define both a global constant à la /namespace/cl_constant=>gc_soldto_function and a local scope redefinition:
CONSTANTS c_soldto_function TYPE ... VALUE /namespace/cl_constant=>gc_soldto_function.
JNN
02-28-2017 4:09 PM
I think that misses the whole point of having a single place that the constants are declared. In your example you are re-declaring the constant for local use. I have found a slightly better way - so that you are declaring an ALIAS and not actually carrying around new declarations.
INTERFACE const.
INTERFACES /namespace/if_long_interface_name.
ALIASES sun FOR /namespace/if_long_interface_name~sun.
ALIASES moon FOR /namespace/if_long_interface_name~moon.
...
ENDINTERFACE.
...
my_variable = const=>sun.
my_variable2 = const=>moon.
I still don't like even this method, because it looses the elegance and you have to determine which (or all) the constants to declare the alias for. If the OP truly has a 100 constants that need to stay together in one class/interface/include (whatever), that is a lot of redeclaring!
03-01-2017 8:11 AM
If a bit of extra effort is made to make the code readable, I don't mind if a developer has to do a lot of redeclaration.
btw - I'd alias as c_sun, c_moon. Here using prefixes to indicate usage, not type.
03-01-2017 1:46 PM
const=>c_sun.
Little redundant, no?
Here using prefixes to indicate usage, not type.
I guess you have the same aversion to Hungarian notation (I just learned about its source yesterday in a Coffee Corner post by Jelena) as I do.
03-01-2017 2:37 PM
03-01-2017 3:26 PM
Oh, you are talking about the method Jacques Nomssi described! I was talking about using the keyword ALIASES like my example... In that case yes, no argument there.
In my example, I was locally redeclaring the interface and Aliasing the used constants with that local redeclaration. You will have to use the const=> there.
03-01-2017 8:01 PM
Personally, I like this trick of aliasing constants (eventually using a custom-defined macro like "mac_alias
/namespace/if_long_interface_name : sun, moon") . Of course, I would prefer enumerations from ABAP 7.50.