• 以下都以電子書代表(書與雜誌)

不知道大家在網路購買電子書有甚麼樣的期待?

這個商品不算物理上真實存在,且沒有數量限制的問題,理論上購買後就能夠直接閱讀,至少絕大多數的電子書網站是如此服務的。


前陣子在經理人網站有個非常糟糕的購買體驗,首先我在入口網站註冊了會員,點擊了訂雜誌按鈕,導到訂購頁面且選擇好商品後,付費頁面建議我登入會員,方便訂單管理。

此時我心裡納悶,不是剛剛已經完成註冊且登入了嗎?為什麼會說我沒登入?

於是又嘗試登入一次,系統只有不斷的告訴我帳號或密碼無效的。本能的看了一下網域,嗯..不同網域啊..,背後的會員資料庫可能不同,於是我再用相同帳號去註冊,果然註冊成功了。

用戶體驗到這兒,已經讓我打了十足的退堂鼓了。不同系統還能理解,商業模式都是陸續在擴展的,但系統給我點明確提示要新註冊用戶會比較順暢。

成功付款後,等待了幾分鐘,滿心期待的打開 Readmoo 網站(對的,電子書功能則是委外合作 Readmoo,我買一本電子雜誌需要註冊到三個網站),卻發現書櫃內沒有雜誌!這不對吧!會不會是遇上什麼差錯,想到要找客服就心累。

閱讀全文 »

C# 擴充方法是蠻早期提供的功能,讓指定型別的物件能夠使用額外自訂的方法,將不需要接露的部分隱藏、簡化流程程式碼。

  • 擴充方法必須定義在靜態類別內的靜態方法
  • 擴充方法至少需要一個參數,參數型別之前必須加上 this 關鍵字

範例

假設系統常使用 decimal 型別,且需要固定轉換成小數位四位,一般是這樣

1
2
3
decimal a = 0.1234567m;
Console.WriteLine(a.ToString("f4"));
// 0.1235

這樣做沒問題也達到需求,但會有個小缺點,就是整個系統會四處存在這種 hard code,除了不簡潔之外,萬一需求要改成五位,是不是就很麻煩了?

收斂

這種特殊功能的方法其實可以透過靜態類別來處理,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static class DomainConvertHelper
{
public static string ConvertToF4(decimal val)
{
return val.ToString("f4");
}
}

public static void Main()
{
decimal a = 0.1234567m;
Console.WriteLine(DomainConvertHelper.ConvertToF4(a));
}

// 0.1235
閱讀全文 »

本文討論的範圍僅限軟體開發業為主的產業,並不適用其他產業。


WFH 推手

Covid-19 在全球爆發以來,台灣經歷了兩波大的感染。第一次疫苗覆蓋率極低的時期,當時,政府果斷宣布封城,非必要不得外出,能夠遠距的也都遠距上班了(Work From Home)。第二次則是現在,每天數萬人的感染,按照這速度,染疫數應該是指數上去。這次,政府沒再宣佈封城,部分公司則自主宣布 WFH 的規則。

台灣獨有特色

要探討 WFH 這個問題之前,個人認為還有一個點非常重要。台灣係從勞力密集的製造業起家,才到後來的軟體與半導體,很多擁有遠見與財力的老闆們對於有實體產出的觀念還是根深蒂固,深深認為只有實體產品才能夠賺到錢。

證明的方式很簡單,嘗試著去外包網站看一輪就知道,很多業主只想花個數萬到數十萬不等,就想完成龐大的需求與功能,最常見的大概就是後台管理系統或者是電商網站。當然,這個技術水深有時連業內的工程師也不會理解,因為沒這個經驗自然沒這個能力,人是無法想像未知事物的。

第二個證明方式更簡單,可以看看各位工程師電腦內的所有軟體是不是正版?不敢說國外月亮有多圓,但在亞洲,公司都無法提供最基本的合法開發環境。Windows? Visual Studio? Oracle? Office? 小至文字編輯器可能都不是正版。為什麼這些東西可以不是官方授權的呢?難道工廠可以使用來路不明的機台製造產品嗎?可能連安全性和品質都是問題了,但軟體不是,軟體就是個..看不到的東西。

WFH 是什麼樣的生活

早上可以多賴個半小時床,悠閒的沖杯咖啡開啟新的一天。有別於前往辦公室的日子,每天需要至少一個半小時的時間在盥洗與通勤上,有的人是拼命的划手機,把握屬於自己的歡樂時光、有的是緊盯開盤後的動向,有的則是閉目養神,而把握看書進修時間的人則是少見。相比之下,前者更甚吸引人。

