常见的洗钱方法

常见的洗钱方法有:

  • 旅行支票:海关会对于通关者携带的现金要求申报,未申报者超过限制者没收,但不会对携带旅行支票者做金额的限制,重点在于无背书转让给第三者,因为支票被存入银行兑现,最终会回到原发票人的手中。
  • 在赌场以代币间接兑换:在赌场中兑换成代币,再将代币直接交付给洗钱的受益人。再由他去将代币兑换回现金(通常需要5%左右的手续费),在外可声称在赌场内赌赢的。这样可以避免透过纸钞上的编号直接追查到洗钱的受益人。常用于各国可将代币兑换回现金的职业赌场。
  • 购买已经中奖的彩票或马票:与银行勾结,以高价向得主私下购买已得奖的票券,并公开兑换。
  • 购买无记名债券或期货
  • 购买古董珠宝或具价值收藏品、高价中古精品:利用低买高卖的假买卖,将钱以合法的交易方式,洗到目的账号。此方式亦常用于收贿的收钱方式;或购买具价值的古董珠宝或收藏品,再讹称为自家收藏品在市场上放售,一般会购买没有记号的物品如文物、邮票或历史悠久的名厂乐器。或私下购买多部名车,中古私人飞机,珠宝名牌等高价值物转售。
  • 纸上公司的假买卖:用空壳、信用不良、股份公司做假交易、股票投资、偿还债务等方式洗钱。
  • 购买保险:将大笔金额投保,期间亦可不断提升保金,转换保险计划,待一定年数后取回,届时可疑的因素已遭淡化。
  • 基金会:不肖政客,成立基金会,假捐赠给基金会,诱骗企业捐款,再掏空。企业或财团,利用假捐赠给自己能掌控的基金会,左手搬钱到右手,逃漏所得税。政客或企业利用赈灾名义募款,可是募到的善款私自挪用,或用各种名目扣住善款于私人户头。在跨国洗钱活动中,以各地不同慈善名义的基金会中互相转换款额。
  • 跨国多次转汇与结清旧账户:利用转汇的相关单据有保存期限的漏洞。
  • 直接跨国搬运:利用专机或具有海关免验的身份者,直接把钱搬到外国,常用100美元的纸钞方式运送。
  • 人头账户:由于最怕黑吃黑,怕人头到银行声称存折与提款卡与印章丢失,另行申请新的存折与提款卡并变更印鉴,进行盗领。所以通常用于人头本身所不知的外国开户。
  • 外币活存账户:使用多次小额存款的方式存入,再到外国提领外币。俗称“蚂蚁搬砖”,常配合“人头账户”使用。
  • 跨国交易:常见于无实体商品的产业。利用交易金额造假灌水的方式,先透过合法的方式将金钱汇往外国掮客的账户,再通过外国账户分钱,分清原本的交易金额、掮客的佣金与原本要洗出去的钱;或利用各地的商品贸易,例如以过高金额购买普通消费品,将大量款项汇到国外账户,装作用以支付买货款项。反过来亦可将商品高价出售,让国外的洗钱伙伴将款项汇进国内。
  • 地下汇兑:常见于不肖的卖珠宝金饰的银楼。除了非法兑换外币以外,甚至可将现金兑换为外国的无记名与背书的支票,供客户至外国的账户存入。
  • 跨国企业的资金调度:常见于金融业,银行或保险业等,常以大批的现金纸钞进行跨国搬运。例如以麻绳捆绑、纸箱方式搬运。
  • 百货公司的礼券:具有高度的流通性,但由于具有不易兑换回现金的特性,故需有一定的人脉,才方便消化礼券。例如转卖给各公司的员工福利机构,将礼券做为其各公司员工的节假日奖金方式发放。就这样把礼券洗到不知情的第三者手中,原礼券持有人则取回接近等值的现金。
  • 人头炒楼:使用人头购买房地产,向承包商或开发商以市价五至七折买入,以现金支付。然后在短期内快速脱手(例如预售屋在交屋前),获利约50%-100%。
  • 假借贷:常用于收贿或贪污。收钱的人持有对方开立的远期兑现的本票或支票。即使被查到这张本票或支票,可声称为借贷关系。等风头过了或不在其位,没有明显的对价关系时,再把本票或支票转手给第三者,或是扎进银行兑现。或是贪污被揭发的人说要还钱,但开立本票或支票,只要没有兑现,就没有真正的还钱。
  • 伪币或伪钞:将伪币或伪钞,通过多次小金额消费行为,或是利用自动贩卖机找零行为,或是纸钞兑换成硬币的机器。将伪币或伪钞洗成真钱。
  • 黑道:购入价值的毒品贩毒、地下枪械等。将赃款转嫁给他人。
  • 比特币(Bitcoin)等加密货币:基于比特币等加密货币的匿名性,且可自由、不记名的产生不同的比特币钱包,搭配混币服务,难以追踪真实身份,是近年来常见的洗钱工具。
  • 第三方或者第四方支付平台:部分第三方支付平台存在账户未实名注册、管理不规范等问题,致使一些账号可以在网络上直接买卖,部分平台沦为电信诈骗团伙套取、漂白非法资金的“绿色通道”。诈骗团伙利用第三方支付平台转移赃款和洗钱的手段一般有3种:通过第三方支付平台发行的商户POS机虚构交易套现;将诈骗得手的资金转移到第三方支付平台账户,在线购买游戏点卡、比特币等物品后转卖套现;将赃款在银行账户和第三方支付平台之间多次转账切换,逃避公安追查。

Windows下 NTP时间服务器设置

NTP时间服务器
pool.ntp.org: public ntp time server : https://www.ntppool.org/zh/

pool.ntp.org 是一个以时间服务器的大虚拟集群为上百万的客户端提供可靠的 易用的 网络时间协议(NTP)服务的项目

NTP池正在为世界各地成百上千万的系统提供服务。 它是绝大多数主流Linux发行版和许多网络设备的默认“时间服务器”


国内NTP服务 http://ntp.org.cn/pool.php

设置

Windows 可以使用系统内置的ntp客户端: 以管理员权限在命令行运行如下指令:

w32tm /config /syncfromflags:manual /manualpeerlist:"0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org"

这在Windows 2003及之后的版本中被支持。 如果您使用旧版的Windows,您可以尝试如下指令:

net time /setsntp:"0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org"

作为管理员,右键任务栏的时钟,选择“更改日期和时间设置…”,并且在“Internet时间”选项卡下输入服务器名也能达到同样的效果。

免费SSL证书 – Let’s Encrypt 与 certbot 延期

给网站加了SSL,用的 Let’s Encrypt 。后来看有效期只有90天,官网推荐用 certbot  延期,开始感觉挺麻烦,但看到一篇文章,写的很好,转贴留存一下!

文章出自:https://ksmx.me/letsencrypt-ssl-https/

现在用 Let’s EncryptStartSSL 的免费证书有效期是1年,1年后需要手动更换。配置过程还挺麻烦的。

更推荐 Let’s Encrypt,虽然有效期只有3个月,但可以用 certbot 自动续期,完全不受影响。而且 Let’s Encrypt 因为有了 certbot 这样的自动化工具,配置管理起来非常容易。

生成 Let’s Encrypt 证书

Let’s Encrypt 证书生成不需要手动进行,官方推荐 certbot 这套自动化工具来实现。3步轻松搞定:

  1. 下载安装 certbot (Let’s Encrypt项目的自动化工具)
  2. 创建配置文件
  3. 执行证书自动化生成命令

下面的教程运行在 Arch Linux 上,其他操作系统也大同小异。你可以在 certbot 网站上,选择你的 Web Server 和 操作系统,就能看到对应的安装和配置教程。

1. 下载安装 certbot

在 Arch Linux 上,安装很简单:

$ sudo pacman -Syu
$ sudo pacman -S certbot

2. 创建配置文件

先创建存放配置文件的文件夹:

$ sudo mkdir /etc/letsencrypt/configs

编辑配置文件:

$ sudo vim /etc/letsencrypt/configs/example.com.conf

把 example.com 替换成自己的域名,配置文件内容:

