精华内容
下载资源
问答
  • mybatis概念

    2019-03-06 19:57:12
    1.MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. ... 是什么:MyBatis是一个一流的持久性框架,支持自定义SQL、存储过程和高级...

    官网解释:http://www.mybatis.org/mybatis-3

    1.MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings.

      是什么:MyBatis是一个一流的持久性框架,支持自定义SQL、存储过程和高级映射。

    2.MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results.

      优点:MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

    3.MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.

     MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

    展开全文
  • 三流大学和一流大学学生的简历有什么区别?

    万次阅读 多人点赞 2020-09-23 09:17:06
    简历有忘记写名字的,有标点符号中英文不统一的,有还没毕业就有上亿QPS经验的,有说自己精通java,这个同学估计QPS是啥都没理解,上亿QPS和精通java是什么的⼀个概念估计他也不知道。 还有嚷嚷着让我内推,说是我...

    点赞再看,养成习惯,微信搜一搜【三太子敖丙】关注这个喜欢写情怀的程序员。

    本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

    最近公司秋招,我写了一篇秋招文章,吸引了不少跃跃欲试的小伙伴,看着邮箱里形形色色的简历,不禁感慨,果然大家对敖丙是真爱,知道我最近比较缺素材,疯狂给我输送反面教材。

    简历有忘记写名字的,有标点符号中英文不统一的,有还没毕业就有上亿QPS经验的,有说自己精通java,这个同学估计QPS是啥都没理解,上亿QPS和精通java是什么的⼀个概念估计他也不知道。

    还有嚷嚷着让我内推,说是我铁粉的,邮件说了⼀大堆励志煽情的话,给我都看感动了。结果附件没放简历....让我内推空⽓?还有简历连电话都没有的....hr差点没把我diss死。

    有的人在准备面试前会绕着商场逛到腿酸,厚着脸皮,忍着营业员嫌弃的眼神试几十套正装,画上比见对象还要精致的妆容,简历呢就从网上随便搜一个简历模板,随意填填草草了事。

    问题太多,我就不一一列举了,简历里面其实是有很多小细节的,这些细节里藏了你简历被拒,石沉大海的原因。

    我今天就带着问题把简历中的每⼀项都跟⼤家说⼀下,内容可能有点长,如果大家一次看不完可以收藏起来,就从简历的格式开始说吧。

    简历格式

    这个时候我估计弹幕里面肯定有人说:不是吧敖丙,格式这种东西还用教么肯定都是PDF啊。

    别,还真有人不知道这个细节的,不过比较庆幸的是这次秋招我收到的大部分简历格式还是没有问题的,都是pdf格式的,但是还是有少数是word文档,word格式的小伙伴可能这会已经懵逼了,word还有错了?

    word格式其实大家可能忽略了一个问题,兼容的问题,每个人电脑上的软件是有差异的,你是office hr小姐姐可能是wps 你是Windows 他是mac 都是offerc 还分版本的,不同版本是可能出现格式兼容问题的,总之各种可能都是有的。

    看到一个乱码的简历我想再有耐心的hr也不会完整的看完。

    pdf就不存在这个问题了,只要你导出的简历是没问题的,那在任何电脑甚至手机上看都是ok的。

    简历命名

    这个时候小伙伴可能又是满屏的问号?不是吧敖丙,简历命名还有讲究的?

    傻瓜,我先给你们看看几个我收到的简历名字(同样是来自公司绯闻女友的吐槽)

    image-20200912113652168
    image-20200912113652168

    简历只用你名字命名没有任何意义,很多人更过分直接就叫简历两个字,或者一串乱码,这种肯定会被hr拉入人才库的。

    大家找熟人内推还好,要是像我这样不是很熟的,而且我收到了上千份简历,因为在我们后台的内推系统我需要找到对应的岗位再点内推系统才会自动识别你的简历信息进行投递的,我不可能一个个点开仔细看了再内推吧。

    我说一下我一直用的一个文件命名,我看这次很多小伙伴也用了,名字_ 学校/学历 _ 岗位 _手机号 顺序不一定固定,学校不是很好的可以忽略学校这一环节,直接写学历就好了。

    小结

    到目前为止我才讲了两个小点,但是就已经可以淘汰部分选手了,这真的就是一场竞赛,跟你一起比赛的还是一群学历很好履历很好的人,结果你还没人家仔细和认真,你说你拿什么去赢?

    很多人抱怨自己的学历,但是很多时候往往还没到拼学历的时候其实你已经败了,大家真的要注意细节呀,好啦我们接着往下。

    封面

    我看到还有人用封面的,而且还是并不是很帅气的自拍照。。。

    如果通过邮件投递简历,建议不要放置封面。

    如果是在招聘会、宣讲会 现场投递简历,可给简历加一个符合自己求职岗位和“正能量”形象的封面,但不建议设计过于花哨。

    个人信息

    很多求职者都把籍贯、民族、身份证号码、身高、体重、居住地、婚姻状况等认为是比较重要的信息列出,但实际上HR最关注的是你是否具备职位所要求的资历和技能;

    这些信息并不能就你的资历和技能提供有效的佐证,相反有可能成为自己被提前否定的可能因素。

    比如你列出了籍贯,刚好看到你简历的 HR被贵州的敖丙甩了,正好对贵州的人没有好感, 很有可能直接将你排除掉。

    但是如果你的资历足够,有机会参加面试 并表现优秀,那么即使获知了你的籍贯也可能给你 offer。

    团员:根据你要应聘的企业的类型决定是否写出党员; 对于团员和群众这样的 极其普通的身份,就不用浪费宝贵的简历空间了。

    联系方式:简历中留 QQ 邮箱有些不正式,敖丙那个年代专门有学长让我去申请了别的邮箱我不确定现在是否还有这种说法。手机号码一定要写对,我以前帮朋友内推他告诉我一直没联系他,其实他是手机号码写成他以前的号码了....这完全就是搞心态啊有没有

    照片:如果不是长得比较好看,我觉得照片大可不必,hr真的不是很在意这个,要是像敖丙一样丑到hr还容易被pass

    薪资期望

    这一点我单独拎出来说一下。

    除非招聘广告中要求你必须说明,否则不要泄露自己的薪资情报和期望。

    薪资是面试过程或之后才涉及的问题,而且通常都有谈判的余地; 主动在简历中提及,可能会使自己在薪资谈判时不利。出来打工能多为自己争取一点还是多争取一点,一个月多一千一年也多一万多呢。

    如果大家对面试技巧感兴趣我也可以单独出一期,我们继续往下看。

    教育经历

    如果你的教育经历具有优势,那就把教育经历放在简历的偏前部分;

    不然的话,一定要把你缺乏优势的教育经历放到简历的后面部分去,让 HR 首先看到的是你具备优势的工作经历、业绩和技能;

    其次,如果你是大 专、自考、独立学院之类的学历,你没有必要如此坦白;通通隐去,只 写你的学校、专业和就读起止时间就好;只要你没有撒谎就没有问题。

    很多时候等你面试完他们发现你确实很匹配,就算学历一般也是有入职机会的,但是你直接就写了一个名不见经传的学校,被提前pass的机会就大大增加了。

    工作/实习经验

    很多同学在简历中长篇累牍地罗列了许多社团活动和实习经历,却缺乏 经验总结和能力提炼。HR 喜欢看到的是逻辑非常清晰,用一些动词打头 的短句来表明你的经历;用数字来表明你的成果,并以此来判断你的综 合能力;不喜欢赘述项目概况以及琐碎的活动进程。 大家一定要记得:我们需要在简历中展现的是自己的能力,而不仅仅是 经历。

    实习经历和在校经历尽量选取和求职职位相关的,如果没有就写自己已 有的实习或兼职经历。在撰写时注意突出工作成果和工作收获,因为不 错的工作成果能体现出求职者的很多个人优点,工作收获中可集中阐述 自己收获的和目前求职职位相关的技能、素质。

    要避免没有重点的简历。简历应该是根据不同目标职位来制作,在工作 经历描述应突出与目标职位类似经历的描述,而把与目标职位不相关的 经历描述得简洁一些。在技能和培训经理上也应该写与目标职位相关的 内容。

    简历应该以客观性事实来证明自己具备对方所要求的技能和素养;如果 你觉得自己具有“很强的协调组织和团队合作能力”的特点,应该寻找能 够证明这些特点的实例来陈述,对方自然就会明白而且深信不疑。

    技能介绍

    技能介绍就介绍你目前掌握的技术栈就好了,但是大家一定要分清,熟悉,数量掌握,精通等词语的应用,因为我不止一次看到居然有应届生写精通java这样的词汇,

    大家可能接受社会的毒打还是太少了,不明白你知道的越多,你知道的越多这句话的含义,精通二字就连java之父都不敢妄谈,大家一般就写熟悉,数量掌握就够了。

    项目经历

    项目经验可能是整个简历最重要的环节了,如果你还在读书又没有一个亮眼的项目,那我建议你可以去好好做一个好的项目,不然真的很难跟别的同学竞争。

    项目部分是最能体现你核心竞争力的地方

    项目简介、涉及技术栈、设计思路、你的职责、必要的话可以写一些你的思路

    技术栈就是面试官面试你的依据,不熟悉的千万不要乱写,面试官一般都不会乱问的,就按照你写的来。

    自我评价

    在项目中是否写自我评价一直都是一个比较有争议的话题如果你篇幅还有,我觉得可以写一下,我就曾经因为自我评价被兴业数金的总监特意留意过。

    而简历的版面非常珍贵,应该留给更重要的内容,所以大家酌情考虑。

    整体篇幅

    尽量做到“一页纸”简历。如果内容很多,两整页也可以接受。但是尽量不要出现那种一页再多三行的情况。

    标点符号一定要统一,我看到过小伙伴一会中文标点,一会英文标点的情况的,这样看起来真的显得很不专业。

    不要在简历中插入大容量图片。HR 每天要收无数封邮件,如果你发个 10M 的简历过去,半天下载不下来,还影响别的邮件的接收,估计也就 没心情看内容了。如果是设计类的职位另说,一般如果没要求简历上还 是不要放太多,可以做个单独的文件需要的时候再发。

    投递时间

    如同交通有上下班高峰,投递简历也是如此。通常,一个职位在刚发布 时,会迎来一个投递高峰,在职位发布的第一天和第二天,HR 的邮箱里 收到的简历是最多的。

    求职者想要提高自己的简历的被关注度,不如避 开这个高峰。 另一个高峰,是指在招聘网站职位搜索器的反馈结果中,列在前几页的 职位会被集中投递。

    出于习惯,很多求职者都会选择投递搜索器反馈结 果中列在前面几页的职位,导致在前几页出现的招聘企业能收到的简历 数量远高于之后的企业。有鉴于此。建议求职者可以多用一些筛选条件 来排列关心的职位,多关注一些别人不太关注的职位,不要放过一丝一 毫可以让 HR 看到自己简历的潜在机会。

    注意

    需要提醒的是,如果你向前一家公司投递简历后没有获得面试机会,那 再向其他公司投递前,请同步更新一下简历内容。

    还可以根据不同的公司,切换不同的风格和技术栈,这样会大大加深你的成功率。

    重要的事情再说一遍,简历很重要,值得花点时间去斟酌的,求职路上 的这个第一步,迈对了很重要,有时候不只是写给别人看的,用心想的 时候也能帮助自己理清思路。

    总结

    “⼈靠⾐装,佛靠⾦装”。简历,就是你的⾦装,⼀份好的简历,可以最⼤程度展现你的优点,隐藏你的劣势,让别⼈在没⻅到你之前,就对你有了个大致的印象,甚至产生想见到你的意愿;⽽⼀份不好的简历,也可以让⼀个与⽬标⼯作⼏乎完美匹配的⼈与机会失之交臂。

    简历是求职者的敲门砖,只有你的敲门砖足够好,你才有进一步和招聘方交流的机会。

    第⼀次实习的时候我就是⼀次⼜⼀次的找我的班主任帮我修改简历,直到没有任何瑕疵,所以我的职场之路开头特别顺利。我想这不仅是一份完美的简历,更是我一直对待工作的态度。

    希望⼤家能认真对待⼯作和⽣活中的每⼀件⼩事,你认真对待⽣活,⽣活会加倍回馈你,而你所遇见的、热切渴望的、真诚追求的、全心争取的,都会自然而然地实现。

    絮叨

    另外,敖丙把自己的面试文章整理成了一本电子书,共 1630页!目录如下,还有我复习时总结的面试题以及简历模板,现在免费送给大家。

    链接:https://pan.baidu.com/s/1ZQEKJBgtYle3v-1LimcSwg 密码:wjk6

    我是敖丙,你知道的越多,你不知道的越多,感谢各位人才的:点赞收藏评论,我们下期见!

    展开全文
  • 机器学习概念西洋跳棋

    千次阅读 2019-03-19 00:10:56
    本篇文章基于机器学习来分析下西洋跳棋学习问题。 从1989年开始,美国艾尔伯特大学的计算机科学家Jonathan Schaeffer和同事就致力于开发西洋跳棋人工智能程序。 通过研究5万亿亿个跳棋位置,研究人员于16年4月完成了...

    本篇文章基于机器学习来分析下西洋跳棋学习问题。
    从1989年开始,美国艾尔伯特大学的计算机科学家Jonathan Schaeffer和同事就致力于开发西洋跳棋人工智能程序。
    通过研究5万亿亿个跳棋位置,研究人员于16年4月完成了切努克终极程序,它是无法被击败的——就算人类智力发挥到极限,也只能跟它打个平手。

    学习问题的标准描述:

    我们给学习一个宽广的定义,以使其包括任何计算机程序通过经验来提高某任务处理性能的行为。更准确地讲:

    • 定义: 对于某类任务 T 和性能度量 P,如果一个计算机程序在 T 上以 P 衡量的 性能随着经验 E而自我完善,那么我们称这个计算机程序在从经验 E 学习。

    例如,对于学习下西洋跳棋的计算机程序,它可以通过和自己下棋获取经验,
    它担负的任务是参与西洋跳棋对弈,它的性能用它赢棋的能力来衡量。通常,为了很好地定义一个学习问题,我们必须明确这样三个特征:任务的种类;衡量任务提高的标准;经验的来源。

    西洋跳棋学习问题:

    • 任务 T:下西洋跳棋
    • 性能标准 P:比赛中击败对手的百分比
    • 训练经验 E:和自己进行对弈

    我们可以用以上方法定义很多学习问题,例如学习手写识别、学习自动驾驶机器人汽车。

    为了更好理解本例,下面简要介绍一下这种跳棋。
    棋盘为 8×8方格,深色棋格不可着子。可单步行走,亦可每步跨对方一子单跳或连跳,被跨越的子被杀出局。到达对方底线的子成为王,可回向行走(成为王前只可前行),又可隔空格飞行。下图为西洋跳棋棋盘示例(起始状态)。

    在这里插入图片描述

    这里对学习的定义很宽广,足以包括大多数惯于被称为“学习”的任务,就像我们日常
    使用的这个词一样。

    设计一个学习系统:

    考虑设计一个学习下西洋跳棋的程序。(假设:)

    • 我们的目标是让它进入西洋跳棋世界锦标赛。
    • 我们采用最显而易见的标准衡量它的性能。
    • 在世界锦标赛上打赢的比赛占总参赛次数的百分比

    选择训练方式

    1、我们面临的第一个设计问题是选取训练经验的类型,使系统从中进行学习。

    • 给学习器提供的训练经验对它的成败有重大的影响。一个关键属性是训练经验能否为系统的决策提供直接或间接的反馈。
    • 对于学习下西洋跳棋,系统可以从直接的(direct)训练样例,即各种棋盘状态和相应的正确走子中学习。
    • 另一种情况,它可能仅有间接(indirect)的信息,包含很多过去的对弈序列和最终结局。对于后一种情况,关于博弈中较早走子的正确性必须从对弈最终的输赢来推断。

    2、这时学习器又额外面临一个 信用分配(credit assignment)问题,也就是考虑每一次走子对最终结果的贡献程度。

    • 信用分配可能是一个非常难以解决的问题,因为如果后面下得很差,那么即使起初的走子是最佳的,这盘棋也会输掉。所以通常从直接的训练反馈来学习比间接的简单。

    3、训练经验的第二个重要属性是学习器可以在多大程度上控制训练样例序列。

    • 例如,学习器可能依赖施教者选取棋盘状态,和提供每一次的正确移动。或者,学习器可能自己提出它认为特别困惑的棋局并向施教者询问正确的走子。

    或者,学习器可以完全控制棋局和(间接的)训练分类,就像没有施教者时它和自己对弈进行学习一样。

    • 注意对于最后一种情况学习器可能选择以下两种情况中的一种:第一,试验它还未考虑过的全新棋局;
      第二,在它目前发现的最奏效的路线的微小变化上对弈,以磨砺它的技能。后续的章节考虑一些学习框架,

    包括了以下几种情况:训练经验是以超乎学习器控制的随机过程提供的;学习器可向施教者提出不同类型的查询;以及学习器通过自动探索环境来搜集训练样例。

    4、训练经验的第三个重要属性是,训练样例的分布能多好地表示实例分布,而最终系统的
    性能 P 是通过后者来衡量的。一般而言,当训练样例的分布和将来的测试样例的分布相似时,学习具有最大的可信度。

    • 对于我们的西洋跳棋学习,性能指标 P 是该系统在世界锦标赛上赢棋的百分比。
    • 如果它的训练经验 E 仅由和它自己对弈的训练组成,便存在一个明显的危险:这个训练可能不能充分地表示该系统以后被测试时的情形。
    • 例如,学习器可能在训练中从来未遇到过某些非常关键性的棋局,而它们又非常可能被人类世界冠军采用。

    5、实际上,学习的样例通常与最终系统被评估时的样例有一定差异,学习器必须能从中进行学习(举例来说,世界级的西洋跳棋冠军可能不会有兴趣教一个程序下棋)。

    掌握了样例的一种分布,不一定会导致对其他的分布也有好的性能。
    可以看到,目前多数机器学习理论都是基于训练样例与测试样例分布一致这一前提。尽管我们需要这样的前提以便得到理论的结果,但同样必须记住在实践中这个假设经常是不严格成立的。

    进行算法设计

    我们决定系统将通过和自己对弈来训练。这样的好处是不需要
    外界的训练者,所以可以让系统产生无限多的训练数据,只要时间允许。
    一个完整的学习任务

         	 • 任务 T:下西洋跳棋
    	     • 性能标准 P:世界锦标赛上击败对手的百分比
    		 • 训练经验 E:和自己进行对弈
    

    为了完成这个学习系统的设计,现在需要选择:

    1. 要学习的知识的确切类型
    2. 对于这个目标知识的表示
    3. 一种学习机制

    选择目标函数:

    我们从一个对于任何棋局都能产生合法(legal)走子的西洋跳棋博弈程序开始。那么,最终的程序仅须学会从这些合法的走子中选择最佳的。
    这个学习任务代表了一大类任务:合法走子定义了某个先验已知的巨大搜索空间,但最佳的搜索策略未知。
    很多最优化问题都可归于此类,例如对于生产过程的调度和控制问题,生产中的每一步都很清楚,但调度这些步骤的最佳策略未知。

    为了学习从合法走子中作出选择,很明显,要学习的信息类型就是一个程序或函数,它
    对 任 何 给 定 的 棋 局 能 选 出 最 好 的 走 法 。 可 称 此 函 数 为 ChooseMove , 并 用 记 法ChooseMove:B→M 来表示这个函数以合法棋局集合中的棋盘状态作为输入,并从合法走子集合中产生某个走子作为输出。在关于机器学习的所有讨论中,我们发现可以把对任务 T提高性能 P 的问题简化为学习象 ChooseMove 这样某个特定的 目标函数(target function )的问题。所以目标函数的选择是一个关键的设计问题。

    • 尽管在例子中很明显应把 ChooseMove 作为目标函数,但我们会发现学习这个目标函数是非常困难的,原因是提供给系统的是间接的训练经验。
    • 另外一个可供选择的目标函数是一个评估函数,它为任何给定棋局赋予一个数字的评分。可以发现,对于本例,学习这个目标函数更简单

    令这个目标函数为 V,并用 V:B→ℜ 来表示 V 把任何合法的棋局映射到某一个实数值(用ℜ来表示实数集合)。我们打算让这个目标函数 V 给好的棋局赋予较高的评分。如果系统能够成功地学会这个目标函数 V,那么它便能使用此函数轻松地找到当前棋局的最佳走法。实现的方法是,先产生每一个合法走子对应的所有后续棋局,然后使用 V 来选取其中最佳的后继棋局,从而选择最好的走子。

    对于任意棋局,目标函数 V 的准确值应该是多少呢?当然任何对较好的棋局赋予较高
    的分数的评估函数都适用。然而,最好在那些产生最佳对弈的众多方法中定义一个特定的目标函数 V。可以看到,这将使得设计一个训练算法变得简单。因此,对于集合 B 中的任意的棋局状态 b,我们如下定义目标函数 V(b):

    1. 如果 b 是一最终的胜局,那么 V(b)=100
    2. 如果 b 是一最终的负局,那么 V(b)=-100
    3. 如果 b 是一最终的和局,那么 V(b)=0
    4. 如果 b 不是最终棋局,那么 V(b)=V(b′),其中 b′是从 b 开始双方都采取最优对
      弈后可达到的终局。

    然而,由于这个定义的递归性,它的运算效率不高,所以这个定义对于西洋跳棋比赛者
    不可用。
    除了无关紧要的前三种终局的情况,对于某一个棋盘状态(情况 4)b 要决定它的值 V(b)需要向前搜索到达终局的所有路线!由于这个定义不能由西洋跳棋程序高效地运算,这个定义被称为 不可操作的定义 。当前的目标是发现一个可操作的定义 V,它能够被西洋跳棋程序用来在合理的时间内评估棋局并选取走法。

    这样,这种情况的学习任务被简化成发现一个数 理想目标函数 V 的可操作描述。通常要
    完美地学习这样一个 V 的可操作的形式是非常困难的。

    事实上,我们经常希望学习算法仅得到目标函数的某个 近似(approximation),由于这个原因学习目标函数的过程常被称为函数逼近函数逼近(function approximation)。

    在当前的讨论中,用Vˆ来表示程序中实际学习到的函数,以区别理想目标函数 V。

    目标函数的表示

    至此,我们已经确定了目标函数 V,接下来必须选择一个表示,被学习程序用来描述要
    学习的函数Vˆ。对此也有很多设计选择。

    • 例如,可以将Vˆ表示为一张大表,对于每个惟一的棋盘状态 b,表中有惟一的表项来确定它的状态值Vˆ(b)。

    或者,可以让程序用一个规则集合来匹配棋局的特征以表示Vˆ,或采用一个与预定义棋盘特征有关的二次多项式函数,或者用人工神经元网络。
    通常,选择这个描述包含一个重要的权衡过程。一方面,我们总希望选取一个非常有表征力的描述,以最大可能地逼近理想的目标函数 V.另一方面,越有表征力的描述需要越多的训练数据,使程序能从它表示的多种假设中做出选择。为了简化讨论,现在选择一个简单的表示法:对于任何给定的棋盘状态,函数Vˆ可以通过以下棋盘参数的线性组合来计算:
    x 1 :棋盘上黑子的数量
    x 2 :棋盘上红子的数量
    x 3 :棋盘上黑王的数量
    x 4 :棋盘上红王的数量?
    x 5 :被红子威胁的黑子数量(即会在下一次被红吃掉的子)? x 6 :被黑子威胁的红子数量

    学习程序把Vˆ(b)表示为一个线性函数
    在这里插入图片描述

     Vˆ(b)=w0 +w1x1 +w2x2 +w3x3 +w4x4 +w5x5 +w6x6
    

    其中 w 0 到 w 6 为数字系数,或叫权,由学习算法来选择。在决定某一个棋盘状态的分值时,w 1 到 w 6 决定了不同的棋盘特征的相对重要性,而权 w 0 为一个附加的常量。
    概括一下目前为止的设计。我们已经详细阐述了这个学习问题的原型,即为它选择一种
    类型的训练经验、一个要学习的目标函数和这个目标函数的一种表示法。现在的学习任务是:

    西洋跳棋程序的部分设计
    • 任务 T:下西洋跳棋
    • 性能标准 P:世界锦标赛上击败对手的百分比
    • 训练经验 E:和自己进行训练对弈
    • 目标函数:V:B→ℜ
    • 目标函数的表示:Vˆ(b)=w 0 +w 1 x 1 +w 2 x 2 +w 3 x 3 +w 4 x 4 +w 5 x 5 +w 6 x 6
    前三条是对学习任务的说明,后两条制定了为实现这个学习程序的设计方案。注意这个
    设计的关键作用是把学习西洋跳棋战略的问题简化为学习目标函数描述中系数w 0 到w 6 值的问题。

    选择函数逼近算法

    为了学习目标函数Vˆ,需要一系列训练样例,每一个样例描述了特定的棋盘状态 b 和
    它的训练值 V train (b)。换言之,每一个训练样例是形式为<b,V train (b)>的序偶。举例来说,下面的训练实例描述了一个黑棋胜利(注意 x 2 =0 表示红棋已经没有子了)的棋盘状态 b,它的目标函数值 V train (b)为 100。
    <<x 1 =3,x 2 =0,x 3 =1,x 4 =0,x 5 =0,x 6 =0>,+100>下文描述了一个过程,它先从学习器可得的间接训练经验中导出上面的训练样例,然后调整权值 w i 以最佳拟合这些训练样例。

    估计训练值

    根据以上的学习模型,学习器可以得到的训练信息仅是对弈最后的胜负。 另一方面,
    我们需要训练样例为每个棋盘状态赋予一个分值。给对弈结束时的棋盘状态评分是容易的,而要给对弈结束前的大量中间棋局评分就不那么容易了。因为,一盘棋的最终输赢未必能说明这盘棋当中的每一个棋盘状态的好或坏。例如,即使某个程序输了一盘棋,仍会有这样的情况,这盘棋前面的棋局应该给予很高的评价,失败的原因在于后来糟糕的走法。
    尽管估计中间棋局训练值具有内在的模糊性,但令人惊讶的是有一个简单的方法却取得了良好结果。这种方法对于任何中间棋局 b 的训练值 V train (b)等于Vˆ(Successor(b)),其中Vˆ是学习器采用的对 V 的近似,Successor(b) 表示 b 之后再轮到程序走棋时的棋子状态(也就是程序走了一步和对手回应一步后的棋局)。
    这种估计训练值的方法可被归纳为:
    训练值估计法则

    V train (b)←Vˆ(Successor(b)) 
    

    在这里插入图片描述
    或许这看起来有点离奇,只使用当前的Vˆ来估计训练值,这一训练值有被用来更新
    Vˆ。但请注意,我们是在用后续棋局 Successor(b)的估计值来估计棋局 b 的值。凭直觉,我们可以看到越接近游戏结束的棋局的Vˆ越趋向精确。事实上,在特定条件下(将在第 13 章讨论)这种基于对后继棋局进行估计的迭代估计训练值的方法,已被证明可以近乎完美地收敛到V train 估计值。

    权值调整

    剩下的事情就是为 这个学习算法选择最适合训练样例{<b, V train (b)>}的权 w i 。第一步必须定义 最佳拟合(best fit)训练数据的含义。一种常用的方法是把最佳的假设(或权向量集合)定义为使训练值和假设Vˆ
    预测出的值间的误差平方 E 最小。
    在这里插入图片描述

    至此,我们的目标就是寻找权值(等价地,寻找Vˆ),使对于观测到的训练数据 E 值最
    小化。第 6 章将讨论在什么条件下,最小化误差平方和等价于寻找给定观测训练数据下的最可能假设。
    已经知道一些算法可以得到线性函数的权使此定义的 E 最小化。在这里需要一个算法,
    它可以在有了新的训练样例时进一步改进权值,并且它对估计的训练数据中的差错有好的健壮性。

    一个这样的算法被称作最小均方法(least mean squares),或叫 LMS 训练法则。对于每一训练样例,它把权值向减小这个训练数据误差的方向略为调整。

    这个算法可被看作对可能的假设(权值)空间进行随机的梯度下降搜索,以使误差平方和 E最小化。LMS 算法是这样定义的:

    LMS 权值更新法则 对于每一个训练样例<b,V train (b)>
    • 使用当前的权计算Vˆ(b)
    • 对每一个权值 w i 进行如下更新

    w i ←w i +η(V train (b)-Vˆ(b)) x i
    

    在这里插入图片描述
    这里 η 是一个小的常数(比如 0.1)用来调整权值更新的幅度。为了直观地理解这个权
    值更新法则的工作原理,请注意当误差(V train (b)-Vˆ(b))为 0 时,权不会被改变。

    (V train (b)-Vˆ(b))为正时(例如,当Vˆ(b)太低时)每一个权值会根据其对应特征值增加一定的比例。这会提升Vˆ(b)的值而减小误差。
    注意如果某个参数 x i 为 0,那么它的值不会因这个误差而改变,这样便使只有那些在训练样例的棋局中确实出现的特征的权值才被更新。
    令人吃惊的是,在一定的条件下,这种简单的权值调整方法被证明可以收敛到 V train 值的最小误差平方逼近。

    最终的设计

    西洋跳棋学习系统的最终设计可以自然地用四个清楚的程序模块来描述,这些模块在很
    多学习系统中是核心组件。这四个模块它们是:

    执行系统(Performance system) ,这个模块是用学会的目标函数来解决给定的任务,在此就是对弈西洋跳棋。它把新问题(新一盘棋)的实例作为输入,产生一组解答路线(对弈历史记录)作为输出。在这里,执行系统采用的选择下一步走法的策略是由学到的评估函数Vˆ来决定的。所以我们期待它的性能会随着评估函数的日益准确而提高。

    鉴定器(Critic) ,它以对弈的路线或历史记录作为输入,输出目标函数的一系列训练样
    例。如图所示,每一个训练样例对应路线中的某个棋盘状态和目标函数给这个样例的评估值V train 。在我们的例子中,鉴定器对应式 1.1 给出的训练法则。

    泛化器(Generalizer) ,它以训练样例作为输入,输出一个假设,作为它对目标函数的
    估计。它从特定的训练样例中泛化,猜测一个一般函数,使其能够覆盖这些样例以及样例之外的情形。在我们的例子中,泛化器对应 LMS 算法,输出假设是用学习到的权值 w 0 ,…, w 6描述的函数Vˆ。

    实验生成器(Experiment Generator ),它以当前的假设(当前学到的函数)作为输入,输出一个新的问题(例如,最初的棋局)供执行系统去探索。它的角色是挑选新的练习问题,以使整个系统的学习速率最大化。在我们的例子中,实验生成器采用了非常简单的策略:它总是给出一个同样的初始棋局来开始新的一盘棋。更完善的策略可能致力于精心设计棋子位置以探索棋盘空间的特定区域。

    总体来看

    我们为西洋跳棋程序作的设计就是产生执行系统、鉴定器、泛化器和实验生
    成器的特定实例。很多机器学习系统通常可以用这四个通用模块来刻画。
    设计西洋跳棋程序的流程被归纳在图 1-2 中。

    这个设计已经在几方面把学习任务限制在较小的范围内。要学习的知识类型被限制为一个单一的线性评估函数。
    而且这个评估函数被限制为仅依赖于六个棋盘特征。如果目标函数真的可表示为这些特定参数的线性组合,那么程序学到这个目标函数的可能性很大。
    反之,最多只希望它学到一个合理的近似,因为一个程序当然不能学会它根本不能表示的东西。

    我们假定真实函数 V 的合理的近似确实可被表示为这种形式。那么问题变成这种学习
    技术是否确保能发现一个合理的近似。

    已经设计的程序能学得足够好而击败人类的西洋跳棋冠军吗?或许不能。部分地,这是
    因为Vˆ的线性函数表示太简单以致于不能很好捕捉这种棋的微妙之处。然而,如果给与一个更完善的目标函数表示法,这种通用的途径事实上可以非常成功。

    • 例如,Tesauro(1992,
      1995)报告了学习下西洋双陆棋的程序的类似设计,方法是学习一个非常类似的棋局评估函数。它的程序使用人工神经元网络表示学到的评估函数,它考虑对棋局的完整描述而不是棋盘的几个参数。
    • 经历了一百万次以上的自我生成的训练比赛后,他的程序能够和一流的人类西洋双陆棋选手一争高下。当然还可能为西洋跳棋学习任务设计很多其他的算法。
    • 例如,一种可能只简单地存储训练样例,然后去寻找保存的“最接近的”情形来匹配新的情况。或者可以产生大量候选的西洋跳棋程序,并让它们相互比赛,保留最成功的程序并进一步用模拟进化的方式来培育或变异它们。
    • 人类似乎遵循另一种途径寻找学习策略,他们分析或向自己解释比赛中碰到的成败的原因。

    上面的设计是这些种类中的一个简单的算法,它是为了给我们今后的针对特定类别的任务的学习方法的设计奠定基础。

    展开全文
  • 随想录:开发一流Android SDK

    万次阅读 多人点赞 2016-12-10 13:59:32
    明确SDK的概念之后,再来聊一聊这三个概念:Library,API,Framework 什么是Library Library即我们所说的库,通常是一组或者几组类的集合,通常是应用中某些功能的具体实现或者对系统已有功能的增强或补充.对...

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

    自从前段时间离职后,因为个人的事情一直没有选择再工作,也导致原有的文章并没有按时产出.最近个人的事情整理的也差不多了,恰好有不少朋友来问有关SDK开发方面的事情,在此就做个简单的梳理,希望能帮助各位.

    目前更多开发者热衷于应用开发,极少数的开发者才有机会从事SDK开发工作,而市面上关于SDK开发介绍的文章少之又少,以至于让大家觉得SDK开发是相对比较难而且非常无聊的工作,今天我们就来简单的聊聊SDK开发的哪点事.


    关于SDK的解释

    什么是SDK

    在开始正文之前,首先来聊聊SDK是个啥玩意.

    SDK是Software Development Kit的缩写,译为”软件开发工具包”,通常是为辅助开发某类软件而编写的特定软件包,框架集合等,SDK一般包含相关文档,范例和工具.

    SDK可以分为系统SDK和应用SDK.所谓的系统SDK是为特定的软件包,软件框架,硬件平台,操作系统等简历应用时所使用的开发工具集合.而应用SDK则是基于系统SDK开发的独立于具体业务而具有特定功能的集合.

    比如在进行Android 应用开发时,我们使用Google提供的系统SDK(Android SDK),而我们经常使用的友盟SDK,极光SDK则是基于系统SDK开发的.

    明确SDK的概念之后,再来聊一聊这三个概念:Library,API,Framework

    什么是Library

    Library即我们所说的库,通常是一组或者几组类的集合,通常是应用中某些功能的具体实现或者对系统已有功能的增强或补充.对Android开发者而言,最常见的莫过于是Support Library,另外就是我们经常使用各种网络请求库(OkHttp,Volley),数据库操作,图片加载库(Glide,ImageLoader)等.

    什么是Framework

    Framework即我们所说的框架,通常是系统或者应用的骨架,很多时候,它表现为一组抽象的构建及构件实例间交互的方法.因此,可以认为,Framework规定了应用的体系结构,阐明了整体设计,写作构件之间的依赖关系以及控制流程.注意自处的Framework并不完全等同于你所熟知的Android Framework框架,可以认为Android Framework中体现了Framework的思想,并进行了实现.

    什么是API

    API是Application Programming Interface,又称为应用编程接口,是软件系统不同组成部分衔接的约定。更加通俗的说就API就是我们常见和编写的方法或函数.

    小结

    明确了上面提到的概念之后,现在就可以来描述这四者之间的关联:
    SDK主要包含Framework,API及Library的三部分.Framework定义了SDK整体的可重用设计,规定了SDK各功能模块的职责以及依赖关系.其中个功能模块体现为Library.模块之间的内部通信及SDK外部通信(SDK对外提供服务的接口)则通过API进行.

    另外完整的SDK还应该包含大量的示例和其他工具.比如在Android SDK的tools目录下提供了大量的辅助开发工具.

    对我们而言,大部分情况下是为某种具体的业务需求开发对应的SDK,以便作为第三正提供给其他需求方使用.比如百度推送的SDK主要实现消息推送功能,需求方只需要集成百度推送的SDK便可以使自己应用具备推送功能.

    到现在已经介绍了SDK的主要构成,接下来我们重点来介绍SDK的实现目标以及在SDK架构中的一些核心点.


    浅谈SDK实现目标

    上面介绍了开发中常见的概念,现在来谈谈SDK的实现目标.任何应用都应具备:简洁易用,稳定,高效,轻量,SDK作为一种特定应用当然也不例外.

    简洁易用

    按照”奥卡姆剃须刀”理论,一个好的产品对第三方使用者使用而言应该是简洁易用,不用改让使用者花费太长时间学习的.这对SDK同样适用—SDK不应该对宿主应用有过多的代码侵入,也不应该有复杂频繁的接入工作.比如当开发者需要使用SDK的服务时,只需要在缘由的代码中新增一行即可.常见的SDK初始化如下:

    public class Ad{
    
        @TargetApi(9)
        public synchronized static void init(Context context, SdkParams params) {
            //省略多行代码
        }
    }
    

    当我们需要使用该SDK的服务时,通过一行代码便可启用Ad.init(this,params)

    要保证较少的代码侵入主要在对外提供服务时充分考虑到使用者的使用场景来设计出优良的API.一个优良的API在定义的时候应该满足绝大数开发者所预期的方式—语义上要求通俗易懂,使用上要求简单可靠.

    一个优良的API首先是简单可靠的.在正常使用的情况下体现为稳定可靠的执行,在异常情况下体现为及时的告知使用者使用错误.初次之外,遵循一致的明明规则,并是所有的API呈现出一致的风格对开发而言无疑是个好消息.

    稳定

    站在SDK使用者角度来看,我们期望第三方的SDK服务应该是稳定高效的,体现在提供稳定可靠的服务,在不影响宿主稳定性的前提下足够的高效,这就要求我们SDK设计者在设计并实现SDK时要尽可能的做到以下几点:

    • 对外提供稳定的API.SDK的API一旦确定,如无非常严重情况不可更改.作为提供服务方,发生API变更所带来的变更成本非常大.
    • 对外提供稳定的业务.在稳定的API后,必须要有稳定的业务来支撑.
    • SDK运行时的稳定,作为服务提供方,我们必须确保SDK自身运行的稳定,并且保证接入方不会因为我们的SDK产生不稳定的情况.
    • 版本稳定更新.和面向普通用户的应用相比,SDK版本的迭代是非常缓慢的.并且需要尽可能的对开发者屏蔽迭代过程,以免给开发者带来不必要的适配开销.

    高效

    无论是普通的应用开发还是SDK开发,都应该考虑到性能问题,SDK设计者应该着重考虑以下问题:

    • 更少的内存占用.在不使用多进程的情况下,SDK服务和宿主程序运行在同一进程中,这种情况下必须要求限制SDK内存的占用,不能因为说因为我们SDK占用太多的内存资源,导致应用的存活时间变短.
    • 更少的内存抖动.在占用更少内存的前提下,SDK设计者必须刻意的减少反复GC造成的内存抖动问题.
    • 更少的电量消耗.尽管很多时候无法对电量消耗做一个很好的权衡,但是仍然有一些可以参考的做法,比如减少使用耗电模块的时间.比如在使用定位服务时,不要求非常高的精度下优先使用网络定位而不是GPS定位.
    • 更少的流量消耗.

    SDK整体架构设计

    SDK的架构实现决定了SDK后续的维护难度,因此有必要在此对SDK整体架构中的一些点做些简单的说明.

    模块化开发

    根据单一职责将系统拆分为不同的小模块,每个模块保持相对独立。

    模块之间通过协议或接口通信,以减少相互之间的依赖耦合.模块内部按照设计的几大原则进行实现,以保证模块本身可以灵活实现

    对于现代开发而言,模块化是常用的手段,从宏观角度来看,模块是系统最小的组成单元.

    组件化开发

    组件开发同样是个老生常提的概念,但从我个人的感受来说,组件是对逻辑的封装,并具备单个可移植性.比如可以把日志记录做成一个组件,之后它可以被轻松在应用在不同的项目中.对于android 开发者而言,Android 提供的每个UI 控件同样也是组件,比如Button,TextView等.

    在明确了组件这一概念之后,组件化开发也就不难理解:所谓的组件化就是将整个项目划分成多个模块,几个模块或者单个模块作为一个组件,开发过程中我们可以对每个组件进行并行开发,最后发布时通过依赖将组件合并成完整的应用.

    那为什么要使用组件化呢?
    随着android的逐渐成熟,现在的app业务越来越复杂,与此同时,android工程也变得日益庞大,代码行数十几万已经是常态,此时有几个问题便会凸显出来:

    1. 工程任何一点改动都会造成整个工程的重新编译.记忆最深的就是早期在没有进行组件化的时候,庞大的工程动辄需要十几分钟的编译时间,一杯茶的时间就出来了,很多时候,不得不眼巴巴的等着,尽管现在可以使用facebook出品的buck以及来自阿里的feeline来加速编译过程,单仍然不够.
    2. 整个工程中充斥的大量重复或者冗余的子模块,业务耦合度非常高,牵一发而动全身.这就造成了”老人不敢改,新人无法改”,因为谁也不能预知在做修改之后,会产生什么影响.
    3. 协作开发基本上是不可能的,天知道彼此在做什么.代码合并的的时候更是令人痛苦.
    4. 不方便测试.高度耦合的业务和模块导致无法下手进行测试,只能草草了事.

    通过引入组件化,上面遇到的问题便可迎刃而解.在SDK当中,根据实际情况对其进行组件化,比如我们将分享功能组件化,可以轻松的支持多种渠道的分享,在需要更新分享功能时,可以对其进行单独的编译和测试.

    通过组件化,我们也可以轻松的实现SDK的定制功能,通过编写编译脚本,我们可以决定哪些组件被依赖,最终合并到完整的应用当中.比如友盟中的提供的可定制分享组件(如下图)的原理就是如此.

    这里写图片描述

    插件化开发

    什么是插件化开发这里就不做介绍了,一方面插件化并不是个新概念,另外就是插件化到目前为止理论层次上已经非常成熟,不想15念开始研究的时候资料相对较少.

    在SDK中为什么使用插件化呢?SDK不同于普通应用,不能频繁的进行更新,以免让开发者觉得SDK不稳定或者让开发者频繁的集成.SDK看起来变化较慢,实则变化频繁.就以以前做的广告SDK而言,有时候经常需要对某类机型进行数据采集或者及时更新反作弊模块,在没有使用插件化之前,解决该问题是非常麻烦的.但是在我们利用插件化之后,解决该问题就变得非常容易:我们将SDK整体划分为两部分:宿主和插件.宿主只向开发者提供必要的服务接口,并提供了自定义插件加载器.而核心的逻辑则是存在于插件中.当需要采集数据的时候,只需要由开发人员开发好数据采集插件并下发到指定设备即可;当需要修复SDK缺陷时,同样也只需要下发新的插件包即可.

    通过在SDK使用插件化方案,可以有效的对开发者屏蔽手动更新的过程.宿主相对稳定,一旦确定,一般不会变动,而后续的业务变化则只需要通过更新插件来支撑.

    除了上面谈到的利用插件化解决动态更新之外,通过将整个工程分为宿主和插件可以实现宿主的并行开发和分开编译,并且能有效的解决方法数65535的限制.在没有使用插件化之前,我们整个项目是由很多组件通过依赖形成的庞大工程,不得不通过


    SDK初始化

    和应用开发不同,很多情况下SDK没有自身的上下文Context,而必须要借助应用提供.SDK初始化的常见做法:Ad.init(Context context,AdParams params),我们往往推荐开发者在应用Application组件中的onCreate()中去掉用该方法,这就意味着该初始化过程是同步的,假如SDK本身初始化时间较长,就会影响应用的启动速度.

    在这种情况下,作为SDK的设计者必须着手解决该问题.通常将SDK服务进一步划分成核心服务和辅助服务,之后通过并行初始化和延迟初始化的手段来减少SDK初始化耗时.曾经在我所负责的广告SDK中,有开发者反馈我们的SDK启动较慢,通过对整个SDK启动流程进行分析后,我们将插件加载服务和云控服务并行初始化,而对于像日志服务则采用颜值初始化,通过该手段有效的减少了初始化耗时

    云更新控制

    云控服务作为一种服务端控制客户端的手段在SDK中开发中非常重要,现在的SDK开发可以不支持插件化,但是必须要提供云控服务,以便让服务端能控制SDK,比如在不需要进行数据采集的时候,可以通过云控服务关闭SDK采集功能,在需要的时候在将其打开.

    对本身是基于插件化开发的SDK而言,云控服务更是不可或缺.

    从实现的角度而言,云控服务分为服务端主动和客户端主动.服务端主动是指服务端会将最新的云控开关的信息推送到SDK,而客户端主动则是SDK在进行操作之前会首先请求云控信息.对有推送开发经营的同学而言,这非常容易理解,就是像是为了实现消息推送功能,我们可以通过客户端轮训也可以通过服务端保持长连接进行消息推送一样.

    安全

    SDK自身安全

    为了区分接入者并挑高SDK自身安全性,我们通常会为开发者分配api key和api secret,SDK会读取开发者配置的api key和api secret,并用于随后的网络通信中.这是非常常见的做法,比如当你集成极光推送SDK的时候,它也许需要你提供api key和api secret,如果没有则需要到官网进行申请.

    核心逻辑采用C/C++

    为了安全起见,数据加密类,模块算法类都都应该采用NDK开发,将其封装在so文件当中.有很多开发者不明白为什么这样会增强安全性.这里我们简单的做个说明.由于.so文件是通过c/c++编译出的文件,相对于java的反编译文件来说,可读性更差,另外大部分的Android开发者并不具备较深的C/C++能力,因此一定程度上增加了被破解的能力.

    通讯加密

    针对实际情况对通讯协议进行加密,具体是采用对称加密还是非对称加密,则需要根据实际情况做选择.另外,请尽可能使用https来代替http.

    设备安全

    在很多情况下,比如广告SDK中,有一些开发者会通过虚拟机来刷广告,因此有必要针对此情况做判断.一旦SDK检测出非法请求后可以采取两种方案,一种是SDK拒绝服务,另外一种则是正常服务,SDK会将作弊信息上传至服务器,以便后端服务定向排除数据.

    减少传输数据大小

    在设计SDK和服务端通讯之间的数据协议时,需要根据实际情况考虑,但有以下几条建议值得我们接受:

    • 如果对传输的数据大小有要求,建议对数据进行压缩.
    • 可以采用json/xml/Protobuf等协议,如果它们仍然不能满足则可以考虑自定义二进制协议.

    选择支持最低系统版本

    作为SDK的设计者,面临一个很大的问题是我们不得不考虑开发者应用所支持的系统最小版本,但是在SDK发布之前,我们并不知道会什么样的开发者使用我们提供的服务,因此为了让SDK支持更广泛的设备,我们需要降低最低支持的系统版本.比如现在失眠上主流的系统版本是Android 5.0,那么对SDK而言,起码要支持到Android 4.0,甚至是Android 2.3.

    降低最低支持版本看起来很容易,但是我们不得不做更多的工作来确保SDK能表现出一致的工作行为(通常,我们在SDK内部检测当前系统版本来确定哪些方法可以被调用).更残酷的真相是我们花费了很大的精力去支持2.3,但来自2.3系统版本的请求量却连1%都不到.

    权限管理

    Android中任何开发都避不开权限申请.作为SDK的设计者,对于权限遵循”如无必要,无需增加”,换句话说就是用不到的权限,就不要加上去,这也是我们所谓的最小权限原则,该原则同样适用于普通应用开发.

    在刚接触SDK开发时,某些早期功能需要某些权限,但是后期该功能被砍掉了,但是权限却忘记去掉,这就导致不必要权限仍然存在的情况.

    另外过多的权限申请,会让开发者怀疑你的目的.比如一个广告SDK的你申请照相机权限是想干嘛?恩,我怀疑你在偷拍我….好吧,这里我只是开个玩笑.

    另外,从android 6.0以上,google改变了权限申请的策略,因此需要单独对此做适配.

    日志服务

    无论系统大小,日志服务是基本的服务.一个良好的日志服务能够帮助我们快速的发现问题,定位缺陷,从而获得问题的解决方案.

    SDK的日志服务和其他常见的日志服务并无太大的不同,但是要保证以下几点:

    1. 日志服务能够记录有效的信息,在SDK要关键位置进行打点.
    2. 日志服务上传日志信息到服务器时,要保证最大的可靠性,不能发生上传失败后抛弃日志的情况.
    3. 日志服务不能影响对正常的操作流程有过多的性能影响.SDK产生的日志信息往往是非常多的,因此必须考虑日志IO操作所带来的开销.

    深究API设计

    API的设计在任何开发中都是非常重要的,很多时候软件的质量好不好在API的设计可以得到体现.在普通的应用开发中,API只会在应用开发人员间流通而不会暴露给非本应用开发的其他人员,但是SDK作为一种服务,需要向开发者暴露一部分API.通常我们将内部流通的API称之为内部API,而开放给开发者的称之为SDK API.

    两者使用场景虽然不同,但是都遵循着一些通用的设计规则,这里无法细说,只列出我认为需要重点关注的十一条原则:

    方法名能够表明其用途

    方法名是理解方法含义的第一渠道.一个好的方法名首先是能够向他人展示自身功能,这样做的好处就是能够减少不必要的沟通成本,对于开发者而言,还有什么比直接读代码更直观呢.

    参数的合法性检验

    对参数进行合法性检验是非常重要的,请不要想当然的认为可以用运行时异常来代替.当合法性校验不通过时,针对方法权限不同分别对应不同不同的处理策略:

    • 对于公开方法通过显示检查抛出异常的方式,并且使用javadoc的@throw来说明抛出异常的原因
    • 对于私有方法通过断言的方式来检查参数的合法
    • 检查构造方法的参数的合法性,以使对象处在统一状态
      需要注意,如果检查的代价太大,需要综合考量,比如如果接受的是一个很大的List,此时检查的代价可能很大

    方法要明确其单一的功能

    一个方法应该具有单一的功能,尽可能做更少,但是更专的事情.这也是我们常说的单一职责原则.另外一定要记住宁可提供小而美的方法也不要提供大而全的方法,经验正面大而全的方法往往发生变动,产生风险的可能性更高,因此不如提供更小的方法以便组合使用

    方法异常问题

    对于需要暴露给开发者的方法要及时的抛出可查异常来帮助开发者在编译阶段发现问题,另外,对于运行时异常,SDK设计者必须保证该类异常不会导致宿主程序出问题并且需要告知开发者.

    方法权限控制

    方法的权限也是需要着重考虑的,SDK设计者必须同时从安全和业务的角度考虑哪些方法是可公开的,哪些是不可公开以及哪些是静态的.

    避免过长参数

    过长的参数会造成记忆上困难,需要慎重对待.在无法避免过长参数的情况下,需要考虑其他的方法进行解决:

    a. 通过使用Builder模式来实现
    b. 通过使用辅助类,通常采用静态内部类的方式,具体见静态内部类的使用
    c. 通过将多个参数封装成类对象
    d. 通过将参数拆解成多个方法的参数

    谨慎使用方法重载

    重载不应该让使用者感到疑惑,即不应该出现这种情况:同样的参数,但是开发者不能明确哪个方法会被执行.换言之就是不要产生歧义性.

    另外需要注意,不要存在参数类型经过自动转换就可以运行在另外一个方法的情况,我曾经在code review中看到这样的代码:list中的remove(Object)remove(int),请务必保证自己不会犯类似的错误.尽管在java当中能够使用重载,但是我不建议使用,尤其是不要重载变长参数,在需要重载的时候宁可使用不同方法名来代替也要好的多.关于这点java中提供的ObjectOutputStream类给我们做了很好的示范:它的write对于每个基本类型都有一个变形,比如写出字符,写出boolean等操作,我们发现设计者,并没有使用重载将其设计成write(Long l),write(Boolean b),而是将其设计为writeLong(l),writeBoolean().

    对于构造函数,则可以通过是用静态工厂的方式来代替重载.

    谨慎使用变长参数

    多数情况下不需要使用变长参数,一般方法的参数在5个以上的时候,才 建议使用变长参数.在还有其他非变长参数的情况下,我觉得变长参数放在形参列表的最后.

    避免方法直接返回NUll

    对于需要返回数组或这集合的方法,不要返回null.比如我们去买糕点店买面包,面包没了是一种正常状态,就不应该返回null,而是返回长度为0的数组或集合.

    必要时进行保护性拷贝

    当类接受来自客户端的对象或者需要向客户端返回对象,如果该类不能容忍进来的对象再发生变化,那么有必要对对象进行保护性拷贝.另外要注意参数的合法性检验发生在保护性拷贝之后.
    需要注意的是如果需要进行保护性拷贝的对象非常大,比如list集合中存在十多万个对象,需要权衡处理.

    这十一条原则是我在团队中推广并要求严格遵守的,下面,将对这十条原则分别进行说明.


    SDK开发流程

    关于SDK开发流程,我会从以下三个方面写:一时团队中如何协同开发,二是SDK的持续集成,三是SDK多仓库拆分和管理.

    这三方面会再另外的篇章中展现(具体什么时候写完目前还未确定)


    SDK版本管理策略

    SDK 版本号命名及修改原则

    SDK版本号命名和我们以往的命名规则并无太大不同,通由4部分组成,格式为:
    V主版本号子版本号阶段版本号_日期版本号加希腊字母版本号.比如V1_1_2_161209_beta.

    希腊字母版本号说明

    • Alpha版:内部测试版,此版本表示该软件在该阶段主要是以实现功能为主,Bug相对较多,需要继续修改,通常只在内部流通流通而不对外开放.
    • Beta版:外部测试版,该版本相对Alpha已经有了很大的改进,不存在严重的Bug,但还是存在一些缺陷,需要进一步的测试以检查和消除Bug.
    • RC版:该版本已经相当成熟,不存在导致错误的Bug.与正式版相差无几.
    • Release版:该版本意味着”最终版本”,是最终交付用户或者公开发布的版本,也称为标准版.需要注意的是,该版本在发布的时候回以符合R来代替Release单词.

    版本号修改规则

    1. 主版本号变化:当功能模块有较大的变化或者整体架构发生变化
    2. 子版本号变化:当功能有一定变化
    3. 阶段版本号变化:一般是Bug修复或者较小的变动,根据反馈,需要经常发布修订版本.
    4. 日期版本号(161209):用于记录修改项目的当前日期,每天对项目的修改都要更改日期版本号.
    5. 希腊字母版本号:此版本�号用于标注当前软件处于那个开发阶段,当软件进入到另一个阶段是需要修改.

    API版本管理

    和普通应用API版本管理不同,SDK设计者需要着重关注SDK API的管理.原则上SDK API一旦公开发布后其状态(签名和具体实现)应为不可变.

    对于特殊情况下API的变更,需要遵守”开闭原则”,即一个类,模块,方法应该对扩展开发,对修改关闭.这就要求我们做到以下几点:

    1. 在需要调整SDK API时,优先选择添加新方法,而不是在原方法上修改.对于实现相同功能的新方法,尽可能的要兼容原始方法.
    2. 在需要废除某些方法时,需要在正式版发版前使用@deprecated标识,并给出替代方案和废弃的时间(通常是SDK版本号)

    接入文档和API文档版本管理

    接入文档是用来告诉SDK使用者,如何使用SDK,使用的详细步骤和可能发生的问题,每个公司会有自己的一套规则,这个不需要做太多的解释.

    另外,接入文档通常分为两份:内部版和公开版.内部版通常用于内部开发人员和测试人员,信息较为详细,而公开版则是面向开发者,相比内部版会省略的一些信息.

    API文档其实就是对SDK API的更详细说明,类似java中的api doc,可以借助jdk的自带javadoc直接生成,当然在android studio也提供了便捷的生成方式.

    无论是接入文档还是api说明文档,其变更一般发生在SDK版本发生变化时.当SDK发生变更时,文档必须随之更新,不能出现SDK更新后说明文档不与之匹配的情况.

    集成Demo版本管理

    集成Demo通常是一个简单的app,用来展示如何快速的接入SDK.其版本变更策略和SDK版本的变化保持一致.


    总结

    SDK开发中需要关注的点非常多,每个点都不能用三言两语完成的,后面会在此基础上慢慢的补充.

    展开全文
  • 函数糊涂概念扩散何时了? 近日,国家教育部发文,要求全国高校组织力量建设一批世界水平本科微积分课程。 上世纪30年代,法国布尔巴基数学学派给出了函数的序偶标准定义。 反观国内本科微积分教材,关于函数...
  • RTP、RTCP、RTSP 概念

    千次阅读 2015-03-30 09:50:59
     虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑定到传输层连接(如TCP等),也就是说在整个RTSP连接期间,RTSP用户可打开或者关闭多个对RTSP服务器的可靠传输连接以发出...
  • 先进计算机概念

    千次阅读 2007-07-26 14:02:00
    下载第12章先进计算机概念研究计算机性能与技术是为了使计算机运行得更快,从质量上看,这意味着要减少完成指定计算或运行特定程序的时间。为了提高计算机的速度,我们必须修改已有的电路设计,甚至针对数据流通路...
  • 上个月带一个日本公司老板去一家中国一流互联网企业拜访,看到公司前台处堆积如山的快递盒子和频繁的签收,极为震惊。在日本是不可能的,前台甚至只有一台电话,绝少有私人物品快递到公司。 然而,正是以上的...
  • Matlab概念与功能

    千次阅读 2020-05-19 11:53:32
    其程序由国际一流的专家编制优化,计算功能为matlab赢得了良好的口碑。 绘图功能: 利用matlab绘图十分方便,它可以绘制各种图像,囊括了2d和3d图形,也可以对图像进行修饰控制,以增强图像的表现效果。Matlab提供两...
  • 这个文章我们主要来说一下Consul的基本概念,以及其实现的内部原理,和Eureka的比较。 1.什么是Consul? Consul是一种服务网格解决方案,提供具有服务发现,配置和分段功能的全功能控制平面。 这些功能中的每一个都...
  • Mybatis简介及其核心概念

    千次阅读 2018-08-06 22:43:45
    MyBatis(3.x以前的版本叫ibatis)是一款一流的支持自定义SQL、存储过程和高级映射的持久化框架。MyBatis几 乎消除了所有的JDBC 代码,也基本不需要手工去设置参数和获取检索结果。 MyBatis 能够使用简单的XML格式或...
  • 透视一流团队

    千次阅读 2006-09-27 13:15:00
    公司采用"员工企业单位"概念,动员一部分生产部门的员工加入自愿离职计划,离职自建小型采炭公司,再把炭送到宝德纳莫纳。  这一计划马上受到工会的反对,他们称这为"合同劳工制"。最终,建立了一种新的工作...
  • 流体力学基本概念

    千次阅读 2018-06-17 15:30:12
    迹线(Pathlines):某一流体质点的运动轨迹。 脉线(Streaklines):关注空间某一位置,在经历较短的时间后,可以标识出流动过程中经过该空间点的许多流体质点,所有这些流体质点都在一定的时间内,先后流经这个...
  • 对ESB概念的理解

    千次阅读 2016-05-28 10:12:11
    从 IBM 的立场来说,ESB 不仅仅是一个概念,而是一种中间件模式;它不是某个产品,而是一种全新的集成应用,协调资源和操纵信息的框架。 下面来介绍 ESB 或可以称为 ESB 的中间件产品保护一些特征,有些是必须的,...
  • Golden Gate - 概念和机制

    千次阅读 2020-04-13 13:42:38
    Oracle Golden Gate - 概念和机制 (ogg) Golden Gate(简称OGG)提供异构环境下交易数据的实时捕捉、变换、投递。 OGG支持的异构环境有: GoldenGate能够支持多种拓扑结构,包括一对一,一对多,多对一,层叠...
  • 2017年9月21日,教育部公布了建设世界一流大学和一流学科的重点名单,包括42所一流大学建设高校和95所一流学科建设高校,可谓“犹抱琵芭半遮面,千呼万唤始出来”。 与此前网传名单一致,一流大学被分为A、B两类,除...
  • HDFS一流式数据访问模式来存储超大文件,运行于商用硬件集群上。 一、HDFS 的概念 1、数据块: (1) 每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位 (2) HDFS有数据块的概念,默认是64M,...
  • BAT,IBM,联合利华,宝洁或华为这样的平台我们就不说了——都是一流平台。刚刚毕业的你,尽量选择顶级或最好的平台肯定没错,工作几年后再决定是否到小公司或初创公司,这个顺序如果错了,那么大公司或顶级公司对你...
  • Orchard基本概念快速理解

    千次阅读 2019-07-10 09:26:29
     需要引入一个额外的间接层,展示ASP.NET MVC上提出的概念,将在Orchard概念层中分离。  例如:当请求一个指定的view时,LayoutAwareViewEngine引入 ,  严格地说,它不是一个新的视图引擎,它包含了依赖当前...
  • 这几天断断续续地读完了《三个月成为一流员工》这本小书,受到一些启发。书中讲了一些自己以前没有听过的概念,小记以自励。 书中核心概念有四个:学校人到社会人;知识人到能力人;个体人到单位人;自然人到职业人...
  • 要说构建生态圈这种能力,软件绝对是一流的。互联网软件正是把握这个规律,不断应用最新的软件开发技术和开发模式,不断降低软件的生产成本。 我们当前的编程语言和编程方式,16 年来几乎没有变化。...
  • 几个表示“光”的概念

    千次阅读 2020-10-21 13:51:39
    1、光强、光通量、照度和亮度的概念 光强(发光强度):luminous intensity,指光源在给定方向上单位立体角内所发出的光通量,符号用I表示,单位为坎德拉(cd),1 cd = 1 lm/sr 光通量:luminous flux,指光源单位...
  • laravel 服务容器,容器概念

    千次阅读 2019-11-06 11:38:11
    作为初学者,很多人会在这一个概念上犯难,因此,我打算从一些基础的内容开始讲解,通过理解面向对象开发中依赖的产生和解决方法,来逐渐揭开“依赖注入”的面纱,逐渐理解这一神奇的设计理念。 本文一大半内容都...
  • 其实,读书和吃饭一样,也有个人口味,但是最好不要挑食,人生最大的捷径就是,用时间和生命阅读和拥抱了世上一流的书。史上一流的好书都在这里,找来细细品读吧!   第一,文学不可不读。作家通过语言向人的想象...
  • 初涉服务器领域陌生概念汇总

    千次阅读 2013-07-12 20:52:27
    这么多概念 = =! LAMP,LNMP,Apache, Nginx,Lighttpd,cgi,fastcgi,wsgi,uwsgi,redis,mongodb,flask,django ......
  • iOS开发基本概念问题

    千次阅读 2014-05-05 18:15:38
    、协议的基本概念和协议中方法默认为什么类型 答: OC  中的协议是一个方法列表,且多少有点相关。它的特点是可以被任何 类使用(实现),但它并不是类(这里我们需要注意),自身不会实现这样方法,   ...
  • CMS系统基本概念

    千次阅读 2008-05-09 14:32:00
    超过75个一流公司,包括Ziff- Davis' ZDNet, First Chicago NBD, Bay Networks 和 CNET ,使用StoryServer 3 ,每天提供2500万个网页浏览。 StoryServer3 获得了5个行业奖励,包括UPSIDE杂志的"网络基础组织类最...
  • 信息检索的概念 信息检索(Information Retrieval)是指信息按一定的方式组织起来,并根据信息用户的需要找出有关的信息的过程和技术。狭义的信息检索就是信息检索过程的后半部分,即从 信息集合中找出所需要的信息...
  • C++/CLR 概念原理

    千次阅读 2013-07-16 15:14:51
    一流的 C++ 类支持 --C++ 特色,例如模板和析构函数对于拖管和非拖管类继续有效。实际上, C++/CLI 是你可以 " 表面上 " 在栈或 C++ 本地堆上声明一个 .NET 类型唯一的 .NET 语言。 ④  在 .NET 与 C++ 之间的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,709
精华内容 7,083
关键字:

一流的概念