維護作業

工作近況

上半年 Q2 即將結束,打雜工作也逐漸到了尾聲,不斷地在產品使用的細節上著墨,使用者介面、顯示效果、錯誤反饋,這些基礎工作差不多是大家不願意做的打雜。一點一滴的累積,將缺少的細節設計遞補上,減少溝通成本,能不透過研發部門或文件來除錯,就可以擺脫三不五時 Microsoft Teams 響起,不然老是向其他部門請求技術支援,卻又老是打回來問我,那訊息可說是回應不完。

有時候,交代工作下去給底下的人,彼此覺得很難開發,老是花一大把的時間去改寫,互相抱怨也是浪費彼此時間。工作包山包海,功能日新增強,操作複雜到開發人員也不堪負荷,解決之道便是改善流程。將每一步拆分得當,可讓操作複雜度下降,連帶介面效能也會有所改善,可謂製程的精隨,相關人員也能專注在自身的開發項目上。少了改寫時間,也不用處理那些過度工程的討論。

五月中開始討論調薪、人員調度、組織等問題,非常時刻就沒有寫扣的時間。作為管理職要了解每一個員工的特質,還要去協調職涯規劃,將適任與不適任的工作再次分配。處理這些事情時,都會想著人類無法難控制。實務上不需要技術狂熱分子,唯有解決當前之急,才有辦法去研發長遠目標。若老是想著造火箭,而過程中的技術卻不能應用在相關項目上,就變成了純燒錢的項目,時候一到就會被檢討。

「本來依靠他人這件事本身就不現實」

沒能力看懂別人寫的、沒能力分析別人或自身的錯誤、沒能力選擇合適的工具,這普遍的現象卻發生在菜鳥與老鳥身上,要說這世代的的問題?還是團隊並沒有朝著同一個目標前進?這幾個月都在挑戰認知,與以往自己奮力向前的情況不同。當一般開發人員,倒也是輕鬆自在,要求自身比要求他人簡單多了。

持續新進的菜鳥中,還遇到有人跑來問我是不是寫部落格的 Morris,沒想到隔了五年的落差,還有人認識我這個離開戰場的老屁股。思維逐漸工程化,設計算法偏向通用的限制,要去吹毛求疵的數學遊戲,看起來已經操不動了。

最後一個消息,工作將於七月升職為 T5 Senior Software Engineering Manager,相較於去年升 T4 Principal 與 Manager,只是換名稱的同一個位階,吃力不討好的工作,還是做了一年。升職速度與加薪幅度還是不如預期,不過幾個月來的努力有被上頭看見,那就算是一件好事,不需自己寫報告去做 promotion。

資產維護作業

資產維護作業,簡稱「打掃」連假不知道要忙什麼?那就是打掃莫屬。接著,又花了幾個星期去看大台北的房子,

Q:浴室怎麼沒有面盆 (板橋)
房仲:報告先生,因為漏水無法解決,拆了

Q:不要機械車位 (板橋)
房仲:這只有左右移動的,不是一般機械車位

Q:要坡道平面 (板橋)
房仲:B1 到 B2 汽車搭電梯,但還是平面車位

Q:這頂天櫃子怎麼都無法全開,全部卡到消防偵測器 (新店)
房仲:…

Q:為什麼屋主沒有車位權狀,一直在繳車位管理費 (信義區)
房仲:屋主找不到權狀,也不知道有沒有車位

Q:為什麼老華廈物件,土地持份不到三坪 (中正區)
房仲:當時權狀處理複雜,沒有完全過戶成功

荒唐指數滿點,挑老屋得評估的項目實在太多,修繕成本先抓兩百萬上去。永慶各種推薦的 A 案雷又雷,還浪費時間去看。可謂好的房仲幫你省時間,爛的房仲帶你看事故。

伴隨著兩幅一千片拼圖的拼圖耗時半年完成,女友的台北尋房故事也告一段落,六月初開始試住一周,有一種重返頂加租房的苦日子,在冷氣熱浪的台北市,走在路上都有一種荒漠感。而空當昏暗的房裡,有著歲月的味道。

