Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Square pegs and round holes A reflection on Class::DBI http://popcorn.cx/ Who am I? • Developer at Monash University • Applications in and related to the staff and student portal • Built upon open source – Perl, HTML::Mason, Apache http://popcorn.cx/ Class::DBI • Database abstraction layer for Perl • Allows mapping of classes to database tables • Each row of the table is an instance of the class http://popcorn.cx/ The square peg User directory Learning Management System Student records Teaching staff http://popcorn.cx/ Initial development • Bulk written in Perl, remainder PL/SQL and Java • Chose Class::DBI as it gave us a leg up due to time constraint – But not as much as we expected http://popcorn.cx/ Clash of standards Music::CD->has_a( artist => 'Music::Artist’ ); print $cd->artist->name; http://popcorn.cx/ Clash of standards Music::CD->has_a( artist_id => 'Music::Artist’ ); print $cd->artist_id->name; http://popcorn.cx/ Clash of standards Music::CD->has_a( artist_id => 'Music::Artist’ ); *artist = \&artist_id; print $cd->artist->name; http://popcorn.cx/ Clash of standards Music::CD->has_a( artist_id => 'Music::Artist’ ); *get_artist = \&get_artist_id; *set_artist = \&set_artist_id; print $cd->get_artist->name; http://popcorn.cx/ Playing nice with friends • Our expectation was for error at runtime • If remote service is not available: – Module loads – Only when used is error indicated • By return value or an exception http://popcorn.cx/ Playing nice with friends • Class::DBI connects to database, and errors, at module load • Which mean an error at load paradigm • If database is unavailable – Module will not load – Thus stopping remaining code from loading • We needed to be more defensive than usual and wrap the use in an eval http://popcorn.cx/ I canna do it captain! • Takes XML extract of all user accounts upwards of 90,000 • Compares against data in database • Updates accordingly http://popcorn.cx/ First attempt • Run through extract and call retrieve() for each record • 90,000 database queries • Database bottleneck • Runtime of over an hour http://popcorn.cx/ Second attempt • Load all objects into memory via retrieve_all() • Single database query – no longer the bottleneck • Now encounter memory allocation issues • Still a runtime of over an hour http://popcorn.cx/ Third attempt • Avoid Class::DBI and use DBI directly • Single database query gave all records in an array of hash references • Then we only call retrieve() if a change is required • Runtime of less than ten minutes http://popcorn.cx/ Fourth attempt • Did not try as third attempt gave satisfactory results • Would have probably loaded entire extract and then used iterator from retrieve_all() http://popcorn.cx/ Overview of initial development • A success • Built working system in a few weeks • Class::DBI gave significant head start. Although we needed to: – learn how to use it – bend to our standards – avoid in some cases for performance http://popcorn.cx/ Maintenance and enhancement • Now been running for over two years • Huge increase in usage – Second largest installation in the world • Also expansion of functionality • Can at times be frustrating http://popcorn.cx/ Where is the object? print $section->get_course(); • • • • Many hours wasted A number is printed Not the expected blessed referent Due to stringification feature of Class::DBI – That we had not mentioned in our documentation http://popcorn.cx/ Unforeseen implications • Extended update(), create() and delete() to require a username for an audit trail – $object->delete($username) • Worked well • Until we tried to use features such as cascade delete http://popcorn.cx/ Unforeseen implications • Class::DBI follows ‘has many’ relationships and calls delete() • Does not know to pass our username • Which makes it fail • Our solution to a business need limited the features we could use • Better knowledge of Class::DBI internals should provide a better solution http://popcorn.cx/ Building a round peg Public website Course database Administrators http://popcorn.cx/ Development • All Perl solution – Except for Oracle database • Perl CGI for public website • Perl under HTML::Mason for administration interface • Perl for batch load process http://popcorn.cx/ Class::DBI or not Class::DBI • Our data model led to a matching set of classes and database schema • But – Class::DBI was not available on the target environment – Recent issues (at the time) soured our opinion of Class::DBI • Decided to build our classes from scratch http://popcorn.cx/ It lives • Quickly became apparent that some form of framework was needed. • So we built our own: http://popcorn.cx/ Basic setup use base 'Base'; __PACKAGE__->_set_table_name( ’table' ); __PACKAGE__->_setup_attribtes( qw{ code name ... }, ); http://popcorn.cx/ ‘has_a’ relationship __PACKAGE__->_setup_has_a_relationship( 'class' => 'Faculty', 'get_method' => 'get_faculty', 'set_method' => 'set_faculty', ); http://popcorn.cx/ ‘has_many’ relationship __PACKAGE__->_setup_has_many_relationship( 'class' => 'OtherClass', 'table' => 'other_table', 'get_method' => 'get_others', 'add_method' => 'add_other', 'remove_method' => 'remove_other', ); http://popcorn.cx/ ‘has_many’ relationship __PACKAGE__->_setup_has_many_relationship( 'class' => 'OtherClass', 'table' => 'other_table', 'get_method' => 'get_others', ); http://popcorn.cx/ Compensating for ‘issues’ • • • • Built to expect our standards Follows error at runtime paradigm Still need to bypass in some cases Only built what we needed/wanted – So no stringification to primary key • Natively requires username for audit trail http://popcorn.cx/ Was it worth it? • Course Finder project was a success • Framework allowed later changes to be implemented quickly • We knew exactly how our framework worked http://popcorn.cx/ Would we do it again? • No. • Because we can reuse this framework • Which we have done in one other project and fed enhancements back http://popcorn.cx/ Another peg • There are other database abstraction frameworks: – DBIx::Class is biggest alternative • Either didn’t exist or appear on our radar at the time • They are not excluded for future projects http://popcorn.cx/ Conclusion • I don’t really have one… http://popcorn.cx/ Conclusion • Any framework is beneficial • But you need one that does what you need • And you will need to bypass it http://popcorn.cx/ Questions? http://popcorn.cx/ • Blackboard Learning System Vista Enterprise License Release 3 Patch something or other. Potato! http://popcorn.cx/ This slide left intentionally blank http://popcorn.cx/