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

群晖怎么做网站网站简繁体转换js

群晖怎么做网站,网站简繁体转换js,微商的自己做网站叫什么,网站建设 网站软文推广测试驱动开发遵守了测试—开发—重构的闭环。测试设定了新功能的需求期望#xff0c;并为功能实现提供了保护#xff1b;开发让实现真正落地#xff0c;满足产品功能的期望#xff1b;重构则是为了打磨代码质量#xff0c;降低软件的维护成本。期望—实现—改进的螺旋上升…测试驱动开发遵守了测试—开发—重构的闭环。测试设定了新功能的需求期望并为功能实现提供了保护开发让实现真正落地满足产品功能的期望重构则是为了打磨代码质量降低软件的维护成本。期望—实现—改进的螺旋上升态势为测试驱动开发闭环提供了源源不断的动力。缺少任何一个环节闭环都会停滞不动。没有期望实现就失去了前进的目标没有实现期望就成为了空谈没有改进前进的道路就会越来越窄突破就会变得愈发地艰难。 重构改进的目标 若已有清晰的用户需求为其设定期望然后寻求实现这并非难事。但是改进的标准却是模糊的。要达到什么样的目标才符合重构的要求Martin Fowler 的回答是让代码消除坏味道他甚至编写了专著《重构改善既有代码的设计》来总结他在多年开发和咨询工作中遇见的所有坏味道如下表所示 坏味道问题重复代码函数包含相同代码两个子类包含相同代码两个不相干类包含相同代码过长函数函数越长越难以理解过大的类一个类要做的事情太多可能导致重复代码过长参数列表参数列表过长会导致难以理解太多参数会造成前后不一致、不易使用会导致频繁修改发散式变化一个类因为不同原因在不同的方向发生变化指“一个类受多种变化的影响”霰弹式修改与发散式修改相反因为一个变化导致多个类都需要作出修改依恋情结函数对某个类的兴趣高过对自己所处类的兴趣数据泥团两个类中相同的字段、许多函数签名中相同的参数。这些总是绑在一起出现的数据应该拥有属于它们自己的对象基本类型偏执基本类型不能很好地表现某个概念Switch 语句Switch 语句的问题在于重复平行继承体系每当你为某个类增加一个子类必须也为另一个类相应增加一个子类冗余类一个类的所得不值其身价就是冗余的应该去掉夸夸其谈未来过度设计过度抽象临时字段某个实例变量仅为某种特定情况而设消息链条如果你看到用户向一个对象请求另一个对象然后再向后者请求另一个对象然后再请求另一个对象这就是消息链条中间人过度运用委托例如某个类接口有一半的函数都委托给其他类狎昵关系两个类过于亲密花费太多时间去探究彼此的 private 成分异曲同工的类如果两个函数做同一件事却有着不同的签名数据类拥有一些字段以及访问这些字段的函数除此之外没有其他方法被拒绝的馈赠子类应该继承超类的函数和数据但如果它们不想或不需要继承意味着继承体系设计错误过多的注释一段代码有着长长的注释但这些注释之所以存在是因为代码很糟糕 数一数Martin Fowler 一共提出了二十一种代码坏味道。要记住所有的坏味道并非易事更何况我们还得保持嗅觉的敏感性一经察觉代码的坏味道就得尽量着手重构。经科学家研究证明人类的短时记忆容量大约为 7±2如果一时无法记住所有的坏味道则可遵循 Kent Beck 的简单设计原则。我在 1-11《领域实现模型》中已经简单地介绍了简单设计原则内容为 通过所有测试Passes its tests尽可能消除重复Minimizes duplication尽可能清晰表达Maximizes clarity更少代码元素Has fewer elements以上四个原则的重要程度依次降低。 最后一个原则说明前面四个原则是依次递进的功能正确减少重复代码可读是简单设计的根本要求。一旦满足这些要求就不能创建更多的代码元素去迎合未来可能并不存在的变化避免过度设计。 简单设计的量化标准 在满足需求的基本前提下简单设计其实为代码的重构给出了三个量化标准重复性、可读性与简单性。重复性是一个客观的标准可读性则出于主观的判断故而应优先考虑尽可能消除代码的重复然后在此基础上保证代码清晰地表达设计者的意图提高可读性。只要达到了重用和可读就应该到此为止不要画蛇添足地增加额外的代码元素如变量、函数、类甚至模块保证实现方案的简单。 第四个原则是“奥卡姆剃刀”的体现更加文雅的翻译表达即“如无必要勿增实体”。人民大学的哲学教授周濂在解释奥卡姆剃刀时如是说道 作为一个极端的唯名论者奥卡姆的威廉William of Occam1280—1349主张个别的事物是真实的存在除此之外没有必要再设立普遍的共相美的东西就是美的不需要再废话多说什么美的东西之所以为美是由于美最后这个美完全可以用奥卡姆的剃刀一割了之。 这个所谓“普遍的共相”就是一种抽象。在软件开发中那些不必要的抽象反而会产生多余的概念实际会干扰代码阅读者的判断增加代码的复杂度。因此简单设计强调恰如其分的设计若实现的功能通过了所有测试就意味着满足了客户的需求这时只需要尽可能消除重复清晰表达了设计者意图就不可再增加额外的软件元素。若存在多余实体当用奥卡姆的剃刀一割了之。 一个实例 让我们通过重构一段 FitNesse 代码来阐释简单设计原则。这段代码案例来自 Robert Martin 的著作《代码整洁之道》。Robert Martin 在书中给出了对源代码的三个重构版本这三个版本的演化恰好可以帮助我们理解简单设计原则。 重构前的代码初始版本是定义在 HtmlUtil 类中的一个长函数 public static String testableHtml(PageData pageData, boolean includeSuiteSetup) throws Exception {WikiPage wikiPage pageData.getWikiPage();StringBuffer buffer new StringBuffer();if (pageData.hasAttribute(Test)) {if (includeSuiteSetup) {WikiPage suiteSetupPage PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_SETUP_NAME, wikiPage);if (suiteSetupPage ! null) {WikiPagePath pagePath wikiPage.getPageCrawler().getFullPath(suiteSetupPage);String pagePathName PathParser.render(pagePath);buffer.append(\n!include -setup .).append(pagePathName).append(\n);}}WikiPage setupPage PageCrawlerImpl.getInheritedPage(SetUp, wikiPage);if (setupPage ! null) {WikiPagePath setupPath wikiPage.getPageCrawler().getFullPath(setupPage);String setupPathName PathParser.render(setupPath);buffer.append(\n!include -setup .).append(setupPathName).append(\n);}}buffer.append(pageData.getContent());if (pageData.hasAttribute(Test)) {WikiPage teardownPage PageCrawlerImpl.getInheritedPage(TearDown, wikiPage);if (teardownPage ! null) {WikiPagePath tearDownPath wikiPage.getPageCrawler().getFullPath(teardownPage);String tearDownPathName PathParser.render(tearDownPath);buffer.append(\n).append(!include -teardown .).append(tearDownPathName).append(\n);}if (includeSuiteSetup) {WikiPage suiteTeardownPage PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_TEARDOWN_NAME, wikiPage);if (suiteTeardownPage ! null) {WikiPagePath pagePath wikiPage.getPageCrawler().getFullPath(suiteTeardownPage);String pagePathName PathParser.render(pagePath);buffer.append(\n!include -teardown .).append(pagePathName).append(\n);}}}pageData.setContent(buffer.toString());return pageData.getHtml();} 假定这一个函数已经通过了测试按照简单设计的评判步骤我们需要检查代码是否存在重复。显然在上述代码的 6~13 行、15~22 行、26~34 行以及 36~43 行四个地方都发现了重复或相似的代码。这些代码的执行步骤像一套模板 获取 Page若 Page 不为 null则获取路径解析路径名称添加到输出结果中 这套模板的差异部分可以通过参数差异化完成故而可以提取方法 private static void includePage(WikiPage wikiPage, StringBuffer buffer, String pageName, String sectionName) {WikiPage suiteSetupPage PageCrawlerImpl.getInheritedPage(pageName, wikiPage);if (suiteSetupPage ! null) {WikiPagePath pagePath wikiPage.getPageCrawler().getFullPath(suiteSetupPage);String pagePathName PathParser.render(pagePath);buildIncludeDirective(buffer, sectionName, pagePathName);}}private static void buildIncludeDirective(StringBuffer buffer, String sectionName, String pagePathName) {buffer.append(\n!include ).append(sectionName).append( .).append(pagePathName).append(\n);} 在提取了 includePage() 方法后就可以消除四段几乎完全相似的重复代码。重构后的长函数为 public static String testableHtml(PageData pageData, boolean includeSuiteSetup) throws Exception {WikiPage wikiPage pageData.getWikiPage();StringBuffer buffer new StringBuffer();if (pageData.hasAttribute(Test)) {if (includeSuiteSetup) {includePage(wikiPage, buffer, SuiteResponder.SUITE_SETUP_NAME, -setup);}includePage(wikiPage, buffer, SetUp, -setup);}buffer.append(pageData.getContent());if (pageData.hasAttribute(Test)) {includePage(wikiPage, buffer, TearDown, -teardown);if (includeSuiteSetup) {includePage(wikiPage, buffer, SuiteResponder.SUITE_TEARDOWN_NAME, -teardown);}}pageData.setContent(buffer.toString());return pageData.getHtml();} 从重复性角度看以上代码已经去掉了重复。当然也可以将 pageData.hasAttribute(“Test”) 视为重复因为该表达式在第 5 行和第 12 行都出现过表达式用到的常量 “Test” 也是重复。不过你若认为这是从代码可读性角度对其重构也未尝不可 private static boolean isTestPage(PageData pageData) {return pageData.hasAttribute(Test);} 重构后的 testableHtml() 方法的可读性仍有不足之处例如方法的名称buffer 变量名都没有清晰表达设计意图对 Test 和 Suite 的判断增加了条件分支给代码阅读制造了障碍。由于 includePage() 方法是一个通用方法未能清晰表达其意图且传递的参数同样干扰了阅读应该将各个调用分别封装为表达业务含义的方法例如定义为 includeSetupPage()。当页面并非测试页面时 pageData 的内容无需重新设置可以直接通过 getHtml() 方法返回。因此添加页面内容的第 11 行代码还可以放到 isTestPage() 分支中让逻辑变得更加紧凑 public static String renderPage(PageData pageData, boolean includeSuiteSetup) throws Exception {if (isTestPage(pageData)) {WikiPage testPage pageData.getWikiPage();StringBuffer newPageContent new StringBuffer();includeSuiteSetupPage(testPage, newPageContent, includeSuiteSetup);includeSetupPage(testPage, newPageContent);includePageContent(testPage, newPageContent);includeTeardownPage(testPage, newPageContent);includeSuiteTeardownPage(testPage, newPageContent, includeSuiteSetup);pageData.setContent(buffer.toString());} return pageData.getHtml();} 无论是避免重复还是清晰表达意图这个版本的代码都要远胜于最初的版本。Robert Martin 在《代码整洁之道》中也给出了他重构的第一个版本 public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {boolean isTestPage pageData.hasAttribute(Test);if (isTestPage) {WikiPage testPage pageData.getWikiPage();StringBuffer newPageContent new StringBuffer();includeSetupPages(testPage, newPageContent, isSuite);newPageContent.append(pageData.getContent());includeTeardownPages(testPage, newPageContent, isSuite);pageData.setContent(newPageContent.toString());}return pageData.getHtml();} 对比我的版本和 Robert Martin 的版本我认为 Robert Martin 的当前版本仍有以下不足之处 方法名称过长暴露了实现细节isTestPage 变量不如 isTestPage() 方法的封装性好方法体缺少分段不同的意图混淆在了一起 最关键的不足之处在于第 7 行代码。对比第 7 行和第 6、8 两行代码虽然都是一行代码但其表达的意图却有风马牛不相及的违和感。这是因为第 7 行代码实际暴露了将页面内容追加到 newPageContent 的实现细节第 6 行和第 8 行代码却隐藏了这一实现细节。这三行代码没有处于同一个抽象层次违背了“单一抽象层次原则SLAP”。 Robert Martin 在这个版本基础上继续精进给出了重构后的第二个版本 public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {if (isTestPage(pageData))includeSetupAndTeardownPages(pageData, isSuite);return pageData.getHtml();} 该版本的方法仍然定义在 HtmlUtil 工具类中。对比 Robert Martin 的两个重构版本后一版本的主方法变得更加简单了方法体只有短短的三行代码。虽然方法变得更简短但提取出来的 includeSetupAndTeardownPages() 方法却增加了不必要的抽象层次。封装需要有度引入太多的层次反而会干扰阅读。尤其是方法Java 或大多数语言都不提供“方法嵌套方法”的层次结构Scala 支持这一语法特性。如果为一个方法的不同业务层次提取了太多方法在逻辑上它存在递进的嵌套关系在物理上却是一个扁平的结构。阅读这样的代码会造成不停的跳转不够直接。正如 Grady Booch 所述“整洁的代码从不隐藏设计者的意图充满了干净利落的抽象和直截了当的控制语句。”干净利落直截了当可以破除对过度细粒度方法的迷信与其封装一个用超长名称才能表达其意图的 includeSetupAndTeardownPages() 方法不如直接“敞开”相同层次的代码细节如 includeSuiteSetupPage(testPage, newPageContent, includeSuiteSetup); includeSetupPage(testPage, newPageContent); includePageContent(testPage, newPageContent); includeTeardownPage(testPage, newPageContent); includeSuiteTeardownPage(testPage, newPageContent, includeSuiteSetup); 这五行代码不正是直截了当地表达了包含的页面结构吗因此我觉得 Robert Martin 提取出来的 includeSetupAndTeardownPages() 方法违背了简单设计的第四条原则即增加了不必要的软件元素。事实上如果一个方法的名称包含了 and就说明该方法可能违背了“一个方法只做一件事情”的基本原则。 我并不反对定义细粒度方法相反我很欣赏合理的细粒度方法如前提取的 includePageContent() 方法。一个庞大的方法往往缺少内聚性不利于重用但什么才是方法的合适粒度呢不同的公司有着不同的方法行限制有的是 200 行有的是 50 行有的甚至约束到 5 行。最关键的不是限制代码行而在于一个方法只能做一件事。 若发现一个主方法过长可通过提取方法使它变短。当提取方法的逻辑层次嵌套太多彼此的职责又高内聚时就需要考虑将这个主方法和提取出来的方法一起委派到一个专门的类。显然testableHtml() 方法的逻辑其实是一个相对独立的职责根本就不应该将其实现逻辑放在 HtmlUtil 工具类而应按照其意图独立为一个类 TestPageIncluder。提取为类还有一个好处就是可以减少方法之间传递的参数因为这些方法参数可以作为单独类的字段。重构后的代码为 public class TestPageIncluder {private PageData pageData;private WikiPage testPage;private StringBuffer newPageContent;private PageCrawler pageCrawler;private TestPageIncluder(PageData pageData) {this.pageData pageData;testPage pageData.getWikiPage();pageCrawler testPage.getPageCrawler();newPageContent new StringBuffer();}public static String render(PageData pageData) throws Exception {return render(pageData, false);}public static String render(PageData pageData, boolean isSuite) throws Exception {return new TestPageIncluder(pageData).renderPage(isSuite);}private String renderPage(boolean isSuite) throws Exception {if (isTestPage()) {includeSetupPages(isSuite);includePageContent();includeTeardownPages(isSuite);updatePageContent(); }return pageData.getHtml();}private void includeSetupPages(boolean isSuite) throws Exception {if (isSuite) {includeSuitesSetupPage();}includeSetupPage();}private void includeSuitesSetupPage() throws Exception {includePage(SuiteResponder.SUITE_SETUP_NAME, -setup);}private void includeSetupPage() throws Exception {includePage(SetUp, -setup);}private void includeTeardownPages(boolean isSuite) throws Exception {if (isSuite) {includeSuitesTeardownPage();}includeTeardownPage();}private void includeSuitesTeardownPage() throws Exception {includePage(SuiteResponder.SUITE_TEARDOWN_NAME, -teardown);}private void includeTeardownPage() throws Exception {includePage(TearDown, -teardown);}private void updateContent() throws Exception {pageData.setContent(newPageContent.toString());}private void includePage(String pageName, String sectionName) throws Exception {WikiPage inheritedPage PageCrawlerImpl.getInheritedPage(pageName, wikiPage);if (inheritedPage ! null) {WikiPagePath pagePath wikiPage.getPageCrawler().getFullPath(inheritedPage);String pathName PathParser.render(pagePath);buildIncludeDirective(pathName, sectionName);}}private void buildIncludeDirective(String pathName, String sectionName) {buffer.append(\n!include ).append(sectionName).append( .).append(pathName).append(\n);} } 引入 TestPageIncluder 类后职责的层次更加清晰了分离出来的这个类承担了组装测试页面信息的职责HtmlUtil 类只需要调用它的静态方法 render() 即可避免了因承担太多职责而形成一个上帝类。通过提取出类和对应的方法形成不同的抽象层次让代码的阅读者有选择地阅读自己关心的部分这就是清晰表达设计者意图的价值。 对比 Robert Martin 给出的重构第二个版本以及这个提取类的最终版本我赞成将该主方法的逻辑提取给专门的类但不赞成在主方法中定义过度抽象层次的 includeSetupAndTeardownPages() 方法。二者同样都增加了软件元素我对此持有的观点却截然不同。我也曾就 Robert Martin 给出的两个版本做过调查发现仍然有一部分人偏爱第二个更加简洁的版本。这一现象恰好说明简单设计的第三条原则属于主观判断不如第二条原则那般具有客观的评判标准恰如大家对美各有自己的欣赏。但我认为一定不会有人觉得重构前的版本才是最好。即使不存在重复代码单从可读性角度判断也会觉得最初版本的代码不堪入目恰如大家对美的评判标准仍具有一定的普适性。 Robert Martin 在《代码整洁之道》中也给出了分离职责的类 SetupTeardownIncluder。两个类的实现相差不大只是 TestPageIncluder 类要少一些方法。除了没有 includeSetupAndTeardownPages() 方法外我也未曾定义 findInheritedPage() 和 getPathNameForPage() 之类的方法也没有提取 isSuite 字段因为我认为这些都是不必要的软件元素它违背了简单设计的第四条原则应当用奥卡姆的剃刀一割了之。
http://www.pierceye.com/news/842193/

