Skip to content

zh

偽Scrum - 瀑布式和敏捷的混合體

我有些事情要告訴你:你並非真正的敏捷。你可能已經完成了所有的 Scrum 儀式,如站立會議、示範和檢討。你甚至可能有所有必要的工具,如JIRA、使用者故事和Scrum看板。然而,如果心態不正確,那麼某些基本的東西仍然缺失。以下是原因:

你有一個詳細的計劃

你正在堅持嚴格的一年期限。Scrum團隊根據在衝刺計劃期間做出的估算來計算速度。那麼,你怎麼能期待Scrum團隊與高層管理的最佳猜測相符呢?當路線圖是固定的,範圍不變,並且發布計劃不切實際時,你實際上正在遵循瀑布模型。

真正的Scrum Master缺席

你的組織圖上可能有一個Scrum Master,但他們的實際角色是什麼?通常,這個人不是全職的Scrum Master,而是一個項目經理、產品擁有者或者資深開發者,他們並未全心投入這個角色。當Scrum Master兼顧多項責任時,事情就開始出軌。即使你有一個專門的Scrum Master,他們可能也無法解決由於技術複雜性或超出他們工作職責的限制所帶來的實際障礙。

沒有指定的產品擁有者

需要有人負責產品,但通常這個人會被其他優先事項所佔據。如果沒有明確的視野和產品所有權,特性開發可能會出錯。當要求由外部高級主管指導時,這一點尤其正確,導致開發努力被浪費。雖然產品擁有者應該做出這些決定,但很少有人願意冒這些風險,許多人對他們實際想要什麼並不確定。

缺乏預算策略

故事點並不能替代預算。當你操縱估算來獲得更多的資金和時間,或者為了符合預算限制而向下談判,你就會對團隊的真實速度失去了視覺。傳統的會計方法也與敏捷開發不兼容。在預算上吝嗇往往會導致團隊燒休息,而不達到預期的結果。

我對敏捷宣言的看法

以下是我用自己的話來解釋敏捷宣言:把對變化的反應性放在遵循高級管理層設定的嚴格路線圖之上。尊重個人和互動超過辦公室政治。強調工作軟體超過無休止,毫無意義的會議。偏愛客戶合作超過預算談判。實現這一點並非易事,但對於官僚機構來說,這是在數位時代適應和繁榮的唯一途徑。

將 Koa.js 應用程式部署至 AWS EC2 Ubuntu 實例

我正在使用 Koa.js 開發一個應用程式,這是一個由 Express 團隊創建的新網頁框架。在這個逐步教學中,我將指導您如何在 Amazon Web Services (AWS) Ubuntu 伺服器上部署 Koa.js 應用程式。

在 AWS 上啟動 Ubuntu 實例

首先,在 AWS 上啟動一個 Ubuntu 實例。您需要修改安全組設定。

Security Group Settings

如果您沒有進行這些更改,試圖在瀏覽器中訪問公共域將導致“連接”狀態,直到超時,導致無法訪問網站。

Site Unreachable

默認情況下,啟動嚮導僅啟用 SSH。

SSH Only

點擊“編輯”按鈕以添加適用於 HTTP 端口 80 和 HTTPS 端口 443 的入站規則。

Edit Inbound Rules

安裝 Node.js

通過 SSH 登入您的實例並根據官方文檔安裝 Node.js:

curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs

設置 Nginx 作為反向代理伺服器

接下來,安裝 Nginx:

sudo apt-get update
sudo apt-get install nginx

打開配置文件並進行以下編輯。別忘了分號:

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

    root /var/www/yourApp;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

保存文件並重新啟動 Nginx 服務:

sudo systemctl restart nginx

部署您的應用程式

將您的 Git 存儲庫克隆到 /var/www/yourApp 目錄。您可能會遇到“Permission Denied”錯誤,所以更改文件夾的所有權:

sudo chown -R ubuntu /var/www

創建一個簡單的 app.js 來運行您的伺服器:

var koa = require("koa")
var app = koa()

// logger
app.use(function* (next) {
  var start = new Date()
  yield next
  var ms = new Date() - start
  console.log("%s %s - %s", this.method, this.url, ms)
})

// response
app.use(function* () {
  this.body = "Hello World"
})

app.listen(3000)

