在開始這個議題之前,先來閒聊這個速食當道世代,對於一個全新或者普羅大眾沒聽過的名詞,在台灣大部分的職場工作者都沒有太多時間去了解真正的意義,多半都是透過新聞或是網路文章,其內容可能是帶有政治傾向、未經過考證,甚至是斷章取義。舉個早年的例子,「宅男」一詞來自日本的「御宅族」,是形容對特定文化有深入研究者,內容不限於當今的動漫類,也包含了電影、鐵道與格鬥等,但來到了台灣,經過媒體大肆報導後,變成了喜好二次元文化、不修邊幅與不善交際的男性。之後又延伸了「宅」這個字,只要不出門就是「宅」。

我並不是要說這樣是好或壞,這也是一種語言的自然演進,只是這個過程並不健康,且媒體經常性的誤用原本意義、再演化出新的意涵。今天的「安靜辭職」一詞,也有這種狀況。


安靜辭職一詞爆紅於 TikTok,zkchilling的這部影片,其意思並不是指默默得、低調的離職,而是內心對於這份工作崗位選擇做到工作的基本要求,不上也不下,能理解為60-70分鐘個區間,不再追求工作表現卓越,不競爭往上爬,但也不會愧對於公司,將更多的精力與心思用在下班後的生活上。

安靜辭職強調的是,不要因為過度在意工作而毀了自己的生活

我認為這個名詞會再度活躍在媒體上是拜Covid-19所賜,部分類型員工得以(被迫)在家遠距上班。自從在家上班後,少了通勤花費的時間與精力,讓很多人重新開始省思汲汲營營上班的意義,以及少了上下班的分壘所帶來的隱性延長工時。(這部分我也在之前文章- 在台灣的遠距上班為何窒礙難行提到過)。

愚民政策後,亞洲新興的控制手段:讓人民越忙碌於工作,就越少時間去思考、了解其他事物,便更好管理。

當我嘗試著用「安靜辭職」四個字進行搜索,仔細的看了一些文章後,蠻多文章的觀點都是非常極端,使用了假探討、真主觀的方式來洗腦讀者,任何事過於絕對肯定是有問題的。

公司老闆與主管必然不希望下屬是「安靜辭職」的狀態,在管理方面會顯得很無力且辛苦。這樣的員工很容易與「擺爛」劃上等號,甚至誇張一點會被形容為沒上進心,於是「內捲」就開始了,員工為了得到上司的好印象,開始努力加班、搶著做有價值的事,造成部門風氣越來越負面,長期來看整體士氣是很嚴重的打擊。

溫水煮青蛙的壞習慣是最難以發現的,當意識到時通常為時已晚

Read more »

本篇討論的自我介紹不是用在職場面試上,不過多少有點關聯。


想像一下,就在閱讀本文的時候,要你馬上進行簡單的的自我介紹,內容會是什麼?

「大家好,我是 Apie Chou,來自新竹,現在任職於某某公司的軟體工程師,興趣是攝影,很高興認識大家」

我想絕大多數人都是類似的內容,如果是這樣就沒辦法給人深刻的印象,你說完大家也跟著忘記你了。一個讓人印象深刻的自我介紹非常重要,如果採用上述那種方式,就完全錯失認識人的好機會。

所以所謂自我介紹,背後真正的目的是讓別人對你「印象深刻」。

在參加活動之前

首先,要搞清楚這個是什麼場合?

雖然不是每一個場合都有機會讓你說到話,但俗話說「機會是留給準備好的人」,如果麥克風突然遞到你的面前,你霎時從聽眾的身分轉為講者時,聆聽者可能是你的同儕、晚輩甚至是上市櫃老闆!仔細想想,平常有機會讓大家暫停手邊工作專心聽你說一分鐘的話嗎?

向上

Read more »

在物件導向的世界中,每一個階層的物件都有其定義、屬性與權限規範,因此在我們程式中常有物件與物件間的轉換。

在不使用今天介紹的工具之前,我們的程式碼很常會是這個樣子

1
2
3
4
5
6
7
8
9
10
var personModel = new PersonModel
{
Id = personDto.Id,
EMail = personDto.EMail,
Name = personDto.Name,
Gender = personDto.Gender,
Remark = personDto.Remark
};

restPersonService.DoOtherLogic(personModel);

這個東西會隨著每個階層都來一次,像是 service 層、repository 層等,會造成以下困擾:

  • 程式碼又臭又長
  • 阻礙閱讀
  • 模糊焦點,邏輯難查
  • 重複程式碼超多
  • 新增一個成員變數會改到死,容易遺漏

