code-prettify

2016年12月16日 星期五

大人學 A101 職場大人學:職場人際關係與優勢策略 課後心得

職場上,人際關係的基礎在於合作,聽起來理所當然的一句話,卻是令我大大震撼。回想過去,總是自己埋頭苦幹,堅持做對的事情,卻忽略他人的需求,久而久之,雙方的關係便陷於死結,聽到這句話,無疑是當頭棒喝。

常常聽到一些故事,某甲總愛找我麻煩,是壞人,某乙常常有小動作,是壞人,某丙從來不做事卻受到表揚,是壞人,然後故事中的自己一定是好人。從小到大,我們總習慣把人分別好人壞人,影響了思維的判斷。

有些人心裡想著,這些小人雖然得意於一時,但是我相信,老闆的眼睛是雪亮的,總有一天壞人會被處罰,好人會得以平反,換言之,也就是期待著公平正義從天而降,王子與公主從此過著幸福快樂的日子。但那個是童話,這樣的想法太天真,事實上我們真正該做的,是主動找出改變的方法,解決問題。

再從另一個角度來說,雖然常常聽到,但是從來沒有想過,每個人的故事中自己都是好人,那些故事中的壞人到底哪裡來的呢?其實很簡單,大家都是好人,只是角色不同。公司是一個完整的生態圈,有各式各樣的角色,簡單來說,兔子吃草是很正常的現象,總不會因為草被吃掉,因此就說兔子壞壞吧?在職場上,雖然不會真的有誰被吃掉,但是不同角色發生衝突很平常,不需要把對方貼上壞人的標籤,而是去思考如何解決衝突。

當思維轉換到解決問題時,就是利用限制理論,來分析衝突的時候了。衝突往往來自於「錯誤的假設」,只要找出這些錯誤假設,解決方案往往就自動跑出來了,除非雙方完全沒有共識,否則多數的情況下都能解決衝突。

其它還有很多內容需要慢慢消化,這邊特別感謝 William Yeh,因為看到課後心得後,才讓我下定決心來上這門課程,果然超值得!

#A101職場大人學
#大人學


2016年12月14日 星期三

大人學 用遊戲思維規劃你的職涯策略 課後心得

「打電動這麼用心,如果你讀書有一半認真就好了」相信不少人聽過這句話。今天這堂課,藉由遊戲化思維套入職場,不只可以讓平常的工作變有趣,更可以讓自己勇於面對挑戰!
用遊戲的角度看待自己的職涯,可以發現需要找攻略,收集情報,制定自己的目標,確認自己的角色定位,不要明明是個補師,卻總是站在怪面前坦,也難怪別人給你白眼,自己還搞不清楚狀況。
短短三個小時,收獲滿滿,雖然當天台中台北來回跑,但是我要說,這真的很值得啊!

A101 心得拖稿中
期待下個月的天賦熱情

#遊戲思維與職涯策略
#職場玩家的生存攻略
#大人學

2016年10月24日 星期一

C++ Coding Style Guide

Coding Style

第一章:
一、以檔案為最小單位,維持一致的風格
二、以這份風格為目標改進,如果現況不是的話
三、對任何規則有疑慮請提出來討論

第二章:
以 Qt Coding Style 為主,下列例外
一、使用 int* p,不要用 int *p



總結

不要使用例外 (Exceptions)
不要使用 Run Time Type Information (RTTI)
明智的使用 Template,而不只是因為你會
使用 C++ 轉型,不要使用 C 形式的轉型

檔案名稱全小寫 myclass.h or myclass.cpp
(for linux 大小寫敏感,打錯時會找不到,所以一律小寫
Ex: KeepALive.h, Keepalive.h, KeepAlive.h...etc)

類別命名使用峰駝式命名大寫開頭 MyClass
函式命名使用峰駝式命名小寫開頭 myFunction()
變數命名使用峰駝式命名小寫開頭 widthOfBox
私有成員變數命名使用 m_ 開頭 m_widthOfBox
全域變數開頭加上 g 及底線 g_widthOfBox
常數變數使用峰駝式命名大寫開頭 WidthOfBox
列舉 (Enum) 使用峰駝式命名大寫開頭
宣告指標或參考時,在 * 或 & 後面加上空白,不要在前面加上空白

大括號應該 (未決定)

引用 (include) 標頭檔 (header file) 的順序如下
(Names and Order of Includes)
自己的標頭檔 (myclass.h)
專案內的標頭檔 (otherclassinproject.h)
自行開發的工具標頭檔 (mylibary.h)
非標準庫標頭檔 (qt...etc)
近乎標準庫標頭檔 (boost)
標準庫標頭檔 (stl 的 iostream)
系統標題檔

順序的目的是確保自我描述(定義),
每個檔案都應該自行 include 需要的標頭檔。

Ex:
#include <string>
#include "otherclass.h"

可能會發生 otherclass.h 沒有 include <string> 但是編譯成功,
當其它地方使用 otherclass 的時候卻編譯失敗。

函式的參數順序及如何選擇使用指標 (pointers) 或參考 (references)
參數的順序是先輸入後輸出
輸入參數使用 const reference
輸出參數使用 non-const pointer