啟動伺服器:

node app.js

打開您的瀏覽器並導航到您的公共域。您應該看到您的 Koa.js 應用程式正在運行。

App Running

完成!如果您有任何問題,請隨時在下面留言。:)

從物聯網項目中吸取的教訓

去年,我參與了一個專注於藍牙智能裝置的物聯網(IoT)項目。這個經驗與純軟體開發在幾個方面有顯著的不同:

首先,集成帶來了挑戰,因為項目的機械設計、固件、手機應用程式和設計組件被分包給多個供應商。這些供應商有地理上分散的團隊和不同的工作文化。當開發人員在他們的領域專門化到組織成獨立的群體時,Scrum模型不太可能有效運行。

其次,硬體迭代的時長遠超過軟體迭代,使其難以適應變化。與軟體不同,軟體可以輕易被模塊化,許多硬體組件如晶片和主機板卻是相互關聯。這種情況推動了開發過程向著更像瀑布模型的方向。你只能收到整個原型或者一無所有;沒有傳遞一個用於消費者測試的最小可行產品(MVP)的中間地帶。早期用戶反饋的缺乏進一步阻礙了特性優先級的確定過程。

第三,當事情出錯時,診斷問題尤其具有挑戰性。很難確定問題是出在機械設計、固件還是手機應用程式的開發。此外,隨著介面的演變,端到端的測試變得更加複雜。在沒有全面的硬體自動化的情況下進行測試也很耗時。為了緩解這一點,有必要明確並可驗證的接受準則,確保“完成”的嚴格定義。

對任何IT項目的成功而言,有效的溝通至關重要,特別是當各個方面沒有按計劃進展時。指責和防衛可以嚴重損害部門之間的關係。有效的溝通需要同理心;嘗試從他人的角度理解問題,而不是情緒化或判斷式地反應。

客戶根據他們從產品中獲得的價值來評估性能。採取同理心和解決問題的思維方式可以減少浪費的時間和精力,從而提高整體性能。我期待著產品的發佈和最終用戶的積極反饋。

如何修復 iOS 10 權限崩潰錯誤

我一直在開發一款需要訪問用戶麥克風的應用程序。

該應用在 iOS 9 上運行正常,但在升級到 iOS 10 之後,它開始崩潰。終端顯示的錯誤消息如下:

> 此應用程序已崩潰,因為它試圖訪問隱私敏感數據而未提供使用說明。應用程序的 Info.plist 必須包含一個 NSMicrophoneUsageDescription 鍵,並提供一個字符串值解釋應用程序如何使用這些數據。
> (lldb)

要解決此問題,按源碼編輯 Info.plist 文件並添加以下行:

    <key>NSMicrophoneUsageDescription</key>
    <string>提供一個說明,解釋您的應用為何需要訪問麥克風。</string>

此外,如果您的應用需要訪問用戶的相機,請添加以下內容:

    <key>NSCameraUsageDescription</key>
    <string>提供一個說明,解釋您的應用為何需要訪問相機。</string>

如果您的應用需要訪問用戶的聯繫人,請添加以下內容:

    <key>NSContactsUsageDescription</key>
    <string>此應用需要訪問您的聯繫人。</string>

祝你編碼愉快!

香港金融科技的未來

我經常被我的老師告知,香港是一個國際金融中心。確實,在我們競爭激烈的企業環境中,我們每天都享受著經濟的成功。然而,香港目前在金融科技的革命中落後了。新加坡已經抓住了這個機會,並積極地前進。新加坡政府在吸引金融科技公司方面起著至關重要的作用,他們提供了激勵措施和明確的規章制度。此外,中國內地金融科技公司可用的廣大客戶基礎使得他們能夠以香港公司無法實現的方式蓬勃發展。

挑戰十分明顯:香港過於保守的心態正在減緩金融科技行業的進步。作為一名 IT 顧問,我聽到許多銀行業的人對像區塊鏈、比特幣和移動支付等創新科技表示擔憂。他們擔心這些技術可能會破壞他們的業務,威脅工作,並導致大公司無法適應。

然而,這裡有一線希望:香港擁有大量的創新和創造力的個體。我們的社區擁有多樣化的思考者,建設者,和領導者。我們有可能組建優秀的團隊來啟發並為創造世界上最好的金融科技生態系統做出貢獻。現在是提高我們的意識,重新想象當金融科技作為正向產業轉型的助推器時,可能會發生什麼。