繁雜的工作之餘,逛廚具、家電、裝潢,再與設計師商量。當初買房都沒這麼煩惱過,再次體驗,看看薪水一般怎麼變成喜歡的樣子。不知道哪一天,薪水也能讓我在台北買房無壓力。

Read More +

Company Ghost Story 公司鬼故事 15

Redundant Debug Message

1
2
3
class Placement {
Image image = new BufferedImage(1024, 768); // unused
}

Naming

1
2
class Colorizer { setDrawDevice(Device), removeDrawDevice(Device)}
// setDisplay(Device, boolean)

Inheritance

1
2
class XXXPanel { Panel getPanel(); }
// why not extends Panel

String Equal

1
2
if (input.contains("yes"))
// ???, equals???

Key in Condition

1
2
3
4
5
6
7
void drawTick(Color axisColor) {
if (color.equals(Color.RED))
dx++;
else
dy++;
}
// Color as key? why not pass enum Axis

Out-of-Knowledge in Library

1
2
3
4
class AbstractTableViewRenderer {
EDA_DIE_ONLY_RENDER dieRender;
}
// don't put your shit on UI library

Over-overloading for Lambda

1
2
3
4
5
6
class AbstractTableView {
public void with(MouseInterface)
public void with(TextInterface)
public void with(IconInterface)
}
// overloading is not for heterogeneous

Oversize

1
2
long degree; // [0, 360)
// oooooooooooooover-size

Missing Else

1
2
3
4
if (geom instanceof Circle) { renderAsBall((Circle) geom); }
else if (geom instanceof Oblong) { if (type == ball) renderAsCylinder(geom);} // new feature
else renderAsPoly(geom.toPoly());
// fuckup, default as polygon, where is your else
1
2
3
4
setProperty(Object dbo, String name, Object val) {
if ("group".equals(name)) Group.set(dbo, val);
}
// where is your else and exception

OK, then Action

1
2
3
4
buttonOK.setOnAction(e -> apply());
void apply() {...; rebuildModel();}
slider.setOnChange(e -> rebuildModel()); // new feature
// our performance is gone by you

Listener

1
2
3
4
void setDisplay(...) {
fireProperytChange("SetDisplay");
}
// ... property is display, not the method name

Time-consuming Message

1
2
Object.requireNotNull(number, "The number is not illegal by " format + " with" + ... context);
// don't compose the error message, construct it on demand.

Time-consuming Render

1
2
3
4
5
class ListRenderer {
void render(ListItem e) {
ImageIO.read(getImagePath(e.getValue().getType()));
}
}

Crazy UI Design

1
2
3
4
5
6
7
|------------------|
| Chooser |
+------------------+
| [ComboBox] | # 10^6 objects
| [Cancel] [OK] |
+------------------+
# tell me, how do you pick
Read More +

規劃 ‧ 生活

工作近況

產品整合事業越做越大,跨產品的問題也越來越複雜,合作關係要牽涉各種不同層級的人。正可謂辦公室政治,彼此都不願意付出額外的資源應付,開會顯得明爭暗鬥。

即便很理所當然的修改項目,也指點出代碼要怎麼修正,溝通上盡是不滿意的答覆。望著其他部門的資源調度,重複且冗餘的決策滿是困惑,不知風險評估與商業價值到底是怎麼看待的。

解決多產品整合使用,遇到應用層級的架構問題,一度被歸類在我們這邊,開會一直被檢討。花了好幾陣子分析,得知問題壓根不在我們這邊,即使不牽涉我們的產品,問題早就存在很久。結果,即便圖文解說,還在互踢皮球,老是被問無關緊要的問題,明明闡述操作方法 A 出事,結果一直被說方法 B 沒問題,那樣的鬼打牆。不想解決非常態性問題是人之常情,上頭明確要求要解決的項目,跟我辯也沒用。

