2019年8月12日 星期一

程式設計師應有的程式技能-ASP.NET(C#)語法與API資料介接-後端技術

18. (番外篇) 五分鐘實作 C# 介接 OpenData(政府行政機關辦公日曆表)

前言

今天主要講的是快速介接政府資料開放平臺上的政府行政機關辦公日曆表
緣由是最近實作一個小型的工作行事曆
主要是讓客戶可以送件時,可以計算交件期限
邏輯蠻簡單的,從送件日根據案件等級往後推 N 個工作天即是
所以我們需要幾個資訊
  1. 送件日期
  2. 案件等級
  3. 判別工作日與例假日
工作日與例假日的部分,希望每年都可以匯入人事行政處公布的辦公日曆表
之後若遇颱風或其他不可抗拒因素彈性放假時,也要有地方可以手動調整
那我們就開始先接資料吧

先找到資料來源

  1. 先到 政府行政機關辦公日曆表 點選 JSON 檢視資料
    如圖
  2. 複製 資料網址
  3. 將網址貼到 Chrome 上就可以看到要接收的資料了
    data

發送 Http request & 接收 response

  1. 我們要先建立一個 WebRequest
var url = "http://data.ntpc.gov.tw/api/v1/rest/datastore/382000000A-000077-002";
var request = WebRequest.Create(url);
// 透過 Chrome 開發者工具可以取得 Method, ContentType
request.Method = "GET";
request.ContentType = "application/json;charset=UTF-8";
  1. 取得 request 的 response stream
var response = request.GetResponse() as HttpWebResponse;
var responseStream = response.GetResponseStream();
var reader = new StreamReader(responseStrea  Encoding.GetEncoding("utf-8"));
var srcString = reader.ReadToEnd();
  1. srcString 就是我們要的資料了

建立 JSON 格式對應的 class

感謝 Visual studio 提供強大的貼上 JSON 做為類別 功能
  1. 先複製在 Chrome 貼上資料來源後,畫面中的 JSON 資料
    copy
  2. 建立一個 class
    create class
  3. 編輯(E) => 選擇性貼上(S) => 貼上 JSON 做為類別(J)
    paste

將剛剛的 response string 轉為 class 吧

我利用 Newtonsoft 提供的轉型方法
var jsonData = Newtonsoft.Json.JsonConvert.DeserializeObject<HolidayOpenData>(srcString);
整段 code 看起來就會是
static void Main(string[] args)
{
    var url = "http://data.ntpc.gov.tw/api/v1/rest/datastore/382000000A-000077-002";
    var request = WebRequest.Create(url);

    var response = request.GetResponse() as HttpWebResponse;
    var responseStream = response.GetResponseStream();
    var reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
    var srcString = reader.ReadToEnd();
    var jsonData = Newtonsoft.Json.JsonConvert
        .DeserializeObject<HolidayOpenData>(srcString);
    foreach (var holiday in jsonData.result.records)
    {
        Console.WriteLine($"Date: {holiday.date}, IsHoliday: {holiday.isHoliday}, Category: {holiday.holidayCategory}");
    }
    Console.ReadKey();
}
運行結果如圖
result

結論

目前用簡單的方式先接資料
看之後要開 thread 或是採用 async await 方式都可以
完整的程式碼在 Github 上 https://github.com/ChiYunJai/Day18_OpenData
目前有個小缺點是她日期為 string
看之後轉型成 DateTime 會比較方便處理
接著開一張資料表紀錄某年某月某天是否為工作日即可
匯入步驟也很簡單
  1. 先將 openData 取得所有 IsHoliday = "是" 的日期匯入
  2. 剩下的都是為工作日匯入
  3. 提供介面讓使用者可以根據情況調整某天為工作日或例假日即可
最後在算交件期限時,用送件日期當 query 條件去找即可!
【資料引用資訊】
google關鍵字:18. (番外篇) 五分鐘實作 C# 介接 OpenData(政府行政機關辦公日曆表)

程式設計師應有的程式技能-SourceTree版控工具-管理技術

第一部分:版控概念

遠端多人合作開發-單分支

上個單元介紹如何在GitHub建立一個遠端儲存庫,接下來這個
單元要來看本地與遠端如何運作,同時為了將問題複雜度簡化,
此單元只介紹一個mater分支情況下的開發流程。

一、只有一個人開發

若你在使用GIT版本控管只是自己一個人獨力開發程式,且不會分支,
只用master分支來開發,那開發流程是如何呢?我們來看一下。
首先就像上個單元所講的,你必須先建立一個遠端儲存庫和本地儲存庫,
並且讓兩個儲存庫連結:
你可以使用自己建立的遠端儲存庫。若懶得建立,請上網將底下專案Fork至你自己的儲存庫吧:
https://github.com/kingofamani/sample501
接著clone至辦公室的電腦,記得要用你自己的GitHub帳號:
git clone https://github.com/[你的GitHub帳號]/sample501.git
打開sourceTree開一下分支圖,有5個提交版本:
圖中除了有master分支外,多了origin/master及origin/HEAD分支,
這兩個分支其實是存在於遠端GitHub儲存庫的分支。當我們把儲存庫clone下來後,
就會自動在本地建立起這些分支,藉以追蹤遠端分支,
因此我們可以將origin/master、origin/HEAD稱為本地追蹤分支
而origin/HEAD是GIT自動產生,用來指向目前分支的最新版本,
也就是指向origin/master,所以其實遠端只有一個origin/master分支。
而origin其實就是遠端儲存庫的別名,你可以輸入git remote -v就可以看到遠端儲存庫的路徑:
如果要查看所有分支,可用git branch -a指令查看,其中紅色的表示本地追蹤分支
好了,現在你辦公室電腦已經有完整的Git版控啦。
現在要進行程式開發,假如我又提交了兩個版本:
cd sample501
echo 1 > 6.txt
git add .
git commit -m "C6"
echo 1 > 7.txt
git add .
git commit -m "C7"
現在開始,本地和遠端的儲存庫版本有差異了,本地有7個版本,遠端只有5個版本:
那遠端要如何取得這兩個新的版本呢?簡單,只要下push指令就可以了:
git push origin master
現在遠端也有最新版本,準備下班回家囉!
回到家後,準備洗澡看電視,好好休息一番…但…老闆此時來電,表示案子進度不夠,明天要
看到某某功能完成,天啊!又要加班,不得已,只好又打開電腦,繼續coding…
打開電腦後,家裡電腦並沒有程式碼,怎麼辦咧?
克隆下來就好啦…
git clone https://github.com/[你的GitHub帳號]/sample501.git home501
接著在家裡又提了一個版本,並上傳至遠端:
cd home501
echo 1 > 8.txt
git add .
git commit -m "C8"
git push origin master
現在家裡電腦和GitHub遠端儲存庫都同步了,開心!總算可以睡覺囉!
隔天…
來到公司辦公室後,打開電腦,再來要做什麼呢?當然是繼續扣頂!扣頂!
呼~好不容易又改了一個功能,也提交了一個版本:
cd sample501
echo 1 > 9.txt
git add .
git commit -m "C9"
接著開開心心下了push指令,準備上傳吧~~~
git push origin master
蝦米~error~怎麼了?開發的程序和之前一樣,怎麼會出錯呢?啊…早知道就不要用Git…哇~~
沒關係,別急!來看怎麼了,我們先來比較一下GitHub網站、家裡、辦公室儲存庫的版本:
原來是昨天晚上在家裡做的C8版本,並沒有在辦公室的儲存庫裡,
這個時候我們只要透過git pull指令,將GitHub昨晚更新的版本下載至辦公室儲存庫即可:
git pull origin master
※ pull後看一下分支圖,你會發現多了一個耳朵,就好像之前在做merge時一樣。
其實pull指令包含了兩個動作,第一個動作是先將origin/master遠端分支的版本抓下來(fetch),
然後再將master與origin/maser做合併(merge)的動作,如此本地的master也就有了遠端master分支的新版本了。
所以 pull = fetch + merge
有些人不喜歡每次pull後,會產生一堆merge後的耳朵,因為會習慣將master與origin/master看成一同一分支,
當有新版本時,也只是在同一分支做快轉而已,那要怎麼做呢?
如果下 git push --no-ff origin master可以嗎?當然不行,origin和origin/master在C7時已經分叉開了,
當然也就沒有所謂的快轉合併,因此用--no-ff參數是沒有意義的。
有一個方法可以解決,我們可以使用pull --rebase來完成任務,
指令為
git pull --rebase origin master
下載合併後,C8放進來了,而且還是在同一條線上,好看!
但有一點要注意,使用--rebase後,C9版本的SHA1值被改變了,
由於我們還沒將C9版本push上遠端,因此也就不用擔心其他人版本會亂掉的問題。
另外還有一個問題,若rebase時origin/master有多個commit,一旦發生衝突(conflict)時,
是會接續產生的,你必須一一處理每個commit的衝突後,才能pull
辦公室的儲存庫也有C8版本了,但GitHub遠端還沒有今天做的C9版本,
此時下push指令就可以上傳了:
git push origin master
今天的工作總算又解決了~
考考大家,如果回家後,要繼續做版控,你會怎麼做呢?
偷偷地告訴做法好了,但這次我要用不一樣的方法來完成,
還記得剛才有說過pull其實是fetch + merge兩個指令,如果分開下指令會怎麼樣呢?
首先下fetch指令:
cd home501
git fetch origin master
分支圖可以看到已經將C9版本抓下來了,但還沒有合併,因為master和origin/master
是在不同版本上。
接著我們要做合併動作
git merge origin/master
由於master和origin/master並沒有分叉,想當然爾這是一個快轉合併囉!
由上你可發現使用同一遠端儲存庫,然後在不同電腦做版控,
就只是clonepushpull三個指令在做變化而已。
第一次用clone複製到本地,
然後本地建好版本就push上傳、若遠端有新版本就pull下來,
等本地又有新版本再push上去,遠端若又有新版本就再pull下來…
就這樣一直循環建立版本控制,不難!不難!

二、多人合力開發

其實不管是幾個人,整個團隊的開發流程是差不多的,
你只要將辦公室家裡改成同事甲同事乙,然後所有流程都一樣,搞定!

+

流程:先要有人在遠端建好儲存庫,接著團隊的每個人clone一份完整的儲存庫到自己的電腦,
接下來若有人寫了新版本就push上遠端,其他人要這個新版本就pull下來自己電腦…一直循環,
完成版本控制。

【資料引用資訊】
google關鍵字:遠端多人合作開發-單分支
網址:https://kingofamani.gitbooks.io/git-teach/content/chapter_5/pull.html

第二部分:工具的使用


SourceTree的基本使用


1. SourceTree是什麼

  • 擁有可視化介面的項目版本控制軟體,適用於git項目管理
  • window、mac可用

2. 獲取項目代碼

1. 點擊克隆/新建
2. 在彈出框中輸入項目地址,http或者ssh地址都可以



如果箭頭指向的倉庫類型表明「這不是一個標準的Git倉庫」,可能是有以下原因
1) 項目地址獲取錯誤
2) 沒有項目訪問權限
3. 點擊「克隆」,等待項目克隆完成,完成後,左側只有一個分支master