相关文章:

  • 网站建设介绍会发言稿网站开发主页
  • 做推广赚钱的网站如何制作网站策划书
  • 微信公众号商城网站开发能不能不用虚拟主机建设网站
  • iis 网站目录权限vps网站无法通过ip访问
  • 重庆关键词优化咸阳seo培训
  • 专业网站建设分类标准嘉兴网络项目建站公司
  • 做婚礼网站的公司简介网页打不开怎么办页面无法显示
  • 怎么套用模板做网站白嫖二级域名
  • 网站如何进行备案建立平台的步骤
  • 济南免费网站建设网站用什么软件编写
  • 网站如何注册微信公众平台 类型站长要维护网站
  • 美食类网站模板有的网站为什么打不开怎么回事
  • 平面设计网站导航1万元可以注册公司吗
  • 做网站接口多少钱怎样做旅游网站
  • dw制作旅游网站教程天津市区县档案部门网站建设指导意见
  • 关于网站建设的大学pinthis wordpress
  • 济宁 做网站企业做外贸网站常用术语
  • 国内优秀的设计网站推荐网页设计工作室赚钱吗
  • 商汇通网站广州白云学校网站建设
  • 茶叶企业建设网站php网站开发基础
  • 深圳网站建设 猴王网络地方信息网站源码
  • 微网站后台内容设置erp系统定制
  • 图片点击切换网站模板网站开发 北京外包公司
  • 网站正在建设中 免费东莞手机网站设计公司
  • 旅游网站开发成本包括企业管理控制系统
  • 青浦做网站中美最新局势分析
  • 高端网站建设公司哪家公司好有关网站开发的知识
  • 西宁做网站_君博示范cpa做电影网站侵权吗
  • 云梦网站开发什么是网络营销市场营销学
  • 六安建六安建设网站徐州招标信息网