# 写你的域名和邮箱
domains = example.com
rsa-key-size = 2048
email = your-email@example.com
text = True

# 把下面的路径修改为 example.com 的目录位置
authenticator = webroot
webroot-path = /var/www/example

这里需要解释一下,上面配置文件用了 webroot 的验证方法,这种方法适用于已经有一个 Web Server 运行中的情况。certbot 会自动在 /var/www/example 下面创建一个隐藏文件 .well-known/acme-challenge ,通过请求这个文件来验证 example.com 确实属于你。外网服务器访问 http://www.example.com/.well-known/acme-challenge ,如果访问成功则验证OK。

我们不需要手动创建这个文件,certbot 会根据配置文件自动完成。

3. 执行证书自动化生成命令

一切就绪,我们现在可以运行 certbot 了。

$ sudo certbot -c /etc/letsencrypt/configs/example.com.conf certonly

## 片刻之后,看到下面内容就是成功了
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem.

如果运行顺利,所有服务器所需要的证书就已经生成好了。他们被放在了 /etc/letsencrypt/live/example.com/ 下:

$ ls /etc/letsencrypt/live/example.com/
cert.pem #server cert only
privkey.pem #private key
chain.pem #intermediates
fullchain.pem #server cert + intermediates

配置 Nginx 加入证书

到这里已经成功一大半了,只需要配置 Nginx 支持刚刚生成的证书。而且这个配置有最佳实践可以参考,访问:Mozilla SSL Configuration Generator,这是 Mozilla 搞得一个 HTTPS 配置文件自动生成器,支持 Apache,Nginx 等多种服务器。按照这个配置文件,选择 Intermediate 的兼容性。这里生成的配置文件是业界最佳实践和结果,让 Nginx 打开了各种增加安全性和性能的参数。

默认配置文件是这样的:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # intermediate configuration. tweak to your needs.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    resolver <IP DNS resolver>;

    ....
}

请根据自己的服务配置修改和添加内容,重点只需要关注6行

server {
	listen 443 ssl http2;
	....
	ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
	ssl_dhparam /etc/nginx/ssl/dhparam.pem;

	ssl_trusted_certificate /etc/letsencrypt/live/example.com/root_ca_cert_plus_intermediates;

	resolver <IP DNS resolver>;
	....
}

这6行中,部分文件还不存在,逐个说明。

首先是第一行 listen 443 ssl http2; 作用是启用 Nginx 的 ngx_http_v2_module 模块 支持 HTTP2,Nginx 版本需要高于 1.9.5,且编译时需要设置 --with-http_v2_module 。Arch Linux 的 Nginx 安装包中已经编译了这个模块,可以直接使用。如果你的 Linux 发行版本中的 Nginx 并不支持这个模块,可以自行 Google 如何加上。

ssl_certificate 和 ssl_certificate_key ,分别对应 fullchain.pem 和 privkey.pem,这2个文件是之前就生成好的证书和密钥。

ssl_dhparam 通过下面命令生成:

$ sudo mkdir /etc/nginx/ssl
$ sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

(可选)ssl_trusted_certificate 需要下载 Let’s Encrypt 的 Root Certificates,不过根据 Nginx 官方文档 所说,ssl_certificate 如果已经包含了 intermediates 就不再需要提供 ssl_trusted_certificate,这一步可以省略:

$ cd /etc/letsencrypt/live/example.com
$ sudo wget https://letsencrypt.org/certs/isrgrootx1.pem
$ sudo mv isrgrootx1.pem root.pem
$ sudo cat root.pem chain.pem > root_ca_cert_plus_intermediates

resolver 的作用是 “resolve names of upstream servers into addresses”, 在這個配置中,resolver 是用來解析 OCSP 服務器的域名的,建议填写你的 VPS 提供商的 DNS 服务器,例如我的 VPN 在 Linode,DNS服务器填写:

resolver 106.187.90.5 106.187.93.5;

Nginx 配置完成后,重启后,用浏览器测试是否一切正常。

$ sudo systemctl restart nginx

这时候你的站点应该默认强制使用了 HTTPS,并且浏览器地址栏左边会有绿色的小锁:

自动化定期更新证书

Let’s Encrypt 证书有效期是3个月,我们可以通过 certbot 来自动化续期。

在 Arch Linux 上,我们通过 systemd 来自动执行证书续期任务。

