Моделирование аспектов статической типизации на языке с утиной типизацией

StackOverflow https://stackoverflow.com/questions/2933438

Вопрос

На своей нынешней работе я создаю набор сценариев Perl, которые сильно зависят от объектов.(с использованием Perl bless() на хеше, чтобы максимально приблизиться к ОО)

Из-за отсутствия лучшего способа выразить это, большинство программистов в моей компании не очень умны.Хуже того, они не любят читать документацию и, похоже, имеют проблемы с пониманием кода других людей.Здесь главное — ковбойское программирование.Всякий раз, когда они сталкиваются с проблемой и пытаются ее решить, они находят ужасное решение, которое на самом деле ничего не решает, а обычно только ухудшает ситуацию.

Честно говоря, это приводит к тому, что я не доверяю им код, написанный на языке утиной типизации.Например, я вижу слишком много проблем, связанных с тем, что они не получают явной ошибки за неправильное использование объектов.Например, если ввести A имеет члена foo, и они делают что-то вроде: instance->goo, они не увидят проблему сразу.Он вернет нулевое/неопределенное значение, и они, вероятно, потратят час на поиск причины.Затем в конечном итоге меняют что-то еще, потому что они не определили должным образом исходную проблему.

Поэтому я ищу способ сохранить свой язык сценариев (его быстрое развитие является преимуществом), но выдавать явное сообщение об ошибке, когда объект используется неправильно.Я понимаю, что, поскольку нет этапа компиляции или статической типизации, ошибка должна произойти во время выполнения.Меня это устраивает, пока пользователь получает очень явное уведомление о том, что «этот объект не имеет X».

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

Несмотря на то, что я работаю на Perl, я думаю, что это может быть независимо от языка.

Это было полезно?

Решение

Если у вас есть возможность добавить модули, попробуйте лось.Он предоставляет практически все функции, которые вам нужны в современной среде программирования, и даже больше.Он осуществляет проверку типов, отличное наследование, имеет возможности самоанализа и MooseX::Объявить, один из лучших интерфейсов для классов Perl.Взглянем:

use MooseX::Declare;

class BankAccount {
    has 'balance' => ( isa => 'Num', is => 'rw', default => 0 );

    method deposit (Num $amount) {
        $self->balance( $self->balance + $amount );
    }

    method withdraw (Num $amount) {
        my $current_balance = $self->balance();
        ( $current_balance >= $amount )
            || confess "Account overdrawn";
        $self->balance( $current_balance - $amount );
    }
}

class CheckingAccount extends BankAccount {
    has 'overdraft_account' => ( isa => 'BankAccount', is => 'rw' );

    before withdraw (Num $amount) {
        my $overdraft_amount = $amount - $self->balance();
        if ( $self->overdraft_account && $overdraft_amount > 0 ) {
            $self->overdraft_account->withdraw($overdraft_amount);
            $self->deposit($overdraft_amount);
        }
    }
}

Я думаю, что это довольно круто.:) Это слой над объектной системой Perl, поэтому он работает с тем, что у вас уже есть (в основном).

С помощью Moose вы можете очень легко создавать подтипы, чтобы убедиться, что введенные вами данные верны.Ленивые программисты соглашаются:поскольку для того, чтобы подтипы работали в Moose, нужно сделать так мало, их легче сделать, чем нет!(от Поваренная книга 4)

subtype 'USState'
    => as Str
    => where {
           (    exists $STATES->{code2state}{ uc($_) }
             || exists $STATES->{state2code}{ uc($_) } );
       };

И, Тада, штат США теперь стал тем типом, который вы можете использовать!Никакой суеты, никакой суеты, и только небольшое количество кода.Если что-то не так, он выдаст ошибку, и все, что нужно сделать потребителям вашего класса, — это передать скаляр с этой строкой.Если все в порядке (а так и должно быть... верно?:) ) Они используют его как обычно, а ваш класс защищен от мусора.Как это приятно!

У Moose есть масса подобных замечательных вещей.

Поверьте мне.Проверьте это.:)

Другие советы

В Перл,

  • заставить его требовать use strict а также use warnings находятся в 100% кода

  • Вы можете попытаться сделать почти частные переменные участника, создавая замыкание. Отказ Очень хороший пример - «Частные переменные элемента, вроде» раздел в http://www.usenix.org/publications/login/1998-10/perl.html. Отказ Они не являются 100% частными, но довольно не очевидно, как получить доступ, если вы действительно не знаете, что вы делаете (и требуете, чтобы они читали свой код и проведите исследование, чтобы узнать, как).

  • Если вы не хотите использовать закрытие, следующий подход работает несколько хорошо:

    Сделайте все ваши переменные элемента объекта (клавиши HASH HASH AKA в Perl), завернутые в аксессуары. Существуют способы эффективно от стандартов кодирования POV. Один из наименьших безопасных - это класс :: Accessor :: Fast. Я уверен, что лось имеет лучшие способы, но я не так знаком с лосям.

    Убедитесь, что «скрыть» фактические переменные участника в именах частных конвенций, например, $object->{'__private__var1'} будет переменная участника, а также $object->var1() будет доступа к дому / сеттеру.

    ПРИМЕЧАНИЕ. Для последнего класса :: Accessor :: Fast - это плохое, так как его переменные участника делятся имена с аксессуарами. Но у вас могут быть очень легкие строители, которые работают так же, как Class :: Accessor :: Fast и создают значения ключевых значений, таких как $ OBJ -> {'__ private__foo'} для "foo".

    Это не помешает им стрелять в ногу, но сделает это намного сложнее сделать это.

    В вашем случае, если они используют $obj->goo или $obj->goo(), они получат ошибку выполнения, по крайней мере, в Perl.

    Конечно, они могли бы выйти из своего пути сделать $obj->{'__private__goo'}, но если они сделают Гонцо Ковбойское дерьмо из-за прозрачной лени, последний намного больше работы, чем делать правильные $obj->foo().

    Вы также можете иметь сканирование кодовой базы, которая обнаруживает $object->{"_ Введите строки, хотя из вашего описания, которые могут не работать сдерживающим фактором.

Вы можете использовать Класс :: Инсульт или Объект :: Инсульт которые дают вам настоящую конфиденциальность данных. Вместо того, чтобы хранить данные в благословенной хэш-справочнике, благословенная скалярная ссылка используется в качестве ключа к хэси лексических данных. Долгая история короткая, если ваши сотрудники пытаются $obj->{member} Они получат ошибку времени выполнения. В $obj Для них схватить и не простым способом получить данные, кроме посредников доступа.

Вот Обсуждение техники изнутри и различных реализаций.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top