五月
23
2017

SSH 方式下为 Git 设置多用户登录 补充说明

之前在 SSH 方式下为 Git 设置多用户登录 中对 Git 配置多个不同的账号访问不同的仓库做了说明。今天早上提交代码的时候,意外发现提交者的信息有些问题。提交者的名称和邮箱,变成了公司仓库的名称和邮箱。 仔细检查了一下,发现自己在多用户登录不同仓库的配置上,配置得不够到位,这也是很多相关的配置教程中没有提到的。 现在,将遗漏的配置项,做一个补充说明。 取消全局用户设置 Hy369 在自己的 Git 配置中遇到的问题,就是所有仓库的提交者信息,都是统一的。问题就出在配置提交信息的时候,采用的 git config --global 进行配置的。这个时候,Git 软件自然就是取用全局配置了。因此,我们先把全局配置的用户信息去掉。相关命令为: git config --global --unset user.name git config --global --unset user.email 那个,至于不取消有没有影响,Hy369 还没有测试过,如果哪位朋友测试过了,烦请告知一下。 为 Git 仓库单独配置用户信息 直接到每个克隆的仓库中,单独配置用户信息即可。相关命令为: git config --add user.name xxx git config --add user.email xxx@xxx.com 至此,新的提交者信息就是你需要的了。
五月
22
2017

SSH 方式下为 Git 设置多用户登录

特别说明 这个是目前开发过程中经常要遇到的问题了。呃,一般是系统装了环境之后会用到。又是 Hy369 要说的老话了:唉,不想每次都去谷歌百度了! 功能说明 针对 GIT 的 SSH 的方式,实现用不同的账号和密钥访问不同的仓库。 可能的场景: 通过电子邮箱1和密钥1访问 Github 通过电子邮箱2和密钥2访问 Oschina 通过电子邮箱3和密钥3访问公司内部仓库 实现方式 第一步 生成各个站点需要用到的密钥 相关命令与推荐参数: # 切换到 .ssh 目录(建议,可偷懒) cd ~/.ssh # 生成密钥文件 ssh-keygen -t rsa -C "youremail@mail.com" -f 密钥文件名,如:id_rsa.github # 加载私钥文件 ssh-add 密钥文件名 命令说明: 推荐切换到 .ssh 目录下面,Windows 环境下,.ssh目录在 C:\Users\登录账号同名文件夹\。这样可以在输入生成文件路径的时候省事。若不存在这个文件夹,直接创建即可。 ssh-keygen -t 参数表示生成的类型为:rsa ssh-keygen -C 注释,推荐带上,这样拷贝公钥到 Git 仓库中时,Web端一般会自动把 Comment 作为公钥名称显示,嗯,又可以偷懒了。 ssh-keygen -f 输出密钥文件的路径,很多教程中,都没有这个选项,这样就导致执行时会询问把文件用什么名字存在哪里。个人认为:不利于偷懒,所以推荐带这个选项咯。 后续的所有询问直接回车搞定了,一般不设置密码,如果需要,请自行百度,Hy369 还没有使用过,没有发言权。 命令执行完以后, .ssh 目录下,就会生成密钥文件,带 .pub 的就是密钥的公钥。 需要多少个不同的密钥,便执行上述步骤即可。 第二步 配置 config 文件 在 .ssh 目录下,创建一个 config 文件。注意没有后缀。实现为不同的仓库配置不同的密钥: 配置文件样例: # oschina Host git.oschina.net HostName git.oschina.net PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa.oschina User Hylin # github Host github.com HostName github.com PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa.github User Hy369 至此,配置完成,正常情况下,便可使用了。 第三步 添加公钥到网站 登录自己的 Github 或者 Oschina,公司的请咨询运维。一般在个人设置的界面,有个 SSH 的选项或者导航标签,点击进去,就可以看到添加公钥的界面。 将公钥中的字符,全部复制到文本框内,然后设置一个便于自己区分的名字,提交即可。 第四步 测试 ssh -T git@github.com # 如果出现了这个提示,直接输入 yes 确认即可 The authenticity of host 'github.com (192.30.255.113)' can't be established. RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8. Are you sure you want to continue connecting (yes/no)? # 以下是成功之后的信息: Hi Hy369! You've successfully authenticated, but GitHub does not provide shell access. 如果没有成功,试着备份或者重命名一下 .ssh 目录下的 known_hosts 文件,再次尝试。 如果还是有问题,请针对具体问题,利用搜索引擎查找一下解决方案。或者,你也可以给 Hy369 发邮件,Hy369 会为你提供力所能及的帮助。 SSH 方式下为 Git 设置多用户登录 补充说明
七月
29
2016

