I have a class which is essentially a collection of methods for some data transformations. In another words I have some data in my files and I use a few different code snippets to transform the textual data into something that I can easily query.
Now the methods often reuse each-other and as the core data is changing I'd like to simply cache the results of each method, for the speed reasons.
I don't want to change each method by adding:
^ methodsCache ifNil: [ methodsCache := "compute" ]
I want to use the power of Pharo reflection to accomplish my task without touching much of code.
One idea that I had is if I can run some code before each method, thing I can either return a cached value or continue the execution of the method and cache it's result
You could use the Reflectivity framework to add pre and post meta links to your methods. A link could check a cache before execution transparently.
link := MetaLink new
metaObject: self;
selector: #cachedExecute:;
arguments: #(selector);
control: #before.
(MyClass>>#myMethodSelector) ast link: link.
This code will install a meta link that sends #cachedExecute: to a MyClass object with the argument #myMethodSelector. The link is installed on the first AST node of the compiled method (of that same method selector, but could be on another method). The #control: message ensures that the link will be executed before the AST node is executed.
You can of course install multiple meta links that influence each other.
Note that in the above example you must not send the same message (#myMethodSelector) again inside of the #cachedExecute: method since you'd end up in a loop.
Update
There's actually an error in the code above (now fixed). The #arguments: message takes a list of symbols that define the parameters of the method specified via #selector:. Those arguments will be reified from the context. To pass the method selector you's use the #selector reification, for the method context the #context reification and for method arguments #arguments. To see which reifications are available, look at the #key on the class side of the subclasses of RFReification.
One idea that I had is to define
doesNotUnderstand: aMessage
aMessage selector beginsWith: 'cached' ifFalse: [ ^ super doesNotUnderstand: aMessage ].
^ cache at: aMessage selector ifAbsentPut: [
self perform: aMessage selector allButFirst: 6 ]
This way the only thing you have to do is to replace all message sends like self methodName with self cachedmethodName (or self cachedMethodName but then you have to do additional lowercase workaround in doesNotUnderstand:)
Another well-known option would be to replace your new and return a caching proxy, delegating to the actual object
Related
I have a custom method in an ABAP class.
I used the 'Where used' tool to show where the class is called from but, as it turns out, it's called from somewhere else I didn't expect.
So what's the best way of showing a complete list of everything that calls the method?
Due to the wonders of object-oriented programming, an instance of a class can hide behind a reference to one of its base classes or interfaces it implements. For example:
DATA foo TYPE REF TO z_my_interface.
CREATE OBJECT foo TYPE z_my_class.
" lots of more code
foo->bar( ).
You can not find this reference to z_my_class->foo with its "Where Used" list, because at that code location foo could also be a reference to an instance of any other class which implements z_my_interface. But you might be able to find this if you don't just look at the where-used list of the method but at the where-used list of the whole class or the interface / base class which declares the method.
And then there are evil dynamic programming tricks like this which determine methods and classes at runtime:
DATA foo TYPE REF TO object.
CONSTANTS: classname TYPE string VALUE 'Z_MY_CLASS',
methodname TYPE string VALUE 'BAR'.
CREATE OBJECT foo TYPE (classname).
CALL METHOD foo->(methodname).
There is no chance to find this with the where-used tool. But if the class- and/or method name does actually appear in the code (it might not, for example if they are read from a customizing table) then you can use the report RS_ABAP_SOURCE_SCAN. This handy little tool allows you to select a set of ABAP programs and search for strings (and even regular expressions) within their sourcecodes.
However, if you know the method gets called when you do something specific as a user and just want to know where, then it can be easier to just set a debugger breakpoint in the method, run into it and check the call stack.
Sorted using the code_scanner transaction.
I have an object containing sensitive data that I want to marshal (using Marshal) without the sensitive data.
I'd like to be able to say:
def _dump(*args)
# Clean-up sensitive data
super
end
but this produces a 'no superclass method' error. Is there a way I can make my object behave the way I want in response to Marshal.dump, while using the default implementation?
I want Marshal.dump(my_obj) to work out-of-the-box without requiring the API consumer to remember to call a different method.
It may be that there is no superclass method for _dump. If it's defined on your object it's called. If not, the default handler is used.
You probably want to clone your object and remove the sensitive fields, returning that as a Hash inside your _dump function, then undo that within the _load method.
You can also read the documentation on Marshal where it describes the recommended methods.
What is the best way of doing delegation in Smalltalk, more specifically in Pharo? I know of the doesNotUnderstand strategy, but it does not delegates subclassResponsability messages.
I was thinking on something that delegates every message send not explicitly implemented on the class to some specified object, like I can do, for example, with #Delegate in Groovy. Is there some already known way of doing this?
doesNotUndersand: will only work on methods that the object does not understand (thus the name), so if you already have implemented a method it will not be used (as is the case with subclassResponsibility.
If you use Pharo 5 (which should be released this week (May 2016)), you could use MetaLinks. It's a bit of an overkill, however what you are doing doesn't seem right to begin with (why would you want to delegate subclassResponsibility)?
In either case, MetaLinks allow to attach runtime behavior to your methods, for example:
You have some method that you want to delegate
MyObject>>someMethod
^ self subclassResponsiblity
And an object to which you wish to delegate to…
MyObject>>delegate
^ delegate
So you create a MetaLink
link := MetaLink new
metaObject: [ :object :selector :arguments |
object delegate perform: selector withArguments: argument ];
selector: #perform:withArguments:;
arguments: #(object selector arguments);
control: #instead.
Which you can install to any method AST you want.
(MyObject>>someMethod ast) link: link.
Now every time the method will be called, instead (that's what the control: does) of executing the method, the arguments of the message (if any) will be given to the block in metaObject:.
Although this should work and is extremely powerful mechanism, right now there are serious disadvantages that currently being addressed:
no documentation
little tooling support (it's pretty hard to debug)
a lot of work (we are working on a framework that would ease this as you would want to easily install them and uninstall them everywhere you need, but it's not ready yet, so it has to be done by hand)
recompilation removes the link (see point above)
Summary
To summarize, this is possible to do with MetaLinks as I've shown, however at the moment it's quite a lot of work, but we are addressing those issues.
what Peter was talking about is, you can override the
subclassResponsibility, just like you did for the doesNotUnderstand method.
There is no need to override every senders of "self subclassResponsibility".
For example, just delegate to the implementation of doesNotUnderstand
subclassResponsibility
^ self
doesNotUnderstand: (Message selector: thisContext sender selector
arguments: thisContext sender arguments)
Im using the page object gem and selenium,
when filling in a sign up form, the form fills in correctly, but when clicking apply it errors saying the fields are required even though they are filled in.
this seems to be caused because the page object/selenium method isn't firing the javascript change method which is needed for the application to know the field has been filled in
this can be fixed by using code such as
on(SettingsPage).payment_method_account_number = number
#browser.execute_script("$('input[name=account_number]').change()")
but this is obviously not ideal and breaks the whole point of using page object in the first place by having to declare the fields name attribute again
is there a way better way to solve this problem than what i have shown?
To avoid duplicating an element definition within the page object as well as the execute_script script, you can pass the page object element to the script.
The underlying Selenium-WebDriver (and therefore the Page-Object gem) supports an arguments array within the script being executed. This arguments array basically takes a Selenium-WebDriver elements and converts them to something usable by the script. The Page-Object execute_script method handles the conversion of elements to the right type, so you simply need to:
Declare a script that uses the arguments array
Pass in a PageObject::Element
For example, let us assume your page object has used the accessor:
text_field(:payment_method_account_number, :name => 'account_number')
Therefore, the page object will have a payment_method_account_number_element method that returns the PageObject::Element for this text field.
Within the script you want to execute, you can replace how you locate the element with the arguments array and pass in the PageObject::Element to the execute_script method:
execute_script("$(arguments[0]).change();", payment_method_account_number_element)
Then you can re-write the call to on as:
on(SettingsPage) do |page|
page.payment_method_account_number = number
page.execute_script("$(arguments[0]).change();", page.payment_method_account_number_element)
end
(Or, as Dane pointed out, put this into a method in the page object.)
I have had a similar problem but the event was "onblur" instead of "onchange". I would imagine the on change would fire, but if it doesn't you could use an approach similar to mine. I ended up creating a widget that redefined the "#{name}=" method to also call the event on the spot. It's a little bit more complicated, but it centralizes all the magic to one class and keeps the code brief.
After reading this post,
http://mcc.id.au/2013/lca-webidl/
I have some questions in the page 20,
What happens when you pass too many/few arguments.
What happens when you grab a Function corresponding to an IDL operation and apply it to some other type of object.
How interface inheritance corresponds to a prototype chain.
How DOM objects are stringified.
Can anyone give a specific explanation or example to these points.
Thanks
If you pass too many arguments the extra ones are ignored. Try document.getElementsByTagName("a", "b"). If you pass too few, you get an exception: document.getElementsByTagName().
If you apply a WebIDL operation to the wrong type of object, you get an exception. See http://heycam.github.io/webidl/#es-operations step 4 under "Try running the following steps". document.getElementsByTagName.call(document.body, "div") for example.
Interface inheritance corresponds to a prototype chain as described at http://heycam.github.io/webidl/#interface-prototype-object but in brief if you have interface Foo : Bar { }; then Object.getPrototypeOf(Foo.prototype) === Bar.prototype. So for example, the prototype of HTMLElement.prototype is Element.prototype.
DOM objects with a stringifier defined (e.g. HTMLAnchorElement) are stringified however the relevant specification defines them to be. All other objects become "[object MostDerivedInterfaceName]".