克隆完成後,得到的是發布後的master源碼,如果想要獲取最新的正在開發中的源碼,需要對項目流進行初始化,點擊「Git工作流」



直接點「確定」,獲取develop分支源碼



開發任務都是在develop分支上完成的
4. 分支共有5種類型
1) master,最終發布版本,整個項目中有且只有一個
2) develop,項目的開發分支,原則上項目中有且只有一個
3) feature,功能分支,用於開發一個新的功能
4) release,預發布版本,介於develop和master之間的一個版本,主要用於測試
5) hotfix,修復補丁,用於修復master上的bug,直接作用於master
5. master和develop上文中已介紹過,當開發中需要增加一個新的功能時,可新建feature分支,用於增加新功能,並且不影響開發中的develop源碼,當新功能增加完成後,完成feature分支,將新功能合併到develop中,更新develop上的代碼
1) 新建feature。首先當前開發分支指向develop,點擊「Git工作流」






選擇「建立新的分支」



在預覽中可看到,feature分支是從develop分出的,輸入功能名稱,點擊確定,項目結構中增加feature分支,並且當前開發分支指向新建的feature分支



2) 在F_add_feature分支下進行開發任務,並提交



以上操作分別增加了feature_1、feature_2、feature_3文件,共提交3次,現項目文件夾下共三個文件