閱讀全文 »

2022/09/30 Update
最近重新翻出這篇文章,覺得當初撰寫時有些不夠明確與細節,特地再更新一下內容


寫這一篇是想到了當年對於時間的設計,還特地回頭翻了以前寫的文章 MongoDB 使用、設計時間欄位小心得

又經過一年的磨練,對於之前的設計又有點想法想來聊聊。

起因

我們使用的語言是 .Net Core,設計的系統為跨國使用,因此時區問題是無法避免的。系統中一律使用 C# DateTimeOffset,直接存進 MongoDB 會變成一個陣列(可以參考上面的連結),除了使用上稍微不方便、時區功能也是無用的儲存(因為系統端通常都是無時區,到了呈現端才會轉換),在查詢上也會稍微有差距。

接著嘗試了 C# DateTime,進了 MongoDB 後就是 Date 格式,很好處理掉上面的問題,但另一個更致命的是,商業產品上對於毫秒的精確度很高,而 Date 最多只支援三位毫秒,完全不服使用情境。

最後選用了 C# 的 UtcTick,這樣好處是儲存體都是 UTC 時間,對外溝通都一率使用 UTC,很符合我們的技術棧 gRPC (時間皆是用 timestamp)。很好的解決了當時的所有問題,反正客戶端在哪個時區,再進行轉換就好; 最大的不便莫過於可讀性了,但暫時沒有更好的解決方案。

1
Timestamp 是 Unix 時間,`1970年1月1日00:00:00 UTC` 為時間原點
閱讀全文 »

新增欄位

新增欄位目前我都使用 $set居多,已經很少在用 $addFields

使用其他欄位的資料

在實務上我們很常有類似的需求或查詢,根據已經存在的資料中的欄位A,經過運算後存在欄位B,例如:

1
2
3
4
5
{
_id: "Y000000001",
"LastName": "Chou",
"FirstName": "MingYiPie"
}

在功能上線後,發現某個頁面只需要呈現完整名字,也就是 FirstName + 空格 + LastName,礙於一些”特殊”原因,只需要在資料庫中儲存成一個欄位,如下:

1
2
3
4
{
_id: "Y000000001",
"FullName": "MingYiPie Chou"
}

這時候要上個 Data Patch 將所有資料改成上述格式該怎麼做?

思路

  • 取出 LastName, FirstName 組合在一起
  • 寫入該筆資料
  • 刪除 LastName, FirstName
閱讀全文 »

我們在寫程式中,絕對會需要撰寫測試,而很多測試情境需要使用假資料。

以下是一個 People 類別以及兩個 enum

1
2
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
public class People
{
public string Id { get; set; }

public string Name { get; set; }

public string EMail { get; set; }

public int Age { get; set; }

public int Height { get; set; }

public decimal TotalAssets { get; set; }

public Gender Gender { get; set; }

public SexualOrientation SexualOrientation { get; set; }
}

public enum Gender
{
Male = 0,
Female = 1
}

public enum SexualOrientation
{
Heterosexual = 0,
Homosexual = 1,
Bisexual = 2
}

以往我們都是這樣產生假資料的…

1
2
3
4
5
6
7
8
9
10
11
var mysterious = new People
{
Id = "Y000000001",
Name = "MidSquare",
EMail = "[email protected]",
Age = 143,
Height = 170,
TotalAssets = 999999999999M,
Gender = Gender.Male,
SexualOrientation = SexualOrientation.Heterosexual
};

要隨機性的話就會開始使用 random 的方式,但會有一些問題

  • 資料不夠隨機
  • 各種類別的屬性都必須個別刻出隨機的方法
  • CODE 很多
  • 產生假資料很難客製化條件

今天要介紹的是 Bogus,是 DotNet 的產生假資料工具,其功能與類型真的是廣泛到不可思議,有興趣的可以去看看他的 Github

首先透過 nuget 安裝 Bogus,接著程式碼如下:

閱讀全文 »

在之前文章有介紹過 MongoDB IDE。2021 iThome 鐵人賽 - DAY3 MongoDB 連線與 IDE

我本身在使用時都是雙刀流 robo 3t + compass,簡單查詢時就開啟 robo 3t,速度快操作簡單。近日在與同事分享此 IDE 時發現官網已經不再提供了,取而代之的是 studio 3t,想說它極力推薦免費使用,便請同事先裝這個練習一下。