=== Code Style Tools ===
cpplint - automated checker to make sure a C++ file follows Google's C++ style
guide
https://github.com/google/styleguide/tree/gh-pages/cpplint

vera++ - verification, analysis and transformation of C++ source code
https://bitbucket.org/verateam/vera/wiki/Home

Indent - reformats C and C++ code in a user-defined indent style and coding style
http://www.gnu.org/software/indent/

Artistic Style 2.05 - Automatic Formatter
http://astyle.sourceforge.net/

Uncrustify - Code Beautifier
http://uncrustify.sourceforge.net/

clang - C language family frontend for LLVM
http://clang.llvm.org/

C++ Style Checker Tool (Not Free)
http://www.semanticdesigns.com/Products/StyleChecker/CppStyleChecker.html

=== 資料來源 ===
Google C++ Style Guide
http://google.github.io/styleguide/cppguide.html

不要使用例外 (Exceptions)
如果是新專案的話,一開始就使用例外的好處應該會高於付出的成本,
但是存有專案的話,因為所有會被影響的部份要全面考慮,所以成本過高。

避免使用 Run Time Type Information (RTTI)
避免使用 typeid or dynamic_cast

避免複雜的 Template

使用 C++ 轉型,不要使用 C 形式的轉型
使用 static_cast, const_cast, reinterpret_cast
不要用 y = (int)x; 或 int y = int(x);

類別命名使用峰駝式命名大寫開頭 MyClass
函式命名使用峰駝式命名大寫開頭 MyFunction()
變數命名使用 width_of_box 或 widthofbox
私有成員變數命名最後加上底線 width_of_box_ 或 widthofbox_
全域變數開頭加上 g 及底線 g_width_of_box 或 g_widthofbox
常數變數開頭加上 k 且改用峰駝式命名 kWidthOfBox
列舉 (Enum) 使用峰駝式命名大寫開頭

宣告指標或參考時,在 * 或 & 前面加上一個空白,或者在在後面加上空白,
不要同時在前面都加上空白
char *x; or char* x;
NOT
char * x;

大括號應該在同一行
if (codec) {
} else {
}
class 宣告及函式實作時也不例外
class Foo {
}

Foo::Bar() {
}

引用 (include) 標頭檔 (header file) 的順序如下
(Names and Order of Includes)

自己的標頭檔
C 系統標題檔
C++ 系統標題檔
自行開發的工具標頭檔
專案內的標頭檔

函式的參數順序及如何選擇使用指標 (pointers) 或參考 (references)
參數的順序是先輸入後輸出
輸入參數使用 const reference
輸出參數使用 non-const pointer

在 C 要改變傳入參數只能使用指標,C++ 可以使用參考,
使用參考可以避免程式碼比較醜,像是 (*pval)++,
而且參考不像指標會出現空指標。



Function names in C++: Capitalize or not? [closed]
http://stackoverflow.com/questions/1776291/function-names-in-c-capitalize-or-not
此文很下面的回答中有提到 C++11 開始支援的 Range-based for loop 要求要使用的類別實作 begin() 及 end() 函式,所以函式名稱使用小寫比較適合。

另外一個回答有提到標準函式庫習慣使用 my_function 來命名,例如
<algorithm>
http://www.cplusplus.com/reference/algorithm/




QT Coding Conventions
This is an overview of the high-level coding conventions we use when writing Qt code.
https://wiki.qt.io/Coding_Conventions

Qt Coding Style
This is an overview of the low-level coding conventions we use when writing Qt code.

Qt Creator Coding Rules
https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html

不要使用例外 (Exceptions)
不要使用 Run Time Type Information (RTTI)
明智的使用 Template,而不只是因為你會

類別命名使用峰駝式命名大寫開頭 MyClass
函式命名使用峰駝式命名小寫開頭 myFunction()
變數命名使用峰駝式命名小寫開頭 widthOfBox
私有成員變數命名使用 m_ 開頭 m_widthOfBox
列舉 (Enum) 使用峰駝式命名大寫開頭

宣告指標或參考時,在 * 或 & 前面加上一個空白,不要在後面加上空白
char *x;
NOT
char* x;

大括號應該在同一行
if (codec) {
} else {
}
class 宣告及函式實作時例外
class Foo
{
}
Foo::Bar()
{
}

引用 (include) 標頭檔 (header file) 的順序如下
(Including Headers)
自己的標頭檔
專案內的標頭檔
自行開發的工具標頭檔
Qt 標頭檔
STL 標頭檔
系統標題檔

目的是確保所有的標頭檔包含自己所需要的引用

在公開標頭檔引用 Qt 時候加上完整路徑
#include <QtCore/qwhatever.h>
這在 Mac OS X frameworks 是必須的,而且對於非 qmake 專案非常方便



Bjarne Stroustrup's C++ Style and Technique FAQ

Should I use call-by-value or call-by-reference?
http://www.stroustrup.com/bs_faq2.html#call-by-reference

當你想要改變參數時,使用參考或指標,f(X&) or f(X*)
當你不想改變參數時而且物件很大時,使用常數參考 (const reference),f(const X&)
其它情況,使用傳值(call by value),f(X)

