代码可读性-格式和测试

2016-12-30  本文已影响0人  woodccc

原文地址

代码可读性

格式和测试

格式

读代码就像是读文章、小说、新闻

阅读的顺序一般来说都是从上到下,从左到右

竖向格式

距离产生美

有距离的代码是这样的

…
    const { UDFs, type } = this.props
    
    const textFields = this.handleGroupByType('Text')
    const numericFields = this.handleGroupByType('Numeric')
    const timeFields = this.handleGroupByType('Time')
    const datetimeFields = concat(this.handleGroupByType('Datetime'), timeFields)
    
    const UDFsFunctions = sortBy(filterByUdfTypes(UDFs, [FUNCTION_TYPE_UDF]), UDF => UDF.name)
    const UDAFsFunctions = filterByUdfTypes(UDFs, [FUNCTION_TYPE_UDAF])
    const NORMALsFunctions = filterByUdfTypes(UDFs, [FUNCTION_TYPE_NORMAL])
    const basicFunctions = isNotMetric(type) ? [...UDFsFunctions, ...NORMALsFunctions] : UDFsFunctions
    
    const numericFunctions = filterByReturnType(basicFunctions, 'Numeric')
    const textFunctions = filterByReturnType(basicFunctions, 'Text')
    const datetimeFunctions = filterByReturnType(basicFunctions, 'Datetime')
    
    const distinctUDAFs = uniqBy(UDAFsFunctions, 'name')
    
    const aggregateFunctions = sortBy(distinctUDAFs, 'name')
    const aggregateFunctionsFilter = filter(aggregateFunctions, aggregateFunction => aggregateFunction.tag != 'None')

    return (
…

没有距离就变成下面这样了

…
    const { UDFs, type } = this.props
    const textFields = this.handleGroupByType('Text')
    const numericFields = this.handleGroupByType('Numeric')
    const timeFields = this.handleGroupByType('Time')
    const datetimeFields = concat(this.handleGroupByType('Datetime'), timeFields)
    const UDFsFunctions = sortBy(filterByUdfTypes(UDFs, [FUNCTION_TYPE_UDF]), UDF => UDF.name)
    const UDAFsFunctions = filterByUdfTypes(UDFs, [FUNCTION_TYPE_UDAF])
    const NORMALsFunctions = filterByUdfTypes(UDFs, [FUNCTION_TYPE_NORMAL])
    const basicFunctions = isNotMetric(type) ? [...UDFsFunctions, ...NORMALsFunctions] : UDFsFunctions
    const numericFunctions = filterByReturnType(basicFunctions, 'Numeric')
    const textFunctions = filterByReturnType(basicFunctions, 'Text')
    const datetimeFunctions = filterByReturnType(basicFunctions, 'Datetime')
    const distinctUDAFs = uniqBy(UDAFsFunctions, 'name')  
    const aggregateFunctions = sortBy(distinctUDAFs, 'name')
    const aggregateFunctionsFilter = filter(aggregateFunctions, aggregateFunction => aggregateFunction.tag != 'None')
    return (
…

我也经常这样子做代码格式的处理

import React from 'react'
import Radio from 'antd/lib/radio'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'

import Button from 'components/commons/Button'
import VirtualFieldDropDownMenu from './VirtualFieldDropDownMenu'
import VirtualFieldPreview from './VirtualFieldPreview'
import VirtualMetricPreview from './VirtualMetricPreview'
import Notification from 'components/Notification'
import Title from './Title'

import { insertField, insertFunction, filterByReturnType, filterByUdfTypes } from './virtualFieldService'
import isNotUndefined from 'utils/lodash/isNotUndefined'

import * as ReportActions from 'actions/report'
import * as DataSetFieldsActions from 'actions/dataSetFields'

import * as ReportSelectors from 'selectors/report'

import isUndefined from 'lodash/isUndefined'
import trim from 'lodash/trim'
import isEmpty from 'lodash/isEmpty'
import concat from 'lodash/concat'
import uniqBy from 'lodash/uniqBy'
import sortBy from 'lodash/orderBy'
import filter from 'lodash/filter'

import { FUNCTION_TYPE_UDF, FUNCTION_TYPE_NORMAL, FUNCTION_TYPE_UDAF } from 'constants/BindingItemsConstants'

import './VirtualField.styl'

适当的距离

没有间距

handleAddNewUsers() {
    const { newUsers } = this.state
    if (isEmpty(newUsers)) return Notification.error('所选用户不能为空')
    this.props.updateUsersInUserGroup(this.props.viewUserGroup.id, {userIds: newUsers}).then((response) => {
      responseNotification(response, '添加成功')
      this.setState({newUsers: []})
    })
}

很多间距

handleAddNewUsers() {
  
    const { newUsers } = this.state
    
    if (isEmpty(newUsers)) return Notification.error('所选用户不能为空')
    
    this.props.updateUsersInUserGroup(this.props.viewUserGroup.id, {userIds: newUsers}).then((response) => {
    
      responseNotification(response, '添加成功')
      
      this.setState({newUsers: []})
      
    })

}

适当的间距

handleAddNewUsers() {
    const { newUsers } = this.state
    
    if (isEmpty(newUsers)) return Notification.error('所选用户不能为空')
    
    this.props.updateUsersInUserGroup(this.props.viewUserGroup.id, {userIds: newUsers})
        .then((response) => {
            responseNotification(response, '添加成功')
            this.setState({newUsers: []})
        })
}

大家一起看看这段代码


handleSaveReport({ name, directory, isSaveAsCopy }) {
    const { workingReport, reportId } = this.props

    if (isSaveAsCopy) {
      const requestParams = saveReportCopyRequestParams(name, directory, workingReport)
      this.props.createReportCopy(requestParams, this.state.directoryOfCurrentReport).then(() => {
        Notification.success('另存成功')
        this.setState({openSaveReportDialog: false, isSaveAsCopy: false})
      }).catch((errors) => forEach(errors, error => Notification.error(error)))
    } else {
      const request = saveReportRequestParams(name, directory, workingReport)
      this.props.saveWorkingReport(reportId, request, this.props.currentPageId).then(() => {
        Notification.success('报表已保存')
        this.setState({openSaveReportDialog: false, isSaveAsCopy: false})
      }).catch((errors) => forEach(errors, error => Notification.error(error)))
    }
  }

修改意见


handleSaveReport({ name, directory, isSaveAsCopy }) {
    const { workingReport, reportId } = this.props

    if (isSaveAsCopy) {
    
      const requestParams = saveReportCopyRequestParams(name, directory, workingReport)
      
      this.props.createReportCopy(requestParams, this.state.directoryOfCurrentReport)
          .then(() => {
            Notification.success('另存成功')
            this.setState({openSaveReportDialog: false, isSaveAsCopy: false})
          })
          .catch((errors) => forEach(errors, error => Notification.error(error)))
          
    } else {
    
      const request = saveReportRequestParams(name, directory, workingReport)
      
      this.props.saveWorkingReport(reportId, request, this.props.currentPageId)
          .then(() => {
            Notification.success('报表已保存')
            this.setState({openSaveReportDialog: false, isSaveAsCopy: false})
          })
          .catch((errors) => forEach(errors, error => Notification.error(error)))
     }
  }

划重点(此处用力敲黑板)

1.有关联的代码放在一块,并且与其他代码块用空行隔开(垂直方向上的靠近与距离)

2.垂直顺序(自上而下的展示函数调用依赖顺序)

横向格式

横向的间隔与靠近

有横向间隔的代码

const quarter = Math.floor((today.getMonth() + 3) / 3)

删除这些横向间隔

const quarter=Math.floor((today.getMonth()+3)/3)

强调运算优先级

…
const XXX = (Math.…) + (a*2)
…

横向格式应有空格的地方(此处用力敲黑板)

const view = this.props.view

handleChange() {  …  }

handleSave(arg1, arg2) {  …  }

['a', 'b', 'c']

const { id, name } = view

[slide]

{:&.rollIn}

格式(完)

测试

使用函数

describe('buildSelectorValue', () => {
  it('should return new selector when oldSelectors is empty', () => {
    const oldSelectors = {}
    const originalSelector = buildOriginalSelector(1, ['四川'])
    const exceptSelector = buildExceptSelector(1, ['四川'])

    expect(buildSelectorValue(oldSelectors, originalSelector)).to.eql(exceptSelector)
  })

})

使用常量

it('should return selectors deleted by viewId', () => {
  expect(deleteSelectorByViewId(twoViewsState, deleteSelectorViewId)).to.eql(oneViewState)
})

const deleteSelectorViewId = '1'
const twoViewsState = {
  '1': {
    pageId: 1,
    dataSetId: 3,
    values: [{
      fieldId: 4,
      selectorValues: ['四川']
    }]
  },
  '2': {
    pageId: 1,
    dataSetId: 3,
    values: [{
      fieldId: 4,
      selectorValues: ['广东']
    }]
  }
}
…

使用函数和常量的利与弊


| 利 | 弊
:-------|:------:|--------
函数 | 便于重用 | 逻辑复杂
函数 | 不会暴露细节 | 不够直观
常量 | 无逻辑 | 重复太多
常量 | 够直观 | 异常点不是很明确

上一篇 下一篇

猜你喜欢

热点阅读