Child pages
  • Общие вопросы
Skip to end of metadata
Go to start of metadata

Мануал по работе с фреймворком ABillS

Мануал разработчика

Форматирование кода

  • Для отступов не использовать табуляций, только двойные пробелы
  • Форматирование if else:

    if (expr) {
      ...
    }
    else {
      ...
    }

Однострочные или-выражения

Всегда выражения берутся в скобки

$result = ($total_users == 1) ? "Ok" : "Fail";

print "test" if ($test == 1);

Переменные

  • Переменные указываются строчными буками

      $test, @devices, %switch
  • Объекты указываются с заглавной

    $Test = Test->new();
  • Массивы указываются в множественном числе

    my @devices = ();
    my @users = ();
  • Хеши в единственном

    %status_list = ();
    $status_list{disable}=1;

Общий шаблон функций

#**********************************************************
=head2 test_function($attr) - Test function
 
  Arguments:
    $attr   - Extra attributes
       TEXT   - Some text
 
  Returns:
   TRUE or FALSE
 
  Example:
 
    test_function({ TEXT => 'Some text' });
 
=cut
#**********************************************************
sub test_function {
  my ($attr) = @_;
 
  print "Hello world!";
 
  return 1;
}

Рекомендации:

  1. Отделяйте шапки функций звёздочками (58 штук).
  2. Не игнорируйте создание комментариев перед началом функции.
  3. Называйте функции строчными буквами с разделением нижним подчёркиванием.
  4. По умолчанию, в случае успешного выполнения функция должна возвращать 1, в случае ошибки - 0.

  5. Минимизируйте использование глобальных переменных в функциях.

Дата обновления в шапке модуля

Дату обновления модуля следует указывать в шапке модуля (в начале файла) в формате YYYYMMDD.

Пример:

=head1 Cdata

  C-data
  MODEL:
    epon
      FD1104SN
  ...

  DATE: 20190704
  UPDATE: 20210324

=cut

DATE - дата создания модуля

UPDATE - дата обновления модуля

Указывать дату правильно важно для коммерческих модулей, так как скрипт обновления update.sh ожидает увидеть дату в этом формате.

Можно ли использовать HTML в коде?

Ни в коем случае не используйте HTML в коде управляющей модели, вместо этого используйте объекты Abills::HTML или шаблоны.

Дополнительные модули

Загрузка дополнительных модулей Perl осуществляется командой

load_pmodule('Simple::XML');

(Библиотека Misc.pm)

С проверкой ошибок код выглядит так:

my $loaded_imager_error = load_pmodule( "Imager", { RETURN => 1 } );
if ( $loaded_imager_error ) {
  print $loaded_imager_error;
  return 0;
}

Дополнительные модули с автоустановкой

Загрузка дополнительных модулей Perl с автоустановкой осуществляется командой

load_perl_module('SQL::Translator');
(Библиотека PModules.pm)

Поиск в полях

Для удобства поиска было разработано несколько разделителей.

Для цифровых полей

Разделитель запятая (,) обозначает AND.

Пример: искать значения поля 56 и 66

56,66

Разделитель точка с запятой (;) обозначает OR.

Пример: искать значения поля 56 или 66

56;66

Тестирование

Для тестирования системы существует каталог с тестами abills/t.

make

Жесткий тест работоспособности, никогда его не выполняйте на рабочей системе, чревато пропажей данных

perl web.t brutal

тестирование синтаксиса и стресс-тест веб-приложений

НЕ ИСПОЛЬЗОВАТЬ НА ПРОДАКШН СИСТЕМЕ

Тест проверки авторизации и аккаунтинга

t/Aaa.t

Проверка DHCP авторизации используя приготовленный RAD PAIRS пакет dhcp.discover

perl Aaa.t dhcp_test dhcp.discovery

Тестирование абон. платы тарифного плана

perl Tariffs.t FILENAME=tp_test1.tp

FILENAME - файл с описанием тарифного плана и параметров абонента.

Для задания логина и пароля авторизации используется файл t/.test

login:password

В системе также есть специальный скрипт запуска выделенных тестов, которые хранятся в отдельных каталогах: Запуск тестов для модуля или папки

Создание демона

use Abills::Base;
use Abills::Server;

my $ARGV = parse_arguments(\@ARGV);

# Демонизация и ведение лога
if (defined($ARGV->{'-d'})) {
  my $pid_file = daemonize();
  #ведение лога
  #$Log->log_print('LOG_EMERG', '', "$prog_name Daemonize... $pid_file");
}
# Остановка процесса
elsif (defined($ARGV->{stop})) {
  stop_server();
  exit;
}
# Проверка, не запущен ли уже
elsif (make_pid() == 1) {
  exit;
}

# Таймаут между запусками 100 секунд
my $UPDATE_TIME=100;

while (1) {
  check_activity({ ALL => ($ARGV->{RECONFIG_PERIOD}) ? undef : $all });
  sleep $UPDATE_TIME;

Языковые маркеры

Сохраняются в глобальном хеше %lang.

Пример:

$lang{LANG_MARKER} = 'Языковой маркер';

Названия маркеров обязательно писать заглавными буквами.

Отображение в шаблонах:

_{LANG_MARKER}_

Переменные внутри lang

$lang{LANG_MARKER_WITH_VARS} = 'У абонента минус %DEPOSIT%';

И использовать функцию:

use Abills::Base qw(vars2lang);

vars2lang($lang{LANG_MARKER_WITH_VARS}, { DEPOSIT => '5' });

Но, конечно, вы можете использовать любой string с такой разметкой.

JSON тестирование

Для того, чтобы протестировать функцию:

  1. Создайте тест в /usr/abills/t
  2. Подключите JSON.t

    require "./JSON.t";
  3. Создайте JSON, заполнив его. API_KEY - ключ API текущего администратора

    my @test_list = (
      {
        name       => 'InfoFields',
        params     => {
          qindex       => 96,
          API_KEY      => '1523615231263123',
          json         => 1
        },
        result     => '',
        valid_json => 1,
        schema     => {
     
        }
      }
      );
  4. Передайте данные в функцию json_test

    json_test(
      \@test_list, 
      { TEST_NAME => 'info_fields_new test' });
  5. Выполните ваш тест, запустив программу

    # prove -v <название теста>.t

String Eval

Когда нужно загрузить динамически модуль необходимо его загрузить следующим образом

my $module = 'Example';
eval "use $module";

Но настоятельно не рекомендуется это делать в Perl. Потому нужно использовать следующий вариант

my $module_name = 'Example';
eval {
  my $module = "$module_name.pm";
  require $module;
  $module->import();
  1;
};

Если модуль имеет назву с названием директории пример

Module::Example

Тогда нужно получить последнее слово модуля, это его название

my $module_full_name = 'Module::Example';
my ($module_name) = $module_full_name =~ /(\w+)$/;

eval {
  my $module = "$module_name.pm";
  require $module;
  $module->import();
  1;
};

Конфигурационные переменные

Здесь описаны правила при заполнении конфигурационных переменных.

  1. Если ваша переменная должна иметь изначальное значение (fallback), то нужно её добавить в функцию _fill_config_defaults.
  • No labels