Skip to content

组织代码

编码模式

旧模式:

  1. 处理相同逻辑关注点的代码被强制拆分在了不同的选项中,位于文件的不同部分。
  2. 「这写的什么玩意,这变量干嘛用的!」

改组后:

ts
export default {
  setup() {
    // Network
    const { networkState } = useNetworkState();
    // Folder
    const { folders, currentFolderData } = useCurrentFolderData(networkState);
    //
    const folderNavigation = useFolderNavigation({ networkState, currentFolderData });
    //
    const { favoriteFolders, toggleFavorite } = useFavoriteFolders(currentFolderData);
    //
    const { showHiddenFolders } = useHiddenFolders();
    //
    const createFolder = useCreateFolder(folderNavigation.openFolder);
    // Current working directory
    resetCwdOnLeave();
    //
    const { updateOnCwdChanged } = useCwdUtils();
    // Utils
    const { slicePath } = usePathUtils();
    //
    return {
      networkState,
      folders,
      currentFolderData,
      folderNavigation,
      favoriteFolders,
      toggleFavorite,
      showHiddenFolders,
      createFolder,
      updateOnCwdChanged,
      slicePath,
    };
  },
};

示例

代码改造演示 - 改造前
vue
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useHttp } from '@monorepo/vue-use'
import { APPLICANT_CONFIG } from '@/views/work-online/form/schema'
import { LOGIN_TYPE } from '@/constant/user'

const props = defineProps<{
  // 业务表id
  bzmGgSb: string
}>()

// 申请人列表
const applicantList = ref([])

// 表格字典
const tableDict = ref({})

// 弹出框显隐
const showDialog = ref(false)

// 弹窗声明
const dialogRef = ref<any>()

// 表单ref申明
const formRef = ref()

// 字典数据信息接口请求
const zdSjLb = useHttp('/api/chxx/ww/Vzdsj')

// 字典数据信息接口请求
const sqrHttp = useHttp('/api/ws/GgSqr')

// 实体
const formEntity = ref<any>({})

// table按钮点击事件
function onCompanyTable(key: string, { row }: any) {
  console.log(key, row)
  if (key === 'edit') {
    formEntity.value = row
    showDialog.value = true
  }

  if (key === 'delete')
    deleteApplicant(row.bzmGgSqr)
}

// 证件类型
const zjLxList = ref<any>([])
const zjLxListShow = ref<any>([])
// 申请人类型列表
const sqrLxList = ref<any>([])

// 个人申请人类型
const SQR_LX_PERSON = ref(['1'])
// 企业申请人类型
const SQR_LX_ENTERPRISE = ref(['2', '3', '4'])
// 个人申请人证件类型范围
const SQR_ZJ_ZL_PERSON = ref(['1', '2', '3', '4', '5'])

// 登录用户数据
const userInfo = computed(() => {
  const userExtInfoJson = window.localStorage.getItem('userExtInfo')
  const userExtInfo = JSON.parse(userExtInfoJson)

  const userInfoJson = window.localStorage.getItem('userInfo')
  const userInfo = JSON.parse(userInfoJson)

  return {
    dlLx: userExtInfo.dlLx,
    accountId: userInfo.accountId,
    xm: userExtInfo.dlLx === LOGIN_TYPE.ENTERPRISE ? userExtInfo.frDwmc : userExtInfo.smZsxm,
    lxDh: userExtInfo.dlLx === LOGIN_TYPE.ENTERPRISE ? userExtInfo.frLxrSjh : userExtInfo.smSjh,
    zjHm: userExtInfo.dlLx === LOGIN_TYPE.ENTERPRISE ? userExtInfo.frTyshxydm : userExtInfo.smSfzh,
  }
})

// 弹窗事件
function onDialog(key: string) {
  if (key === 'ok') {
    // 确定按钮
    submit()
  }

  if (key === 'cancel')
    closeFormDialog()
}

// 初始化字典数据
function getDictData() {
  const dictTypes = ['申请人性质', '证件类型']

  zdSjLb.get(`${dictTypes}`).then((res: any) => {
    if (res != null) {
      zjLxList.value = res['证件类型'].map((v) => {
        return { label: v.fullName, value: v.enCode }
      })
      sqrLxList.value = res['申请人性质'].map((v) => {
        return { label: v.fullName, value: v.enCode }
      })

      tableDict.value = { zjLx: zjLxList.value, sqrLx: sqrLxList.value }
    }
  })
}

// 提交
function submit() {
  formRef.value.validate((entity: any) => {
    const requestUrl = entity.bzmGgSqr ? 'editSbrInfo' : 'saveSbrInfo'
    sqrHttp.put(requestUrl, { ...entity, bzmGgSb: props.bzmGgSb }).then((res) => {
      getSqrList()
      closeFormDialog()
    })
  })
}

// 删除申请人
function deleteApplicant(bzmGgSqr) {
  sqrHttp.delete('delete', { bzmGgSqr }).then(() => {
    getSqrList()
  })
}

