Showing posts with label polymorphism. Show all posts
Showing posts with label polymorphism. Show all posts

Wednesday, March 31, 2010

Polymorphic Libvirt

The Libvirt virtualization library is great for interacting with heterogeneous hypervisors. Depending on the hypervisor connection, most domains support the same virtual machine interfaces. For instance, you can you the same code to start and stop virtual machines using Libvirt for both KVM and Xen.

But when the operation isn't supported for a particular hypervisor type, you better be prepared to handle this scenario. Libvirt only defines a single exception type but we can determine that it is a hypervisor interface support issue by looking at the error code.

This is shown below. The following operation on the domain will fail on KVM.
import libvirt

if __name__ == "__main__":

conn = libvirt.open("qemu:///system")

for id in conn.listDomainsID():

domain = conn.lookupByID(id)

try:
domain.reboot(0)
except libvirt.libvirtError, e:
if e.get_error_code() == libvirt.VIR_ERR_NO_SUPPORT:
print "Cannot Reboot"

Friday, October 2, 2009

Polymorphism And Inheritance

One of the main key principles of the object-oriented software development paradigm is polymorphism. Polymorphism in the context of object-oriented design is the ability to define behavior that varies by type, as opposed to varying by interface. For instance, in functional programming design, to invoke different behavior, a different function name is invoked. In object-oriented design, behavior can be invoked on instances by using a single method name. This means that the behavior that is actually executed depends on the type.

Inheritance, another key principle of object-oriented design, plays a big role in implementing polymorphic behavior. Given a class hierarchy, the topmost classes will often define a base interface for behavior. These base methods often go unimplemented. It is the classes that inherit from the base class that are responsible for implementing the behavior. This means that subclasses even further down the inheritance hierarchy can also define this behavior.

Any descendants of the base class can be used in the same context and will behave as expected. Below is an example illustrating the difference between inheriting a method and providing an implementation for it and inheriting an already-defined method.
#Example; Polymorphism and inheritance.

#Do imports.
import uuid
import timeit

#Simple person class.
class Person(object):

#Constructor. Initialize the data.
def __init__(self):
self.data={"first_name":"FirstName",\
"last_name":"LastName",\
"id":uuid.uuid1()}

#Return the first name.
def get_first_name(self):
return "first_name_%s"%(self.data["first_name"])

#Return the last name.
def get_last_name(self):
return "last_name_%s"%(self.data["last_name"])

#Return the id.
def get_id(self):
raise NotImplementedError

#Simple manager class that extends Person.
class Manager(Person):

#Constructor. Initialize the Person class.
def __init__(self):
Person.__init__(self)

#Return the manager id.
def get_id(self):
return "manager_%s"%(self.data["id"])

#Simple employee class that extends Person.
class Employee(Person):

#Constructor. Initialize the Person class.
def __init__(self):
Person.__init__(self)

#Return the employee id.
def get_id(self):
return "employee_%s"%(self.data["id"])

#Main.
if __name__=="__main__":

#Employee.get_id() timer.
t_employee_get_id=timeit.Timer("Employee().get_id()",\
setup="from __main__ import Employee")

#Manager.get_id() timer.
t_manager_get_id=timeit.Timer("Manager().get_id()",\
setup="from __main__ import Manager")

#Employee.get_first_name() timer.
t_employee_get_first_name=timeit.Timer("Employee().get_first_name()",\
setup="from __main__ import Employee")

#Manager.get_first_name() timer.
t_manager_get_first_name=timeit.Timer("Manager().get_first_name()",\
setup="from __main__ import Manager")

#Display the results.
print "Employee Get ID: ", t_employee_get_id.timeit(10000)
print "Manager Get ID: ", t_manager_get_id.timeit(10000)
print "Employee Get First Name: ", t_employee_get_first_name.timeit(10000)
print "Manager Get First Name: ", t_manager_get_first_name.timeit(10000)

Friday, March 20, 2009

SQL engine dialect in SQLAlchemy