依我看,這是我們期望的結果:我們正引導全球的金融科技變得更以人為本。我們目前的法律沙盒政策允許公司在市場上測試他們的創新想法。這些金融科技有可能對全球人民的生活產生積極的影響。讓我們一起利用金融科技的語言和工具,將香港重新建立為金融科技商業的區域中心。

什麼是區塊鏈,以及它如何被使用?

很多朋友都在問我關於區塊鏈革命的出現。根據最近的新聞,世界四大銀行已經聯手開發一種新形式的數位現金。這種數位現金旨在成為清算和結算金融交易的區塊鏈技術的行業標準。同時,Ripple已經在B輪融資中籌得5500萬美元。在我看來,無疑區塊鏈有潛力顛覆傳統銀行。

何謂區塊鏈?

區塊鏈是一種數據結構,用作交易的數字記錄簿。這個記錄簿在數以百萬計的分散式網絡的電腦之間共享。利用最先進的密碼學,該技術安全地管理記錄簿。區塊鏈依賴共識模型運作:每個節點都同意每一筆交易,從而消除了傳統結算過程中需要中央交易對手(CCP)的需要。

如何使用?

區塊鏈通過使其更高效,對跨貨幣支付有廣泛的影響。它消除了時間延遲並降低了後勤成本。為了回應客戶對更快、更低成本的全球支付的日益增長的需求,區塊鏈允許直接的銀行對銀行的結算。這種技術的一些應用包括零售客戶的匯款服務,國際交易,企業支付和跨國銀行間的貨幣轉帳。

何種創新?

這項技術提供了交易可以在不需要知道對方是誰的情況下進行的機會。其最創新的特點是分散化數據庫的理念,其中信任是通過大規模協作建立的,而不是通過一個負責認證和結算的中心化機構建立的。

可解決哪些問題?

區塊鏈的潛在應用擴展到了金融市場之外。這種技術可能提供一個對於多種用途可以信賴的不可變更的記錄。當前的身份識別基礎設施很容易被破壞;然而,在區塊鏈中,一旦數據塊被記錄,修改起來就變得非常困難。因此,它可以用於真正的隱私保護。每當有人試圖向區塊鏈添加數據時,所有現有的副本都運行算法來驗證交易。試圖欺詐系統的惡意嘗試被拒絕,而預期的交易在大多數節點通過鏈交易歷史驗證其有效性時獲得批准。因此,區塊鏈可以作為基於web的身份驗證的開放協議的基礎,創建一個'信任網絡',並以加密格式儲存數據。

參考文獻
  1. Martin Arnold, "Big banks plan to coin new digital currency," Financial Times, August 24, 2016, Financial Times Article
  2. Alyssa Jarrett, "Ripple Raises $55 Million in Series B Funding," Ripple official website, September 15, 2016, Ripple Article
  3. Don Tapscott, Alex, and Rik Kirkland, "How Blockchains Could Change the World," McKinsey & Co, May 8, 2016, ValueWalk Article

在 macOS 上安裝 Jupyter Notebook

我正在使用 Anaconda 發行版安裝 Jupyter Notebook。

步驟 1:下載 Anaconda

首先,訪問 Anaconda 網站以下載安裝程式:https://www.anaconda.com/products/distribution

步驟 2:安裝 Anaconda

運行下載的安裝程式並按照圖形提示進行 Anaconda 的安裝。

步驟 3:嘗試運行 Jupyter Notebook

安裝完成後,嘗試執行 Jupyter Notebook:

jupyter notebook

你可能會遇到以下錯誤:

> zsh: command not found: jupyter

這是因為 conda 命令也找不到:

> zsh: command not found: conda

步驟 4:更新 Shell 配置

為了解決此問題,使用你偏好的文本編輯器打開你的 .zshrc 文件:

vim ~/.zshrc

在文件底部添加以下行:

export PATH="$HOME/anaconda3/bin:$PATH"

步驟 5:重新啓動 Shell 並運行 Jupyter Notebook

保存文件並重新啓動你的 shell。嘗試再次運行 Jupyter Notebook。現在應該可以在 http://localhost:8888/ 上訪問。

