文档章节

再次吐槽红薯的J2Cache

悠悠然然
 悠悠然然
发布于 2017/12/21 11:25
字数 1780
阅读 6783
收藏 19
点赞 9
评论 70

序言

以前写过两篇吐槽@红薯 的文章,吐槽一下J2Cache扒掉红薯的内裤-深入剖析J2Cache,应该说受到了广大Oscer们的一致认同,作为一个站长不好好的搞网站非要搞程序,说什么要做站长里面代码写得最好的,写代码里面网站办的最好的。好吧,这些我都忍了,但是,居然赤果果的点名叫嚣:

作为一个程序员,作为一个连续扒过两次红薯内裤的喷子,为了维护程序员的尊严,为了广大OSCER们不要掉到红薯的坑里,为了世界和平,必须狠狠的砍他。

正文

槽点一:目录结构不规范

上眼首先来找test目录想看看这么测试和使用的,居然找不到,再仔细看居然有个Java类叫

CacheTester

再看resource和src居然不在main目录下,是我已经out了吗?

修改方式,完全按照Java&Maven的开发和代码组织规范老老实实的执行。

槽点二:测试方式不规范

下面就是所谓的测试代码了

/**
 * 
 */
package net.oschina.j2cache;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 缓存测试入口
 * @author Winter Lau
 */
public class CacheTester {

   public static void main(String[] args) {
      
      System.setProperty("java.net.preferIPv4Stack", "true"); //Disable IPv6 in JVM
      
      CacheChannel cache = J2Cache.getChannel();
      BufferedReader in=new BufferedReader(new InputStreamReader(System.in));

       do{
           try {
               System.out.print("> "); 
               System.out.flush();
               
               String line=in.readLine().trim();
               if(line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit"))
                   break;

               String[] cmds = line.split(" ");
               if("get".equalsIgnoreCase(cmds[0])){
                  CacheObject obj = cache.get(cmds[1], cmds[2]);
                  System.out.printf("[%s,%s,L%d]=>%s\n", obj.getRegion(), obj.getKey(), obj.getLevel(), obj.getValue());
               }
               else
               if("set".equalsIgnoreCase(cmds[0])){
                  cache.set(cmds[1], cmds[2],cmds[3]);
                  System.out.printf("[%s,%s]<=%s\n",cmds[1], cmds[2], cmds[3]);
               }
               else
               if("evict".equalsIgnoreCase(cmds[0])){
                  cache.evict(cmds[1], cmds[2]);
                  System.out.printf("[%s,%s]=>null\n",cmds[1], cmds[2]);
               }
               else
               if("clear".equalsIgnoreCase(cmds[0])){
                  cache.clear(cmds[1]);
                  System.out.printf("Cache [%s] clear.\n" , cmds[1]);
               }
               else
               if("help".equalsIgnoreCase(cmds[0])){
                  printHelp();
               }
               else{
                  System.out.println("Unknown command.");
                  printHelp();
               }
           }
           catch(ArrayIndexOutOfBoundsException e) {
               System.out.println("Wrong arguments.");
              printHelp();
           }
           catch(Exception e) {
              e.printStackTrace();
           }
       }while(true);
       
       cache.close();
       
       System.exit(0);
   }
   
   private static void printHelp() {
      System.out.println("Usage: [cmd] region key [value]");
      System.out.println("cmd: get/set/evict/quit/exit/help");
   }

}

为什么不用JUnit,TestNG等单元测试框架,居然还用main?

我们想象一下,每次红薯修改完代码,都得认真输入各种命令来验证是不是正确是不是引入了新的BUG?

槽点三:程序结构组织不合理

按照红薯的设计,提供了2级代理:1级是Ehcache,2级是Redis。

那如果我想把Ehcache换成另外一个比如MemCache的话怎么办?

红薯兄冷笑一声,回答:“你的想法我早就想到了,你只要扩充一个新MemcacheCacheProvider”,然后修改j2cache.properties文件中的配置就可以了

说的确实很有道理,但是,你这里依赖进来的Ehcache相关的包怎么办?去一个一个排除吗?

实际上比较好的办法是:

J2Cache工程制定接口标准和框架的实现类,Ehcache和Redis以及其他的缓存实现各自作为独立工程,用的时候依赖进来即可,这样也可以提供不同版本的缓存实现,而不是都在框架底层依赖死。

槽点四:拒绝接受新鲜事物

对于增加程序的灵活性方面,一个是通过依赖注入的方式,一个是通过配置的方式。

当然红薯同学是不屑于引入Spring等依赖注入框架的,也懒得增加配置文件的,所以就导致一个结果,如果你接受,那么就全盘接受我的方案要不就滚犊子你不是我的菜。但是作为一个通用的框架来说这么做应该是远远不够的,这也大大限制了框架的通用型,或者就只能Clone下代码衍生出各种版本来。这个和红薯同学开源的初始目的完全是背离的。

小节

通过上面的分析,由于代码规范性和设计方面的问题,其实已经没有看代码的必要了,但是回想起红薯叫嚣的样子,不行,还得举起大刀继续深深的砍下去:)

