关于 REST 的思考

2018-07-11 Dev 孙耀珠

这篇文章是我在《B/S 体系软件设计》课程的中期报告(命题作文)。因为在开发求是潮手机站时有写过与后端 API 通信的部分,在其他项目中也不时要考虑 API 设计的问题,所以在这方面也有一些自己粗浅的体悟。

表现层状态转化(REST)是一种网络应用程序的架构风格,通常体现在客户端与服务端的通信方式上。不过 REST 与简单对象访问协议(SOAP)等不同,它并不是一种规范化的协议,而是直接基于 HTTP 实现的一种接口风格。它相比 SOAP 等协议而言更加简单自然,因此在网站接口设计上得到了广泛应用。REST 这个名字起得有点令人费解,这是 Roy Fielding 在其博士论文1中创造的名词,不过其思想也可以被解释为「HTTP 对象模型」,并且这些思想早已被用在 HTTP 和 URI 标准的设计上。因此,我们可以先从 HTTP 和 URI 谈起。

  1. Roy Fielding. Architectural Styles and the Design of Network-based Software Architectures. PhD dissertation, University of California, Irvine, 2000. Chapter 5: Representational State Transfer (REST) 

Read More

东京一年

2018-03-04 Diary 孙耀珠

東京工業大学

说起来,第一次来日本还是四年前的高中毕业旅行,当时沿着东海道线一路游览了近畿、箱根和东京。如今作为留学生重踏东京的土地,身份从风尘仆仆的游客转变为一千三百万都民中的一员,想到能与真实的东京近距离接触就十分心动。

Read More

使用 fastlane 自动化 iOS 部署

2016-11-30 Dev 孙耀珠

对于 iOS 开发者来说,应用发布和代码签名证书大概是最令人头疼的两个环节了,这倒不是因为技术上有多难,而是它们的操作流程相当麻烦,尤其是在中国的网络环境下。

一般来讲,手动发布应用更新大致有以下流程:修改所有 Target 的版本号、用 Xcode 给项目 Archive、在 Xcode Organizer 中上传到 App Store、到 iTunes Connect 更新相关信息、提交给苹果审核。而其中上传那一步在不翻墙的情况下成功率极低,经常会卡在「Authenticating with the iTunes Store…」,而且系统 SOCKS 代理(如 Shadowsocks)在此时似乎并不起作用,只有使用 Proxifier 或者 VPN 才有效果。也是基于这个原因,我一般不会直接在 Organizer 中直接上传,而是先导出为 .ipa 文件,再使用 Xcode 附带的 Application Loader 上传,这样就免去了上传失败的话每次直接上传时将 .xcarchive 转为 .ipa 的时间。

当然以上还没考虑第一次发布时配置证书的流程,一个初学者面对苹果开发者中心琳琅满目的 Certificates / Identifiers / Provisioning Profiles 多半是一脸懵逼,不过幸运的是从 Xcode 8 开始已经能够比较完美地自动管理代码签名了,不再像以前一样需要自己去 Fix issues。

对于 iOS 应用的部署,如果你也像我一样饱受折磨,fastlane 也许是你的救星。

Read More

Deploy Rails with PostgreSQL Using Passenger and Nginx on CentOS

2016-02-10 Dev 孙耀珠

最近读完了 Michael Hartl 的《Ruby on Rails Tutorial》,于是想试着在自己的 Digital Ocean (CentOS 7) 上部署一下最终完成的 sample app。最简单的方法当然是:

$ rails server -e production -b 0.0.0.0 -p 80

但 Rails 内建的 WEBrick + SQLite 性能较差,而且这样部署也不够灵活,还是上 Apache / Nginx 比较主流。与 Apache 相比 Nginx 的异步模型能更好地处理高并发的场景,Passenger 性能不错并且可以直接集成于 Apache / Nginx 而不必反向代理,而 PostgreSQL 比 MySQL / MariaDB 功能更强大,这三者是 Ruby 服务器的最佳实践之一,因此我决定折腾一下 Nginx + Passenger + PostgreSQL。

安装 Ruby

直接使用 yum 安装当然是可行的,但 Ruby Version Manager (RVM) 能够更方便地安装并管理 Ruby 版本,因此下面以 RVM 为例。安装 RVM:

$ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
$ curl -sSL https://get.rvm.io | bash -s stable