在AWS EC2上啟動RancherOS

RancherOS是一種為運行Docker容器而設計的Linux發行版。雖然AWS Marketplace已經有可用的AMI(Amazon Machine Image),但設置安全組和其他配置可能會有些棘手。這份指南就是缺少的使用手冊。

1. 使用Rancher AMI啟動一個實例

假設你已經有一個 .pem密鑰,啟動一個實例並選擇Rancher AMI。

2. 連接到您的實例

打開終端並連接到您的實例。請注意,您應該使用rancher作為用戶,而不是root:

ssh -i "XXX.pem" rancher@ec2-XX-XXX-XX-XX.ap-southeast-1.compute.amazonaws.com
3. 驗證Rancher服務器

Rancher服務器應該已經在運行。你可以通過執行以下命令進行檢查:

docker ps

如果它沒有運行,可以使用Docker下載並啟動服務器:

docker run -d -p 8080:8080 rancher/server
4. 配置安全組

在AWS控制台中,轉到Security Group選項卡並創建一個包含入站規則的新組:

規則應包括:

  • 端口22、2376和8080/tcp 供Docker機器分配主機
  • 端口500和4500/udp 供Rancher網絡使用
  • 端口9345和9346/tcp 用於UI界面
  • 端口80/tcp 用於您部署的站點
5. 分配新的安全組

選擇實例,然後導航到Actions > Networking > Change Security Group。檢查新的安全組ID並將其分配給您的實例。

6. 訪問Rancher UI

打開一個瀏覽器並轉到公共DNS的8080端口,如 http://ec2-XX-XXX-XX-XX.ap-southeast-1.compute.amazonaws.com:8080

您應該會看到Rancher UI:

7. 使用AWS憑證添加主機

要使用Amazon EC2添加一個主機,您需要Access Key和Secret Key。如果您沒有它們,請前往AWS Console > IAM (Identity and Access Management) > Create New Users。下載credentials.csv文件。

接下來,前往Groups選項卡 > Group Actions > Add Users to Group。通過搜索"AmazonEC2FullAccess"來附加策略,選中方框,並應用更改。

8. 在Rancher UI中輸入AWS憑證

返回到Rancher UI,並從credentials.csv文件中輸入新生成的Access Key和Secret Key。

最後,填寫所需的信息,您將看到您的主機正在運行。

附言

要管理Docker的秘密API鑰匙、證書文件和生產配置,您可以根據您的具體需求嘗試使用beta版的Vault集成。

使用Docker容器部署Java Spring伺服器

在這份指南中,我將展示如何使用Docker部署Java Spring伺服器。請按照以下步驟操作:

1.啟動一個Ubuntu Server

對於這份演示,我們假設你已經啟動了一個運行Ubuntu 14.04的伺服器。使用APT資源庫安裝Docker:

sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

使用你最喜歡的文字編輯器打開/etc/apt/sources.list.d/docker.list,並添加以下行:

