2013/08/31

Embedded Sencha Touch Demo Code in My Blog

今天在思考怎麼在我的 blog 嵌入 Sencha Touch 的 library,之後寫 demo code 就可以看到 preview了!


首先選擇必要的 library

Sencha Touch 專案預設是用 micro-loader 載入設定在 app.json 的 js / css 檔,不過檔案太零碎需要發很多 request,若透過 internet 會拖慢速度,SDK 內同時也有提供整合的版本:
  • sencha-touch.js 131KB
  • sencha-touch-debug.js 514KB
  • sencha-touch-all.js 671KB
  • sencha-touch-all-debug.js 2.7M

各版本的用途可以參考 Using and Creating Builds,由於我需要使用到 widget,所以要選 all 的版本,sencha-touch-all.js (671KB) 雖然壓縮過了還是好肥大...

CSS 的部分,SDK 內也提供不同組的 theme 可以套:
  • base.css 230KB
  • bb10.css 184KB BlackBerry
  • sencha-touch.css 258KB
  • wp.css 194KB Windows Phone

2013/08/28

Sencha Touch AJAX 跨網域存取 (Cross Domain Request)

通常為了省麻煩,我們會把『提供網頁的 server』與『提供資料的 API server』放在同一個網域下,除非是存取第三方的 server,但現在大多走 OAuth 配合 token 在做存取...


那為何我會遇到跨網域問題?

是這樣的,使用 PhoneGap 開發 app 時,若要跟 API server 要資料也屬於跨網域存取,不過 PhoneGap 的 webkit 設計不像我們平常在用的 browser,所以不會有此限制。

只是開發過程我們會直接利用 browser debug,不會每次都把網頁放到 PhoneGap 內,然後 build、deploy 到 mobile device... 這實在太花時間了,這就是為何我需要解決 cross domain 的原因。

2013/08/26

PhoneGap 開發:Android back button 事件處理

使用 PhoneGap 開發 app 時,在 Android 平台上,預設按下 back button 的處理方式是關閉程式,這應該會讓使用者崩潰。PhoneGap 有提供對應的 backbutton 事件可以註冊,這樣就可以照自己的方式來處理。


這邊的處理方式是呼叫原生的 confirm 對話框,詢問 user 是否離開:
// Register event for back button
document.addEventListener("backbutton", function() { 
    navigator.notification.confirm(
        '你確定要離開程式嗎?', 
        onConfirmQuit, 
        '關閉', 
        ['確定', '取消']
    );
}, true);

function onConfirmQuit(button) {
    if (button == "1") {
        // Leave app
        navigator.app.exitApp(); 
    }
}


身為一個 Sencha Touch 的使用者,用客制化的視窗也是可以 OK 的
document.addEventListener("backbutton", function() { 
    Ext.Msg.confirm("關閉", "你確定要離開程式嗎?", function(buttonId) {
        if (buttonId == 'yes')
            navigator.app.exitApp();
    });
}, true);

更進階的做法就是讓使用者按下 back 時可以回到上一層的畫面,不過這邊我也還沒試過,目前的想法是啓用 location hash,按下 back 時就像瀏覽器回到上一頁一樣。參考:History Support - Touch 2.2.1 - Sencha Docs

利用 ImageMagick 製作 App 所需的 icon size

以下是 Android / iOS 兩種平台的 icon 開發指南,裡面有條列解析度/機型對應的 icon size


在此我是利用 PhoneGap 建立 mobile 專案,預設就有一組 icon,我們只要準備相同解析度的圖片覆蓋過去就可以了

Android 各解析度 icon 分別放置在不同的資料夾底下
  • res/drawable/logo.png 96x96
  • res/drawable-xhdpi/logo.png 96x96
  • res/drawable-hdpi/logo.png 72x72
  • res/drawable-mdpi/logo.png 48x48
  • res/drawable-ldpi/logo.png 36x36

iOS 擺放 icon 的位置在專案資料夾底下的 {project-name}/Resources/icons/
  • icon-72.png 72x72
  • icon-72@2x.png 144x144
  • icon.png 57x57
  • icon@2x.png 114x114


利用 ImageMagick 搭配 shell script 就可以一次轉出所有解析度的 icon

安裝 ImageMagick 目前最新版本 6.8.6-8
$ ./configure --with-png=yes
$ make && make install

轉換解析度
$ convert logo-src.png -resize 72x72 logo-72.png

批次轉換 script: convert.sh
#/bin/sh

res=(144 114 96 72 57 48 36)
for i in "${res[@]}"
do
    echo "convert icon for ${i}x${i}"
    convert logo-src.png -resize ${i}x${i} logo-${i}.png
done

記得 icon 的來源檔案解析度至少要大於144,轉出來才不會糊掉

2013/08/19

PhoneGap + Sencha Touch Quickstart (Part III)


透過前兩篇(Part I, Part II)我們分別建立的 PhoneGap 專案與 Sencha Touch 專案,再來就是將他們合併,也就是讓 Sencha Touch 透過 PhoneGap run 在模擬器上



Part III:Sencha Touch 與 PhoneGap 的結合


1. 把 Sencha Touch web page 複製到 PhoneGap

我們可以把 PhoneGap 想像成一個載體 (webview),上面運行著 Sencha Touch web page,而透過 javascript 可以和底層的 device 溝通。

所以最快的方式就是把 build 出來的 Sencha Touch package 複製到 PhoneGap 底下的 www 資料夾,然後重新 build PhoneGap,再重新 build 各平台的專案。
(在此為了簡化示範流程,才會用手動的方式複製,真正在開發時應該使用 ST project 內的 build.xml 去描述此步驟)

編譯出來的 ST 程式碼
 