Object relational mapping technology is used in object-oriented systems to provide a layer between the objects in the system, and the underlying relational database system. ORMs help reduce the time investment, and thus the cost as well, during development because developers can still think in an object-oriented way while interacting with the database. Tables in the database are classes in the code. Instances of these classes are rows in the database tables. This is an over-simplification of the problem. It isn't quite so straightforward as to generate standardized SQL statements based on what the instance is doing in the code. Not all database systems use a standard set of SQL. To further complicate matters, the various popular database systems don't even support the same features.

In any given language, there are different dialects of that language. For instance, if two people were engaged in a conversation, one person from the west coast of the country, the other from the east, there is bound to be some ambiguity even though they are speaking the same language. This could arise from a number of factors such as politics, or culturally-related customs. The same effect happens in technology. The language is SQL and while some database systems are very similar in some ways, they can be just different enough to cause an application to require a huge amount of duplicated code just so that the application can support multiple database systems. These are the systems that are supposed to speak the same language. SQLAlchemy addresses this issue by introducing the concept of a dialect. Every database system supported by SQLAlchemy defines a dialect. This isn't just a dialect for the SQL language alone but rather for the entire database system. We can do a lot more than merely execute SQL statements with SQLAlchemy so this is a requirement of the Dialect interface. This interface specifies what each dialect for a specific database must look like. For instance, with a specific dialect, we can specify whether the database accepts unicode SQL statements or not. With SQLAlchemy, there are other classes that do work related to communication with the database such as preparing SQL statements and generating schemas. All these are specified in the Dialect interface.

SQLAlchemy also defines a DefaultDialect class which provides the Dialect interface. This class actually implements some of the methods and attributes specified by the Dialect interface. Some of these methods and attributes are common across all supported database systems. The attributes and methods that are specialized for any given database, are simply overridden by that particular dialect implementation.

When a connection is established in SQLAlchemy, it will construct a new engine instance. This engine will then use the dialect specified in the connection string. For example, mysql would be considered a dialect. Method calls made through the constructed database engine instance are then delegated to the dialect. The dialect will then act accordingly for the database system it is using.

The Dialect interface and the implemented dialect classes in SQLAlchemy serve as a good example of polymorphism in object-oriented programming. There is a single interface that is used to invoke behavior and that behavior varies by type. This is a resilient design because it is loosely coupled and highly replaceable. We can implement our own database dialect and plug in into SQLAlchemy if we are so inclined.

Tuesday, February 10, 2009

The best way to call Python methods

What is the best way to invoke behaviour on objects in Python? Is there any better way than simply invoking a method which defines behaviour for a given instance? Or, given a class method, does the same principle not apply?

I would say it depends how you are using the instances or the classes. In the majority of cases, an instance is created, and some behaviour is invoked from that instance. However, the invoking code doesn't always know what behaviour is supported by the instance. For instance, consider the following example.
#Example; testing is a method is callable.

class MyClass:
def do_something(self):
print 'Doing something...'

def do_something(obj):
if hasattr(obj, 'do_something') and callable(obj.do_something):
obj.do_something()

if __name__=="__main__":
do_something(MyClass())

Here, we have a simple class, MyClass, that will "do something". We also have a function that will "do something". The purpose of the do_something() function is to accept some object as a parameter and invoke the "do something" behaviour on that object.

The problem I'm interested in here is that the do_something() function has no way of knowing for sure that it will be able to "do something" with the provided instance. It is the responsibility of the do_something() function to determine the invoking capability of the instance.

Now, what if we take the responsibility of know the invoking capabilities of the instance away from the do_something() function and gave it to the MyClass class? For example.
#Example; testing is a method is callable.

class MyClass:
def _do_something(self):
print 'Doing something...'
do_something=property(_do_something)

def do_something(obj):
try:
obj.do_something
except AttributeError:
pass

if __name__=="__main__":
do_something(MyClass())

In this example, obj.do_something is a managed attribute instead of a method. The do_something() function no longer needs to test the invoking capabilities of the provided instance. However, more responsibility has been added to MyClass.

Which solution is better? It depends. If our system were simple and we only needed managed attributes for all instances passed to do_something(), the latter approach may simplify things. I think in the majority of cases, the first approach offers more flexibility.