如果你的程式碼、工作的專案有類似狀況,那 AutoMapper 這個工具將非常適合你。


測試範例

以下都會用這兩個類別來做測試的範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class PersonDto
{
public string Id { get; set; }

public string FirstName { get; set; }

public string LastName { get; set; }

public string Remark { get; set; }
}

public class PersonModel
{
public string Id { get; set; }

public string Remark { get; set; }

public string FullName { get; set; }
}
Read more »

今天來聊聊輕鬆點話題,不知道大家有沒有看新聞的習慣,礙於台灣的電視台政治過於偏頗、內容又相當貧乏,墮落到網路文章都能當作新聞,大概是也沒啥資金去跑底層或是深層研究。

透過網路看新聞是當今最方便的管道了,但我本人實在很少直接使用手機,因為下面這種狀況:

alt
alt
alt

沒錯,滿滿的廣告!
剛點進去先吃一個滿版廣告,接著進入新聞頁面也還有 80% 的廣告,甚至是在內容觀看中再突然出現彈窗廣告,每個設計都是滿滿的阻礙原本功能使用,想要看個內容有這麼困難嗎?

使用者唯一能做的就是抵制,因此我才鮮少在手機上閱讀新聞。

偶然間發現了這個 app,看著平凡無奇的推薦截圖,還是決定給它個機會!沒想到使用後,完全命中我的需求,它就是 每日新聞

它有以下特點:

  • 介面真的非常陽春
  • THEME 很古老XDDD
  • 完全免費
  • 完全不需註冊
  • 完全不搜集個資
  • 資料源來自 google rss,所以也包含了各大網站!
  • 重點是:幫你去廣告!!

沒錯,他會幫你去除那些網站沒必要的廣告,讓你閱讀再也不用受到阻礙、不會再為了點那極小的取消叉叉而誤點廣告!!(當然還是有些遺漏的)

新聞列表:
alt

Read more »

日常生活中很多事物我們會一起做,例如買水果不會一次只買一種、也不會一次只買一顆,去水果攤一趟就是來回的時間成本。在程式中也一樣,我們透過任何形式接口、儲存體也不會一次只拿一筆資料,難道取得 100 筆資料會嘗試呼叫 100 次接口嗎?肯定是不會的。

另一種情境是反過來,接口允許批量呼叫,但想執行的量實在太大了,於是改成小批量執行,這也是今天想分享的內容。

在原本的程式中因為貪圖快速,想要進行分批執行時,很自然地使用了無限迴圈來做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static void RunInfLoop(int[] bigBatch)
{
const int batchSize = 10;
var skipCount = 0;

while (true)
{
var smallBatch = bigBatch.Skip(skipCount).Take(batchSize).ToArray();
if (smallBatch.Length == 0) break;

// DoMethod(smallBatch);

skipCount += BatchSize;
}
}

首先,這段程式是能夠運作沒錯,不過算是不夠嚴謹,當外界需要終止時,沒有人能夠控制這段無限迴圈直到它做完,所以外部被呼叫的儲存體或模組停止服務時,就只能等它噴錯噴到死了。比較正確的方式是加上 CancellationToken 來控制,不太清楚的也可以參考之前文章 CancellationToken 非同步取消工作

其次這樣執行方法很容易因為執行邏輯沒包裝好,導致整個程式進入無窮迴圈。

最後是這個方法不夠通用,若有多個地方要使用這個批次概念,就要寫很多份重複的 code。

於是我就自行調整了內容,加入了非同步呼叫、泛型、委派、參數、CancellationToken:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static async Task BatchExecute<T>(T[] bigBatch, Func<T[], Task> func, CancellationToken cancellationToken)
{
const int batchSize = 10;
var skipCount = 0;

while (!cancellationToken.IsCancellationRequested)
{
var smallBatch = bigBatch.Skip(skipCount).Take(batchSize).ToArray();

if (smallBatch.Length == 0) break;

await func(smallBatch);

skipCount += BatchSize;
}
}

這個方法委派了 func 去執行真正內容,每次丟進去的就是分好小批量的 smallBatch

Read more »

在 .Net Core 世界中,非同步執行變成最基本的內容,甚至現在大部分系統設計理念皆是如此,若你對多執行序稍有了解,應該能理解放出去的 task 是很難掌控跑去哪的。

這次要介紹的是 CancellationTokenCancellationTokenSource

