工欲善其事必先利其器(二)—–vagrant

学会使用虚拟机之后,那么我们一定会面临一个比较棘手的问题:我们应该如何来管理这些虚拟机?因为我们常用的虚拟机都是配置好的,熟悉的环境,熟悉的工具。重复配置无疑是一种浪费时间的行为,为了避免这种浪费,那么我们需要一个强有力的工具vagrant.

什么是vagrant

Vagrant is a tool for building and managing virtual machine environments in a single workflow.

来自于官方的说法,vagrant就是专门用来建立和管理虚拟机环境的工具。

vagrant是用ruby语言编写的,在vagrant中所有的虚拟机环境都来自于一个叫做box的文件,通过 配置Vagrantfile,指定需要使用的box,然后配置cpu核心数量,内存大小,网络,共享文件,登录凭证等信息,可以快速的得到一个已经配置好的虚拟机环境。其实大多数配置都是可以省略的,最便捷的配置文件甚至只有一条配置。

什么场景下应该使用vagrant

抛开场景谈工具都是耍流氓,每一种工具都有它最适合存在的地方。虽然平时作为个人使用的时候,我们大多用来迁移和管理自己的虚拟机,但是我觉得它最实用的地方就是“团队协作”。每个人都会有自己的使用习惯,有些人习惯mac,有些人习惯linux,还有人则习惯用windows。哪怕同样用的是windows,也有win7和win10等各种区别,就算同样用的win7或者win10,那么大家用的IDE也可能都是不一样的。linux更不用说了,对应着各种不同的发行版。这个时候vagrant的强大就体现出来了,不管用户所使用的操作系统是何种类别,都能保证开发环境的一致性。这样可以避免开发过程中,因为环境不一致所带来问题。

获取vagrant

vagrant下载页,  可以获得最新版的vagrnat版本,有debian,windows,centos,mac.arch linux等各种版本可以选择,如果是ubuntu操作系统的话,除了可以使用debian的deb安装包来安装,还可以使用apt命令进行安装

sudo apt install vagrant

不过通过apt安装的vagrant版本不是最新版本,请酌情使用

vagrant操作

vagrant操作系统的基本操作非常简单,只有简单的几条命令

vagrant init  初始化虚拟机

vagrant up 启动虚拟机

vagrant provision 应用虚拟机配置

vagrant halt  关闭虚拟机

vagrant destroy 摧毁虚拟机

vagrant ssh  进入虚拟机终端

获得vagrant官方基本系统环境hashicorp/precise64的方法非常简单,只需要运行命令


vagrant init hashicorp/precise64
vagrant up

就可以获得一个基础的虚拟机环境了,不过需要注意的是,因为vagrant的box有时候体积比较大,在执行下载的过程中可能会非常缓慢甚至是没有办法获得资源的情况,如果在运行命令的过程中出现超时或者卡主的情况,可以在后面找到解决的办法

vagrant的box

vagrant官方提供了一系列的box下载,在下载页中,支持最多的虚拟机就是virtualbox,

vagrant中添加box的命令如下

vagrant box add  box名称 box路径     ps:可以是网络路径或者是本地路径

可以添加本地路径的box,那么我们可以先从下载页把box下载到本地,然后本地环境添加hashicorp/precise64,接着执行

vagrant init hashicorp/precise64
vagrant up

就能快速得到一个可用的虚拟机环境了

如果要查看当前可用的box,可以使用命令
vagrant box list

制作属于自己的box

box除了可以从网上获取之外,还自己制作,除了可以从无到有制作一个box,还可以在已有的box之上,添加一些定制功能,把它变成只属于自己的box

在vagrant中有一条命令,可以打包属于自己的虚拟机

vagrant package --base 虚拟机标识 --output box名称

ps:虚拟机标识不是在虚拟机页面显示的名称,这个标识需要通过命令vboxmanage list vms来得到,其中vboxmanage命令是virtualbox自带的工具,如果是其他虚拟机的话,则需要其他工具来获取