當切換為develop分支後,會發現,在develop下並沒有新增的三個文件,說明在feature下進行操作,並不影響develop分支源碼
3) 完成feature開發後,將feature中的源碼合併到develop分支。將當前分支指向F_add_feature分支,點擊「Git工作流」,選擇「完成功能」






預覽中,表明feature分支將合併到develop,點擊確定,進行提交合併,合併成功後



4) 需要再增加新的功能時,重複以上操作即可
5) 當多人協作開發時,可能會出現,不同人員對同一文件進行操作,從而引起合併衝突,對這種情況進行模擬,在當前新建兩個feature,分別對feature_1文件進行修改,然後分別合併



feature_1在feature_1.txt下做如下操作
feature_2在feature_1.txt下做如下操作



先後合併F_feature_1和F_feature_2,會出現衝突



點擊close,查看未提交的更改,提示feature_1.txt出現衝突,



打開feature_1.txt



出現<<<<<<< HEAD、=======、>>>>>>> feature/F_feature_2,HEAD和=號之間表示當前分支下的代碼,=號和>>>>>>> feature/F_feature_2之間表示要合併的分支下的代碼,>>>>>>> feature/F_feature_2表示了要合併的分支的分支名稱,
根據情況區分要保留的代碼,要刪除的代碼,最後再刪除<<<<<<< HEAD、=======、和>>>>>>> feature/F_feature_2