殊不知

如同其他軟體一樣,都是號稱免費使用,卻必須要註冊才能使用。
我並不是說他們無償提供免費是應該的,只是這種事情沒有事先告知,等到下載、安裝完成後,卻發現要先行註冊,感覺真的不太好啊~


robo 3t 本身還是開源專案,仍然可以從 github 下載使用,只是僅支援到 MongoDB 4.2 版本囉!對目前的使用還不礙事,於是想繼續免費使用的還是可以透在這裡下載喔!

閱讀全文 »

C# 在 7,8,9 陸續加了很多 Pattern Matching 的東西,讓你的程式碼能夠再簡潔與彈性化一點(其實是我沒更新技術、有些語法糖看不懂,於是就有了這篇)。Pattern 數量不少,但看過幾次就會使用了,是很簡單易學的語言呢!!(招生)


Logic pattern

  • 判斷是否為 null。

以前我們都是直接使用 ==

1
2
3
4
5
6
7
8
9
10
11


if (sample == null)
{
Console.WriteLine("Sample is null");
}
else
{
Console.WriteLine("Sample is NOT null");
}

新版的可以直接使用 is 以及 is not

1
2
3
if (sample is null)

if (sample is not null)

Parenthesized pattern

其實算是上面的延伸,就看商務需求各自發揮了

閱讀全文 »

這本書算是蠻暢銷的,應該有其價值在,不過跟我預期的實在落差很大。原本以為是一個提點你如何找尋工作上適合的位置,結果大概只有第一章有「提到」,接下來的二三四章都是教你「如何工作」。我不是否定本書觀點,裡面也有很多值得思考的項目,後面會有一點筆記,只是內容與書名有極大的落差,讓我很失望。

想再次強調這篇文章只是隨興的筆記,並非完整的精華摘要,有些我已經知道或理解的,就不會特別列出來了


CH1

強調找尋自己的特長,而特長是會轉移、變動,且隨時間年紀而不同的。

  • 不要低估自己,因為消極面對決策而減少面對失敗的話,會讓自己過於自卑
  • 確認自己的目標,將之分為多個小項目,逐漸邁進
  • 生命中最重要的決定:
    • 你將用甚麼方式來謀生?甚麼職業?
    • 你將朝甚麼方向發展?找到一個立足點、熱愛的工作開始前進
    • 你將以甚麼方式工作?是積極還消極..等

CH2

  • 不要以社會地位、威望、體面、金錢等來評估一個工作的位置
  • 每個人都有選擇的權利!你的任何抉擇都是在選擇
  • 每一個位置都有其價值,如果不能給老闆創造價值,那就有可能失去工作的地位
  • 選擇最佳位置而非最佳行業
  • 每個人生階段都有最佳位置
  • 每一個工作都是值得尊敬的,沒人能夠貶低你,關鍵在於你如何看待自己的工作

CH3

  • 老闆眼中每個位置都有其價值,也絕對不會是一人獨占
  • 在甚麼位置就該做好那個位置的本分,創造價值
  • 主動、自發的工作
  • 自律,即使無人監管下,也要如同平常一樣勤奮
  • 別帶情緒工作。也許我們不能控制環境,但我們能夠控制面對環境的反應
閱讀全文 »

2022/10/03 Updated…

看到以前的文章,發現把這功能想得太複雜了,通常在批量調整索引時,數量也不會太多,直接從系統取得 Index 名稱,再進行刪除或建立即可。

1
2
3
4
5
db.getCollection("your.collection").getIndexes().forEach(doc => {
if(doc.name.indexOf("_id") != -1) return;
// or if(doc.name == "_id_" ) return;
db.getCollection("your.collection").dropIndex(doc.name);
});

非常簡單明瞭要做什麼。
雖然之前寫的做法可以開發出不同功能,不過簡單操作的話,上面這一段即可。


最近因為部署有些狀況,反而需要因應各環境 index 不同,分別有不同的調整,查了一下 MongoDB 並沒有類似的語法,只要是

  • Create 時名稱重複
  • Drop 不存在的 index

都會噴錯,導致後續語法不能繼續執行,因此自己寫了一個概念類似 upsert index 或者像是 insert ignore 的方法。

思路

  • 建立時,遇到
    • 名稱不重複:
      • 欄位一樣,可刪除舊的或者忽略新的
      • 欄位不同,建立新的
    • 名稱重複:
      • 欄位一樣,略過此建立
      • 欄位不同,先 drop 舊的再建新的
閱讀全文 »