錄取新人上,除了面試人選上的問題,也得花時間在處理薪資結構上,看著 MTK、TSMC 那樣的分紅獎勵,聽著同事下屬們的抱怨,自己也是求償無門,分紅也不是說有就有。不自覺地感傷了起來,心灰意冷。

若每一年多少能拿到 RSU 股票,那心情估計也不是的問題,老說新產品上檯面賣錢,薪資上也沒有什麼變化。升主管會立即調薪?可以調到嚇死人的價碼?大部分的人還是有很大的幻想,當真正面對的時候,就會知道公司運作可不是那一回事。

自然也會想朝著其他產業投石問路,整包的薪資價碼看起來不錯,也值得一談。但是海的另一側是可以去的地方嗎?考慮到國情要素、家人的顧慮,好像不值得冒風險去做。就好像高薪的博奕產業,總會與自身的價值倫理產生衝突。

購車狀況

過年前回花蓮處理銀行事務,銀行行長順便諮詢訂車折扣,最後問了整個東部營業所。一想到台北的營業所,看起來生意太好,服務品質也隨之下降,NX 改車型也沒準確做到,導致延誤交車。詢問年底交車能不能折扣,只說一句「沒有」,只好改營業所訂車,那時願意給折扣。即便折扣多了一些,一開始就不老實給優惠,我看來是回老鄉訂車給認識的朋友賺吧。以免省了小錢,花了大錢。

礙於駕車技術有限、非通勤需求、以及其餘個人需求,老是被補了一刀「小車」,至於那一台車到底值不值得,這部分也得釋懷了。只有這樣的薪水,也不能妄想什麼。比起紙上談兵,勇於實踐,即便完美解法與現實不符,認清事實地踏實生活。

大台北尋屋

跟著女友跑了好幾輪的台北看屋,新莊、板橋、新店、中正、中山都走遍了一輪。現在看房還得在大樓下面領號碼牌,像極了上摩天大樓欣賞風景。這麼多人可以隨手拋出個三千萬,殺都不殺價?相較於當時買林口房子的狀況,有著截然不同的處理方式。每一間都動輒兩、三千萬,高樓大廈與複雜的交通,頓覺得山上買房特別簡單。

一開始習慣住台北的人,估計也離不開那裏的生活型態。身為一個鄉下野孩子,恨不得離開台北。那些的生活娛樂,並不能給予什麼心靈滋潤,更有機會被房貸弄上身心枷鎖。不少案子,有著獨特的生活起居規劃、高額的基礎開銷、複雜的格局、繁多的設施、夾在無法交流的人群中,有一種說不過去的窒息感。即便這樣,房子還是炙手可熱,內心的各種批判顯得格格不入。

賣房的各種社會成功人士,因婚姻問題、新置產等問題而脫手老房。再看到房屋價碼上,一年漲三百萬,甚至有的屋主多喊漲一千萬。若一部分人這樣賺錢的,認真工作也不過投資。那長期下來,就是更加剝削其他人的未來價值,窮還是選擇窮的生活方式。

一房精實、兩房務實、三房踏實、四房絕食

Read More +

二八 ‧ 年尾

工作近況

產品需求步入穩定,緊急的要求逐漸變少,但零星的硬體環境問題變多,這一類也不知道要怎麼交付給什麼人,只能硬著頭皮去做,甚至到自己要客制化 JDK 去解決問題,問題並不難,但網路上能用的資源很少,大部分只是花個時間解決那幾行程式小毛病。在 EDA 的場景下,大多的應用都不會接觸到如此大量資料、互動性高的桌面應用、有限的工作環境、穩定的作業系統。因此,相關資料少之又少,只能透過不斷地抽象化問題去找答案。

面試情況

陸陸續續收了不少來自 104 的履歷,普遍性都只是刷題達人。若問起最近讀了什麼書,當有一部分人答起《Cracking the Coding Interview》,都會懷疑只是剛好命中書中的內容,以至於在隨後問起簡單的問題時,大多都會想往極為教科書上的標準答案去想,現實世界並不是如此,有時只需要先把功能做出來,至於有沒有完美的複雜度,那又是另一個回事。別因為想不到完美的解法,而感到困惑,有信心地拿出自己擁有的武器解決問題,就只是這樣的要求。