Copy 到 PhoneGap 的www
注意來源跟目的,一個是 ST 一個是 PhoneGap。
另外原本在 www 裡面的 config.xml 要留著,編譯時會用到!
$ cp -a SenchaTouch/hello/build/HelloWorld/package/* PhoneGap/hello/www/
$ phonegap build ios
$ phonegap build android

按照 Part I 的方式分別編譯 ios/android 並運行
Good! It works.


2. 加入 PhoneGap deviceready event

由於 Sencha Touch demo 程式中並未使用到 PhoneGap 提供的 API,為了證明它可以work,所以我們要修改 Sencha Touch project 中的 index.html,加入很簡單的程式碼:當 deviceready event 觸發時就在 debug window 印出 deviceready (註:device ready 就表示 API 可以呼叫了)
加在 <head></head>之間,include "touch/microloader/development.js" 之後
<script type="text/javascript" src="phonegap.js"></script>
<script type="text/javascript">
document.addEventListener('deviceready', function() {
  console.log('deviceready');
}, false);
</script>

重新編譯 Sencha Touch project 後產生 package,將其 copy 到 PhoneGap ... (重複步驟1)
還記得編譯 ST 的指令嗎
$ sencha app build package

若看到 demo 網頁出現,同時 console 也跑出 deviceready 字眼,表示我們成功結合 Sencha Touch 與 PhonaGap 了!

iOS 訊息
2013-08-19 23:51:55.016 HelloWorld[71208:c07] deviceready
Android 訊息
I/Web Console( 1291): deviceready at file:///android_asset/www/index.html:61

註:
ios 的 debug window 在 Xcode 裡面
android 可以透過下面指令觀看整個系統的 log
$ adb -s emulator-5554 logcat

PhoneGap + Sencha Touch Quickstart (Part II)


上一篇講完了如何建立 PhoneGap 專案並且 run 在模擬器上,再來要講 Sencha Touch 這個 mobile web framework



Part II: 建立 Sencha Touch 專案


1. 下載 Sencha Touch SDK 與 Sencha Cmd

SDK 有分兩種版本 GPL 與 Commercial,目前最新版本為 2.2.1 在此下載
解壓縮開之後可以得到 touch-2.2.1 資料夾

Sencha Cmd 有 Mac 專屬版本,最新版本為 3.1.2 在此下載
下載後是個安裝檔,請指定安裝路徑。安裝後請把 sencha 執行檔的路徑加到環境變數 $PATH

試一下是否 work
$ sencha help | head -n 1
Sencha Cmd v3.1.2.342


2. 建立專案

利用 Sencha CMD 來建立專案,請指定 sdk 路徑到剛剛下載的 touch-2.2.1,HelloWorld 為專案名,"./hello"是專案建立的位置
$ sencha -sdk ~/Development/touch-2.2.1 generate app HelloWorld ./hello
產生專案資料夾 hello,裡面的 index.html 就是 app 的首頁
app.js 是程式進入點,app 資料夾依據 MVC 的分類放置自己的程式碼
resources 擺放 css, image, icon 這些檔案
touch 放置 Sencha Touch 原始碼,編譯時會引用


3. 編譯專案

夠過編譯可以將引用到的 javascript 從 source 中抽出並壓縮,SCSS 的部分也是會經過 compass 編譯壓縮
$ sencha app build package
在 hello/build/HelloWorld/package 資料夾下可以看到編譯結果


4. 測試

啓動 MacOS 內建 apache
$ sudo apachectl start

將 hello/build/HelloWorld/package copy 到 apache 預設的 document root: /Library/WebServer/Documents/hello
瀏覽網頁 http://localhost/hello/ 即可看到 demo 網站

PhoneGap + Sencha Touch Quickstart (Part I)


PhoneGap + Sencha Touch 這是跨平台 mobile app 開發的一種組合,在開發速度與效能都能接受的情況下,我近期都投入在這個 framework。在此要與大家分享如何快速建立一個 mobile app,系列文章包含三部分:

基本需求

開發環境 MacOS
PhoneGap 3.0.0
SenchaTouch 2.2.1


Part I:建立 PhoneGap 專案


1. 安裝 Mobile SDK

PhoneGap 支援的 mobile 平台有很多種,在這邊只針對 iOS 與 Android 做說明。
iOS 需要安裝 Xcode,可以從 app store 下載,目前我使用的版本是 4.6.3。
而 Android 的部分請參照 Android Platform Guide 下載 ADT,裡面包含了 Eclipse 編輯器與 SDK,SDK 的路徑必須加到環境變數 $PATH,日後 command line 會使用到。


2. 安裝 PhoneGap

PhoneGap 3.0.0 開始的 command line tool 改由 npm 套件管理程式來維護,所以我們要先安裝 node。Node.js官方網站有提供 Mac 專屬的.pkg可以下載,不過我習慣抓 source code 下來編譯,node 安裝好之後自然也會有 npm 指令可以用

利用 npm 來安裝 phonegap
$ sudo npm install -g phonegap
$ phonegap -v
3.0.0-0.14.3


3. 建立 PhoneGap 專案

$ phonegap create hello com.example.hello HelloWorld
產生 hello 資料夾,裡面包含 merges, platforms, plugins, www
platform 擺放各 mobile 平台的專案,plugins 存放提供你存取 device-level API 的 plugin,而 www 就是 app 主程式,平時就是編譯這一份檔案,預設會有基本的 demo 程式在裡面

剛建立好的 phonegap project 是不包含任何 mobile 平台支援,我們要加入 ios, android
$ phonegap build ios
$ phonegap build android
可以看到 hello/platform/ 之下有這兩個平台的專案資料夾

再來我們安裝 device-level API 支援,在此僅安裝最基本的 console plugin,至少可以拿來 debug,其它像是 camera, geolocation... 日後都可以依需求再安裝
$ phonegap local plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-console.git


4. 編譯 PhoneGap 專案

PhoneGap 提供 command line 的方式可以編譯與運行,在此我則採用自己的方式
$ phonegap build
下達此指令後,PhoneGap 會從 hello/www 去建立各平台的必要資源,包含 app 原始碼與 plugin,可以在下面資料夾看到編譯結果
hello/platform/ios/www
hello/platform/android/assets/www


5. 編譯各平台的專案並運行

iOS 的部分,用 Xcode 開啓 hello/platform/ios/HelloWorld.xcodeproj,按下左上角的編譯就可以在模擬器上面運行了。同時間在 console window 也可以看到 deviceready 的字眼


Android 的部分程序比較多,請先參照 Android Platform Guide 設定模擬器並開啓

編譯 android 專案
$ cd platform/android
$ ant debug

列出可用的模擬器
$ adb devices
List of devices attached
emulator-5554   device

安裝到模擬器
$ adb -s emulator-5554 install -r bin/HelloWorld-debug.apk
337 KB/s (1579758 bytes in 4.565s)
        pkg: /data/local/tmp/HelloWorld-debug.apk
Success

2013/06/20

jQuery Mobile: Page 動態載入與切換

jQuery Mobile Page 是在 implement mobile app 很常用到的元件,它可以模擬 iOS navigation controller + view controller 的操作界面,不用寫太多程式碼就可以達到這樣的 UI 呈現,但真正在使用時,常常會遇到動態載入 page 或是同一個 page 要呈現不同 content 的時候,對於我這個初學者而言,也還在摸索怎麼管理這些page。

以下列出幾種動態載入 page 的方式:

Static page

提供兩種切換頁面的方式
In html file
<div data-role="page" id="page1">      
    <div data-role="header">         
        <h1>Page 1</h1>     
    </div>
    <div data-role="content">
        <a href="#page2">Change Page</a>
        <a href="#" onclick="$.mobile.changePage('#page2');">Change Page</a>
    </div>
    <div data-role="footer"> 
        <h4>Page Footer</h4>             
    </div> 
</div>    

<div data-role="page" id="page2">         
    <div data-role="header">    
       <h1>Page 2</h1>     
    </div>
    <div data-role="content">  
        <p>In page 2</p>
    </div>
    <div data-role="footer">   
        <h4>Page Footer</h4>      
    </div>
</div>


Load from html file

先放一個空的 page,再用 ChangePage() 的方式 load 下一個 page,把 page 分開在不同的檔案,code 比較清楚
In html file
<div data-role="page" id="page1">
</div>

In js file
$(function(){ 
    $.mobile.changePage("tpl/page2.html", {
        transition: "pop",
        reverse: false,
        changeHash: false
    });
});


Load html file as template

用 ajax 的方式去 load html 並當成 template,套用 data 後變成 page
index.html
<div data-role="page" id="page2">
 <div data-role="header">
  <h1><%= title %></h1>
 </div>

 <div data-role="content">
  <p><%= content %></a>
 </div>

 <div data-role="footer">
  <h4>Page Footer</h4>
 </div>
</div>

In js file
需要搭配 underscore.js 的 template
$(function(){
    $.get('tpl/page2.html', function(data) {
        var tpl = _.template(data);
        var m = {title: "This is title", content: "In the page 2"};
        var newPage = $(tpl(m));
        newPage.appendTo($.mobile.pageContainer);
        $.mobile.changePage(newPage);
    });
});

但上述的方法有個問題,就是 page 一直用 append 的方式加到 html 裡,對記憶體是個消耗,尚在思考要怎麼管理這些 page...

2013/06/16

jQuery Mobile + PhoneGap 快速打造 App

再次回到 mobile app 的世界。

最近接了一個 case,要做一個跨平台的 news feed,想到的組合就是 jQuery Mobile + PhoneGap,為了讓 code 更乾淨,也加入了 backbone.js 這個 MV* framework,說真的,這樣的組合我還沒開發過任何一支產品,本身是 back-end 起家,frontend 算是玩興趣的,兜一些小玩意還可以,開發大 project 就辛苦些...


用 jQuery mobile 兜 UI 比 native code 快了 n 倍,常用的 page view、table view、navigation bar...都可以在簡單的幾行 html 搞定。呈現 static 資料很容易,如果是 dynamic 資料對我這新手就...
分析需求之後,大概就幾個版型:category list、title list、content display,然後塞進不同的資料(來源可以是 api server 吐回來的 json)


Main menu 打算用 slide panel 來呈現,panel 這物件是要擺在 page 裡面的,那如果每個 page 都需要 panel 該怎做?
javascript - jquery mobile: do I have to create a new panel for every page - Stack Overflow
一份 menu 共用摟,我想到的是把 panel 獨立成一個 template,在 pageshow event 去加載
看到一些蠻炫的 panel


jQM 的 page sample 中,同個 html 嵌了多個 page,這在現實環境也是不合需求的。第一、全部的 page 放在同一頁肯定 code 會過長,第二、page 的內容會是 dynamic 的,page 本身應該只是個樣版
官網有提到動態載入 page 的方式:jQuery Mobile and Dynamic Page Generation
很明顯的沒有 router 與 template 的支援,code 相當冗長,於是就引入了 backbone.js 的 route 與 underscore.js 的 template

由於 jQM 與 backbone.js 都會監聽 hash change event,若要使用後者的 router,請參考


如果閒自己寫 html 太慢,可以使用 jQM UI builder

2013/05/21

解開 fd_set size limitation

寫 socket programming 時會用 select 搭配 fd_set 來偵測 file descriptor 是否可讀寫
但 Linux 系統預設的 fd_set size 只有 1024,若同時間處理的 fd 超過 1024 就會出問題


修改下面這兩個檔案,重新 build application 時就會引用到新的 define 值

/usr/include/bits/typesizes.h:
#define    __FD_SETSIZE        1024

/usr/include/linux/posix_types.h:
#define    __FD_SETSIZE        1024

2013/04/25

初次玩 Backbone.js: 多種 Template 的實作方式

假設我想設計一個公司資料,model 為單一員工資料,包含 id 與 name。collection 為部門資料,由多個員工所組成。而 view 用來顯示部門資料之用。
// Models
company.models.Employee = Backbone.Model.extend({
    defaults: {
        id: undefined,
        name: undefined
    }
});

// Collections
company.collections.Department = Backbone.Collection.extend({
    model: company.models.Employee
});

// Views
company.views.EmployeeList = Backbone.View.extend({
    el: "#container",
 
    render: function() {
        ...
    }
});

// Create base data
var c = new company.collections.Department(
        [{id:1, name: "Star Willard"},
         {id:2, name: "Rhona Eggleston"},
         {id:3, name: "Cassi Chowdhury"},
         {id:4, name: "Leigh Nilson"},
         {id:5, name: "Niesha Auger"}
        ]);

// Create view
var v = new company.views.EmployeeList({collection: c});
v.render();


以下就來探討 render function 該怎麼把 collection 套用到 template 並呈現在 UI 上

2013/04/23

WebSocket on Tornado

Tornado 一直是我愛用的 python web framework,這幾年工作上一直在寫 event-drivent socket programming,所以被它 non-blocking 的特性給深深吸引,如果每件 block 的工作都能用 asynchronous 的方式來解決,那程式執行的效率一定超好!


延續『WebSocket 雙向即時通訊 - 初探』,今天就以 Tornado 來寫個簡單的 WebSocket 範例。當 client 連到 server 後,會傳送 hello ,而 server 回應一樣的訊息,傳送到第五次,server 就把 client 斷掉。

Server (ws_server.py)
import tornado.ioloop
import tornado.web
from tornado import websocket


class WSHandler(websocket.WebSocketHandler):
    count = 0
    def open(self):
        print "Client connected"

    def on_message(self, msg):
        print "[%d] Got message [%s] from client" % (self.count, msg)
        if self.count == 4:
            self.close()
            return
        # Write back message
        self.write_message("[%d] Echo: %s" % (self.count, msg))
        self.count += 1

    def on_close(self):
        print "Client disconnected"


application = tornado.web.Application([
    (r"/", WSHandler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()



Client (ws_client.py)
from tornado.websocket import websocket_connect
from tornado.ioloop import IOLoop


class ws_client():
    conn = None # This is WebSocketClientConnection
    def __init__(self):
        websocket_connect('ws://localhost:8888/', callback=self.conn_cb)
        
    def conn_cb(self, future):
        self.conn = future.result()
        self.conn.write_message("hello")
        self.conn.read_message(self.read_cb)
        
    def read_cb(self, future):
        msg = future.result()
        if msg is None:
            print "Server disconnected"
            IOLoop.instance().stop()
        else:
            print msg
            self.conn.write_message("hello")
            self.conn.read_message(self.read_cb)

if __name__ == '__main__':
    ws_client()
    IOLoop.instance().start()

2013/04/21

人生 就該有限度的冒險

一件事六成把握就去做吧
要相信自己的應變能力
最差的時候 你還有求生存的自我保護機制

一件事不要尋求全部人的認同
如果想迎合全部的人
那肯定會失去初衷 失去原始的自我

追求完美的境界 永無止境
有時候 留一成餘地給別人
反而可以創造更多機會

沒有什麼是絕對的
要說可以做到十成
我想只有你堅定的信心

人生 就該有限度的冒險

2013/04/18

對於今日電視新聞的看法

新聞有毒,勇敢戒斷你會更快樂
                                --- Inside 硬塞的網路趨勢觀察


這半年沒看過幾次電視新聞 但不因而跟社會脫節
網路 書籍 所帶來的更多 不管是 及時性 時事 知識
選擇性也更廣 不只有藍台 綠台

網路新聞雖然也是記者寫的 但有更多評判的機會
很容易可以看到正反兩面

通常新聞報導都是不好的居多 而且越糟糕的的報越久
畢竟 這件事情只是一小部份 社會上還是有很多好的地方
很容易過度恐慌 造成大家對社會的觀感不好

像之前三餐都配人頭案 很倒胃口
每天看這些 心情會好才怪

畫面的呈現蔚為一種趨勢
記者還要充當演員 還原現場演一次
不如看寶傑的關鍵時刻娛樂性更甚
人對於畫面的理解較好
相對 思考 評斷能力也降低了
照單全收 很好洗腦


究竟 新聞的目的在於?
原始概念應該接近
客觀的呈現當下的情況 由收看的人思考而後斷
媒體只是扮演傳遞的角色

furthermore
讓社會進步 而不是圖利政黨財團
監督社會 揚善伐惡 但評斷的人 素質待加強
畢竟 結論是直接深植到大眾

播放的內容該跟大眾利益有關
腥羶色 奇人異事 是新聞 但我相信有更重要的東西可以報
世界觀 整體趨勢 試著把層次拉的更高


2013/04/17

來去基隆走走吧

愛上了平日逛街、平日旅遊的感覺,除了人比較少之外,可以和正在工作的人形成一種對比,心情特別不一樣 :P

今天請假在家休息,下午一個衝動就想去基隆走走,從汐止過去還蠻快的,沿新台五路走20分鐘就到了。基隆的路真不是普通亂的,除了很多單行道,還有一些路彎彎曲曲的,感覺很容易就逆向,尤其在港邊,差點誤闖貨運專用道。

查了一下比較 popular 的景點有
  • 基隆廟口夜市
  • 和平島公園
  • 白米甕砲台
  • 外木山漁港

港邊
 


和平島公園
 


走著走著 沙灘上突然浮現一些文字...


  


發現外星生物與外星地表
 

夕陽餘暉
 


天黑前趕快前往白米甕砲台
原來這邊的炮台早撤了 不過這是個制高點 瞭望港邊還不錯
如果晚上來 港邊燈火應該更漂亮
 

核彈基地?


基隆廟口 奠濟宮
 

來到廟口當然別忘了伴手禮呀
李鵠餅店的綠豆椪
連珍的芋泥球~超好吃

2013/04/13

WebSocket 雙向即時通訊 - 初探

Web 已經走向 Application 的概念,其中即時性(real-time)這個特點扮演很重要的角色

早期 Web service 要做到即時通訊不外乎兩種
  • Polling
    每n秒問一次 server,n 越小即時性越好,但相對 server loading 就越大
  • Long polling
    需要 Server support,延遲 response,確切來說是需要的時候再 response


但這兩種方式都需要額外的 overhead
  • HTTP 協定限制,一個 request 配一個 response,然後結束 connection,每次重新連線都需要 tcp 3-way handshake
  • Request 只能從 client 主動發出,若要做到 server push,client 得先建立一條連線讓 server 需要時 send back
  • 每次連線都要帶上 HTTP header,對頻寬也是一種浪費
  • Connection 斷掉再建立有個空窗期


而 WebSocket 正是改善這些缺點
  • 全雙工通訊(full-duplex communication),連線一旦建立,server/client 隨時都可以發送資料給對方
  • 除了第一次 handshake 外,過程中傳送資料的 header 很小
  • 避免對同一個網站建立多條 connection


WebSocket 的 implementation


WebSocket 對各種瀏覽器版本的支援度


WebSocket Protocol/Packet 分析


其實在 HTTP 1.0 與 1.1 也有 persistent connection 的實作
  • HTTP 1.0 persistent connection:又稱 HTTP keep-alive 或 HTTP connection reuse,可以在同個 connection 下發送多次 request/response 
  • HTTP 1.1 提出了 pipelining:允許一次發送多個 request 給 server,但 server response 時也必需按照順序
但這機制卻沒有被廣泛的應用?是因為早期的 web server 存在 C10K problem 嗎?還是 server 支援度的問題?加上 proxy 與 browser 有限制 client 到 web server 的 current connection 只能建立兩條,避免浪費 server 資源

詳細可以參考 HTTP 連線管理 | ihower { blogging }

2013/04/12

SQL Injection Prevention - Postgresql

這是一個 C 版本的 postgresql database 存取
#include <libpq-fe.h>

#define UPDATE_COMMAND   \
        "UPDATE employee SET password='%s' WHERE username='%s';"

int db_update(char *username, char *password)
{
  PGconn            *conn;
  PGresult          *res;
  ExecStatusType    status;
  char              query[1024];

  // connect to server

  /*
   * Set parameter
   */
  snprintf(query, sizeof(query), UPDATE_COMMAND, password, username);

  /*
   * Execute the query.
   */
  res = PQexec(conn, query);
  if (res) {
    status = PQresultStatus(res);
    if (status == PGRES_COMMAND_OK)) {
      printf("Update successfully\n");
    } else {
      printf("error message=[%s]\n", PQresultErrorMessage(res));
    }
  }
}
初學者容易犯的錯誤就是把 user input 直接跟 SQL query 串接在一起,如果 username, password 存在不安全的字眼,很有可能會造成 SQL injection,切記永遠不要相信 user 的資料,該做的檢查、防呆都不能少。


