[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [coldsync-hackers] Writing conduits that read more then one DB.



On June 5, 2003 06:11 pm, Andrew Arensburger wrote:
> On Wed, 4 Jun 2003, Izzy Blacklock wrote:
> > WARNING:  A perlmonk I am not.  This is my first go at writing anything
> > serious in Perl, so go easy on me! :)
>
> 	See http://www.ooblick.com/text/perl/, if I may be forgiven some
> shameless self-advertising.

Thanks.  I'd found them already.  It's come in handy to help clarify some 
things for me. :)  I also have the Perl Cookbook and browsers open to 
Perldoc.com, Perlmonks.net, and search.cpan.org.  With such a wealth of 
information around, perl is turning out to be quite an easy language to 
learn! :)

I've played with it on and off for a while, but I've never had the time to 
really do much more then make small changes to code from others.  My NEED for 
a working Titrax conduit has given me the incentive to do something a little 
more meaningfull with it. :)

> > I'm thinking of building my conduit to use a config like this:
> >
> >    conduit dump {
> >                    path: /path/to/conduit/titrax;
> >                    type: ttrx/name;
> >                arguments:
> >                    DBpath: /path/to/user/.palm/backup
> > 		   Datebookdb: /path/to/user/.palm/backup/DatebookDB.pdb
> > 		   TitraxNoteDB: /path/to/user/.palm/backup/TitraxNoteDB.pdb
> > 		   TitraxDataDB: /path/to/user/.palm/backup/TitraxDataDB.pdb
> >            }
> >
> > My intention is that the last three arguments would be optional if DBpath
> > is set.  If none of the arguments are set, I'm thinking I can pull the
> > path off of InputDB, which would be set to
> > /path/to/usr/.palm/backup/TitraxNameDB.pdb (I think) given this config.
>
> 	This sounds reasonable. Personally, I would write the conduit to
> use the arguments above as default values. That is, by default it will
> assume that the Note database is "TitraxNoteDB.pdb", and is located in the
> same directory as InputDB (that is, take InputDB and chop off everything
> after the last "/").
> 	If the "TitraxNoteDB" argument is given, see if its value begins
> with a slash. If yes, then use the value as the path to the database.
> Otherwise, use it as a relative pathname under the default directory.

This is similar to my thinking, although I never thought of the possibility of 
allowing users to specify just the DB name without the path.  If I take that 
approach, then I could do something like this:

# Set default values
%HEADERS = (
        File            =>      "./TitraxTestOutput.txt"
        DBpath          =>      InputDB =~ /(.*)\/.*$/
        Datebookdb      =>      "DatebookDB.pdb"
        TitraxNoteDB    =>      "TitraxNoteDB.pdb"
        TitraxDataDB    =>      "TitraxDataDB.pdb"

);

Or not.  This produces a syntax error.  I'm guessing you can't set a hash 
value like this, or am I doing it wrong?  Oh well, I'll just set DBpath from 
within my dump function.  Unless there is a way to do what I'm trying here?

> > Given this constraint, I'm thinking I should create three sub
> > classes (one for each file) derived from Palm::raw.  This seems ugly, so
> > if someone has a better idea, please speak up! ;)  It'd be nice just to
> > have Palm::Titrax, not Palm::TitraxName, Palm::TitraxData,
> > Palm::TitraxNote.
>
> 	Well, you could always go with Palm::Titrax::Name,
> Palm::Titrax::Data, and Palm::Titrax::Note. This seems reasonably perlish.

Ok, that makes sense. If I understand modules correctly, I'd just create three 
.pm files, one for each of the data types, and put them all into a 
Palm/Titrax folder.  Than use package Palm::Titrax::Name, etc.  

> 	You said that Palm::PDB seems to be designed for dealing with only
> one file at a time. Actually, each subclass of Palm::PDB is intended to
> deal with only one _type_ of file. However, you can handle multiple files
> of the same type:
>
> 	use Palm::Memo;
>
> 	$memo1 = new Palm::PDB;
> 	$memo1->Load("Memo1.pdb");
>
> 	$memo2 = new Palm::PDB;
> 	$memo2->Load("Memo2.pdb");

That is what I was asking.  I had the idea in my head of creating a single 
subclass of Palm::PDB that would deal with all the files at once.  This 
doesn't seem like a reasonable, or possible approach anymore.  

> > If I take this approach, then I'd need a container class to hold four PDB
> > objects; three Titrax DBs and one Datebook.  The current coldsync class
> > only holds one.  Should I create a new class derived from coldsync to
> > accommodate the extra PDBs or just code a conduit with three local PDB
> > objects?
>
> 	Go with whatever you feel most comfortable with. I think both
> approaches are defensible. I guess the main criteria should be the extent
> to which you think you might reuse your code, and how much the extra
> encapsulation might get you.