代码评审

Main方法

在许多代码里面都有main方法的存在,

在许多安全扫描程序看来,main方法是存在安全问题的,必须加以说明解释或剔除。如果只是用来做一下测试,还是用Unit test case的方式进行比较好,这样每次install deploy release都可以进行测试为你的代码保驾护航,而放在main里面,我敢保证绝大多数的情况下都是不运行的。

从这个角度来说,开发过程管理是存在问题的。

 

解决思路:有些时间看起来是花的多的,比如JUnit测试用例;有些时间看起来是节省的,比如main方法。

实例初始化

private final static CacheProvider getProviderInstance(String value) throws Exception {
   if("ehcache".equalsIgnoreCase(value))
      return new EhCacheProvider();
   if("redis".equalsIgnoreCase(value))
      return new RedisCacheProvider();
   if("none".equalsIgnoreCase(value))
      return new NullCacheProvider();
   return (CacheProvider)Class.forName(value).newInstance();
}

value这个变量名明显有点词不达意,叫cacheType,cacheProviderType是不是好一点?当然其实叫什么不重要,我觉得这里参数用Class<CacheProider> cacheProvider 更好一点,这样一来清晰,而来代码也清晰的多,类似如下:

return cacheProvider.newInstance();

原因如下:第一让使用者记这些魔鬼字符串是不合适的;第二如果扩充新的类型,都要修改核心代码,这里有依赖倒置的问题;第三,你一会儿是类型一会儿是类的名字,你的注释又没有说明,你是准备让使用你的框架的人都必须熟读里面的每一行代码的意思吗?

扩展性的考虑

当我看到红薯提供了配置文件来修改1、2级缓存的实现的时候,说实际我是比较开心,终于有进步了啊,不容易。

不过看到这里的时候:

String cache_broadcast = props.getProperty("j2cache.broadcast");
if ("redis".equalsIgnoreCase(cache_broadcast)) {
   String channel = props.getProperty("redis.channel");
   policy = ClusterPolicyFactory.redis(channel, CacheProviderHolder.getRedisClient());//.getInstance();
}
else if ("jgroups".equalsIgnoreCase(cache_broadcast)) {
   String channel_name = props.getProperty("jgroups.channel.name");
   policy = ClusterPolicyFactory.jgroups(channel_name);//
}
else
   throw new CacheException("Cache Channel not defined. name = " + cache_broadcast);

我才知道,那只是一种错觉,为什么不能完全解耦,透明切换?

修改建议:从Cache核心代码里面忘记Redis&Ehchche,完全不要出现任意一种具体的缓存的名字和相关类。

结论

看到这里的时候,基本上感觉距离成熟还有一段距离,继续努力!

纳尼,居然要夸两句?!好吧,还是要夸的,那就夸几句:

1、感觉红薯还是发挥稳定的,灰常稳定,几年以来代码质量水平非常稳定!!

2、对新的JDK特性了解非常好,充分使用了在接口中实现通用method的方法

3、成功的从V1进化到V2,版本上有巨大越变

4、一如既往的帅,这方面我望尘莫及啊

备注:由于时间和水平的关系,槽点数量和质量肯定有遗漏和不足之处,希望其他Oscer们补充。

本人开源的tinyscript已经成熟,感兴趣的同学请移步查看

 

© 著作权归作者所有

共有 人打赏支持
悠悠然然

悠悠然然

粉丝 2373
博文 184
码字总数 360373
作品 14
杭州
架构师
加载中

评论(70)