Python 字符串方法汇总

注意 需要注意的是,以下罗列的所有字符串方法,均不会修改原始的字符串数据。故需要返回字符串的那些方法,均是返回一个新的字符串。 字符串方法 方法 描述 s.captitalize() 首字母变大写 s.center(width [, pad]) 在长度为 width 的字段内将字符串居中,pad 为填充字符 s.count(sub [, start [, end]]) 计算指定子字符串 sub 出现的次数 s.decode([encoding [, errors]]) 解码一个字符串并返回一个 Unicode 字符串(只能用于字节字符串) s.encode([encoding [, errors]]) 返回一个字符串的编码版本(只能用于 Unicode 字符串) s.endswitch(suffix [, start [, end]]) 检查字符串是否以 suffix 结尾 s.expandtabs([tabsize]) 使用空格替换制表符 s.find(sub [, start [, end]]) 找到指定字符串 sub 首次出现的位置,否则返回 -1 s.format(*args, **kwargs) 格式化 s s.index(sub [, start [, end]]) 找到指定字符串 sub 首次出现的位置,否则报错 s.isalnum() 检查所有字符是否都为字母或数字 s.isalpha() 检查所有字符是否都为字母 s.isdigit() 检查所有字符是否都为数字 s.islower() 检查所有字符是否都为小写 s.isspace() 检查所有字符是否都为空白 s.istitle() 检查所有字符串是否为标题字符串(每个单词首字母大写) s.isupper() 检查所有字符是否都为大写 s.join(t) 使用 s 作为分隔符连接序列 t 中的字符串 s.ljust(width [, fill]) 在长度为 width 的字符串内左对齐 s.lower() 字符串转换为小写 s.lstrip([chrs]) 删掉字符串前面的空白或指定的 chrs 字符 s.partition(sep) 使用分隔符字符串 sep 划分一个字符串。返回一个元组(head, sep, tail),如果未找到 sep,则返回 (s, "", "") s.replace(old, new [, maxreplace]) 替换一个子字符串 s.rfind(sub [, start [, end]]) 找到一个字符串最后出现的位置,否则返回 -1 s.rindex(sub [, start [, end]]) 找到一个字符串最后出现的位置,否则报错 s.rjust(width [, fill]) 在长度为 width 的字符串内右对齐 s.rpartition(sep) 从字符串结尾开始,使用分隔符字符串 sep 划分字符串 s s.rsplit([sep [, maxsplit]]) 使用 sep 作为分隔符对 一个字符串从后往前进行划分。 maxsplit 决定划分的最大次数,省略 maxsplit 时,结果与 split() 方法完全相同 s.rstrip([chrs]) 删除字符串尾部的空白或者指定的 chrs 字符 s.split([sep [, maxsplit]]) 使用 sep 作为分隔符对一个字符串进行划分。 maxsplit 决定划分的最大次数 s.splitlines([keepends]) 将字符串分为一个行列表。如果 keepends 为 1,则保留各行最后的换行符 s.startswith(prefix [, start [, end]]) 检查一个字符串是否以 prefix 开头 s.strip([chrs]) 删掉字符串开头与结尾的空白或指定的 chrs 字符 s.swapcase() 将大写转换为小写,小写转换为大写 s.title() 将字符串转换为标题格式 s.translate(table [, deletechars]) 使用一个字符转换表 table 转换字符串,删除 deletechars 中的字符 s.upper() 将一个字符串转换为大写形式 s.zfill(width) 在字符串的左边填充 0,直至其宽度为 width 说明 下面是 s.format() 方法的应用举例: >>> a = "Your name is {0} and your age is {age}" >>> a.format("Mike", age=40) 'Your name is Mike and your age is 40' >>> table th:first-of-type { width:220px;}
七月
28
2016

Python 链表方法汇总