改成參數形式就可以避免 :)
Database client library 都會有提供類似的用法
#include <libpq-fe.h>

#define UPDATE_COMMAND   \
        "UPDATE employee SET password=$1 WHERE username=$2;"
#define PREPARED_STMT    "my_update"
#define NPARAMS          2

int db_update(char *username, char *password)
{
  PGconn            *conn;
  PGresult          *res;
  ExecStatusType    status;
  char              *params[NPARAMS];

  // connect to server

  /*
   * Set parameter
   */
  params[0] = password;
  params[1] = username;

  res = PQprepare(conn, PREPARED_STMT, UPDATE_COMMAND, NPARAMS, NULL);
  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
    printf("PQprepare() failed [%s]", PQresultErrorMessage(res));
    return -1;
  }

  /*
   * Execute the query.
   */
  res = PQexecPrepared(conn, PREPARED_STMT, NPARAMS, 
                       (const char **)params, NULL, NULL, 0);
  if (res) {
    status = PQresultStatus(res);
    if (status == PGRES_COMMAND_OK)) {
      printf("Update successfully\n");
    } else {
      printf("error message=[%s]\n", PQresultErrorMessage(res));
    }
  }
}
關於 PQprepare()PQexecPrepared() 的使用方式可以參考官方文件

2013/04/11

Basic Authentication for Apache Virtual Host

最近裝了 phpmemcacheadmin 這套 monitor tool 來用,但它本身沒有使用者驗證的機制,雖然是內部使用,但擁有這麼大的權限應該要控管一下。
在不動到 source 的前提,想到了可以在 Apache web server 端加上 basic authentication:


Apache virtual host 設定檔 vhost.conf

<VirtualHost 10.0.0.1:80>
  ServerName example.com
  DocumentRoot /home/user/www
  DirectoryIndex index.php
  <Directory /home/user/www>
    Deny from all
    # Allow from 10.0.2.1 # 允許從這個 IP 來的不用認證
    AuthUserFile ~/.htpasswd
    AuthName authorization
    AuthType Basic
    Satisfy Any
    require valid-user
  </Directory>
</VirtualHost>
重啓 Apache 就生效了


用 htpasswd 建立帳號/密碼設定檔

$ htpasswd ~/.htpasswd brian
New password:
Re-type new password:
Adding password for user brian

關於 htpasswd 的使用方式請參考 htpasswd - Manage user files for basic authentication

2013/04/05

第一次做西餐就上手

今天要請好朋友來家裡一起做西餐,這算是難度最高的一次了

 

幸好有各位的幫忙 最後當然是完美上菜啦


沙拉

生菜佐優格醬
加點柳橙跟檸檬 酸酸的比較開胃

前菜

煎馬鈴薯 兩種做法
可以切片後直接下去煎 口感是酥脆的
另外可以切成條狀 先滾一下變鬆軟 再下去煎 表皮焦焦的很香

海鮮巧達湯

玉米 紅蘿蔔 洋蔥 蘑菇 綠花椰 馬鈴薯 全部切丁下去滾
要滾到馬鈴薯變成泥 湯頭的口感才會濃郁
加一些蛤蠣 蝦子 干貝 也不錯

拿坡里茄汁義大利麵

鹽巴 + 義大利麵煮七分鐘 -> 起鍋拌橄欖油
番茄 洋蔥 切丁 + 蝦 花枝 + 紅酒 炒一下
倒入茄汁義大利麵醬 還有撈起來的麵條 再翻炒一下
最後撒上起司粉 羅勒葉裝飾


煎沙朗牛排、松版豬排

