Повышаем продуктивность Flutter-разработчика. 5 методов

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Всем привет! Меня зовут Юра и я Flutter-разработчик. Изучая эту технологию, работая с ней, я начал все чаще задаваться вопросом: как я могу успевать больше за меньший промежуток времени? Собственно, формула простая: мне нужно меньше тратить времени на рутинные процессы и уделять больше времени написанию нового кода. За два года, я собрал своеобразный список методов, которые помогли лично мне привести эту формулу в действие и повысить эффективность работы. Надеюсь, они будут полезны и вам.

Начнем с наиболее простых методов и постепенно перейдем к более сложным.

1. Используйте плагины

Самое простое, что вы можете сделать для повышения вашей производительности — это установить необходимые плагины в IDE. Плагины — это дополнения для IDE, которые расширяют ее возможности.

Вот мой топ таковых для IntelliJ IDEA:

  • Dart Data Class
  • Key Promoter X
  • String Manipulation
  • Git Tool Box

2. Используйте хоткеи

Один из данных плагинов — это Key Promoter X, данный плагин говорит после каждого действия, сделанного руками, какой был хоткей для него. Хоткей — это сочетание клавиш для быстрого выполнения действий. Данный плагин поможет вам больше использовать хоткеи, что в перспективе очень сильно может сказаться на вашей производительности. Привыкайте использовать все команды с помощью хоткеев!

3. Используйте генерацию кода

Не отходя далеко, продолжим настройку IDE. IDE — это программа для написания кода. Практически в каждой IDE есть такая функция как «Live Templates». Она позволяет сохранить часто используемые участки кода и использовать их, написав указанную команду прямо в редакторе кода. На самом деле, хорошо настроенные «Live Templates» позволяют сэкономить очень много времени и, наверное, являются одним из самых эффективных методов писать код быстрее.

4. Билды и нюансы работы с ними

Далее поговорим про билды. Многие команды необоснованно собирают постоянно только «release» билды для тестирования, но «debug» билд в среднем собирается раза в 3-4 быстрее «release» билда, и об этом не стоит забывать. Оптимизируйте и выберите в каких ситуациях какого типа билды вам необходимы и экономьте время на этом.

Продолжая тему билдов, также не обойдем стороной использование различных CI для автоматизации их сборки.

CI (Continuous Integration) — в дословном переводе «непрерывная интеграция». Имеется в виду интеграция отдельных кусочков кода приложения между собой.

Если посчитать время, которое в день разработчик тратит на сборки билдов, то это будет точно больше часа в день. При грамотно настроенном CI, разработчик после коммита может вообще не делать больше никаких лишних действий. Но в таком случае возникает вопрос как выбирать параметры билда и устройства, на которых его нужно делать.

В своей команде мы решили это таким методом: при создании комита разработчик указывает также типы билдов, которые ему нужны и CI проверяет текст коммита и создает билд с необходимыми параметрами.

Пример: git commit -m «Commit text -d -r -i»

Команда -d создает дебаг билд, -r — релиз билд, -i — IOS билд.

Наша команда для билдов использует Jenkins CI, но вы можете выбрать любую другую и использовать ее.

5. Перейдем к самому интересному: как проверить код и потратить на это как можно меньше времени?

Самым действенным и простым методом будет создать и настроить линтер файл и проверять код, используя Dart Analyzer. Это может сильно сократить время при проверке пул реквестов а также его можно переносить из проекта в проект.

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

👍НравитсяПонравилось0
В избранноеВ избранном1
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Юрий, вопрос не по теме. Насколько легко с помощью Flutter, если доводилось, делаются виджеты, — работа приложения на заблокированном экране. Я видел, что делают простейший функционал, например, аудио-плеера: pause/play & <> . Но можно ли сделать что-то кастомное?

На сколько мне известно, на данный момент флаттер на прямую не умеет работать с ними, есть только варианты через использование нативных языков. (На сколько помню Google обещали добавить эту фичу до середины 21 года.)

Есть повод для оптимизма )) Спасибо.

В своей команде мы решили это таким методом: при создании комита разработчик указывает также типы билдов, которые ему нужны и CI проверяет текст коммита и создает билд с необходимыми параметрами.

я сломался, я не понимаю этого, ну от слова совсем..

При создании коммита, в тексте коммита указываются дополнительные параметры. (-i, -d, -r)
В Jenkins pipeline идет проверка на их наличие и если они есть выполняются определенные шаги.

ANDROID_DEBUG_BUILD_TOKEN = " -d";
ANDROID_RELEASE_BUILD_TOKEN = " -r";
IOS_BUILD_TOKEN = " -i";

IS_ANDROID_DEBUG_BUILD = stringContains(env.GIT_COMMIT_MSG, ANDROID_DEBUG_BUILD_TOKEN)

IS_ANDROID_RELEASE_BUILD = stringContains(env.GIT_COMMIT_MSG, ANDROID_RELEASE_BUILD_TOKEN)

