当前位置: 首页 > news >正文

奉化建设局网站白云区建材网站建设推广

奉化建设局网站,白云区建材网站建设推广,海南省建设执业资格管理中心网站,网站有了订单邮箱提醒代码软件开发中#xff0c;有个很重要的DRY原则#xff0c;即Dont Repeat Yourself#xff0c;也就是不要重复自己。 重复的代码会带来以下问题#xff1a; 开发效率低#xff0c;重复造轮子不同人开发的同一类功能#xff0c;质量层次不齐修改问题时可能会遗漏#xff0c…软件开发中有个很重要的DRY原则即Dont Repeat Yourself也就是不要重复自己。 重复的代码会带来以下问题 开发效率低重复造轮子不同人开发的同一类功能质量层次不齐修改问题时可能会遗漏修了这个地方忘了那个地方导致一个bug反复修改多次。 重复产生的原因是多方面有的是工作模式导致的有的是编码导致的弄清楚重复的原因也就很容易找出消除重复的方法。 工作模式导致的重复 团队缺少沟通 同一个团队可能会针对相同或相似的功能进行编码有时你封装了一个功能却没有在团队内部大量使用 究其原因可能是大家根本不知道有这么个功能或者不知道怎么使用干脆自己写也或者虽然有点相似但是并不完全适用自己。 这类问题核心还是沟通问题所以要根本解决这类重复我们必须在工作流程上做一些改进。 1.基础功能开发评审 当你要开发一个基础功能时需要发起设计评审这样首先起到了周知的作用让大家知道有这么个东西 其次大家会针对功能提出自己的建议以方便他人后续使用。 2.基础功能宣贯 在开发完某个功能之后需要及时的进行宣贯让其他同事知道可以使用了可以在每周的团队周会上安排一个环节 进行公共功能的变更宣贯。 3.CodeReview CodeReview中发现存在重复问题及时提出修正。 缺少基础设施-公共库 在一个项目中我们可能建一个公共的文件夹比如common用来存放我们的基础组件和库但是一旦跨项目这种方式就无效了 如果没有公共库就需要进行复制粘贴了把一段代码从一个项目复制到另一个项目这样就造成一个问题的修改需要同时修改多个项目 如果赶上项目时间紧张再加上可能有懒惰思想慢慢的多个项目之间的基础功能就不再一致了后续的维护更加复杂。 解决这类问题可以参考两个方法 1.使用monorepo monorepo也就是单一仓库管理多个项目有些公司将所有代码存储在一个代码库中由所有人共享 因此monorepo可以非常大。例如理论上谷歌拥有有史以来最大的代码库每天有成百上千次提交整个代码库超过 80 TB。 其他已知运营大型单一代码库的公司还有微软、Facebook 和 Twitter。 我们可以在monorepo中添加一个公共项目用来存放我们的基础组件和utils工具库。 2.通过发布公共包 可以建设一个基础组件库发包到npm或者公司内部的包管理系统。 monorepo和npm发包各有优缺点根据自身情况进行选择。 知识的重复 在团队中不只是代码存在重复在知识层面也会存在重复比如大家重复的进行某个知识的学习包括技术上的和业务上的 整体上增加了团队工作的重复降低了效率。 针对知识的重复我们可以定期举办内部分享。 1.新功能上线演示 针对一些大的功能上线可以组织内部的上线演示一方面增加大家对业务的了解另一方面减少大家后续重复学习的问题。 2.定期分享 团队内部定期举办业务、技术、工作方法/效率等方面的分享减少对知识学习的重复工作。 编码层面的重复 没有意识到重复 有时候重复的代码并不是那么明显可能只是几行代码由于重复的行数较少所以就很自然的采用复制粘贴 没有意识到重复的发生。 比如针对一个应用的状态判断应用存在多种状态比如未安装(Uninstalled)、运行中Running、已销毁Destroyed等 只有当应用处于未安装或者已销毁状态才允许安装而这个条件可能在多处都使用。 // 应用列表页在进行安装操作时进行状态的判断 function install(app) {if ([Uninstalled, Destroyed].includes(app.status)) {} } !--应用详情页在进行安装时进行状态的判断-- templatebutton v-if[Uninstalled, Destroyed].includes(app.status)安装/button /template 每当安装条件发生变更时都要四处寻找然后一个一个地方修改针对这种也应该进行封装虽然他很小。 我们可以封装一个判断是否能安装的方法其他地方进行引用。 //抽象一个方法判断是否能按照 function canInstall(app) {return [Uninstalled, Destroyed].includes(app.status) }//在需要进行状态判断的地方引用封装的函数 function install(app) {if (canInstall(app)) {} } 后续安装条件发生变更只需要修改canInstall方法即可 //需求发生变化InstallError状态和没有runtimeId也支持安装 function canInstall(app) {return [Uninstalled, Destroyed, InstallError].includes(app.status)|| !app.runtimeId } 我们一般对大块的重复代码比较敏感而对于小块的代码重复则一般会忽略但是重复是部分大小的小段代码很可能在更多的地方使用。 缺少抽象和封装 比如要让你炸毁地球不应该直接写一个炸毁地球的方法而是写一个炸毁星球的方法将地球作为参数传进去。 抽象的东西要比具体的东西复用性更强因此要想提高复用性就要对所做的功能进行抽象而不是面向具体单一的业务需求开发。 示例1组件的重复 比如在删除k8s资源时需要输入k8s资源的名称进行确认输入正确后才能进行删除于是针对这个业务场景封装了一个弹窗确认组件 在调用显示弹窗方法showDialog时传入了一个名为k8s资源名称(k8sResourceName)的参数。 !--删除确认弹窗 DeleteResource.vue 的实现-- templateel-dialogtitle删除确认:visible.syncdialogVisibleconfirmdeleteResourcediv请输入span{{ k8sResourceName }}/span确定删除/divel-input v-model.triminputName//el-dialog /templatescript export default {data() {return {dialogVisible: false,k8sResourceName: ,inputName: };},methods: {showDialog(params) {this.k8sResourceName params.k8sResourceName;this.dialogVisible true;this.inputName ;},deleteResource() {if (this.inputName this.k8sResourceName) {this.dialogVisible false;this.$emit(delete);}}} }; /script 其实这是一个很常用的功能可能很多地方都会使用比如在删除应用页面也可能用到这个组件进行确认 那么我们传递一个名为k8sResourceName的参数显然是很不合适的这里只是简化了这块的实现实际可能并不是简单改一个名称这么简单。 显然并不是写这块代码的同事 没有能力封装一个通用的组件而是缺少抽象的思维导致写出了面向具体单一业务的组件。 试着利用抽象思维写出更具复用性的代码。 示例2样式的重复 比如在CSS中经常会针对某段文字设置字体大小、颜色等一般情况下同一个网站的字体大小、颜色是存在共性的 比如标题的颜色每个页面都是一样的提示类型的文字颜色也是一样的如果没有进行抽象那么我们代码可能是这样的。 .news-title {color: #409EFF;font-size: 16px; }.app-title {color: #409EFF;font-size: 16px; } 这样的设置会在样式中存在大量的重复大致有两个解决方法。 第一种就是对整个网站的css进行分层比如样式分为全局样式、页面样式和组件样式。我们可以在全局样式中抽取共性的css样式。 比如抽取common.css定义网站通用标题的样式。 .common-title {color: #409EFF;font-size: 16px; } 另外一种就是通过抽取一些变量在页面样式和组件样式中引用这些变量。 比如element中的var.scss /* Color -------------------------- */ /// color|1|Brand Color|0 $--color-primary: #409EFF !default; /// color|1|Background Color|4 $--color-white: #FFFFFF !default; /// color|1|Background Color|4 $--color-black: #000000 !default;/* Size -------------------------- */ $--size-base: 14px !default;/* z-index -------------------------- */ $--index-normal: 1 !default; $--index-top: 1000 !default; $--index-popper: 2000 !default; 后续如果想修改网站的配色只需要修改模板文件即可。 示例3网络请求的重复 网络请求也是重复容易滋生的地方比如在一个组件内部请求文章的详情方法getNewsDetail看看有那几处重复呢 script import axios from axiosexport default {methods: {getNewsDetail(id) {axios.get(/api/v1/news/detail/ id).then(res {this.detail res}).catch(e {if (e.code 401) {showToast(未登录请先登录)} else {showToast(接口请求失败)}})}} } /script 上述代码可能存在如下重复问题 接口地址可能存在重复别的页面也能会使用文章详情接口如果接口地址发生变更需要修改多处请求方法可能存在重复别的页面如果也要请求文章详情也需要写一个getNewsDetail方法错误处理存在重复多个网络请求可能都要进行相同的错误处理请求依赖具体的第三方库axios如果有一天要更换网络请求库则需要进行大量的修改 接下来我们来逐一解决这些重复。 首先是依赖axios的问题我们尽量不要直接依赖某个第三方插件解决办法也很简单就是增加一层封装 这样把依赖局限在具体某个方法内部后续要替换只需要更改一处即可也就是上层业务不依赖底层实现。 不是axios有什么功能我的网络请求怎么调用而是我想怎么调用网络请求怎么利用axios进行实现 也就是要遵循依赖倒置原则。 我们可以实现一个request方法来完成网络请求内部调用axios同时进行通用的错误处理。 // request.js import axios from axiosexport default function request(config) {return new Promise((function (resolve, reject) {axios(config).then(res {if (res.code res.code 200) {resolve(res)} else if (res.code 401) {//其他各种错误处理类似showToast(网络请求失败)window.location.href /#/login} else {reject(res)}}).catch(e {reject(e)})})) }[get, post, put, delete].forEach(method {return function (url, params, body, options) {return request({method,url,params,body,...options})} }) 针对接口重复问题我们可以创建一个 api.js文件来配置各个接口地址。 export default {newDetail: /api/v1/news/detail/:id// 其他接口地址 } 针对接口调用重复问题我们可以封装一个service层所有页面调用均通过调用service层方法来实现。 service/news.js import request from ./utils/request import api from ./apiexport default {getNewsDetail(id) {return request.get(api.newDetail, {id}).then(res {return res.data})} } 修改之前和修改之后对比如下通过增加中间层service.js、封装网络请求方法request.js以及封装接口地址配置常量api.js 大大降低网络请求的复用同时也不再依赖第三方axios实现了解耦。 职责不单一 单一职责的函数或者组件就像是一个积木块而不满足单一职责特性的函数或组件就像是一个功能模块。 单一职责的积木块可以进行各种排列组合绽放出强大的生命力而多功能的模块只适用于特定的业务场景复用性则大大降低。 比如我们要实现一个下载一段文字的功能这个功能分为两步第一步将文字内容转为url第二步通过创建a标签实现下载。 假如实现的downloadText方法如下 function downloadText(text, filename) {//根据text内容创建urllet blob new Blob([content]);let url URL.createObjectURL(blob);//创建a标签通过模拟a标签的点击实现下载let eleLink document.createElement(a);eleLink.download filename;eleLink.style.display none;eleLink.href urldocument.body.appendChild(eleLink);eleLink.click();document.body.removeChild(eleLink); } 很明显这里不符合单一职责假如我现在不是根据text文本进行下载而是给定一个具体src下载可能还要再写个downloadUrl方法很明显二者之间有很多重复。 function downloadText(text, filename) {//根据text内容创建urllet blob new Blob([text]);let url URL.createObjectURL(blob);//创建a标签通过模拟a标签的点击实现下载let eleLink document.createElement(a);eleLink.download filename;eleLink.style.display none;eleLink.href urldocument.body.appendChild(eleLink);eleLink.click();document.body.removeChild(eleLink); }function downloadUrl(url, filename) {//创建a标签通过模拟a标签的点击实现下载let eleLink document.createElement(a);eleLink.download filename;eleLink.style.display none;eleLink.href urldocument.body.appendChild(eleLink);eleLink.click();document.body.removeChild(eleLink); } 根据单一职责原则对downloadText方法进行拆分可以拆成两个一个根据文本生成url一个根据url进行下载如果还想保留downloadText 只需要组合这两个小方法即可这样我们一下就产出了3个通用方法。 function createUrlByText(text) {let blob new Blob([text]);return URL.createObjectURL(blob); }function downloadUrl(url, filename) {let eleLink document.createElement(a);eleLink.download filename;eleLink.style.display none;eleLink.href urldocument.body.appendChild(eleLink);eleLink.click();document.body.removeChild(eleLink); }//对上面的单一职责功能进行组合 function downloadText(text, filename) {let url createUrlByText(text)downloadUrl(url, filename) } 其实功能实现并没有本质的区别只是简单的进行拆分使其满足单一职责原则即大大提高了复用性。 数据之间的重复 数据之间的重复也是经常出现的一种重复问题也就是能用1个字段表示的数据不要用2个或多个字段表示。 通常可以有1个基础的数据字段其他字段可以通过这个基础字段来计算而不是维护其他几个额外字段。 比如要实现如下的一个列表一共有3个字段列表数据list、已选中数量selectedCount、总数量totalCount。 假如维护这三个字段每次当列表数据发生变化时可能是选择状态变化也可能是增删数据 都要小心设置selectedCount、totalCount否则就会出现数据不一致的bug这其实是一种逻辑上的重复。 我们可以只维护一个基础数据listselectedCount和totalCount都可以通过对list进行计算而得到 可能是写一个方法每次刷新组件时重新计算也可以利用vue中的计算属性。 script export default {data() {return {list: [{name: 苹果,selected: false},{name: 橘子,selected: true},{name: 香蕉,selected: true}]}},computed: {selectedCount() {return this.list.filter(item item.selected).length},totalCount() {return this.list.length}} } /script 这样我们只需要对list进行处理即可其他两个字段自动计算出来避免数据不一致问题。 复用和耦合 复用虽好但是也不能贪杯因为复用就意味着耦合不合理的复用会导致严重的耦合代码可读性及可维护性变差。 不合理的复用甚至不如不进行复用所以在进行复用抽象时应该慎重。 充斥着各种if-else的复用 有的复用并不是真正的复用而是将一些功能集中到了一个函数内部然后再内部进行大量的if-else判断实际是把逻辑复杂性转移到了函数内部 由于存在大量的分支判断复杂度呈现指数式增长。 比如应用的安装、重启、销毁、切换版本等都使用一个函数表面上都复用了operate函数但是却在函数内部进行大量的分支判断各自处理各自的事情 而且由于各个操作需要的传参可能还不一样导致虽然共用一个函数但是传参不一样内部处理逻辑也没有复用还增加了耦合 导致想要搞明白某个操作的处理流程非常复杂这样的复用有什么意义呢 !--不合理的复用-- templatedivel-button clickoperate(row, install)部署/el-buttonel-button clickoperate(row, restart)重启/el-buttonel-button clickoperate(row, destroy)销毁/el-buttonel-button clickoperate(row, upgrade-version, row.package_version)切换版本/el-button/div /template script export default {methods: {operate(row, opt, package_version) {if (opt install) {//...}if (opt destroy) {//...} else if ([install, update-values, update-default, upgrade-version].includes(opt)) {//...} else {if ([restart].includes(opt)) {//...} else {//...}}}} } /script 上面这个不如针对不同的操作直接对应一个独立的处理函数如果多个函数之间有复用可以抽取出来公共函数但是每个操作的处理流程是清晰的。 修改之后每个交互对应的操作是明确的由于拆分了传参也简化了每个操作内部没有了分支判断逻辑也简化了。 !--修改之后-- templatedivel-button clickinstall(row)部署/el-buttonel-button clickrestart(row)重启/el-buttonel-button clickdestroy(row)销毁/el-buttonel-button clickupgradeVersion(row,row.package_version)切换版本/el-button/div /template script export default {methods: {install(row) {//安装处理流程this.commonOperate()},restart(row) {//重启处理流程this.commonOperate()},destroy(row) {//销毁处理流程this.commonOperate()},upgradeVersion(row, version) {//切换版本处理流程this.commonOperate()},commonOperate() {//...}} } /script 尽量不要复用不同业务的处理流程不同业务的流程后续很可能向着不同的方向发展强行复用只会增加复杂度和耦合我们可以抽象各个流程的公共处理方法 比如多个操作的接口请求是一致的但是每个操作的参数是不同的那么可以在不同的业务处理方法中准备不同的参数然后调用统一的网络请求方法完成接口调用。 还有一种类似的问题出现在UI的复用上根据不同的属性比如应用的操作类型(安装、重启等待)渲染不同的页面由于充斥大量的分支 很难搞明白某个操作对应那些UI修改某个bug时很容易引入新的bug。 templatedivdiv v-ifoperate install***/divdiv v-else***/divdiv v-if[install, start].includes(operate)***/div/div /template script export default {props: [operate] } /script 综上当遇到有大量分支判断时就要考虑这个复用是否合理了。 入口文件尽量不要复用 所谓的入口文件就是和用户直接进行交互的文件比如不同路由对应的页面是一种入口文件不同按钮对应的handle函数也是一种入口文件 入口文件耦合着业务逻辑最好不进行复用。 比如两个路由对应的页面非常相似如果我们直接复用这个路由文件那么就会在路由文件的实现中进行各种if-else判断来区分环境 而且很难了解不同路由到底会对页面产生哪些影响。 比如route1和route2复用User组件那么User组件内部肯定要进行各种条件判断来针对route1和route2呈现不同的效果 那么要问route1和route2的表现在User组件有什么不同你必须去仔细阅读User的实现才能知晓。 //假设两个页面很相似复用了路由入口文件 const routes [{path: route1,name: route1,component: User,},{path: route2,name: route2,component: User,}, ] User组件实现 templatediv!-- 入口文件只能通过路由不同的参数来区分到底是从哪个路由进来的呈现不同效果 --div v-if$route.params.test ****/divdiv v-else**/div/div /template script export default {mounted() {// 入口文件只能通过路由不同的参数来区分到底是从哪个路由进来的呈现不同效果if (this.$route.params.test **) {//...} else {//...}} } /script 复用了入口文件后很难说清楚不同入口有什么区别如果入口文件不复用我们可以把公共内容封装成组件然后在不同的入口文件中进行调用 调用时传递明确的属性很清楚整体的逻辑。 比如route1对应User1文件route2对应User2文件 //假设两个页面很相似复用了路由入口文件 const routes [{path: route1,name: route1,component: User1,},{path: route2,name: route2,component: User2,}, ] User1组件实现如下User1组件中调用组件User同时传递属性过去 templateUser :can-addtrue :can-deletefalse / /template User2组件实现如下User2组件也调用复用的组件User同时传递所需属性过去 templateUser :can-addfalse :can-deletetrue / /template User组件实现 templatediv v-ifcanAdd添加/divdiv v-ifcanDelete删除/div /template script export default {props:[canAdd, canDelete] } /script 我们通过抽取User组件实现了主要功能的复用同时又避免了入口文件的复用每个入口文件传递什么属性都很容易看到也很容易理解其中逻辑。 类似的不同按钮对应的操作函数尽量不要复用因为不同的按钮就代表不同的业务流程很难说多个业务的流程始终能保持一致可能初始时 两个按钮操作基本一样但是随着后续需求变化这个复用的函数就开始增加各种if-else以应对需求变化导致可读性越来越差耦合越来越多。 不能因为长得相似就复用 假如某个管理系统的2个列表页非常相似比如一个是资讯列表页一个是商品列表页它们都有一个添加按钮、一个按名称搜索的输入框一个表格 而且表格的列都只有名称、创建人、创建时间三列那么我们应该复用吗 很显然这样的情况是不能复用的随着业务的发展资讯和商品一定会向着两个不同的方向发展不可避免的后续会增加各种逻辑判断 而且因为这种耦合还会造成各种意外的bug。 我们应该复用其中的组件单元比如统一的button组件、搜索表单、表格组件通过组合基础组件来完成两个页面的开发。 类似的还有表单校验的规则比如名称和描述可能初始的校验规则一致就进行了复用但是本质上名称和描述是不同的业务元素 他们的校验规则并没有完全的相关性很可能后续往着不同的方向发展。但是如果是多个表单的同一个业务元素的校验则是可以复用的 可以预料到如果该元素在这个页面变化了校验在其他页面也应该会变化。 是否能复用要看逻辑上有没有相关性而不是仅仅因为长得像就复用复用的代价就是耦合。 最后 整理了75个JS高频面试题并给出了答案和解析基本上可以保证你能应付面试官关于JS的提问。 有需要的小伙伴可以点击下方卡片领取无偿分享
http://www.dnsts.com.cn/news/205435.html