Probably not much.  I'm working on a simple dump function for now.  I've taken 
the approach of using three local PDB objects (well, actually two, I don't 
need the data from TitraxDataDB).  As I build sync and fetch functions, I'll 
look at whether encapsulating things into a module would be useful or not.  
For now, I'm happy with the results I'm getting! ;)

> 	If you're used to C++- or Java-style object-oriented coding, it
> may come as a shock to learn that in Perl, you can just reach into another
> class or object and use its methods and members (you're discouraged from
> doing this because it isn't polite, is all).

I cut my OO teeth on C++.  I've never done much with it, but learned the 
principles of OO on it.  I was a little surprised at first to learn that perl 
didn't really have private members, but in the big scheme of things, I doubt 
it matters.  It's not like you could "accidently" mess with members of 
another module.  If you chose to, then any bugs that is created is your own 
fault, right! ;)

> 	In particular, take a look at the ParseArgs and ReadHeaders
> functions inside ColdSync.pm. They're just functions, not methods, so you
> can, in principle, use
>
> 	use ColdSync;
>
> 	&ColdSync::ParseArgs(@ARGV);
> 	&ColdSync::ReadHeaders();
>
> However, RTFS before you do this, to make sure they'll work for you.
> They're not documented, which is the standard Perl way of telling people
> not to use a certain function, but I don't remember whether this was
> because I thought they'd break if used outside of the ColdSync module, or
> simply because I hadn't cleaned them up to make this easy.

I guess if ReadHeaders() isn't a method, I can't overload it to handle my 
DBpath from above.  If I understand correctly, to make ReadHeaders() a 
method, I'd just add it to @EXPORT.  Could I then do something like this 
(assuming my logic is correct):

sub ReadHeaders {
	&ColdSync::ReadHeaders();
	if ( !defined $HEADERS{DBpath}  {
		( $HEADERS{ DBpath } = $HEADERS{ InputDB } )  =~ s!(.*)/.*$!$1!;
	}
}


> 	In other words, there's nothing magical about the ColdSync module:
> it just provides a convenient way to implement the most common type of
> conduit, but the ColdSync<->conduit interaction is fairly simple. See the
> "ColdSync Conduits" texinfo file for more details.
> 	So if it were me, I'd just raid ColdSync.pm for useful code and do
> things by hand, rather than subclassing it or whatever.
>
> 	The other possible class, which might be more useful, would be one
> that unites the four files being used.
> 	If you just load the four files, you'll have to keep track of
>
> relationships like the one you mentioned above:
> : Also, the TitraxNoteDB is cross indexed with it.  ie, the
> : project name for record 5 in the noteDB is record 5 in the NameDB.
>
> So if you delete NoteDB record #5, you'll also need to delete NameDB
> record #5. Presumably you'll write some helper functions to do this. If
> there's a lot of this sort of thing going on, you may want to write a
> Titrax class that keeps track of everything (it need not be subclassed
> from anything, since Titrax _has-a_ Titrax::Data, but not Titrax _is-a_
> Titrax::Data).
> 	But I guess this is a bit of a tangent.

I was thinking more along the lines of Titrax _is-a_ Coldsync, which _has-a_ 
Palm::Titrax::Data, Palm::Titrax::Name, Palm::Titrax::Note, and 
Palm::Datebook; all being Palm::PDB objects.   Coldsync provides the first 
PDB object, a Coldsync::Titrax would need to create three more and provide 
the logic which ties them together.  

I don't like the idea of simply raiding ColdSync.pm for my needs.  It's a 
simple answer, but it defeats the purpose of OO design.  Not to mention I'd 
have to watch your code for changes to the parts I raided.  

For now, I'm just creating the extra PDB objects within my conduit functions.  
It's the simplest way to get what I need done. :)   

>
> > Due to my limited Perl experience, I'm probably making this more
> > difficult/ugly then it needs to be.  If there are better/easier ways to
> > code this, please let me know.
>
> 	"more difficult/ugly" depends on what you're trying to do. You may
> want to start out doing it by hand (looting^Wadapting code from
> ColdSync.pm if it seems useful), and see what you actually need.
>
> 	Having said this, there's nothing that says you need to do this in
> Perl. ColdSync communicates with conduits using nothing more than
> command-line arguments, stdin/stdout, and a few environment variables.
> 	If you're more comfortable with Python, Ruby, C++, Lisp, or
> whatever, and are willing to spend the time to write a module that'll make
> it easier to write conduits in that language, then by all means write it
> and send it in.

Perhaps one day.  I've been meaning to learn Python and creating a Python 
interface to Coldsync would give me a project to learn with! ;)  
...If only there were more time in a day! :( ...

...Izzy

-- 
This message was sent through the coldsync-hackers mailing list.  To remove
yourself from this mailing list, send a message to majordomo@thedotin.net
with the words "unsubscribe coldsync-hackers" in the message body.  For more
information on Coldsync, send mail to coldsync-hackers-owner@thedotin.net.