Below is a code snippet that is creating object.
Form userexit_save_document_prepare.
data: /bks/exitmanager type ref to /bks/exit_manager.
create object /bks/exitmanager
exporting main_prog = 'SAPMV45A'
exit_form = 'USEREXIT_SAVE_DOCUMENT_PREPARE'.
include /bks/exitman.
ENDFORM.
I got this from the documentation
For performance reasons, the parameters "main_prog" and "exit_form" should be filled, in the case of userexits, which are performed very often like "user_field_modification" in "SAPMV45A" which is called for every single screen-field.
1) What happened exactly behind when create object /bks/exitmanager is called? memory allocated for the object etc?
2) Why for performance reasons the exporting parameters of create object needs to be filled?
I'm not 100% sure, but here is my best guess:
an object called /bks/exitmanager is constructed (which is an oject of the class /bks/exit_manager or more specific a reference/"pointer" to an object of this class) .. the required memory allocated etc., but also the "constructor" code is called (probably sets some instance variables as passed to the call).
If you're explicitly passing these parameters, they don't have to be "calculated" at run-time (e.g. by looking at the call stack). This should save some time, especially if it would have to be done quite often (as described in the documentation).
It would help to see what /bks/exit_manager actually is, and a brief explanation of what you are trying to accomplish.
Expanding on what IronGoofy wrote:
data: /bks/exitmanager type ref to /bks/exit_manager
This creates a reference pointer in the ABAP memory of your program, much like a field symbol. Also it must be already delared. If it is in the include, you need to move the include.
create object /bks/exitmanager
exporting main_prog = 'SAPMV45A'
exit_form = 'USEREXIT_SAVE_DOCUMENT_PREPARE'.
This creates an object instance based on the declared class, and assigns it to the referance pointer. It does this by calling the constructor method first.
Only by examing /bks/exit_manager will you find out exactly what you need to export.
It's impossible to tell what's going on and why the parameters should be passed without taking a look at the constructor of /BKS/EXIT_MANAGER. It's a common pattern though to keep a buffer of settings (think of a static hashed table with the key being the parameters and the value holding whatever is complicated and time-consuming to fetch). In this case, I would have expected a protected constructor that cannot be accessed directly, but only using a static factory method that uses a hashed table to keep the references of the exit handler itself - optimally using weak references...
Related
The other day I noticed that I sometimes put data in front of objects and other times not:
object A
data object B
What's the difference between an object and a data object?
The fact that data is allowed on an object declaration is in fact a bug (KT-6486) which should be fixed.
data is an annotation which causes the compiler to generate equals, hashCode, toString, copy and componentN functions. It doesn't make much sense when applied to an object declaration for two reasons:
An object declaration cannot have a constructor, and all these functions work based on properties defined in the primary constructor.
There's only one instance of any object at runtime.
So no componentN functions would be generated, copy can't work, and the generated equals/hashCode/toString implementations will be equivalent to the default ones from Any which are based on identity.
Let's say I have a static variable in a function:
Private Sub SomeFunction()
Static staticVar As String = _myField.Value
End Sub
When, exactly, is the value from _myField assigned to staticVar? Upon the first call to the function? Instantiation of the enclosing class?
The CLR has no support for this construct so the VB.NET compiler emulates it.
Creation first. The variable is lifted to a private field of the class with an unspeakable name that ensures no name collisions can occur. It will be an instance field if the variable is inside an instance method of the class. So will be created when an object of the class is created with the new operator. It will be a Shared field if the method is Shared or is part of a Module. So will be created in the loader heap by the jitter.
Assignment next, the much more involved operation. The language rule is that assignment occurs when code execution lands on the Dim statement for the first time. The term first time is a loaded one. There's an enormous amount of code generated by the compiler inside the method to ensure this is guaranteed. The kind of problems that need to be addressed are threading, recursion and exceptions.
The compiler creates another hidden helper field of type StaticLocalInitFlag at the same scope as the hidden variable field to keep track of initialization state for the variable. The first part of the injected code is a call to Monitor.Enter() to deal with threading. Same thing as SyncLock. The StaticLocalInitFlag serves as the locking object, note how it is a class and not just a Boolean.
Next, Try and Finally statements guard against exceptions. Inside the Try statement, the value of StaticLocalInitFlag.State is checked for 0. This protects against recursion on the same thread. State is then set to 2 to indicate that initialization code is running. Followed by the assignment. Next, State is checked again to see if it is still 2. If it is not then something went drastically wrong and an IncompleteInitialization exception is thrown.
The Finally block then sets the State to 1 to indicate that the variable is initialized. Followed by a call to Monitor.Leave().
Lots of code, 96 bytes of IL for just a simple variable. Use Static only if you don't worry about the cost.
A Static variable is instantiated when it is assigned, obviously.
When that line is run, not before, not after.
Put a breakpoint on it and you'll see.
Static just means that the value will persist between calls.
Shared class/module members are instantiated the first time the class is accessed, before any Shared constructor and before the call, whether that is to the class constructor or some Shared method/property. I think this may be the origin of your confusion. Static local variables, like local statics in c# are not instantiated in this way.
Interesting information from Tim Schmelter, it appears the value is maintained internally using a hidden Shared class level variable that is instantiated like other Shared class level variables but always with the default value.
The effect observed by you the developer is unchanged, apart from some instantiation delay when the class is accessed. This delay should be undetectable in practice.
The VB.NET compiler creates a static (shared in VB.NET) class-level variable to maintain the value of "staticVar". So it's initialized like any other static/shared variable, on the first use of a static field of that class (or when you call this method).
http://weblogs.asp.net/psteele/pages/7717.aspx
Well I am a new to VB.NET, converting a legacy system to .NET world. Recently I have been reviewing the already existing code since I joined the project quite late in the team.
So I find that there are many shared functions (not shared class) inside many classes. I doubt this may create some problem if two requests ( i.e two different HTTP request to the same method as it's a WCF application, of course exposed methods are not shared but internally called methods are shared) comes to the same shared method and both the calls to the method may have different method parameters/arguments, overwriting each other's arguments.
In short, if shared method has a list of arguments which is going to be processed, is there any chance of inconsistencies in the light of multiple access to the shared method via two http requests.
I would appreciate each and every response the thread.
Thanks,
JJ
No.
Parameters are local to the method call and will not interact across threads.
However, if you use Shared fields or variables, you will have issues.
It is true that parameters are local to the method call; however, that will not necessarily limit their reach. Class variables sent as ByVal parameters can still result in interactions across threads. You may want to read up on the SyncLock keyword. The use of the Shared keyword will not affect (i.e. reduce) the chances of such interactions.
The main issue about multithreaded applications is when the very same range of memory gets referenced by more than one thread at a time, particularly when any one of those threads may make memory writes.
Some things to think about:
(1) Visual Basic (and C#) dichotomizes variables (and data types) into two species: the "Value" (or "Structure"), and the "Reference" (or "Class").
(2) The "Value" data type means that a direct reference is made to an actual collection of bits that represents an Integer, or a Boolean, or even a bitmap, or some other kind of object. In old school parlance, this is the "image" of an instantiation of an object. It is the state space of the object. It is what makes an object itself versus being some other object, independant of where in memory it may be.
(3) The "Reference" data type means that this a very special Structure which somehow indicates the data type of the object and where in memory it resides. The computer will interpret a "Reference" to obtain the actual image of the object.
(4) When a "Value" parameter is passed ByVal, that means a new object is created that is in the identical image of the original expression being passed, and it is upon this copy that the function or method operates. The image of the original "Value" cannot be affected.
(5) When a "Value" parameter is passed ByRef, that means a new "Reference" variable is created, and that "Reference" variable will contain the information that will interpret back to the image of the original "Value". Now the image of the original "Value" can be changed.
(6) When a "Reference" parameter is passed ByVal, the very special Structure, which gets interpreted back to the actual image of the object, gets copied. It is upon this copy of the very special Structure that the function or method operates. This copy still points to the actual image of the object. Which means that an object of a Reference variable that is passed by ByVal can still have its image (i.e. its "Value") changed. However, the very special Structure of the original "Reference" itself cannot be changed.
(7) Note that the String type is an odd duck: It will behave as if it were a "Value" parameter even though it is in fact a "Reference" type. Hence a String passed ByVal will not be affected in the same way any other class would. Actually, String is an example of an immutable type - which means that steps are taken to prevent changes to the image of its "Value". (See http://msdn.microsoft.com/en-us/library/bb383979.aspx and http://codebetter.com/patricksmacchia/2008/01/13/immutable-types-understand-them-and-use-them/ for more details.)
(8) When a "Reference" parameter is passed ByRef, one now has created a new "Reference" object that points to the original "Reference" object (that, in turn, points to the "Value" of some other object). The use of ByRef on a "Reference" allows one to modify (or create anew) the very special Structure of the original "Reference" object being passed as a parameter. A function or method that performs a swap operation will use ByRef on "Reference" parameters.
(9) Some people say that a "Reference" is the same as a memory address. While in particular cases this may in fact be true, technically it is not. The very special Structure does not have to be a memory address in whatever image would be valid for the CPU - although utlimately the computer will translate it into a valid memory address at some point.
(10) The keyword Me is an automatic "Reference" to the object that is currently executing the class member. Under the hood, it exists as a parameter too, one that is sent unseen. EXCEPT in the case of a Shared member - in which case Me is unavailable.
I need to write some instance method, something like this (code in ruby):
def foo_bar(param)
foo(param)
if some_condition
do_bar(param)
else
do_baz(param)
end
end
Method foo_bar is a public api.
But I think, param variable here appears too many times. Maybe it would be better to create an private instance variable and use it in foo, do_bar and do_baz method? Like here: (#param is an instance variable in ruby, it can be initialized any time)
def foo_bar(param)
#param = param
foo
if some_condition
do_bar
else
do_baz
end
end
Which code is better? And why?
Is param replacing part of the state of the object?
If param is not changing the object state then it would be wrong to introduce non-obvious coupling between these methods as a convenience.
If param is altering the state of the object then it may still be bad practice to have a public api altering the state - much better to have a single private method responsible for checking and changing the state.
If param is directly setting the state of the object then I would change the instance variable here but only after checking that the new state is not inconsistent
The first version should be preferred for a couple of reasons. First, it makes testing much easier as each method is independent of other state. To test the do_bar method, simply create an instance of its containing class and invoke the method with various parameters. If you chose the second version of code, you'd have to make sure that the object had all the proper instance variables set before invoking the method. This tightly couples the test code with the object and results in broken test cases or, even worse, testcases that should no longer pass, but still do since they haven't been updated to match how the object now works.
The second reason to prefer the first version of code is that it is a more functional style and facilitates easier reuse. Say that another module or lambda function implements do_bar better than the current one. It won't have been coded to assume some parent class with a certain named instance variable. To be reusable, it will have expected any variables to be passed in as parameters.
The functional approach is the much better approach ... even in object oriented languages.
If you do not need param outside of the foo_bar method the first version is better. It is more obvious what information is being passed around and you are keeping it more thread friendly.
And I also agree with Mladen in the comment above: don't add something to the object state that doesn't belong there.
Is setX() method name appropriate for only for setting class property X?
For instance, I have a class where the output is a string of an html table. Before you can you can call getTable, you have to call setTable(), which just looks at a other properties and decides how to construct the table. It doesn't actually directly set any class property -- only causes the property to be set. When it's called, the class will construct strHtmlTable, but you can't specify it.
So, calling it setTable breaks the convention of get and set being interfaces for class properties.
Is there another naming convention for this kind of method?
Edit: in this particular class, there are at least two ( and in total 8 optional ) other methods that must be called before the class knows everything it needs to to construct the table. I chose to have the data set as separate methods rather than clutter up the __construct() with 8 optional parameters which I'll never remember the order of.
I would recommend something like generateTable() instead of setTable(). This provides a situation where the name of the method clearly denotes what it does.
I would probably still use a setTable() method to actually set the property, though. Ideally, you could open the possibility of setting a previously defined table for further flexibility.
Yes, setX() is primarily used for setting a field X, though setX() may have some additional code that needs to run in addition to a direct assignment to a field. Using it for something else may be misleading to other developers.
I would definitely recommend against having a public setTable() and would say that setTable() could be omitted or just an unused private method depending upon your requirements.
It sounds like the activity to generate the table is more of a view of other properties on the object, so you might consider moving that to a private method on the object like generateHtmlTable(). This could be done during construction (and upon updates to the object) so that any subsequent calls to getTable() will return the the appropriate HTML.