G
G
Gleb Kiselev2020-02-19 10:42:16
Vue.js
Gleb Kiselev, 2020-02-19 10:42:16

How to correctly describe the logic of converting data to the desired form in vuex actions?

I ran into a problem that my actions became too bloated in the amount of logic, how to separate it all correctly:

convertReceivedDataAndHeaders({commit}, response) {

      const {
        head_info: headersInfo, // Вытаскиваем настройки таблицы (пагинация, количество колонок и тд)
        fields: headers, // Вытаскиваем название колонок, тип колонок
        rows : data // Вытаскиваем данные таблицы
      } = response
      
      commit('setHeadersInfo', headersInfo) // Сразу отдаем данные из заголовков
      
      let filteredHeadersArray = []
      let howManyGridColumnsToShow = 0 // Число колонок которые должны показываться в гриде (нужно для css grid)
      let index = 0
      // Обрабатываем заголовки, именно проходимся по англ названиям, как первичным ключам        
      for (let element in headers) {         
        filteredHeadersArray[index] = {
          'FIELD_NAME' : element.toUpperCase(), // Англ название (в snake_case) приводим к верхнему регистру
          'FIELD_CAPTION' : headers[element]['caption'], // Русское название
          'TYPE' : headers[element]['field_type'], // Номер типа данных, если 1 то это Number, 2 - String
          'IS_PK' : headers[element]['is_pk'], // Если 1, то эта колонка является первичным ключом, если 0, то нет
          'IS_VISIBLE' : headers[element]['is_visible'], // Если 1 то отображаем в гриде эту колонку, если 0, то нет
        }
        index++

        // Прибавляем считчик колонок которые нужно показывать
        headers[element]['is_visible'] == 1 ? howManyGridColumnsToShow++ : 0
      }

      // Сортируем полученный массив заголовков таким образом, чтобы первой колонкой всегда был IS_PK
      filteredHeadersArray = filteredHeadersArray.sort((a, b) => {
        return b['IS_PK'] - a['IS_PK']
      })

      
      let filteredDataArray = []
      // Формируем данные таблицы, отталкиваясь от вычесленных заголовков таблицы
      for (let i = 0; i < filteredHeadersArray.length; i++) {
        // Получаем тип данных для столбца
        const typeInColum = filteredHeadersArray[i]['TYPE'] == 1 ? Number : String
        // Получаем информацию, нужно ли показывать это поле или нет
        const visible = filteredHeadersArray[i]['IS_VISIBLE']
        // На каждой итерации получаем массив значений одного столбца таблицы (по вертекали)
        let dataArray = data[filteredHeadersArray[i]['FIELD_NAME']]
        
        // Если в данных ничего нету, то заполняем ее пустыми данными: первому элементу (он у нас всегда id) даем -1
        // (чтобы по клику на это поля он вызывал создание нового поля, а не редактирование), а всем остальным пустое значение
        if (!dataArray) {
          dataArray = i === 0 ? [-1] : [0]
        }

        // Раскидываем по массивам значения, по сути мы из "вертикальных массивов" делаем "горизонтальные"
        for (let x = 0; x < dataArray.length; x++) {
          // Сразу как закидываем преобразовываем к нужному типу
          if (i === 0) {
            // На первой итерации верхнего цикла мы создаем мыссивы (первую колонку)
            filteredDataArray.push([ { value : typeInColum(dataArray[x]), visible } ])
          } else {
            // На второй итерации верхнего цикла мы уже добавляем в эти колонки значения
            filteredDataArray[x].push( { value : typeInColum(dataArray[x]), visible})
          }
        }
      }

      //  Дополнительная обработка на цвет текста и цвет бэкраунда
      for (let i = 0; i < filteredHeadersArray.length; i++) {
        const fieldName = filteredHeadersArray[i]['FIELD_NAME']
        // Находим тот нужный нам объект где хранятся данные о цвете 
        const colorType = fieldName === 'FONT_COLOR' ? 'FC' : fieldName === 'BG_COLOR' ? 'BC' : null
        
        if (colorType) {
          const dataArray = data[fieldName] // На каждой итерации получаем массив значений одного столбца таблицы

          for (let c = 0; c < dataArray.length; c++) {
            let num = parseInt(dataArray[c]) // Преобразовываем сначала в число
            let hex = num.toString(16) // А потом в формат HEX

            filteredDataArray[c].forEach((item) => {
              if (dataArray[c] == -1) return // Прерываем цикл, если значение по умолчанию
              return item[colorType] = '#' + (hex.length < 2 ? hex + '00000' : 
                                              hex.length < 3 ? hex + '0000' :
                                              hex.length < 4 ? hex + '000' :
                                              hex.length < 5 ? hex + '00' :
                                              hex.length < 6 ? hex + '0' : hex)
            })
          }
        }
      }
      
      commit('setHeadersAndData', { // Передаем обработанные данные в стейт
        gridHeaders : filteredHeadersArray, 
        gridData : filteredDataArray,
        howManyGridColumnsToShow
      })

    }


This is all one dispatch, over time it swelled to such a size that it’s not very cool.

What is the best way to describe such a large data transformation logic, make a bunch of dispatches, or even move this logic to another separate file?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alex, 2020-02-19
@Glebkiselev11

Read about the methodology for refactoring bloated functions - https://refactoring.guru/en/smells/long-method

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question