IS_IOS_BUILD = stringContains(env.GIT_COMMIT_MSG, IOS_BUILD_TOKEN)

if (IS_IOS_BUILD) {
// do something
}

Вопрос не в реализации, спасибо конечно, непонятна целесообразность вашего флоу оно безумно странное

Не могли бы вы указать конкретнее в чем странность данного флоу? Наша логика заключается в том, что далеко не каждый комит требует билд и мы его собираем по необходимости. Мы для трэкинга задач используем Jira + BitBucket, в связи с чем в Тексте каждого важного комита уже указывается код задачи, и я не вижу проблемы в использовании других ключей для того чтобы указать в какой момент требуется собирать билд, а в какой — нет. Если вы считаете что данный флоу странный — укажите пожалуйста причины)

Я конечно очень давно не использую Дженкинс, но все же.
Совмещение коммита суть которого хранить историю и команд для ci, это очень плохая идея.
Не понятно, почему не использовать юайку/триггеры для прямой сборки?
Ну и флоу странный, это просто в первую очередь по тому, что я не очень понимаю, где тут реквесты, ревью и прочее, если это дебажный билд, то тем более делать его с коммитов, немного странно.

upd: попытался немного вчитаться, я так понимаю, это бранча по типу мастера, на нее у вас дженкинс смотрит и после мерджа ревью, вы хотите не всегда билды собирать, но я все равно не понимаю, почему инфа о билде находится в коммите, а не в общем конфиге хотя бы

По поводу флоу не совсем так.
В коменте комита прописывается «T-1(Код таски в Jira) -r Текст коммита».
После комита в ветку feature/*, hotfix/*, dev, master. Стартует через вебкук билд в jenkins.
Данный билд проводит написанные тесты в любом случае и отправляет статус билда в BitBucket и Jira.

Что это дает? Деву банально после комита не нужно делать побочные действия кроме как затрекать время и отправить ПР на проверку(Уверен что и это можно сделать автоматически).

В тоже время тим лид и тестировщик могут прямо с таски взять соответсвующий таске билд.

PS: Точно есть варианты и умнее но на данный момент данный нас устраивает полностью.

Наша команда для билдов использует Jenkins CI, но вы можете выбрать любую другую и использовать ее.

а поделитесь примерчиком?

Уточните пожалуйста примерчиком чего именно?

скриптиков, которые по по команде собирают нужный конфиг

Команда -d создает дебаг билд, -r — релиз билд, -i — IOS билд.

В пайпе есть 3 шага для каждого типа билда(IOS, Android debug, Android release).
Так же одним из первых шагов идет шаг анализа комита.
В данном шаге используется функция написанная на груви которая проверяет наличие в тексте комита строк (" -i", " -d«, «-r»).
Результат функции записывается в переменные и проверяется в начале этапов для каждого типа.
Если пайп заходит в соотвествующий этап он просто выполняет стандартные команды для сборки: [sh «flutter build apk —release»], [sh «flutter build apk —debug»].
С билдом под IOS мы приняли решение вынести сборку за пределы нашего сервера дабы ускорить процесс сборки. И на данный момент мы просто использование курл запроса стартуем билд на CodeMagic. (До этого был создан отдельный job в jenkins для IOS билдов но в связи с тем что IOS билд на нашем сервере занимает ±15 минут было принято решение в пользу CodeMagic с длительностью билда ±3-5 минут).

В данный момент пайп выглядит ± так:

/* import shared library */
@Library('jenkins-shared-library')_