CancellationToken

首先來看這個物件的 Property

  • CanBeCanceled: 此 token 是否可以被取消執行
  • CanllationRequested: 此 token 是否被請求取消
  • None: 直接使用空的 token,無法被取消或者請求取消
  • WaitHandle: 阻塞當前執行緒直到收到取消請求,再繼續執行

在使用各種建構方式,其屬性分別是甚麼內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var token = new CancellationToken();
Console.WriteLine($"CanBeCanceld:{token.CanBeCanceled}, IsCancellationRequested:{token.IsCancellationRequested}");

var tokenTrue = new CancellationToken(true);
Console.WriteLine($"CanBeCanceld:{tokenTrue.CanBeCanceled}, IsCancellationRequested:{tokenTrue.IsCancellationRequested}");

var tokenNone = CancellationToken.None;
Console.WriteLine($"CanBeCanceld:{tokenNone.CanBeCanceled}, IsCancellationRequested:{tokenNone.IsCancellationRequested}");

---
myctw.cc
CanBeCanceld:False, IsCancellationRequested:False
CanBeCanceld:True, IsCancellationRequested:True
CanBeCanceld:False, IsCancellationRequested:False

先前常見的無限執行方法:

1
2
3
4
5
6
7
8
9
10
public static void InfiniteLoop()
{
while(true)
{
if ( !cond ) break;

Console.WriteLine("Loop myctw.cc ..");
Thread.Sleep(1000);
}
}

現在也建議採用正規作法,透過 CancellationToken 來傳遞是否取消執行的訊息

Read more »

工程師,一個大部分人都有既定印象的職業,大概是不諳表達、溝通與賺得很多這種。

臺灣與大部分東方國家的教育方式類似,主要還是以灌入學生知識為主,其知識能否應用在職場,那又是另一個話題。相較於西方國家,更注重於個人想法、鼓勵你表達,不難猜想未來在職場上工作特質的差異,若是出了社會,工作時間大部分都不需要和人交談,那訓練的機會就更少了。雖然網路上有人戲稱工程師是回收業者,但有時候也不能全怪他們,今天如果是擔任業務這種需要大量與人交談的工作,那見人說人話、見鬼說鬼話也只是基本技巧而已吧!

作為一個軟體工程師,領域的技術、知識力是最基本的,然而諸如領導技巧、專案管理、向上管理或品質管理等都是不同面向的分支,這很考驗個人興趣與學習力。

誤區 1 - 資深人員就具備帶領新人的能力

每個人的人格特質不盡相同,有些是醉心於研究技術的,這類在職涯規劃上就不傾向需要擔任帶人的職位,而常見的錯誤就是將他派去帶領新人、團隊,很容易因為技術力落差太大而失去耐心,或是說話、應對方式不夠恰當,導致摧殘了一個可能具備潛力的同事。

誤區 2 - 比較早進公司的同事就能帶新人

我很常說一句話「聞道有先後、術業有專攻」,每個人都有各自擅長的領域,知識的學習也只是差異在誰先學習,熟稔公司工作流程也是,論先後是沒有高低優劣之分,公司派資深同事去指導,產出虧損會比派資歷尚淺的同事來的多,於是又衍伸出另一個問題,這位資歷尚淺的同仁具備怎樣的領導力呢?或者是說相關能力是否足夠與洽地?


在國際與職場上,我非完全認同儒家思想,但有一點是非常重要的「因材施教」。

正因為每個人的人格特質與心理耐受度不同,面對所有新人採用相同指導法是不正確的。我曾看過懶得管你型,就是非常被動,不主動提問的話,就不會跟新人說話; 權威型,需要像軍中階級就是一切的制度來管理,任何的犯錯都是不被允許,否則會被罵到狗血淋頭那種; 照顧BABY型,什麼事情都直接幫你處理好,連自己動手的機會都不多; 技術至上型,你技術力差,說出來的話都不重要,甚至是直接被否定。概述幾種即可,人與人之間的碰撞會產生無限多種可能。

Read more »

今天在 code review 修改資料腳本時,對於 $regex 查找條件覺得哪裡怪怪的,於是實際行了一下,果然找到一些貓膩。

