精华内容
下载资源
问答
  • Java Lombok 减少代码冗余 利刃

    万次阅读 2015-07-22 21:06:18
    无论使用的是哪种流行的框架,在其中都少不了Model类的编写,还有其中错综负责的getter/setter方法,这些getter/setter方法的存在,使得代码变得非常的臃肿。那么需要怎 么解决这个问题呢,便引入了这篇文章的主角L

    前言:

    现在是ORM框架大行其道的时代,有着如Hibernate这样重量级的框架,提供Java<->数据的双向映射,也有如Mybatis这样的轻量级框架,提供Java<-数据的单方向映射,

    无论使用的是哪种流行的框架,在其中都少不了Model类的编写,还有其中错综负责的getter/setter方法,这些getter/setter方法的存在,使得代码变得非常的臃肿。那么需要怎

    么解决这个问题呢,便引入了这篇文章的主角Lombok。

    1.下载:

    Lombok的官网地址是:http://projectlombok.org/ 

    2.使用:

    Lombok是一种JavaArchive(jar)文件,旨在为了减少编码时的冗余。

    自动安装方法:

    直接运行lombok.jar文件,首先要确保机器的Java环境已正常配置,在自动安装完成后,会达到和手动安装一样的效果。

    手动安装方法:

    1.将lombok.jar复制到myeclipse.ini/eclipse.ini所在的文件目录中。

    2.打开 eclipse.ini / myeclipse.ini,在最后面插入以下两行并保存:

    -Xbootclasspath/a:lombok.jar

    -javaagent:lombok.jar

    3.重启 myeclipse/eclipse

    注:这是官方提供的一种安装方式,当使用的是myeclipse时,按照上述方法时不能正常使用的,需要将myeclipse的可执行文件名称由myeclipse.exe更改为

    eclipse.exe,此时才可以正常使用(具体原因是不是因为lombok在内部指定了一些常量,还未定)。

    IDE中使用步骤:

    按照正常步骤安装Lombok.jar文件后,在项目中需要引入Lombok.jar文件,将其加入到ClassPath路径下。

    3.详解:

    Lombok是基于注解完成标记的,再对已经标记的变量进行特殊解析,Lombok中包含着如下一些自定义注解:

    @val/@NonNull/@Cleanup/@Getter / @Setter/@ToString/@EqualsAndHashCode/@NoArgsConstructor/@RequiredArgsConstructor and @AllArgsConstructor

    /@Data/@Value/@Builder/@Synchronized/@Getter(lazy=true)/@Log、Lombok提供了这几种注解来完成对代码的精简。

    Lombok能做到在IDE少编写代码,既不是用annotations process,也不是反射,而是直接在编译器对原码的编译过程进行操作。

    具体示例如下:

    使用Lombok的MModel类:

        public @Data class User {
            private String name;

        }

    或者

        public class User {
            @Getter @Setter
            private String name;

        }

    此时:若在IDE的Outline视窗中可以看到在字节码中直接生成了name的getter/setter方法,这极大的简化了在编程过程的代码量,况且Lomnok无需第三方依赖,便可完成

    对于Model类的操作。

    在其他类中可以像正常使用类一样使用:

        User user = new User();
        user.setName("Wangbc");

        user.getName();

    4.注解含义:

    ·@Data:相当于同时使用了@String、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstrutor这些注解,对于Pojo类十分有用

            ·@NonNull:给方法参数增加这个注解会自动在方法内对该参数进行是否为空的校验,如果为空,则抛出NPE

            ·@CleanUp:自动生成try-finally这样的代码来关闭流

            ·@Getter(lazy=true):可以替代经典的Double Check Lock样板代码。

            ·其他的可以参考官网文档进行详细了解。

    5.不足:

    尽管Lombok可以对代码进行精简,但是在使用的过程中还是会遇到问题:例如,源码中代码的隐藏使得在代码调试的过程中难度增加,增加代码重构的麻烦,而且

    Lombok在使用过程中与eclipse尚不能完美兼容,这些在实际应用过程中都是需要考虑的问题,但本人觉得其无伤大雅。

    6.完结:

    Lombok是一个很小的,但是很实用的开源项目,它可以大幅的减少由于ORM框架应用导致的代码冗余。无论如何,对于已经接近完善project的源码中,毫无用处的重复代

    码会降低其可读性,精而少的代码才更易维护。

    展开全文
  • java 减少代码冗余

    2019-12-26 14:17:48
    最简便的就是减少了get/set方法,虽然快捷键就可以生成,but,减少了很多代码哟   ******************************************************分割线****************************************************** ...

    一、idea安装lombok插件å®è£lombokæ件

    å¨è¿éæå¥å¾çæè¿°

    二、重启idea


    三、添加maven依赖
    <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.10</version>
     </dependency>


    四、来个实体类测试
    import lombok.Data;

    @Data
    public class MyTestBean {
        private Integer id;
        private String name;
        private String password;
    }

    五、测试代码
    public class TestMyBean {
        public static void main(String[] args){
            MyTestBean m=new MyTestBean();
            m.setId(1);
            m.setName("zhangsan");
            m.setPassword("123456");
            System.out.println(m);
        }
    }

    六、结果

    七、扩展
    @Data : 注解在类上, 为类提供读写属性, 此外还提供了 equals()、hashCode()、toString() 方法
    @Getter/@Setter : 注解在类上, 为类提供读写属性
    @ToString : 注解在类上, 为类提供 toString() 方法
    @Slf4j : 注解在类上, 为类提供一个属性名为 log 的 log4j 的日志对象
    @Log4j : 注解在类上, 为类提供一个属性名为 log 的 log4j 的日志对象

    最简便的就是减少了get/set方法,虽然快捷键就可以生成,but,减少了很多代码哟

     

    ******************************************************分割线******************************************************

     

    再分享两个注解@GetMapping和@PostMapping

    @getMapping = @requestMapping(method = RequestMethod.GET)。

    @postMapping = @requestMapping(method = RequestMethod.POST)。

    以前我们在控制器中, 被请求方法头上会有一个标签

    @RequestMapping(value="test", method = RequestMethod.GET)

    或者@RequestMapping(value="test", method = RequestMethod.post)

    可以改为

    @getMapping/@postMapping

    展开全文
  • 解决代码冗余问题

    千次阅读 2018-08-03 15:22:40
    import socket import re import os import sys import mini_web_frame_3 """ GET /a/b/c HTTP/1.1\r\n 请求行 Accept: text/html;iamge/jpeg.... Accept: text/html;iamge/jpeg.... ......
    import socket
    import re
    import os
    import sys
    import mini_web_frame_3
    """
    
    GET /a/b/c HTTP/1.1\r\n 请求行
    Accept: text/html;iamge/jpeg....
    Accept: text/html;iamge/jpeg....
    \r\n
    请求体
    
    
    HTTP/1.1 200 OK\r\n
    Server: fdfff
    Content-type:cfdf\r\n
    \r\n
    响应体
    
    """
    
    
    
    
    class HttpServer(object):
        def __init__(self):
            # 1、创建负责监听的socket
            self.socket_watch = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 2、设置地址重用
            self.socket_watch.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # 3、绑定监听的端口
            self.socket_watch.bind(("localhost", 8888))
            # 4、转为被动
            self.socket_watch.listen(128)
    
        def handle_client(self,socket_con):
            """
            负责处理客户端的连接
            接收客户端发送的请求报文
            解析客户端发送的请求报文
            返回响应报文
            """
            request = socket_con.recv(4096).decode()
            # print(request)
            # 通过split函数,切割请求报文,获取请求行
            request_lines = request.split("\r\n")
            # print(request_lines)
            # 获取请求行
            requeset_line = request_lines[0]
            # print(requeset_line)
            # GET /a/b/c/d.html HTTP/1.1
            #/ a / b / c / d.html
            # favicon.ico
            res = re.match(r"\w+\s+(\S+)",requeset_line)
            path = res.group(1)
            # path ="/Users/zhaojianyu/Desktop/hm_day02/www" + path
            path = os.getcwd() + "/www" + path
            # print(path)
            # 如果访问的资源路径,服务器中不存在, return 404  # ......py
            #key: value
            if path.endswith(".py"): # WSGI
                response_line = "HTTP/1.1 200 OK\r\n"
                response_head = "Server: mini_web_frame v 1.0\r\n"
                response_head += "Content-type:text/html;charset= utf-8\r\n"
    
                # 1、浏览器发送了一个.p请求,服务器处理不了,将请求给web应用
                # 2、web应用根据请求,来选择性的调用响应的函数处理
                # 3、通过全路径获取文件名
                file_name = os.path.basename(path).split('.')[0] #login.py
    
                response_body = mini_web_frame_3.application(file_name)
                response = response_line + response_head + "\r\n" +response_body
                socket_con.send(response.encode())
                socket_con.close()
                return
    
    
    
    
    
    
    
    
    
    
            else:
                if not os.path.exists(path):
                    response_line = "HTTP/1.1 404 Not Found\r\n"
                    response_head = "Server:laozhao v3.0\r\n"
                    response_body = "request directory or file is not exist\r\n"
                    response = response_line + response_head + "\r\n" +response_body
                    socket_con.send(response.encode())
                    socket_con.close()
                    return
                else:
                    # 要么是文件,要么是文件夹
                    # 判断用户请求的是文件
                    if os.path.isfile(path):
                        # 读取指定路径下的文件,并返回(响应报文)
                        response_line = "HTTP/1.1 200 OK\r\n"
                        response_head = "Server: laozhao v3.0\r\n"
                        file = open(path,"rb")
                        response_body = file.read()
                        file.close()
                        response = response_line.encode() + response_head.encode() + "\r\n".encode() +response_body
                        socket_con.send(response)
                        socket_con.close()
                        return
                    else:
                        #请求的文件夹资源,没有/
                        if not path.endswith("/"):
                            response_line = "HTTP/1.1 302 Found\r\n"
                            response_head = "Server: laozhao v3.0\r\n"
                            response_head += "Content-Type:text/html;charset=utf-8\r\n"
                            response_body = "重定向到"+path +"/"
                            response = response_line+ response_head +"\r\n" +response_body
                            socket_con.send(response.encode())
                            socket_con.close()
                            return
                        else:
                            # 请求的资源路径有斜线
                            # 1、我允许你访问我的默认文件
                            defualt_document = False
                            # 如果为True,则读取对应的默认文件
                            if defualt_document:
                                if os.path.exists(path+"index.html"):
                                    file = open(path+"index.html","rb")
                                    response_body =file.read()
                                    file.close()
                                    response_line = "HTTP/1.1 200 OK\r\n"
                                    response_head = "Server: laozhao v3.0\r\n"
                                    response = response_line.encode() + response_head.encode() +"\r\n".encode()+response_body
                                    socket_con.send(response)
                                    socket_con.close()
                                    return
                                elif os.path.exists(path + "default.html"):
                                    file = open(path + "default.html", "rb")
                                    response_body = file.read()
                                    file.close()
                                    response_line = "HTTP/1.1 200 OK\r\n"
                                    response_head = "Server: laozhao v3.0\r\n"
                                    response = response_line.encode() + response_head.encode() + "\r\n".encode() + response_body
                                    socket_con.send(response)
                                    socket_con.close()
                                    return
                                else:
                                    response_line = "HTTP/1.1 404 Not Found\r\n"
                                    response_head = "Server: laozhao v3.0\r\n"
                                    response_body = "Not Found"
                                    response = response_line + response_head +"\r\n" +response_body
                                    socket_con.send(response.encode())
                                    socket_con.close()
                                    return
                            else:
                                # 判断是否开启了目录浏览
                                document_browsing = True
                                if document_browsing :
                                    # 1、获取访问资源文件夹下所有的文件和文件夹(当前目录下)
                                    list_names = os.listdir(path)
                                    # 2、拼接HTML页面,返回给浏览器客户端
                                    response_body = "<html><head><body><ul>"
                                    for item in list_names:
                                        response_body += "<li><a href='#'>" + item +"</a></li>"
                                    response_body += "</ul></body></head></html>"
                                    response_line ="HTTP/1.1 200 OK\r\n"
                                    response_head = "Server: laozhao v3.0\r\n"
                                    response = response_line +response_head +"\r\n" +response_body
                                    socket_con.send(response.encode())
                                    socket_con.close()
                                    return
    
    
    
    
    
    
    
    
                            # index.html default.html
                        # 2、如果不允许你访问我的默认文件,判断是否开启了目录浏览
                        # 3、如果开启了目录浏览,则拼接文件夹的列表,进行返回
                        # 4、如果没有开启目录浏览,404  提示............
    
            # print(path)
            # /Users/zhaojianyu/Desktop/hm_day02/www/favicon.ico
            # /Users/zhaojianyu/Desktop/hm_day02/www/a/b/c/d.html
            # 拼接响应报文
            """
                响应行
                响应头
                空行
                响应体
            """
            """
                www.baidu.com
                www.baidu.com/
                www.baidu.com/index.html
                www.baidu.com/a
                www.baidu.com/a/b
                结论:从路径是否有扩展名判断是文件或者是文件夹是不成立的。
                服务器处理:
                    如果用户请求的是文件夹,
                    首先判断文件夹的结尾是否有 /(服务器认为,只有文件夹后加上/,才是访问文件夹的标准格式)
                    重定向到 带/的路径下
                文件夹有/
                    1、如果说文件夹中有默认的文件,则给你返回默认的文件 index.html defalut.html
                    2、是否开启了目录浏览
            """
    
    
            response_line = "HTTP/1.1 200 OK\r\n"
            response_head = "Server:laozhao v1.0\r\n"
            response_head += "Content-Type: text/html;charset=utf-8\r\n"
            # 返回固定页面的web服务器
            path = "/Users/zhaojianyu/Desktop/hm_day02/www/index.html"
            file = open(path,"r")
            response_body = file.read()
            file.close()
            response = response_line + response_head + "\r\n" + response_body
            # send给客户端浏览器
            socket_con.send(response.encode())
            socket_con.close()
    
        def run_server(self):
            while True:
                # 返回与客户端通信的socket和客户端的地址
                socket_con, con_addr = self.socket_watch.accept()
                print("客户端%s连接成功!!!!" % str(con_addr))
                # handle_client
                self.handle_client(socket_con)
    def main():
        # 1、创建HttpServer对象
        # port = int(sys.argv[1])
        http_server = HttpServer()
        # 2、调用run_server方法
        http_server.run_server()
    
    
    if __name__ == '__main__':
        main()

     

    展开全文
  • 用 Groovy 减少代码冗余

    千次阅读 2008-12-14 10:35:00
    Groovy 简洁的语法将开发人员从那种需要进行代码编译但却无助于表达 什么 是程序真正想要实现的典型的 Java™ 结构中解放了出来。在实战 Groovy 系列的这一复兴篇中,Groovy 开发人员兼特约专栏作家 J. Scott Hickey...
     
    Groovy 简洁的语法将开发人员从那种需要进行代码编译但却无助于表达 什么 是程序真正想要实现的典型的 Java™ 结构中解放了出来。在实战 Groovy 系列的这一复兴篇中,Groovy 开发人员兼特约专栏作家 J. Scott Hickey 带您进行一系列对常规 Java 代码和 Groovy 代码的比较,展示这门令人兴奋的语言如何将您解放出来,让您能够专注于编码的重要方面。

    通常,程序员们转而选择诸如 Groovy 之类的编程语言,是为了构建快速的实用程序,快速编写测试代码,甚至创建构成大型的 Java 应用程序的组件,而 Groovy 先天具有这样一种能力,它能够减少传统的基于 Java 系统所固有的许多冗余并降低其复杂度。Groovy 简洁而灵活的语法将开发人员从那种需要进行代码编译却无助于表达什么 是程序真正想要实现的典型的 Java 结构中解放出来。不仅如此,Groovy 轻松的类型通过减少一些接口和超类使代码不再复杂,这些接口和超类都是常规 Java 应用程序用以支持不同具体类型间的通用行为所需的。

    为了举例说明 Groovy 如何减少 Java 应用程序所涉及的无用数据,我将使用 Bruce Tate 和 Justin Ghetland 的 Spring: A Developer's Notebook(参见 参考资料) 中的样例代码,该书介绍了如何使用 Spring 进行控制反转。每当回顾一个 Java 样例,我都会将其与实现相同功能的相应的 Groovy 源代码进行比较,您将很快发现 Groovy 通过减少 Java 编程的不同方面(冗余且不必要地传递了应用程序的行为)而使应用程序代码变得多么地清晰。

    Groovy 之声

    在 Bruce 和 Justin 这本书的第一章中,创建了一个简单的自行车商店应用程序,其中包含有四个类。首先,我将向您展示一个简单的名为 Bike 的 JavaBean 类,该类代表了一辆库存的自行车。然后,我会考查自行车商店的类型,名为 RentABike。它包含了一个 Bike 集。还有一个命名为 CommandLineView 的用于显示自行车列表的类,该类依赖于 RentABike 类型。最后,有一个用于集成这些部分以创建工作应用程序的类,该类利用 Spring 来传递完整地配置了 RentABike 类型的 CommandLineView 类 —— 免去了复杂的硬编码。

    停用 JavaBean!

    清单 1 中一个代表自行车的类在常规 Java 代码中被实现为一个简单的 JavaBean,它是 Java 开发人员可能已经编写好的成百上千的类的一个典型。通常来说,JavaBean 并没有什么特殊之处 —— 其属性被声明为 private,且可通过 public getter 和 setter 对其进行访问。


    清单 1. Java 代码中的 Bike JavaBean
        
    import java.math.BigDecimal;

    public class Bike {
    private String manufacturer;
    private String model;
    private int frame;
    private String serialNo;
    private double weight;
    private String status;
    private BigDecimal cost;

    public Bike(String manufacturer, String model, int frame,
    String serialNo, double weight, String status) {
    this.manufacturer = manufacturer;
    this.model = model;
    this.frame = frame;
    this.serialNo = serialNo;
    this.weight = weight;
    this.status = status;
    }

    public String toString() {
    return "com.springbook.Bike : " +
    "manufacturer -- " + manufacturer +
    "/n: model -- " + model +
    "/n: frame -- " + frame +
    "/n: serialNo -- " + serialNo +
    "/n: weight -- " + weight +
    "/n: status -- " + status +
    "./n"; }

    public String getManufacturer() { return manufacturer; }

    public void setManufacturer(String manufacturer) {
    this.manufacturer = manufacturer;
    }

    public String getModel() { return model; }

    public void setModel(String model) { this.model = model; }

    public int getFrame() { return frame; }

    public void setFrame(int frame) { this.frame = frame; }

    public String getSerialNo() { return serialNo; }

    public void setSerialNo(String serialNo) { this.serialNo = serialNo; }

    public double getWeight() { return weight; }

    public void setWeight(double weight) { this.weight = weight; }

    public String getStatus() { return status; }

    public void setStatus(String status) { this.status = status; }

    public BigDecimal getCost() { return cost; }

    public void setCost(BigDecimal cost) {
    this.cost = cost.setScale(3,BigDecimal.ROUND_HALF_UP);
    }

    }

    清单 1 是一个只有一个构造方法和六个属性的小例子,但其代码却填满了浏览器的整个页面!清单 2 显示了在 Groovy 中定义的相同的 JavaBean:


    清单 2. Bike GroovyBean
      
    class Bike {

    String manufacturer
    String model
    Integer frame
    String serialNo
    Double weight
    String status
    BigDecimal cost

    public void setCost(BigDecimal newCost) {
    cost = newCost.setScale(3, BigDecimal.ROUND_HALF_UP)
    }


    public String toString() {
    return """Bike:
    manufacturer -- ${manufacturer}
    model -- ${model}
    frame -- ${frame}
    serialNo -- ${serialNo}
    """
    }
    }

    您认为哪一个没那么多冗余呢?

    Groovy 版的代码要少很多很多,这是因为 Groovy 的默认属性语义用 public 访问器和存取器自动定义了 private 域。例如,上述 model 属性现在有了自动定义的 getModel() 方法和 setModel() 方法。可以看到,这项技术的好处是,不必在一种类型中按照属性手工定义两个方法!这也解释了 Groovy 中的一条反复强调的定律:使普通的编码规则变得简单

    Groovy 更新了的属性语法
    最新版的 Groovy, JSR-06 简化了 Groovy 的属性语法。在此版本之前,属性要在变量声明前跟一个特定的 @Property 符号。但这个符号现在已经不再需要。在 JSR-06 中,只需指定一个类型和一个变量名,就会自动生成一个有着 public getter 和 setter 的 private 属性。也可以使用 def 关键字来代替特定的类型。

    另外,在 Groovy 中,类的默认函数表达得更为简洁,而在常规 Java 代码(如 清单 1)中该函数必须显式编码。当需要用构造函数或 getter 或 setter 来完成一些特殊任务时,Groovy 真的很出色,因为只需瞥一眼代码,其精彩的行为就会立即变得十分明显。例如,在 清单 2 中很容易看出,setCost() 方法会将 cost 属性换算为三个十进制的位。

    将这段不太显眼的 Groovy 代码同 清单 1 中的 Java 源代码进行比较。第一次阅读这段代码时,您注意到 setCost() 方法中嵌入了特殊的函数了吗?除非仔细观察,否则太容易看漏了!

    Groovy 测试

    清单 3 中 Bike 类的测试用例展示了如何使用自动生成的访问器。同时,出于进一步简化通用编程任务的考虑,测试用例也使用了更为简便的 Groovy 点属性名 标记来访问属性。相应地,能够通过 getModel() 方法或更为简洁的 b.model 形式来引用 model 属性。


    清单 3. Groovy 中的 Bike 测试用例
      
    class BikeTest extends GroovyTestCase {
    void testBike() {
    // Groovy way to initialize a new object
    def b = new Bike(manufacturer:"Shimano", model:"Roadmaster")

    // explicitly call the default accessors
    assert b.getManufacturer() == "Shimano"
    assert b.getModel() == "Roadmaster"

    // Groovier way to invoke accessors
    assert b.model == "Roadmaster"
    assert b.manufacturer == "Shimano"
    }
    }

    也注意到在上述 Groovy 例子中,不必定义一个如 清单 1 中定义的 Java 构造函数那样的能够接受全部六个属性的构造函数。同时,也不必要创建另一个 只含两个参数的构造函数来支持测试用例 —— 在对象创建过程中设置对象属性的 Groovy 的语义不需要这种冗余、烦人的构造函数(它们综合有多个参数但其作用却只是初始化变量)。

    Groovy 和 IDE
    像 Eclipse 那样的 IDE 使得自动创建 getter 和 setter 变得十分简单。这些工具也便利了从具体类中提取接口以利于对其进行重构。但我敢说,读那段代码的次数要比写它的次数多很多。 不幸的是,开发人员仍需要通过已经生成的代码和源文件来费力地分辨程序真正在实现什么。用这个高质量的 Java 工具究竟能不能节省创建 Groovy 源代码的敲键次数尚有争议,但一看即明的是 Groovy 代码更为简洁、更易于解释,且没那么复杂。在实际的有着数百个类和数千行代码的应用程序,这种优势就更为突出。

    降低的复杂性

    在前面的部分中,Bike GroovyBean 利用了 Groovy 的属性和构造语义以减少源代码中的冗余。在这一部分中,Groovy 版的自行车商店也将受益于额外的冗余减少特性,如针对多态的 duck-typing、集合类的改进及操作符重载。

    Grooving 中使用多态

    在 Java 自行车应用程序中,名为 RentABike 的接口是用来定义由自行车商店支持的 public 方法的。正如在清单 4 中说明的那样,RentABike 定义了一些简单的方法,这些方法用来返回商店中单个的 Bike 或所有 Bike 的列表。


    清单 4. 由 Java 定义的 RentABike 接口
      
    import java.util.List;

    public interface RentABike {
    List getBikes();
    Bike getBike(String serialNo);
    void setStoreName(String name);
    String getStoreName();
    }

    此接口允许多态行为并在下面两种重要情况下提供了灵活性。其一,如果要决定将实现由 ArrayList 转变为数据库形式,余下的应用程序与该变化是隔绝的。其二,使用接口为单元测试提供灵活性。例如,如果要决定为应用程序使用数据库,可以轻易地创建一个该类型的模拟实现,而且它不依赖于实时数据库。

    清单 5 是 RentABike 接口的 Java 实现,它使用 ArrayList 来存储多个 Bike 类:


    清单 5. RentABike 接口的 Java 实现
        
    import java.util.List;
    import java.util.ArrayList;
    import java.util.Iterator;

    public class ArrayListRentABike implements RentABike {
    private String storeName;
    final List bikes = new ArrayList();

    public void setStoreName(String name) {
    this.storeName = name;
    }

    public String getStoreName() {
    return storeName;
    }

    public ArrayListRentABike(String storeName) {
    this.storeName = storeName;
    bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, "Fair"));
    bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12, "Excellent"));
    bikes.add(new Bike("Trek","6000", 19, "33333", 12.4,"Fair"));
    }

    public String toString() { return "com.springbook.RentABike: " + storeName; }

    public List getBikes() { return bikes; }

    public Bike getBike(String serialNo) {
    Iterator iter = bikes.iterator();
    while(iter.hasNext()) {
    Bike bike = (Bike)iter.next();
    if(serialNo.equals(bike.getSerialNo())) return bike;

    }
    return null;
    }
    }

    现在将 清单 45 中的 Java 代码同 清单 6 中的 Groovy 代码进行比较。Groovy 版的代码很灵巧地避免了对 RentABike 接口的需求。


    清单 6. Groovy 的 ArrayListRentABike 实现
      
    public class ArrayListRentABike {
    String storeName
    List bikes = []
    public ArrayListRentABike(){
    // add new instances of Bike using Groovy's initializer syntax
    bikes << new Bike(manufacturer:"Shimano", model:"Roadmaster",
    frame: 20, serialNo:"11111", weight:15, status:"Fair")
    bikes << new Bike(manufacturer:"Cannondale", model:"F2000",
    frame: 18, serialNo:"22222", weight:12, status:"Excellent")
    bikes << new Bike(manufacturer:"Trek", model:"6000",
    frame: 19, serialNo:"33333", weight:12.4, status:"Fair")
    }

    // Groovy returns the last value if no return statement is specified
    public String toString() { "Store Name:=" + storeName }

    // Find a bike by the serial number
    def getBike(serialNo) { bikes.find{it.serialNo == serialNo} }

    }

    Groovy 像其他动态语言(如 Smalltalk 或 Ruby)一样支持具有 “duck typing” 的多态 —— 在运行时,如果一个对象表现得像个 duck ,它就会被视为 duck ,从而支持 接口的多态。有了 Groovy ArrayListRentABike 实现,不但减少了成行的代码,而且由于少创建和维护一个模块,复杂性也降低了。那是非常重要的冗余减少!

    除了 duck typing,清单 6 中的默认属性语法还简单地定义了两个普通属性,storeNamebikes,如同拥有了 getter 和 setter 一样。这样做的好处和在 清单 12 中比较 JavaBean-GroovyBean 时所说明的好处是一样的。尤其是,清单 6 还阐明了另一个用以减少代码冗余的 Groovy 特性 —— 操作符重载。请注意如何使用 << 操作符来代替 add() 方法。通过减少一层嵌套的括号使代码的可读性得以改善。这也是 Groovy 众多通过减少冗余而改善代码可读性的特性中的一种。

    Groovy 方式下的和谐集合
    用诸如 eachfind 的方法来使用闭包简化了最常见的任务集,如循环和查找。将 清单 5 中 Java 版本的 getBike()清单 6 中 Groovy 版的进行比较。在 Groovy 中,很明显是通过其序列号来寻找 Bike。而在 Java 版中,定义了一个 Iterator 并计算列表中下一个条目,这很多余,且不利于理解该应用程序真正要实现的功能,即寻找一辆自行车。

    透明的代码

    Groovy 中的 duck-typing 和属性语义通过减少代码行数来减少冗余;然而,也可以通过增加透明度来减少冗余。在 清单 6 中,请注意在 ArrayListRentABike 构造函数中创建新 Bike 对象的方式。Groovy 名称和值的初始化语法比 Java 版的略微详细,但这些额外的代码却使整个代码更为透明 —— 将这一点与 清单 5 中 Java 版的进行比较,哪个属性被初始化为哪个值会立即明显 起来。不回过头来看 Bike JavaBean 源代码,您能记起哪个参数是 frame,哪个是 new Bike("Shimano"、 "Roadmaster"、20、 "11111"、15、 "Fair")weight 吗?尽管我刚写过,但我还是记不起来!








    一个更小的、更加 Groovy 化的自行车商店视图

    到目前为止,我将 Bike 和自行车商店类型在 Java 和 Groovy 下进行了比较。现在,到了更近距离地看一下自行车商店的视图 的时候了。在清单 7 中,该视图类具有一个 rentaBike 属性,该属性引用 RentABike 接口并在行动上说明 Java 版的多态。由于 Java 要求所有类属性都必须是声明过的类型,而不是针对某个特定的实现进行编码,我向一个接口编程,该接口使这个类跟 RentABike 实现的改变分隔开来。这是很好的、扎实的 Java 编程实践。


    清单 7. Java 版的自行车商店视图
      
    public class CommandLineView {
    private RentABike rentaBike;

    public CommandLineView() {}

    public void setRentaBike(RentABike rentaBike) {
    this.rentaBike = rentaBike;
    }

    public RentABike getRentaBike() { return this.rentaBike; }

    public void printAllBikes() {
    System.out.println(rentaBike.toString());
    Iterator iter = rentaBike.getBikes().iterator();
    while(iter.hasNext()) {
    Bike bike = (Bike)iter.next();
    System.out.println(bike.toString());
    }
    }
    }

    将清单 7 中的 Java 视图与清单 8 中的 Groovy 视图进行比较,请注意我声明了带 def 关键字的 rentaBike。这是 duck-typing 的实践,与 Java 版的很像。我正在实践好的软件设计,这是因为我还没有将视图和特定的实现耦合起来。但我也能够 定义接口就实现解耦。


    清单 8. Groovy 的 CommandLineView
      
    public class CommandLineView {
    def rentaBike // no interface or concrete type required, duck typing in action

    def printAllBikes() {
    println rentaBike
    rentaBike.bikes.each{ println it} // no iterators or casting
    }
    }

    Bike 和自行车商店类型一样,Groovy 的 CommandLineView 没有了为 RentABike 属性所显式编写 的 getter 或 setter 的冗余。同样,在 printAllBikes() 方法中,通过使用 each 来打印在集合里找到的每辆自行车,我再一次利用了 Groovy 强大的集合功能的改进。







    使用 Spring 进行组装

    在前面的部分中,已经介绍了 Groovy 相比 Java 是如何定义自行车、自行车商店和自行车商店视图的。现在该介绍如何将整个应用程序组装起来并在命令行视图中使用 Spring 来显示库存自行车列表了。

    工厂的工厂

    在 Java 编程中,一旦定义了一个接口,就可以使用工厂模式将创建真实的实现类的责任委派给一个对象工厂。使用 Spring 作为一个工厂极大地减少了冗余,并在 Groovy 和 Java 中都能够使用,在最终的代码样例中,Spring 负责在 Java 和 Groovy 中创建一个 CommandLineView 类型的实例。

    在清单 9 中,配置 Spring 是为了在返回一个 CommandLineView 实例前,创建并将自行车商店的 ArrayList 实现注入 CommandLineView 中。这意味着,不需要引用在 清单 78 的 Java 或是 Groovy 版的命令行视图中的 ArrayList 实现。在 Java 版中,被注入的类通常都会引用一个接口而不是实现。在 Groovy 中,由于使用 def 关键字,而允许利用 duck-typing。无论在哪个实例中,配置 Spring 的目的都是为了将自行车商店视图的实例和自行车商店类型的实例完整地配置起来


    清单 9. Spring 配置文件
            
    <beans>
    <bean id="rentaBike" class="ArrayListRentABike">
    <property name="storeName"><value>"Bruce's Bikes (spring bean)"</value></property>
    </bean>
    <bean id="commandLineView" class="CommandLineView">
    <property name="rentaBike"><ref bean="rentaBike"/></property>
    </bean>
    </beans>

    在清单 10 和 11 中,自行车商店组装类型用清单 9 中的配置文件创建了一个 Spring 的 ClassPathXmlApplicationContext 实例,然后,请求自行车商店视图的实例:


    清单 10. Java 版本下调用 Spring 创建自行车商店视图
      
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class RentABikeAssembler {
    public static final void main(String[] args) {
    // Create a Spring application context object
    ClassPathXmlApplicationContext ctx =
    new ClassPathXmlApplicationContext("RentABike-context.xml");

    // retrieve an object from Spring and cast to a specific type
    CommandLineView clv = (CommandLineView)ctx.getBean("commandLineView");

    clv.printAllBikes();
    }
    }

    请注意Java 版的清单 10 中,用以请求一个命令行视图实例的对 Spring 的调用要求向一个支持 printAllBikes() 方法的对象类型强制转换。在本例中,由 Spring 导出的对象将被强制转换为 CommandLineView

    有了 Groovy 及其对 duck-typing 的支持,将不再需要强制转换。只需确保由 Spring 返回的类能够对合适的方法调用(printAllBikes())作出响应。


    清单 11. Groovy 版的 Spring 组合件
      
    import org.springframework.context.support.ClassPathXmlApplicationContext

    class RentABikeAssembler {
    public static final void main(String[] args) {
    // Create a Spring application context object
    def ctx = new ClassPathXmlApplicationContext("RentABike-context.xml")

    //Ask Spring for an instance of CommandLineView, with a
    //Bike store implementation set by Spring
    def clv = ctx.getBean("commandLineView")

    //duck typing again
    clv.printAllBikes()
    }
    }

    正如在清单 11 中看到的那样,在 Groovy 中,duck-typing 对减少冗余的贡献不仅体现在无需声明接口即可支持由 Spring 自动配置对象,其贡献还体现在简化了对完全配置的 bean 的使用(一旦它从 Spring 容器中返回)。







    与 Groovy 相协调

    至此,希望我已经阐明了 Groovy 的强大功能及其如何能如此深远地改变源代码的性质。与上述 Java 样例相比,Groovy 代码更简短也更易理解。任何人,无论是经验丰富的 Java 架构师还是非 Java 程序员,都能轻易地掌握 Groovy 代码的意图。Groovy 及其对动态类型的支持减少了要管理的文件。总之,使用 Groovy 减少了在典型的 Java 程序中所常见的大量冗余。这实在是福音啊!






    展开全文
  • (不用你提醒,改多了他自己就知道优化代码,减少代码冗余) 2:业务要清晰,业务不清晰不可避免的写冗余代码,(所以需要一个好的产品) 3:封装方法的时候,最小模块化,就是一个方法的封装,要保证这个方法...
  • 机房收费系统中有很多都是重复的代码,代码冗余很严重,降低了代码利用率,也浪费自己的时间去敲重复的代码。所以我们为什么不想一个办法去解决这个问题呢。懒是发明的第一推动力。 一、快速清空文本框、下拉框等等...
  • 代码冗余到底有没有好处?

    千次阅读 2017-01-09 20:15:39
    2:其实就我开发java程序来看,如果一开始需求比较完整,不容易写出很多冗余代码,往往冗余代码就是一开始设计不够好,或者需求不够完整造成的。 3:比如说我曾经做个一个系统,一开始是人工创建订单,调用...
  • 如何解决重复冗余代码

    千次阅读 2020-05-18 00:12:41
    如何解决重复冗余代码1.利用工厂模式+模板方法模式消除if...else和重复代码2.利用注解+反射消除重复代码3.利用属性拷贝工具消除重复代码 1.利用工厂模式+模板方法模式消除if…else和重复代码 我们可以把重复的逻辑...
  • 代码过程中的冗余处理

    千次阅读 2017-10-09 15:47:29
    代码时往往会遇到冗余,那么,我们什么时候应该保留冗余什么时候应该去除冗余呢? 1、 冗余有好处吗?大部分情况下是没有的。 2、 冗余的好处主要体现在恢复数据和并发读取数据提高效率方面。 3、 冗
  • 代码优化就一个原则-消除冗余

    千次阅读 2019-03-22 20:37:56
    架构,设计,优化,重构,编码。 就一个原则:把重复的东西交给while...消除冗余,无疑,代码的数量少了。 代码的数量少了,一般是容易理解的。 代码的数量少了,一般执行的效率是高的。 代码的数量少了,一般是重复...
  • 那么在做这样的项目时,首先要做的除了对单个网页的框架进行设计以外,我们还应该注意代码冗余问题,就是要使你设计的那个框架能够很好的兼容这几个网页的内容,达到写最少的代码实现同样的功能的效果。...
  • CRC循环冗余码原理简述及python代码实现 CRC循环冗余码在计算机组成原理和计算机网络中都有重要的地位,但也不太好懂。 本人通过华南理工大学袁华老师的计算机网络(中国大学mooc平台)课程对CRC编码有了一点肤浅的...
  • 冗余代码检查工具Simian

    千次阅读 2012-12-11 21:43:38
    冗余代码检查工具Simian 微软web2.0开发示例Kobe,重蹈了Oxite的覆辙。Ayende连续发表了五篇高质量的Kobe探讨贴: Kobe – In the nuts & bolts and don’t really liking itKobe – Data Access done ...
  • 代码同步至我的Github:Stackery 前言: 为积极响应学校课程签到工作,由于课程太多,这几天我朋友来问我能不能实现每日超星学习通自动化处理,避免每日信息的漏报、延报。 大家最好不要拿来搞坏事情哦!!! 声明...
  • 去掉tppabs冗余代码

    千次阅读 2010-09-16 15:08:00
    呵呵,不过昨天拿到代码后,确实吓我一跳。那么多网页要修改。诶,说来也是运气好,当然也要感谢我们伟大的互联网,因为有了它,所以我们的生活更加方便了,更加多姿多彩啦、因为有了它,所以我修改网页也方便了很...
  • 在项目中写一些冗余代码

    千次阅读 2017-12-17 22:32:55
    这个问题发生的根本原因在于过于追求代码的简洁(其实丧失了可读性),没有使用冗余代码做防御式编程。导致我现在有种“一朝被蛇咬十年怕井绳”的感觉,在配置这种需要数据源的视图时,一定要考虑 indexPath.row / ...
  • CRC循环冗余校验码代码实现

    千次阅读 2018-08-13 12:36:44
    三、CRC循环冗余校验代码实现 四、程序执行结果 一、CRC循环冗余校验简介 现实的通信链路都不是理想的。也就是说,比特在传输过程中可能会产生差错:1可能变成0,0也可能变成1。这叫做比特差错。为了保证数据传输...
  • 里面介绍了CRC 计算的原理,也给出了些代码,里面的代码稍微改改就能计算常见的各种 CRC。 但是可能 CRC 计算确实有点难度,改写我的代码也不那么容易。趁着周末空闲,把原来的代码重新整理了一下,用 C++ 重新实现...
  • 消除Java 的冗余代码

    千次阅读 2015-07-19 10:34:02
    我们有些实际项目中的代码例如:setter ,getter等太多,从而使项目看上去代码很臃肿;  我们来讲讲如何安装此插件,首先在网上下载一个名为:lombok.jar;放到Eclipse开发环境的根目录下如下图:  不是放在...
  • 五、合理使用模板,避免代码冗余 六、C++也能反射 七、单例模式解决静态成员对象和全局对象的构造顺序难题 八、更为高级的预处理器PHP 九、Gtkmm的最佳实践 本系列文章属 西风逍遥游 原创,转载请...
  • 代码中, 我们经常会出现重复的代码, 我们可以使用AS自带的方式进行合并以使代码看上去不至于冗余: ![这里写图片描述]...
  • Java未来 - 去掉可恶的冗余代码 - append改进篇# 你应该始终记得,代码设计应该向着设计方向发展,而不是做很多的重复性工作,代码天生就是为了减少重复性工作的。 ---online zuozuo 著1 .经常用到的append方式 /*...
  • 目录 一、项目背景 二、eclipse安装lombok ...使用lombok虽然能够省去手动创建setter和getter方法的麻烦,但是却大大降低了源代码文件的可读性和完整性,降低了阅读源代码的舒适度。  参考文献:  [1]  ...
  • 编程基本原则 —— 避免冗余代码

    千次阅读 2018-08-31 09:29:15
    最近组内做代码评审,看到了如下一段代码,这段代码从功能上、甚至效率上来讲都没有问题,但从可读性和可维护性来讲,可优化的地方显而易见:函数‘foobar’接收‘op_type’为输入参数,该函数的调用完全可以放在...
  • 去除烦人的WORD及EXCEL冗余代码(Javascript),使用方法: 将上述代码COPY到记事本,保存为.htm文件,用浏览器打开,然后在WORD或EXCEL 复制相关的内容,按“从裁剪板粘贴”按钮,下面代码区即为去除冗余代码后的...
  • CRC循环冗余检验的纠错功能和代码实现 写这篇文章呢,主要是想聊一下CRC的纠错功能,虽然我们谈到CRC很少说到它的纠错功能,但不代表没有,因此写一文以记录下它的纠错功能以及如何用java代码实现。 给出java代码...
  • 如题所讲,谢谢各位大神!没有金币了,不好意思啊。。 希望大家都能给点思路,谢谢! 还有,在这里想向大家咨询一个问题,saas-当前市场如何在做了?有实例最好,谢谢
  • Teleport Pro 是款优秀的网站离线浏览工具(即网站整站下载工具),Teleport Ultra是其增强版,但使用此系列软件下载的离线网页里会包含大量冗余代码(如tppabs),手动去修改工作量很大,下面介绍如何通过软件进行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 227,630
精华内容 91,052
关键字:

代码冗余是什么意思