先把牛排血水用紙巾擦乾
大火煎第一面 90 秒鎖住肉汁 翻面上色即可
不過平底鍋似乎火侯不夠 發現要煎久一點 不然裡頭還很生
佐蒜片 岩鹽

蒜片製作:蒜頭切片 -> 川燙去辣味 -> 油炸呈金黃色 -> 用紙巾把油吸掉 -> 烤稍微酥脆
配菜:綠花椰 番薯 紅蘿蔔 燉梨 都不錯

最後當然要來一杯紅酒啦
松版豬排就煎全熟 肉質真的帶勁 撒上黑胡椒 海鹽 就很好吃


mojito

方糖 1 顆 + 薄荷葉 10片 + 檸檬汁 用搗棒搗碎
碎冰 +  1/4 片檸檬 + Rum 45oz + soda 少許
最上面薄荷枝葉裝飾

2013/04/03

成大事必備9種能力、9種心態、9種手段

轉載自網路,收納到我的做人做事小語裡面

成大事必備的九種能力 – 挑戰生存的能力:善於在現實中尋找答案

1、擺正心態,敢於面對現實

對於那些不停地抱怨現實惡劣的人來說,不能稱心如意的現實,就如同生活的牢籠,既束縛手腳,又束縛身心,因此常屈從於現實的壓力,成為懦弱者;而那些真正成大事的人,則敢於挑戰現實,在現實中磨煉自己的生存能力,這就叫強者!

在此,我們可以得出一條成大事的經驗:適應現實的變化而迅速改變自己的觀念,最重要的是需要我們有一副聰慧的頭腦和靈活的眼睛,做生活的有心人。

在現實的壓力之下,如果你能改變觀念,適時而進,可收到事半功倍的效果。

我們的自下而上須臾離不開現實,隨著現實的變化,我們必須隨之調整自己的觀念、思想、行動及目標。這是生存的必須。

如果我們有辦法來改變現實,使之適合我們能力和欲望的發展需要,則是最難能可貴的。


2、讓你擁有過硬的自制能力

自制,就是要克服欲望,不要因為有點壓力就心裏浮躁,遇到一點不稱心的事就大發脾氣。

一個人除非先控制了自己,否則將無法控制別人。

一個人只要有成大事的目標,知道自己想要的,然後采取行動,告訴自己絕對不要放棄,成功只是時間早晚而已。

假使你在途中遇上了麻煩或阻礙,你就去面對它、解決它、然後再繼續前進,這樣問題才不會愈積愈多。

你在一步步向上爬時,千萬別對自己說“不”,因為“不”也許導致你決心的動搖,放棄你的目標,從而前功盡棄。

人最難戰勝的是自己,這話的含義是說,一個人成功的最大障礙不是來自於外界是,而是自身。只有控制住自己,才能控制住壓力,讓壓力在你面前屈服。


3、把情感裝入理性之盒

一種抵觸情緒的產生往往是潛移默化的,但它對人一生的影響卻是巨大的,這種影響從諸多小事上體現出來。我們應盡量消除自己的不良情緒、因為它不僅會給我們造成身心上的傷害,而且在我們通往成功的路途上,不良情緒有時會成為絆腳石。

為了你的成功,你必須把情感裝入理性之盒,你必須去適應別人,適應形勢,不然的話,你註定成不了大事,註定會被淘汰。


4、獨處可以激發思考的力量

如果你知道怎麼獨處的話,成大事者都是善於獨處的人--在獨處的過程中激發思考的力量。

自卑可以像一座大山把人壓倒並讓你永遠沈默,也可以像推進器產生強大的動力。

比別人先走一步,能創造一種成功的心境。

在獨處時,你應當有所思考,不要總人浮於事。


5、壓力是最好的推動力

欲成大事者,因目標高遠,壓力可能會更大。但若欲成大事,就必須能承受這種壓力,把壓力當成推進人生的動力。

人們最出色的工作往往是在外於逆境的情況下做出的。人要有所為就要有所不為。應做的一定要做好,不該做的堅決不做。

得到的並不一定就值得慶幸,失去的也並不完全是壞事情。


6、以變應變,才有出路

順應時勢,善於變化,及時調整自己的行動方案,這是成大事者適應現實的一種方法。

一個人如果沒有和人打交道的高超技巧,沒有把各種情況都考慮周全的頭腦,靈活應變的手段,就根本無法駕馭大的局面,將很難成大事。

一個人能看清自己的現狀,心態就會平衡許多,就能以一種客觀的眼光去看待,認識這個世界,並且相應地調整自己的行為。


7、自信心是人生的堅強支柱

自信心充足者的適應能力就高,反之則適應能力較低。

一般信心不足較嚴重的人常有一些身心癥狀,比如孤僻,害怕與人交往,說話過於偏激,悲觀失望。

如果做事成功的經驗越多,那麼自信心就越強。

自我成功鍛煉的機會越少,自信心就越弱,以致產生嚴重的自卑情緒。

十九世紀的思想家愛默生說:“相信自己‘能’,便會攻無不克。”拿破侖說:“在我的字典裏沒有不可能。”


8、把精力投入到自己的強項上

大多數人的生活層次只停留在:為吃飯而吃、為搭公車而搭、為工作而工作、為了回家而回家。

成大事者與不成大事者只差別在一些小小的動作:每天花5分鐘閱讀、多打一個電話、多努力一點、在適當時機的一個表示、表演上多費一點心思、多做一些研究,或在實驗室中多試驗一次。

在行動之前你自己就知道你是否足以勝任這一個任務。

沒有任何藉口可以解釋你為什麼會長時間仍然無法勝任一項工作。

不論你想追求的是什麼,你必須強迫自己增強能力以實現目標。

勤加練習、勤加練習、最後還是勤加練習!決不放棄學習,而且一定要將學到的知識運用於日常生活中。


9、要專心地做好一件事

如果大多數人集中精力專註於一項工作,他們都能把這項工作做得很好。

最成大事者的商人是能夠迅速而果斷作出決定的人,他們總是首先確定一個明確的目標,並集中精力,專心致誌地朝這個目標努力。

一次只專心地做一件事,全身心地投入並積極地希望它成功,這樣你的心裏就不會感到筋疲力盡。

把你需要做的事想象成是一大排抽屜中的一個小抽屜。不要總想著所有的抽屜,而要將精力集中於你已經打開的那個抽屜。每個人做人辦事的手段都是不一樣的,可以講,一個人就有一種手段,一個人就有一種靠自己手段獲得成功的途徑。無數事實表明,有些人就是太過於自信,想念自己確認的手段能夠解決任何問題,但不知道這種往往是起不到任何作用。因此,他們總覺得離成功的目標不是越來越近,而實際上越來越遠。





成大事必備的九種心態 + 六要素

心態之一:積極向上
  1. 時刻想著出人頭地
  2. 做“小人物”時要向“大人物”看齊
  3. 惟有進取心,才能成大事
  4. 摒棄逆境的干擾,尋找向上的根源
  5. 放棄也是一種成功的開始
  6. 在平凡中做不平凡的事
  7. 保持年輕的心態很重要

心態之二:勤勉謙恭
  1. 壯志淩雲地想,腳踏實地地幹  
  2. 勤敬產業,謙恭做人
  3. 勤勉高於天賦
  4. 勤奮造就成功,懶惰摧毀天才
  5. 養成勤奮的習慣會終生受益
  6. 有一份耕耘,就有一份收穫
  7. 恒心與支持能“點石成金”
  8. 莫道君行早,更有早行人

心態之三:誠實守信
  1. 誠實是一種源自自身的本質
  2. 誠實守信才是大贏家
  3. 以誠信奠定成功基業
  4. 真誠的友誼會使你的事業更發達
  5. 做人要有正直的品行
  6. 誠實守信是成大事的“信用卡”
  7. 要成大事,擇友不可草率
  8. 以真誠待人,用熱忱做事

心態之四:敢於挑戰
  1. 敢於挑戰自我,克服貶低心理
  2. 挑戰無極限
  3. 堅持到底造靠勇氣,半途而廢是懦夫
  4. 用於挑戰激起成大事的信心
  5. 勇氣是戰勝困難的良方
  6. 勝人者力,自勝者強
  7. 毅力與恒心是成大事的基本功
  8. 堅持不懈成大事,淺嘗輒止無出路

心態之五:善於合作
心態之六:知足平衡
心態之七:樂觀豁達
心態之八:寬厚容人
心態之九:永遠自信


一:沉穩
(1)不要隨便顯露你的情緒。
(2)不要逢人就訴說你的困難和遭遇。
(3)在徵詢別人的意見之前,自己先思考,但不要先講。
(4)不要一有機會就嘮叨你的不滿。
(5)重要的決定儘量有別人商量,最好隔一天再發佈。
(6)講話不要有任何的慌張,走路也是。

二:細心
(1)對身邊發生的事情,常思考它們的因果關係。
(2)對做不到位的執行問題,要發掘它們的根本癥結。
(3)對習以為常的做事方法,要有改進或優化的建議。
(4)做什麼事情都要養成有條不紊和井然有序的習慣。
(5)經常去找幾個別人看不出來的毛病或弊端。
(6)自己要隨時隨地對有所不足的地方補位。

三:膽識
(1)不要常用缺乏自信的詞句
(2)不要常常反悔,輕易推翻已經決定的事。
(3)在眾人爭執不休時,不要沒有主見。
(4)整體氛圍低落時,你要樂觀、陽光。
(5)做任何事情都要用心,因為有人在看著你。
(6)事情不順的時候,歇口氣,重新尋找突破口,就結束也要乾淨俐落。

四:大度
(1)不要刻意把有可能是夥伴的人變成對手。
(2)對別人的小過失、小錯誤不要斤斤計較。
(3)在金錢上要大方,學習三施(財施、法施、無畏施)
(4)不要有權力的傲慢和知識的偏見。
(5)任何成果和成就都應和別人分享。
(6)必須有人犧牲或奉獻的時候,自己走在前面。