接着就能轻松地安装任意版本的 Ruby 了(rvm list known 可以列出已知的版本):

$ rvm install X.X.X
$ rvm --default use X.X.X
Read More

Ruby: collect, detect, inject, reject, select

2016-01-04 Study 孙耀珠

在比较 Ruby 和 Python 的时候,很多人会说 Python 是一门简约的语言,而 Ruby 是一门魔幻的语言。之所以说 Ruby 魔幻,一方面是因为神奇的元编程和甜甜的语法糖,另一方面是在 Ruby 中总有不止一种方法去做一件事(There’s more than one way to do it),循环便是其中一例。

如果写过主流的结构化编程语言,那么一定对 for 循环非常熟悉吧。Pascal 继承了 ALGOL 风格的 for 循环,由初值、终值以及可选的步长组成;C 语言则创造了现在广为人知的三段式 for 循环,被 Java / JavaScript / PHP 等主流语言所沿用;而 Python / Swift 等语言使用 for-in 语句结合 range 也能实现相同的功能:

for i := 0 to n-1 do ……         ⍝ Pascal
for (int i = 0; i < n; ++i) ……  ⍝ C
for i in range(0, n): ……        ⍝ Python
for i in 0..<n { …… }           ⍝ Swift

而在 Ruby 的世界中,有一些有趣的方法可以取代 for 循环:

n.times { |i| …… }
0.upto(n-1) { |i| …… }
(0...n).each { |i| …… }

不过 Ruby 并没有激进地删掉 for 关键字,实现了 each 方法的对象都能以 for-in 语句进行迭代。像上述 times / upto / each 这样的方法在 Ruby 中被称为迭代器(iterator),其实现方式与后来 Python / JavaScript 等语言中的生成器(generator)相似,但使用方式更接近于函数式编程中广泛采用的高阶函数(higher-order function)。

Read More

Qt 多线程解决 UI 阻塞

2015-11-17 Dev 孙耀珠

这学期选了一门物理实验的小课题「宇宙射线μ子探测」,于是需要给实验用到的程序写个 GUI。因为目标平台是 Windows,何宇就直接去写 WPF 了;而我本身不是 Windows 用户,当然倾向于寻找一个跨平台的解决方案,目前主流的 GUI 框架中 Qt 大概是最优雅的选择(知乎上也有对此的讨论)。

除了原生的 C++,Qt 也支持其他许多语言的绑定,譬如 PyQt、QtRuby 等等;Qt 近年新推的 Qt Quick 也改用了可以内嵌 JS 的新语言 QML。不过因为我恰好在上 C++ 的面向对象程序设计课,正想借此机会实践一下,所以我还是选择了原生的 C++。

因为实验模拟是个计算密集型的任务,整个计算函数要跑很长时间,如果直接调用它,必然会阻塞事件循环。这样一来,GUI 所有的绘制和交互都被阻塞在事件队列中,整个程序就失去响应了。

对于这样的阻塞一般有两种解决办法:一是在计算任务中不停地调用静态成员函数 QCoreApplication::processEvents() 来手动运行事件循环,它会在处理完队列中所有事件后返回。不过这样做毕竟没有从根本上解决问题,另外如果两次函数调用之间间隔的时间不够短,用户仍能明显感觉到程序卡顿。

第二种解决办法就是为任务新开一个线程,这样就能在不干扰 GUI 线程的情况下完成计算了。Qt 提供了三种控制线程的方式:QThread、QRunnable / QThreadPool、QtConcurrent,其中最通用、也是最常见的是 QThread。

Read More

魔都纪行

2015-08-05 Diary 孙耀珠

大一这年来,屈指一算我总共去了三次上海:第一次是去看 CCG;第二次游历了五角场,然而重点是去嘉兴路看了 SNH48 剧场公演;最近的一次是去看 ChinaJoy。虽然说不上有多熟悉上海,但渐渐对上海有了一种莫名的亲切感,大概今后依然会经常造访魔都吧。

CCG

去年暑假是我和初中同学第二次一起去看 CCG,原计划五天的行程因为随后的日本之行压缩成了两天,交通路线、食宿都是轻车熟路,没有什么波折。我原以为浦东新区是个高度现代化、处处高楼鳞次栉比的地方,正如我原以为上海站会干净整洁、富丽堂皇,然而真正来了才发现,这里的大街小巷跟我的家乡并没有太大差别:从地铁站到宾馆的路上,依旧是熟悉的小餐馆、小超市、以及路边叫卖的摊贩,只有远远眺望那红色的中国馆才提醒着我这里几年前可是举世瞩目的世博园区。