有時不考慮看最後碩士的成績單,碩士班課程很多並不用寫程式,大多科目都像機器學習、人工智慧、深度學習、區塊鏈等,在高階語言流程上玩弄。對於 EDA 工作環境的話,那些毫無用武之地,這個產業就像傳統產業,已經有著二、三十年的歷史。調閱大學成績單,滿是基礎科目在及格邊緣的案例,在這樣的情況下,信任度便是問號。除了履歷上所列出的條目,沒有其他作品或著作,要在短短時間內認識一個人,只有推薦制度比較可靠。最終,基本上都會拒絕從 104 來的人選。也有收到一些經驗老道的特殊案例,許多四、五十歲的老大哥,工作經驗與年齡不符,好幾份工作都沒有超過三個月,原來世道如此險惡。

管理體驗

持續督促同事,那些應該在碩士班學習到的能力,基礎的寫作能力與閱讀能力,細心與自我研究,並超出管理指定的工作項目。不時,常常感慨「難道,以前我是這樣子的嗎?」對此毫無印象,也許是自己老了,也許時代變了,那都不得而知了。並非自願升上管理階級,但轉換職位的過程中,還是得下去寫比較複雜的部份、做一些技術指導,並不是只動一張嘴工作。許多管理階級要做的文書作業—評鑑評分制度,也開始接踵而來,處理請假事宜、採購設備等。

學校聯繫

接連收到幾次來自高中母校的電話,由以前資訊老師聯繫過來,想要我指導學弟相關程式問題,看著十年前拋出的程式設計問題,現在的學弟還能從中練習成長,原來以前的我做了不少事,而學校老師也還記得我。那些滿滿的黑歷史文章,看起來相當稚嫩。

年末時,有高中同學被班級導師邀回去分享經驗,而我這忙碌的小社畜自然不在其中,沒有這麼多悠哉的時間進行回校講座。過年也被老爸提前抓回去,說是要跟花中學弟一對一經驗談,同樣是考大學的成績不好,那時面臨到的極大壓力,要怎麼一路走過來,現在的我也沒有好的答案,至於我現在算不算過得好,心中仍沒有個底,畢竟每個人都不盡相同。

這回收到老師的邀請,要在二零二二的一月底寒訓回去跟資訊組的學弟妹們分享,至於為什麼合併花女一起,似乎只能在當下明白了。目前投影片的部分也準備了 連接,標題還在構思、內容還持續充實。沒有辦法像其他講者一樣,做著潮流項目 (如 NFT、比特幣、區塊鏈、機器學習、深度學習或人工智慧),只有一些老老的工作項目,倍感突兀。

生活歷程

處理完房子也過了快一年,大老婆還沒有娶,便開始著手小老婆,在十二月初跑去台北的 Lexus 營業所訂下了 NX 休旅車,最後考慮一次買到 NX 350 f sport,交車時間估計可以直接推到明年的生日禮物,恰好能持續堅持零貸款的生活原則。很多人也許會覺得為什麼要一次買這麼貴,想了想人生就這麼短,顧自己生命安全為主,也不要後悔做一些折衷的行為,好好地體驗人生。那為什麼不買歐系車?在臺灣水土不服的機率太大,還是買相近環境的車款吧,就像我們不該買俄羅斯產的汽車一樣,因為他們肯定沒有考慮散熱的設計,若是跑來這副熱帶島嶼國家,肯定毛病不少。

九月多邂逅了一個妹子,這中間的點點滴滴都在《批改娘串起得那段經歷》系列文中,有歡樂有哀愁,等到時機成熟,才會公開出來。在年尾慶生旅遊時,稱說「若寫到了二十篇,就跟我求婚」話可不能說這麼滿的,二十篇這個 KPI 要說難不難呢?不幸地,下一秒話就被收回了。

「在互相幫助的日子裡漸漸萌生戀情」—《無職轉生》

Read More +

《獻給某工程師的情書》

