Announcement Announcement Module
Collapse
No announcement yet.
Wrapping a wrapper Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wrapping a wrapper

    OK, so now things are going really well, I have another (silly) question!

    Can I *wrap* a wrapper?

    Here's the class I want to wrap (simplified down):
    Code:
    class CommentatorCharacterObserver(MethodInterceptor):
        def __init__(self):
            pass
            
        def invoke(self, invocation):        
            tags = self.whoTaggedWho(invocation)
            
        def whoTaggedWho(self, invocation):
            character = invocation.instance
            return [character, character]
    and I'm wrapping with:

    Code:
    pointcutAdvisor = RegexpMethodPointcutAdvisor(advice = [WrappingInterceptor()], patterns = [".*"])
    self.characterAdvisor = ProxyFactoryObject(target = CommentatorCharacterObserver(), interceptors = pointcutAdvisor)
    Now, here's my output (with the debug logger on)
    Code:
    > : grep "CommentatorCharacterObserver" output
    2008-11-10 18:27:08,262 - springpython.aop.RegexpMethodPointcut - DEBUG - Candidate is [CommentatorCharacterObserver.invoke]; pattern is [.*]; matched=True
    2008-11-10 18:27:13,169 - springpython.aop.RegexpMethodPointcut - DEBUG - Candidate is [CommentatorCharacterObserver.invoke]; pattern is [.*]; matched=True
    2008-11-10 18:27:13,171 - springpython.aop.RegexpMethodPointcut - DEBUG - Candidate is [CommentatorCharacterObserver.invoke]; pattern is [.*]; matched=True
    2008-11-10 18:27:16,450 - springpython.aop.RegexpMethodPointcut - DEBUG - Candidate is [CommentatorCharacterObserver.invoke]; pattern is [.*]; matched=True
    2008-11-10 18:27:16,452 - springpython.aop.RegexpMethodPointcut - DEBUG - Candidate is [CommentatorCharacterObserver.invoke]; pattern is [.*]; matched=True
    It never even looks into CommentatorCharacterObserver.whoTaggedWho, but does happily watch invoke. Am I formulating something wrong?

    I know that wrapping a wrapper is a bizarre thing to do. My intention is that the Commentator will be output agnostic, and then a database aspect will wrap round it and store things in a database. So here, whoTaggedWho would be wrapped by the database, so the event will be saved across sessions. Is there a more intelligent way to do this with AOP?

    This is an experiment into whether the final project looks nicer than an OOP implementation, which it might well not!

    I'm sorry to have been such a bother all the time
    Last edited by Lewisham; Nov 10th, 2008, 09:47 PM.

  • #2
    First of all, this isn't bothersome. I need real-life examples and use cases of problems people are solving, or this framework doesn't really mean much.

    Now to address your question at hand: the way I see things, aspects are typically used to intercept the mainline code and then do a job. I admit it is tricky wrapping my head around what you are trying to do. But, what may be tricky is wrapping my head around "how" you are proposing to do it.

    Based on your comments, you want to somehow store the results. Now, I may not be answering "how" you want to do it, but assuming persistence of some type is the question at hand, this is how I would go about it. I suggest injecting your aspect with the task to do, instead of wrapping it with another layer. This seems simpler to me, and requires less smarts about the the actual framework. I'm afraid that to wrap the wrapper, you are forcing yourself to understand more and more how it actually does its job, which takes you away from your game code.

    Code:
    class CommentatorCharacterObserver(MethodInterceptor):
        def __init__(self, storage_strategy=None):
            self.storage_strategy = storage_strategy
            
        def invoke(self, invocation):   
            results = invocation.proceed()
            self.storage_strategy.store(invocation, results)
            return results
    
    class Storage(object):
        def store(self, invocation, results):
            print "This would be the place to store the information somewhere, such as in a database (using DatabaseTemplate of course!)"
    If I remember where you were plugging this in:
    Code:
    c = ProxyFactoryComponent(target = Character(Circle(Constants.radius), brain), interceptors = tagAdvisor)
    It seems you want to observe things happening to Character objects. How about this?
    Code:
    class CharacterObserver(MethodInterceptor):
        def __init__(self, storage_strategy=None):
            self.storage_strategy = storage_strategy
            
        def invoke(self, invocation):   
            results = invocation.proceed()
            self.storage_strategy.store(invocation, results)
            return results
    
    class Storage(object):
        def store(self, invocation, results):
            print "LOG: ACTION=%s INSTANCE=%s RESULTS=%s" % (invocation.method_name, invocation.instance, str(results))
    
    # Plug this in to where you construct the Character object
    tagAdvisor = CharacterObserver(storage_strategy=Storage())  # This is an aspect with a plugged-in behavior
    pointcutAdvisor = RegexpMethodPointcutAdvisor(advice = [tagAdvisor], patterns = [".*"])
    c = ProxyFactoryComponent(target = Character(Circle(Constants.radius), brain), interceptors = pointcutAdvisor)
    Some more tweaks to your storage strategy, and you can track the time it happened, what arguments are tied to that instance, anything! And you don't have to dig into the framework, but instead can focus on your game code.
    Last edited by gregturn; Nov 11th, 2008, 08:12 AM.

    Comment


    • #3
      Hey Greg,
      Yeah, this is how I instinctively want to do it. I'm actually doing this as part of research assignment for a grad class, which is why my request was sort of nuts.

      One of the questions was "If I want to save things in a database, can I make the original commentator aspect agnostic of what happens to it's output using aspects, rather than an object that conforms to a certain interface? Would this be elegant code if it does work?"

      I'm happy to accept the answer is "no", I just wanted to check in with you. I'm trying to find the limits of sane AOP programming

      Your code is what I'll go with, as I can't see any way of making it any more elegant than that; the storage strategy is able to poke around with the invocation and get the information it needs to, and it does look a lot like an aspect, albeit not explicitly wrapped. It all makes for a good write-up!

      Like I said, I'll be releasing the code when it's done, so you can see the mess I've made using your lovely module

      Comment

      Working...
      X