from : http://zingson.com/72.html弊端是,没有人还记得面向对象原本要解决的问题是什么。1、面向对象原本要解决什么?(或者说有什么优良特性)似乎很简单,但实际又很不简单:面向对象三要素封装、继承、多态。(警告:事实上,从业界如此总结出这面向对象三要素的一刹那开始,就已经开始犯错了!)。封装:封装的意义,在于明确标识出会访问某个数据结构(用面向对象的术语来说就是 类成员变量)的所有接口。有了封装,就可以明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者;而外部调用者也可以知道自己不可以碰哪里。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。继承+多态:继承和多态必须一起说。一旦割裂,就说明理解上已经误入歧途了。先说继承:继承同时具有两种含义:其一是继承基类的方法,并做出自己的扩展——号称解决了代码重用问题;其二是声明某个子类兼容于某基类(或者说,接口上完全兼容于基类),外部调用者可无需关注其差别。再说多态:基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。很显然,多态实际上是依附于继承的第二种含义的。让它与封装、继承这两个概念并列,是不符合逻辑的。不假思索的就把它们当作可并列概念使用的人,显然是从一开始就被误导了。实践中,继承的第一种含义(实现继承)意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。继承的第二种含义非常重要。它又叫“接口继承”。接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。归一化使得外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,如果你需要,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。归一化的实例:a、一切对象都可以序列化/toStringb、一切UI对象都是个window,都可以响应窗口事件。——必须注意,是一切(符合xx条件的)对象皆可以做什么,而不是“一切皆对象”。后者毫无意义。显然,归一化可以大大简化使用者的处理逻辑:这和带兵打仗是类似的,班长需要知道每个战士的姓名/性格/特长,否则就不知道该派谁去对付对面山坡上的狙击手;而连长呢,只需知道自己手下哪个班/排擅长什么就行了,然后安排他们各自去守一段战线;到了师长/军长那里,他更关注战场形势的转变及预期……没有这种层层简化、而是必须直接指挥到每个人的话,累死军长都没法指挥哪怕只是一场形势明朗的冲突——光一个个打完电话就能把他累成哑巴。软件设计同样。比如说,消息循环在派发消息时,只需知道所有UI对象都是个window,都可以响应窗口消息就足够了;它没必要知道每个UI对象究竟是什么——该对象自己知道收到消息该怎么做。合理划分功能层级、适时砍掉不必要的繁杂信息,一层层向上提供简洁却又完备的信息/接口,高层模块才不会被累死——KISS是最难也是最优的软件设计方法,没有之一。总结:面向对象的好处实际就这么两点。一是通过封装明确定义了何谓接口、何谓接口内部实现、何谓接口的外部调用者,使得大家各司其职,不得越界;二是通过继承+多态这种内置机制,在语言的层面支持归一化的设计,并使得内行可以从代码本身看到这个设计——但,注意仅仅只是支持归一化的设计。不懂如何做出这种设计的外行仍然不可能从瞎胡闹的设计中得到任何好处。显然,不用面向对象语言、不用class,一样可以做归一化的设计(如老掉牙的泛文件概念、游戏行业的一切皆精灵),一样可以封装(通过定义模块和接口),只是用面向对象语言可以直接用语言元素显式声明这些而已;而用了面向对象语言,满篇都是class,并不等于就有了归一化的设计。甚至,因为被这些花哨的东西迷惑,反而更加不知道什么才是设计。2、人们以为面向对象是什么、以及因此制造出的悲剧以及闹剧误解一、面向对象语言支持用语言元素直接声明封装性和接口兼容性,所以用面向对象语言写出来的东西一定更清晰、易懂。事实上,既然class意味着声明了封装、继承意味着声明了接口兼容,那么错误的类设计显然就是错误的声明、盲目定义的类就是无意义的喋喋不休。而错误的声明比没有声明更糟;通篇毫无意义的喋喋不休还不如错误的声明。除非你真正做出了漂亮的设计,然后用面向对象的语法把这个设计声明出来——仅仅声明真正有设计、真正需要人们注意的地方,而不是到处瞎叫唤——否则不可能得到任何好处。一切皆对象实质上是在鼓励堆砌毫无意义的喋喋不休。大部分人——注意,不是个别人——甚至被这种无意义的喋喋不休搞出了神经质,以至于非要在喋喋不休中找出意义:没错,我说的就是设计模式驱动编程,以及如此理解面向对象编程。误解二、面向对象三要素是封装、继承、多态,所以只要是面向对象语言写的程序,就一定“继承”了语言的这三个优良特性。事实上,如前所述,封装、继承、多态只是语言层面对良好设计的支持,并不能导向良好的设计。如果你的设计做不出真正的封装性、不懂得何谓归一化,那它用什么写出来都是垃圾。误解三、把软件写成面向对象的至少是无害的。要了解事实上是什么,需要先科普几个概念。什么是真正的封装?——回答我,封装是不是等于“把不想让别人看到、以后可能修改的东西用private隐藏起来”?显然不是。如果功能得不到满足、或者未曾预料到真正发生的需求变更,那么你怎么把一个成员变量/函数放到private里面的,将来就必须怎么把它挪出来。你越瞎搞,越去搞某些华而不实的“灵活性”——比如某种设计模式——真正的需求来临时,你要动的地方就越多。真正的封装是,经过深入的思考,做出良好的抽象,给出“完整且最小”的接口,并使得内部细节可以对外透明(注意:对外透明的意思是,外部调用者可以顺利的得到自己想要的任何功能,完全意识不到内部细节的存在;而不是外部调用者为了完成某个功能、却被碍手碍脚的private声明弄得火冒三丈;最终只能通过怪异、复杂甚至奇葩的机制,才能更改他必须关注的细节——而且这种访问往往被实现的如此复杂,以至于稍不注意就会酿成大祸)。一个设计,只有达到了这个高度,才能真正做到所谓的“封装性”,才能真正杜绝对内部细节的访问。否则,生硬放进private里面的东西,最后还得生硬的被拖出来——当然,这种东西经常会被美化成“访问函数”之类渣渣(不是说访问函数是渣渣,而是说因为设计不良、不得不以访问函数之类玩意儿在封装上到处挖洞洞这种行为是渣渣)。一个典型的例子,就是C++的new和过于灵活的内存使用方式之间的耦合。这个耦合就导致了new[]/delete[]、placement new/placement delete之类怪异的东西:这些东西必须成对使用,怎么分配就必须怎么释放,任何错误搭配都可能导致程序崩溃——这是为了兼容C、以及得到更高执行效率的无奈之举;但,它更是“抽象层次过于复杂,以至于无法做出真正透明的设计”的典型案例:只能说,c++设计者是真正的大师,如此复杂的东西在他手里,才仅仅付出了如此之小的代价。(更准确点说,是new/delete和c++的其它语言元素之间是非正交的;于是当同时使用这些语言元素时,就不可避免的出现了彼此扯淡的现象。即new/delete这个操作对其它语言元素非透明:在c++的设计里,是通过把new/delete分成两层,一是内存分配、二是在分配的内存上初始化,然后暴露这个分层细节,从而在最大程度上实现了封装——但比之其它真正能彼此透明的语言元素间的关系,new/delete显然过于复杂了)。这个案例,可以非常直观的说明“设计出真正对外透明的封装”究竟会有多难。接口继承真正的好处是什么?是用了继承就显得比较高大上吗?显然不是。接口继承没有任何好处。它只是声明某些对象在某些场景下,可以用归一化的方式处理而已。换句话说,如果不存在“需要不加区分的处理类似的一系列对象”的场合,那么继承不过是在装X罢了。封装可应付需求变更、归一化可简化(类的使用者的)设计:以上,就是面向对象最最基本的好处。——其它一切,都不过是在这两个基础上的衍生而已。换言之,如果得不到这两个基本好处,那么也就没有任何衍生好处——应付需求变更/简化设计并不是打打嘴炮就能做到的。了解了如上两点,那么,很显然:1、如果你没有做出好的抽象、甚至完全不知道需要做好的抽象就忙着去“封装”,那么你只是在“封”和“装”而已。这种“封”和“装”的行为只会制造累赘和虚假的承诺;这些累赘以及必然会变卦的承诺,必然会为未来的维护带来更多的麻烦,甚至拖垮整个项目。正是这种累赘和虚假的承诺的拖累,而不是所谓的为了应付“需求改变”所必需的“灵活性”,才是大多数面向对象项目代码量暴增的元凶。2、没有真正的抓到一类事物(在当前应用场景下)的根本,就去设计继承结构,是必不会有所得的。不仅如此,请注意我强调了在当前应用场景下。这是因为,分类是一个极其主观的东西,不存在普适的分类法。举例来说,我要研究种族歧视,那么必然以肤色分类;换到法医学,那就按死因分类;生物学呢,则搞门科目属种…… 想象下,需求是“时尚女装”,你却按“窒息死亡/溺水死亡/中毒死亡之体征”来了个分类……你说后面这软件还能写吗?类似的,我遇到过写游戏的却去纠结“武器装备该不该从游戏角色继承”的神人。你觉得呢?事实上,游戏界真正的抽象方法之一是:一切都是个有位置能感受时间流逝的精灵;而某个“感受到时间流逝显示不同图片的对象”,其实就是游戏主角;而“当收到碰撞事件时,改变主角下一轮显示的图片组的”,就是游戏逻辑。看看它和“武器装备该不该从游戏角色继承”能差多远。想想到得后来,以游戏角色为基类的方案会变成什么样子?为什么会这样?——你还敢说面向对象无害吗?——在真正明白何谓封装、何谓归一化之前,每一次写下class,就在错误的道路上又多走了一步。——设计真正需要关注的核心其实很简单,就是封装和归一化。一个项目开始的时候,“class”写的越早,就离这个核心越远。——过去鼓吹的各种面向对象方法论、甚至某些语言本身,恰恰正是在怂恿甚至逼迫开发者尽可能早、尽可能多的写class。误解四、只有面向对象语言写的程序才是面向对象的。事实上,unix系统提出泛文件概念时,面向对象语言根本就不存在;游戏界的精灵这个基础抽象,最初是用C甚至汇编写的;……。面向对象其实是汲取以上各种成功设计的经验才提出来的。所以,面向对象的设计,不必非要c++/java之类支持面向对象的语言才能实现;它们不过是在你做出了面向对象的设计之后,能让你写得更惬意一些罢了——但,如果一个项目无需或无法做出面向对象的设计,某些面向对象语言反而会让你很难受。用面向对象语言写程序,和一个程序的设计是面向对象的,两者是八杆子打不着的两码事。纯C写的linux kernel事实上比c++/java之类语言搞出来的大多数项目更加面向对象——只是绝大部分人都自以为自己到处瞎写class的面条代码才是面向对象的正统、而死脑筋的linus搞的泛文件抽象不过是过程式思维搞出来的老古董。——这个误解之深,甚至达到连wiki词条里面,都把OOP定义为“用支持面向对象的语言写程序”的程度。——恐怕这也是没有人说泛文件设计思想是个骗局、而面向对象却被业界大牛们严厉抨击的根本原因了:真正的封装、归一化精髓被抛弃,浮于表面的、喋喋不休的class/设计模式却成了”正统“!总结: 面向对象其实是对过去成功的设计经验的总结。但那些成功的设计,不是因为用了封装/归一化而成功,而是切合自己面对的问题,给出了恰到好处的设计。让一个初学者知道自己应该向封装/归一化这个方向前进,是好的;用一个面向对象的条条框框把他们框在里面、甚至使得他们以为写下class是完全无需思索的、真正应该追求的是设计模式,则是罪恶的。事实上,class写的越随意,才越需要设计模式;就着错误的实现写得越多、特性用得越多,它就越发的死板,以至于必须更加多得多的特性、模式、甚至语法hack,才能勉强完成需求。只有经过真正的深思熟虑,才有可能做到KISS。到处鼓噪的面向对象编程的最大弊端,是把软件设计工作偷换概念,变成了“就着class及相关教条瞎胡闹,不管有没有好处先插一杠子”,甚至使得人们忘记去关注“抽象是否真正简化了面对的问题”。
从@蔡学镛看到的数据库的一些设计原则,可以考虑考虑.梳理数据库时,你会很惊讶地发现,各种数据都被塞进数据库,所以做数据库梳理的第一步是把它们区分出来,我的区分方式是:核心数据、业务数据、核心缓存数据、业务缓存数据、Session 数据。核心数据及其缓存都要再根据领域(domain)来区分,业务数据及其缓存都要再根据业务(business)来区分。梳理数据库或设计数据存储时,可以考虑数据的属性:1. 访问频率 (高/中/低)2. 读写比 (只读/读多/读少)3. 重要性 (重要/普通/不重要)4. 保密性 (保密/普通/不需保密)5. 数据笔数 (多/一般/少)6. 数据体积 (大/中/小)7. 一致性要求 (强/中/弱)8. 热点现象 (强/中/弱)9. 索引方式 ( ____ )
from: http://robbinfan.com/blog/38/orm-cache-sumupORM缓存引言从10年前的2003年开始,在Web应用领域,ORM(对象-关系映射)框架就开始逐渐普及,并且流行开来,其中最广为人知的就是Java的开源ORM框架Hibernate,后来Hibernate也成为了EJB3的实现框架;2005年以后,ORM开始普及到其他编程语言领域,其中最有名气的是Ruby on rails框架的ORM - ActiveRecord。如今各种开源框架的ORM,乃至ODM(对象-文档关系映射,用在访问NoSQLDB)层出不穷,功能都十分强大,也很普及。然而围绕ORM的性能问题,也一直有很多批评的声音。其实ORM的架构对插入缓存技术是非常容易的,我做的很多项目和产品,但凡使用ORM,缓存都是标配,性能都非常好。而且我发现业界使用ORM的案例都忽视了缓存的运用,或者说没有意识到ORM缓存可以带来巨大的性能提升。ORM缓存应用案例我们去年有一个老产品重写的项目,这个产品有超过10年历史了,数据库的数据量很大,多个表都是上千万条记录,最大的表记录达到了9000万条,Web访问的请求数每天有300万左右。老产品采用了传统的解决性能问题的方案:Web层采用了动态页面静态化技术,超过一定时间的文章生成静态HTML文件;对数据库进行分库分表,按年拆表。动态页面静态化和分库分表是应对大访问量和大数据量的常规手段,本身也有效。但它的缺点也很多,比方说增加了代码复杂度和维护难度,跨库运算的困难等等,这个产品的代码维护历来非常困难,导致bug很多。进行产品重写的时候,我们放弃了动态页面静态化,采用了纯动态网页;放弃了分库分表,直接操作千万级,乃至近亿条记录的大表进行SQL查询;也没有采取读写分离技术,全部查询都是在单台主数据库上进行;数据库访问全部使用ActiveRecord,进行了大量的ORM缓存。上线以后的效果非常好:单台MySQL数据库服务器CPU的IO Wait低于5%;用单台1U服务器2颗4核至强CPU已经可以轻松支持每天350万动态请求量;最重要的是,插入缓存并不需要代码增加多少复杂度,可维护性非常好。总之,采用ORM缓存是Web应用提升性能一种有效的思路,这种思路和传统的提升性能的解决方案有很大的不同,但它在很多应用场景(包括高度动态化的SNS类型应用)非常有效,而且不会显著增加代码复杂度,所以这也是我自己一直偏爱的方式。因此我一直很想写篇文章,结合示例代码介绍ORM缓存的编程技巧。今年春节前后,我开发自己的个人网站项目,有意识的大量使用了ORM缓存技巧。对一个没多少访问量的个人站点来说,有些过度设计了,但我也想借这个机会把常用的ORM缓存设计模式写成示例代码,提供给大家参考。我的个人网站源代码是开源的,托管在github上:robbin_siteORM缓存的基本理念我在2007年的时候写过一篇文章,分析ORM缓存的理念:ORM对象缓存探讨 ,所以这篇文章不展开详谈了,总结来说,ORM缓存的基本理念是:以减少数据库服务器磁盘IO为最终目的,而不是减少发送到数据库的SQL条数。实际上使用ORM,会显著增加SQL条数,有时候会成倍增加SQL。数据库schema设计的取向是尽量设计 细颗粒度 的表,表和表之间用外键关联,颗粒度越细,缓存对象的单位越小,缓存的应用场景越广泛尽量避免多表关联查询,尽量拆成多个表单独的主键查询,尽量多制造 n + 1 条查询,不要害怕“臭名昭著”的 n + 1 问题,实际上 n + 1 才能有效利用ORM缓存利用表关联实现透明的对象缓存在设计数据库的schema的时候,设计多个细颗粒度的表,用外键关联起来。当通过ORM访问关联对象的时候,ORM框架会将关联对象的访问转化成用主键查询关联表,发送 n + 1条SQL。而基于主键的查询可以直接利用对象缓存。我们自己开发了一个基于ActiveRecord封装的对象缓存框架:second_level_cache ,从这个ruby插件的名称就可以看出,实现借鉴了Hibernate的二级缓存实现。这个对象缓存的配置和使用,可以看我写的ActiveRecord对象缓存配置 。下面用一个实际例子来演示一下对象缓存起到的作用:访问我个人站点的首页。 这个页面的数据需要读取三张表:blogs表获取文章信息,blog_contents表获取文章内容,accounts表获取作者信息。三张表的model定义片段如下,完整代码请看models :class Account < ActiveRecord::Base acts_as_cached has_many :blogsendclass Blog < ActiveRecord::Base acts_as_cached belongs_to :blog_content, :dependent => :destroy belongs_to :account, :counter_cache => trueendclass BlogContent < ActiveRecord::Base acts_as_cachedend传统的做法是发送一条三表关联的查询语句,类似这样的:SELECT blogs.*, blog_contents.content, account.name FROM blogs LEFT JOIN blog_contents ON blogs.blog_content_id = blog_contents.id LEFT JOIN accounts ON blogs.account_id = account.id往往单条SQL语句就搞定了,但是复杂SQL的带来的表扫描范围可能比较大,造成的数据库服务器磁盘IO会高很多,数据库实际IO负载往往无法得到有效缓解。我的做法如下,完整代码请看home.rb :@blogs = Blog.order('id DESC').page(params[:page])这是一条分页查询,实际发送的SQL如下:SELECT * FROM blogs ORDER BY id DESC LIMIT 20转成了单表查询,磁盘IO会小很多。至于文章内容,则是通过blog.content的对象访问获得的,由于首页抓取20篇文章,所以实际上会多出来20条主键查询SQL访问blog_contents表。就像下面这样:DEBUG - BlogContent Load (0.3ms) SELECT `blog_contents`.* FROM `blog_contents` WHERE `blog_contents`.`id` = 29 LIMIT 1DEBUG - BlogContent Load (0.2ms) SELECT `blog_contents`.*…
一篇很不错的进行加密的文章!from: http://www.oschina.net/news/52976/hashing-or-encrypt对于网站来说, 再没有什么比用户信息泄露更让人尴尬的了。 尤其是当存有用户密码的文件如果被黑客获取, 对网站的安全和用户的信心来说都是巨大的打击。 如最近的Ebay泄密事件和小米的用户数据泄露事件。 保证用户信息安全首先需要正确理解对于用户密码的安全控制和保护。 这里OWASP的主席Michael Coates最近的一篇关于一些基本概念的介绍能够帮助开发人员更好的理解现代Hashing算法和加密对于用户密码保护的作用。 安全牛编译如下:在过去几个月, 我们看到了一些严重的数据泄露事件, Ebay和Adobe的数据泄露事件影响了几百万用户。 Snapchat也遭受到了数据泄露事件的影响。 每一次密码泄露事件后, 人们都会问同一个问题, 这些密码的存储是不是安全? 不幸的是, 这个看上去简单的问题其实并不好回答。尽管在很多情况下, Hashing和加密都能够满足安全存储的需要, 对于在线应用而言, 很多情况下, 对于用户密码的安全存储往往只有一种正确的方案。 Hashing.是通过一个不可逆的杂凑函数计算出一个Hash值, 而通过这个值无法逆向计算出输入值(比如用户密码)。 对称加密则是采用密钥进行加密计算, 这是一种可逆的运算。 任何人如果有了密钥, 就能够解密出原始明文。下表是Hashing和对称加密的对比Hashing对称加密不可逆函数可逆运算能够逆向算出初始值不能可以对于现代杂凑算法而言, 从Hash值逆向算出输入值非常困难。 参见下面关于彩虹表,盐化等的讨论对称加密就是设计来是的任何拥有密钥的人能够解密出原始明文其他需要考虑的方面杂凑算法的选择加密算法的选择对每个用户进行盐化保护密钥显示第 1 至 6 项结果,共 6 项当在线应用收到一个用户名和一个密码后, 就以密码为输入到杂凑函数中去得出一个Hash值, 然后用这个Hash值与数据库中存储的该用户的密码Hash值做比较, 如果两个Hash值相同, 就可以认为用户提供了有效的用户名和密码。 采用Hashing的好处是, 应用不需要存储用户的明文密码, 只需要存储Hash值。在线应用如何利用密码的Hash值来认证用户下图就是关于采用Hashing方式的简单描述:那么, 所有杂凑算法都能用吗? 不是的, 事实上, 杂凑算法中不同的算法的差别很大, 并不是所有的杂凑算法都适合存储密码。说起来可能有点出人预料, 早期的杂凑算法速度过快, 黑客们尽管不能通过Hash值逆向计算出原输入值, 但是黑客们可以通过暴力破解的方式遍历所有可能的密码组合来尝试能够能够“碰撞”到用户密码的Hash值。 为了避免这种威胁, 现代的杂凑算法能够通过多重迭代, 使得在每次Hash计算时产生一些延时, 对单次Hash计算, 这样的延时基本没有任何影响, 而对于黑客的暴力破解来说, 几百万次计算的延时能够被放大几百年, 这样到使得暴力破解基本不现实的地步。在Hashing中, 最好采用针对每个用户的盐化方式, 通过对用户密码添加一个随机字符串(随机字符串可以是显式存储), 这样可以相同的密码产生相同的Hash值, 这样, 攻击者可以下载一个巨大的存有事先计算好Hash值的查找表, 也叫做彩虹表。 通过Hash值, 反向查找对应的输入值。而通过下面两个表格可以看出, 通过对不同用户进行不同的盐化, 同样的密码就会出现不同的Hash值, 这样使得攻击者利用彩虹表进行攻击变得困难。没有盐化用户名密码Hash值Joepassword123xyfkdl323...Suepassword123xyfkdl323...**盐化后**用户名密码盐化字符串Hash值Joepassword12348a023jl2…ied390fl2...Suepassword1239fh3ls321…40akdl23…**类似于账户锁定的机制对于密码存储的模式有什么影响吗?**简单的回答, 就是, 没有影响。 对密码的安全存储是为了提供在密码文件被盗取后的防护。 黑客对于密码Hash的攻击是一种离线攻击。 也就是说, 密码文件已经被盗取, 黑客可以利用自己的计算机通过尝试不同的密码来找出密码。 由于是离线攻击, 账号锁定或者验证码之类的安全机制已经没有作用了。 这些机制只有在针对网站服务器的在线登录页面攻击时才会起作用。对于密码存储, 采用对称加密而不是Hashing的风险在哪里?对称加密的设计就是一个可逆的运算, 这意味着在线应用必须能够访问到密钥, 并且在每次密码验证时都要使用。 如果加密后的密码被窃取的话, 黑客需要获取对称加密的密钥, 而一旦密钥被破解出来, 不管是通过某种方式泄露出来, 或者一些弱的密钥被暴力方式破解出来, 所有的密码都会被黑客获得。总结对于密码的安全存储来说, 理解对称加密与Hashing的区别非常重要。 一些如PBKDF2, bcrypt以及scrypt等算法都采用的每用户盐化以及多重迭代的Hashing方式以安全存储密码。互联网已经日益成为重要的用户信息存储的场所。 网站开发人员及网站老板们需要尽其所能地保证用户信息的安全。 了解如何利用现代的Hashing算法对用户密码进行基本的安全控制保护非常重要。
GistBox 提供一种漂亮的方式来组织代码片段。将你的库保存到云端进行备份,再也不用担心丢失。GistBox采用标准的HTML5技术构建。GistBox使用GitHub的后端,但增加了自己的标签和搜索功能层。使用Github账号登陆Gistbox可以将你的代码直接同步进来,反过来,你在GB上的所有改动也都会同步到Github上;GistBox的结构设 计清晰,从左至右分别是主导航(新建Gist,Gists入口,收藏入口-Labels)、Gists列表(Public/Private)、具体代码 区,亲们可以用Label给代码加上各种分辨标签,方便分类整理,在检索代码时可以用顶部的搜索栏,输入关键词或Label可以更快的搜索到目标代码。网址: http://www.gistboxapp.com/
from: http://it.deepinmind.com/java/2014/05/21/better-java.htmlJava是最流行的编程语言之一,但似乎并没有人喜欢使用它。好吧,实际上Java是一门还不错的编程语言,由于最近Java 8发布了,我决定来编辑一个如何能更好地使用Java的列表,这里面包括一些库,实践技巧以及工具。这篇文章在GitHub上也有。你可以随时在上面贡献或者添加你自己的Java使用技巧或者最佳实践。编码风格结构体* builder模式依赖注入避免null值不可变避免过多的工具类格式* 文档Stream部署框架Maven* 依赖收敛持续集成Maven仓储配置管理库遗失的特性* Apache CommonsGuavaGsonJava TuplesJoda-TimeLombokPlay frameworkSLF4JjOOQ测试jUnit 4jMockAssertJ工具IntelliJ IDEA* ChrononJRebel校验框架Eclipse Memory Analyzer资源书籍播客编码风格传统的Java编码方式是非常啰嗦的企业级JavaBean的风格。新的风格更简洁准确,对眼睛也更好。结构体我们这些码农干的最简单的事情就是传递数据了。传统的方式就是定义一个JavaBean:public class DataHolder { private String data;public DataHolder() {}public void setData(String data) { this.data = data;}public String getData() { return this.data;}}这不仅拖沓而且浪费。尽管你的IDE可以自动地生成这个,但这还是浪费。因此,[不要这么写](http://www.javapractices.com/topic/TopicAction.do?Id=84)。相反的,我更喜欢C的结构体的风格,写出来的类只是包装数据:public class DataHolder { public final String data;public DataHolder(String data) { this.data = data;}}这样写减少了一半的代码。不仅如此,除非你继承它,不然这个类是不可变的,由于它是不可变的,因此推断它的值就简单多了。如果你存储的是Map或者List这些可以容易被修改的数据,你可以使用ImmutableMap或者ImmutableList,这个在不可变性这节中会有讨论。Builder模式如果你有一个相对复杂的对象,可以考虑下Builder模式。你在对象里边创建一个子类,用来构造你的这个对象。它使用的是可修改的状态,但一旦你调用了build方法,它会生成一个不可变对象。想象一下我们有一个非常复杂的对象DataHolder。它的构造器看起来应该是这样的:public class ComplicatedDataHolder { public final String data; public final int num; // lots more fields and a constructorpublic class Builder { private String data; private int num; public Builder data(String data) { this.data = data; return this; } public Builder num(int num) { this.num = num; return this; } public ComplicatedDataHolder build() { return new ComplicatedDataHolder(data, num); // etc }}}现在你可以使用它了:final ComplicatedDataHolder cdh = new ComplicatedDataHolder.Builder() .data("set this") .num(523) .build();关于Builder的使用[这里](http://en.deepinmind.com/blog/2014/05/21/the-builder-pattern-in-practice.html)还有些更好的例子,我这里举的例子只是想让你大概感受一下。当然这会产生许多我们希望避免的样板代码,不过好处就是你有了一个不可变对象以及一个连贯接口。依赖注入这更像是一个软件工程的章节而不是Java的,写出可测的软件的一个最佳方式就是使用依赖注入(Dependency injection,DI)。由于Java强烈鼓励使用面向对象设计 ,因此想写出可测性强的软件,你需要使用DI。在Java中,这个通常都是用Spring框架来完成的。它有一个基于XML配置的绑定方式,并且仍然相当流行。重要的一点是你不要因为它的基于XML的配置格式而过度使用它了。在XML中应该没有任何的逻辑和控制结构。它只应该是依赖注入。还有一个不错的方式是使用Dagger库以及Google的Guice。它们并没有使用Spring的XML配置文件的格式,而是将注入的逻辑放到了注解和代码里。避免null值如果有可能的话尽量避免使用null值。你可以返回一个空的集合,但不要返回null集合。如果你准备使用null的话,考虑一下@Nullable注解。IntelliJ IDEA对于@Nullable注解有内建的支持。如果你使用的是Java 8的话,可以考虑下新的Optional类型。如果一个值可能存在也可能不存在,把它封装到Optional类里面,就像这样:public class FooWidget { private final String data; private final Optional<Bar> bar;public FooWidget(String data) { this(data, Optional.empty());}public FooWidget(String data, Optional<Bar> bar) { this.data = data; this.bar = bar;}public Optional<Bar> getBar() {…
from: http://zhuanlan.zhihu.com/wooyun/19747591作者:园长 (@mm yz)攻击JavaWeb应用[1]-JavaEE 基础攻击JavaWeb应用[2]-CS交互安全攻击JavaWeb应用[3]-SQL注入[1]攻击JavaWeb应用[4]-SQL注入[2]攻击JavaWeb应用[5]-MVC安全攻击JavaWeb应用[6]-程序架构与代码审计攻击JavaWeb应用[7]-Server篇[1]攻击JavaWeb应用[8]-后门篇攻击JavaWeb应用[9]-Server篇[2]
Iconfont.cn是阿里巴巴推出的矢量图标库,其中涵盖了1000多个常用图标,并在持续更新中。(目前已有7000+图标,部分图标为用户上传,因此默认不公开,但是可以搜索到。) Iconfont提供以下功能:在线图标搜索图标分捡下载在线储存矢量格式转换图标库管理iconfont的优势自由变化大小(高清屏无压力)自由修改颜色(纯色)可以添加一些视觉效果如:阴影、旋转、透明度iconfont使用声明字体@font-face {font-family: ‘iconfont’;src: url(‘iconfont.eot’); /* IE9*/src: url(‘iconfont.eot?#iefix’) format(‘embedded-opentype’), /* IE6-IE8 /url(‘iconfont.woff’) format(‘woff’), / chrome、firefox /url(‘iconfont.ttf’) format(‘truetype’), / chrome、firefox、opera、Safari, Android, iOS 4.2+/url(‘iconfont.svg#iconfont’) format(‘svg’); / iOS 4.1- */}`定义样式`.iconfont{font-family:"iconfont";font-size:16px;font-style:normal;}`选择图标、获取字体编码,应用于页面`<i class="iconfont">!</i>