Is ``int* p;'' right or is ``int *p;'' right?
C 程式設計師較常強調 int *p, *p 是一個 int。
C++ 程式設計師較常強調 int* p,p 是一個 int pointer 型別。



The GNU C++ Library
https://gcc.gnu.org/onlinedocs/libstdc++/

The GNU C++ Library - Coding Style
https://gcc.gnu.org/onlinedocs/libstdc++/manual/source_code_style.html

類別命名使用小寫,以底線分段,my_class
函式命名使用小寫,以底線分段,my_function()
變數命名使用兩個底線開頭,__width_of_box
私有變數命名使用 _M_ 開頭,_M_width_of_box
私有函式命名使用 _M_ 開頭,_M_width_of_box()
常數變數使用 _S_ 開頭,_S_widthOfBox
列舉 (Enum) 使用 _S_ 開頭,_S_widthOfBox

宣告指標或參考時,在 * 或 & 後面加上空白,不要在前面加上空白
char* x;
NOT
char *x;

呼叫成員函式時,使用 this 指標,this->foo();


Boost Library Requirements and Guidelines
http://www.boost.org/development/requirements.html
(還沒看過)

GNU Coding Standards
http://www.gnu.org/prep/standards/standards.html
(還沒看過)

GCC Coding Conventions
https://gcc.gnu.org/codingconventions.html
(還沒看過)

Why Google Style Guide for C++ is a deal-breaker
https://www.linkedin.com/pulse/20140503193653-3046051-why-google-style-guide-for-c-is-a-deal-breaker




C/C++ include file order/best practices [closed]
http://stackoverflow.com/questions/2762568/c-c-include-file-order-best-practices

h file corresponding to this cpp file (if applicable)
headers from the same component,
headers from other components,
system headers.


The prototype/interface header for this implementation (ie, the .h/.hh file that corresponds to this .cpp/.cc file).
Other headers from the same project, as needed.
Headers from other non-standard, non-system libraries (eg, Qt, Eigen, etc).
Headers from other "almost-standard" libraries (eg, Boost)
Standard C++ headers (eg, iostream, functional, etc)
Standard C headers (eg, cstdint, dirent.h, etc)




#include "filename" or <filename> ?
"filename" 表示先找專案內的檔案名稱,找不到再找 include 路徑下
<filename> 表示直接找 include 路徑下


#include <filename.h> or <filename> ?
filename.h 跟 filename 是兩個不同的檔案,
filename.h 是 C 的實作,filename 是 C++ 的實作,
在現代 C++ 標準,C 的實作已經改為 cfilename。
另外,沒有副檔名的用法只存在於標準函式庫,一般標頭檔還是有副檔名。



header file is .h / .hh / .hpp

使用 .h / .hh 的分別在於區分 C / CPP
一、C 實作,CPP Warp 時,會有相同的檔案名稱,使用不同的副檔名可以區別。
二、C / CPP 使用不同的 Coding Style 時,工具可以區別

使用 .hpp 是 boost 約定 CPP 的 header file 副檔名 (代替上面的 .hh)

另一種用法,.hpp 是代表此檔案包含完整實作,例如 template,這時候沒有 .cpp 檔案。



When can you omit the file extension in an #include directive?
http://stackoverflow.com/questions/441568/when-can-you-omit-the-file-extension-in-an-include-directive

When to use .hpp files
http://stackoverflow.com/questions/20023610/when-to-use-hpp-files

*.h or *.hpp for your class definitions
http://stackoverflow.com/questions/152555/h-or-hpp-for-your-class-definitions

C++: Reason why using “.hh” as extension for C++ header files [closed]
http://stackoverflow.com/questions/10354321/c-reason-why-using-hh-as-extension-for-c-header-files

Is having C++ header files without extension a good practice?
http://programmers.stackexchange.com/questions/135683/is-having-c-header-files-without-extension-a-good-practice

2016年10月15日 星期六

gitignore 範本及多個 gitignore 檔案實踐方法

Git 用了一段時間,常常遇到要調整 .gitignore 忽略自動產生的檔案,
當專案多了之後就會覺得不知道有沒有什麼範本可以使用,
馬上發現 GitHub 有個 gitignore 專案專門收集各種 .gitignore 範本。
https://github.com/github/gitignore

接下來想到的問題是,雖然一開始可以用範本,但是之後修修改改又不一致了?
有沒有什麼好的方法呢?直覺是能不能分開成多個 gitignore 檔案呢,
可惜,Git 不支援也不建議。
還好在 StackOverFlow 有網友提出合併檔案的方法,這樣就可以實踐了!

在 git 根目錄下建立一個 gitignore 目錄,然後將範本放進去,像是 VisualStudio.gitignore、C++.gitignore、Qt.gitignore
接著將專案的設定放在 Project.gitignore,最後用一個批次檔來產生 .gitignore。

cat Project.gitignore VisualStudio.gitignore C++.gitignore Qt.gitignore > ../.gitignore

這麼一來 gitignore 既方便使用也好維護 !



資料來源:
gitignore - A collection of useful .gitignore templates
https://github.com/github/gitignore