Hello_Maybe
Hello_Maybe
好用就行
雷兽

引用来自“雷兽”的评论

红薯的测试命令类 没毛病 这是运维命令 单元测试那是程序员角度思想

看悠然的文章内容 就是码农 高级点的。。。嘿嘿嘿 好像 不是架构、项目运营级别的思想哦 嘿嘿嘿

j2cache是基础运维组件 不是业务代码库 由少数人开发 测试 发布 本来就不一定要坚守业务开发那种项目框架结构吧 哈哈哈哈

引用来自“悠悠然然”的评论

哈哈,一下就被你猜中了,厉害~~~果然高级,一看就是CEO级别。
btw,测试命令类你以为我看不懂啊?问题是你每次都靠这东东来验证正确性吗?
你怎么保证别人提交pr的时候是OK的?每次都是执行这个命令类吗?
所以红薯写这个类是没有毛病的,但是测试用例在哪里?!
凡是没有测试用例的框架都是耍流氓。
我没具体看代码 我只是想说 可能那是运维测试工具

你在说的是红薯没有放测试用例

关我啥事。。。。。。

这根本就是两件事情 你吐槽不着我
悠悠然然
悠悠然然

引用来自“乌龟壳”的评论

引用来自“悠悠然然”的评论

引用来自“黑狗”的评论

除了main方法胡乱点评意外 其他都在理!

回复@黑狗 : 当你做过外资银行的项目你就知道了,你以为没有道理是因为你碰到得事情还不够多
想听你说下单元测试放在main函数里有什么问题?你的这篇博客里写得太简单,没交代原因只是旁敲侧击说明了下。

回复@乌龟壳 : 其实我已经说得很清楚了。
乌龟壳
乌龟壳

引用来自“悠悠然然”的评论

引用来自“黑狗”的评论

除了main方法胡乱点评意外 其他都在理!

回复@黑狗 : 当你做过外资银行的项目你就知道了,你以为没有道理是因为你碰到得事情还不够多
想听你说下单元测试放在main函数里有什么问题?你的这篇博客里写得太简单,没交代原因只是旁敲侧击说明了下。
蓝风970655147
蓝风970655147
哦哟, mark 下, 周末看看这个版本
悠悠然然
悠悠然然

引用来自“开源中国首席卡牌中单”的评论

引用来自“悠悠然然”的评论

引用来自“雷兽”的评论

红薯的测试命令类 没毛病 这是运维命令 单元测试那是程序员角度思想

看悠然的文章内容 就是码农 高级点的。。。嘿嘿嘿 好像 不是架构、项目运营级别的思想哦 嘿嘿嘿

j2cache是基础运维组件 不是业务代码库 由少数人开发 测试 发布 本来就不一定要坚守业务开发那种项目框架结构吧 哈哈哈哈
哈哈,一下就被你猜中了,厉害~~~果然高级,一看就是CEO级别。
btw,测试命令类你以为我看不懂啊?问题是你每次都靠这东东来验证正确性吗?
你怎么保证别人提交pr的时候是OK的?每次都是执行这个命令类吗?
所以红薯写这个类是没有毛病的,但是测试用例在哪里?!
凡是没有测试用例的框架都是耍流氓。

回复@悠悠然然 : 你们每次修改都建立分支的吗?

回复@开源中国首席卡牌中单 : Release版BUG修订需要建分支,正在开发期的不用
开源中国首席罗纳尔多
开源中国首席罗纳尔多

引用来自“悠悠然然”的评论

引用来自“雷兽”的评论

红薯的测试命令类 没毛病 这是运维命令 单元测试那是程序员角度思想

看悠然的文章内容 就是码农 高级点的。。。嘿嘿嘿 好像 不是架构、项目运营级别的思想哦 嘿嘿嘿

j2cache是基础运维组件 不是业务代码库 由少数人开发 测试 发布 本来就不一定要坚守业务开发那种项目框架结构吧 哈哈哈哈
哈哈,一下就被你猜中了,厉害~~~果然高级,一看就是CEO级别。
btw,测试命令类你以为我看不懂啊?问题是你每次都靠这东东来验证正确性吗?
你怎么保证别人提交pr的时候是OK的?每次都是执行这个命令类吗?
所以红薯写这个类是没有毛病的,但是测试用例在哪里?!
凡是没有测试用例的框架都是耍流氓。

