Как избежать глобальности в программировании на Perl Tk (Tkx) с использованием модели MVC

У меня есть старое и очень большое приложение на Perl Tk с графическим интерфейсом, которое я реорганизую в Tkx. Я хочу разделить интерфейс на несколько пакетов, чтобы создать модульный интерфейс приложения. Кроме того, я хочу отделить представление от модели, используя контроллер для обеспечения интерфейса между ними.

Мне кажется, что единственный способ спроектировать это с помощью двух огромных глобальных переменных, одна из которых содержит модель ($MODEL), а другая содержит ссылки на виджеты ($UI), которые распределены по многим пакетам. Затем контроллер связывает их с помощью ряда команд, подобных следующим:

$UI->{'entry_widget'}->configure(-variable=>\$MODEL->{'entry_value'});
$UI->{'button_widget'}->configure(-command=>sub {$MODEL->{'entry_value'} = "New Value"} );

Мой вопрос: есть ли лучший способ для разработки приложения, которое позволяет избежать использования этих двух больших глобальных переменных ($ UI и $MODEL)? Любые предложения будут очень приветствоваться.

2 ответа

Вы не хотите избегать глобальных переменных, вы хотите использовать методы, то есть заменить $hashref->{data} с $model->data или же $self->model->data, где $model или же $self, является аргументом (или "синглтоном", как демонстрирует Аксеман), переданным обработчику сигнала /callback/ команде, а не хешем, к которому вы обращаетесь напрямую

Вы используете методы для изменения $model потому что методы могут отказаться обновлять модель бессмысленными / неверными данными, они гарантируют, что вы не пытаетесь платить монопольными деньгами

Ваше приложение всегда будет создавать переменную модели и переменную представления и соединять их (возможно, через посредника, контроллер) посредством передачи аргументов.

Они не должны быть фактическими глобальными переменными в смысле perl ( справиться со Scoping), они могут быть my $variables и по-прежнему отлично работают, как вы используете их сейчас (через замыкания), и вы избегаете проблем http://perl.plover.com/varvarname.html, но вы не получаете преимуществ интеллектуальных моделей, которые знать, какое топливо им нужно (дизельное или неэтилированное); и подключение ваших взглядов к вашей модели больше печатать

Смотрите также ответы и ссылки из Что такое Model View Presenter?

Я думаю, что методы пакета - это способ сделать что-то глобально доступным, но не глобальную переменную. Так что-то вроде этого, будет работать:

package MVC;

use strict;
use warnings;
use Scalar::Util qw<refaddr>;

my %MVCs;

sub _domain { 
    my ( $domain_name, $ref, $value ) = @_;
    my $r = \$MVCs{ $key }{ $domain_name };
    return unless $$r or ref( $value );
    if ( ref $value ) {
        $$r = $value;
    }
    return $$r;
}

sub model      { shift; return _domain( 'model', @_ ); }
sub controller { shift; return _domain( 'controller', @_ ); }
sub view       { shift; return _domain( 'view', @_ ); }

Поэтому вне пакета вам просто нужно вызвать это:

my $controller = MVC->controller( $self ); 

Чтобы получить контроллер, связанный с объектом.

Вы могли бы даже поместить некоторую логику экспорта в аксессоры, например:

unless ( $ref->can( $domain_name )) { 
    not strict 'refs';
    *{ ref( $ref ) . "::$domain_name" } 
        = sub { _domain( $domain_name, $ref ) }
        ;
}

Так что вы можете просто сделать это:

$self->view->view_method( @args );
Другие вопросы по тегам