由於 MongoDB 相關資料顯示與操作都是使用 Single quote ` 或是 Double quote"",這很容易在 $regex 查詢條件中混淆進而造成不預期的後果。


準備測試資料

1
2
3
4
db.getCollection('reg-test').insertMany([
{field: "myctw.cc [-] document8"},
{field: "myctw.cc - document9"},
])

查詢包含 [ 的資料

我們希望查詢出包含 [ 的關鍵字,前後內容不拘。

於是寫出了這樣的語法 {field: { $regex: ".*\[.*", $options: "i" }}

還自以為很了解的加上了 \ 來作為 [ 的跳脫字元,結果得到 mongo 無情回絕!

Read more »

這篇文章是 MongoDB Developer 考證照的重點,翻譯與整理自官方的Study Guide,我是當作考前快速複習使用,至少知道每一個項目的內容是什麼。

建議學習方式是直接到官方免費線上課程 MongoDB University,上課時間彈性自由,透過實做與測驗讓你印象更深刻。

考取證照:MongoDB Developer Certification

開發者證照課程

  • M001 MongoDB Basics
  • M103 Basic Cluster Administration
  • M121 Aggregation Framework
  • M220 MongoDB for Developers
  • M201 MongoDB Performance
  • M320 MongoDB Data Modeling

CRUD

  • CRUD 語法,以及如何使用
  • MongoDB 支援的資料型別
  • 不會考語法記憶,但需要知道正確語法長相、必填或選填參數。

Create

  • insert(insert, insertOne, insertMany), update, upsert, save
  • Bulk insert(ordered, unordered)
  • _id 對於 CRUD 的影響
  • ObjectId 建立與應用
Read more »

時光飛逝,距離上次寫 MongoDB 大版本號更新 MongoDB 5.0 新功能 已經過了一年,在前幾天 MongoDB 6.0 正式上線,我們來看看提供了什麼樣的功能,以及官方列出 7 個需要升級到 6.0 的原因。(技術實作面,如運算子使用會在之後再發文紀錄)

本文依舊是 blog 的精簡與快速風格,若不習慣可參閱原文 7 Big Reasons to Upgrade to MongoDB 6.0


  • 時間序列集合(Time series collection)更多支援。這邊先描述了 5.1~5.3 的特性,我們也來 recap 一下這些功能

    • 5.1: 支援 Sharding!
    • 5.2: Columnar compression 新的資料壓縮技術,號稱比市面上常用的都好,壓縮效率達 70%
    • 5.3: Densification and gap-filling,緻密化與填補空隙,看中文是絕對不會懂的,簡單來說就是填補空缺資料,使得時間序列資料不在統計上不會突然出現斷點。使用場景像是停機或是設備問題等導致資料缺少,就能透過 Aggregation 內的 $densify$fill 階段來補全模擬資料。
    • 6.0: 支援 Compound Index,可真是千呼萬喚,之前覺得使用時間序列集合最大問題點在於查詢,在 6.0 終於支援了,至少有了 POC 的入門磚。
  • Better way to build Event-driven architecture。早期可以透過 API 去訂閱 oplog 的改變,使得 application 得到變動的通知,現在更加強了這個功能。

    • 文件的修改、刪除都能得知狀態以及被刪除整份文件
    • 不僅是 DML,現在連 DDL 也支援
  • 更方便的查詢$lookup, $graphlookup 在少數量效能快 5-10倍,在大數量則快到 2倍 以上,不過很可惜官方沒說何謂 “少數量”、”大數量”,但整體是提高效能的。另一個非常重要的就是這兩個也支援在 Sharding 上使用囉!有要考證照的要特別留意。

  • 更多的運算子,更少的工。稍微掃了一下新增的運算子,真的是超棒的,節省了開發者很多工,不過內容比較多,完整的介紹之後再寫一篇。簡單來說像是 First, Last, Top n 等等這種其他程式或資料庫的語法也支援啦!

  • Replica 新節點的初始同步加快

    • 企業版支援了檔案複製功能,比原本資料同步快四倍
    • Sharding 預設的 Chunk size 從 64 -> 128MB
  • 機敏資料加密

    • 現在在寫入硬碟之前也能壓縮且加密機敏資料
    • 查詢加密資料(Preivew)及效能提升,同時確保整個生命週期都是加密的
  • 查詢體驗與無縫資料同步

    • Atlas 支援 Facet
    • FacetCount 效能最高快到 100 倍
    • 支援 Cluster 對 Cluster 的資料同步,在營運環境搬移、資料備份等需求能夠更便捷。

以上就是 6.0 的新功能,綜觀蠻吸引人的,尤其效能提升與減少開發的工。初期極度有可能會有 bug,還是要經過一段時間運行與效能評估再做決定了。

Read more »