《中国近代史》读书笔记

《中国近代史》——蒋廷黻(著)

最后更新时间:2021-01-06

黻(

  1. 古代礼服上黑与青相间的花纹:黼~。
  2. 同“韨”。

琦善

琦(qí)

  1. 美玉。
  2. 珍奇,美好:~玮(奇丽的意思)。瑰意~行。

马戛尔尼(乔治·马戛尔尼,George Macartney)

戛(jiá)

  1. 长矛。
  2. 敲,敲打。
  3. 常礼;常法。
  4. 刮。
  5. 象声词:~然长鸣。

恭亲王奕(yì)䜣(xīn)

郭嵩焘(guo song tao)

伊里布和耆英

耆(qí)

  1. 年老,六十岁以上的人:~老。~年。~绅。~宿(sù)(指在社会上有名望的老年人)。
  2. 强横。

 

端王载漪子溥(pǔ)隽(jùn)

漪(yī)

水波纹:~沦。~澜。清~。涟~(细小的波纹)。

隽(jùn)

古同“俊”。

 

《中国近代史》是蒋廷黻所著的,于1938年首次出版的中国近代史研究的重要著作。他作为一个“知外交”的学者和政客,从外交的角度讲述中国近代史以及从外交的角度分析近代历史事件发生的原因,背景。

在讲述鸦片战争爆发前后清政府(实际更多是地方官员自主决定)与英国(商人、政府代表)交涉的过程中,通过史料讲述了清政府官员对外的极其无知,从上到下不了解外面的世界,不愿意给外国平等交往的机会;在交涉的过程中,又极其自大,不守诚信,不主动了解敌人情况,很多事情都凭道听途说和意淫。战争失败后,不能接受失败思检讨问题,认清差距,反而对外争执一些无关紧要的内容,对关于主权的事情放任英国制定规则(当然作者也知道,我们是以后来着的角度来看待这个问题,觉得痛心棘手,当时人并不觉得)。

协定关税和治外法权是我们近些年所认为不平等条约的核心,可是当时的人却并不这样看治外法权,在道光时代的人的目光中,不过是“让夷人管夷人”。他们想那是最方便、最省事的办法。至于协定关税,他们觉得也是方便省事的办法。每种货物应该纳多少税都明白地载于条约,那就可以省去争执。负责交涉条约的人如伊里布、耆英、黄恩彤诸人知道战前广东地方官吏的苛捐杂税是引起战争原因之一,现在把收税标准明文规定岂不是一个釜底抽薪,一劳永逸的办法?而且,新的收税标准平均到5%,比旧日的自主关税还要略微高一点。负交涉责任者计算以后的海关收入比以前还要多,所以他们洋洋得意,以为他们的外交是成功的。其实,他们牺牲了国家的主权,贻害不少。总而言之,道光年间的中国人完全不懂国际公法和国际形势,所以他们争所不应争的,放弃所不应放弃的。

想起了书中关于海关税收的内容了。在下篇“外交策略不进反退“一节中,作者认为在康熙中后期的外交是积极的,对外平等的(在涉及和俄国签订尼布楚条约的章节有讲到)。之后的时间里基本都是开倒车。关于税收税率和规则有一段很深刻的描述:

清政府正式设海关监督,规定粤海关由内务府派,闽海关由福州将军兼,浙海关及江海关的由各省巡抚兼。按法律,中国旧关税制度完备极了、公道极了。康熙的训谕说:“各省关钞之设,原期通商利民以资国用”;“国家设关榷税,必征输无弊,出入有经,庶百物流通,民生饶裕”。世宗的旨趣相同:“国家之设关税,所以通商而非累商,所以便民而非病民也。”乾隆也说过:“朕思商民皆为赤子,轻徭薄赋,俾人民实沾惠泽,乃朕爱养黎庶之本怀。”户部颁有税则,其平均率不到百分之五,比《南京条约》以后的协定税则还要低廉。

……

很明显的,中国自十七世纪末年起,已有了法定的、公开的海关税则。

实际上,中国海关收税的情形不但离高尚道德甚远,且与法律绝不相符。直到鸦片战争,外商不知中国的税则的模样。历康雍乾嘉四朝,外人索看海关税则多次,每次概被衙门拒绝。关税分两种:船钞与货税。照户部的章程,船钞应丈量船的大小而定:大船约纳一千二百两,中船约九百六十两,小船约五百四十两。实际除船钞外,还须“官礼”。在十七世纪末年,官礼的多少,每次须讲价。到康熙末年,十八世纪初年,官礼渐成固定:不问船的大小,概须送一千九百五十两,比正钞还多。货税也有正税及“陋规”。陋规最初也是由收税者及纳税者临时去商议,到康熙末年,大约已达货价百分之六,比正税亦大。雍正初年,杨文乾以巡抚兼关监督的时候,官礼报部归公,于是官吏在货税上加了百分之十的陋规,名曰“缴送”。正税及各种陋规总起来约当百分之二十,这是中国实行的税则。

在讲曾国藩时,作者认为,曾国藩技术革新和思想守旧两条路一起走,在对抗太平天国过程中起到重要作用。但是对于一个国家、民族振兴而言是远远不够的,是必然会失败的。作者认为失败原因两点:曾国藩为代表的改革派本身由于成长经历,思想素质等原因不愿因全面改革(比如不赞同政体改革,……);另外一点就是反对者总舵,阻力太大。

作者虽然“知外交”,但却不是鼓吹外交决定一切的人。书里,作者有一句特别让我感慨:“在近代世界,败仗是千万不能打的。”。所以作者在讲到中日在朝鲜的争端时有说到:“近代战争固不是儿戏。不战而求和当然要吃亏……但战败以后而求和,吃亏之大远过于不战而和。”

总体而言我觉得这本书还是蛮好的。对于1840~1912年间,几个大事件和时人为之努力(改革)的分析很精彩。

 

 

名句摘录:

中西的关系是特别的。在鸦片战争以前,清政府不肯给外国平等待遇;在以后,西方国家不肯给清政府平等待遇。

 

在维持清政府作为政治中心的大前提之下,曾国藩的工作分两方面进行。一方面他要革新,那就是说,他要接受西洋文化的一部分;另一方面他要守旧,那就是说,恢复中国固有的美德。革新守旧同时举行,这是曾国藩对中国近代史的大贡献。

 

曾国藩及其他自强运动的领袖虽然走的路线不错,然而他们不能救国救民族。此其故何在?在于他们的不彻底。他们为什么不彻底呢?一部分因为他们自己不要彻底,大部分因为时代不容许他们彻底。我们试先研究领袖们的短处。

恭亲王奕、文祥、曾国藩、李鸿章、左宗棠这五个大领袖都出身于旧社会,受的都是旧教育。他们没有一个人能读外国书,除李鸿章以外,没有一个人到过外国。就是李鸿章的出洋尚在甲午战败以后,他的建设事业已经过去了。这种人能毅然决然推行新事业就了不得,他们不能完全了解西洋文化是自然的,很可原谅的。他们对于西洋的机械是十分佩服的,十分努力要接受的。他们对于西洋的科学也相当尊重,并且知道科学是机械的基础。但是,他们自己毫无专业的机械常识,此外更不必说了。他们觉得中国的政治制度及立国精神是至善至美,无须学西方的。事实上他们的建设事业就遭了旧的制度和旧的精神文化的阻碍。

 

总之,资本主义可变为帝国主义,也可以不变为帝国主义。未开发的国家容易受资本主义的国家的压迫和侵略,也可以利用外国的资本来开发自己的富源及利用国际的通商来提高人民的生活程度。资本主义如同水一样:水可以资灌溉,可以便利交通,也可以成灾,要看人怎样对付。

同时我们不要把帝国主义看得过于简单,以为世界上没有资本主义就没有帝国主义了。…… 据我们所知,历史上各种政体,君主也好,民主也好,各种社会经济制度,资本主义也好,封建主义也好,共产主义也好,都有行帝国主义的可能。

 

在近代世界,败仗是千万不能打的。

 

我们不要以为顽固分子不爱国,从鸦片战争起,他们是一贯的反对屈服,坚强的主张抗战。

 

近代战争固不是儿戏。不战而求和当然要吃亏……但战败以后而求和,吃亏之大远过于不战而和。

 

马戛尔尼的外交失败是由于中西方邦交观念之不相容。中国抱定“天朝统驭万国”的观念,不承认有所谓“国际”者存在;西方在近代则步步地推演出国际生活及其所需的惯例和公法。马戛尔尼的失败证明中国绝不愿意自动或和平地放弃这种传统观念。因此中国外交史有一大特点:除康熙亲政初年外,中外曾无平等邦交的日子。在鸦片战争以前,中国居上,外国居下;鸦片战争以后则相反。

 

 

 

Unix Timestamp(Unix时间戳)

UNIX时间,或称POSIX时间是UNIX或类UNIX系统使用的时间表示方式:从UTC 1970年1月1日0时0分0秒起至现在的总秒数,不考虑闰秒。在多数Unix系统上Unix时间可以透过date +%s指令来检查。(Unix time (also known as Epoch timePOSIX timeseconds since the Epoch, or UNIX Epoch time) is a system for describing a point in time. It is the number of seconds that have elapsed since the Unix epoch.)

从这个解释可以看出来,同一时刻,在全世界任一时区,获取的Unix时间戳是相同的。

所以,针对PHP而言,time()函数获取的到时间戳与时区无关。

time ( ) : int

Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).