以下罗列链表可用的方法: append(x) 把一个元素添加到链表的结尾,相当于 a[len(a):] = [x]。 extend(L) 通过添加指定链表的所有元素来扩充链表,相当于 a[len(a):] = L。 insert(i, x) 在指定位置插入一个元素,第一个参数是准备插入到其前面的那个元素的索引,例如 a.insert(0, x) 会将 x 插入到整个链表的前面,而 a.insert(len(a), x) 则会实现与 a.append(x) 一样的功能。 remove(x) 删除链表中的值为 x 的第一个元素,如果没有这样的元素,将返回一个错误。 pop([i]) 从链表的指定位置删除元素,并返回被删除的元素。如果没有指定索引,a.pop() 将会删除并返回最后一个元素。(注意:方法 i两边的方括号表示该参数可选,并非是要求输入一对方括号) index(x) 返回链表中第一个值为 x 的元素的索引。如果没有匹配的元素则返回一个错误。 count(x) 返回 x 在链表中出现的次数。 sort() 对链表中的元素按升序进行排序。 reverse() 倒置整个链表(即最前的变成最后,最后的变成最前的)。 链表方法示例: >>> a = [66.6, 333, 333, 1, 1234.5] >>> print a.count(333), a.count(66.6), a.count('x') 2 1 0 >>> a.insert(2, -1) >>> a.append(333) >>> a [66.6, 333, -1, 333, 1, 1234.5, 333] >>> a.index(333) >>> a 1 >>> a.remove(333) >>> a [66.6, -1, 333, 1, 1234.5, 333] >>> a.reverse() >>> a [333, 1234.5, 1, 333, -1, 66.6] >>> a.sort() >>> a [-1, 1, 66.6, 333, 333, 1234.5]
七月
21
2016

通过反射类实现对类的 protected 和 private 属性及方法的测试

在编写类(Class)的时候,部分方法及属性为了限制访问,会设置为 private 和 protected 权限,尤其是对于类属性来说,为了安全方面的原因,多数是不允许直接访问的。而在测试时,由于无法在外部直接访问,这样的设置会让测试变得很麻烦。当然,所谓的麻烦,也就是在 Hy369 知道 ReflectionObject 相关的类之前的事,因为从麻烦变得简单了,所以 Hy369 的 PHP 博客中便有了这样一篇文章。

阅读全文>>

三月
24
2016

PHP 正则中的断言