在使用vagrant中可能会遇到的问题

  • 在执行vagrant up过程中,出现超时或者卡住的现象,这个是因为网络的问题,因为在国内的网络速度不是很给力,而且还有GFW的存在可能没有办法获取到资源,不过这个可以通过添加本地box的方式或者通过科学上网工具来解决
  • vagrant up过程中,ssh配置失败,这个现象发生的原因有很多种,调试方法是打开gui选项,看看是否出现故障,其次是可以通过ssh vagrant@ip  password:vagrant 登录到虚拟机 手动配置ssh权限即可
  • 更多问题请仔细阅读vagrant官方文档,或者通过stackoverflow寻找解决方案

 

 

工欲善其事必先利其器(一)—–虚拟机

作为一名程序员,大多数时候都是在自己熟悉的环境里工作,永远是熟悉的操作系统,熟悉的那个IDE,熟悉的那个环境,仿佛一切都那么自然。但是如果永远是这样的话, 那么生活就显得太安逸了,实际生活中我们总会遇到各种各样复杂的情况。比如说,我们常常在windows或者是mac下工作,但是有些时候服务器的环境往往都是linux,为了熟悉服务器上的环境,我们必须要去熟悉并且灵活这种工具。但是在现实生活中,拥有多台物理机的成本还是相对于普通人来说,还是比较昂贵的,这个时候使用虚拟机把现有的硬件进行虚拟化来达到拥有多台计算机的效果就显得十分有必要了。

使用虚拟机的情景

  • 宿主机是windows或者mac,想要学习linux或者是unix
  • 沙箱环境,构建一个和本机相同环境的沙箱,当需要运行一些可能对计算机造成损害的软件的时候,先在沙箱中运行检查软件是否有危害,而后迁移到本机上,保证计算机的安全性
  • 工作环境迁移,一个用的十分熟练的系统必定是经过自己打磨许久之后逐渐磨合的一个超级工具,装了很多熟悉的软件,到一个新的环境下 之后,重新安装上这些东西会非常的麻烦,但是如果选择在虚拟机里进行工作的话,就可以在任何地方迅速的搭建起熟悉的环境

虚拟机软件常见的种类

  • Vmware ,横跨windows,linux,mac各种平台(注:在mac下叫FUSION,其他平台一般叫WORKSTATION),性能强大,功能齐全,唯一不足的地方就是价格了,每个月$249.99,多0.01美金就是250了
  • Hyper-V, 微软的产品,采用hypervisor的技术,据说可以和Vmware比肩,优点非常明显,windows自带,直接开箱即用,但这也是最大的缺点,只能在windows下用。
  • parallels,mac用户的福音,mac下的专属软件,可以非常方便快速的在mac下执行windows软件,价格每年$79.99,不算很贵,缺点就是只能在mac下运行。
  • VirtualBox,我最钟爱的虚拟机软件,强大的跨平台能力,支持windows,linux,mac,solaris等各种平台,体积轻巧,并且开源信仰。

不一样的VirtualBox

尽管virtualbox在功能上来说,它没有vmware那么强大,并且对于windows用户来说没有内置的Hyper-v来那么方便快捷,但是它拥有的特性:开源,跨平台,对我来说都有着深深的吸引力,我觉得对于大部分人来说都是一个非常好的选择,而且如果使用vagrant的话,就更能体会到它的优势所在了

  • 获取virtualbox

virtualbox的安装包可以在virtualbox的官方下载页获得

ubuntu用户可以通过apt工具来获得

sudo apt update

sudo apt install VirtualBox-5.2

centos用户可以直接通过yum工具来获得

yum install VirtualBox-5.2

使用virtualbox需要注意的地方

  • 虚拟硬盘,使用virtualbox创建虚拟硬盘的时候有三个选项,分别是VDI,VHD,VMDK,其中VHD是微软虚拟磁盘文件,一般应用于virtual PC,而VMDK则是由vmware创建的磁盘,如果创建这种磁盘可以共享给vmware使用,而VDI则是virtualbox自己创建的虚拟硬盘了,如果没有特殊需求的话,只要选择VDI类型的磁盘就可以了
  • 网卡,在virtualbox中的网卡有6种,分别是网络地址转换(NAT),NAT网络,桥接网卡,内部网络,仅主机(host-only)网络,通用驱动。

网络地址转换和NAT网络的区别并不是很大,都是把主机当成路由器来使用,同一网段下的多个虚拟机之间可以相互访问,并且虚拟机能访问到外部网络,包括互联网

