Reputation: 97
I have two classes that need to pass data between each other. The first class instantiates the second. The second class needs to be able to pass information back to the first. However I cannot instantiates the ClassOne
again from class two. Both classes are running off a shared timer where they poll different things so while they share the timer they cannot share the objects they poll.
My current solution (that works) is to pass a method to ClassTwo
and used to send data back up but I feel this might be a bit hack-ey and the wrong way to go about it.
classOne():
def __init__(self,timer):
self.classTwo = classTwo(self.process_alerts,timer)
self.classTwo.start
def process_alerts(alert_msg):
print alert_msg
classTwo():
def __init__(proses_alerts,timer)
self.process_alerts = process_alerts # <----- class ones method
def start(self):
check for alerts:
if alert found:
self.alert(alert_msg)
def alert(self,alert_msg):
self.process_alert(alert_msg) # <----- ClassOnes method
Thank you for your time.
Upvotes: 1
Views: 73
Reputation: 55932
You could remove/minimize the coupling between the classes! I found this sort of architecture maps really well to sharing data by communicating across a Queue.
By using Queue you can decouple the two classes. The producer (ClassTwo
) can check for messages, and publish them to a queue. It no longer needs to know how to correctly instantiate a class or interact with it, it just passes a message.
Then a ClassOne
instance could pull messages from the queue, as they become available. This also lends well to scaling each instance independent of each other.
ClassTwo -> publish to queue -> Class One pulls from queue.
This also helps with testing as the two classes are completely isolated, you can provide a Queue to either class.
Queues also usually provide operations that support blocking until message becomes available, so you don't have to manage timeouts.
Upvotes: 2
Reputation: 77902
Nothing prevents you from passing the current ClassOne
instance (self
) to it's own ClassTwo
instance:
class ClassOne(object):
def __init__(self):
self.two = ClassTwo(self)
self.two.start()
def process_alert(self, msg):
print msg
class ClassTwo(object):
def __init__(self, parent):
self.parent = parent
def start(self):
while True:
if self.has_message():
self.parent.process_alert(self.get_message())
Note that in this context "parent" means it's a containment relationship ("has a"), it has nothing to do with inheritance ("is a").
If what bugs you is that ClassOne
is responsible for instanciating ClassTwo
(which indeed introduce a strong coupling), you can either change ClassOne
so it takes a factory:
class ClassOne(object):
def __init__(self, factory):
self.other = factory(self)
self.other.start()
# etc
and then pass ClassTwo
as the factory:
c1 = ClassOne(ClassTwo)
So you can actually pass anything that returns an object with the right interface (makes unittesting easier)
Or - at least in your (I assume striped down) example - you could just make ClassOne
pass itself to ClassTwo.start()
and explicitely pass ClassTwo
instance to ClassOne
, ie:
class ClassOne(object):
def __init__(self, other):
self.other.start(self)
def process_alert(self, msg):
print msg
class ClassTwo(object):
def start(self, parent):
while True:
if self.has_message():
parent.process_alert(self.get_message())
c2 = ClassTwo()
c1 = ClassOne(c2)
Or even simpler remove the call to ClassTwo.start
from ClassOne
and you don't need any reference to a ClassTwo
instance in ClassOne.__init__
:
class ClassOne(object):
def process_alert(self, msg):
print msg
class ClassTwo(object):
def start(self, parent):
while True:
if self.has_message():
parent.process_alert(self.get_message())
c1 = ClassOne()
c2 = ClassTwo()
c2.start(c1)
which is as decoupled as it can be but only works if ClassTwo
only needs ClassOne
instance in start()
and methods called from start
and ClassOne
doesn't need to keep a reference on the ClassTwo
instance either.
Upvotes: 2