回复@悠悠然然 : 你们每次修改都建立分支的吗?
悠悠然然
悠悠然然

引用来自“雷兽”的评论

红薯的测试命令类 没毛病 这是运维命令 单元测试那是程序员角度思想

看悠然的文章内容 就是码农 高级点的。。。嘿嘿嘿 好像 不是架构、项目运营级别的思想哦 嘿嘿嘿

j2cache是基础运维组件 不是业务代码库 由少数人开发 测试 发布 本来就不一定要坚守业务开发那种项目框架结构吧 哈哈哈哈
哈哈,一下就被你猜中了,厉害~~~果然高级,一看就是CEO级别。
btw,测试命令类你以为我看不懂啊?问题是你每次都靠这东东来验证正确性吗?
你怎么保证别人提交pr的时候是OK的?每次都是执行这个命令类吗?
所以红薯写这个类是没有毛病的,但是测试用例在哪里?!
凡是没有测试用例的框架都是耍流氓。
雷兽
红薯的测试命令类 没毛病 这是运维命令 单元测试那是程序员角度思想

看悠然的文章内容 就是码农 高级点的。。。嘿嘿嘿 好像 不是架构、项目运营级别的思想哦 嘿嘿嘿

j2cache是基础运维组件 不是业务代码库 由少数人开发 测试 发布 本来就不一定要坚守业务开发那种项目框架结构吧 哈哈哈哈
zzuqiang
zzuqiang
这次内裤没扒的那么彻底
J2Cache 2.3.19 性能提升 30%,这不是 Bugfix 版本

这个版本你们没有槽点可喷了吧,因为没有 Bug 了!!! J2Cache 2.3.19 带来了部分性能的提升达 30% ,而且进一步降低对 Redis 请求的压力。 纳尼?你说我吹牛逼?下面说说详情! 假设有 10...

红薯
05/23
0
44
关于J2cache ...

刚刚开始接触红薯大大的J2cache,在此感谢! 请教大家关于j2cache的一些问题: 1. j2cache的优缺点是什么呢? 2.它适用于什么场景,该怎样去用它? 在此拜谢诸位英雄好汉!谢谢!!...

磁爆步兵001
06/01
0
0
J2Cache 新增 Mybatis 支持模块,代码少到没 Bug

花了点时间撸了个 MyBatis 的 J2Cache 支持模块,含注释共八十多行代码 (J2CacheAdapter.java),再有 Bug 我就真的要退役了。 使用方法很简单,请看 https://gitee.com/ld/J2Cache/tree/mast...

红薯
05/15
0
30
J2Cache 2.3.17 发布,有 Bug 吐槽,不更新也吐槽

用 J2Cache 的开发者太多了,以至于 Bug 都被第一时间给你挑出来,所以直接导致每次发布完新版本紧接着又要发一个补丁版本。这就是人气啊! J2Cache 最新 bugfix 版本又来了,咋地,你还能打...

红薯
05/18
0
6
j2cache居然不支持集群的redis?

@红薯 是不是j2cache不支持集群模式的reids,我的redis是集群部署的,然后我看j2cache客户端好像用的是jedisclient,报异常redis.clients.jedis.exceptions.JedisMovedDataException : MOVED ...

潘meallon
07/10
0
0
J2Cache 2.3.14 红薯欲哭无泪版发布,紧急修复 Bug

重要!!! 请不要使用 2.3.13 和 2.3.14 版本,2.3.15 版本已经提交到 Maven 中央库!!! 我检讨,我反省,我犯了一个愚蠢的错误!!! J2Cache 2.3.13 版本发布时,脑袋被驴踢了,删掉了 ...

红薯
05/03
0
33
J2Cache 2.3.22 发布,又发现 Bug 建议更新

J2Cache 有日子没更新了,作为史上第一个两级 Java 缓存框架,也是最棒的两级 Java 缓存框架(我就违反广告法了,你能把我咋地),Bug 是不容许存在滴! 所以无聊的时候我增加了一些单元测试...

红薯
07/03
0
1
飞特商城后台管理系统引入开源中国二级缓存 J2Cache

2018已过半,向着目标与飞特一起加油 缓存是后台系统中必不可少的组件,灵活的缓存配置,可以使我们开发,运维变的更简单。这次我们整合了J2Cache ,它是 OSChina 目前正在使用的两级缓存框架...