桥接网卡则是把虚拟机当成局域网下一台真实的主机一样使用,使用桥接网卡的虚拟机可以使用宿主机相同网段的ip地址,并且可以让局域网下其他的计算机访问到

内部网络是虚拟机自成网络,虚拟机内部可以互相通信,但是不能对外,也不能访问互联网

仅主机网络,相当于用一根网线把虚拟机和主机连接起来,相互可以访问,但是如果需要访问其他地方的话,则需要其他配置

多种网卡有所区别,但是在virtualbox中是可以配置多块网卡的,所以使用还是非常方便的

使用virtualbox可能遇到的问题

  • 虚拟机不能全屏

virtualbox的安装目录下,有名为VBoxGuestAdditions.iso的镜像文件,这是virtualbox的增强工具,只有安装了增强工具的虚拟机才能使用文件夹共享,目录同步,虚拟机全屏等一些扩展功能

  • 不能选择64位操作系统的虚拟机

造成这个原因的极有可能是,在bios没有开启cpu的虚拟化功能,修复这个操作需要进入到bios开去cpu 虚拟化,不同的硬件厂商标准不一样,这里不多介绍

  • 虚拟机中复制的文件或者文字不能粘贴到宿主机

打开虚拟机设置,在常规选项》高级, 启用共享剪切板和拖放功能

  • 虚拟机卡顿不流畅

需要多分配一些内存给虚拟机,虚拟机和真实的电脑差不多,也是需要消耗计算机资源的

结语

如果用来学习多个操作系统的话,除了选择虚拟机之外,还可以使用双系统,双系统的优势是两个操作系统都可以享受完整的计算机cpu和内存等资源,而且互不干扰,缺点就是两个系统不能同时启动,而使用虚拟机的话,那就意味着你的电脑配置相对来说需要好一点。如果计算机的配置不是很高的话,还是推荐使用双系统。

解决前端跨域的方法

引言:由于浏览器的安全性能问题,导致ajax非同源请求无法访问,但是有些时候我们必须要用到这一功能,所以整理出四种层面不同思想来解决这个问题

 

一、Javascript

在javaCript层面,有一种耳熟能详的手段来解决跨域问题,那就是jsonp,原理是在客户端注册一个callback函数,然后把callback的名字传给服务器,此时,服务器先生成 json 数据。
然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)

 

二、Php

在html直接请求同源地址的接口文件,如api.php,然后在api.php中利用curl扩展去请求需要请求的页面获取相关数据,然后返回给前端页面,这种方式相当与代理,利用本地同源的页面去请求非同源页面

 

三、HTML5

HTML5之前的标准是没有办法进行跨域的,但是但HTML5中新增加的特性可以实现这一功能,通过设置Access-Control-Allow-Origin头可以在页面中允许特定页面或者所有页面的请求,在php中可以使用header函数设置

header('Access-Control-Allow-Origin:*');

 

四、Nginx

Nginx服务器层面的解决方法和php中类似,也是代理模式,前端页面请求同源地址,然后用nginx重写规则将此请求代理到需要请求的非同源页面,达到一种欺骗浏览器的效果。

 

尾语:部分浏览器经过设置以后也可以解决跨域问题,但是作为程序员,我们不能把希望寄托在用户的身上,所以还是从上述解决方案中挑选为佳

javascript生成随机数

引子:
在写程序间突然需要用到随机数,于是用到了js的Math.random随机函数,生成指定范围内的随机数,根据网上流传的写法生成指定范围内的随机数如下

function random(min, max){
    return Math.round(Math.random()*(max-min))+min;
}

var zero = one = two = three = 0;
for(var i=0;i<10000;i++){
    var num = random(0,3);
    if(num==0){
        zero++;
    }else if(num==1){
        one++;
    }else if(num==2){
        two++;
    }else if(num==3){
        three++;
    }else{
        console.log("assert false");
    }
}
console.log(zero,one,two,three);

经过10000次计算,在0-3范围内生成的结果数据如下,0=1670次 1=3348次 2=3266次 3=1717次
发现这个算法略坑,min以及max的边界命中率简直低的可怜,并不是一个均匀分布,而是正态分布,为了满足需求,只能对算法进行重写了