pipeline {
    agent any

    environment {
        PROJECT_FLUTTER_VERSION = "1.20.4";

        // Tokens
        DEBUG_BUILD_TOKEN = " -d";
        RELEASE_BUILD_TOKEN = " -r";
        IOS_BUILD_TOKEN = " -i";
        ALL_BUILD_TOKEN = " -a";

        // Routes to .apk files.
        RELEASE_APK_ROUTE = "build/app/outputs/apk/release"
        DEBUG_APK_ROUTE = "build/app/outputs/apk/debug"
    }

    stages {
        stage ('Checkout') {
            steps {
                checkout scm
            }
        }
        stage ('Steps Analysis') {
            steps {
               script {
                   env.FLUTTER_VERSION = sh (script: 'flutter --version', returnStdout: true).trim()
                   env.GIT_COMMIT_MSG = sh (script: 'git log -1 --pretty=%B ${GIT_COMMIT}', returnStdout: true).trim()

                   env.IS_ANDROID_DEBUG_BUILD = stringContains(env.GIT_COMMIT_MSG, DEBUG_BUILD_TOKEN)
                   env.IS_ANDROID_RELEASE_BUILD = stringContains(env.GIT_COMMIT_MSG, RELEASE_BUILD_TOKEN)
                   env.IS_IOS_BUILD = stringContains(env.GIT_COMMIT_MSG, IOS_BUILD_TOKEN)
                   env.IS_ALL_BUILDS = stringContains(env.GIT_COMMIT_MSG, ALL_BUILD_TOKEN)
                   env.IS_FLUTTER_VERSION_CORRECT = stringContains(env.FLUTTER_VERSION, PROJECT_FLUTTER_VERSION)

                   def data = readYaml file: "pubspec.yaml"
                   env.PROJECT_VERSION = data.version
                   env.PROJECT_NAME = data.name
                   env.PROJECT_DESCRIPTION = data.description

                   currentBuild.displayName = "${env.PROJECT_NAME}-v${env.PROJECT_VERSION} - Build number: ${env.BUILD_NUMBER}"
                   currentBuild.description = "${env.PROJECT_DESCRIPTION}\n${env.GIT_COMMIT_MSG}"

                   env.Build_text =
                   "\nProject Name: ${env.PROJECT_NAME}\nProject Version: ${env.PROJECT_VERSION}\nProject Description: ${env.PROJECT_DESCRIPTION}\n\nFlutter Version: $PROJECT_FLUTTER_VERSION\n\nCommit message: ${env.GIT_COMMIT_MSG}$BUILD_PAGE_TEXT$BUILD_LOGS_TEXT";
               }
            }
        }
        stage ('Flutter version') {
            when {
                expression {(env.IS_ANDROID_DEBUG_BUILD == "true" || env.IS_ANDROID_RELEASE_BUILD == "true" || env.IS_IOS_BUILD == "true"  || env.IS_ALL_BUILDS == "true") && IS_FLUTTER_VERSION_CORRECT == "false"}
            }
            steps {
                sh 'flutter version $PROJECT_FLUTTER_VERSION'
            }
        }
       stage ('Flutter pub get') {
            when {
                expression { env.IS_ANDROID_DEBUG_BUILD == "true" || env.IS_ANDROID_RELEASE_BUILD == "true" || env.IS_IOS_BUILD == "true" || env.IS_ALL_BUILDS == "true"}
            }

            steps {
                sh 'flutter clean && flutter pub get'
            }
        }
        stage ('Flutter Doctor') {
            when {
                expression { env.IS_ANDROID_DEBUG_BUILD == "true" || env.IS_ANDROID_RELEASE_BUILD == "true" || env.IS_IOS_BUILD == "true" || env.IS_ALL_BUILDS == "true"}
            }

            steps {
                sh 'flutter doctor'
            }
        }
        stage ('Build IOS Release') {
            when {
                expression {env.IS_IOS_BUILD == "true" || env.IS_ALL_BUILDS == "true"}
            }

            steps {
                sh "curl --location --request POST 'https://api.codemagic.io/builds' \
                    (ТУТ ПАРАМЕТРЫ CODE MAGIC)"}'"
            }
        }
        stage ('Build Android Debug') {
            when {
                expression {env.IS_ANDROID_DEBUG_BUILD == "true" || env.IS_ALL_BUILDS == "true"}
            }

            steps {
                sh "flutter build apk --debug"
                script {
                    sh "mv $DEBUG_APK_ROUTE/app-debug.apk $DEBUG_APK_ROUTE/${env.PROJECT_NAME}-v${env.PROJECT_VERSION}-debug.apk"

                    archiveArtifacts artifacts: "$DEBUG_APK_ROUTE/${env.PROJECT_NAME}-v${env.PROJECT_VERSION}-debug.apk"
                }
            }
        }
        stage ('Build Android Release') {
            when {
                expression {env.IS_ANDROID_RELEASE_BUILD == "true" || env.IS_ALL_BUILDS == "true"}
            }

            steps {
                sh "flutter build apk --release"
                script {
                    sh "mv $RELEASE_APK_ROUTE/app-release.apk $RELEASE_APK_ROUTE/${env.PROJECT_NAME}-v${env.PROJECT_VERSION}-release.apk"

                    archiveArtifacts artifacts: "$RELEASE_APK_ROUTE/${env.PROJECT_NAME}-v${env.PROJECT_VERSION}-release.apk"
                }
            }
        }
    }
    post {
        success {
             echo "Success"
             script {
                  if (env.IS_ANDROID_DEBUG_BUILD == "true" || env.IS_ANDROID_RELEASE_BUILD == "true" || env.IS_IOS_BUILD == "true" || env.IS_ALL_BUILDS == "true") {
                      // Telegram send notification
                      // Slack send notification
                  }
             }
        }
        aborted {
            echo "Aborted"
            script {
                if (env.IS_ANDROID_DEBUG_BUILD == "true" || env.IS_ANDROID_RELEASE_BUILD == "true" || env.IS_IOS_BUILD == "true" || env.IS_ALL_BUILDS == "true") {
                    // Telegram logs post
                    // Slack send notification
                }
            }
        }
        failure {
            echo "Failure"
            script {
                    // Telegram logs post
                    // Slack send notification
                }
            }
        }
    }
}

PS
Так же добавлена новая команда " -a" для всех билдов.

PS x2
Прошу экспертов не судить строго тк это первая настройка Jenkins и я уверен что есть варианты сделать что-то подобное проще)

Подписаться на комментарии