$ sudo vim /etc/systemd/system/letsencrypt.service
[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
ExecStartPost=/bin/systemctl reload nginx.service

然后增加一个 systemd timer 来触发这个服务:

$ sudo vim /etc/systemd/system/letsencrypt.timer
[Unit]
Description=Monthly renewal of Let's Encrypt's certificates

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

启用服务,开启 timer:

$ sudo systemctl enable letsencrypt.timer
$ sudo systemctl start letsencrypt.timer

上面两条命令执行完毕后,你可以通过 systemctl list-timers 列出所有 systemd 定时服务。当中可以找到 letsencrypt.timer 并看到运行时间是明天的凌晨12点。

在其他 Linux 发行版本中,可以使用 crontab 来设定定时任务,自行 Google 吧。

用专业在线工具测试你的服务器 SSL 安全性

Qualys SSL Labs 提供了全面的 SSL 安全性测试,填写你的网站域名,给自己的 HTTPS 配置打个分。

如果你完全按照我上面教程配置,遵循了最佳实践,你应该和我一样得分是 A+

一些文件比对和合并的资料

(最近整理一下)

FC

(CMD命令行)

The fc command has been included in Microsoft operating systems since MS-DOS 3.3 and is included in all versions of Microsoft Windows.

C:\Users\Administrator>fc /?

比较两个文件或两个文件集并显示它们之间

的不同

FC [/A] [/C] [/L] [/LBn] [/N] [/OFF[LINE]] [/T] [/U] [/W] [/nnnn]
    [drive1:][path1]filename1 [drive2:][path2]filename2
FC /B [drive1:][path1]filename1 [drive2:][path2]filename2

  /A         只显示每个不同处的第一行和最后一行。
   /B         执行二进制比较。
   /C         不分大小写。
   /L         将文件作为 ASCII 文字比较。
   /LBn       将连续不匹配的最大值设置为指定
              的行数。
   /N         在 ASCII 比较上显示行数。
   /OFF[LINE] 不要跳过带有脱机属性集的文件。
   /T         不要将制表符扩充到空格。
   /U         将文件作为 UNICODE 文本文件比较。
   /W         为了比较而压缩空白(制表符和空格)。
   /nnnn      指定不匹配处后必须连续
              匹配的行数。
   [drive1:][path1]filename1
              指定要比较的第一个文件或第一个文件集。
   [drive2:][path2]filename2
              指定要比较的第二个文件或第二个文件集。

COMP

(CMD命令行)

A newer command, fc was added in DOS 3.3 which allows for line comparisons in addition to binary comparisons.

C:\Users\Administrator>comp /?

比较两个文件或两个文件集的内容。

COMP [data1] [data2] [/D] [/A] [/L] [/N=number] [/C] [/OFF[LINE]]

  data1      指定要比较的第一个文件的位置和名称。
   data2      指定要比较的第二个文件的位置和名称。
   /D         以十进制格式显示差异。
   /A         以 ASCII 字符显示差异。
   /L         显示不同的行数。
   /N=number  只比较每个文件中第一个指定的行数。
   /C         比较文件时 ASCII 字母不区分大小写。
   /OFF[LINE] 不要跳过带有脱机属性集的文件。

要比较文件集,请在 data1 和 data2 参数中使用通配符。

——————————-

GNU DiffUtils for Windows

(CMD命令行)

显示文件之间的差异

http://gnuwin32.sourceforge.net/packages/diffutils.htm

——————————-

Diff Text – The Online Compare Plain Text & Find Differences Web Page

http://www.diff-text.com/

WinMerge

(桌面程序)

Windows visual diff and merge for files and directories

https://sourceforge.net/projects/winmerge/

Selection Diff Tool

(Web程序)

Microsoft Office 2013 app which reports the differences between two blocks of plain text.

Note: This will not work with previous versions of Office.

https://store.office.com/zh-cn/app.aspx?assetid=WA103863850&ui=zh-CN&rs=zh-CN&ad=CN&appredirect=false

The XML Diff and Patch GUI Tool

https://msdn.microsoft.com/en-us/library/aa302295.aspx

shtml中的脚本 – SSI 服务器端包含 (Server Side Includes)

服务器端包含

 

介绍

服务器端包含(Server Side Includes),通常简称为SSI,是HTML页面中的指令,在页面被提供时由服务器进行运算,以对现有HTML页面增加动态生成的内容,而无须通过CGI程序提供其整个页面,或者使用其他动态技术。

对什么时候用SSI,而什么时候用某些程序生成整个页面的权衡,取决于页面中有多少内容是静态,有多少内容需要在每次页面被提供时重新计算。SSI是一种增加小段信息的好方法,诸如当前时间。如果你的页面大部分是在被提供时生成的,那就要另找方案了。

。将服务器信息添加到一个 HTML 文档。包括以下的形式:

<!--#command variablename="value"-->
Whether or not you can use SSI on your site depends on your provider. Ask your favourite support person if you can use SSI, what server software is used and if there are any special techniques, conditions or rules. For example, on my site I can only use SSI in files that have an .shtml extension instead of the normal .html one. You also have to ask what path to files to use.

Unfortunately, not all includes explained here work for all servers. For example, the #hide and #show includes are specific to WebStar. With Apache server software, you can achieve the same things by using #if and #endif.

更改时间格式

Before starting to use server side includes, you need to configure a number of things. For starters, choose a format for date and time you like (the #echo command is explained later in this chapter).

<!–#config timefmt=”%A, %d %B %Y at %H:%M:%S”–>
<!–#echo var=”date_gmt”–>

Below is a table of many of the options you can use. You can also include things like colons, commas and slashes as well as bits of text and HTML. You can mix the elements below at will.

Element Value Example
%a Abbreviated day of the week Sun
%A Day of the week Sunday
%b Abbreviated month name Jan
%B Month in full January
%d Date 1 (and not 01)
%H 24-hour clock hour 13
%I 12-hour clock hour 1
%j Decimal day of the year 360
%m Month number 11
%M Minutes 08
%p AM or PM AM
%S Seconds 09
%U Week of the year (also %W) 49
%w Day of the week number 05
%y Year of the century 95
%Y Year 1995
%Z Time zone EST

Here are some more examples of different formats:

<!–#config timefmt=”Week %U of %y”–>
<!–#echo var=”date_gmt”–>

<!–#config timefmt=”%d/%m/%y, day %j of the year”–>
<!–#echo var=”date_gmt”–>

<!–#config timefmt=”%I:%S %p”–>
<!–#echo var=”date_gmt”–>

The last format you have set will remain valid throughout the rest of the page. However, unless you want to use the default format (which usually is something like 98/07/12:16:45:34) you will have to set your favourite time format in every page that uses server side includes that have to do with time.

更改大小格式

You can also specify the way file sizes are displayed.

<!–#config sizefmt=”bytes”–>
<!–#fsize file=”top.gif”–>
<!–#config sizefmt=”abbrev”–>
<!–#fsize file=”top.gif”–>


The #fsize include is explained later in this chapter. You can see that the “bytes” option gives the size in full in bytes, the “abbrev” option gives the size in kilobytes.

自定义错误消息

You can change the default error message to anything you want. Here is an example of changing the error message and then trying to include the non-existent file “nosuchfile.html”:

<!–#config errmsg=”Sorry, an error occurred. Please mail your complaints to webmaster@somewhere.net”–>

<!–#include file=”nosuchfile.html”–>

There is only one error message available. However, you can change the error message more than once in a single html file:

<!–#config errmsg=”Sorry, an error occurred including nosuchfile.html. Please mail your complaints to webmaster@somewhere.net”–>

<!–#include file=”nosuchfile.html”–>

<!–#config errmsg=”Sorry, an error occurred including nosuchfileagain.html. Please mail your complaints to webmaster@somewhere.net”–>

<!–#include file=”nosuchfileagain.html”–>

Specifying your own error messages will make it easier for you to spot and solve problems. If you want to use more than one error message, you have to make sure that you change the error message before the command it refers to.

包括文件

The include command allows you to dynamically insert other HTML files into the current HTML file. Use it like this:

<!–#include file=”file.shtml”–>

What path to use, again, depends on your provider. Normally it will be a path that is local to the server, so it will not include http://etc. The most sensible use of this command is to take standard bits of your pages such as headers and footer and put them in a separate file. On all of your pages you use the include command to include that file. That way, in order to change the footer on all pages, you only need to change one file. For example, you could make a simple text file that contains:

<P ALIGN=”center”>Copyright 1998 Tom, Dick and Harry<BR>
Please mail us at tom.dick@harry.com</P

You save this file as ssifooter.html and include it in your other files by using:

<!–#include file=”ssifooter.html”–>

The files you include can be plain text files or can include HTML. You don’t need to give them <HEAD> and <BODY> tags, just put in whatever you want to insert. In these files you can use whatever HTML you want and you can make links, etc.

隐藏 / 显示

With the Hide and Show commands you can avoid that your reader sees certain parts of the document:

<P>Now you see me, <!–#hide–> This text is not shown. <!–#show–> now you don’t.</P

Show and Hide can be used to temporary exclude parts of your document. Hide and Show only work under WebStar, so I cannot show you an example here.

根据时间隐藏和显示

The next example shows how to display bits of HTML only after certain days. Comparisons like this always use the default time format of 1998/07/24:17:34:45 no matter what you have done with the timefmt option.

<!–#hide–>
<!–#show after=”1998/06/30″–>
This text is shown after 30 June 1998.
<!–#show–>

<!–#hide–>
<!–#show after=”1999/06/30″–>
This text is shown after 30 June 1999.
<!–#show–>

Or you can show and hide things on specific days using a combination of ‘hide after’ and ‘show after’:

<!–#hide–>
<!–#show during=”1998/07/12″–>
This text is shown on 12 July 1998.
<!–#show–>

<!–#hide–>
<!–#show during=”1998/07/13″–>
This text is shown on 13 July 1998.
<!–#show–>

<!–#hide–>
<!–#show during=”1998/07/14″–>
This text is shown on 14 July 1998.
<!–#show–>

As you can see, you do not have to specify a full date and time but only what is relevant for you. If you would want to show something during 1998 you could use: during=”1998″.

依据时间隐藏和显示

Here is an example of how to show a bit of text only to a user of Netscape’s Navigator:

<!–#hide–>
<!–#show var=”http_user_agent” operator=”contains”
value=”nav”–>
Welcome Netscape Navigator user!
<!–#show–>

<!–#hide–>
<!–#show var=”http_user_agent” operator=”contains”
value=”MSIE”–>
Welcome Internet Explorer user!
<!–#show–>

As you can see in this example, the output of Webstar is by default on. That’s why you start any of these examples by switching the output of (#hide) and then switching it on again if the appropriate condition is fulfilled. At the end of the example you switch the output on again with a #show include. Again, show and hide do not work under Apache so I cannot show you the result here.

随机隐藏和显示

Show and Hide can also be used at random:

<!–#hide–>
<!–#show var=”random” op=”<” value=”50″ –>
Heads
<!–#hide–>
<!–#show var=”random” op=”=>” value=”50″ –>
Tails
<!–#show–>

If you do a couple of reloads, you should see the text change. Of course you can use the same thing to show and hide images or any other HTML. The number that is used by Webstar is a random number ranging from 1 to 99 inclusive. Here is an example for three random texts:

<!–#hide–>
<!–#show var=”random” op=”<” value=”33″ –>
To be or not to be,
<!–#hide–>
<!–#show var=”random” op=”=>” value=”34″ –>
<!–#hide var=”random” op=”>” value=”66″ –>
that’s the question,
<!–#hide–>
<!–#show var=”random” op=”>” value=”66″ –>
my dear Watson.
<!–#show–>

更多的隐藏和显示

In fact you can show and hide text at will using any of the environment variables (see the section on Echo below). This example shows a bit of text to a user with IP address 195.99.40.125:

<!–#hide–>
<!–#show var=”remote_addr” operator=”=” value=”195.99.40.125″–>
Welcome BTinternet user!
<!–#show–>

If you have friends with fixed IP addresses you can leave messages especially for them in the same manner. Finally, you should know which operators are available:

Operator Meaning
“contains” or “con” variable contains the value string
“starts with” or “start” variable starts with the value string
“ends with” or “end” variable ends with the value string
“=” or “==” variable equals the value string
“!=” or “<>” variable does not equal the value string
“<“ variable is less than the value string
“<=” or “=<“ variable is less than or equal to the value string
“>” variable is greater than the value string
“>=” or “=>” variable is greater than or equal to the value string

If 和 Endif

Because this server runs Apache I could not show the examples of #hide and #show. I can, however, demonstrate the #if and #endif includes (if and endif, in turn, do not work under Webstar):

<!–#config timefmt=”%A”–>
<!–#if expr=”$date_gmt = Friday” –>
Hang in there, it’s almost weekend
<!–#elif expr=”($date_gmt = Saturday) || ($date_gmt = Sunday)” –>
Have a nice weekend
<!–#else –>
Have a good day
<!–#endif –>

Hang in there, it’s almost weekend Have a nice weekend Have a good day

The first thing you will notice is that the #if include, opposite to the #hide and #show, does use the date as formatted with timefmt. This has some clear advantages. You can also see that this example is a bit easier to understand the #show and #hide spaghetti that WebStar seems to need. Note that the #if and #endif are obligatory, the #elif and #else are optional. This example uses date_gmt which is London time -ignoring summertime- rather than date_local which depends on where the server is.

The following operators are available:

Operator Meaning
string1 = string2 string1 equals string2
string1 != string2 string1 does not equal string2
string1 < string2 string1 is less than string2
string1 <= string2 string1 is less than or equal to string2
string1 > string2 string1 is greater than string2
string1 >= string2 string1 is greater than or equal to string2

If, Endif 和环境变量

you can use the #if include to show different information to different browsers. Each browser sets the environment variable http_user_agent differently. This is how Netscape Navigator 4.04, Microsoft Internet Exploder and Apple’s Cyberdog respectively do it:

Mozilla/4.04 (Macintosh; I; PPC, Nav)
Mozilla/4.0 (compatible; MSIE 4.0; Mac_PowerPC)
Cyberdog/2.0 (Macintosh; PPC)

As you can see these are all the Macintosh versions. By the way, this is what your own browser makes of http_user_agent: . So this is how to show different information to different browsers:

<!–#if expr=”$HTTP_USER_AGENT=/MSIE/ ” –>
Fight the Microsoft Monopoly. Get Netscape!
<!–#elif expr=”$HTTP_USER_AGENT=/Nav/ ” –>
Welcome Netscape Navigator user!
<!–#elif expr=”$HTTP_USER_AGENT=/Cyberdog/ ” –>
Welcome Apple Cyberdog user!
<!–#else –>
Welcome! So what browser are you using?
<!–#endif –>

Fight the Microsoft Monopoly. Get Netscape! Welcome Netscape Navigator user! Welcome Apple Cyberdog user! Welcome! So what browser are you using?

Note that the /Nav/ I am looking for here is produced by Netscape Navigator, which is Communicator without the news, mail and webeditor modules. The above is obviously not an exhaustive list of browsers, which is why there is also an #else include for all the browsers that are not covered.

The two slashes around MSIE, Nav and Cyberdog in the example above means that the second string is interpreted as a regular expression, commonly used under Unix. In this case it checks if http_user_agent contains that string.

Set

The #set include can be used to create your own variables and assign them a value. Variables can be printed or can be used in #if statements:

<!–#set var=”carmodel” value=”Mercedes” –>
<!–#echo var=”carmodel” –><BR>
<!–#if expr=”$carmodel = Mercedes” –>
That’s a jolly nice car
<!–#endif –>


That’s a jolly nice car

The $ sign in the #if include is needed to ensure that “carmodel” is interpreted as a variable, not as a string.

Echo

ECHO can be used to insert information from the browser and the server into your document, the so-called environment variables. The following possibilities are available:

Document Name: <!–#echo var=”document_name”–>
Document URI: <!–#echo var=”document_uri”–>
Local Date: <!–#echo var=”date_local”–>
GMT Date: <!–#echo var=”date_gmt”–>
Last Modified: <!–#echo var=”last_modified”–>
Server Software: <!–#echo var=”server_software”–>
Server Name: <!–#echo var=”server_name”–>
Server Protocol: <!–#echo var=”server_protocol”–>
Server Port: <!–#echo var=”server_port”–>
Gateway Interface: <!–#echo var=”gateway_interface”–>
Request Method: <!–#echo var=”request_method”–>
Script Name: <!–#echo var=”script_name”–>
Remote Host: <!–#echo var=”remote_host”–>
Remote Address: <!–#echo var=”remote_addr”–>
Remote User: <!–#echo var=”remote_user”–>
Content Type: <!–#echo var=”content_type”–>
Content Length: <!–#echo var=”content_length”–>
HTTP Accept: <!–#echo var=”http_accept”–>
HTTP User Agent (Browser): <!–#echo var=”http_user_agent”–>
HTTP Cookie: <!–#echo var=”http_cookie”–>
Unescaped query string: <!–#echo var=”query_string_unescaped”–>
Query String: <!–#echo var=”query_string”–>
Path Info: <!–#echo var=”path_info”–>
Path Translated: <!–#echo var=”path_translated”–>
Referer: <!–#echo var=”referer”–>
Forwarded: <!–#echo var=”forwarded”–>

Document Name:
Document URI:
Local Date:
GMT Date:
Last Modified:
Server Software:
Server Name:
Server Protocol:
Server Port:
Gateway Interface:
Request Method:
Script Name:
Remote Host:
Remote Address:
Remote User:
Content Type:
Content Length:
HTTP Accept:
HTTP User Agent (Browser):
HTTP Cookie:
Unescaped query string:
Query String:
Path Info:
Path Translated:
Referer:
Forwarded:

Not all ECHO commands always result in information being printed. This can depend on the server, on your browser and on the way you reached this page. The #echo include works both under WebStar and Apache.

Print Environment

If you want to print the entire environment, you do not need to use a whole list of #echo includes. Instead you can use this shortcut.

<PRE> <!–#printenv –> </PRE>



Note that the environment includes the variable “carmodel” that was defined in an earlier example.

执行脚本

You can use a server side include to run a script. This is what I use on my homepage:

<!–#exec cgi=”ssi.demo.cgi”–>

The CGI script (which is in Perl 5) opens a file with a dozen quotes, selects one at random and prints it to the page. The script, by the way, is courtesy of Matt Wright who offers a brilliant collection of scripts.

文件大小

You can insert the size of a file in this way:

<!–#fsize file=”top.gif”–>

This inserts the size of the file top.gif (the logo at the top of this page). As explained earlier in this chapter, you can determine if the size is displayed in full bytes or abbreviated in kilobytes or megabytes.

文件日期

You can insert the date of a file in this way:

<!–#flastmod file=”top.gif”–>

This inserts the date and the time the file top.gif (the logo at the top of this page) was last modified. The format of the date and time can be customized by you as explained earlier in this chapter.

This page has been translated into Spanish language by Maria Ramos from Webhostinghub.com.

 

 

Google搜索技巧

搜索引擎在今天其实就是使用网络的基本功,也是在线一切工作的得力助手。
而很多人依然不知道如何使用搜索引擎查找想要的东西,经常会有人打电话问你帮他找些什么。
所以把这个谷歌文档发给他就可以了。

了解一些帮助您轻松通过 Google 找到信息的提示和技巧。

提示 1:使用简单的搜索字词

无论要搜索什么,都请先用简单的字词进行搜索,例如最近的机场在哪里?您随时可以根据需要添加一些描述性字词。

如果您要查找特定地点的某个场所或商品,可添加该地点名称。例如,南京面包店

提示 2:通过语音搜索

不想打字?点击 Google 应用或 Chrome 搜索框中的麦克风图标 通过语音执行搜索

提示 3:认真选择措辞

在确定输入搜索框中的字词时,尽量选择要查找的网站上可能会出现的字词。例如,不要使用我的头很痛,而要使用头痛,因为医学网站上往往会使用后者。

提示 4:不用担心输入方面的琐事

  • 拼写。 无论您的拼写是否正确,Google 的拼写检查工具都会自动使用给定字词的最常用拼写形式。
  • 大写。 搜索 QQqq 所得到的结果是一样的。

提示 5:查找快速解答

对于您进行的许多搜索,Google 都会替您完成相关工作,并会在您输入搜索字词后在搜索结果页上显示相关解答。有些功能(例如查询与球队有关的信息)并非在所有地区都提供。

  • 天气:搜索天气可查看您所在地点的天气信息,如果在“天气”后加上城市名(例如天气北京),则可查看相应城市的天气信息。
  • 字典:在任意字词前加上 define 即可查询其定义。
  • 计算:输入数学公式(例如 3*9123)或求解复杂的图形公式。
  • 单位换算:输入任何换算内容,例如 3 美元兑换欧元
  • 体育:搜索球队的名称,即可查看相关赛程和比赛得分等信息。
  • 快讯:搜索名人、地点、电影或歌曲的名称可看到相关重要信息。

 

搜索中的标点、符号和运算符

您可以使用特殊的字符和字词来获取更具体的搜索结果。Google 会忽略大部分的标点符号(以下示例除外)。例如,搜索字词狗! 会被 Google 视为

Google 搜索可以识别的标点和符号

即使以下符号均受支持,在您的搜索中加入这些符号也并不一定会改善搜索结果。如果我们认为该标点不会为您提供更好的结果,则会显示出不含标点的搜索字词所对应的建议结果。

请注意:在使用符号进行搜索时,请勿在符号和搜索字词之间添加空格。我们可以识别-狗中的符号,但无法识别- 狗中的符号。

符号 用途
+ 搜索 Google+ 网页或血型 示例:+Chrome 和 AB+
@ 查找社交标记 示例:@agoogler
$ 查找价格
示例:尼康 $400
# 查找热门主题标签以搜索热门话题 示例:#throwbackthursday
- 移除字词在某个字词或网站之前添加一个短横可排除所有包含该字词或网站的搜索结果。在搜索有多种含义的字词(例如“汽车品牌捷豹”和“动物捷豹”)时,这种方法尤为实用。

示例:捷豹速度 -汽车熊猫 -site:wikipedia.org

连字如果多个字词以短横相连,Google 便会知道这些字词是紧密关联的。

示例:twelve-year-old dog

_ 用于连接两个字词,例如 quick_sort。 您会在搜索结果中发现,这对字词要么组成一个字词 (quicksort),要么由下划线相连 (quick_sort)。
" 如果您将字词或词组置于引号中,则搜索结果中将仅显示以下网页:包含引号中的字词且字词顺序也与引号中相同。 请注意:请仅在需要搜索某个精确字词或词组时使用这种搜索方式,不然,可能会错误地排除掉很多有用的搜索结果。 示例:"想象一下所有人"
* 在搜索中添加一个星号,以表示任何未知或不确定的字词。与引号结合使用,可以查找具体词组的不同变体,或记住词组中间的字词。 示例:"省*就是赚*"
.. 使用不含空格的两个半角句号 (..) 隔开多个数字,即可查看日期、价格和尺寸等方面的数值在指定范围内的搜索结果。 示例:相机 $50..$100

使用搜索运算符缩小搜索结果范围

搜索运算符是可添加到搜索字词中以帮助缩小搜索结果范围的字词。不必担心,您不一定要记住每个运算符,因为您也可以使用“高级搜索”页面来进行这种搜索。

请注意:使用运算符进行搜索时,请勿在运算符和搜索字词之间添加空格。搜索 site:nytimes.com 可以获取相关搜索结果,而搜索 site: nytimes.com 则是行不通的。

运算符 用途
site: 仅从特定网站或网域获得搜索结果。例如,您可以查找 NBC 网站或任何 .gov 网站上所有提到“奥运”的内容。 示例:olympics site:nbc.com 和 olympics site:.gov
link: 查找链接到某个特定网页的页面。例如,您可以查找链接到 google.com.hk 的所有页面。 示例:link:google.com.hk
related: 查找与您已浏览过的网址类似的网站。当您搜索与 time.com 相关的网站时,会找到您可能感兴趣的其他新闻出版物网站。 示例:related:time.com
OR 如果您想搜索可能只包含多个搜索字词中某一个的页面,可以在这些字词之间加上 OR(大写)。如果不加 OR,您的搜索结果中通常只会显示与这些字词都匹配的页面。 示例:世界杯举办地2014年OR 2018年
info: 获取某网址的相关信息,包括网页的缓存版本、相似网页和链接至该网站的网页。 示例:info:google.com
cache: 查看 Google 上次抓取网站时网页的外观。 示例:cache:washington.edu

继续阅读“Google搜索技巧”

修改启动 Windows 服务时允许花费的时间

今天安装 Team Foundation Server。

 

20140725163301

在安装结果信息中有点以为的收获:
信息

启动 Windows 服务时允许花费的时间已从 30 秒增加为 600 秒。这会影响此服务器上的所有 Windows 服务。(注册表值设置是 HKLM\SYSTEM\CurrentControlSet\Control\!ServicesPipeTimeout。)

通过设置此注册表键值,调整加载服务所允许使用的时间。

SuperHidden.vbs , 右键 添加\卸载 “显示\隐藏 系统文件”

一段VB脚本,将“显示隐藏系统文件”加入到右键,如图。

20140725101903

Dim WSHShell
Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.RegWrite "HKCR\CLSID\{00000000-0000-0000-0000-000000000012}\Instance\InitPropertyBag\CLSID", "{13709620-C279-11CE-A49E-444553540000}", "REG_SZ"
WSHShell.RegWrite "HKCR\CLSID\{00000000-0000-0000-0000-000000000012}\Instance\InitPropertyBag\method", "ShellExecute", "REG_SZ"
if WSHShell.RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideFileExt") = 0 then
WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSuperHidden", "0", "REG_DWORD"
WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden", "2", "REG_DWORD"
WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideFileExt", "1", "REG_DWORD"
WSHShell.RegWrite "HKCR\CLSID\{00000000-0000-0000-0000-000000000012}\Instance\InitPropertyBag\command", "显示扩展名及文件", "REG_SZ"
WSHShell.SendKeys "{F5}+{F10}e"
else
WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSuperHidden", "1", "REG_DWORD"
WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden", "1", "REG_DWORD"
WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideFileExt", "0", "REG_DWORD"
WSHShell.RegWrite "HKCR\CLSID\{00000000-0000-0000-0000-000000000012}\Instance\InitPropertyBag\command", "隐藏扩展名及文件", "REG_SZ"
WSHShell.SendKeys "{F5}+{F10}e"
end if
Set WSHShell = Nothing
WScript.Quit(0)

 

 

程序员的持续学习之道

原文出处: ShareCore (@Justin_Programer)

 

我其实是一个悲观主义者,从开始成为一名程序员的那一天开始,我就对自己的职业充满着担忧。早期,我担忧的是我刚进入这一行,落后身边从事这一行多年的人太多,跟他们比,我一开始就处于“不公平“的起跑线上;二是当我稍微深入这行后,发现技术的道路充满了歧路和死胡同,稍不留神,就将落入再也跟不上技术进步的节奏,身边也充斥着类似的示例。

好在在这条路上,我找到了一个克服担忧的良方:学习,坚持不懈的学习!

人类最大的恐惧莫过于对未知的恐惧,而学习,是克服未知的一个最有效途径。那作为一个程序员,该如何才能做到坚持不懈的学习呢?我想主要有以下几点:

1. 不抗拒变化,跟踪变化

这里说的变化,更多指的是技术的变化。新技术永远层出不穷,如果你抗拒变化,或惧怕变化,在心里优势上就落后了一大截。很多程序员的技术道路越走越窄,当一门新技术来临时,他们从不去了解或研究,他们要么认为这是”换汤不换药“的”技术幌子“,不值得去研究,要么等着别人去研究,自己被动的接受别人的结论与成果。诚然,等待别人的研究结果也可行,但是,当身边没有人去研究呢?当研究的人不愿意提供给你他的研究结果呢?当别人的结论和结果是错误的呢?

当然,业界的新技术层出不穷,要去跟踪每一项新技术的变化也是不可能的,我的建议是尽量掌握基础的技术,越是基础的技术越是恒定。如计算机的体系架构,TCP,HTTP,各类编程范式,OOP,MVC架构等,都是好多年来没有发生过变化的技术了。许多新技术也是建立在他们上面,当你了解了这些基础的技术,建立在他们之上的新技术也就能很快掌握了,并能迅速而准确地对这些新技术作出“价值判断”。

技术的变化,其实也并不全是指业界的新技术来临,更多指的是,超出自己当前技术能力外,主动研究和选择的“新技术” ,主动丢弃老的套路和技术,不固步自封。见过很多的程序员,他们写了很多年的代码了,技术能力还停留在数据库层写一个Sql(存储过程)+前端调用上。为什么如此呢?因为自开始写代码起,这样简单粗暴的方式就可以解决他们面对的问题了。所以,当碰到新的问题,他们就继续沿用着这种方式,而从不去看看业界是不是有更合适的方案来解决。长此以往,他们的技术能力也就不会有任何的变化,工作十年,只是将第一年所学的技术重复十年而已

2. 书宜杂读,业宜精钻

建筑学家梁思成赴美留学,其父梁启超告诫说:你该挤出一部分时间学些常识性东西,特别是文学或人文科学,稍稍多用点工夫就能有大的收获。我深怕你因所学太专一,把多彩的生活弄得平平淡淡,生活过于单调,则生厌倦心理,厌倦一生即成苦恼之事……书宜杂读,业宜精钻。

学习本身应该是一件很快乐的事情,但如果只是一味地沉浸于专业学习之中,难免会将本来快乐的事情弄成平淡和单调,更可怕的是,由此产生厌倦心理,放弃学习。

所以,可以尽量跟随自己的兴趣,去更广泛地读书。历史,文学,心理学,哲学等等各方面的书都可以尝试去读,它们不仅丰富你的知识,更能让你在阅读中受到感动、教育和启迪。书读的更多更广泛,知道的事也就多,思路更加开阔,解决问题的能力也就能高于常人,从而反过来帮助到你专业能力的提升。

3. 投资团队,积极打造学习型团队

现代社会,难免的一点就是个人必须置身于群体之中,程序员更是如此。从群体心理学的角度来看,在群体里,个人的才智被削弱,异质性被同质性所吞没。由此,如果一个团队不爱学习,那么,其中的成员也很难坚持学习(个性和意志力特别强的人除外)。

如果你爱学习,请想办法让你的团队也变得爱学习,这样,你对学习的坚持将变得更加容易。或许你认为建立学习氛围,是团队领导的事情,跟自己无关。领导当然可以来做也需要来做这样的事情,但要明白的一点,学习这事,如果变成从上向下,就难免“政治化”了,容易失去它本身的意义。而从下往上,更能建立轻松和谐的学习环境。

一些软件设计原则

出自:http://blog.jobbole.com/685/

导读:酷壳网的陈皓给大家介绍了软件设计的一些原则,作者认为一个好的程序员通常由其操作技能、知识水平,经验层力和能力四个方面组成。软件设计的这些原则,每一个程序员都应该了解。相信大家从中能够从中学了解到一些设计原理方面的知识。
文章内容如下:

以前本站向大家介绍过一些软件开发的原则,比如优质代码的十诫和Unix传奇(下篇)中所以说的UNIX的设计原则。相信大家从中能够从中学了解到 一些设计原理方面的知识,正如我在《再谈“我是怎么招聘程序员”》中所说的,一个好的程序员通常由其操作技能、知识水平,经验层力和能力四个方面组成。在这 里想和大家说说设计中的一些原则,我认为这些东西属于长期经验总结出来的知识。这些原则,每一个程序员都应该了解。但是请不要教条主义,在使用的时候还是 要多多考虑实际情况。

下面这些原则,不单单只是软件开发,可以推广到其它生产活动中,甚至我们的生活中

Don’t Repeat Yourself(DRY)

DRY是一个最简单的法则,也是最容易被理解的。但它也可能是最难被应用的(因为要做到这样,我们需要在泛型设计上做相当的努力,这并不是一件容易 的事)。它意味着,当我们在两个或多个地方的时候发现一些相似的代码的时候,我们需要把他们的共性抽象出来形一个唯一的新方法,并且改变现有的地方的代码 让他们以一些合适的参数调用这个新的方法。

参考http://en.wikipedia.org/wiki/Don%27t_repeat_yourself

Keep It Simple, Stupid (KISS)

KISS原则在设计上可能最被推崇的,在家装设计,界面设计,操作设计上,复杂的东西越来越被众人所BS了,而简单的东西越来越被人所认可,比如这些UI的设计和我们中国网页(尤其是新浪的网页) 者是负面的例子。“宜家”(IKEA)简约、效率的家居设计、生产思路;“微软”(Microsoft)“所见即所得”的理念;“谷歌”(Google) 简约、直接的商业风格,无一例外的遵循了“kiss”原则,也正是“kiss”原则,成就了这些看似神奇的商业经典。而苹果公司的iPhone/iPad 将这个原则实践到了极至。

把一个事情搞复杂是一件简单的事,但要把一个复杂的事变简单,这是一件复杂的事。

参考http://en.wikipedia.org/wiki/KISS_principle

Program to an interface, not an implementation

这是设计模式中最根本的哲学,注重接口,而不是实现,依赖接口,而不是实现。接口是抽象是稳定的,实现则是多种多样的。以后面我们会面向对象的SOLID原则中会提到我们的依赖倒置原则,就是这个原则的的另一种样子。还有一条原则叫Composition over inheritance(喜欢组合而不是继承),这两条是那23个经典设计模式中的设计原则。

Command-Query Separation (CQS)–命令-查询分离原则

查询:当一个方法返回一个值来回应一个问题的时候,它就具有查询的性质;
命令:当一个方法要改变对象的状态的时候,它就具有命令的性质;

通常,一个方法可能是纯的Command模式或者是纯的Query模式,或者是两者的混合体。在设计接口时,如果可能,应该尽量使接口单一化,保证 方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用,而会改变对象的状态的方法不可能有返回值。也就是说:如果我们要问一个 问题,那么就不应该影响到它的答案。实际应用,要视具体情况而定,语义的清晰性和使用的简单性之间需要权衡。将Command和Query功能合并入一个 方法,方便了客户的使用,但是,降低了清晰性,而且,可能不便于基于断言的程序设计并且需要一个变量来保存查询结果。

在系统设计中,很多系统也是以这样原则设计的,查询的功能和命令功能的系统分离,这样有则于系统性能,也有利于系统的安全性。

参考http://en.wikipedia.org/wiki/Command-query_separation

You Ain’t Gonna Need It(YAGNI)

这个原则简而言之为——只考虑和设计必须的功能,避免过度设计。只实现目前需要的功能,在以后您需要更多功能时,可以再进行添加。
如无必要,勿增复杂性。

软件开发先是一场沟通博弈。

以前本站有一篇关于过度重构的文章,这个示例就是这个原则的反例。而,WebSphere的设计者就表示过他过度设计了这个产品。我们的程序员或是架构师在设计系统的时候,会考虑很多扩展性的东西,导致在架构与设计方面使用了大量折衷,最后导致项目失败。这是个令人感到讽刺的教训,因为本来希望尽可能延长项目的生命周期,结果反而缩短了生命周期。

参考http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It

Law of Demeter–迪米特法则

迪米特法则(Law of Demeter),又称“最少知识原则”(Principle of Least Knowledge),其来源于1987年荷兰大学的一个叫做Demeter的项目。Craig Larman把Law of Demeter又称作“不要和陌生人说话”。在《程序员修炼之道》中讲LoD的那一章叫作“解耦合与迪米特法则”。关于迪米特法则有一些很形象的比喻:

如果你想让你的狗跑的话,你会对狗狗说还是对四条狗腿说?

如果你去店里买东西,你会把钱交给店员,还是会把钱包交给店员让他自己拿?

和狗的四肢说话?让店员自己从钱包里拿钱?这听起来有点荒唐,不过在我们的代码里这几乎是见怪不怪的事情了。

对于LoD,正式的表述如下:
对于对象‘O’中一个方法‘M’,M应该只能够访问以下对象中的方法:

  • 1.对象O;
  • 2.与O直接相关的Component Object;
  • 3.由方法M创建或者实例化的对象;
  • 4.作为方法M的参数的对象。

在《Clean Code(代码整洁之道)》一书中,有一段Apache framework中的一段违反了LoD的代码:

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

这么长的一串对其它对象的细节,以及细节的细节,细节的细节的细节……的调用,增加了耦合,使得代码结构复杂、僵化,难以扩展和维护。

在《重构》一书中的代码的环味道中有一种叫做“Feature Envy”(依恋情结),形象的描述了一种违反了LoC的情况。Feature Envy就是说一个对象对其它对象的内容更有兴趣,也就是说老是羡慕别的对象的成员、结构或者功能,大老远的调用人家的东西。这样的结构显然是不合理的。 我们的程序应该写得比较“害羞”。不能像前面例子中的那个不把自己当外人的店员一样,拿过客人的钱包自己把钱拿出来。“害羞”的程序只和自己最近的朋友交 谈。这种情况下应该调整程序的结构,让那个对象自己拥有它羡慕的feature,或者使用合理的设计模式(例如Facade和Mediator)。

参考http://en.wikipedia.org/wiki/Principle_of_Least_Knowledge

面向对象的S.O.L.I.D原则

一般来说这是面向对象的五大设计原则,但是,我觉得这些原则可适用于所有的软件开发。

Single Responsibility Principle (SRP)–职责单一原则

关于单一职责原则,其核心的思想是:一个类,只做一件事,并把这件事做好,其只有一个引起它变化的原因。单一职 责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原 因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一职责,通常意味着单一的功能,因此不要为一个模块实现过多的功能 点,以保证实体只有一个引起它变化的原因。

Unix/Linux是这一原则的完美体现者。各个程序都独立负责一个单一的事。

Windows是这一原则的反面示例。几乎所有的程序都交织耦合在一起。

Open/Closed Principle (OCP)–开闭原则

关于开发封闭原则,其核心的思想是:模块是可扩展的,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的

对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

对于面向对象来说,需要你依赖抽象,而不是实现,23个经典设计模式中的“策略模式”就是这个实现。对于非面向对象编程,一些API需要你传入一个 你可以扩展的函数,比如我们的C语言的qsort()允许你提供一个“比较器”,STL中的容器类的内存分配,ACE中的多线程的各种锁。对于软件方面, 浏览器的各种插件属于这个原则的实践。

Liskov substitution principle (LSP)–里氏代换原则

软件工程大师Robert C. Martin把里氏代换原则最终简化为一句话:“Subtypes must be substitutable for their base types”。也就是,子类必须能够替换成它们的基类。即:子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。另外,不应该 在代码中出现if/else之类对子类类型进行判断的条件。里氏替换原则LSP是使代码符合开闭原则的一个重要保证。正是由于子类型的可替换性才使得父类 型的模块在无需修改的情况下就可以扩展。

这么说来,似乎有点教条化,我非常建议大家看看这个原则个两个最经典的案例——“正方形不是长方形”和“鸵鸟不是鸟”。通过这两个案例,你会明白 《墨子小取》中说的——“娣,美人也,爱娣,非爱美人也….盗,人也;恶盗,非恶人也。”——妹妹虽然是美人,但喜欢妹妹并不代表喜欢美人。盗贼是人,但 讨厌盗贼也并不代表就讨厌人类。这个原则让你考虑的不是语义上对象的间的关系,而是实际需求的环境

在很多情况下,在设计初期我们类之间的关系不是很明确,LSP则给了我们一个判断和设计类之间关系的基准:需不需要继承,以及怎样设计继承关系。

Interface Segregation Principle (ISP)–接口隔离原则

接口隔离原则意思是把功能实现在接口中,而不是类中,使用多个专门的接口比使用单一的总接口要好。

举个例子,我们对电脑有不同的使用方式,比如:写作,通讯,看电影,打游戏,上网,编程,计算,数据等,如果我们把这些功能都声明在电脑的抽类里 面,那么,我们的上网本,PC机,服务器,笔记本的实现类都要实现所有的这些接口,这就显得太复杂了。所以,我们可以把其这些功能接口隔离开来,比如:工 作学习接口,编程开发接口,上网娱乐接口,计算和数据服务接口,这样,我们的不同功能的电脑就可以有所选择地继承这些接口。

这个原则可以提升我们“搭积木式”的软件开发。对于设计来说,Java中的各种Event Listener和Adapter,对于软件开发来说,不同的用户权限有不同的功能,不同的版本有不同的功能,都是这个原则的应用。

Dependency Inversion Principle(DIP)–依赖倒置原则

高层模块不应该依赖于低层模块的实现,而是依赖于高层抽象。

举个例子,墙面的开关不应该依赖于电灯的开关实现,而是应该依赖于一个抽象的开关的标准接口,这样,当我们扩展程序的时候,我们的开关同样可以控制 其它不同的灯,甚至不同的电器。也就是说,电灯和其它电器继承并实现我们的标准开关接口,而我们的开关产商就可不需要关于其要控制什么样的设备,只需要关 心那个标准的开关标准。这就是依赖倒置原则。

这就好像浏览器并不依赖于后面的web服务器,其只依赖于HTTP协议。这个原则实在是太重要了,社会的分工化,标准化都是这个设计原则的体现。

参考http://en.wikipedia.org/wiki/Solid_(object-oriented_design)

Common Closure Principle(CCP)–共同封闭原则

一个包中所有的类应该对同一种类型的变化关闭。一个变化影响一个包,便影响了包中所有的类。一个更简短的说法是:一起修改的类,应该组合在一起(同 一个包里)。如果必须修改应用程序里的代码,我们希望所有的修改都发生在一个包里(修改关闭),而不是遍布在很多包里。CCP原则就是把因为某个同样的原 因而需要修改的所有类组合进一个包里。如果2个类从物理上或者从概念上联系得非常紧密,它们通常一起发生改变,那么它们应该属于同一个包。

CCP延伸了开闭原则(OCP)的“关闭”概念,当因为某个原因需要修改时,把需要修改的范围限制在一个最小范围内的包里。

参考http://c2.com/cgi/wiki?CommonClosurePrinciple

Common Reuse Principle (CRP)–共同重用原则

包的所有类被一起重用。如果你重用了其中的一个类,就重用全部。换个说法是,没有被一起重用的类不应该被组合在一起。CRP原则帮助我们决定哪些类 应该被放到同一个包里。依赖一个包就是依赖这个包所包含的一切。当一个包发生了改变,并发布新的版本,使用这个包的所有用户都必须在新的包环境下验证他们 的工作,即使被他们使用的部分没有发生任何改变。因为如果包中包含有未被使用的类,即使用户不关心该类是否改变,但用户还是不得不升级该包并对原来的功能 加以重新测试。

CCP则让系统的维护者受益。CCP让包尽可能大(CCP原则加入功能相关的类),CRP则让包尽可能小(CRP原则剔除不使用的类)。它们的出发点不一样,但不相互冲突。

参考http://c2.com/cgi/wiki?CommonReusePrinciple

Hollywood Principle–好莱坞原则

好莱坞原则就是一句话——“don’t call us,we’ll call you.”。意思是,好莱坞的经纪人们不希望你去联系他们,而是他们会在需要的时候来联系你。也就是说,所有的组件都是被动的,所有的组件初始化和调用都 由容器负责。组件处在一个容器当中,由容器负责管理。

简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:

  • 1.不创建对象,而是描述创建对象的方式。
  • 2.在代码中,对象与服务没有直接联系,而是容器负责将这些联系在一起。

控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

好莱坞原则就是IoC(Inversion of Control)或DI(Dependency Injection)的基础原则。这个原则很像依赖倒置原则,依赖接口,而不是实例,但是这个原则要解决的是怎么把这个实例传入调用类中?你可能把其声明 成成员,你可以通过构造函数,你可以通过函数参数。但是IoC可以让你通过配置文件,一个由Service Container 读取的配置文件来产生实际配置的类。但是程序也有可能变得不易读了,程序的性能也有可能还会下降。

参考
http://en.wikipedia.org/wiki/Hollywood_Principle
http://en.wikipedia.org/wiki/Inversion_of_Control

High Cohesion & Low/Loose coupling & –高内聚,低耦合

这个原则是UNIX操作系统设计的经典原则,把模块间的耦合降到最低,而努力让一个模块做到精益求精。

  • 内聚:一个模块内各个元素彼此结合的紧密程度
  • 耦合:一个软件结构内不同模块之间互连程度的度量

内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。

参考
http://en.wikipedia.org/wiki/Coupling_(computer_science)
http://en.wikipedia.org/wiki/Cohesion_(computer_science)

Convention over Configuration(CoC)–惯例优于配置原则

简单点说,就是将一些公认的配置方式和信息作为内部缺省的规则来使用。例如,Hibernate的映射文件,如果约定字段名和类属性一致的话,基本 上就可以不要这个配置文件了。你的应用只需要指定不convention的信息即可,从而减少了大量convention而又不得不花时间和精力啰里啰嗦 的东东。配置文件很多时候相当的影响开发效率。

Rails中很少有配置文件(但不是没有,数据库连接就是一个配置文件),Rails的fans号称期开发效率是java开发的10倍,估计就是这 个原因。Maven也使用了CoC原则,当你执行mvn -compile命令的时候,不需要指源文件放在什么地方,而编译以后的class文件放置在什么地方也没有指定,这就是CoC原则。

参考http://en.wikipedia.org/wiki/Convention_over_Configuration

Separation of Concerns (SoC)–关注点分离

SoC是计算机科学中最重要的努力目标之一。这个原则,就是在软件开发中,通过各种手段,将问题的各个关注点分开。如果一个问题能分解为独立且较小 的问题,就是相对较易解决的。问题太过于复杂,要解决问题需要关注的点太多,而程序员的能力是有限的,不能同时关注于问题的各个方面。正如程序员的记忆力 相对于计算机知识来说那么有限一样,程序员解决问题的能力相对于要解决的问题的复杂性也是一样的非常有限。在我们分析问题的时候,如果我们把所有的东西混 在一起讨论,那么就只会有一个结果——乱。

我记得在上一家公司有一个项目,讨论就讨论了1年多,项目本来不复杂,但是没有使用SoC,全部的东西混为一谈,再加上一堆程序员注入了各种不同的观点和想法,整个项目一下子就失控了。最后,本来一个1年的项目做了3年。

实现关注点分离的方法主要有两种,一种是标准化,另一种是抽象与包装。标准化就是制定一套标准,让使用者都遵守它,将人们的行为统一起来,这样使用 标准的人就不用担心别人会有很多种不同的实现,使自己的程序不能和别人的配合。Java EE就是一个标准的大集合。每个开发者只需要关注于标准本身和他所在做的事情就行了。就像是开发镙丝钉的人只专注于开发镙丝钉就行了,而不用关注镙帽是怎 么生产的,反正镙帽和镙丝钉按标来就一定能合得上。不断地把程序的某些部分抽像差包装起来,也是实现关注点分离的好方法。一旦一个函数被抽像出来并实现 了,那么使用函数的人就不用关心这个函数是如何实现的,同样的,一旦一个类被抽像并实现了,类的使用者也不用再关注于这个类的内部是如何实现的。诸如组 件,分层,面向服务,等等这些概念都是在不同的层次上做抽像和包装,以使得使用者不用关心它的内部实现细节。
说白了还是“高内聚,低耦合”。

参考http://sulong.me/archives/99

Design by Contract (DbC)–契约式设计

DbC的核心思想是对软件系统中的元素之间相互合作以及“责任”与“义务”的比喻。这种比喻从商业活动中“客户”与“供应商”达成“契约”而得来。例如:
供应商必须提供某种产品(责任),并且他有权期望客户已经付款(权利)。
客户必须付款(责任),并且有权得到产品(权利)。

契约双方必须履行那些对所有契约都有效的责任,如法律和规定等。

同样的,如果在程序设计中一个模块提供了某种功能,那么它要:
期望所有调用它的客户模块都保证一定的进入条件:这就是模块的先验条件(客户的义务和供应商的权利,这样它就不用去处理不满足先验条件的情况)。

保证退出时给出特定的属性:这就是模块的后验条件——(供应商的义务,显然也是客户的权利)。

在进入时假定,并在退出时保持一些特定的属性:不变式。

契约就是这些权利和义务的正式形式。我们可以用“三个问题”来总结DbC,并且作为设计者要经常问:

  • 它期望的是什么?
  • 它要保证的是什么?
  • 它要保持的是什么?

根据Bertrand Meyer氏提出的DBC概念的描述,对于类的一个方法,都有一个前提条件以及一个后续条件,前提条件说明方法接受什么样的参数数据等,只有前提条件得到 满足时,这个方法才能被调用;同时后续条件用来说明这个方法完成时的状态,如果一个方法的执行会导致这个方法的后续条件不成立,那么这个方法也不应该正常 返回。

现在把前提条件以及后续条件应用到继承子类中,子类方法应该满足:

  • 1.前提条件不强于基类.
  • 2.后续条件不弱于基类.

换句话说,通过基类的接口调用一个对象时,用户只知道基类前提条件以及后续条件。因此继承类不得要求用户提供比基类方法要求的更强的前提条件,亦 即,继承类方法必须接受任何基类方法能接受的任何条件(参数)。同样,继承类必须顺从基类的所有后续条件,亦即,继承类方法的行为和输出不得违反由基类建 立起来的任何约束,不能让用户对继承类方法的输出感到困惑。

这样,我们就有了基于契约的LSP,基于契约的LSP是LSP的一种强化。

参考http://en.wikipedia.org/wiki/Design_by_contract

Acyclic Dependencies Principle (ADP)–无环依赖原则

包之间的依赖结构必须是一个直接的无环图形,也就是说,在依赖结构中不允许出现环(循环依赖)。如果包的依赖形成了环状结构,怎么样打破这种循环依 赖呢?有2种方法可以打破这种循环依赖关系:第一种方法是创建新的包,如果A、B、C形成环路依赖,那么把这些共同类抽出来放在一个新的包D里。这样就把 C依赖A变成了C依赖D以及A依赖D,从而打破了循环依赖关系。第二种方法是使用DIP(依赖倒置原则)和ISP(接口分隔原则)设计原则。

无环依赖原则(ADP)为我们解决包之间的关系耦合问题。在设计模块时,不能有循环依赖。

参考http://c2.com/cgi/wiki?AcyclicDependenciesPrinciple

上面这些原则可能有些学院派,也可能太为理论,我在这里说的也比较模糊和简单,这里只是给大家一个概貌,如果想要了解更多的东西,大家可以多google一下。

不过这些原则看上去都不难,但是要用好却并不那么容易。要能把这些原则用得好用得精,而不教条,我的经验如下:(我以为这是一个理论到应用的过程)

  • 1.你可以先粗浅或是表面地知道这些原则。
  • 2.但不要急着马上就使用。
  • 3.在工作学习中观察和总结别人或自己的设计。
  • 4.再回过头来了回顾一下这些原则,相信你会有一些自己的心得。
  • 5.有适度地去实践一下。
  • 6.Goto第 3步。