在阅读 symfony 源码的过程中,发现了一个不认识的正则表达式:([^ ]+?)(?: |(?<!\\)"|(?<!\\)'|$),看了很久,还真没有弄懂是要干嘛。 所以赶紧查看了一下 PHP 文档正则表达式的部分,直到翻看到断言这一章的时候,终于算是找到答案了。原来这是运用了 PHP 正则中的断言。 一个断言就是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符。简单的断言代码有\b、\B、 \A、 \Z、\z、 ^、$ 等等。 更加复杂的断言以子组的方式编码。 断言有两种类型: 前瞻断言:用于从当前位置向前测试,注意前瞻表示向当前字符串之后的字符串进行测试。 后瞻断言:用于从当前位置向后测试,注意后瞻表示向当前字符串之前的字符串进行测试。 两种断言又细分为积极断言和消极断言。 前瞻断言中的积极断言以 (?= 开始,用于断言向前测试的结果为真;前瞻断言中的消极断言以 (?! 开始,用于断言向前的测试结果为假。例如: \w+(?=;) 匹配一个单词紧跟着一个分号但是匹配结果不会包含分号 foo(?!bar) 匹配所有后面没有紧跟 ”bar” 的 ”foo” 字符串 但是有个特别需要注意的地方: (?!foo)bar 不能用于测试 bar 前面出现的不是 foo,因为前瞻断言的特性,他只能判断向右的字符串不是 foo,所以在 (?:foo) 遇到 bar 的时候永远为真(我想,此时电脑的心声是:这熊孩子,明明是 bar,还问我是不是 foo,哈哈)。 要实现上例中原本要实现的想法,就得换个法子了,也就是接下来登场的后瞻断言。 后瞻断言中的积极断言以 (?<=开头,消极断言以 (?<! 开头。例如: (?<!foo)bar 用于查找任何前面不是 ”foo” 的 ”bar”。 后瞻断言的内容被严格限制为只能用于匹配定长字符串。但是,如果有多个可选分支, 它们不需要拥有相同的长度。比如 (?<=bullock|donkey) 是允许的, 但是 (?<!dogs?|cats?) 将会引发一个编译期的错误。 多个断言(任意顺序)可以同时出现。 比如 (?<=\d{3})(?<!999)foo 匹配前面有三个数字但不是 ”999” 的字符串 ”foo”。注意, 每个断言独立应用到对目标字符串该点的匹配。 首先它会检查前面的三位都是数字, 然后检查这三位不是 ”999”。 这个模式不能匹配 ”foo” 前面有三位数字然后紧跟 3 位非 999 共 6 个字符的字符串,比如, 它不匹配 ”123abcfoo”。 匹配 ”123abcfoo” 这个字符串的模式可以是 (?<=\d{3}…)(?<!999)foo。 这种情况下,第一个断言查看(当前匹配点)前面的 6 个字符,检查前三个是数字, 然后第二个断言检查(当前匹配点)前三个字符不是 ”999”。 断言可以以任意复杂度嵌套。 比如 (?<=(?<!foo)bar)baz 匹配前面有 ”bar” 但是 ”bar” 前面没有 ”foo” 的 ”baz”。 另外一个模式 (?<=\d{3}…(?<!999))foo 则匹配前面有三个数字字符紧跟 3个不是 999 的任意字符的 ”foo”。 断言子组时非捕获子组,并且不能用量词修饰, 因为对同一件事做多次断言是没有意义的.如果所有的断言都包含一个捕获子组, 那么为了在整个模式中捕获子组计数的目的,它们都会被计算在内。然而, 子字符串的捕获仅可以用于正面断言,因为对于消极的断言是没有意义的。 将断言计算在内,可以拥有的最大子组数量是 200 个。
十一月
25
2015

git 中 通过 https 方式的仓库设置密码

写在前面 除了最开始使用 git 的时候,是通过 git 方式访问 git 仓库,后来都是使用 https 方式来进行仓库的访问。 通过 https 方式访问仓库,有个最大的问题,就是每次拉取提交的时候,都需要填写账户和密码,很是麻烦。后来在网上搜索了相应的解决方式,因为觉得使用得并非很频繁,所以就没有作记录,而是需要的时候再找度娘问。 既然现在发这篇博客了,那自然是因为被这些反复的操作弄烦了,嘿嘿。 设置密码的方式 采用默认时间记住密码 git 默认的记住密码的时长为 15 分钟,相关指令如下: git config --global credential.helper cache 自定义记住密码时间 通过下面的指令,可以自定义 git 记住密码的时间: git config credential.helper 'cache --timeout=3600' 永久保存密码 既然提到了自定义密码时间,那么自然要涉及到永久保存密码的问题了。指令自然还是有的: git config --global credential.helper store 其它处理方式 上面提供的方法都是涉及到指令的,这里还有个不涉及到指令的方法,而是在 git 仓库的地址上做文章,你可以将自己的 git 地址修改为如下的样式: http://yourname:password@git.oschina.net/name/project.git 以上信息收集于网络,现在附上来源地址:点击这里
十月
21
2015

数据库设计中的十四个技巧原则

1. 原始单据与实体之间的关系 可以是一对一、一对多、多对多的关系。在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体。 在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体。 这里的实体可以理解为基本表。明确这种对应关系后,对我们设计录入界面大有好处。 〖例1〗:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表、社会关系表、工作简历表。 这就是“一张原始单证对应多个实体”的典型例子。 2. 主键与外键 一般而言,一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键,也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。 主键与外键的设计,在全局数据库的设计中,占有重要地位。当全局数据库的设计完成以后,有个美国数据库设计专家说:“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核心(数据模型)的高度抽象思想。因为:主键是实体的高度抽象,主键与外键的配对,表示实体之间的连接。 3. 基本表的性质 基本表与中间表、临时表不同,因为它具有如下四个特性: 原子性。基本表中的字段是不可再分解的。 原始性。基本表中的记录是原始数据(基础数据)的记录。 演绎性。由基本表与代码表中的数据,可以派生出所有的输出数据。 稳定性。基本表的结构是相对稳定的,表中的记录是要长期保存的。 理解基本表的性质后,在设计数据库时,就能将基本表与中间表、临时表区分开来。 4. 范式标准 基本表及其字段之间的关系, 应尽量满足第三范式。但是,满足第三范式的数据库设计,往往不是最好的设计。 为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。 〖例2〗:有一张存放商品的基本表,如表1所示。“金额”这个字段的存在,表明该表的设计不满足第三范式, 因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。 在Rose 2002中,规定列有两种类型:数据列和计算列。“金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。 表1 商品表的表结构 商品名称 商品型号 单价 数量 金额 电视机 29吋 2,500 40 100,000 5. 通俗地理解三个范式 通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解): 第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解; 第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性; 第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。 没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余。 6. 要善于识别与正确处理多对多的关系 若两个实体之间存在多对多的关系,则应消除这种关系。消除的办法是,在两者之间增加第三个实体。这样,原来一个多对多的关系,现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个实体,实质上是一个较复杂的关系,它对应一张基本表。一般来讲,数据库设计工具不能识别多对多的关系,但能处理多对多的关系。 〖例3〗:在“图书馆信息系统”中,“图书”是一个实体,“读者”也是一个实体。这两个实体之间的关系,是一个典型的多对多关系:一本图书在不同时间可以被多个读者借阅,一个读者又可以借多本图书。为此,要在二者之间增加第三个实体,该实体取名为“借还书”,它的属性为:借还时间、借还标志(0表示借书,1表示还书),另外,它还应该有两个外键(“图书”的主键,“读者”的主键),使它能与“图书”和“读者”连接。 7. 主键PK的取值方法 PK是供程序员使用的表间连接工具,可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时,建议字段的个数不要太多,多了不但索引占用空间大,而且速度也慢。 8. 正确认识数据冗余 主键与外键在多表中的重复出现, 不属于数据冗余,这个概念必须清楚,事实上有许多人还不清楚。非键字段的重复出现, 才是数据冗余!而且是一种低级冗余,即重复性的冗余。高级冗余不是字段的重复出现,而是字段的派生出现。 〖例4〗:商品中的“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,它就是冗余,而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性,因为同一数据,可能从不同时间、地点、角色上多次录入。因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)。 9. E--R图没有标准答案 信息系统的E--R图没有标准答案,因为它的设计与画法不是惟一的,只要它覆盖了系统需求的业务范围和功能内容,就是可行的。反之要修改E--R图。尽管它没有惟一的标准答案,并不意味着可以随意设计。好的E—R图的标准是:结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。 10 . 视图技术在数据库设计中很有用 与基本表、代码表、中间表不同,视图是一种虚表,它依赖数据源的实表而存在。视图是供程序员使用数据库的一个窗口,是基表数据综合的一种形式, 是数据处理的一种方法,是用户数据保密的一种手段。为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。 若三层视图仍不够用, 则应在视图上定义临时表,在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。 对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统,视图的作用更加重要。这些系统的基本表完成物理设计之后,立即在基本表上建立第一层视图,这层视图的个数和结构,与基本表的个数和结构是完全相同。并且规定,所有的程序员,一律只准在视图上操作。只有数据库管理员,带着多个人员共同掌握的“安全钥匙”,才能直接在基本表上操作。请读者想想:这是为什么? 11. 中间表、报表和临时表 中间表是存放统计数据的表,它是为数据仓库、输出报表或查询结果而设计的,有时它没有主键与外键(数据仓库除外)。临时表是程序员个人设计的,存放临时记录,为个人所用。基表和中间表由DBA维护,临时表由程序员自己用程序自动维护。 12. 完整性约束表现在三个方面 域的完整性:用Check来实现约束,在数据库设计工具中,对字段的取值范围进行定义时,有一个Check按钮,通它定义字段的值城。 参照完整性:用PK、FK、表级触发器来实现。 用户定义完整性:它是一些业务规则,用存储过程和触发器来实现。 13. 防止数据库设计打补丁的方法是“三少原则” 一个数据库中表的个数越少越好。只有表的个数少了,才能说明系统的E--R图少而精,去掉了重复的多余的实体,形成了对客观世界的高度抽象,进行了系统的数据集成,防止了打补丁式的设计; 一个表中组合主键的字段个数越少越好。因为主键的作用,一是建主键索引,二是做为子表的外键,所以组合主键的字段个数少了,不仅节省了运行时间,而且节省了索引存储空间; 一个表中的字段个数越少越好。只有字段的个数少了,才能说明在系统中不存在数据重复,且很少有数据冗余,更重要的是督促读者学会“列变行”,这样就防止了将子表中的字段拉入到主表中去,在主表中留下许多空余的字段。所谓“列变行”,就是将主表中的一部分内容拉出去,另外单独建一个子表。这个方法很简单,有的人就是不习惯、不采纳、不执行。 数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点。“三少”是一个整体概念,综合观点,不能孤立某一个原则。该原则是相对的,不是绝对的。“三多”原则肯定是错误的。试想:若覆盖系统同样的功能,一百个实体(共一千个属性) 的E--R图,肯定比二百个实体(共二千个属性) 的E--R图,要好得多。 提倡“三少”原则,是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系统集成为应用数据库,将应用数据库集成为主题数据库,将主题数据库集成为全局综合数据库。集成的程度越高,数据共享性就越强,信息孤岛现象就越少,整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。 提倡“三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改,使企业数据库变成了随意设计数据库表的“垃圾堆”,或数据库表的“大杂院”,最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章,不计其数,导致企事业单位的信息系统无法维护而瘫痪。 “三多”原则任何人都可以做到,该原则是“打补丁方法”设计数据库的歪理学说。“三少”原则是少而精的原则,它要求有较高的数据库设计技巧与艺术,不是任何人都能做到的,因为该原则是杜绝用“打补丁方法”设计数据库的理论依据。 14. 提高数据库运行效率的办法 在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是: 在数据库物理设计时,降低范式,增加冗余, 少用触发器, 多用存储过程。 当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方式用C++语言计算处理完成之后,最后才入库追加到表中去。这是电信计费系统设计的经验。 发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。水平分割的做法是,以该表主键PK的某个值为界线,将该表的记录水平分割为两个表。若发现某个表的字段太多,例如超过八十个,则垂直分割该表,将原来的一个表分解为两个表。 对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。 在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。 总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三个层次上同时下功夫。 上述十四个技巧,是许多人在大量的数据库分析与设计实践中,逐步总结出来的。对于这些经验的运用,读者不能生帮硬套,死记硬背,而要消化理解,实事求是,灵活掌握。并逐步做到:在应用中发展,在发展中应用。 该文转发自百度经验,原文地址:点击这里
九月
23
2015

