[DSL]模式匹配与请求跳转

具体上次撰写博客有一段时间了。这段时间内自己学些了很多,想了很多,尝试去理解了很多。结果之一是不管这个博客是为了什么而建立的,我还是把自己的技术思考记录下来。

本文描述是自己在工作中实现的一种DSL。DSL是个人今天年初左右才决定的发展方向,只是在具体工作中使用还是第一次。希望这可以作为自己在技术上选择性发展的一个好的开端。
由于是工作中开发出来的一种DSL,所以不会讲太具体的业务场景,而是以技术设计与实现为主。
本DSL的设计目的的核心如题,模式匹配和请求跳转。结合起来就是按照某种业务规则以模式匹配的方式决定请求是否跳转。更直接的一种表达方式是if else决定是否要redirect,只是这段if else是用DSL定义的。
使用DSL定义规则的好处在于更清晰地展现跳转的条件,避免技术实现给业务规则辨识带来的”噪音”,特别是复杂的跳转规则。其次是快速支持规则的变化,比如易变(不管是运行时易变,还是需求期易变)的规则,附带的另外一个好处是如果业务上需要动态定义的话,DSL可以快速支持,不再需要通过数据库设计,配置等传统方式。

Read More

[Java]运行时动态改变日志级别

其实这不是什么神奇的trick,只是很多人包括我在一直以来使用Java的日志框架比如log4j时没有意识到可以动态改变日志级别。如果你看到别人这么写了的话,很快就会转变观念的,我也是。

https://github.com/xnnyygn/dynamic-log-level 这个github是我整理的log4j动态改变日志级别的代码以及测试,有兴趣的可以参考下。

个人觉得这个trick可以用的地方还是程序员给自己开“后门”,特别是查线上问题时。由于很多人打印日志的级别的convention不一致。比如我喜欢非常详细的输入参数和输出结果用DEBUG,但是有些人就喜欢打INFO。一些复杂的逻辑有些人打了十几八行的INFO级别日志,看得我心烦,这帮人打INFO就像喝水一样……所以有些时候临时改变日志级别可能是有用的。不过从开发上来说,没有很好地统一日志级别规范,没有重视CR,是导致这个问题的主因,但是作为程序员要给自己留一手,比如动态改变日志级别之类的。

Read More

[Java]简单的延迟初始化实现

本篇文章本来打算在上个月下半旬写的,不过个人状态一直都不太好,最近重新开始调整自己的技术心态,慢慢恢复,这篇也算是恢复中的一小步吧。

延迟初始化是我在上个月公司的一个项目中加入的一个技术,感觉小组对这种东西不感兴趣,所以还是放到自己的博客上来了。技术背景是业务对象是一个非常大的对象(胖领域模型),每次加载非常耗时,而且因为部分非关键服务的不稳定导致不需要这些服务数据的功能不可用。举个例子,导航页不需要用户的B信息,但是每次加载用户信息由于是在服务层(是的,传统的分层结构)加载的,无法直接控制加载的内容,所以导致在B服务失败之后,导航页不可用。

从技术角度来说,领域模型完全是保证业务执行的必要条件,但是实际情况并不是所有场景都需要这么严格的领域模型完整性的保证的,所以类似“降级”的处理方式应由而生。具体来说就是“按需加载”。实现“按需加载”的方式不仅仅只有延迟初始化一种,通过服务的参数显示地控制加载的内容也是一种方式,不过存在侵入性和严格的规约,对开发来说并不是那么方便。其实“按需加载”不是只在特定业务场景才有的需求,在ORM上,加载关联数据也是一种典型的“按需加载”。所以亦可以参考ORM在“按需加载”方面的实现。