// 关闭dialog
function closeFormDialog() {
  showDialog.value = false
  formEntity.value = {}
}

// 获取申请人列表
function getSqrList() {
  sqrHttp.get('getSqrList', { bzmGgSb: props.bzmGgSb }).then((res) => {
    applicantList.value = res
  })
}

// 申请人类型事件
function sqrLxChange(key, sqrLx) {
  if (key !== 'change')
    return

  // 证件类型
  let list = []

  // 根据申请人类型
  if (!sqrLx)
    list.push('1')

  if (SQR_LX_PERSON.value.includes(sqrLx)) {
    list = SQR_ZJ_ZL_PERSON.value
    // 设置默认值为身份证
    formEntity.value.sqrzjzlBm = '1'
  }

  if (SQR_LX_ENTERPRISE.value.includes(sqrLx)) {
    list = ['82']
    // 设置默认值为统一社会信用代码
    formEntity.value.sqrzjzlBm = '82'
  }

  zjLxListShow.value = zjLxList.value.filter((item) => {
    return list.includes(item.value)
  })
}

onMounted(() => {
  getDictData()
  // 获取申请人数据
  getSqrList()
})
</script>

<template>
  <e-title class="my-3 w-full justify-between" title="申请人(单位)信息" icon="carbon:identification">
    <el-button size="small" type="primary" class="mb-1 mr-1" icon="plus" @click="showDialog = true">
      新增
    </el-button>
  </e-title>

  <e-table
    v-model="applicantList" adaptor="v3" :columns="APPLICANT_CONFIG.TABLE" row-key="bzmGgSqr" :dicts="tableDict"
    :action-list="['edit', 'delete']" @cmd="onCompanyTable"
  />

  <!-- 表单 -->
  <e-dialog
    ref="dialogRef" v-model="showDialog" :keep-alive="true" class="h-auto w-520px"
    title="申请人(单位)信息" @cmd="onDialog"
  >
    <e-form
      ref="formRef"
      v-model="formEntity" prop="f1" adaptor="v3" class="px-4 pt-4" :label-width="200"
      item-class="w-1/2" :schema="APPLICANT_CONFIG.FORM_SCHEMA"
    >
      <template #sqrlxBm>
        <e-adaptor
          v-model="formEntity.sqrlxBm"
          adaptor="select"
          :schema="sqrLxList"
          @cmd="sqrLxChange"
        />
      </template>

      <template #identification>
        <e-adaptor
          v-model="formEntity.sqrzjzlBm"
          adaptor="select"
          :schema="zjLxListShow"
        />
      </template>
    </e-form>
    <div class="h-16" />
  </e-dialog>
</template>
代码改造演示 - 改造后
vue
<script setup lang="ts">
import { APPLICANT_CONFIG } from '@/views/work-online/form/schema';
import { useHttp } from '@monorepo/vue-use';
import { onMounted, ref } from 'vue';

const props = defineProps<{
  // 业务表id
  bzmGgSb: string
}>()

const BlockO = {
  // 个人申请人类型
  SQR_LX_PERSON: ['1'],
  // 企业申请人类型
  SQR_LX_ENTERPRISE: ['2', '3', '4'],
  // 个人申请人证件类型范围
  SQR_ZJ_ZL_PERSON: ['1', '2', '3', '4', '5']
}

// 字典数据信息接口请求
const sqrHttp = useHttp('/api/ws/GgSqr')

/**
 *  字典数据处理:涉及 申请人列表 证件类型
 */
function useDicts() {
  // 字典数据信息接口请求
  const zdSjLb = useHttp('/api/chxx/ww/Vzdsj')
  // 证件类型
  let zjLxList = []
  //
  const zjLxListShow = ref<any>([])
  // 申请人类型列表
  const sqrLxList = ref<any>([])
  // 表格字典
  const tableDict = ref({})
  // 初始化字典数据
  function getDictData() {
    const dictTypes = ['申请人性质', '证件类型']

    zdSjLb.get(`${dictTypes}`).then((res: any) => {
      if (res != null) {
        zjLxList = res['证件类型'].map((v) => {
          return { label: v.fullName, value: v.enCode }
        })
        sqrLxList.value = res['申请人性质'].map((v) => {
          return { label: v.fullName, value: v.enCode }
        })

        tableDict.value = { zjLx: zjLxList, sqrLx: sqrLxList.value }
      }
    })
  }

  return {
    tableDict,
    sqrLxList,
    zjLxListShow,
    getDictData,
    filterFromSQRLX(list) {
      zjLxListShow.value = zjLxList.filter((item: any) => {
        return list.includes(item.value)
      })
    }
  }
}

const { tableDict, sqrLxList, zjLxListShow, getDictData, filterFromSQRLX } = useDicts()

/**
 * 弹窗及表单相关
 */
