Как избежать глобальности в программировании на Perl Tk (Tkx) с использованием модели MVC - PullRequest
3 голосов
/ 22 ноября 2011

У меня есть старое и очень большое приложение на 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 ]

1 голос
/ 22 ноября 2011

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

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

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

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

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

1 голос
/ 22 ноября 2011

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

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 );
...