那么,进一步延伸,对于一个给定的日期时间字符串,例如:2020-01-01 00:00:00,那么获取这个日期时间对应的时间戳就是与时区有关的。因为不同时区下的2020-01-01 00:00:00距离UTC的1970-01-01 00:00:00的时间间隔是不一样的。

strtotime ( string $datetime [, int $now = time() ] ) : int

对于PHP而言,在使用strtotime函数时,如果日期时间字符串中没有包含时区信息,那么会使用默认的时区date_default_timezone_get()。(Each parameter of this function uses the default time zone unless a time zone is specified in that parameter. Be careful not to use different time zones in each parameter unless that is intended. )

$dateStr = '2020-01-01 00:00:00';

$timezone = 'Asia/Shanghai';
date_default_timezone_set($timezone);
echo sprintf("%13s)%25s ==> %s\n", $timezone, $dateStr, strtotime($dateStr));

$dateStrWithTimezone = '2020-01-01T00:00:00+08:00';
date_default_timezone_set($timezone);//优先读取日期时间字符串里的时区信息,此处单独设置的时区对下一行的strtotime无效
echo sprintf("%13s)%25s ==> %s\n", $timezone, $dateStrWithTimezone, strtotime($dateStrWithTimezone));

$timezone = 'UTC';
date_default_timezone_set($timezone);
echo sprintf("%13s)%25s ==> %s\n", $timezone, $dateStr, strtotime($dateStr));
echo sprintf("%13s)%25s ==> %s\n", $timezone, $dateStrWithTimezone, strtotime($dateStrWithTimezone));