PHP运算符优先级

运算符的优先级不能不说重要,但是记忆起来还是觉得有些麻烦。每次拿不准的时候就去查找手册,也稍微显得有些麻烦,所以还是把这个收录到自己的PHP博客中,作为常规PHP资料储备吧。

阅读全文>>

九月
07
2015

PHP PSR-2 代码风格规范(中文版)

PSR-2 代码风格规范 本篇规范是 PSR-1 基本代码规范的继承与扩展。 本规范希望通过制定一系列规范化PHP代码的规则,以减少在浏览不同作者的代码时,因代码风格的不同而造成不便。 当多名程序员在多个项目中合作时,就需要一个共同的编码规范, 而本文中的风格规范源自于多个不同项目代码风格的共同特性, 因此,本规范的价值在于我们都遵循这个编码风格,而不是在于它本身。 关键词 “必须”("MUST")、“一定不可/一定不能”("MUST NOT")、“需要”("REQUIRED")、“将会”("SHALL")、“不会”("SHALL NOT")、“应该”("SHOULD")、“不该”("SHOULD NOT")、“推荐”("RECOMMENDED")、“可以”("MAY")和”可选“("OPTIONAL")的详细描述可参见 RFC 2119 。 1. 概览 代码必须遵循 PSR-1 中的编码规范 。 代码必须使用4个空格符而不是 tab键 进行缩进。 每行的字符数应该软性保持在80个之内, 理论上一定不可多于120个, 但一定不能有硬性限制。 每个 namespace 命名空间声明语句和 use 声明语句块后面,必须插入一个空白行。 类的开始花括号({)必须写在函数声明后自成一行,结束花括号(})也必须写在函数主体后自成一行。 方法的开始花括号({)必须写在函数声明后自成一行,结束花括号(})也必须写在函数主体后自成一行。 类的属性和方法必须添加访问修饰符(private、protected 以及 public), abstract 以及 final 必须声明在访问修饰符之前,而 static 必须声明在访问修饰符之后。 控制结构的关键字后必须要有一个空格符,而调用方法或函数时则一定不能有。 控制结构的开始花括号({)必须写在声明的同一行,而结束花括号(})必须写在主体后自成一行。 控制结构的开始左括号后和结束右括号前,都一定不能有空格符。 1.1 例子 以下例子程序简单地展示了以上大部分规范: <?php namespace Vendor\Package; use FooInterface; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class Foo extends Bar implements FooInterface { public function sampleFunction($a, $b = null) { if ($a === $b) { bar(); } elseif ($a > $b) { $foo->bar($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body } } 2. 通则 2.1 基本编码规则 代码必须符合 PSR-1中的所有规范。 2.2 文件 所有PHP文件必须**使用Unix LF (linefeed)作为行的结束符。 所有PHP文件必须以一个空白行作为结束。 纯PHP代码文件必须省略最后的 ?> 结束标签。 2.3 行 行的长度一定不能**有硬性的约束。 软性的长度约束一定要限制在120个字符以内,若超过此长度,带代码规范检查的编辑器一定要发出警告,不过一定不可发出错误提示。 每行不应该多于80个字符,大于80字符的行应该折成多行。 非空行后一定不能有多余的空格符。 空行可以使得阅读代码更加方便以及有助于代码的分块。 每行一定不能存在多于一条语句。 2.4 缩进 代码必须使用4个空格符的缩进,一定不能用 tab键 。 备注: 使用空格而不是tab键缩进的好处在于, 避免在比较代码差异、打补丁、重阅代码以及注释时产生混淆。 并且,使用空格缩进,让对齐变得更方便。 2.5 关键字以及 true/false/null PHP所有关键字必须全部小写。 常量 true 、false 和 null 也必须全部小写。 3. namespace 以及 use 声明 namespace 声明后必须插入一个空白行。 所有 use 必须 在 namespace 后声明。 每条 use 声明语句必须只有一个 use 关键词。 use 声明语句块后必须要有一个空白行。 例如: <?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; // ... additional PHP code ... 4. 类、属性和方法 此处的“类”泛指所有的class类、接口以及traits可复用代码块。 4.1 扩展与继承 关键词 extends 和 implements 必须写在类名称的同一行。 类的开始花括号必须独占一行,结束花括号也必须在类主体后独占一行。 <?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable { // constants, properties, methods } implements 的继承列表也可以分成多行,这样的话,每个继承接口名称都必须分开独立成行,包括第一个。 <?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable, \Serializable { // constants, properties, methods } 4.2 属性 每个属性都必须添加访问修饰符。 一定不可使用关键字 var 声明一个属性。 每条语句一定不可定义超过一个属性。 不要使用下划线作为前缀,来区分属性是 protected 或 private。 以下是属性声明的一个范例: <?php namespace Vendor\Package; class ClassName { public $foo = null; } 4.3 方法 所有方法都必须添加访问修饰符。 不要使用下划线作为前缀,来区分方法是 protected 或 private。 方法名称后一定不能有空格符,其开始花括号必须独占一行,结束花括号也必须在方法主体后单独成一行。参数左括号后和右括号前一定不能有空格。 一个标准的方法声明可参照以下范例,留意其括号、逗号、空格以及花括号的位置。 <?php namespace Vendor\Package; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } } 4.4 方法的参数 参数列表中,每个逗号后面必须要有一个空格,而逗号前面一定不能有空格。 有默认值的参数,必须放到参数列表的末尾。 <?php namespace Vendor\Package; class ClassName { public function foo($arg1, &$arg2, $arg3 = []) { // method body } } 参数列表可以分列成多行,这样,包括第一个参数在内的每个参数都必须单独成行。 拆分成多行的参数列表后,结束括号以及方法开始花括号必须写在同一行,中间用一个空格分隔。 <?php namespace Vendor\Package; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body } } 4.5 abstract、final 以及 static 需要添加 abstract 或final 声明时, 必须写在访问修饰符前,而 static 则必须写在其后。 <?php namespace Vendor\Package; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } } 4.6 方法及函数调用 方法及函数调用时,方法名或函数名与参数左括号之间一定不能有空格,参数右括号前也 一定不能有空格。每个参数前一定不能有空格,但其后必须有一个空格。 <?php bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3); 参数可以分列成多行,此时包括第一个参数在内的每个参数都必须单独成行。 <?php $foo->bar( $longArgument, $longerArgument, $muchLongerArgument ); 5. 控制结构 控制结构的基本规范如下: 控制结构关键词后必须有一个空格。 左括号(后一定不能有空格。 右括号)前也一定不能有空格。 右括号)与开始花括号{间一定有一个空格。 结构体主体一定要有一次缩进。 结束花括号}一定在结构体主体后单独成行。 每个结构体的主体都必须被包含在成对的花括号之中, 这能让结构体更加结构话,以及减少加入新行时,出错的可能性。 5.1 if 、elseif 和 else 标准的 if 结构如下代码所示,留意 括号、空格以及花括号的位置, 注意 else 和 elseif都与前面的结束花括号在同一行。 <?php if ($expr1) { // if body } elseif ($expr2) { // elseif body } else { // else body; } 应该使用关键词elseif代替所有else if ,以使得所有的控制关键字都像是单独的一个词。 5.2 switch 和 case 标准的 switch 结构如下代码所示,留意括号、空格以及花括号的位置。 case 语句必须相对 switch 进行一次缩进,而 break 语句以及 case 内的其它语句都必须相对 case 进行一次缩进。 如果存在非空的 case 直穿语句,主体里必须有类似 // no break 的注释。 <?php switch ($expr) { case 0: echo 'First case, with a break'; break; case 1: echo 'Second case, which falls through'; // no break case 2: case 3: case 4: echo 'Third case, return instead of break'; return; default: echo 'Default case'; break; } 5.3 while 和 do while 一个规范的 while 语句应该如下所示,注意其 括号、空格以及花括号的位置。 <?php while ($expr) { // structure body } 标准的 do while 语句如下所示,同样的,注意其 括号、空格以及花括号的位置。 <?php do { // structure body; } while ($expr); 5.4 for 标准的 for 语句如下所示,注意其 括号、空格以及花括号的位置。 <?php for ($i = 0; $i < 10; $i++) { // for body } 5.5 foreach 标准的 foreach 语句如下所示,注意其 括号、空格以及花括号的位置。 <?php foreach ($iterable as $key => $value) { // foreach body } 5.6 try catch 标准的 try catch 语句如下所示,注意其 括号、空格以及花括号的位置。 <?php try { // try body } catch (FirstExceptionType $e) { // catch body } catch (OtherExceptionType $e) { // catch body } 6. 闭包 闭包声明时,关键词 function 后以及关键词 use 的前后都必须要有一个空格。 开始花括号必须写在声明的同一行,结束花括号必须紧跟主体结束的下一行。 参数列表和变量列表的左括号后以及右括号前,必须不能有空格。 参数和变量列表中,逗号前必须不能有空格,而逗号后必须要有空格。 闭包中有默认值的参数必须放到列表的后面。 标准的闭包声明语句如下所示,注意其 括号、逗号、空格以及花括号的位置。 <?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body }; 参数列表以及变量列表可以分成多行,这样,包括第一个在内的每个参数或变量都必须单独成行,而列表的右括号与闭包的开始花括号必须放在同一行。 以下几个例子,包含了参数和变量列表被分成多行的多情况。 <?php $longArgs_noVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) { // body }; $noArgs_longVars = function () use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_longVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_shortVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ($var1) { // body }; $shortArgs_longVars = function ($arg) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; 注意,闭包被直接用作函数或方法调用的参数时,以上规则仍然适用。 <?php $foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 ); 7. 总结 以上规范难免有疏忽,其中包括但不仅限于: 全局变量和常量的定义 函数的定义 操作符和赋值 行内对齐 注释和文档描述块 类名的前缀及后缀 最佳实践 本规范之后的修订与扩展将弥补以上不足。 资料来源 RSR-2 代码风格规范 点击这里