五:誠信
(1)做不到的事情不要說,說了就努力做到。
(2)虛的口號或標語不要常掛嘴上。
(3)針對客戶提出的“不誠信"問題,拿出改善的方法。
(4)停止一切“不道德"的手段。
(5)耍弄小聰明,要不得!
(6)計算一下產品或服務的誠信代價,那就是品牌成本。

六:擔當
(1)檢討任何過失的時候,先從自身或自己人開始反省。
(2)事項結束後,先審查過錯,再列述功勞。
(3)認錯從上級開始,表功從下級啟動
(4)著手一個計畫,先將權責界定清楚,而且分配得當。
(5)對“怕事"的人或組織要挑明瞭說。
(6)因為勇於承擔責任所造成的損失,公司應該承擔





成大事的九種手段:

1、敢於決斷--克服猶豫不定的習性
很多人之所以一事無成,最大的毛病就是缺乏敢於決斷的手段,總是左顧右盼、思前想後,從而錯失成功的最佳時機。成大事者在看到事情的成功可能性到來時,敢於做出重大決斷,因此取得先機。

2、挑戰弱點--徹底改變自己的缺陷
人人都有弱點,不能成大事者總是固守自己的弱點,一生都不會發生重大轉變;能成大事者總是善於從自己的弱點上開刀,去把自己變成一個能力超強的人。一個連自己的缺陷都不能糾正的人,只能是失敗者!

3、突破困境--從失敗中撮成功的資本
人生總要面臨各種困境的挑戰,甚至可以說困境就是“鬼門關”。一般人會在困境面前渾身發抖,而成大事者則能把困境變為成功的有力跳板。

4、抓住機遇--善於選擇、善於創造
機遇就是人生最大的財富。有些人浪費機遇輕而易舉,所以一個個有巨大潛力的機遇都悄然溜跑,成大事都是絕對不允許溜走,並且能縱身撲向機遇。

5、發揮強項--做自己最擅長的事情
一個能力極弱的人肯定難以打開人生局面,他必定是人生舞臺上重量級選手的犧牲品;成大事者關於在自己要做的事情上,充分施展才智,一步一步地拓寬成功之路。

6、調整心態--切忌讓情緒傷害自己
心態消極的人,無論如何都挑不起生活和重擔,因為他們無法直面一個個人生挫折,成大事者則關注於高速心態,即使在毫無希望時,也能看到一線成功的亮光。

7、立即行動--只說不做,徒勞無益
一次行動勝過百遍心想。有些人是“語言的巨人,行動的矮子”,所以看不到更為實際現實的事情在他身上發生;成大事者是每天都靠行動來落實自己的人生計畫的。

8、善於交往--巧妙利用人力資源
一個人不懂得交往,必然會推動人際關係的力量。成大事者的特點之一是:善於靠借力、借熱去營造成功的局勢,從而能把一件件難以辦成的事辦成,實現自己人生的規劃。

9、重新規劃--站到更高的起點上
人生是一個過程,成功也是一個過程。你如果滿足于小成功,就會推動大成功。成大事者懂得從小到大的艱辛過程,所以在實現了一個個小成功之後,能繼續拆開下一個人生的“密封袋”。

成大事者總是選擇最佳的手段,達到最完善的結果,這就是非一般人所能做到的。因此在成功之路上,你要想成大事,首先要解決的問題就是:你的手段對你推動成功的計畫是否立竿見影!

2013/04/02

一位年輕女董事長的47個忠告!

轉載自網路,收納到我的做人做事小語裡面

無論你是男人,還是女人,做人想成功,下面就是你必須要參考的

1、好朋友裡面,一定要培養出一個知己,不要以為你有多麼八面玲
瓏,到處是朋友,最後真心對你的,只有一個,相信我。

2、給自己定目標,一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運。破罐子破摔只能和懦弱做朋友。

3、朋友請你吃飯,不要覺得理所當然,請禮尚往來,否則你的名聲會越來越差。

4、這是個現實的社會,感情不能當飯吃,貧窮夫妻百事哀。不要相信電影裡的故事情節,那只是個供許多陌生人喧囂情感的場所。只有不理智和不現實的人才相信。

5、不要相信算卦星座命理,那是哄小朋友的,命運掌握在自己手中。坐在家裡等什麼房子,車子,還不如睡一覺做個好夢。

6、不喜歡的人少接觸,但別在背後說壞話,說是非之人,必定是是非之人,謹記,禍從口出。

7、少玩遊戲,這不是韓國,你打不出房子車子還有資本。可以有愛好,但要把握尺度,少玩農場、牧場、鬥地主等一些高度吸引人思想的晉級遊戲,也許你的級別很高,但不代表你有多麼成功,反而會影響和占據你成功的時間。

8、是人都有惰性,這是與生俱來的,但是我們後天可以改變這種惰性,因為有很多人正在改變。對於某種事物或是生意不要等別人做到了,我才想到。不要等別人已經賺到錢了,我才想去做。沒有人相信的是市場和機遇,大家都相信的叫做膨脹。

9、知道自己要幹什麼,夜深人靜,問問自己,將來的打算,並朝著那個方向去實現。而不是無所事事和做一些無謂的事。

10、出路出路,走出去了,總是會有路的。困難苦難,困在家裡就是難。

11、作為女人,不要倚老賣老,認為事業跟自己沒關係,以為自己就是洗衣服,做飯,看孩子,那就是大錯特錯。

12、做人,要做到;萬事孝為先,教童品之道,夫妻和諧美,幸福萬年長。但是這些不是拿來用嘴說說就能辦到的,解放初期年代要做到這些,需要付出很大的努力和辛苦,當今現實的社會需要你付出很大的金錢,聰明的人都知道這個道理。

13、空閒時間不要經常上網做無聊的事和玩一些沒有意義的遊戲,讀點文學作品,學習一些經營流程,管理規範,國際時事,法律常識。這能保證你在任何聚會都有談資。

14、寧可錯殺一千次來自各方面的信息,也不放過任何一個有可能成功的機會。只有這樣你才不會去買後悔藥。

15、要做一件事,成功之前,沒有必要告訴其他人。成功之後不用你說,其他人都會知道的。這就是信息時代所帶來的效應。

16、頭髮,指甲,鬍子,打理好。社會是個排斥性的接受體,這個星球所需要的藝術家極其有限,請不要冒這個險,就算你留長頭髮比較好看,也要盡量給人乾淨的感覺。

17、不要以為你是個男人,就不需要保養。至少飲食方面不能太隨便,多吃番茄,海產品,韭菜,香蕉,都是對男性健康有益處的食物。你要是看不到價值,我可以告訴你。至少你能把看病節約下來的錢給你的女人多買幾個化妝品。

18、力求上進的人,不要總想著靠誰誰,人都是自私的,自己才是最靠得住的人。

19、面對失敗,不要太計較,天將降大任於斯人也,必先苦其心志,勞其筋骨,餓起體膚……但要學會自責,找到原因,且改掉壞習慣。二十歲沒錢,那很正常;三十歲沒錢,可能是沒有好的家境,需要更大的努力;四十歲沒錢,只能自己找原因。窮人變成富人是可能的,而且很可能。窮人能窮一輩子,也是必然的,存在就是理由,只是有所選擇。

20、每個人都有成功的機會!就看你給不給自己機會!

21、記住,平均每天看電視超過三個小時以上的,一定都是那些月收入不超過五萬元的,如果你想要月收入超過五萬,請不要把時間浪費在電視上。同樣的道理,那些平均每天玩網路遊戲或聊天超過三個小時以上的,也都是那些月收入不超過五萬的。

22、因為窮人很多,並且窮人沒有錢,所以,他們才會在網路上聊天抱怨,消磨時間。你有見過哪個企業老總或主管經理有事沒事經常在臉書裡閒聊的?

23、這個世界,有這麼一小撮的人,打開報紙,是他們的消息,打開電視,是他們的消息,街頭巷尾,議論的是他們的消息,仿佛世界是為他們準備的,他們能夠呼風喚雨,無所不能。你的目標,應該是努力成為這一小撮人。

24、如果,你真的愛你的爸媽,愛你的女朋友,就好好的去奮鬥,去拼搏吧,這樣,你才有能力,有經濟條件,有自由時間,去陪他們,去好好愛他們。

25、這個社會,是快魚吃慢魚,而不是慢魚吃快魚。

26、這個社會,是贏家通吃,輸者一無所有,社會,永遠都是只以成敗論英雄。

27、如果你問周圍朋友,如果十個人,九個人說不知道,那麼,這是一個機遇,如果十個人,九個人都知道了,就是一個行業。

28、任何一個行業,一個市場,都是先來的有肉吃,後來的湯都沒的喝。

29、這個世界上,一流的人才,可以把三流項目做成二流或更好,但是,三流人才,會把一流項目,做的還不如三流。

30、趁著年輕,多出去走走看看。讀萬卷書,不如行萬里路,行萬里路,不如閱人無數。

31、與人交往的時候,多聽少說。這就是,上帝為什麼給我們一個嘴巴兩個耳朵的原因。

32、記得,要做最後出牌的人,出讓別人覺得出其不意的牌,在他們以為你要輸掉的時候,這樣,你才能贏得牌局。

33、不要裝大,對於裝大的人,最好的辦法就是,撿塊磚頭,悄悄跟上去,一下子從背後放倒他。

34、不要隨便說髒話,這會讓別人覺得你沒涵養,不大願意和你交往。即使交往,也是敷衍。因為他內心認定你素質很差。

35、想要抽煙的時候,先問下周圍的人可不可以,要學會尊重別人。少在女生面前耍酷抽煙,你不知道,其實她們內心很反感。

36、買衣服的時候,要自己去挑,不要讓家人給你買,雖然你第一、第二次買的都不怎麼樣,可是,你會慢慢有眼光的。

37、要想進步,就只有吸取教訓,成功的經驗都是歪曲的,成功了,想怎麼說都可以,失敗者沒有發言權,可是,你可以通過他的事例反思,總結。教訓,不僅要從自己身上吸取,還要從別人身上吸取。