function useDialogAndForm({ filterFromSQRLX }) {
  // 表单ref申明
  const formRef = ref()
  // 实体
  const formEntity = ref<any>({})
  // 弹出框显隐
  const formVisible = ref(false)
  // 弹窗声明
  const dialogRef = ref<any>()
  // 关闭dialog
  function closeFormDialog() {
    showDialog(false)
    formEntity.value = {}
  }
  // 提交
  function submit() {
    formRef.value.validate((entity: any) => {
      const requestUrl = entity.bzmGgSqr ? 'editSbrInfo' : 'saveSbrInfo'
      sqrHttp.put(requestUrl, { ...entity, bzmGgSb: props.bzmGgSb }).then((res) => {
        fetchSqrList()
        closeFormDialog()
      })
    })
  }

  function showDialog(flag?) {
    formVisible.value = flag ?? true
  }

  return {
    showDialog,
    formVisible,
    formRef,
    formEntity,
    // 弹窗事件
    onDialog(key: string) {
      if (key === 'ok') {
        // 确定按钮
        submit()
      } else if (key === 'cancel')
        closeFormDialog()
    },
    // 申请人类型事件
    onSelectSQRLX(key, sqrLx) {
      if (key !== 'change')
        return
      // 证件类型
      let list: any[] = []

      // 根据申请人类型
      if (!sqrLx)
        list.push('1')

      if (BlockO.SQR_LX_PERSON.includes(sqrLx)) {
        list = BlockO.SQR_ZJ_ZL_PERSON
        // 设置默认值为身份证
        formEntity.value.sqrzjzlBm = '1'
      }

      if (BlockO.SQR_LX_ENTERPRISE.includes(sqrLx)) {
        list = ['82']
        // 设置默认值为统一社会信用代码
        formEntity.value.sqrzjzlBm = '82'
      }
      filterFromSQRLX(list)
    }
  }
}

const { showDialog, formVisible, formRef, formEntity, onDialog, onSelectSQRLX } = useDialogAndForm({ filterFromSQRLX })

/**
 * 表格数据
 */
function useTableForApplicantList() {
  // 申请人列表
  const applicantList = ref([])

  // 删除申请人
  function deleteApplicant(bzmGgSqr) {
    sqrHttp.delete('delete', { bzmGgSqr }).then(() => {
      fetchSqrList()
    })
  }

  return {
    applicantList,
    // 获取申请人列表
    fetchSqrList() {
      sqrHttp.get('getSqrList', { bzmGgSb: props.bzmGgSb }).then((res) => {
        applicantList.value = res
      })
    },
    // table按钮点击事件
    onCompanyTable(key: string, { row }: any) {
      if (key === 'edit') {
        formEntity.value = row
        showDialog()
      } else if (key === 'delete')
        deleteApplicant(row.bzmGgSqr)
    }
  }
}

const { applicantList, fetchSqrList } = useTableForApplicantList()

onMounted(() => {
  getDictData()
  // 获取申请人数据
  fetchSqrList()
})
</script>

<template>
  <e-title class="my-3 w-full justify-between" title="申请人(单位)信息" icon="carbon:identification">
    <el-button size="small" type="primary" class="mb-1 mr-1" icon="plus" @click="showDialog">
      新增
    </el-button>
  </e-title>

  <e-table v-model="applicantList" adaptor="v3" :columns="APPLICANT_CONFIG.TABLE" row-key="bzmGgSqr" :dicts="tableDict"
    :action-list="['edit', 'delete']" @cmd="onCompanyTable" />

  <!-- 表单 -->
  <e-dialog v-model="formVisible" :keep-alive="true" class="h-auto w-520px" title="申请人(单位)信息" @cmd="onDialog">
    <e-form ref="formRef" v-model="formEntity" prop="f1" adaptor="v3" class="px-4 pt-4" :label-width="200"
      item-class="w-1/2" :schema="APPLICANT_CONFIG.FORM_SCHEMA">
      <template #sqrlxBm>
        <e-adaptor v-model="formEntity.sqrlxBm" adaptor="select" :schema="sqrLxList" @cmd="onSelectSQRLX" />
      </template>

      <template #identification>
        <e-adaptor v-model="formEntity.sqrzjzlBm" adaptor="select" :schema="zjLxListShow" />
      </template>
    </e-form>
    <div class="h-16" />
  </e-dialog>
</template>

技术债

  • 技术债:简单来说就是“以后再修”的心态。先采用捷径实现,有空再修改成更优的方式。

  • 初心:最开始,先让功能可用就行,而优化留到以后。 短期来看这可能行得通,因为它可以加快项目进度,你可能在 deadline 前完成。

  • 结果:做就会留下大量待完成的工作。会使维护、扩展和优化软件变得更加困难。

  • 技术债会以多种方式阻碍码农的生产力。列举一些:

  1. Code Review 的瓶颈:当技术债增加时,会增加 Code Review 所花费的时间。
  2. 更多 Bug:由于关注点都在速度而不是优化上,会导致引入隐藏的 Bug。
  3. 代码质量降低:只为了让它可以跑,会导致糟糕的代码质量、随意的 Code Review,甚至没有代码注释,随意乱写复杂的代码等。

上述所有点都需要额外的时间来处理。因此,这会拖长项目的时间线。

其他

推荐阅读