code-prettify

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/