38、學習,學習,再學習,有事沒事,去書店看看書,關於管理,金融,行銷,人際交往,未來趨勢等這些,你能獲得很多。這個社會競爭太激烈了,你不學習,就會被淘汰。中國2008底,有一百多萬大學生找不到工作。競爭這麼激烈,所以,一定要認識一點,大學畢業了,不是學習結束了,而是學習剛剛開始。還有,我個人推薦一個很好的視頻節目,《誰來一起午餐》。

39、如果你不是歌手,不是畫家,也不是玩行為藝術的,那麼,請在平時注意你的衣著。現在這個社會,衣著能表現出你屬於哪一個群體,哪一個圈子。

40、 一個年輕人,如果三年的時間裡,沒有任何想法,他這一生,就基本這個樣子,沒有多大改變了。

41、 成功者就是膽識加魄力,曾經在火車上聽人談起過溫州人的成功,說了這麼三個字,“膽子大”。這其實,就是膽識,而拿得起,放得下,就是魄力。

42、無論你以後是不是從事銷售部門,都看一下關於行銷的書籍。因為,生活中,你處處都是在向別人推銷展示你自己。

43、平時的時候,多和你的朋友溝通交流一下,不要等到需要朋友的時候,才想到要和他們聯繫,到了社會,你才會知道,能夠認識一個真正的朋友,有多難?

44、如果你想知道自己將來的年收入如何。找你最經常來往的六個朋友,把他們的年收入加起來,除以六,就差不多是你的了。這個例子,可以充分的說明一點,物以類聚。

45、給自己定一個五年的目標,然後,把它分解成一年一年,半年半年的,三個月的,一個月的。這樣,你才能找到自己的目標和方向。

46、無論什麼時候,記住尊嚴這兩個字,做人是要有尊嚴,有原則,有底線的。否則,沒有人會尊重你。

47、如果我只能送你一句忠告,那就是,這個世界上沒有免費的午餐,永遠不要走捷徑!


2013/04/01

AWS Auto Scaling 自動擴展(二)

延續上篇:AWS Auto Scaling 自動擴展(一),auto scaling 除了可以根據 EC2 instance 狀態,或是 ELB 的健康狀況做擴展,還可以搭配 CloudWatch 使用,CloudWatch 可以 monitor 的狀態有更多了,CPU、disk I/O、network I/O。

Scale up

Create auto scaling policy
$ aws autoscaling put-scaling-policy \
--policy-name as-policy-scale-up \
--auto-scaling-group-name as-group \
--adjustment-type ChangeInCapacity \
--scaling-adjustment 1 \
--cooldown 300

{
    "ResponseMetadata": {
        "RequestId": "4411e437-9b6a-11e2-933c-010eb2f029e6"
    },
    "PolicyARN": "arn:aws:autoscaling:us-east-1:332100208493:scalingPolicy:c534dcbe-91c1-4714-907a-b4974bac7c57:autoScalingGroupName/as-group:policyName/as-policy-scale-up"
}
把 PolicyARN 記下來,下一步會用到

Create cloud watch to monitor the CPU utilization
When the average CPU usage more than 60% and keep 600 seconds, then scale up
$ aws cloudwatch put-metric-alarm \
--evaluation-periods 1 \
--namespace "AWS/EC2" \
--comparison-operator GreaterThanThreshold \
--alarm-name alarm-high-cpu \
--statistic Average \
--threshold 60 \
--period 600 \
--metric-name CPUUtilization \
--alarm-actions arn:aws:autoscaling:us-east-1:332100208493:scalingPolicy:c34f62a8-bb82-4430-9390-67468a7a65f9:autoScalingGroupName/as-group:policyName/as-policy-scale-up


可以做個實驗,用 shell script 寫個 while loop 把 CPU 拉高,果然 10 分鐘後 alarm 就發生了,也會順便執行 scale-up 的 action


Scale down

Create auto scaling policy
$ aws autoscaling put-scaling-policy \
--policy-name as-policy-scale-down \
--auto-scaling-group-name as-group \
--adjustment-type ChangeInCapacity \
--scaling-adjustment -1 \
--cooldown 300
{
    "ResponseMetadata": {
        "RequestId": "c58093f7-9b6b-11e2-82fc-2bb2a883e37c"
    },
    "PolicyARN": "arn:aws:autoscaling:us-east-1:332100238493:scalingPolicy:141d692b-9ae8-4ef8-8d98-7de605c3fe04:autoScalingGroupName/as-group:policyName/as-policy-scale-down"
}

Create cloud watch to monitor the CPU utilization
When the average CPU usage less than 40% and keep 600 seconds, then scale down
$ aws cloudwatch put-metric-alarm \
--evaluation-periods 1 \
--namespace "AWS/EC2" \
--comparison-operator LessThanThreshold \
--alarm-name alarm-low-cpu \
--statistic Average \
--threshold 40 \
--period 600 \
--metric-name CPUUtilization \
--alarm-actions arn:aws:autoscaling:us-east-1:332100238493:scalingPolicy:141d692b-9ae8-4ef8-8d98-7de605c3fe04:autoScalingGroupName/as-group:policyName/as-policy-scale-down


有一些疑問
Scale-up 會增加到多少台?Scale-down 會減至多少台?
CloudWatch 不會重複 trigger,除非狀態從 alarm 回到 normal。


參考資料
Llovizna: Auto Scaling With Amazon EC2

2013/03/31

AWS Auto Scaling 自動擴展(一)

AWS Auto Scaling 是用來處理 application 擴充性問題,根據當下的忙碌狀況來增減 instance。需要搭配 ELB 或是 CloudWatch 使用。

ELB (Elastic Load Balance) 的原理類似 DNS round-robin,在同一個 domain name 上綁定多組 instance IP,讓外部的 request 可以分散到各 instance 去處理。ELB 也會定期對底下的 instance 做 healthy check,若發現 instance 有問題,則 dispatch 時就會掠過這台,而 Auto Scaling 也會根據這個結果去 launch 新的 instance 並掛載 ELB 底下。ELB 下的 instance 是沒有上限值的。




Setup Auto Scaling

Auto Scaling 目前尚未提供 web 界面,只能用 command line 的方式去設定,在開始之前,請確定已經透過 web 設定好:
  • Create Image for a instance (ImageID: ami-7061fb19) 
  • Create ELB (with/without instance) (Load Balance Name: webserver)

Create auto scaling configuration
$ aws autoscaling create-launch-configuration \
--launch-configuration-name as-config \
--image-id ami-7061fb19 --instance-type t1.micro

Show the auto scaling configuration
$ aws autoscaling describe-launch-configurations

Create auto scaling group
$ aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name as-group \
--launch-configuration-name as-config \
--availability-zones us-east-1a \
--load-balancer-names webserver \
--max-size 3 --min-size 2 \
--default-cooldown 300
這個指令一執行,auto scaling 就被啟動了。

為了避免 instance 重複被 launch,有個時間參數設定很重要:
  • --default-cooldown (integer)
    The amount of time, in seconds, after a scaling activity completes before any further trigger-related scaling activities can start.
這個時間至少要大於服務啓動的時間
服務啓動時間 = EC2 開機時間 + Web Service 啓動時間 (+ ELB check health 的時間)

Show the auto scaling group
$ aws autoscaling describe-auto-scaling-groups

照上面的設定最少會有 2 台 instance 在 list 上
            "Instances": [
                {
                    "InstanceId": "i-e0a77c8c",
                    "AvailabilityZone": "us-east-1a",
                    "HealthStatus": "Healthy",
                    "LifecycleState": "Pending",
                    "LaunchConfigurationName": "as-config"
                },
                {
                    "InstanceId": "i-e2a77c8e",
                    "AvailabilityZone": "us-east-1a",
                    "HealthStatus": "Healthy",
                    "LifecycleState": "Pending",
                    "LaunchConfigurationName": "as-config"
                }
            ],

Verify
可以試著把任一台 instance stop,auto scaling 機制偵測到後又會 launch 一台新的,並且掛到 ELB 底下。




Monitor ELB healthy

Create auto scaling group 時,預設是對每個 instance 做 healthy check,若要改為 check ELB,則要加上兩個參數:
  • --health-check-type ELB
  • --health-check-grace-period 60
$ aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name as-group \
--launch-configuration-name as-config \
--availability-zones us-east-1a \
--load-balancer-names webserver \
--max-size 3 --min-size 2 \
--health-check-type ELB --health-check-grace-period 300

Verify
可以試著讓 ELB 的狀態變成 unhealthy,在此我的 ELB 狀態是去 check 各 instance 的 web service,所以我把全部的 instance web service都停止,果真會掛 instance 上來。

但我對於這邊的行為還沒完全掌握,當沒有一台 instance 能夠服務時,那些不能服務的 instance 從 ELB list 中移除並 terminate,auto scaling 會 detect 到,並且循序 launch 一台新的 instance,直到 ELB 正常為止,但如果 service 是因為太忙碌不是掛掉,應該要加更多的 instance 上去而不是移除。



Stop Auto Scaling

Update group setting
$ aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name as-group \
--min-size 0 --max-size 0

如果不更新就直接刪除,會有 error message: You cannot delete an AutoScalingGroup while there are instances or pending Spot instance request(s) still in the group.

Detete auto scaling group
$ aws autoscaling delete-auto-scaling-group --auto-scaling-group-name as-group

要注意一點,刪除 auto scaling group 後,所有的 instance 都會被 terminate!



參考資料

2013/03/30

使用 Command Line Tool 建立 AWS EC2 Instance

AWS 以已經有提供 web 界面可以操作了,為何還要使用 command line 呢?答案是為了自動化的過程。Auto scaling 就是一個很好的例子。


Install AWS Command Line Interface

It run in Python environment, and installed by pip.
$ pip install awscli


Setup credential and region

Method 1
$ vim ~/.aws.conf
aws_access_key_id=AKIAIJQ7YGMRQTBIH7HJ
aws_secret_access_key=ngbsB02udwOmDztTesTJuuZ8ZdkA2ZRq0VHvunX
region=us-east-1
$ export AWS_CONFIG_FILE=~/.aws.conf

