
一、好代码的定义
关于好代码的定义,各路大神都给出了自己的定义和见解
整洁的代码如同优美的散文。—— Grady Booch
首先要达成一致,我们写的代码,除了用于机器执行产生我们预期的效果之外,更多的时候是给人读的,可能是后续的维护人员,更多时候是一段时间后的作者本人,因此优雅面向不同的用户有两层含义的解读。
1.对人而言,代码的整洁,清晰的逻辑;
2.对机器而言,准确性、执行性能、异常处理机制等;
1. 有意义的命名
public List<int[]> getItem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x: theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
整体逻辑没啥问题,读完之后,就有很多问题在脑海中产生
1. theList中是存储什么东西的数组?
2. theList第一个值是做什么的?
3. 值4的意义又是什么?
4. 返回的列表该怎么使用?
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
2. 优雅的注释
1. 一些被注释掉的代码
//something code
//something code
2. 位置标记
//begin
someting code;
//end
3. 签名标记
/** add by xiaoli*/
4. 非公用方法的javadoc
/**
* doSomething
*/
private void doSomething(){
}
5. 日志式注释
/** add xx
* update sometimes
* update sometimes
* update sometimes
*/
6. 误导性注释
//此处怎样xx
3. 优雅的函数
public String renderPageWithSetupAndTeardowns(Page page, boolean isSuite) throws Exception{
if(isTestPage(page)){
includeSetupAndTeardownPages(page,isSuite);
}
return page.getHtml();
}
//把大象装进冰箱
public void frozenElephant(){
//1. 捕捉大象
//2. 运输大象
//3. 打开冰箱
//4. 放入大象
//5. 关闭冰箱
}
public void frozenElephant(){
//1. 捕捉大象
catchElephant();
//2. 运输大象
transportElephant();
//将大象放入冰箱
putElephantInRefrigerator();
}
public void catchElephant(){
}
public void transportElephant(){
}
public void putElephantInRefrigerator(){
//打开冰箱
//放入大象
//关闭冰箱
}
if(deletePage() == OK){
if(registry.deleteReference(page.name) == OK){
if(configKeys.deleteKey(page.name.makeKey) == OK){
logger.log("page deleted")
}else{
logger.log("configKey not deleted")
}
}else{
logger.log("deleteReference from registry failed")
}
}else{
logger.log("delete failed")
return Error;
}
try{
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey);
}catch(Exception e){
logger.log(e.getMessage());
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
三、代码重构
1. 识别代码的坏味道
1.最单纯的重复代码就是“同一个类的两个函数含有相同的表达式”。这时候需要做的就是采用提炼函数提炼出重复的代码,然后让这两个地点都调用被提炼出来的那一段代码
2.如果重复代码只是相似而不是完全相同,需要先尝试用移动语句重组代码顺序,把相似的部分放在一起以便提炼。
遵循这样一条原则:每当感觉需要以注释来说明点什么的时候,就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名,可以对一组甚至短短一行代码做这件事。哪怕替换后的函数调用动作比函数自身还长,只要函数名称能够解释其用途,就要毫不犹豫地那样做,关键不在于函数的长度,而在于函数“做什么”和“如何做”之间的语义距离。
1.百分之九十九的场合里,要把函数变短,只需使用提炼函数。找到函数中适合集中在一起的部分,将它们提炼出来形成一个新函数。
2.如果函数内有大量的参数和临时变量,最终就会把许多参数传递给被提炼出来的新函数,导致可读性几乎没有任何提升。此时可以经常运用以查询取代临时变量来消除这些临时元素。引入参数对象和保持对象完整则可以将过长的参数列表变得更简洁一些。
对数据的修改经常导致出乎意料的结果和难以发现的bug。在一处更新数据,却没有意识到软件中的另一处期望着完全不同的数据,于是出现难以预料的bug,往往比较难排查(需要排查数据流转的整体链路),这就需要一些方法用于约束对数据的更新,降低数据可变性的风险。
1.可以用封装变量来确保所有数据更新操作都通过很少几个函数来进行,使其更容易统一监控和演进
2.如果一个变量在不同时候被用于存储不同的东西, 可以使用拆分变量将其拆分为各自不同用途的变量,从而避免危险的更新操作。
所谓模块化,就是力求将代码分出区域,最大化区域内部的交互、最小化跨区域的交互。但是经常出现一个函数跟另一个模块中的函数或者数据交流格外频繁,远胜于与所处模块内部的交流,这就是模块功能不单一的典型情况。
1.总看到某个函数为了计算某个值,从另一个对象那儿调用半打的取值函数。如果这个函数需要跟这些数据待在一起,那就使用移动功能把它移过去。
2.一个函数往往会用到几个模块的功能,那么它究竟该被置于何处呢?原则是:判断哪个模块拥有的此函数使用的数据最多,然后就把这个函数和那些数据摆在一起。 如果先以提炼函数将这个函数分解为数个较小的函数并分别置放于不同类中,上面的步骤就会比较容易完成。
2. 函数重构的方法
四、小结
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/