output:
Asia/Shanghai)2020-01-01 00:00:00 ==> 1577808000
Asia/Shanghai)2020-01-01T00:00:00+08:00 ==> 1577808000
UTC)2020-01-01 00:00:00 ==> 1577836800
UTC)2020-01-01T00:00:00+08:00 ==> 1577808000 //优先读取日期时间字符串里的时区信息,runtime设置的时区对strtotime无效

 

date ( string $format [, int $timestamp = time() ] ) : string

Format a local time/date

同样的道理,同一个时间戳在不同的时区下,对应的日期时间字符串是不一样的。

date_default_timezone_set('UTC');
$timestamp = 1577836800;//UTC 2020-01-01 00:00:00
$sourceDatetime = new \DateTime(date('Y-m-d H:i:s', $timestamp));
echo sprintf("source datetime:%s(%s)\n", $sourceDatetime->format('Y-m-d H:i:s'), $sourceDatetime->getTimezone()->getName());

$timezone = 'Asia/Shanghai';
$targetDatetime = (new \DateTime(date('Y-m-d H:i:s', $timestamp)))
    ->setTimezone(new \DateTimeZone($timezone));
echo sprintf("target datetime:%s(%s)\n", $targetDatetime->format('Y-m-d H:i:s'), $targetDatetime->getTimezone()->getName());

