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

杭州 seo网站建设 网络服务wordpress 不显示时间

杭州 seo网站建设 网络服务,wordpress 不显示时间,天津网站制作培训,拖曳式网站建设在上一节课中#xff0c;我们讲了 KISS 原则和 YAGNI 原则#xff0c;KISS 原则可以说是人尽皆知。今天#xff0c;我们再学习一个你肯定听过的原则#xff0c;那就是 DRY 原则。它的英文描述为#xff1a;Don’t Repeat Yourself。中文直译为#xff1a;不要重复自己。将…在上一节课中我们讲了 KISS 原则和 YAGNI 原则KISS 原则可以说是人尽皆知。今天我们再学习一个你肯定听过的原则那就是 DRY 原则。它的英文描述为Don’t Repeat Yourself。中文直译为不要重复自己。将它应用在编程中可以理解为不要写重复的代码。 你可能会觉得这条原则非常简单、非常容易应用。只要两段代码长得一样那就是违反 DRY 原则了。真的是这样吗答案是否定的。这是很多人对这条原则存在的误解。实际上重复的代码不一定违反 DRY 原则而且有些看似不重复的代码也有可能违反 DRY 原则。 听到这里你可能会有很多疑问。没关系今天我会结合具体的代码实例来把这个问题讲清楚纠正你对这个原则的错误认知。除此之外DRY 原则与代码的复用性也有一些联系所以今天我还会讲一讲如何写出可复用性好的代码。 话不多说让我们正式开始今天的学习吧 DRY 原则Don’t Repeat Yourself DRY 原则的定义非常简单我就不再过度解读。今天我们主要讲三种典型的代码重复情况它们分别是实现逻辑重复、功能语义重复和代码执行重复。这三种代码重复有的看似违反 DRY实际上并不违反有的看似不违反实际上却违反了。 实现逻辑重复 我们先来看下面这样一段代码是否违反了 DRY 原则。如果违反了你觉得应该如何重构才能让它满足 DRY 原则如果没有违反那又是为什么呢 public class UserAuthenticator {public void authenticate(String username, String password) {if (!isValidUsername(username)) {// ...throw InvalidUsernameException...}if (!isValidPassword(password)) {// ...throw InvalidPasswordException...}//... 省略其他代码...}private boolean isValidUsername(String username) {// check not null, not emptyif (StringUtils.isBlank(username)) {return false;}// check length: 4~64int length username.length();if (length 4 || length 64) {return false;}// contains only lowcase charactersif (!StringUtils.isAllLowerCase(username)) {return false;}// contains only a~z,0~9,dotfor (int i 0; i length; i) {char c username.charAt(i);if (!(c a c z) || (c 0 c 9) || c .) {return false;}}return true;}private boolean isValidPassword(String password) {// check not null, not emptyif (StringUtils.isBlank(password)) {return false;}// check length: 4~64int length password.length();if (length 4 || length 64) {return false;}// contains only lowcase charactersif (!StringUtils.isAllLowerCase(password)) {return false;}// contains only a~z,0~9,dotfor (int i 0; i length; i) {char c password.charAt(i);if (!(c a c z) || (c 0 c 9) || c .) {return false;}}return true;} }代码很简单我就不做过多解释了。在代码中有两处非常明显的重复的代码片段isValidUserName() 函数和 isValidPassword() 函数。重复的代码被敲了两遍或者简单 copy-paste 了一下看起来明显违反 DRY 原则。为了移除重复的代码我们对上面的代码做下重构将 isValidUserName() 函数和 isValidPassword() 函数合并为一个更通用的函数 isValidUserNameOrPassword()。重构后的代码如下所示 public class UserAuthenticatorV2 {public void authenticate(String userName, String password) {if (!isValidUsernameOrPassword(userName)) {// ...throw InvalidUsernameException...}if (!isValidUsernameOrPassword(password)) {// ...throw InvalidPasswordException...}}private boolean isValidUsernameOrPassword(String usernameOrPassword) {// 省略实现逻辑// 跟原来的 isValidUsername() 或 isValidPassword() 的实现逻辑一样...return true;} }经过重构之后代码行数减少了也没有重复的代码了是不是更好了呢答案是否定的这可能跟你预期的不一样我来解释一下为什么。 单从名字上看我们就能发现合并之后的 isValidUserNameOrPassword() 函数负责两件事情验证用户名和验证密码违反了“单一职责原则”和“接口隔离原则”。实际上即便将两个函数合并成 isValidUserNameOrPassword()代码仍然存在问题。 因为 isValidUserName() 和 isValidPassword() 两个函数虽然从代码实现逻辑上看起来是重复的但是从语义上并不重复。所谓“语义不重复”指的是从功能上来看这两个函数干的是完全不重复的两件事情一个是校验用户名另一个是校验密码。尽管在目前的设计中两个校验逻辑是完全一样的但如果按照第二种写法将两个函数的合并那就会存在潜在的问题。在未来的某一天如果我们修改了密码的校验逻辑比如允许密码包含大写字符允许密码的长度为 8 到 64 个字符那这个时候isValidUserName() 和 isValidPassword() 的实现逻辑就会不相同。我们就要把合并后的函数重新拆成合并前的那两个函数。 尽管代码的实现逻辑是相同的但语义不同我们判定它并不违反 DRY 原则。对于包含重复代码的问题我们可以通过抽象成更细粒度函数的方式来解决。比如将校验只包含 az、09、dot 的逻辑封装成 boolean onlyContains(String str, String charlist); 函数。 功能语义重复 现在我们再来看另外一个例子。在同一个项目代码中有下面两个函数isValidIp() 和 checkIfIpValid()。尽管两个函数的命名不同实现逻辑不同但功能是相同的都是用来判定 IP 地址是否合法的。 之所以在同一个项目中会有两个功能相同的函数那是因为这两个函数是由两个不同的同事开发的其中一个同事在不知道已经有了 isValidIp() 的情况下自己又定义并实现了同样用来校验 IP 地址是否合法的 checkIfIpValid() 函数。 那在同一项目代码中存在如下两个函数是否违反 DRY 原则呢 public boolean isValidIp(String ipAddress) {if (StringUtils.isBlank(ipAddress)) return false;String regex ^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\. (1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\. (1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\. (1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$;return ipAddress.matches(regex); } public boolean checkIfIpValid(String ipAddress) {if (StringUtils.isBlank(ipAddress)) return false;String[] ipUnits StringUtils.split(ipAddress, .);if (ipUnits.length ! 4) {return false;}for (int i 0; i 4; i) {int ipUnitIntValue;try {ipUnitIntValue Integer.parseInt(ipUnits[i]);} catch (NumberFormatException e) {return false;}if (ipUnitIntValue 0 || ipUnitIntValue 255) {return false;}if (i 0 ipUnitIntValue 0) {return false;}}return true; }这个例子跟上个例子正好相反。上一个例子是代码实现逻辑重复但语义不重复我们并不认为它违反了 DRY 原则。而在这个例子中尽管两段代码的实现逻辑不重复但语义重复也就是功能重复我们认为它违反了 DRY 原则。我们应该在项目中统一一种实现思路所有用到判断 IP 地址是否合法的地方都统一调用同一个函数。 假设我们不统一实现思路那有些地方调用了 isValidIp() 函数有些地方又调用了 checkIfIpValid() 函数这就会导致代码看起来很奇怪相当于给代码“埋坑”给不熟悉这部分代码的同事增加了阅读的难度。同事有可能研究了半天觉得功能是一样的但又有点疑惑觉得是不是有更高深的考量才定义了两个功能类似的函数最终发现居然是代码设计的问题。 除此之外如果哪天项目中 IP 地址是否合法的判定规则改变了比如255.255.255.255 不再被判定为合法的了相应地我们对 isValidIp() 的实现逻辑做了相应的修改但却忘记了修改 checkIfIpValid() 函数。又或者我们压根就不知道还存在一个功能相同的 checkIfIpValid() 函数这样就会导致有些代码仍然使用老的 IP 地址判断逻辑导致出现一些莫名其妙的 bug。 代码执行重复 前两个例子一个是实现逻辑重复一个是语义重复我们再来看第三个例子。其中UserService 中 login() 函数用来校验用户登录是否成功。如果失败就返回异常如果成功就返回用户信息。具体代码如下所示 public class UserService {private UserRepo userRepo;// 通过依赖注入或者 IOC 框架注入public User login(String email, String password) {boolean existed userRepo.checkIfUserExisted(email, password);if (!existed) {// ... throw AuthenticationFailureException...}User user userRepo.getUserByEmail(email);return user;} } public class UserRepo {public boolean checkIfUserExisted(String email, String password) {if (!EmailValidation.validate(email)) {// ... throw InvalidEmailException...}if (!PasswordValidation.validate(password)) {// ... throw InvalidPasswordException...}//...query db to check if emailpassword exists...}public User getUserByEmail(String email) {if (!EmailValidation.validate(email)) {// ... throw InvalidEmailException...}//...query db to get user by email...} }上面这段代码既没有逻辑重复也没有语义重复但仍然违反了 DRY 原则。这是因为代码中存在“执行重复”。我们一块儿来看下到底哪些代码被重复执行了 重复执行最明显的一个地方就是在 login() 函数中email 的校验逻辑被执行了两次。一次是在调用 checkIfUserExisted() 函数的时候另一次是调用 getUserByEmail() 函数的时候。这个问题解决起来比较简单我们只需要将校验逻辑从 UserRepo 中移除统一放到 UserService 中就可以了。 除此之外代码中还有一处比较隐蔽的执行重复不知道你发现了没有实际上login() 函数并不需要调用 checkIfUserExisted() 函数只需要调用一次 getUserByEmail() 函数从数据库中获取到用户的 email、password 等信息然后跟用户输入的 email、password 信息做对比依次判断是否登录成功。 实际上这样的优化是很有必要的。因为 checkIfUserExisted() 函数和 getUserByEmail() 函数都需要查询数据库而数据库这类的 I/O 操作是比较耗时的。我们在写代码的时候应当尽量减少这类 I/O 操作。 按照刚刚的修改思路我们把代码重构一下移除“重复执行”的代码只校验一次 email 和 password并且只查询一次数据库。重构之后的代码如下所示 public class UserService {private UserRepo userRepo;// 通过依赖注入或者 IOC 框架注入public User login(String email, String password) {if (!EmailValidation.validate(email)) {// ... throw InvalidEmailException...}if (!PasswordValidation.validate(password)) {// ... throw InvalidPasswordException...}User user userRepo.getUserByEmail(email);if (user null || !password.equals(user.getPassword()) {// ... throw AuthenticationFailureException...}return user;} } public class UserRepo {public boolean checkIfUserExisted(String email, String password) {//...query db to check if emailpassword exists}public User getUserByEmail(String email) {//...query db to get user by email...} }代码复用性Code Reusability 在专栏的最开始我们有提到代码的复用性是评判代码质量的一个非常重要的标准。当时只是点到为止没有展开讲解今天我再带你深入地学习一下这个知识点。 什么是代码的复用性 我们首先来区分三个概念代码复用性Code Reusability、代码复用Code Resue和 DRY 原则。 代码复用表示一种行为我们在开发新功能的时候尽量复用已经存在的代码。代码的可复用性表示一段代码可被复用的特性或能力我们在编写代码的时候让代码尽量可复用。DRY 原则是一条原则不要写重复的代码。从定义描述上它们好像有点类似但深究起来三者的区别还是蛮大的。 首先“不重复”并不代表“可复用”。在一个项目代码中可能不存在任何重复的代码但也并不表示里面有可复用的代码不重复和可复用完全是两个概念。所以从这个角度来说DRY 原则跟代码的可复用性讲的是两回事。 其次“复用”和“可复用性”关注角度不同。代码“可复用性”是从代码开发者的角度来讲的“复用”是从代码使用者的角度来讲的。比如A 同事编写了一个 UrlUtils 类代码的“可复用性”很好。B 同事在开发新功能的时候直接“复用”A 同事编写的 UrlUtils 类。 尽管复用、可复用性、DRY 原则这三者从理解上有所区别但实际上要达到的目的都是类似的都是为了减少代码量提高代码的可读性、可维护性。除此之外复用已经经过测试的老代码bug 会比从零重新开发要少。 “复用”这个概念不仅可以指导细粒度的模块、类、函数的设计开发实际上一些框架、类库、组件等的产生也都是为了达到复用的目的。比如Spring 框架、Google Guava 类库、UI 组件等等。 怎么提高代码复用性 实际上我们前面已经讲到过很多提高代码可复用性的手段今天算是集中总结一下我总结了 7 条具体如下。 减少代码耦合 对于高度耦合的代码当我们希望复用其中的一个功能想把这个功能的代码抽取出来成为一个独立的模块、类或者函数的时候往往会发现牵一发而动全身。移动一点代码就要牵连到很多其他相关的代码。所以高度耦合的代码会影响到代码的复用性我们要尽量减少代码耦合。 满足单一职责原则 我们前面讲过如果职责不够单一模块、类设计得大而全那依赖它的代码或者它依赖的代码就会比较多进而增加了代码的耦合。根据上一点也就会影响到代码的复用性。相反越细粒度的代码代码的通用性会越好越容易被复用。 模块化 这里的“模块”不单单指一组类构成的模块还可以理解为单个类、函数。我们要善于将功能独立的代码封装成模块。独立的模块就像一块一块的积木更加容易复用可以直接拿来搭建更加复杂的系统。 业务与非业务逻辑分离 越是跟业务无关的代码越是容易复用越是针对特定业务的代码越难复用。所以为了复用跟业务无关的代码我们将业务和非业务逻辑代码分离抽取成一些通用的框架、类库、组件等。 通用代码下沉 从分层的角度来看越底层的代码越通用、会被越多的模块调用越应该设计得足够可复用。一般情况下在代码分层之后为了避免交叉调用导致调用关系混乱我们只允许上层代码调用下层代码及同层代码之间的调用杜绝下层代码调用上层代码。所以通用的代码我们尽量下沉到更下层。 继承、多态、抽象、封装 在讲面向对象特性的时候我们讲到利用继承可以将公共的代码抽取到父类子类复用父类的属性和方法。利用多态我们可以动态地替换一段代码的部分逻辑让这段代码可复用。除此之外抽象和封装从更加广义的层面、而非狭义的面向对象特性的层面来理解的话越抽象、越不依赖具体的实现越容易复用。代码封装成模块隐藏可变的细节、暴露不变的接口就越容易复用。 应用模板等设计模式 一些设计模式也能提高代码的复用性。比如模板模式利用了多态来实现可以灵活地替换其中的部分代码整个流程模板代码可复用。关于应用设计模式提高代码复用性这一部分我们留在后面慢慢来讲解。 除了刚刚我们讲到的几点还有一些跟编程语言相关的特性也能提高代码的复用性比如泛型编程等。实际上除了上面讲到的这些方法之外复用意识也非常重要。在写代码的时候我们要多去思考一下这个部分代码是否可以抽取出来作为一个独立的模块、类或者函数供多处使用。在设计每个模块、类、函数的时候要像设计一个外部 API 那样去思考它的复用性。 辩证思考和灵活应用 实际上编写可复用的代码并不简单。如果我们在编写代码的时候已经有复用的需求场景那根据复用的需求去开发可复用的代码可能还不算难。但是如果当下并没有复用的需求我们只是希望现在编写的代码具有可复用的特点能在未来某个同事开发某个新功能的时候复用得上。在这种没有具体复用需求的情况下我们就需要去预测将来代码会如何复用这就比较有挑战了。 实际上除非有非常明确的复用需求否则为了暂时用不到的复用需求花费太多的时间、精力投入太多的开发成本并不是一个值得推荐的做法。这也违反我们之前讲到的 YAGNI 原则。 除此之外有一个著名的原则叫作“Rule of Three”。这条原则可以用在很多行业和场景中你可以自己去研究一下。如果把这个原则用在这里那就是说我们在第一次写代码的时候如果当下没有复用的需求而未来的复用需求也不是特别明确并且开发可复用代码的成本比较高那我们就不需要考虑代码的复用性。在之后我们开发新的功能的时候发现可以复用之前写的这段代码那我们就重构这段代码让其变得更加可复用。 也就是说第一次编写代码的时候我们不考虑复用性第二次遇到复用场景的时候再进行重构使其复用。需要注意的是“Rule of Three”中的“Three”并不是真的就指确切的“三”这里就是指“二”。 重点回顾 今天的内容到此就讲完了。我们一块来回顾一下你需要重点掌握的内容。 1.DRY 原则 我们今天讲了三种代码重复的情况实现逻辑重复、功能语义重复、代码执行重复。实现逻辑重复但功能语义不重复的代码并不违反 DRY 原则。实现逻辑不重复但功能语义重复的代码也算是违反 DRY 原则。除此之外代码执行重复也算是违反 DRY 原则。 2. 代码复用性 今天我们讲到提高代码可复用性的一些方法有以下 7 点。 减少代码耦合满足单一职责原则模块化业务与非业务逻辑分离通用代码下沉继承、多态、抽象、封装应用模板等设计模式 实际上除了上面讲到的这些方法之外复用意识也非常重要。在设计每个模块、类、函数的时候要像设计一个外部 API 一样去思考它的复用性。 我们在第一次写代码的时候如果当下没有复用的需求而未来的复用需求也不是特别明确并且开发可复用代码的成本比较高那我们就不需要考虑代码的复用性。在之后开发新的功能的时候发现可以复用之前写的这段代码那我们就重构这段代码让其变得更加可复用。 相比于代码的可复用性DRY 原则适用性更强一些。我们可以不写可复用的代码但一定不能写重复的代码。 课堂讨论 除了实现逻辑重复、功能语义重复、代码执行重复你还知道有哪些其他类型的代码重复这些代码重复是否违反 DRY 原则 欢迎在留言区写下你的想法和同学一起交流和分享。如果有收获也欢迎你把这篇文章分享给你的朋友。
http://www.tj-hxxt.cn/news/136866.html