Math.random()函数

根据官方的定义:random() 方法可返回介于 0 ~ 1 之间的一个随机数。那么猜想在0~1之间,如果对生成的随机数进行四舍五入,那么该概率在(0,1)是呈均匀分布状态,也就是说出现0或者是1的概率是相等的,接下来验证猜想

function guess(){
    var zero = 0;
    var one = 0;
    for(var i=0;i<100000;i++){
        Math.round(Math.random()) ==1 ? one++ : zero++;
    }
    return zero+"  "+one;
}

for(var i=0;i<10;i++){
    var g = guess();
    console.log(g);
}

运行结果如下
50093  49907
49787  50213
49862  50138
49948  50052
49820  50180
50158  49842
50179  49821
49967  50033
49920  50080
50063  49937
从数据结果中可以看出,对随机数四舍五入之后,出现0和出现1的概率呈均匀分部状态,测试次数无穷大的情况下,那么出现1或0的概率的极限都是1/2,根据这个特性,由二进制开始联想,那么在指定位数的情况下,在这个区间内,每一个数出现的概率也是均匀分布的,概率各为1/2^n,于是就有了下面的验证程序如下

var Helpers = {
    getbit: function(num){
        var bit = 0;
        while(num>0){
            num = num>>1;
            bit++;
        }
        return bit;
    },
    randomBin : function(times){
        var num = Math.round(Math.random());
        while(times>1){
            num = (num<<1) + Math.round(Math.random());
            times--;
        }
        return num;
    },
    random : function(min,max){
        var num = max-min;
        var times = this.getbit(num);
        do{
            var binNum = this.randomBin(times);
        }while(!(binNum<=num));
        return binNum+min;
    }
}

var zero = one = two = three = 0;
for(var i=0; i<=10000; i++){
    var n = Helpers.random(0,3);
    if(n == 0){
        zero++;
    }else if(n == 1){
        one++;
    }else if(n == 2){
        two++;
    }else if(n == 3){
        three++;
    }
}
console.log(zero,one,two,three);

运行10000次的结果:2523 2548 2416 2514 ,根据数据可以看出,这种生成随机数的方式比之第一种要更加的均匀

尾语:

虽然复用代码是一个好习惯,但是不要盲目的去复用他人的代码,靠巧合编程是无法长久的,惟有不断的提升自己,才会觉得数学与计算机真的是非常的有趣。

vagrant学习笔记

什么是vagrant
简而言之,vagrant就是一个用来管理虚拟机文件的工具
为什么要使用vagra
如果经常玩虚拟机的话,就会知道,当你需要新建一个虚拟环境的时候,总是要重复的安装操作系统,以及操作系统必备的工具,如果每次新建虚拟环境都要重复这一过程,那将不仅是身体上的煎熬,还有思想上的绑架,所幸的是vagrant已经帮你搞定好了这一切,只要你拥有vagrant,git,VitualBox(or VMWare),就能轻松的接入vagrant

如何使用vagrant
在vagrant中,所有的虚拟机环境都应该被称之为box,当然你也可以叫做盒子,甚至叫包也无所谓,但目的是要理解这个box其实就是把所有的虚拟机中的文件进行了打包而已,所以当你决定要使用某种操作系统的时候,应该去选择对应的box,在vagrant中,下载box非常的简单,只需要一行命令就可以了,比如我需要安装个hashicorp/precise64的box,那么就用下面的命令

vagrant box add hashicorp/precise64

这个下载过程一般都要持续个几分钟,在此期间可以去小酌一杯咖啡
添加box之后,就需要进行初始化了,使用vagrant init hashicorp/precise64命令来初始化box

vagrant init hashicorp/precise64

接着直接vagrant up启动box,就会看到虚拟机已经启动precise64了

vagrant up

再接着就是vagrant ssh登陆到命令行管理界面,剩下的就是和linux操作系统终端一样了,非常的easy

vagrant ssh

 

vagrant还有什么功能
vagrant除了能够管理虚拟机之外,还有很多非常强大的功能,比如说目录映射,把虚拟机的某一个目录映射到宿主机上,可以让你在宿主机修改文件从而同步更新虚拟机中文件的效果,我觉得这个功能真的是非常的black,它能够让你在windows环境下开发,跑的却是linux的服务,同时具有服务器环境一致的属性绝对是团队开发的神器,省去了不断ftp代码然后测试的烦恼了。

