From 08d862b75eb1eac8a4d167677ab7013df816d6fc Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Wed, 6 Apr 2011 00:30:26 -0500 Subject: docs --- lib/Class/Refresh.pm | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/lib/Class/Refresh.pm b/lib/Class/Refresh.pm index 887f04f..5c644ac 100644 --- a/lib/Class/Refresh.pm +++ b/lib/Class/Refresh.pm @@ -1,18 +1,75 @@ package Class::Refresh; use strict; use warnings; +# ABSTRACT: refresh your classes during runtime use Class::Unload; use Class::Load; +=head1 SYNOPSIS + + use Class::Refresh; + use Foo; + + Class::Refresh->refresh; + + # edit Foo.pm + + Class::Refresh->refresh; # changes in Foo.pm are applied + +=head1 DESCRIPTION + +During development, it is fairly common to cycle between writing code and +testing that code. Generally the testing happens within the test suite, but +frequently it is more convenient to test things by hand when tracking down a +bug, or when doing some exploratory coding. In many situations, however, this +becomes inconvenient - for instance, in a REPL, or in a stateful web +application, restarting from the beginning after every code change can get +pretty tedious. This module allows you to reload your application classes on +the fly, so that the code/test cycle becomes a lot easier. + +This module has several limitations, due to reloading modules in this way being +an inherently fragile operation. Therefore, this module is recommended for use +only in development environments - it should not be used for reloading things +in production. + +It makes several assumptions about how code is structured that simplify the +logic involved quite a bit, and make it more reliable when those assumptions +hold, but do make it inappropriate for use in certain cases. For instance, this +module is named C for a reason: it is only intended for +refreshing classes, where each file contains a single namespace, and each +namespace corresponds to a single file, and all function calls happen through +method dispatch. Unlike L, which makes an effort to track the +files where subs were defined, this module assumes that refreshing a class +means wiping out everything in the class's namespace, and reloading the file +corresponding to that class. If your code includes multiple files that all load +things into a common namespace, or defines multiple classes in a single file, +this will likely not work. + +=cut + our %CACHE; +=method refresh + +The main entry point to the module. The first call to C populates a +cache of modification times for currently loaded modules, and subsequent calls +will refresh any classes which have changed since the previous call. + +=cut + sub refresh { my $class = shift; $class->refresh_module($_) for $class->modified_modules; } +=method modified_modules + +Returns a list of modules which have changed since the last call to C. + +=cut + sub modified_modules { my $class = shift; @@ -30,6 +87,16 @@ sub modified_modules { return @ret; } +=method refresh_module $mod + +This method calls C and C on C<$mod>, as well as on +any classes that depend on C<$mod> (for instance, subclasses if C<$mod> is a +class, or classes that consume C<$mod> if C<$mod> is a role). This ensures that +all of your classes are consistent, even when dealing with things like +immutable L classes. + +=cut + sub refresh_module { my $class = shift; my ($mod) = @_; @@ -42,6 +109,12 @@ sub refresh_module { $class->load_module($_) for @to_refresh; } +=method unload_module $mod + +Unloads C<$mod>, using L. + +=cut + sub unload_module { my $class = shift; my ($mod) = @_; @@ -56,6 +129,12 @@ sub unload_module { $class->_clear_cache_for($mod); } +=method load_module $mod + +Loads C<$mod>, using L. + +=cut + sub load_module { my $class = shift; my ($mod) = @_; @@ -154,4 +233,95 @@ sub _mod_to_file { return $file; } +=head1 CAVEATS + +=over 4 + +=item Global variable accesses and function calls may not work as expected + +Perl resolves accesses to global variables and functions in other packages at +compile time, so if the package is later reloaded, changes to those will not be +noticed. As mentioned above, this module is intended for refreshing B. + +=item File modification times have a granularity of one second + +If you modify a file and then immediately call C and then immediately +modify it again, the modification may not be seen on the next call to +C. Note however that file size and inode number are also compared, so +it still may be seen, depending on if either of those two things changed. + +=item Tracking modules which C a given module isn't possible + +For instance, modifying a L module which is used in a class +won't cause the class to be refreshed, even if the change to the exporter would +cause a change in the class's metaclass. + +=item Classes which build themselves differently based on the state of other classes may not work properly + +This module attempts to handle several cases of this sort for L classes +(modifying a class will refresh all of its subclasses, modifying a role will +refresh all classes and roles which consume that role, modifying a metaclass +will refresh all classes whose metaclass is an instance of that metaclass), but +it's not a problem that's solvable in the general case. + +=back + +=head1 BUGS + +=over 4 + +=item Reloading classes when their metaclass is modified doesn't quite work yet + +This will require modifications to Moose to support properly. + +=item Tracking changes to metaclasses other than the class metaclass isn't implemented yet + +=item Metacircularity probably has issues + +Refreshing a class which is its own metaclass will likely break. + +=back + +Please report any bugs through RT: email +C, or browse to +L. + +=head1 SEE ALSO + +L + +=head1 SUPPORT + +You can find this documentation for this module with the perldoc command. + + perldoc Class::Refresh + +You can also look for information at: + +=over 4 + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * RT: CPAN's request tracker + +L + +=item * Search CPAN + +L + +=back + +=head1 CREDITS + +This module was based in large part on L by Jesse Vincent. + +=cut + 1; -- cgit v1.2.3-54-g00ecf