相关文章:

  • 下载网站的服务器文件菏泽建设信息网官网
  • 做电商网站的设计思路有什么意思哪个网站可以做加工代理的
  • 网站底部样式网站中英文切换怎麼做
  • 怎么自己在百度上做网站广州手机软件开发定制
  • 四川seo整站优化费用阿里巴巴国际站怎么注册
  • 西安微信商城网站设计企业网站建设预算
  • 网站被k查询网站开发顶岗报告
  • 广州网站建设广州网络推广公司排名广州seo推广服务
  • 做洗化的网站做网站都用到哪些软件
  • 百度新网站收录大连网站外包
  • 自己电脑做电影网站seo网站优化公司
  • 精品课程网站建设总结报告长春网站建设致电吉网传媒优
  • wordpress原创保护seo优化推广技巧
  • 网站推广有哪些方法编程app下载
  • 网站开发文章在深圳找工作哪个网站好
  • 创建自己的免费网站p2vr做的网站上传
  • 档案网站建设经验软装设计收费标准
  • 乐清定制网站建设域名注册了 如何做网站
  • 做网站互联网公司商丘云网广告有限公司
  • 做商城网站服务器配置怎么选择中国营销网官网
  • 中小型网站建设价位网站建设 软件有哪些方面
  • 免费网站建设模板下载如何制作网络投票的网页
  • 文山专业网站建设哪家好镇江市住房与城乡建设部网站
  • 网站前端切图做多个页面在东莞怎么找工作
  • 怎么做万网网站吗微信小程序api是什么
  • 天猫秘券网站怎么做做百度移动端网站软件
  • 诸暨网站建设公司wordpress解决速度慢
  • 网站开发类论文题目微商城首页
  • 企业网站建设市场分析网站开发公司模板
  • 做网站页面的框架网站是怎么优化的