Method 2
$ export AWS_ACCESS_KEY_ID=AKIAIJQ7YGMRQTBIH7HJ
$ export AWS_SECRET_ACCESS_KEY=ngbsB02udwOmDztTesTJuuZ8ZdkA2ZRq0VHvunX
$ export AWS_DEFAULT_REGION=us-east-1

若沒有設定好,則會出現下面的 error
Unable to locate credentials
You must specify a region or set the AWS_DEFAULT_REGION environment variable.


Create Instance

$ aws ec2 run-instances --image-id ami-002bf169 --min-count 1 --max-count 1 \
--instance-type m1.small --placement '{"availability_zone":"us-east-1a"}'
{
    "OwnerId": "132130202433",
    "ReservationId": "r-ec8f2587",
    "requestId": "05125c46-dfbd-4ef4-89a8-0efe6f59ba87",
    "Groups": [
        {
            "GroupName": "default",
            "GroupId": "sg-2337df4f"
        }
    ],
    "Instances": [
        {
            "Monitoring": {
                "State": "disabled"
            },
            "PublicDnsName": "",
            "KernelId": "aki-825ea7eb",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "EbsOptimized": false,
            "LaunchTime": "2013-03-30T02:58:42.000Z",
            "ProductCodes": [],
            "StateTransitionReason": "",
            "InstanceId": "i-ff16069f",
            "ImageId": "ami-002bf169",
            "PrivateDnsName": "",
            "SecurityGroups": [
                {
                    "GroupName": "default",
                    "GroupId": "sg-2437df4f"
                }
            ],
            "ClientToken": "",
            "InstanceType": "m1.small",
            "NetworkInterfaces": [],
            "Placement": {
                "Tenancy": "default",
                "GroupName": "",
                "AvailabilityZone": "us-east-1a"
            },
            "Hypervisor": "xen",
            "BlockDeviceMappings": [],
            "Architecture": "x86_64",
            "StateReason": {
                "Message": "pending",
                "Code": "pending"
            },
            "VirtualizationType": "paravirtual",
            "RootDeviceType": "instance-store",
            "AmiLaunchIndex": 0
        }
    ]
}

image-id 就是 AMI 的 id,它可以是 My AMI 也可以是 Community AMI


列出目前所有的 instance
$ aws ec2 describe-instances


關於 ec2 的操作,更詳細的可以看
$ aws ec2 help
$ aws ec2 run-instances help


Reference

2013/03/27

memcached 常用指令

Telnet command

> set foo 0 60 3
bar
STORED


> get foo
VALUE foo 0 3
bar
END
add, replace 與 set 的用法一樣,只是 add 遇到 key 已經存在則 return error,replace 遇到 key 不存在則 return error。


> delete foo
DELETED


> flush_all
OK


> stats
STAT pid 30845
STAT uptime 427550
STAT time 1363069077
STAT version 1.4.6
STAT libevent 2.0.7-rc
STAT pointer_size 64
STAT rusage_user 0.068989
STAT rusage_system 0.086986
STAT curr_connections 5
STAT total_connections 506
STAT connection_structures 7
STAT cmd_get 10
STAT cmd_set 19
STAT cmd_flush 1
STAT get_hits 8
STAT get_misses 2
STAT delete_misses 1
STAT delete_hits 1
STAT incr_misses 0
STAT incr_hits 0


> stats slabs
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 9442
STAT 1:free_chunks 490
STAT 1:free_chunks_end 990
STAT 1:mem_requested 875108
STAT 1:get_hits 5987916
STAT 1:cmd_set 182569
STAT 1:delete_hits 16
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 0
STAT 1:cas_badval 0
STAT 2:chunk_size 120
STAT 2:chunks_per_page 8738
STAT 2:total_pages 2


> stats cachedump 1 1000
ITEM test1 [133 b; 1352958262 s]
ITEM test2 [10 b; 1352958262 s]
ITEM test3 [10 b; 1352958262 s]
ITEM test4 [15 b; 1352958262 s]
ITEM test5 [11 b; 1352958262 s]



內建的 tool

Show states
$ memstat --servers=localhost
         pid: 7848
         uptime: 11912375
         time: 1364870637
         version: 1.4.6
         libevent: 2.0.7-rc
         pointer_size: 64
         rusage_user: 1193.212604
         rusage_system: 4398.974254
         curr_connections: 184
         total_connections: 930825
         connection_structures: 249
         cmd_get: 168874575
         cmd_set: 6459571
         cmd_flush: 0
         get_hits: 158956302
         get_misses: 9918273
         delete_misses: 1
         delete_hits: 401
         ...

Dump all keys
$ memdump --servers='localhost'
KEY1
KEY2
...

Cat a set of key values
$ memcat --servers='localhost' TEST --verbose
key: TEST
flags: 0
length: 3
value: 123

How to dump memcache key/value pairs fast - dump the key values in parallel mode


Copy a set of files to a memcached.
The key names will be the names of the files, without any directory path.
$ ls
test.1   test.2   test.3
$ memcp --servers='localhost' test.*
$ memdump --servers='localhost'
test.1
test.2
test.3

2013/03/26

談 Coding Style 與 Naming Convention

工作三年,回頭再來看看一些寫程式的基本 guideline,深深覺得小時候沒學好...

一個程式的週期不只有 key in 程式碼而已,包含了requirement、design、implementation、testing、maintenance。有一些好習慣從平常就要養成,習慣不好,程式寫得再快都沒有用,日後有可能在 maintenance 時就賠上了大半時間。

為了讓自己可以安穩的睡一覺,還是趁早把基礎打好吧。在網路上已經有很多現成的 rule 可以依循,不需要自己發明,除非用了以後發現有更適合自己的地方。



Coding Style

有句話是這麼說的:任何人都可以寫得出電腦看得懂的程式,但要讓『人』看得懂,不是一件容易的事情!
Run 比較久公司,可能內部自己就有一套 coding style,也可以在 google 搜尋一些 keyword: coding style, coding standard, programing guideline

自己就看得順眼的先找一套來使用吧,我自己寫 C 語言比較多,follow 的 style 比較偏向 K&R。

比較強的 IDE 都有內建排版,像是 Eclipse 預設就有 K&R、BSD、GNU...等方式,也可以根據樣板再去做修改,透過軟體排版會快很多。



Naming Convention (Naming Rule)

好的命名法對於程式可讀性是會大大加分的,其範疇包含了程式內部變數、檔案名稱、外部參數,其實命名法也沒有一個制式規定,但有一些約定成俗的法則。
最常聽到的應該是『匈牙利命名法』,有很清楚的規範,但如果完全照著走就會發現變數變得很冗長...
另外還有『駝峰式命名法』也是常見的


根據不同的語言、平台,都有自己的一套命名法,這些『約定成俗』的名稱,我還沒辦法整理出可以遵循的 rule,真的得靠臨摹別人的程式來習得,多看一些 open source project 吧。



Documentation

Programer 好像都蠻討厭寫文件的,但很抱歉,你可能需要開 API 給別人,日後需要轉交給同事,或是自己因為時間久了也會忘記,所以寫文件真的蠻必要的。
Software design document (SDD) 算是我有認為比較常用的一種,裡面包含了 data design、architecture design、interface design、procedural design。但真正常用的還是只有 data structure 與 API,這時候就要介紹一下 doxygen,也就是把文件跟 code 結合在一起,方便維護。按照 doxygen 的格式去寫註解,最後可以產生 html 或 pdf 的文件。
c - Tools to get a pictorial function call graph of code - Stack Overflow
另外,在這篇有提到蠻多工具可以把 function call 畫成圖片,也就是流程圖,這對於 trace code 有些幫助!但 function call 應該是在 design 階段就劃分好,否則輸出的流程太雜亂幫助也不大。



小結

Vgod曾說過:好的程式設計師跟普通的程式設計師,效率可以差上幾十倍甚至幾百倍。除了上述的 coding 習慣、使用工具、開發環境...種種細節都會影響到,在拼專案之餘,也花些時間注重這些東西吧,一起往神人的境界努力!如果還有其他關於基礎學習,我再更新上來。

2013/03/24

在 Mac OS X 建置 python 開發環境

Install gcc for command line

Open XCode, click menu Preferences -> Downloads
check Command-Line Tools


Install Python-2.7.3

$ tar zxvf Python-2.7.3.tgz
$ cd Python-2.7.3
$ ./configure --prefix=/opt/Python-2.7.3
$ make && make install
$ export PATH=/opt/Python-2.7.3/bin:$PATH


Install distribute-0.6.35

$ tar zxvf distribute-0.6.27.tar.gz
$ cd distribute-0.6.27
$ python setup.py build
$ python setup.py install


Install pip-1.3.1

$ tar zxvf pip-1.1.tar.gz
$ cd pip-1.1
$ python setup.py build
$ python setup.py install


Install virtual environment

$ pip install virtualenv
$ virtualenv --no-site-packages /opt/pyenv
$ export PATH=/opt/pyenv/bin:$PATH



Install eclipse IDE

Download Eclipse Classic 4.2.2

Install PyDev plug-in for eclipse

Click menu Help -> Install New Software
Add repository with location: http://pydev.org/updates, then check the PyDev


Configure the interpreter

Click menu Preferences -> PyDev -> Interpreter - Python
Add new...
 

Add a new project and run it.
The debug mode is powerful.

2013/03/16

極致工藝 MacBook Air

昨天把我吃飯的傢伙給升級了 - MacBook Air


從 2009 MacBook Pro (Core 2 Duo) 升級到 2012 MacBook Air (i7 + SSD) 真的超有感覺
我已經忘了什麼是等待

由於 CPU 跟 Ram 都是不能更換的 就一次升到頂規啦
CPU i5 跟 i7 只差 3000 多
Ram 的話由於要跑 VM 升到 8G 也是必要的
SSD 我用 256GB 倒是沒有更大的需求 (SSD可以自行更換)