作为程序员,偷懒是一种必备的品质,如果你也觉得vagrant不错的话,赶紧access to vagrant吧!

我的HTTPS升级之路

引子:

最近在一篇文章中了解到EFF(电子前哨基金会)为了推广https协议,成立了一个Let's encrypt项目,可以发放免费的证书,此证书可以被大多数主流浏览器所信任,于是就顺手给自己的网站弄了一个。

准备:
工具:certbot
环境:centOS7

获取Certbot工具:
根据我在网上了解到的信息,获取certbot工具有三种方法
第一种是通过git在github中下载

git clone https://github.com/certbot/certbot.git

第二种是通过epel-release软件源,这个软件源有许多yum中没有的软件包,包括certbot

yum install epel-release
yum install certbot

第三种是通过wget来进行下载

wget https://dl.eff.org/certbot-auto

由于钟爱github,熟悉git所以直接使用git下载好了
执行命令

git clone https://github.com/certbot/certbot.git

 

生成证书:
下载完了之后,会创建一个certbot的目录,然后使用certbot-auto工具来生成证书,如果certbot没有可执行权限,还需要执行命令chmod u+x certbot-auto

cd certbot
./certbot-auto certonly --standalone --email crisen@crisen.org  -d www.crisen.org

然后agree协议 静静等待生成证书即可
出现下面提示就说明安装好了

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/your.domain.com/fullchain.pem. Your cert
   will expire on 20XX-09-23. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

一般来说证书会生成在/etc/letsencrypt/live目录下

部署证书:
接着把证书的公钥和私钥配置到nginx的ssl目录下,创建软链接

ln -s /etc/letsencrypt/live/www.crisen.org/fullchain.pem   /usr/local/nginx/conf/ssl/www.crisen.org.crt
ln -s /etc/letsencrypt/live/www.crisen.org/privkey.pem    /usr/local/nginx/conf/ssl/www.crisen.org.key

当然直接复制过去也是可行的

cp -i  /etc/letsencrypt/live/www.crisen.org/fullchain.pem  /usr/local/nginx/conf/ssl/www.crisen.org.crt
cp -i /etc/letsencrypt/live/www.crisen.org/privkey.pem  /usr/local/nginx/conf/ssl/www.crisen.org.key

接下来只要配置 nginx 的https服务就可以了 下面是我的nginx服务器配置文件 仅做参考

server {
    listen 80;
    listen 443 ssl http2;
    ssl_certificate /usr/local/nginx/conf/ssl/www.crisen.org.crt;
    ssl_certificate_key /usr/local/nginx/conf/ssl/www.crisen.org.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 10m;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_buffer_size 1400;
    add_header Strict-Transport-Security max-age=15768000;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate   /usr/local/nginx/conf/ssl/www.crisen.org.crt;
    server_name www.crisen.org;
    access_log /data/wwwlogs/www.crisen.org_nginx.log combined;
    index index.html index.htm index.php;
    include /usr/local/nginx/conf/rewrite/none.conf;
    root /data/wwwroot/profiles;
    if ($ssl_protocol = "") { return 301 https://$host$request_uri; }

    location ~ [^/]\.php(/|$) {
        #fastcgi_pass remote_php_ip:9000;
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
        }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
        expires 30d;
        access_log off;
        }
    location ~ .*\.(js|css)?$ {
        expires 7d;
        access_log off;
    }
}
配置好之后重启nginx服务器

效果测试:
然后进入到www.crisen.org测试一下

出现了可信任的证书 到此配置完毕

踩过的坑:
服务器操作系统版本过低:
开始的时候我的操作系统是centOS5.1版本的,内置的python只有2.4,结果没有办法启动certbot出现,

因为certbot-auto是python写的,并且必须要2.6以上的版本才可以,

网上查看了许多文档,也确定了certbot只支持更加现代的操作系统
解决办法:备份网站数据,升级服务器操作系统

ps:互联网的技术是日新月异的,本文仅做参考用.

强大的程序员不一定是优秀的,但是优秀的程序员一定会变的很强大