Best practice for using multiple .gitignore files
http://stackoverflow.com/questions/10274424/best-practice-for-using-multiple-gitignore-files

2016年9月18日 星期日

Bootstrap SB Admin 2 整合 AngularJS 遇到 metisMenu 問題

使用 Bootstrap SB Admin 2 (Live Preview) 樣版 ,
整合 AngularJS 遇到了幾個關於 metisMenu  (Live Demo) 的問題,

第一個問題是如果 menu 在 ng-include 裡面的話,
並不會正常運作,而是處於完全展開的情況。
原因是原本在 sb-admin-2.js 的程式碼:

$(function() {
    $('#side-menu').metisMenu();
});

在第一次載入頁面時已執行完畢,
當 angular app 載入 ng-include 之後,並沒有做任何的動作。
解決辦法就是在 ng-include 加入 onload 函式,
在 controller 加入下列程式碼後解決:

$scope.loaded = function() {
    $('#side-menu').metisMenu();
}

完整的 Plunker 範例



第二個問題是 metisMenu 的 active 功能沒有正常運作,
原因一樣是因為原本的設計是頁面載入完成後執行程式碼:

var url = window.location;
var element = $('ul.nav a').filter(function() {
    return this.href == url;
}).addClass('active').parent().parent().addClass('in').parent();
 if (element.is('li')) {
    element.addClass('active');
}

然而使用 Angular 實作 Single Page Application 之後,
切換頁面並不會重新載入 js,所以沒有觸發這個動作。
解決辦法是當頁面改變後執行這個動作,如下列程式碼:

.run(['$rootScope', function ($rootScope) {
    $rootScope.$on('$viewContentLoaded', function (event) {
        $('ul.nav a').removeClass('active');

        var url = window.location;
        var element = $('ul.nav a').filter(function () {
            return this.href == url || url.href.indexOf(this.href) == 0;
        }).addClass('active').parent().parent().addClass('in').parent();

        if (element.is('li')) {
            element.addClass('active');
        }
    });
}]);



jquery metisMenu not working inside ng-include
http://stackoverflow.com/questions/26335696/jquery-metismenu-not-working-inside-ng-include

Finished Loading of ng-include in angular js
http://stackoverflow.com/questions/27576643/finished-loading-of-ng-include-in-angular-js

2016年8月29日 星期一

Install Qt5.7 binary on Ubuntu 16.04

Use Ubuntu Server 16.04 for Example

For C++ need build-essential, OpenGL need libgl1-mesa-dev
and install Qt 5.7 binary from PPA

sudo add-apt-repository -y ppa:beineri/opt-qt57-xenial
sudo apt update
sudo apt install -y build-essential libgl1-mesa-dev qt-latest
. "/opt/qt57/bin/qt57-env.sh"

For env setting, add bashrc command
echo . "/opt/qt57/bin/qt57-env.sh" >> .bashrc

=== Ref
Install Qt 5 on Ubuntu
https://wiki.qt.io/Install_Qt_5_on_Ubuntu

Stephan Binner
https://launchpad.net/~beineri

2016年8月6日 星期六

開發團隊 - We are Not Scrum

目前在開發團隊中,進行每日「例」會、利用便條貼整理需求,造成有人經過時會以為團隊正在進行敏捷開發,或者說我們在跑 Scrum。這時候我一定會回答,不,不是的,We are Not Scrum。

先說說目前的情況,
一、每日例會
進行於下午四點半,雖然幾乎是全員站立的,其實不是強制性,時間大概是 20~45 分鐘,目標會希望在 30 分鐘內結束,主要目的是同步資訊,無論是市場變動、系統維運狀態、需求或時程變更、系統架構說明、個人任務說明……等等。

其實上述同時也說明為什麼會進行每日例會,為了解決下例情況
# 開發成員對市場狀況不明白,不懂為何而戰
# 系統可能永遠在某些情況當掉,但是開發人員不知道
# 需求變動可能只有部份開發人員收到通知
# 新進工程師、維運、測試人員對系統不了解 (可能沒機會了解)
# 每個角色遇到的問題也許其它人可以協助,像是維運或測試人員需要工具支援

二、便條貼需求
目前的需求會寫成便條紙,單純是因為需求的優先序變化太快了,白板改來改去太累人,所以才改用便條紙的。另一方面是將除了需求之外,維運及優化問題也都寫上去,方便團隊成員全盤了解產品的狀態。

同樣整理一下便條紙需求解決什麼問題
# 需求優先序變化時,不用擦掉重寫 (尤其是字寫很醜的時候
# 將維運及優化項目列上去,可以讓成員明白有哪些技術債需償還 (尤其是主管或 PO
# 成員想到什麼想法時,可以隨手寫張便利貼上去

為什麼會說不是 Scrum (敏捷開發)
一、真的不是
# 每日「例」會,不是每日「立」會,站立不是重點,想快點結束會議才是共識
# 時間不會限制在十五分鐘內結束,需要討論的事情講完了自然會結束,沒有人喜歡開會
# 主要是資訊分享,鼓勵發言,但是不會強制每個人說三件事
# 便利貼是為了便利,不會特別貼成 Todo, In Progress, Done

