Plugin framework - Overcomplicating things?

H

hajducko

As a side project and a learning experience and ultimately, a good
tool for my department, I started developing a simple jabber bot for
our work's conference server, with the intention of making it capable
of running specific commands and utilities. I realize there are other
bots out there, but I thought this would be a good first python
project for me. Most of my current scripts/utilities are in perl or
php, so the OO world is a little new.

In any case, I wrote up a Bot class, got it to connect, join rooms,
see chat, and the world rejoiced. Now, instead of writing a
monolithic function for the message handler to deal with all the
incoming text and all the possible cool things I could do with the bot
like intranet lookups, dns checks, etc, I thought to myself: "self,
wouldn't it be cool if you made a plugin framework that could read in
a bunch of plugins and the bot could hand off the text to a plugin
that was looking for that command and it could do the job". Then the
smarter side of myself said "self, you have no frak'n idea how to do
that".

So I've been scouring this list for days, reading some of the past
conversations. I investigated the trac component system, downloaded
the source and tried my best to make heads ( or tails, take your
pick ) of it. I looked at setuptools and eggs, I looked at Marty's
simple framework at http://gulopine.gamemusic.org/2008/jan/10/simple-plugin-framework/
and I searched all over google for anything, even stuff that was non-
python specific and just detailed plugin frameworks in theory ( I
didn't find any good ones, so if you have some links, gimme. :) ) and
I'm sorry say, but I still don't get it. While I understand half of
it, I'm still not getting the point of using it for something like
what I'm trying to accomplish.

All this comes to my question - am I overcomplicating this project? I
can understand the use of something like the trac component system if
I had multiple components and plugins that handled different areas of
my project and different points of interaction, but I don't. I've got
exactly one spot where I want to check all my plugins and hand off the
message to which ever ones are looking for that command. So really,
should I even bother with trying to setup some framework for this or
should I just be doing a simple loop over a directory, importing all
the plugins and storing them in a list and then looping over them in
the message handler to see which ones were looking for the command and
letting them do their thing? I don't see the advantage I'd get from
implementing something more complicated at this point. If you could
show me the yellow brick road or offer any pointers, I'd appreciate
it. I'm more than willing to go off reading more pages, but when the
first 5 pages of a google search for 'plugin framework design' shows
all purple, visited links and I'm still not getting it, I finally
decided to turn here to the list and get some professional advice.

As an aside, if there is anyone who is an experience developer and
designer and is willing to take some private correspondence, please
let me know. I feel embarrassed for asking, but I've got a alot of
questions that I don't want to litter this list with and would rather
voice them in private.

Thanks,

steve
 
G

Gabriel Genellina

En Thu, 27 Mar 2008 01:50:56 -0300, (e-mail address removed)
All this comes to my question - am I overcomplicating this project? I
can understand the use of something like the trac component system if
I had multiple components and plugins that handled different areas of
my project and different points of interaction, but I don't. I've got
exactly one spot where I want to check all my plugins and hand off the
message to which ever ones are looking for that command.

As you said, it looks like you're really overengineering your design then.
So really,
should I even bother with trying to setup some framework for this or
should I just be doing a simple loop over a directory, importing all
the plugins and storing them in a list and then looping over them in
the message handler to see which ones were looking for the command and
letting them do their thing?

That may be an option.
You may want to setup a simple registry mechanism, so the plugin modules
look like:

### begin niceplugin.py ###
class AVeryNicePlugin(object): # or perhaps using a suitable base class
def handle_message(self, message):
...

from plugin import PluginRegistry
PluginRegistry.register(AVeryNicePlugin)
### end niceplugin.py ###

Your application scans a known directory for files ending in "plugin.py"
and imports them; the modules register themselves any class (or classes),
and at appropiate times the application calls some method(s) of the
registered plugins.
As an aside, if there is anyone who is an experience developer and
designer and is willing to take some private correspondence, please
let me know. I feel embarrassed for asking, but I've got a alot of
questions that I don't want to litter this list with and would rather
voice them in private.

Why not? Get another free account, post using a pseudonym, and nobody will
know that *YOU* were the guy that asked the most stupid question of the
week :)
 
A

André

En Thu, 27 Mar 2008 01:50:56 -0300, (e-mail address removed)


As you said, it looks like you're really overengineering your design then.

You could set thing up so that there's no need to loop over the
plugins.
What you can do is register a plugin (as mentioned to you before by
Gabriel - see below) and create an entry in a handler dict so that you
can directly dispatch the message to the appropriate handler without
having to loop over a list of them. Something like
handlers[message]()
That may be an option.
You may want to setup a simple registry mechanism, so the plugin modules
look like:

### begin niceplugin.py ###
class AVeryNicePlugin(object): # or perhaps using a suitable base class
def handle_message(self, message):
...

from plugin import PluginRegistry
PluginRegistry.register(AVeryNicePlugin)
### end niceplugin.py ###

Your application scans a known directory for files ending in "plugin.py"
and imports them; the modules register themselves any class (or classes),
and at appropiate times the application calls some method(s) of the
registered plugins.

An alternative (which we found simpler with Crunchy) is to not have a
class-based structure, but working with simple modules and functions.
All modules are put in the "plugin" directory which are imported at
the beginning. Each module contain at least two functions:
1. register() which create the handlers dict entry so that it point
out to the appropriate function.
2. one or more function that is called based on the message received.

Hope it helps,

André
 
H

hajducko

En Thu, 27 Mar 2008 01:50:56 -0300, (e-mail address removed)
<[email protected]> escribió:
As you said, it looks like you're really overengineering your design then.

You could set thing up so that there's no need to loop over the
plugins.
What you can do is register a plugin (as mentioned to you before by
Gabriel - see below) and create an entry in a handler dict so that you
can directly dispatch the message to the appropriate handler without
having to loop over a list of them. Something like
handlers[message]()




That may be an option.
You may want to setup a simple registry mechanism, so the plugin modules
look like:
### begin niceplugin.py ###
class AVeryNicePlugin(object): # or perhaps using a suitable base class
def handle_message(self, message):
...
from plugin import PluginRegistry
PluginRegistry.register(AVeryNicePlugin)
### end niceplugin.py ###
Your application scans a known directory for files ending in "plugin.py"
and imports them; the modules register themselves any class (or classes),
and at appropiate times the application calls some method(s) of the
registered plugins.

An alternative (which we found simpler with Crunchy) is to not have a
class-based structure, but working with simple modules and functions.
All modules are put in the "plugin" directory which are imported at
the beginning. Each module contain at least two functions:
1. register() which create the handlers dict entry so that it point
out to the appropriate function.
2. one or more function that is called based on the message received.

Hope it helps,

André

Thanks for the replies. André, you're alternative was exactly what I
was thinking of falling back to, rather than setting up class-based
plugins. Like I said, seems like a whole plugin framework would be
wayyyy too complicated. The only reason I figured I'd loop over the
available plugins was in case two were defined to handle the same
message. I figured something like setting an 'command' attr in the
module and just checking for that. Either way, I think I'll stay away
from trying for a real framework in this case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top