Главная страница
Навигация по странице:

  • 3.3 Настройка рабочей среды

  • 3.4 Архитектурный стиль строения и зависимости приложения

  • Программное средство Инвентаризация компьютеров. ПЗ_new. Руководство пользователя для разработанной системы. Пятый раздел приводит данные по информационной безопасности приложения


    Скачать 4.8 Mb.
    НазваниеРуководство пользователя для разработанной системы. Пятый раздел приводит данные по информационной безопасности приложения
    АнкорПрограммное средство Инвентаризация компьютеров
    Дата25.05.2023
    Размер4.8 Mb.
    Формат файлаdocx
    Имя файлаПЗ_new.docx
    ТипРуководство пользователя
    #1158409
    страница6 из 9
    1   2   3   4   5   6   7   8   9

    3 Разработка программного обеспечения

    3.1 Разработка программного средства


    Следующим шагом будет разработка необходимых систем и компонентов приложения.

    На последнем этапе необходимо разработать и реализовать сервер и клиентское приложение.

    В ходе разработки были реализованы все требования технического задания.

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

    3.2 Разработка компонентов клиентского приложения


    Особенностью разработки на Flutter является то, что все компоненты приложения являются виджетами. Виджеты описывают, как они должны выглядеть, учитывая их текущую конфигурацию и состояние. Когда состояние виджета изменяется, виджет перестраивает свое описание, которое Flutter сравнивает с предыдущим состоянием виджета, чтобы определить минимальные изменения, необходимые в базовом дереве визуализации для перехода из одного состояния в другое. Это позволяет сохранить ресурсы при перерисовке компонентов приложения.

    Для разработки приложения был выбран архитектурный стиль строения приложения BLoCBusiness Logic Components. Данный архитектурный стиль позволят нам контролировать состояние компонентов с помощью событий бизнес-логики. В листинге 3.1 представлен пример BLoC компонента.

    Отделение UI от бизнес-логики для Flutter жизненно необходимо. Согласитесь, что карабкаться вверх-вниз по дереву виджетов (UI-компонентов) в поисках нужной вам логики — не самая приятная вещь. Особенно, если верстка и так содержит очень много кода и разбросана по разным файлам. Кроме того, если мы следуем заветам Clean Architecture (а мы им следуем, не так ли?), то в нашем UI вообще не должно быть ничего лишнего. Равно как и бизнес-логика ничего не должна знать про UI, который к ней обращается. Благодаря такому тщательному разделению ответственностей мы получаем полностью изолированный компонент, который можно легко тестировать независимо от UI и использовать в другом окружении. Этот компонент и есть наш Bloc.

    Каждый Bloc поддерживает общий интерфейс BlocBase, содержащий в себе только один обязательный к реализации метод dispose. Он нужен, чтобы не забыть реализовать освобождение ресурсов, занятых Bloc-ом, например, закрыть активные потоки. Для того чтобы вы могли получить доступ к Bloc-у из любого узла дерева виджетов, корнем этого дерева становится такая сущность, как BlocProvider. Идея заключается в том, что наш провайдер, точно такой же виджет, который состоит из двух слагаемых: Bloc, к которому будут обращаться виджеты, и дерево виджетов, которое мы видим на экране.

    class AuthCubit extends Cubit {

    AuthCubit({required AuthRepositoryBase repository})

    : _repository = repository,

    super(const AuthState());
    final AuthRepositoryBase _repository;
    Future loadTokenState() async {

    try {

    emit(state.copyWith(status: AuthStatus.loading));
    await _repository.checkToken();

    final String? token = await _repository.getToken();
    emit(state.copyWith(status: AuthStatus.loaded, token: token));

    } on DioError catch (e) {

    emit(state.copyWith(status: AuthStatus.error, error: e));

    }

    }
    Future signIn(String login, String email, String password,

    String confirmPassword) async {

    try {

    emit(state.copyWith(status: AuthStatus.loading));
    final String? token =

    await _repository.signIn(login, email, password, confirmPassword);
    emit(state.copyWith(status: AuthStatus.loaded, token: token));

    } on DioError catch (e) {

    emit(state.copyWith(status: AuthStatus.error, error: e));

    }

    }
    Future register(String login, String email, String password,

    String confirmPassword) async {

    try {

    emit(state.copyWith(status: AuthStatus.loading));
    final String? token =

    await _repository.createUser(login, email, password, confirmPassword);
    emit(state.copyWith(status: AuthStatus.loaded, token: token));

    } on DioError catch (e) {

    emit(state.copyWith(status: AuthStatus.error, error: e));

    }

    }
    Future signOut() async {

    try {

    emit(state.copyWith(status: AuthStatus.loading));
    await _repository.signOut();
    emit(state.copyWith(status: AuthStatus.loaded, token: null));

    } on DioError catch (e) {

    emit(state.copyWith(status: AuthStatus.error, error: e));

    }

    }

    }

    Листинг 3.1 – BloC компонент авторизации

    3.2.1 Разработка аутентификации


    Аутентификация в приложении имеет собственный подраздел в хранилище, которое предоставляется зависимостью firebase_core и хранит информацию, необходимую для входа в приложение с использованием выбранного в настройках Firebase Auth способа с помощью пароля и электронного адреса. Также там хранятся данные, необходимые для запоминания текущего пользователя, чтобы в последующем он мог осуществлять вход в приложение, минуя экран аутентификации. Функция обработки аутентификации в качестве сотрудника указана в листинге 3.2.

    Provider.of(context, listen: false)

    .signInWithEmailAndPassword(

    email: loginController.text,

    password: passwordController.text,

    ).then((auth) {

    print("${auth.user.uid} ${auth.user.email}");

    Provider.of(context, listen: false)

    .collection("users")

    .getDocuments()

    .then((value) {

    var doc = value.documents.firstWhere((element) =>

    element.documentID == auth.user.uid, orElse: () {

    Provider.of(context, listen: false)

    .signOut();

    return;

    });

    if (doc != null) {

    if (codeController.text == doc.data['code']) {

    SharedPreferences.getInstance().then((prefs) {

    prefs.setBool(

    'staff', true);

    Router.navigator.pushReplacementNamed(Router.ordersPage);

    });

    }

    }

    })

    })

    Листинг 3.2 – Функция аутентификации пользователя как сотрудника

    Provider – аналог dependency injection для Flutter, зависимость помогает передать компоненты используемые для взаимодействия с внешними сервисами вниз по дереву виджетов. Это позволяет избежать повторения созданий объектов для взаимодействия с внешними сервисами. В листинге 3.3 представлен код для подключения компонентов к зависимости Provider.

    class MyApp extends StatelessWidget {

    @override

    Widget build(BuildContext context) {

    return MultiProvider(

    providers: [

    Provider(create: (_) => FirebaseAuth.instance),

    Provider(create: (_) => Firestore.instance),

    Provider(create: (_) => FirebaseStorage.instance),

    Provider(create: (_) => Geolocator()),

    Provider(create: (_) => FirebaseMessaging()),

    BlocProvider(create: (_) => AuthBloc())

    ],

    child: MaterialApp(

    debugShowCheckedModeBanner: false,

    title: 'Material App',

    theme: ThemeData.light().copyWith(

    primaryColor: Colors.deepOrange[700],

    accentColor: Colors.deepOrangeAccent,

    ),

    builder: ExtendedNavigator(router: Router())

    ),

    );

    }

    }

    Листинг 3.3 – Главный класс приложения с подключенными компонентами

    Сама же функция аутентификации пользователя как сотрудника выбирается по коду выше в зависимости от состояния BLoC компонента AuthBloc. В листинге 3.4 представлен код, который меняет дерево виджетов в зависимости от состояния компонента AuthBloc [6].

    BlocBuilder(

    builder: (context, state) {

    loginController.clear();

    passwordController.clear();

    if (state is AuthRegisterState)

    return AnimatedSwitcher(

    duration: Duration(milliseconds: 590),

    child: Form(

    key: _formKey,

    child: buildRegister(context),

    ),

    );

    else if (state is AuthStaffLoginState)

    return AnimatedSwitcher(

    duration: Duration(milliseconds: 590),

    Листинг 3.4 – Функция смены функциональности по состоянию BLoC

    child: Form(

    key: _formKey,

    child: buildStaffLogin(context),

    ),

    );

    return AnimatedSwitcher(

    duration: Duration(milliseconds: 590),

    child: Form(

    key: _formKey,

    child: buildLogin(context),

    ),

    );},)

    Продолжение листинга 3.4

    3.3 Настройка рабочей среды

    Первым делом необходимо установить необходимые плагины и настроить редактор Android Studio. Для разработки кроссплатформенных приложений на Flutter необходимо установить сам фреймворк Flutter. Для разработки мобильных приложений на Android нужно установить Android SDK. На рисунке 2.4 можно увидеть настройку Android SDK. Для разработки десктопных приложений для Windows нужно установить Visual Studio Build Tools с поддержкой C++.



    Рисунок 2.4 – Экран настройки и установки Android SDK
    Android SDK включает в себя необходимые инструменты, чтобы помочь Android-разработчикам в совершении первых шагов: различные API (прикладной программный интерфейс), разработанные Google для управления функциями устройства и интеграции сервисов, полнофункциональный эмулятор для тестирования приложений, а также все необходимые текстовые материалы, чтобы дать начало для программирования под Android.
    3.4 Архитектурный стиль строения и зависимости приложения

    BLoC (BusinessLogicComponent) ­ это архитектурный шаблон, представленный Google. Идея заключается в том, чтобы иметь отдельные компоненты (компоненты BLoC), содержащие только бизнес-логику, которая должна легко использоваться различными приложениями Dart. Для AndroidStudio, Google предоставляют одноименный плагин для автогенерации bloc компонентов [3].

    Трёхслойный архитектурный стиль – это архитектурный шаблон, представляющий из себя три слоя разделения логики приложения:

    • уровень представления.

    Это верхний слой архитектуры. Самый верхний уровень приложения — пользовательский интерфейс. Основная функция этого слоя — перевод задач и результатов в нечто понятное пользователю. Он содержит такие страницы, как веб-формы, формы окон, где данные представлены пользователю и используются для ввода данных от пользователя. Уровень представления является наиболее важным, потому что именно его видит пользователь, а хороший пользовательский интерфейс привлекает пользователя, и этот уровень должен быть спроектирован правильно;

    • бизнес-уровень.

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

    • уровень данных.

    Этот уровень используется для подключения бизнес-уровня к базе данных или источнику данных. Он содержит методы, которые используются для выполнения операций с базой данных, таких как вставка, удаление, обновление и т. д. Этот уровень содержит хранимые процедуры, которые используются для запросов к базе данных. Следовательно, этот уровень устанавливает соединение с базой данных (или с внешней API, будь то REST или GraphQL) и выполняет функции в базе данных.

    Разработка приложения ведется на Dart, языке, который используется фреймворком Flutter. В фреймоворке есть механизм для добавления специальных пакетов. Список использованных в разработке пакетов приведен в листинге 2.1.

    dependencies:

    adaptive_scrollbar: ^2.1.2

    artemis: ^7.0.0-beta

    auto_route: ^3.2.3+1

    badges: ^2.0.2

    bloc: ^8.0.2

    cupertino_icons: ^1.0.2

    dio: ^4.0.4

    dropdown_search: ^2.0.1

    equatable: ^2.0.3

    flutter:

    sdk: flutter

    flutter_bloc: ^8.0.1

    flutter_dotenv: ^5.0.2

    flutter_form_builder: ^7.1.1

    flutter_localizations:

    sdk: flutter

    flutter_localized_locales: ^2.0.3

    font_awesome_flutter: ^10.0.0

    form_builder_extra_fields: ^7.1.0

    form_builder_validators: ^8.1.1

    freezed: ^1.0.1

    get_it: ^7.2.0

    gql: null

    gql_dio_link: 0.1.0

    gql_exec: 0.3.0

    gql_transform_link: 0.2.0

    graphql_flutter: ^5.0.0

    hive: ^2.1.0

    hive_flutter: null

    intl: ^0.17.0

    json_annotation: ^4.1.0

    jwt_decode: ^0.3.1

    logger: ^1.1.0

    normalize: ^0.5.5

    qr_flutter: ^4.0.0

    shared_preferences: ^0.5.5

    storage_repository: ^1.1.7
    dev_dependencies:

    auto_route_generator: ^3.2.3

    build_runner: ^2.1.7

    flutter_gen_runner: ^4.1.5

    flutter_lints: ^1.0.0

    flutter_test:

    sdk: flutter

    json_serializable: ^6.0.1

    Листинг 2.1 – Список используемых пакетов

    С помощью Flutter можно создать кроссплатформенное приложение под OS Windows, MacOS, Web, Android и iOS. Для того что бы собрать под MacOS и iOS необходимо наличие самой операционной системы MacOS, с помощью XCode. Необходимость его использования обусловлена тем, что для приложений под эти системы нужны сертификаты, которые генерируются только в XCode.
    1   2   3   4   5   6   7   8   9


    написать администратору сайта