Какой хороший способ реорганизовать модуль Perl монстров в подмодули? - PullRequest
5 голосов
/ 28 января 2010

У меня есть модуль Perl для проекта. У меня может быть дюжина программ, свисающих с него, и многие из них - мусор. Раньше я не проводил много личного времени с DBI, так что эта часть исправима, но главное, что она большая. Буквально 2KLOCs.

Было бы легко разбить эту функцию (назовем ее Dumb.pm) на отдельные модули (Dumb :: FormTools, Dumb :: Database и т. Д.) За исключением того, что, как я уже сказал, есть много программ, которые уже ' использовать тупой;

Я бы хотел экспортировать экспортируемые функции Dumb :: Database через Dumb без необходимости повторять это снова и снова:

sub my_dumb_function { return Dumb::Database::my_dumb_function( @_ ) ; }

Дело не в том, что я выше этого. Просто это похоже на глупый и неумелый способ решения проблемы. Я однажды использовал оправдание «Не знаю лучше», а однажды действительно больше, чем ты получаешь. Помощь * +1008 *

Ответы [ 4 ]

7 голосов
/ 28 января 2010

Сложно дать вам конкретный совет, потому что разные кодовые базы требуют разных стратегий. Я выполняю рефакторинг модуля с подпрограммами в 500 строк иначе, чем модуль с небольшими подпрограммами и большим количеством повторяющегося кода. Если мне нужно изменить интерфейс, есть разные стратегии для этого.

  1. Получите все в систему контроля версий. Вы должны держать вокруг оригинальной и промежуточной версий.
  2. Если у вас еще нет набора тестов, напишите его. Получите тестовое покрытие как можно выше. Этот набор тестов является основой для сохранения того же поведения в будущих версиях, ошибках и прочем. Вы, вероятно, столкнетесь с программой, которая зависит от ошибки в исходном модуле.
  3. Начни взломать. На каждом шаге проверяйте, что остальные все еще проходят исходные тесты и что опубликованный интерфейс все еще ведет себя так же.

Я думаю, что ваш реальный вопрос, однако, «Как мне экспортировать в исходный модуль, который загрузил Dumb?». Вы можете предоставить свою собственную подпрограмму import, которая использует метод import_to_level Экспортера. Вы можете импортировать на более высокие уровни, чем тот, который загрузил вас. Таким образом, Dumb::Database import может загружать свои экспорты в пространство имен, в которое загружено Dumb, даже если это Dumb, которое загружает Dumb::Database.

3 голосов
/ 28 января 2010

Я предполагаю, что Dumb.pm в настоящее время использует Exporter. Предполагая, что вы не хотите переименовывать функции (просто разделите их на отдельные модули), вы сможете сохранить существующие определения @EXPORT, импортировать все из своих подмодулей и просто повторно экспортировать функции.

package Dumb;
use Dumb::FormTools ':all';
use Dumb::Database  ':all';

use Exporter 'import';

our @EXPORT = ...;    # Unchanged from original version
our @EXPORT_OK = ...; # Unchanged from original version

1;

Тег :all не определен по умолчанию. Вы должны определить его вручную (в каждом подмодуле).

our %EXPORT_TAGS = ( all => [ @EXPORT, @EXPORT_OK ] );
# or, for a module that doesn't export anything by default:
our %EXPORT_TAGS = ( all => \@EXPORT_OK );

С другой стороны, если подмодуль не имеет функций @EXPORT_OK, вы можете пропустить тег :all и просто сказать use Dumb::Submodule;.

3 голосов
/ 28 января 2010

Не уверен, как вы в настоящее время используете его (он в настоящее время экспортирует методы?), Но вы можете настроить новые дочерние модули, чтобы позволить вам импортировать их функции (используя Exporter), а затем просто явно импортировать оригинальный модуль теперь разбитые кусочки. Что-то вроде:

package Dumb;

use Dumb::Database qw(my_dumb_function);

1;

package Dumb::Database;

use base qw(Exporter);

our @EXPORT_OK = qw(my_dumb_function);

sub my_dumb_function { 1; }

1;
1 голос
/ 29 января 2010

Вы также можете посмотреть Sub :: Exporter

...