18356087258
06/30
0
0
J2Cache 2.3.15 红薯泣血版发布,一个错误两个版本修复

唉,还能说什么呢?一个严重的错误需要两个版本来修复它!!! 由于被公司禁止写代码,搞得我有一天手痒难忍,没事就改了改 Command 类的代码,删除了一些 IDEA 说没用的方法,包括构造函数和...

红薯
05/04
0
1
J2Cache 2.3.16 悄悄发布第三个 Bug 修复版本

实在无颜见江东父老啊,只好选择在星期天大家都在陪着男朋友玩耍的时候再次发布第三个 Bug 修复版本。 J2Cache 2.3.16 版本修复了当一级缓存使用 ehcache 或者 ehcache3 的异常: 修复了 Eh...

红薯
05/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring+jpaNo transactional EntityManager available

TransactionRequiredException: No transactional EntityManager availableEntityManager执行以下方法(refresh, persist, flush, joinTransaction, remove, merge) 都需要需要事务i......

wpfc
刚刚
0
0
八幅漫画理解使用JSON Web Token设计单点登录系统

八幅漫画理解使用JSON Web Token设计单点登录系统 Sep 07, 2015 in Engineering 上次在《JSON Web Token - 在Web应用间安全地传递信息》中我提到了JSON Web Token可以用来设计单点登录系统。...

祖冲之
2分钟前
0
0
Spring框架中的设计模式(三)

Spring框架中的设计模式(三) 原创: 瑞查德-Jack 在之前的两篇文章中,我们看到了一些在Spring框架中实现的设计模式。这一次我们会发现这个流行框架使用的3种新模式。 本文将从描述两个创意...

瑞查德-Jack
5分钟前
0
0
[MicroPython]TPYBoard智能小车“飞奔的TPYBoard装甲一号”

智能小车作为现代的新发明,是以后的发展方向,他可以按照预先设定的模式在一个环境里自动的运作,不需要人为的管理,可应用于科学勘探等等的用途。智能小车能够实时显示时间、速度、里程,具...

bodasisiter
7分钟前
0
0
桌面虚拟化VDI(Virtual Desktop Infrastructure)

为了保证员工(客户)不把公司的资料复制、传输给别人。可以把员工平时办公放在服务器上做。所以使用桌面虚拟化。就是把一个服务器虚拟出很多桌面系统(如:windows)。 桌面虚拟化最大的优势...

王坤charlie
15分钟前
2
0
自我审视及职业规划

啊哈,不知不觉已经工作了3年了。程序员作为一门技术工作,如果分级的话我的能力如何呢?该怎么提升呢? 话说,我现在的能力属于中低级的层次吧,努力在向高级努力。为什么这么说呢: 因为我觉...

一口今心
17分钟前
1
0
《PHP和MySQL Web 开发》 第12章 MySQL高级管理

我决定好好写学习笔记了,对应上书上的目录和重要信息。不瞎jb写了。从这章开始吧,然后之前写的会编辑后重发。嗯,就酱。 12.1 深入理解权限系统 妈蛋 开头就卡住了。。。我先回去修改之前的...

十万猛虎下画山
18分钟前
1
0
Python 3.6:多态的实现

多态的作用不用多说,C++用如下条件来实现多态: 要有继承 要有虚函数函数重写 要有父类指针(父类引用)指向子类对象 实际上C++使用VPTR指针来完成这个事情,其是设计模式的基础,软件分层的基...

全部原谅
18分钟前
0
0
纯Python实现鸢尾属植物数据集神经网络模型[图]

纯Python实现鸢尾属植物数据集神经网络模型[图]: 尝试使用过各大公司推出的植物识别APP吗?比如微软识花、花伴侣等这些APP。当你看到一朵不知道学名的花时,只需要打开植物识别APP,拍摄一张...

原创小博客
20分钟前
1
0
2018安卓巴士开发者大会打造Android技术盛宴

2018安卓巴士开发者大会打造Android技术盛宴2018安卓巴士开发者大会将于8月25日在上海举行,作为中国最具前沿性、专业性的安卓技术会议,将邀请来自爱奇艺、阿里、饿了么等知名企业的一线工程...

逆鳞龙
22分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部