1.Care about your craft  关心你的技艺
2.Think about your work  思考!你的工作
3.Provide options,don't make lame excuses  提出各种选择,不要找蹩脚的借口
4.don't live with broken wendows 不要容忍破窗户
5.be a catalyst for change 做变化的催化剂
6.remember the big picture 记住大图景
7.make quality a requirements issue 使质量成为需求问题
8.invest Regularly in your knowledge portfolio 定期为你的知识资产投资
9.critically analyze what you read and hear 批判性的分析你读到的和听到的
10.it's both what you say and the way you speak it 你说什么和你怎么说同样重要
11.Don't repeat yourself 不要重复自己
12.make it easy to reuse 让复用变的容易
13.eliminate effects between unrelated things 消除无关事物之间的影响
14.there no final decisions 不存在最终决策
15.use tracer bullets to find the target 只用曳光弹找到目标
16.prototype to learn 为了学习而制作原型
17.program close to the problem domain 靠近问题领域编程
18.estimate to avoid surprice 估算,避免发生意外
19.iterate the schedule with the code 通过代码对进度表进行迭代
20.keep knowledge in plain text 使用纯文本保存你的知识
21.use the power of command shells 利用shell命令力量
22.use a single editor well 用好一种编辑器
23.always use source code controll 总是使用源码控制
24.fix the problem not to blame 要修正问题,而不是发出指责
25.don not panic when debuging 不要恐慌
26.'select' isn't broken ‘select’没有问题
27.don't assume it,prove it 不要假定 要证明
28.learn a text manipulation language 学习一种文本操作语言
29.write code that write code 编写能写代码的代码
30.you can't write perfect software 你不可能写出完美的软件
31.design with contracts 通过合约进行设计
32.crash earlt 早崩溃
33.if it can't happen,use assertions to ensure that it won't 如果它不可能发生,用断言确保它不会发生
34.use exceptions for exceptional problems 将异常用于异常的问题
35.finish what you start 有始有终
36.minimize coupling between modules 使模块之间的耦合减至最少
37.configure,don't integrate 要配置 不要集成
38.put abstractions in code,details in metadata 将抽象放进代码,细节放进元数据
39.analyze workflow to improve concurrency 分析工作流以改善并发性
40.design useing service 用服务进行设计
41.always design for concurrency 总是为并发性进行设计
42.separate views for modules 使视图和模型分离
43.use blackboards to coordinate workflow 用黑板协调工作流
44.don't program by coincidence 不要靠巧合编程
45.estimate the order of your algorithms 估算算法的阶
46.test your estimates 测试你的估算
47.refactor early,refactor often 早重构,常重构
48.design to test 为测试而设计
49.test your software,or your users will 测试你的软件,否则你的用户就得测试
50.don't use wizard code you don't understand 不要使用你不理解的向导代码
51.don't gather requirements - dig for them 不要搜集需求,挖掘它们
52.work with a user to think like a user 与用户一同工作,像用户一样思考
53.abstracts live longer than details 抽象比细节活的更长久
54.use a project glossary 使用项目词汇表
55.don't think outside the box - find the box 不要在盒子外面思考,找到这个盒子
56.listen to nagging doubts - start when you're ready 倾听反复出现的疑虑,等你准备好再开始
57.some things are better done than described 有些事情实践比理论来的更好
58.don't be a slave to formal methods 不要做形式方法的奴隶
59.exoensive tools don't produce better designs 昂贵的工具不一定能做出更好的设计
60.organize around functionality,bot job functions 围绕功能进行组织,而不是围绕工作职务
61.don't use manual procedures 不要使用手工流程
62.test early,test often,test automatically 早测试 常测试 自动化测试
63.codeing ain't done till all the test run 要通过全部测试,编码才算完成
64.use saboteurs to test your testing 通过蓄意破坏来测试你的测试
65.test state coverage,not codeing coverage 测试状态覆盖 而不是代码覆盖
66.find bug once 一个bug只抓一次
67.treat English as just another programming language 把英语当作又一种编程语言
68.build document in,don't bolt it once 把文档建在版本中,不要拴在外面
69.gently exceed your users' exceptations  温和的超出用户的期望
70.sign your work 在你的作品上签名

----摘自《程序员的修炼--从小工到专家》