「有些情書,是無法唸出來的。」—《獻給某工程師的情書》

背景

近十多年前,看了一段來自 Matrix67 的一篇文章,並寫下了紀錄。那時,正值大二的我,對於 IOCCC 和 C 語言不夠了解,只做為一個基礎的認識並且記錄下,總幻想著以後有個機會用用。如今,在這個年底,一場邂逅,讓我想起了那好久好久以前的構思。

木製卡片之一

並且做成了一張木製卡片,最後挑了兩家廠商去做,擔心顯示的字型與雷雕技術之間造成難以成色的問題,因此在挑選字型時,也是偏向工業用字型。至於,被抱怨「編譯不起來」,那又是另一個故事了。

規格介紹

編譯

1
2
gcc main.c -o main
./main

限制

  • 這封情書只能容納 84 個字元
  • 字元只能以 ASCII 的形式儲存
  • 只能有 32 種不同字元。
  • ASCII 值會被忽略 < 36,即不可視字元以及特殊符號 !"#

原理說明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
main(h ,_,s) char*s;{return
h<1?main(*s,s[-h],"=a-1kj3gnm:q\
ebh_cf*<r.d>i^+?,()[0qTyrjuvcde'8\
h,Mk2polw-s1.t main(")&&s[-h]&&main
(h-1,_,s):h/2?_==*s?putchar(32[s])
:_%115<36||main(h,_,s+1):main(
0,h,"q>.#::##+b#:#(#k###+\
##h?.)+####b?(##rr###\
##?#,1#?r#<#g:#^#\
q?d?_#<kk##)#\
##>i#=fe#\
####")
;}

還原排版一下

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
main(h ,_,s) char*s; {
return
h<1 ?
main(*s,s[-h],"=a-1kj3gnm:qebh_cf*<r.d>i^+?,()[0qTyrjuvcde'8h,Mk2polw-s1.t main(")
&&s[-h]&&main(h-1,_,s) :
h/2 ?
_==*s ? putchar(32[s]) : _%115<36||main(h,_,s+1) :
main(0,h,"q>.#::##+b#:#(#k###+##h?.)+####b?(##rr#####?#,1#?r#<#g:#^#q?d?_#<kk##)###>i#=fe#####");
}
  1. main(h, _, s) char*s; 是主程式的進入點,相當於常見的 main(int argc, char *argv[]),因此 h = argc 也就是一開始程式的進入參數個數。
  2. ./main 執行時,傳進去的 h = argc = 1
  3. h
    1. 負號時,作為加密訊息的字元索引值 ()。s[-h]&&main(h-1,_,s) 則表示加密訊息非空,繼續推進下一個解析字元位置。
    2. 正數時,只標記狀態為 解密表格索引
  4. _ 作為當前加密訊息的字元
  5. s 作為傳遞資料的磁帶

暗碼對照表

1
2
encode: =a-1kj3gnm:qebh_cf*<r.d>i^+?,()[
decode: 0qTyrjuvcde'8h,Mk2polw-s1.t main(

加密訊息

1
q>.#::##+b#:#(#k###+##h?.)+####b?(##rr#####?#,1#?r#<#g:#^#q?d?_#<kk##)###>i#=fe#####

忽略 # 字元後,第一個 q 要去找 encode row 所在的位置

1
2
3
encode: =a-1kj3gnm:qebh_cf*<r.d>i^+?,()[
decode: 0qTyrjuvcde'8h,Mk2polw-s1.t main(
^this, get `'`

第二個 > 要去找 encode row 所在的位置

1
2
3
encode: =a-1kj3gnm:qebh_cf*<r.d>i^+?,()[
decode: 0qTyrjuvcde'8h,Mk2polw-s1.t main(
^this, get `s`

第三個 . 要去找 encode row 所在的位置

1
2
3
encode: =a-1kj3gnm:qebh_cf*<r.d>i^+?,()[
decode: 0qTyrjuvcde'8h,Mk2polw-s1.t main(
^this, get `w`

產生器


Read More +