二、條件不滿足
# 沒有固定 Sprint 週期,DeadLine 沒有彈性
# 開發人員所作決定得到認可,像是決定實作哪些需求、品質、上線時間

三、避免誤用
# 把 Scrum 的點數當作工時,把預估時程當作承諾
# 誤以為都不用寫文件

最後,要說明我不是在反對 Scrum,Scrum 是個好的方法,但是就好像吃藥一樣,正確的服用才能有好的成果。要先明白要解決的問題,才決定用什麼方法。我也不是反對敏捷,相反的,敏捷正是團隊的目標之一,當宣稱不是使用敏捷開發時,只是避免別人誤以為我們正在進行「某種」工作流程。



資料來源:
敏捷開發
http://wiki.mbalib.com/zh-tw/敏捷开发

敏捷軟體開發
https://zh.wikipedia.org/wiki/敏捷軟體開發

Scrum
https://zh.wikipedia.org/wiki/Scrum

2016年7月27日 星期三

使用 Docker 啟動 Jenkins 2

Jenkins 2 是 Jenkins 的大改版,特色是主打 Pipelines,提供彈性的設定及狀態的視覺化。
詳細的內容可以參考官網 2.0 的介紹

假設已經有了 Docker 環境,如果沒有的話可以參考這篇文章建立一個 VM。
在 Windows 7 使用 Vagrant 建立 Docker VM 環境

因為 docker 內的修改在 container 停止後是不會保留的,為了避免失去相關資料,要先幫 jenkins 建立一個目錄來保存。
sudo mkdir /opt/jenkins
sudo chown vagrant.vagrant jenkins

將著執行指令取得 Jenkins 2 的 image 並且啟動 Container。

docker run -d \
    -v /opt/jenkins:/var/jenkins_home \
    -p 8082:8080 \
    --name jenkins2 \
    jenkinsci/jenkins

-v 參數 Data volumes,建立 Host 跟 Container 的對應,在 Container 中的 /var/jenkins_home 將會連結到 Host 的 /opt/jenkins。

-p 參數 Port Mapping ,是設定 Host 跟 Container 的 Port 對應,當 Container 有設定 export Port 時,可以透過此參數來對應 Host Port 及 Container Port。這個例子是,代表 Host 的 8082 Port 對應到 Container 的 8080 Port。

--name 參數是 Container 的名稱,方便識別,必須是唯一的,如果重覆必須先 rm 掉原本的 Container 。



輸入命令後,Docker 發現本地沒有這個 Image,會從 DockerHub 下載,下載完成會啟動一個 Container。

因為使用 VM,記得要設定 VirtualBox 的 Port Forwarding 喔。
VirtualBox 設定 Port Forwarding

開啟 http://localhost:8082
可以看到第一次登入 Jenkins,要求輸入管理員密碼。


畫面上提示密碼在 /var/jenkins_home/secrets/initialAdminPassword 目錄下,
但是別忘了,這個路徑實際上在 Host 是 /opt/jenkins/secrets/initialAdminPassword。


將那一串密碼輸入後,會請你選擇安裝建議套件,或是自己選擇套件,如果已經清楚需要哪些套件的話可以選右邊,否則就選左邊喔。


選擇左邊之後開始安裝套件,可以看到每個套件安裝的進度。


安裝後請你輸入第一個管理員的帳號及密碼,如果不想自訂可以選右下角的「Continue as admin」


選擇跳過自訂管理員帳號的話,會出現預設帳號 admin,及預設密碼 administrator。


最後就可以開始使用 Jenkins 嘍!




資料來源:
DockerHub - jenkinsci/jenkins
https://hub.docker.com/r/jenkinsci/jenkins/

DockerHub - bmst/jenkins2
https://hub.docker.com/r/bmst/jenkins2/

2016年7月19日 星期二

如何使用 Closure Compiler 最小化 JavaScript 產生 Source Maps 後進行偵錯

本文介紹以一個 AngularJS App 當範例,如何使用 Closure Compiler 最小化 (minimizes) 後產生的 Source Map 透過 Chrome 來進行偵錯 (Debug)。

Closure Compiler 是 Google 開發的 JavaScript 最小化編譯器,
關於細節可以參考 Google Closure Compiler 編譯器:產生最佳化(最小化)JavaScript 程式碼

本文使用的範例是 Kuroneko Idle Game (雖然不能算是一個遊戲)
所有的程式碼在 GitHub
https://github.com/allyusd/kuroneko
範例網站
http://allyusd.github.io/kuroneko