相关文章:

  • 南京网站制作公司电话中国商标网官方查询系统
  • 青梦建站邢台市天气预报15天
  • 台州市建设规划局网站网站建设考评表
  • 昌做网站北京正规网站建设公司哪家好
  • 有域名和虚拟服务器后怎么做网站淘宝实时优惠券网站怎么做的
  • 做网站的需要注册商标吗wordpress修改字体为微软
  • 站长之家官网查询中国网是什么级别的媒体
  • 企业网站建设培训西安建站推广
  • 兰州商城网站建成都模板网站建设服务
  • 海安县建设局网站wordpress 外链缩略图
  • 拖拽式建站如何开展网上营销
  • 百瑞网站建设知名个人网站
  • 哪里免费做网站网页设计的ppt展示
  • 作品集公司网站临沂网站设计价格
  • 石家庄做网站好的网络技术有限公司公司开发个网站怎么做
  • 侠客推 网站建设秘密入口3秒自动转接连接
  • 房产网站流量排名网站建设心得体会
  • 卖水果做哪个网站好公司网页注册
  • 国家工程建设信息网站汕头模板建站代理
  • 做艺人资料卡的网站权威的大良网站建设
  • 建正建设集团有限公司网站肇庆东莞网站建设
  • 北京市建设工程信息白城seo
  • 做付费软件网站怎么做网页游戏开服表源码
  • 网站的建设与管理自考网站建设管理软件
  • 许昌大成建设集团网站搜索引擎营销的特点包括
  • 网站放到国外空间河南城市建设招标类网站
  • 织梦贷款网站源码网站设计师发展方向
  • 自己做免费手机网站吗wordpress thecontent
  • 学校网站建设全包中南建设的网站
  • 网站开发的销售手机app网站制作