將修改的代碼再進行一次提交



一旦出現feature合併衝突,要合併的feature分支不會被刪除,如F_feature_2,確保合併沒有問題後,可手動刪除F_feature_2
6. 當開發到一定階段,可以發布測試版本時,可以從develop分支,建立release分支,進入預發布測試階段。點擊「Git工作流」,選擇「建立新的發布版本」




預覽中可以看到,release是從develop分出的,輸入發布版本名『R_v1.0』,點擊確定



R_v1.0為階段性發布版本,主要用於發布前進行測試,後續的開發工作仍舊在develop上進行,如果在測試過程中發現問題,直接在release上進行修改,修改完成後進行提交
7. 對release分支R_v1.0進行兩次修改後,測試完成,可以進行正式發布,在當前分支指向R_v1.0分支下,點擊「Git工作流」,選擇「完成發布版本」




在預覽中可以看到,R_v1.0向develop和master分別合併,點擊確定,完成正式發布。



完成合併後,默認指向develop為當前分支,master增加多個版本更新,將master分支推送到origin,完成線上發布
8. 正式版本發布後,develop可繼續進行後續開發,當正式版本出現問題時,需要進行問題的修改,可以在master分支建立修改補丁hotfix。將當前分支切換到master,點擊「Git工作流」,選擇「建立新的修復補丁」




預覽中hotfix分支是從master拉去出來的,輸入修復補丁名,點確定



在該分支下進行master的問題修改,修改完成後進行提交。當所有補丁問題修改完成後,點擊「Git工作流」,選擇「完成修復補丁」




預覽中,H_fix_1向master和develop分別合併,點擊確定,完成分支合併。



合併完成後,默認當前分支為develop,master分支有版本需要更新,當前分支切換為master,進行推送,完成補丁修復。
9. 在完成發布版本和完成修復補丁時,如果遇到衝突,可仿照上述5進行衝突修改,再進行後續操作
【資料引用資訊】
google關鍵字:SourceTree的基本使用

備註:
case1
先切換到dev分支,執行fetch,再切換回feature分支,對dev選項右鍵執行fetch到feature分支。

case2
刪除本地端feature分支,從遠端feature抓回本地端。