1

I have test code written in Python, using classes.

The test environment has two types of hosts - app hosts, where applications run, and storage hosts, where storage components run.

I have two classes, each representing the type of host:

class AppHost_Class(object):
    def __init_(self, ip_address):
        # etc.

    # This method handles interfacing with the application
    def application_service(self):

    # This method handles the virtual storage component
    def virtual_storage(self):

    # This method handles caching
    def cache_handling(self):


class Storage_Server_Class(object):
    def __init_(self, ip_address):

    # This method handles interfacing with the storage process
    def storage_handling(self):

    # This method handles interfacing with the disk handling processes
    def disk_handling(self):

The problem is that the topology can change.

Topology #1 is this: - Application Host runs * Application processes * Virtual storage processes * Cache processes

  • Storage Host runs
    • Storage processes
    • Disk handling processes

My current test code handles Topology #1

However, we also want to support another Topology (Topology #2)

  • Application Host runs

    • Application processes
  • Storage Host runs

    • Virtual storage processes
    • Cache processes
    • Storage processes
    • Disk handling processes

How can I refactor the classes so that for Topology 1, the classes and its methods are the same, but for Topology 2, the Storage_Server_Class gets some of the methods from the AppHost_Class?

I was thinking of making a child class like this:

class Both_Class(AppHost_Class, Storage_Server_Class):

But I don't want to do this because I don't want the applcation_service method to be available to Both_Class.

Is there a way to just map a few methods in AppHost_Class into the Storage_Server_Class?

2
  • Can't you just put the methods to be shared into another class which AppHost_Class inherits from and introduces the application_service method to, and then inherit from that other class and Storage_Server_Class for your Both_Class. Although - does it really matter if you have that method available in both class? Commented Jul 20, 2017 at 22:30
  • That would be one way to do it Jon. But it would require some code changes because to make the example, I simplified it. These classes don't have 2-3 methods/attributes. It's more like 30+ methods and 30+ attributes. This would be a major recoding effort. Commented Jul 20, 2017 at 23:44

3 Answers 3

1

Here is an example of a class B that shares exactly one method defined in class A:

class A:
    def a1(self):
        pass
    def a2(self):
        pass

class B:
    def __init__(self, instance_of_a):
        self.a2 = instance_of_a.a2

a = A()
B(a)
Sign up to request clarification or add additional context in comments.

Comments

1

It sounds to me like you want three base classes. One for App stuff, one for VirtualStorage (and cache) stuff and one for Storage (and disk) stuff. Then you can make child classes for your two topologies that mix the desired methods together.

For topology 1, you have a class that inherits from both the App and the VirtualStorage base classes (and you use the Storage base class unmodified). For topology 2, you create a class that inherits from the VirtualStorage and the Storage base classes and use the App base class unmodified.

Example code:

class App:
    def do_app_stuff(self):
        pass

class VirtualStorage:
    def do_virtual_storage_stuff(self):
        pass

class Storage:
    def do_storage_stuff(self):
        pass

# topology 1
class Top1App(App, VirtualStorage):
    pass

Top1Storage = Storage

# topology 2
Top2App = App

class Top2Storage(VirtualStorage, Storage):
    pass

You might not need the aliased names for the base classes you're using directly in the different topologies, I just threw those in to make it look extra nice.

Comments

1

Split the methods up into three classes then combine as needed.

#class NetworkObject(object):    # Python 2.7
class NetworkObject:
    def __init__(self, ip_address):
        self.ip_address = ip_address

class AppHost(NetworkObject):
    def application_service(self):
        print('app service', self.ip_address)

class Storage_Server(NetworkObject):
    def storage_handling(self):
        print('storage handler', self.ip_address)
    def disk_handling(self):
        print('disk handler', self.ip_address)

class Foo(object):
    def virtual_storage(self):
        print('virtual storage', self.ip_address)
    def cache_handling(self):
        print('cache handling', self.ip_address)

topology_1, topology_2 = True, False

# Topology 1
if topology_1:
    class AppHost_Class(AppHost, Foo):
        pass
    class Storage_Server_Class(Storage_Server):
        pass

# Topology 2
if topology_2:
    class AppHost_Class(AppHost):
        pass
    class Storage_Server_Class(Storage_Server, Foo):
        pass

Another option would be to define the two classes with the methods they will always include,

#class NetworkObject(object):    # Python 2.7
class NetworkObject:
    def __init__(self, ip_address):
        self.ip_address = ip_address

class A(NetworkObject):
    def application_service(self):
        print('app service', self.ip_address)

class B(NetworkObject):
    def storage_handling(self):
        print('storage handler', self.ip_address)
    def disk_handling(self):
        print('disk handler', self.ip_address)

... define methods you would like to mix and match

def virtual_storage(self):
    print('virtual storage', self.ip_address)

def cache_handling(self):
    print('cache handling', self.ip_address)

... and conditionally add the methods to the classes

topology = 1
if topology == 1:
    A.virtual_storage = virtual_storage
    A.cache_handling = cache_handling

if topology == 2:
    B.virtual_storage = virtual_storage
    B.cache_handling = cache_handling

You may want to define the extra methods in the parent/base class but have them raise an exception unless a topology has been applied

#class NetworkObject(object):    # Python 2.7
class NetworkObject:
    def __init__(self, ip_address):
        self.ip_address = ip_address
    def virtual_storage(self):
        raise NotImplementedError
    def cache_handling(self):
        raise NotImplementedError

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.