Read More

《C 陷阱与缺陷》笔记

2015-06-07 Study 孙耀珠

词法陷阱(Lexical pitfalls)

  • 由 ALGOL 派生的编程语言如 Pascal 和 Ada,使用 := 作为赋值运算符,而 = 作为比较运算符。C 语言则使用了另一种表示法,以 = 为赋值运算符,以 == 为比较运算符。
  • 在 C 语言中,&| 是按位运算符,而 &&|| 是逻辑运算符。另外,^ 表示按位异或,而不是乘方。
  • C 编译器在词法分析时遵从贪心法,比如 y = x/*p/* 会被理解为注释的开始,而不是 y = x / *p
  • 0 开头的整型字面量将被视为八进制,因此切忌用 0 来占位对齐。
  • 单引号引起的一个字符实际上代表一个整数,而用双引号引起的字符串代表一个无名的字符数组。如果误用单引号引起一个字符串,使用 Clang 等编译器会得到最后一个字符的整数值,而其他编译器也可能得到第一个字符的整数值。
Read More

Swift 学习笔记(三)

2015-05-05 Study 孙耀珠

与 Objective-C API 交互

Swift 3 对 Objective-C API 做了大规模的修改,使之更清晰、更适应于 Swift。Swift Evolution 的三个提案 SE-0005SE-0006SE-0059 都对 API 的设计提出了不少改进,并最终形成了一份 API Design Guidelines

初始化

  • 使用 Swift 语法调用 Objective-C 的构造器时,方法名中的 initinitWith 前缀会被截去,其余各部分依次变为构造器的参数名,不过其中多余的成分会被删掉。同时不再需要调用 alloc 方法。
  • 为了一致性和便捷性,Objective-C 中的工厂方法(factory methods)也被映射成为 Swift 中的构造器。
  • 在 Objective-C 中可能返回 nil 的构造器,引入 Swift 时被定义为了可失败构造器。
// Objective-C
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];
// Swift
let myTableView = UITableView(frame: CGRect.zero, style: .grouped)
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)

方法和属性

  • 在 Swift 中调用 Objective-C 对象的方法和属性时,使用点语法。
  • Objective-C 的方法移植到 Swift 中时,原方法名的第一部分作为新的方法名和第一个参数标签,其余部分依次作为后面的参数标签,当然一些多余的成分会被删掉。
Read More

Swift 学习笔记(二)

2015-05-02 Study 孙耀珠

类和结构体

  • 类和结构体有以下共同点:属性(properties)、方法(methods)、下标(subscripts)、构造器(initializers)、扩展(extensions)、协议(protocols)。
  • 另外类有以下独有特性:继承(inheritance)、类型转换(type casting)、析构器(deinitializers)、自动引用计数(ARC)。
  • 类是引用类型,可通过 === / !== 判断是否同一实例;而结构体是值类型1

属性

存储属性(Stored Properties)

  • 存储属性即存储在类和结构体实例中的变量或常量,可以通过点语法(dot syntax)访问和赋值。
  • 存储属性必须在定义时或是在构造器中被赋初值(常量也可在构造器中赋初值),否则应将其定义为可选类型。
  • 如果创建了一个结构体的实例并赋给一个常量,则无法修改实例的任何属性,包括变量存储属性。而类为引用类型,故仍可修改。
  • 在变量属性声明前使用 lazy var 可以标记一个延迟存储属性,该属性将在第一次被访问时才会创建。因为实例方法在初始化完成前是不可被调用的,所以使用 lazy 可以避开这一规则调用实例方法为属性设初始值。
Read More

Swift 学习笔记(一)

2015-04-26 Study 孙耀珠

苹果自收购 NeXT 公司开始便使用 Objective-C 作为主力开发语言,至今已有十多年了,若是从这门语言发明之日算起更是超过三十年;而在这期间微软推出了 C# 和 F#,谷歌推出了 Go 和 Dart,Mozilla 推出了 Rust……虽然 Objective-C 随着 OS X 和 iOS 的迅速发展而越来越火,但相比之下它的语言设计已经落后于时代了,于是在这个大背景下 Swift 诞生了,开发者正是 LLVM / Clang 之父 Chris Lattner。

Swift 仍然是一门静态类型的语言,不过它拥有很多现代的语言特性,譬如类型推断、泛型、元组、更优雅的闭包等等,同时也有 Playgrounds 这样便利的交互式编程环境。Swift 非常强调安全性,不论是随处可见的可选类型、继承时复杂的构造规则,还是赋值没有返回值、控制流不能省略花括号,都是为了代码安全而考虑。另外 Swift 终于丢掉了 C 语言的包袱,放弃了指针,switch 语句不再需要 break,整型溢出会抛出运行时错误等等。

我们能够看出它本身还是构建在 Objective-C 的基础之上,两者能够很方便地交互和共存,Cocoa / Cocoa Touch 的 API 也是共通的。Swift 的语法目前仍在不断改进,从 Swift-Evolution Proposal Status 可见一斑,我也会根据最新的文档及时更新这三篇学习笔记。(Updated: 2016-10-17)

数据类型

整数

  • 在 32 位平台上,Int / UIntInt32 / UInt32 长度相同。
  • 在 64 位平台上,Int / UIntInt64 / UInt64 长度相同。
  • 字面量前缀:二进制为 0b,八进制为 0o,十六进制为 0x
Read More

Google Web Fonts 无法加载的解决方法

2014-11-14 Dev 孙耀珠

如果没有翻墙,大家一定会发现 Ruby 官方网站 加载得非常慢,在 Chrome 中停止加载的话仍能正常阅读,但在 Safari 中停止加载只能得到一片空白。

为了探明真相,我们可以调出浏览器的开发者工具,从时间线中可以看出究竟是什么拖慢了加载的进度:

屏幕快照

Read More

Sublime Text for Mac 使用配置

2014-11-08 Dev 孙耀珠

Mac OS X 从不缺乏优秀的代码编辑器,从 Vim 和 Emacs 到 Xcode、IntelliJ IDEA、Eclipse,都有着为数甚多的忠实用户。然而大多数的 IDE 是为软件工程而设计的,若只是写写算法题,那么只需要简单的命令行程序,用这些面向工程的 IDE 堪比杀鸡用牛刀了。

Sublime Text 作为一个轻量级的代码编辑器,对于单文件编程非常友好,原生支持不少主流语言的编译运行。它吸收了前辈 TextMate 的优点,并在可扩展性方面更胜一筹。通过各种插件包,我们可以定制包括主题、配色方案、编译选项在内的方方面面。

即便如此,Sublime Text 还是有一些不尽如人意的地方需要进一步配置,以下便是 C / C++、Python、Ruby、HTML 的几处配置技巧。

测试环境:Sublime Text 3 Build 3065 (OS X Yosemite 10.10)

Read More

动画介绍:攻壳机动队

2014-11-03 Diary 孙耀珠

若是谈论科幻,就不得不提赛博朋克(Cyberpunk);提及赛博朋克,一定不会少了《攻壳机动队》(Ghost in the Shell)。

Read More

Hello, World!

2014-11-02 Diary 孙耀珠

这是博客的第一篇文章,首先当然是说声欢迎来访~

我曾经用国外网络服务器商的免费空间搭建过 WordPress 博客,并绑定了 .tk 的免费域名。不过这些免费空间大多不太靠谱,一旦账号不活跃就很可能被停用;在国内不仅访问速度很慢,还有被墙的风险。于是不久我就放弃了原来的博客。

前几天,我偶然接触到了 Markdown 这个轻量级标记语言,发现其与维基百科所使用的 Wiki Markup 异曲同工(不考虑后者复杂的模板功能)——比 HTML 简单、比 Microsoft Word / Apple Pages 纯粹,但同时也能满足平时富文本编辑的需要。自然而然地,我萌生了用 Markdown 写博客的想法。对于一个程序员来说,网站搭建在自己的服务器上这种可控的感觉当然是最好的,不过像博客这样的静态网站托管在 GitHub Pages 也是不错的选择,还省去了自己去维护的工夫。而静态网站生成工具我选择了 Jekyll,首先是因为自己对于 Ruby 更加熟悉,其次 GitHub Pages 原生支持 Jekyll,因此可以直接托管源码,不用像 Hexo 一样先在本地生成所有静态文件再推送到 GitHub 上。

Read More