deb [https://apt.dockerproject.org/repo](https://apt.dockerproject.org/repo) ubuntu-trusty main

繼續在伺服器上安裝Docker:

sudo apt-get update
sudo apt-get install docker-engine
sudo service docker start
2.構建Docker映像

登入Docker Hub (https://hub.docker.com/),並創建新的儲存庫。然後,在你的終端機運行:

docker login

被提示時輸入您的用戶名和密碼。

在你的本地開發Java Spring資料夾,創建一個Dockerfile,內容如下:

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD target/fleet-beacon*.jar app.jar
EXPOSE 8080
RUN sh -c 'touch /app.jar'
ENTRYPOINT ["java", "-jar", "/app.jar"]

要構建映像,執行:

docker build -t username/repo-name .

這裡,-t代表"tag"。將usernamerepo-name替換成你的Docker Hub用戶名和儲存庫名稱。也不要忘記最後的句點。

將構建的映像推送到您的遠程儲存庫:

docker push username/repo-name
3.拉取Docker映像

在您的遠程Ubuntu伺服器上,登入Docker並拉取映像:

docker pull username/repo-name

在後臺運行容器:

docker run -d -p 8080:8080 username/repo-name

這裡,-d表示"detached", -p指定所有暴露的端口(例如,8080)都應該發布到主機接口。

4.設置Nginx

使用Vim編輯器,打開/etc/nginx/sites-available/default並將其修改如下:

server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

  root /usr/share/nginx/html;
  index index.html index.htm;
  server_name localhost;

  location / {
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass [http://localhost:8080/](http://localhost:8080/);
  }
}

退出並使用:wq!保存。

就這樣!打開瀏覽器,導航到你的遠程伺服器的IP地址;你應該能看到Java Spring頁面運行正常。

5.問題排查

如果你遇到Docker守護進程連接的問題,出現:

Cannot connect to the Docker daemon. Is the Docker daemon running on this host?

運行以下命令:

eval $(docker-machine env default)

如果你正在本地測試且找不到你的IP地址,用這個命令找到它:

docker-machine ls

如果你遇到任何其他問題,請隨時在下方留言。

使用Java Spring框架的蘋果推送通知

我正在實現一個使用Java Spring Framework伺服器,使用Swift向iPhone發送Apple推送通知。以下是你將需要的東西:

1. 設定帳戶

假設您已經有一個帶有證書的Apple開發者帳戶,登入 Apple Developer,前往 Identifiers 分頁並點擊"+" 新增一個。填寫前綴和後綴,然後記住勾選 "推送通知" 的箱子。

Image1 Image2

接下来,选择 編輯,滚到 推送通知部分。在这里,你会看到“能够配置”的橙色指示器。使用你的CSR文件创建并下载Development SSL证书。双击运行它,并将其添加到你的钥匙链。

Image3

开启 钥匙链访问,找到证书,并将其导出为 .p12 文件。你会被提示输入密码 - 不要将其留空。否则,Java Spring应用程序可能无法解析空字符串。将此文件保存以供以后使用。

Image4

2. Xcode 設置

建立一个新的Xcode项目,例如一个单视图应用。在功能分頁中,開啟“推送通知”並用你的Apple ID登入。

Image5

AppDelegate.swift 中,新增一個方法來建立一個設定的實例,這將在應用啟動時提示用戶許可:

func registerForPushNotifications(application: UIApplication) {
  let notificationSettings = UIUserNotificationSettings(forTypes: [.Badge, .Sound, .Alert], categories: nil)
  application.registerUserNotificationSettings(notificationSettings)
}

当应用完成启动时调用此方法:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
  // Override point for customization after application launch.
  registerForPushNotifications(application)
  return true
}

在同一個 AppDelegate.swift 文件中,新增方法以處理用戶的權限決定:

func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
  if notificationSettings.types != .None {
    application.registerForRemoteNotifications()
  }
}

如果注册成功,新增:

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
  let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
  var tokenString = ""

  for i in 0..<deviceToken.length {
    tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
  }

  print("Device Token:", tokenString)
}

如果注册失败:

func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
  print("Failed to register:", error)
}

測試時,您將需要一個實體設備;模擬器將無法使用。如果成功,您應該在控制台中看到設備令牌。记下这个供后来使用。

Image6

3. Java Spring 服务器设置

使用你喜欢的IDE(如NetBeans或IntelliJ)创建一个Java Spring Framework服务器。在这个例子中,我们正在使用一个配备pom.xml文件的Maven构建:

<!-- pom.xml content -->

我们将使用来自Maven Repository的 notnoop库。将此依赖项添加到你的 pom.xml:

<dependency>
  <groupId>com.notnoop.apns</groupId>
  <artifactId>apns</artifactId>
  <version>1.0.0.Beta6</version>
</dependency>

服务器启动时,它会寻找主类,例如 PushNotificationApplication.java

// PushNotificationApplication.java content

为了演示目的,我们将创建一个 NotificationController.java

// NotificationController.java content

用你真正的 .p12 文件路径,密码,和设备令牌替换代码中的占位符。如果您对文件路径不确定,将 .p12 文件放在 /src 文件夹的同一级别,即项目文件夹的根目录。

运行以下命令以安装并启动服务器:

mvn install
mvn spring-boot:run

打开你的浏览器并导航到 http://localhost:8080/notification。你应该收到通知!

Image7

如果你有任何疑問,隨時聯絡我 :)


注意:代码块 (XML, Swift, 和 Java) 内的内容未作更改。确保内容准确且最新。