noframes.linuxjournal.com/lj-issues/issue84/4540.html -> www.linuxjournal.com/article.php?sid=4540
An explanation of the mix-in programming style as applied in Python. Mix-in programming is a style of software development where units of functionality are created in a class and then mixed in with other classes. This might sound like simple inheritance at first, but a mix-in differs from a traditional class in one or more of the following ways. Often a mix-in is not the primary superclass of any given class, does not care what class it is used with, is used with many classes scattered throughout the class hierarchy and is introduced dynamically at runtime. There are several reasons to use mix-ins: they extend existing classes in new areas without having to edit, maintain or merge with their source code;
So while mix-ins are not a distinct technical feature of Python, the benefits of this technique are worth studying. Python provides an ideal language for mix-in development because it supports multiple inheritance, supports full-dynamic binding and allows dynamic changes to classes. Before we dive into Python, let me admit that mix-ins are old hat. The first time I saw mix-in programming by that name was when reviewing the now-defunct Taligent Project, known for its Pink operating system and CommonPoint application framework. However, since C does not support language feature 2, full-dynamic binding, or language feature 3, dynamic changes at runtime, Im not surprised that the approach didnt bring to fruition all its inventors had hoped for. I have also seen another instance of mix-in programming under a different name. Objective-C has a nifty language feature called categories that allows you to add and replace methods of existing classes, even without access to their source code. This is great for repairing existing system classes and extending their capabilities. Also, combined with an ability to load libraries dynamically, categories are quite effective in improving the structure of applications and reducing code. The grapevine informs me that Symbolics object-oriented Flavors system is most likely the earliest appearance of bona fide mix-ins. The designers were inspired by Steves Ice Cream Parlor in Cambridge, Massachusetts where customers started with a basic flavor of ice cream vanilla, chocolate, etc.
It continues to work even if the class inheritance or method definitions are altered at runtime. One thing to keep in mind is the order of searching with regard to multiple inheritance. The search order goes from left to right through the base classes, and for any given base class, goes deep into its ancestor classes. When you create mix-ins, keep in mind the potential for method names to clash. By creating distinct mix-ins with well-named methods you can generally avoid any surprises. Most Python things, whether they are lists, dictionaries, classes or instances, have a set of accessible attributes. Python classes have an attribute named __bases__, which is a tuple of their base classes. In the following session with the Python interactive interpreter seen in Listing 1, we create two classes and then later change the inheritance.
Installing a Mix-in Dynamically The first statement above changes the base classes of Person. By using as opposed to we avoid accidentally removing existing base classes, especially if a future version of the code makes Person inherit from another class. Also, the funny looking expression, Friendly, , specifies a tuple that would normally simply be enclosed in parenthesis. However, while Python readily recognizes <IfCourier>x,y<I$f$> as a tuple of two elements, it recognizes <IfCourier>x<I$f$> as a parenthesized expression. MySQLdb Cursor Mix-ins The most straightforward way to apply mix-ins is at design time within the construction of a module. One of the more famous third-party modules for Python, MySQLdb, does exactly this.
The design of this method reflects the fact that Python objects often provide information through both attributes and methods. A Mix-in for Uniform Value Access A useful application of this mix-in is to implement generic code for writing logs see Listing 3. Applying the NamedValueAccessible Mix-in for Logging By simply adding new keys to the logColumns method, the log can be expanded without having to modify the code that generates it, which is found in logEntry . More importantly, you can imagine that logColumns could read its list of fields from a simple configuration file. The transaction object itself is free to provide the given values via either methods or attributes, due to the flexibility of the valueForKey method. Making mix-ins flexible increases their utility and is an art that can be developed over time. Mixing It in after the Fact So far we have seen examples of using mix-ins during the construction of classes. However, Pythons dynamic nature also allows us to mix in functionality at runtime. The simplest technique for doing so is to modify the base classes of the given class, as described earlier.
In the construction of internet applications, keeping domain classes separate from interface classes is generally a good idea. Domain classes represent the concepts, data and operations of a specific application. They are independent of operating system, user interface, database, etc. Some writers refer to domain objects as business objects, model objects or problem space objects. Keeping the domain and interface separate makes sense for various reasons. An individual focus is created for two key areas that are largely independent: What is the subject material of the problem? New interfaces can be constructed without modifying or rewriting the domain classes. Domain classes for a story publishing system might include Story, Author and Site. These classes contain essential attributes such as title, body, name, e-mail, etc.
Existing subclasses of Story are in no way affected by simply creating a new Story class or subclass. But a dynamic mix-in for Story will also affect Editorial, Feature and Column. That is why many times the static approach does not work in practice, thereby making the dynamic approach not only clever, but necessary. Also, consider the case where Story objects are created in parts of the code where Story is hard-coded. In this situation, creating subclasses of Story will have no effect on the code that ignores them. One warning regarding dynamic mix-ins: they can change the behavior of existing objects because they change the classes of those objects. This could lead to unpredictable results, as most classes are not designed with that type of change in mind. The safe way to use dynamic mix-ins is to install them when the application first starts, before any objects are created.
User import User MixInUser, UserMixIn One solution is to bind the mix-ins to their target classes by name and have the application install these at startup. For example, all mix-ins could be named directly after the class they modify and put into a MixIns/ directory. Detecting and Installing Mix-ins Named after Their Classes Additional Uses While its fun to explore more sophisticated versions of the MixIn function, the most important key is the ability to apply them in order to improve your software. Here are some additional uses to stimulate your imagination: A class could augment itself with a mix-in after reading a configuration file. For example, a web server class could mix in Threading or Forking depending on how its configured. A program could provide for plug-ins: software packages that are located and loaded at launch time to enhance the program. Those who implement plug-ins could make use of MixIn to enhance core program classes. Summary Mix-ins are great for improving modularity and enhancing existing classes without having to get intimate with their source code. This in turn supports other design paradigms, like separation of domain and interface, dynamic configuration and plug-ins. Pythons inherent support for multiple inheritance, dynamic binding and dynamic changes to classes enables a very powerful technique. As you continue to write Python code, consider ways in which mix-ins can enhance your software.
|