首先看一下完整建置指令
java -jar compiler-latest\compiler.jar --js_output_file myapp.min.js --create_source_map myapp.min.js.map --output_wrapper "%%output%%//# sourceMappingURL=myapp.min.js.map" js/**.js

這一段指令,將 js 目錄下含子目錄的所有 js 檔案,都合併成 myapp.min.js,並且在最後加上 sourceMappingURL 相關文字,同時產生 myapp.min.js.map 這個 Source Map 檔案。

參數介紹
js_output_file 表示最小化後輸出的 js 檔案名稱
create_source_map 表示同時要產生 Source Map,並指定檔案名稱
output_wrapper 可以進行加工,這個例子是加上 #sourceMappingURL 關鍵字

先介紹一下最小化,在開發 AngularJS (或任何 JavaScript 應用) 時,大部份的情況像是下圖的結構。


透過 Closure Compiler 可以合併成單一檔案,減少 Http request 次數,減少空白或換行字元,用短變數的替換…等等的好處。但是衍生了一個問題,就是不方便偵錯,這是用 Chrome 看到最小化後的結果(部份)。



人是貪心的,有沒有辦法魚與熊掌兼得呢?

實際上是有的,就是利用 Source Map,只要加上 create_source_map 參數就能產生,但是要如何使用呢?

我們在最小化的檔案 myapp.min.js 加上 sourceMappingURL 告訴瀏覽器 Source Map 的位置,接著用 Chrome 查看會出現下圖。



眼尖的話會發現除了 myapp.min.js 外出現很多斜體字檔案,其實就是合併前的 js 檔。開心的別太早,點開檔案發現裡面是空白的,因為並沒有把原始檔案上傳,如果有上傳的話,這時候已經可以看到原本的 JavaScript 檔案內容。

因為不想上傳多餘的東西,所以我們要偵錯的話必須讓 Chrome 知道原本的檔案在哪裡,首先在空白處點擊 Add folder to workspace


指定本地檔案路徑後,Chrome 上方會出現授權請求及警語。


按下允許後下方會出現本地工作目錄。

接著剩下最後一個動作了,在上面斜體字檔案按下右鍵,選擇 Map to file system resource...


最後選擇對應的本地檔案就完成了,結果如下圖


這些原始檔可不是只能看看而已,可以下中斷點的偵錯的喔!




資料來源
Introduction to JavaScript Source Maps
http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

Map Preprocessed Code to Source Code
https://developers.google.com/web/tools/chrome-devtools/debug/readability/source-maps

Secrets of the Browser Developer Tools
http://devtoolsecrets.com/secret/debugging-use-javascript-source-maps.html

Set Up Persistence with DevTools Workspaces
https://developers.google.com/web/tools/setup/setup-workflow

2016年7月17日 星期日

使用 Docker 啟動 Shipyard

Shipyard 提供一個支援多主機 Docker 叢集的 Web UI 管理服務
可以透過 Web 管理容器,如下圖


假設已經有了 Docker 環境,如果沒有的話可以參考這篇文章建立一個 VM。
在 Windows 7 使用 Vagrant 建立 Docker VM 環境

馬上透過官方提供的腳本進行安裝
curl -s https://shipyard-project.com/deploy | bash -s


Docker 會將需要的 Image 從 DockerHub 下載,最後會出現
Username: admin Pasword: shipyard,等等會用到。

因為使用 VM,記得要設定 VirtualBox 的 Port Forwarding 喔。
可以參考 VirtualBox 設定 Port Forwarding

輸入 http://localhost:8080 就可以看到 shipyard 登入畫面,記得輸入剛剛的帳密。


登入後可以看到列出來的容器清單 Containes,可以看到 Shipyard 需要的相關服務都已經下載並啟動完成。


這麼一來就有 Docker 視覺化基本操作介面可以玩嘍!



Updata
20160720 開頭補充 Shipyard 簡單介紹


資料來源
Shipyard - Composable Docker Management
http://shipyard-project.com/

2016年7月11日 星期一

VirtualBox 設定 Port Forwarding

利用 VirtualBox 建立 VM,預設網路設定為 NAT,如果想要從 Host 存取 VM 的 Port,必須設定 Port Forwarding (連接埠轉送)。

開始 VM 的設定頁之後,選擇網路,連接埠轉送。



接著輸入名稱,主機連接埠、客體連接埠,然後按下確定,就完成設定了!

2016年7月10日 星期日

在 Windows 7 使用 Vagrant 建立 Docker VM 環境

需要安裝兩個軟體

一、VirtualBox
https://www.virtualbox.org/wiki/Downloads

二、Vagrant
https://www.vagrantup.com/downloads.html

在下載的過程中,簡單介紹一下 Vagrant。
Vagrant 官方定義為 「建立及設定輕量性、可重覆性及可攜性的開發環境」,主要是透過設定檔使用 VirtualBox 來建立一個虛擬機器 (Virtual Machine, VM),是達成 「Infrastructure As Code」的一種方式。

Vagrant 包裝好的環境,稱為 Vagrant Box,本來在 Vagrant Cloud 提供上傳下載,但是現在被 Atlas 合併後不開放新帳號註冊了,所以只能下載 Box,不能上傳,除非你有原本 Vagrant Cloud 的帳號,幸好主要是要用 Docker,以後有 DockerHub,這些事情就不重要嘍。

下載安裝完 VirutalBox 及 Vagrant 之後,就可以開啟命令提示字元 (cmd.exe) 來操作嘍。首先建立這次要使用的資料夾,會用來放 vagrant 設定檔
mkdir vagrant\ubuntu
cd vagrant\ubuntu



目標版本為 Ubuntu 14.04 LTS ,直接用已經存在的 Box 來進行初始化。
vagrant init ubuntu/trusty64


初始化會在資料夾產生一個 Vagrantfile,是 Vagrant 主要的設定檔,目前只有指定 Box 名稱,如果想要設定 cpu, memory 等等,也在這裡設定,目前先用預設值來啟動 VM。
vagrant up



如果是第一次使用這個 Box,會從 Atlas 網站下載,時間視檔案大小及網路速度而定,第二次之後就會省去這個動作,順便一提,下載後 Box 存放的路徑在 %USERPROFILE%\.vagrant.d\boxes。等進度條跑完,Vagrant 就會依照設定把 VM 開起來嘍。

接著使用 ssh 登入 VM吧。
vagrant ssh


這樣已經可以開始玩新建立的 VM 嘍,但是習慣用 PieTTY 連線的話怎麼辦呢?這時候就要回頭看一下啟動的訊息,其中最重要的是 22 (guest) => 2222 (host) 的 Forwading ports 設定,代表連到本機的 2222 port 就可以連到 VM 的 22 ssh port 喔。



預設的帳密是 vagrant / vagrant


因為 Ubuntu 14.04 還沒有預裝 Docker,所以我們要先安裝,
透過官方提供的指令可以快速完成相關安裝及設定。
curl -sSL https://get.docker.com/ | sudo sh


可以看到安裝的 Docker 版本是 1.11.2,且提示要使用非 root 操作 docker 的話,將該 user 加入 docker 群組中。
sudo usermod -aG docker ${USER}

輸入後重新登入,使用指令測試一下 dockre


回過頭來看一下 Vagrant 的效果,
只需要兩行指令,達到輕量性。
(init 指令可改為從 GitHub 取得 Vagrantfile)
直接使用 Box,為可重覆性。
可以在 Windows, Linux, Max 使用,算是可攜性。

以後就不需要苦惱要設定 VirtualBox 的 Image 要怎麼辦了,大大減少從 OS 安裝開始的流程,也不必靠文件的 SOP 來建立想要的環境,接下來就可以開始放心玩 Docker 嘍!



Udpate
20160716 因為 williamyeh/ubuntu-trusty64-docker 除了安裝 docker 之外有其它客製化,為了保持環境單純,改用 ubuntu/trusty64 當範例



資料來源
Vagrant Tutorial(2)跟著流浪漢把玩虛擬機
http://www.codedata.com.tw/social-coding/vagrant-tutorial-2-playing-vm-with-vagrant/

Vagrant Tutorial(3)細說虛擬機生滅狀態
http://www.codedata.com.tw/social-coding/vagrant-tutorial-3-vm-lifecycle/

Vagrant box: can't login with password from VirtualBox GUI
http://stackoverflow.com/questions/26524691/vagrant-box-cant-login-with-password-from-virtualbox-gui

《Docker —— 從入門到實踐­》正體中文版 - Ubuntu 系列安裝 Docker
https://philipzheng.gitbooks.io/docker_practice/content/install/ubuntu.html

2016年5月19日 星期四

Linux auto build project when file modify

Arch auto build qt project when file modify use inotify-tools

#install inotify tools
pacman -S inotify-tools

# write a monitor script
autobuild.sh

=== Refference ===
Github - inotify-tools
https://github.com/rvoicilas/inotify-tools/wiki

inotifywait(1) - Linux man page
http://linux.die.net/man/1/inotifywait






2016年5月15日 星期日

VirtualBox 啟動 VM 在背景模式下

想要在背景模式下啟動 VM,需要透過 VBoxManage.exe 管理工具,
預設 VirtualBox 不在環境變數 PATH 裡面,所以要先切換到該目錄下。

# 切換目錄到 VirtualBox
cd C:\Program Files\Oracle\VirtualBox

# 列出 VM 清單
VBoxManage list vms
"MyVM" {e4b0c92c-4301-4a7d-8af8-fe02fed00451}

# 啟動 VM 為背景模式下
VBoxManage startvm MyVM --type headless

# 不需要使用時關閉該 VM
VBoxManage controlvm MyVM poweroff



資料來源:
Start VirtualBox VM in Headless Mode
http://schier.co/blog/2013/03/13/start-virtualbox-vm-in-headless-mode.html

2016年5月13日 星期五

關閉 Sublime Text 3 記憶已開啟的檔案

因為想把 Sublime Text 當作預設文字編輯器,
但是有兩個習慣一直無法適應,所以決定把他的設定改掉。

第一,當 Sublime Text 關閉時,當檔案有修改時,並不會詢問是否要存檔,
而是幫你保留當下的變更,當下次你啟動時再給你看,這是 hot_exit 功能。

第二,當 Sublime Text 開啟時,會記憶你上次開啟的檔案,一次開給你看,
這個叫 remember_open_files 功能。

幸好 Sublime Text 擁有高客制化的能力,
透過 Preferences / Settings-User 叫出個人化設定檔,
加上這兩行即可

"hot_exit": false,
"remember_open_files": false,

實際設定圖片:



資料來源:
How To Disable Remember Open Files in Sublime Text 3
http://www.unixmen.com/disable-remember-open-files-sublime-text-3/

2016年2月7日 星期日

如何實現目標

如何實現目標

一、設定目標

決定你要什麼

第一步,花點時間去思考你要什麼。

定義你的條件

對於相同目標,每個人的定義不太一樣。定義自己對於目標的條件。

問為什麼

花點時間來思考為什麼要定這個目標是很重要的。如果你了解動機是什麼,也許你會修改目標或者條件。

確認是否可行

最後確認目標是否可行,這可能取決於你的目標大小和時間長短,定過於不切實際的目標,最終可能導致失敗及沮喪。

二、制定計劃

腦力激盪

制定了目標,接著要開始更詳細的計劃。首先把想法寫下來,利用腦力激盪的方式得到多種可能的方法。

具體方法

利用之前想到的方法,確立可以達到或可以做的具體方法。

考慮利用 SMART 原則

SMART 原則是目標管理的一種方法,分別為
Specific(明確)
Measurable(可衡量)
Attainable(可達成)
Relevant(相關性)
Time-bound(時限)

排序你的目標

大部份的人有多個目標,將他們一一排序,可以幫助自己再次確認目標的意義,以及接下來應該專注的目標。

想像帶來的影響

花一些時間去想像這些目標將會如何影響自己的生活。這將幫助你判斷完成每個目標所帶來的好處,同時可以提高自己的動機。

建立子目標

如果將目標拆解成多個小目標將更容易實現。

列出障礙清單

將實現目標可能遇到的障礙列出來,這可以幫助自己思考如何克服這些障礙。

三、達成目標

奉獻你的時間

有很多方法可以幫助你保持專注,但大多數的目標需要花費許多時間去完成。假如完成一個目標需要60個小時,預計在一個月完成,那平均一天應該花2個小時努力。

養成習慣

一個幫助完成目標的方法是養成習慣,在固定的時間完成任務。例如每天早上七點到九點練習吉它。

追蹤進度

一旦開始努力朝目標進度,開始紀錄目標進度。每天花費時間、子目標達成……等等。追蹤進度可以幫助你保持動力及養成習慣。

保持動力

在達成目標最困難的一部份,就是保持動力。可以透過養成習慣和追蹤進度來幫助,但可能需要其它的方法來強化。
正向強化是在生活中增加一些東西,像是在完成子目標時買個點心來慶祝。
負向強化是在生活中刪除一些東西,像是在完成子目標時不做某個苦差事。
強化動力時,獎勵比懲罰更有效。剝奪一件事物當作目標失敗的懲罰可以小程度使用,但是儘可能的使用獎勵。



資料來源:
How to Accomplish a Goal
http://www.wikihow.com/Accomplish-a-Goal

維基百科 - SMART原則
https://zh.wikipedia.org/wiki/SMART%E5%8E%9F%E5%88%99

2016年1月7日 星期四

Arch 安裝 RabbitMQ

sudo pacman -S rabbitmq

單次啟動
sudo rabbitmq-server

背景執行
sudo rabbitmq-server &

啟動 web 管理介面模組
sudo rabbitmq-plugins enable rabbitmq_management

新增帳號
sudo rabbitmqctl add_user admin passworld
sudo rabbitmqctl set_user_tags admin administrator
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"

允許遠端登入
sudo nano /etc/rabbitmq/rabbitmq.config

輸入下列內容後存檔,然後重啟 rabbitmq
[{rabbit, [{loopback_users, []}]}].

使用此網址登入
帳密為 admin / passworld
http://127.0.0.1:15672/

新增一個使用者及 Virtual Hosts
sudo rabbitmqctl add_user user passworld
sudo rabbitmqctl add_vhost vhost
sudo rabbitmqctl set_permissions -p vhost user ".*" ".*" ".*"

設定 ssl

在 rabbitmq.config 檔案設定

[
  {rabbit, [
     {ssl_listeners, [5671]},
     {ssl_options, [{cacertfile,"/path/to/testca/cacert.pem"},
                    {certfile,"/path/to/server/cert.pem"},
                    {keyfile,"/path/to/server/key.pem"},
                    {verify,verify_peer},
                    {fail_if_no_peer_cert,false}]}
   ]}
].

2016-02-04 Update:
新增帳號及權限設定方法
新增 SSL 設定方法

資料來源:
How to Enable RabbitMQ Management Plugin and Create New User
http://www.thegeekstuff.com/2013/10/enable-rabbitmq-management-plugin/

RabbitMQ 3.3.1 can not login with guest/guest
http://stackoverflow.com/questions/23669780/rabbitmq-3-3-1-can-not-login-with-guest-guest

Can't access RabbitMQ web management interface after fresh install
http://stackoverflow.com/questions/22850546/cant-access-rabbitmq-web-management-interface-after-fresh-install

rabbitmqctl(1) manual page
https://www.rabbitmq.com/man/rabbitmqctl.1.man.html

TLS Support
https://www.rabbitmq.com/ssl.html

下面的方法還沒成功
[solved] how to start the rabbitmq-server with systemctl
https://bbs.archlinux.org/viewtopic.php?id=191587