港版的 MBA 鍵帽上沒有注音符號 相當乾淨
符合我的風格 真的超愛

這個薄度令人驚嘆
重量從 MBP 的 2.06kg 降到 MBA 的1.35kg
天天要帶來帶去 以後身體負擔也減少些

疊疊樂
我的 MBP 可以退役了
MBA 正式上線

2013/03/12

物品的價值在於用了它,而不是擁有它 - 斷捨離


最近看了『斷捨離』這本書,主要在講述『人』與『物品』間的關係,我覺得這是可以自己動手做,而且很快就會有效果的。

整理一些心得跟大家分享:

觀念

  1. 『物品的價值在於用了它,而不是擁有它』,放著不用反而是一種浪費,甚至還會腐蝕你的周遭 (生存空間、心情、打掃時間...)
  2. 物品跟人的生理、心理是相關聯的,影響的層面包括了健康、安全、心情、自信心…甚至是運氣
  3. 一個人的時間是有限的,單一時間能用的物品數量就是那麼多,大部分的時候都太貪心了
  4. 三種『捨不得丟』的人,性格與其表徵:
    1. 逃避現實:在外停留的時間居多,並非忙碌才不在家,而是不想在家而忙碌。不敢面對自己,因為害怕而為自己找藉口
    2. 執著過去:將情感寄托在物品上,任何物品都當作自己的珍藏。給人活在過去的感覺
    3. 擔憂未來:儘管生活上購買東西已經很方便了,但我們還是有「囤貨」的習慣,造成過度購買,何不等到真正需要的時候再來買。庸人自擾,擔憂自己未來可能會發生什麼事情,這是最多人的一種
  5. 人要活在『當下』,不要活在過去,也不要過度擔憂未來
  6. 『捨不得』跟『可惜』是你最大的敵人,捨不得用、捨不得送、捨不得丟,不要把太多情感賦予在物品上面,情感應該是對人付出才是
  7. 如果一件衣服穿在身上都會讓你覺得不自在、沒自信、不舒服,為何還留著?自以為塞在櫃子某個深處就不浪費了,心想著有一天我應該會再穿到它。
  8. 辛苦賺錢買了的東西,當下的價值是100% 卻捨不得用,等到某天要用的時候,它的價值可能只剩 60%,這才是真正的浪費(食物過期、衣服過季、當下快樂的感覺也褪去)
  9. 有個東西一直被我們忽略:生存的空間,東西堆太多就會佔據生存空間。別以為東西越多就是越富有,超過一定的程度就有反效果
  10. 東西變多的時候,不是去買櫃子/箱子來裝,應該檢視一下是不是有不需要的東西,重『質』不要重『量』
  11. 一個家的功能不不該只是安全庇護,待在裡面應該要有跟待在旅館一樣的舒適、放鬆,更進一步有溫暖與愛
  12. 整理是把東西擺整齊、收納起來、放到看不見的地方,但斷捨離的精神不是整理,是把不需要的捨棄掉,剩下的東西不多,自然也整齊了起來,連打掃時間都縮短了

做法

  1. 物品處理的 cycle:
    1. 自用:把最適合、最好的拿來用,並免除多餘的
    2. 送人:為物品找到適合的對象也是很開心的,也能增進彼此的情感
    3. 變賣:換取一些金錢,不無小補
    4. 回收:資源回收、舊衣回收、傢俱回收,都有對應的管道
    5. 丟棄:上述都不行的話,這物品的剩餘價值也不多了
  2. 把同樣的東西擺在一起,挑出最好了幾樣,並拿來用,剩下的淘汰
  3. 判斷是否購買/丟棄的依據:喜好程度、使用頻率、條件。(先跳脫價格)
  4. 分批丟棄,第一步先找出不能用的(壞掉的、發霉的),第二步找出可以用但用不到、不需要的… 最後留下來,就會是自己真正喜愛的、需要的
  5. 物品的收納要以方便拿取為主,否則漸漸的又會凌亂起來。但物品太多時,怎麼收納都不方便
  6. 『三』是我們的好朋友,是一個腦袋可以負荷的數字,分三類、分大中小三種、分三層、三格…
  7. 『七五一總量控制』,看不見的收納最多放七成(留物品通道),看得見的收納放五成(美觀),展示櫃只放一成(精品)
  8. 買東西寧可買貴也不要多買,大賣場的『單價便宜』只是一種銷售策略,往往『總價』還是買過頭了,要清楚知道這次買東西的目的是什麼,不要因為便宜就買
  9. 一個好的東西價值是有可能大過三個普通的東西,雖然貴了些,但如果是自己真的很喜愛的我會買,而且貴的東西大多會保值

結論

  1. 物品的價值是靠『人』來彰顯,用了才會發揮它的價值,而人也因為『物品』的裝飾,整體都提升了,彼此相輔相成
  2. 漸漸會培養出精準的眼光與果斷力,下次在逛街的時候,就會很清楚自己想要的是什麼,不會因為衝動而買了不必要的東西
  3. 東西少一點、簡單一點,生活也輕鬆一點,斷捨離能為你帶來長時間的快樂


2013/03/02

富足人生與圓夢計劃

兼顧把這八大類,打造一個富足的人生。
(註:畫 mind map 的免費工具:Mind42)


之前一直在思考,能否把人生歸納在幾個項目,好讓生活有個目標可以依循,又不至於漏掉些什麼,後來在雜誌上看到這張圖,取自于松村寧雄《曼陀羅九宮格思考術:達成目標成功圓夢》,我認為該有的都概括到,於是開始 follow。

也許有人會選擇把時間都投注在追求某一項,你可以成就一番事業、實現夢想,你的聲譽與財富可能羨煞許多人,但這對我來說都不是真正的成功,因為這成功得背後可能犧牲了自己的健康、陪伴家人、另一半的時間,或是當下的快樂。而且考慮到風險的存在,這個不平衡的狀態,在過程中可能會因失控的健康或家庭,讓你無法進行原本的計劃。

唯有一個均衡的人生,才能穩紥穩打的走下去,這彼此間是相輔相成的,千萬不要放棄任何一項,至少各項要達到60分及格,多餘的時間就看你想成就什麼,就把重心投注在那上面。這是一個保守的做法,要在維持均衡之下再去追求自己想要的目標,是有一定的難度,但真正夠想要的人一定能達到。



圓夢計劃

用紀律來圓夢,是我目前正在嘗試的方法,也是我覺得可行性挺高而且實行起來不會太困難(只要把習慣養成),但缺點就是很漫長,恩...我相信成功沒有一蹴可幾,端看你願意花多少時間與力量。

時間應該要花在真正需要思考的地方,我把 regular 的事情列在月曆上,以週為單位,好像小學生的功課表,什麼時間該做什麼事情都清清楚楚。

(註:Google Calendar 是你的好幫手)

  • 工作
    就是一到五的未標示的部分。自己要很清楚當下工作的『目的』是什麼?為謀生、為成就、為下一階段做準備、為興趣、交朋友...總之專心的把工作做好,才不會拖到下班時間。如果實行夢想與上班做的事情是重疊的,那就更棒了!例如我想在網路上創業,我白天從事的工作也是網路相關的研發。
  • 運動
    這太重要了,這是維持健康必要的條件,沒有健康別談論夢想,不要連累到家人就不錯了,如果你的人生是看長期的話,找一個沒有金錢、時間、地點、年齡、性別、人數限制的運動,游泳是個不錯的選擇,不會太劇烈,也可以運動到全身。健康這東西,平時身體好好的你不會知道它的存在,只有在病痛的時候才會凸顯它的重要。
  • 睡覺
    這也是在日曆裡未標示的。每個人的睡眠時間長短、起始不同,如何找到自己的黃金時間(最少睡眠最大體力),這要靠自己去 try,睡眠跟工作一樣,在於『質』不在於『量』。
  • 寫部落格
    我覺得這是一件很困難的事情,『自己懂了』跟『用文字表達讓別人懂』,這兩個層次真的差很多,進一步再追求排版容易閱讀、內容吸引人、持續更新。
    寫部落格真的對自己有幫助啦,好處有很多就不一一提了。
  • 便利商店看雜誌
    現在的便利商店有冷氣有桌椅,又有各類雜誌,趨勢、財經、自我學習、休閒...除了工作上的專業知識,上述人生八大類都可以在此補足,也培養廣泛快速閱讀的能力。了解一下世界發生了什麼事情,不至於跟社會脫鉤,也跟其他人有話題可以聊,挑幾個對自己有幫助的篇幅再去深究即可。
    我深深覺得這是世界上最划算的事情了,點杯咖啡就可以坐一整個早上,不過通常我都翻不到幾頁啦,大部份時間還是望著窗外思考,靈感也是從這邊兒來。
  • 喝咖啡
    喝咖啡只是舉例,要吃下午茶也可 :D 重點是跟你的朋友見面,你的朋友可能來自於各行各業、各職位,不需要有特別的事情才能見面,單純聯繫感情,關心彼此,也讓他們知道你在做什麼,不同的朋友會給你不同的看法。
  • 實現夢想
    有人說:一個人的成就不在朝9晚5,在於晚7到晚11。朝九晚五不過是每個人每天在做的事情罷了,想跟別人不同?好好利用下班時間吧。
  • 逛街
    每個人逛街的目的大不相同,治裝、看妹、看新奇的東西...總之放鬆就好,我最常做的就是逛新光三越跟誠品。這個目的在於走入人群,人畢竟是群體動物嘛!
  • 禮拜日 do anything you want
    這一天比較彈性,可以延續本週未做完的事情、一場電影、一趟旅程、回家鄉、辦聚會、休息聽音樂...重點在於做你『想』做的,滿足自己的慾望,讓自己快樂。由於一到六比較屬於既定的事情,禮拜日當然要跳脫一下啦,我會選擇去嘗試『之前沒做過的事情』。


計劃表僅供參考,時間要能自己安排,計劃一旦訂了就要去執行,改變 - 從小地方開始。