在讲我的简化版延迟初始化之前,先大致讲下Hibernate这个ORM在按需加载上的处理。Hibernate主要支持one-to-one和one-to-many下的按需加载,Hibernate 3开始支持部分字段的按需加载(CLOB和BLOB不算在内,3之前就有支持)。实现上,部分字段的加载需要bytecode替换,one-to-many是通过改写集合的处理,one-to-one是通过代理对象,具体来说是CGLIB,因为JDK动态代理对象只支持接口。

了解这些对于我的实现有所帮助,不过除了one-to-many很快就能模仿写之外,部分字段的延迟初始化和one-to-one的处理都比较麻烦。one-to-one在查到结果为null时会比较麻烦,从调用上看应该是代理整个领域模型而不是单个延迟加载的对象,这块个人没有细究,因为我后来想想我不需要非常严格的模型字段规约,小小地修改模型理论上也不会有太大问题。而且部分字段的延迟初始化不是类似单个延迟初始化对象就可以解决的。

Read More

scala99解题小结(List)

一个月之前,我把之前知道的scala99除了最后两题都做了下。总体来说自己用Scala来解决一些算法问题上有了一些感觉。

scala99的问题分为List,Arithmetic,Logic,Binary Tree,Multiway Tree,Graph和Misc。树和图和之后的问题和算法关系大一些。以下列一些影像比较深的题目。

本次先是List相关。

Read More

用DLX解sudoku(数独)

最近在做scala99,其中有一道题目P97是sudoku(数独)。一开始我想到的是列举每个空格的可选数字,选择可选数字最少的的格子开始填写。每次填写,修改关联格子的可选数字。再次尝试填写。这里无解条件是存在没有可选数字的格子。还有就是easy或者normal级别的数独一般可选数字都是1个,分批填写很快就能完成。hard或以上就没有那么幸运了,必须猜测然后验证,存在回溯。

这里描述的算法其实就是搜索+启发。启发是选择性地从最少可选数的格子开始。猜测+验证,感觉这个问题属于NP问题。事实上也确实是,而且可以转化为NP完全的精确覆盖问题(Exact Cover),所以这个问题也是NP完全问题。

P97给的答案有两个,第一个就是搜索+启发,第二个是DLX。DLX是Exact Cover的高效解法。本文就是讲如何用DLX来解数独问题的。考虑到scala99上第二个实现大部分都是可变数据,所以我用Java实现了相应算法。

Read More

finagle简单使用

在看awseome-scala的时候,正好看到了twitter的finagle。自己公司里貌似也有那种关注load balance等的解决方案,不过不是很容易理解。考虑到自己之前几个月都在弄电子技术了,重新弄点网络相关的把。

这次的任务是做了一个thrift+finagle的远程服务调用例子。其实不是很难,如果不是连续碰到finagle的坑的话。finagle是twitter开源出来的一个分布式系统解决方案,毕竟是大公司出来的东西,更新频率特别是文档很低,很多文档基本都是几年前,好在有代码……

Read More

rabbitmq在scala下的使用尝试

最近重拾scala,由于某些原因想要尝试了rabbitmq。于是便有了这块代码
刚才重新看了rabbitmq的官网,上面关于scala的客户端的信息貌似更新了?之前那个lift-amqp太旧了,没法使用。不过没关系,这篇就当做了记录下如何在scala的环境下用rabbitmq的Java客户端。如果你想直接用现成的scala客户端,可以参考这里

首先你要安装rabbitmq,这样之后好测试。mac下用brew安装命令是

Read More

[Rails]壁纸推荐网站

简单来说就是一次ITEM CF的尝试。不过壁纸本身的管理也花了不少时间,ITEM CF是最后才做的……

源代码在这里 https://github.com/xnnyygn/get-wallpaper

screenshot-index-2014-12-03

上面第一行是推荐,第二行是最新的,第三行是热度最高的。
所谓ITEM CF推荐就是根据人得到相似的物品,然后推荐给你。
热度最高是按照下载次数来的。
这些都是在网站日常操作中得到数据,然后通过推荐计算得到的。

Read More