output:
source datetime:2020-01-01 00:00:00(UTC)
target datetime:2020-01-01 08:00:00(Asia/Shanghai)

 

References:

https://zh.wikipedia.org/wiki/UNIX时间

记录cp命令在GNU/Linux和BSD(MacOS)下表现不一致的一个行为

重现步骤如下:

现有的目录结构:

├── source

│   └── source.txt

├── target

 

cp -r source target1   //target1 dir not exists

GUN/BSD
├── source

│   └── source.txt

├── target

└── target1

└── source.txt

 

cp -r source target   //target dir exists

GUN/Linux BSD(MacOS)
├── source

│   └── source.txt

├── target

└── source

└── source.txt

├── source

│   └── source.txt

├── target

│   └── source.txt

测试环境:

GNU coreutils 8.22(CentOS)

GNU coreutils 8.30(Ubuntu 20.04)

BSD macOS Catalina 10.15.7

 

总结/Summary:

使用cp -r 复制目录时,如果目标目录不存在,则GUN/Linux&BSD(mac OS)的cp行为一致;如果目录已经存在,则BSD(mac OS)下会和目标目录不存在时行为一致,但是GUN的cp会创建在目标目录下创建子目录。

 

PS:

如果目标目录已经存在,可以使用 cp -r source/.  target  or   cp -r source/* target

 

Console and TTY and PTY

Console:

在早期的电脑上,往往具有带有大量开关和指示灯的面板,可以对电脑进行一些底层的操作,这个面板就叫做Console。其概念来自于管风琴的控制台。一台电脑通常只能有一个Console,很多时候是电脑主机的一部分,和CPU共享一个机柜。

 

Terminal and TTY(终端):

一台大型主机往往需要支持许多用户同时使用,每个用户所使用操作的设备,就叫做Terminal——终端,终端使用通信电缆与电脑主机连接,甚至可以通过电信网络(电话、电报线路等等)连接另一个城市的电脑。

TTY是电传打字机Teletypewriter的缩写,TTY曾经是最流行的终端设备。现在大多数场景TTY基本就是表示terminal。

Linux有7个TTY?
从控制台切换到 X 窗口,一般采用Ctrl+Alt+F7 ,为什么呢?因为系统默认定义了6个虚拟控制台(Ctrl+Alt+F1 ~ F6), 7个用于x-windows实际上,很多人一般不会需要这么多虚拟控制台的,关闭多余的控制台减少对系统资源的占用,可以自己更改配置文件减少它的数量(在支持systemd的系统里,配置文件位置:/etc/systemd/logind.conf, https://freedesktop.org/software/systemd/man/logind.conf.html,所以具体系统开启了多少个tty,要看配置文件,可能各个发行版本不一样,比如Ubuntu18.04/20.04就是默认6个,而且默认是把tty1留给了x-windows(Ctrl+Alt+F1))。

 

PTY(Pseudo TerminalPseudo TTY, or PTY, 虚拟终端/伪终端):

pts/ptmx(pts/ptmx结合使用,进而实现pty)

所谓伪终端是逻辑上的终端设备,多用于模拟终端程序。例如,我们在X Window下打开的终端,以及我们在Windows使用telnet 或ssh等方式登录Linux主机,此时均在使用pty设备(准确的说在使用pty从设备)

 

echo test > /dev/tty1会把单词test发送到连接在tty1的设备上。

1、/dev/pts0, /dev/pts1, …

2、/dev/tty0, …

3、/dev/console 表示物理终端(控制台)

4、/dev/ttyS0, …  表示串行终端

tty命令可以查看当前登录的终端类型,比如/dev/tty2,/dev/pts/0

Go to WebAssembly

什么是WebAssembly?

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

让我们用tinygo来写一个WebAssembly的模块,然后用js调用吧。首先下载TINYGO:(https://tinygo.org/,请下载对应版本的二进制文件)。然后将bin/tinygo(or tinygo.exe)加入到PATH路径。

然后先创建一个main.go文件(文件名必须是main.go,因为js里有用到文件名),文件内容如下:

package main

// This calls a JS function from Go.
func main() {
    println("Go: Hello World") // expecting 5
    println("Go: add(2+3):", add(2, 3)) // expecting 5
    println("Go: multiply(2*3):", multiply(2, 3)) // expecting 6
}

// This function is imported from JavaScript, as it doesn't define a body.
// You should define a function named 'main.add' in the WebAssembly 'env'
// module from JavaScript.
func add(x, y int) int

// This function is exported to JavaScript, so can be called using
// exports.multiply() in JavaScript.
//go:export multiply
func multiply(x, y int) int {
    return x * y;
}

然后用tinygo编译这个go文件,生成wasm文件。

目前最新版的tinygo0.12.0,最高只支持golang 1.13(目前最新版本的golang1.14),编译的命令中文件名必须是main.go,不能写”./main.go”

tinygo build -o wasm.wasm -target wasm main.go

Error:  tinygo build -o wasm.wasm -target wasm ./main.go

 

然后用go写一个简单的文件服务器(用于启动http服务器,因为wasm加载必须在http/https的环境下),注意对于wasm文件,要设置Content-Type为application/wasm

package main

import (
    "log"
    "net/http"
    "strings"
)

const dir = "./html"

func main() {
    fs := http.FileServer(http.Dir(dir))
    log.Print("Serving " + dir + " on http://localhost:8080")
    http.ListenAndServe(":8080", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
        resp.Header().Add("Cache-Control", "no-cache")
        if strings.HasSuffix(req.URL.Path, ".wasm") {
            resp.Header().Set("Content-Type", "application/wasm")
        }
        fs.ServeHTTP(resp, req)
    }))}

然后在服务器目录下创建html目录,目录里新建index.html文件(注意js代码中设置env的代码):

<html>
<head>
    <title>WebAssembly</title>
</head>
<body>
<script src="wasm_exec.js"></script>
<script type="text/javascript">
    const go = new Go(); // Defined in wasm_exec.js
    const WASM_URL = 'wasm.wasm';
    go.importObject.env['main.go.add'] = function (x, y) {
        return x + y
    };
    var wasm;

    console.log("'instantiateStreaming' in WebAssembly => " + ('instantiateStreaming' in WebAssembly ? "Y" : "N"));
    if ('instantiateStreaming' in WebAssembly) {
        WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {
            wasm = obj.instance;
            go.run(wasm);
            console.log('JS: multiplied two numbers:', wasm.exports.multiply(5, 3));
        }).catch((err) => {
            console.error(err);
        });
    } else {
        fetch(WASM_URL).then(resp =>
            resp.arrayBuffer()
        ).then(bytes =>
            WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {
                wasm = obj.instance;
                go.run(wasm);
            })
        )
    }

</script>
</body>
</html>

index.html里面引用的wasm_exec.js文件就在tinygo下载包里,wasm.wasm就是我们刚刚编译生成的文件。

浏览器里打开这个网页 http://localhost:8080/index.html,发现控制台就能输出:

23:25:58.955 ‘instantiateStreaming’ in WebAssembly => Y

23:25:58.964 Go: Hello World

23:25:58.964 Go: add(2+3): 5

23:25:58.964 Go: multiply(2*3): 6

23:25:58.964 JS: multiplied two numbers: 15

23:25:58.966 Fetch finished loading: GET “http://localhost:8080/wasm.wasm”.

References:

https://webassembly.org/

https://tinygo.org/

 

《带着爸爸去留学》观影感言

时光如梭,一看,上一篇的读书笔记已是一年之前的了。过去一年忙于生存,少有闲暇和心情看书/剧、思考,鼠年加油!

想来看这部电视剧,是因为在网上看到一个片段: 董美玲(黄小栋他妈)请求黄成栋不要再说了(真相),请他消消气,要发火就对她发火,然后他们在餐馆点菜,黄成栋点了一桌绿色菜。

本着吃瓜群众的好奇(八卦)心态,在这个春节假期就看了这部剧。

前面几集感觉就是:毁三观。感觉几个小孩都欠揍。之前家庭里都太惯着他们,让他们没有培养独立处理事情的能力,本剧是借着留学来说这些事情,在我看来即使不留学,在国内他们也会做出一些类似的奇葩事情来。不过结局我觉得倒是不错,虽然过程曲折,孩子们受过了不少伤,但是孩子们都成长了,开始能够成熟的面对生活中遇到的事情。

看了这部剧,更坚定了我的看法:夫妻关系才是一个家庭的第一位,尤其不能将对小孩的爱凌驾于夫妻关系之上。夫妻相互扶持,对待小孩要爱护,但是也要适当放手,要培养他们独立的生活能力。要知道将来陪TA过完一生的肯定不是父母,TA只有知道如何独立,如何对待亲人、朋友、另一半(如果有),他可能有幸福的生活。总结起来就是:父母爱子女则为之计深远。

爱就是克制。

PHP中foreach循环时使用引用的一个坑

记录一个广为流传的关于使用PHP引用的坑。

$arr = ['abc', 'ben', 'cam', 'day'];
foreach($arr as $key=>&$val){
    $val = strtoupper($val);
}
foreach($arr as $val){
    echo "$val\n";
    print_r($arr);

}
echo "===END===\n";
print_r($arr);

解释:

//第二次使用$val做foreach循环时,此时$val还是保持着对$arr数组里的最后一个元素($arr[3])的引用。
//所以对于这个foreach,
//1st ==> $arr[3]=’abc’
//2nd ==> $arr[3] = ‘ben’
//3rd ==> $arr[3] = ‘cam’
//4th ==> $arr[3] = ‘day’

所以正确的做法是在使用引用的foreach结束后马上unset($val)
或者干脆不用使用引用,foreach时使用$key=>$val格式,然后使用$arr[$key]方式修改变量并保存。

Wall Clock and Monotonic Clock

Wall clock(time) VS Monotonic clock(time)

Wall clock(time)就是我们一般意义上的时间,就像墙上钟所指示的时间。

Monotonic clock(time)字面意思是单调时间,实际上它指的是从某个点开始后(比如系统启动以后)流逝的时间,jiffies一定是单调递增的!

而特别要强调的是计算两个时间点的差值一定要用Monotonic clock(time),因为Wall clock(time)是可以被修改的,比如计算机时间被回拨(比如校准或者人工回拨等情况),或者闰秒( leap second),会导致两个wall clock(time)可能出现负数。(因为操作系统或者上层应用不一定完全支持闰秒,出现闰秒后系统时间会在后续某个点会调整为正确值,就有可能出现时钟回拨(当然也不是一定,比如ntpdate就有可能出现时钟回拨,但是ntpd就不会))

 

PHP 7.3新增了hrtime函数

hrtime ([ bool $get_as_number = FALSE ] ) : mixed

Returns the system’s high resolution time, counted from an arbitrary point in time. The delivered timestamp is monotonic and can not be adjusted.

<?php


while(true){
    var_dump(time());
//    $micro = microtime(true);
//    var_dump($micro);
//    echo PHP_EOL;

    //var_dump(hrtime());
    $nanosecond = hrtime(true);
    var_dump($nanosecond/1000/1000/1000);//nanosecond => second
    echo PHP_EOL;
    echo PHP_EOL;
    echo PHP_EOL;
    echo PHP_EOL;

    sleep(5);
}

执行此脚本,然后在过程中手动更改系统时间。执行结果如下

 

……

int(1554975423)

float(481987.58385405)

 

int(1554975428)

float(481992.58812)

 

int(1554975433)    ==>    北京时间:2019/4/11 17:37:13

float(481997.59318082)

 

int(1554889031)   ==>      北京时间:2019/4/10 17:37:11

float(482002.59569814)

 

int(1554889036)

float(482007.59825222)

……

 

hrtime()的返回值就是一直单调递增的,而time()的返回值就可能出现跳跃。所以在计算时间差时要用hrtime(),注意PHP版本至少要7.3 。

 

 

《重构 改善既有代码的设计》读书笔记

 

本书可以被看成是一本重构方法的手册。且因为本书成书较早,所以很多重构手段都被大家耳熟能详并从入门开始都被当成的编码规范。所以很大程度上阅读本书也算是温习。

  1. Kent Beck:我不是个伟大的程序员,我只是个有着一些优秀习惯的好程序员。
  2. (大多数时候)不需要专门安排时间重构,重构应该随时随地进行。你不应该为重构而重构,你之所以重构,是因为你先做别的什么事,而重构可以帮助你把那些事做好(比如效率更高,能容易扩展)。重构与编码总是伴随进行的。重构不是一劳永逸的,我们需要在系统发展中不断的进行,不断重构出适应未来的代码(而且这个未来往往也只能指未来一段时间,而非永远)。
  3. “三次法则,事不过三,三则重构。” 实际上,有了IDE的帮助,但第二次相同代码出现时,IDE就会提示需要重构了。
  4. 把未完成的重构工作形容为「债务」。
    Ward Cunningham对此有一个很好的看法。他把未完成的重构工作形容为「债务」。很多公司都需要借债来使自己更有效地运转。但是借债就得付利息,过于复杂的代码所造成的「维护和扩展的额外开销」就是利息。你可以承受一定程度的利息,但如果利息太高你就会被压垮。把债务管理好是很重要的,你应该随时通过重构来偿还一部分债务。
    如果项目己经非常接近最后期限,你不应该再分心于重构,因为己经没有时间了。不过多个项目经验显示:重构的确能够提高生产力。如果最后你没有足够时间,通常就表示你其实早该进行重构。
  5. 从重构联想到软件复用和技术传播
    Geoffrey Moore 把「技术的接纳过程」描述为一条钟型(bell-shaped )曲线:前段包括先行者(innovators )和早期接受者(early adopters),中部急剧增加的人群包括早期消费群体(early majority )和晚期消费群体( late majority),后段则是那些行动缓慢者(laggards)。一个思想或产品如果要成功,必须得到早期消费者和晚期消费者的广泛支持。另一方面,许多对于先行者和早期接受者很有吸引力的想法, 最终彻底失败,因为它们没能跨越鸿沟,让早期消费者和晚期消费者接纳它们。之所以有这样的鸿沟是因为,不同的消费人群有着不同的消费动机。先行者和早期接受者感兴趣的是新技术、「范式移转和突破性思想」的愿景(visions of paradigm shifts and breakthroughs)。早期和晚期消费群则主要关心成熟度、成本、支持,以及这种新思想或新产品是否被「与他们有着相似需求」的其他人成功套用。
    要打动并说服软件开发者,所需方式和打动并说服软件研究者是完全不同的。软件研究者通常是Moore 所说的「先行者」,软件开发者(尤其是软件经理)则往往属于早期或晚期消费者。如果想要让你的思想深入所有人心,了解这一差异是非常重要的。是的,无论软件复用或重构,要想打动软件开发者,这一点都至关重要。

 

《网络安全——输不起的互联网战争》读书笔记

  1. 作者认为,因为物理设备的多样性,网络攻击很难大面积展开。
  2. Buckshot Yankee
  3. 很难定位网络攻击的真实来源,即使定位了物理上的来源,但是由于来源设备可能存在被第三方入侵,所以不能代表设备拥有者的意图。当然有时攻击方也会利用这种情况否认己方发动了攻击。
  4. 作者认为现在网络的攻击的危害有限,当然他同时也告诫我们不能放松警惕。我是不太认同作者的这个观点的。作者说认为现在网络攻击对普通民众的日常生活的影响微乎其微,相比物理上的攻击危害(比如恐怖袭击、核弹……)也小很多。但是我认为现在互联网正在占领各个传统领域(被传统领域应用),比如国内的交通、支付、甚至日常工作……所以网络攻击的危害已经非常大了。

结合第一点,即使物理设备的多样性,但是由于单一种类设备的使用基数大(在不同场景下),那么攻击者还是愿意投入精力开发攻击软件的。另外,现在物理设备越来越智能化,能够运行小型的OS(Unix或Linux),也给攻击者提供了很多发挥的空间。

  1. 恢复能力、组织松散性

“即使在私营企业中,恢复能力与提高效率的目标也是矛盾的,因为冗余明显是一种浪费。”

“专家们注意到,哪些最具效率的企业其实很脆弱,而且受到适应变化能力差及创新能力不足的制约。这些企业缺少”组织松散性“,这种松散性往往能产生积极的文化,并促使企业成才。同样建立“恢复能力”的组织特征也有助于增强“组织松散性”。同样,充分进行安全评估,已经让员工了解企业的远期目标,有助于提高恢复能力.”

  1. 全球范围内,很难在网络安全领域达成一致的协议。很多国家都希望能够独立掌控本国范围内的网络,他们认为网络不存在“没有主权”的公共空间。

 

总的来说,网络安全对一个国家而言是十分重要的,虽然目前时间,网络攻击没有像真实武器那样危害深刻且明显,但是我们一定要在战略上予以重视。在战略层面搭建网络安全框架,与世界网络强国保持紧密联系,尝试与各国一起建立统一的网络安全规范,努力追求网络更高层次的安全。

 

stuxnet(震网病毒)

震网(Stuxnet),又称作超级工厂,是一种Windows平台上的计算机蠕虫,2010年6月首次被白俄罗斯安全公司VirusBlokAda发现,其名称是从代码中的关键字得来,它的传播是从2009年6月开始甚至更早,首次大范围报道的是Brian Krebs的安全博客。它是首个针对工业控制系统的蠕虫病毒,利用西门子公司控制系统(SIMATIC WinCC/Step7)存在的漏洞感染数据采集与监控系统(SCADA),能向可编程逻辑控制器(PLC)写入代码并将代码隐藏。

这是有史以来第一个包含PLC Rootkit的计算机蠕虫,也是已知的第一个以关键工业基础设施为目标的蠕虫。此外,该蠕虫的可能目标为伊朗使用西门子控制系统的高价值基础设施。据报道,该蠕虫病毒可能已感染并破坏了伊朗纳坦兹的核设施,并最终使伊朗的布什尔核电站推迟启动。不过西门子公司表示,该蠕虫事实上并没有造成任何损害。

赛门铁克安全响应中心高级主任凯文·霍根(Kevin Hogan)指出,在伊朗约60%的个人计算机被感染,这意味着其目标是当地的工业基础设施。俄罗斯安全公司卡巴斯基实验室发布了一个声明,认为Stuxnet蠕虫“是一种十分有效并且可怕的网络武器原型,这种网络武器将导致世界上新的军备竞赛,一场网络军备竞赛时代的到来。”并认为“除非有国家和政府的支持和协助,否则很难发动如此规模的攻击。”伊朗成为了真实网络战的第一个目标。

References:

https://zh.wikipedia.org/wiki/%E9%9C%87%E7%BD%91