關於報稅這檔事

服用前請注意:本篇以個人經驗寫成,因此可能有許多法律或稅務相關用語不太精確,還請見諒。

就在去年,a8c在台灣人數堂堂衝破2位數,而且還在穩定增長中,正式擊敗東亞一哥日本,可喜可樂、可喜可樂。因此我們前陣子舉辦了第一次的區域性meetup,在天母古道的1800級階梯毀滅膝蓋、探索隱藏版瀑布,大吃興蓬萊排骨酥與其它大量與健康扯不上邊的食物。

當天我被問到最多的就是如何報稅,我當初也是被這問題搞得暈頭轉向過,是時候寫一篇文章總結一下。

先寫結論

內文很長,有空的人再泡壺茶、沖杯咖啡展開內文看看吧,沒空看一下這段應該就夠了 🙂

Automattic在沒有分公司的地方是以用「契約工作者」(contractor)的方式簽訂發當地貨幣的合約,這種情況可以用個人身分透過全部列舉或是用執行業務所得的名目來報稅,手續簡便但會報到哭出來。後來透過Zapier的前輩Chang-Hung介紹,我才知道更好的方式是成立一間機構,透過「外銷勞務零稅率」來節稅,我是選擇透過Simpany的服務成立行號。行號的稅計算很簡單,營業稅0稅率,免營業所得稅,最後就是「總收入*行業稅率」算出營利所得,算入個人所得稅去報(*修訂1)。軟體服務是8%,軟體出版則是6%,後來透過Simpany協助申請到後者,這樣一來我基本上繳不到稅,除非公司突然加我十倍薪水。但有一個最大缺點就是每個月都要去銀行用印才能拿到錢,我是在玉山開公司戶,他們是說這跟洗錢防制法有關,只要是用這種形式進來的台幣就避不掉。至於其他銀行有沒有別的方法,我就沒去進一步研究了。

因此,我一年關於稅務的常規大概如下:

  1. 每個月月底開一張invoice給公司(無制式格式,自己找個template做就行),以及用線上工具開一張電子發票,勾選「零稅率」,項目寫「服務費」。
  2. 銀行通知有匯入款進來要用印,帶著大小章風塵僕僕地騎車去蓋章。一開始會要請行員把水單email給我,但後來熟了都不用說了。
  3. 雙數月底,Simpany會通知要報稅,這時就把合約、給公司的invoice、銀行水單印出,包成一包預約順豐取件寄出。
  4. 時光匆匆來到12月,這時候會需要申報「年度各類所得」,申報員工薪資等等。因為我都沒有,也沒打算給自己做個薪水的名目,所以就報0即可。(這部份見仁見智,有一說是為了將來申貸或信用卡申辦等事宜最好還是要設定個薪資,免得銀行那邊審核不過,我沒有相關經驗就是了。)
  5. 新的一年開始,繳給Simpany記帳服務費26000+珍奶型電子發票方案660 = 26,660。(*修訂2)

多了許多手續,但這樣一來稅負全免,一年只需繳給事務所26,660即可。

年度交換禮物來啦!

在a8c,每年年末會有一次秘密聖誕老人(Secret Santa)的交換禮物活動,也就是「小天使小主人」遊戲。雖然我幾乎每年都參加,突然想到我好像沒有寫過這件事。

活動進行方法是:

  1. 當年主辦人會在約11月中於watercooler p2宣布開始登記,有興趣的人就自行到內部一個名為"Automattic Gift Exchange"的WordPress網站登記。
  2. 登記時間截止。Automattic Gift Exchange會發送Slack ping,告訴你今年的送禮對象已經決定了,這時去該網站就會看到本次送禮對象的寄送資訊,以及一個可以匿名發送訊息給送禮對象或是你的秘密聖誕老人的表單。
  3. 收到禮物,是時候去watercooler p2發文炫耀啦!一個不成文的規定是最先收到禮物的人要開一個新的p2討論串。

因為公司的人遍布全球,所以玩這個好玩之處就在會有機會收到世界各地的東西。我曾經收過來自瑞典的節慶食品,其中一條焦糖醬因為真的太甜了現在還躺在我家冰箱;來自亞利桑那州的各式仙人掌特產以及當地小咖啡店的重烘焙豆,那支咖啡的風味之好我至今還念念不忘(我常常覺得台灣咖啡師大多對重烘豆過於歧視,不過那是題外話);還有一年某熱愛烘焙的同事因為沒辦法寄她自己的作品來,居然訂了Biolove的蛋糕給我,她不通中文也沒到過台灣,令我印象深刻。

今年收到的是來自英國的恐怖漫畫:Ghost Island: The Complete Collection:

這本書來自一位曾經在grand meetup合作過的同事。他事前有寫匿名信給我,想多了解我的喜好來選擇。
「你最近一次追劇是追了什麼?」
「魷魚遊戲」
大概是這樣,他選了一本恐怖漫畫給我。我收到沒多久就看完了,作畫呈現相當精彩,雖然整體故事張力和人物表現深度似乎礙於篇幅有些不足,但仍然是部佳作。

至於我送的禮物呢?過去每次我都是精選台灣美食大禮包寄送,但今年抽到印度同事,很不幸沒有任何運費合理的方式可以寄送,我只好上Amazon.in去買了一個我出外工作必備的收納神器GRID-IT,從當地商家送去,雖然氣勢不足,起碼顧到實用性與價值感。

如果2022年末全球物流能恢復正常,抽到我的人就賺到了。兩年悶氣集成的兩倍大禮包,必定要他一次從台灣頭吃到台灣尾,看到MIT字樣都會怕。

啥?Terminals database is inaccessible?

今天在設定開發環境以及安裝git-filter-repotmux-open時不知動到什麼,首先發現顏色都跑掉,接著tmux出現一系列令我抓狂的問題:tab completion陣亡,在zsh下delete變空白,打clear會出現terminals database is inaccessible 錯誤,然後我的命令列提示字元甚至還可以刪除:

再鬧啊

搞了半天,桌子快撞壞,才發現$TERM不知為何變成了tmux-256color,在tmux.conf中加下面這行設回macOS預設的xterm-256color就行了:

set -g default-terminal "xterm-256color"

我還是不知道我在安裝過程中到底動到什麼,或許是安裝git-filter-repo時有更新一些tmux相依套件,安裝tmux-open後重開tmux問題才顯現出來。後來我的顏色設置還是回不來,索性就當一個機會把用了6年還是7年的配色給換了。vim換了molokai

terminal則是自己隨便配一配:

僅以本文紀念一下今日花在這問題上的半天,和我一去不復返的配色們 T___T

WordPress.com的產品包裝與定價問題

圖文不符的特色圖片攝自日月潭星巴克的陽台。

前陣子在週末帶著家人到日月潭來了一次毫無事前規劃的三天兩夜旅行,這對我們家來說非常難得。因為我很怕人多的地方,也對長途的車程敬謝不敏,因此過去我們家出遊通常都選平日,出國的次數也比在國內多,乍看之下好像荷包很厚的樣子,其實只是把別人短程出遊10次20次的錢累積起來,加上坐飛機比開車容易避開人潮車潮而已。但疫情當頭,加上小子上小學後時間、空間彈性大減,即使我再怎麼自詡為家裡蹲的佼佼者,竟也覺得蹲到快發霉,必須硬著頭皮去人擠人。

三天兩夜的行程相當鬆散。每天孩子和太座都睡到9點才被我搖醒去吃早餐,吃完就回房間連線打Don’t Starve Together到快中午,接著才懶懶散散地出門。這種過度閑散風格也是我們不愛當天來回旅遊的原因,光是要一早出門就快做不到了,還能期望一天內能去到多遠呢?

不管去到哪裡,晨間散步是我最愛的時間。在天微亮之際,用慢到彷彿身體自己在走的步調,融入朝陽投出長長的影子中,以我一介外來俗人的身影,為這片當地人早已看慣的風景增添一抹新意。這次自然也不例外,在家人還好夢正酣之際,我的足跡已遍佈水社碼頭周邊,兩天來淋過雨也吸過晨霧,

在星巴克等咖啡時打開WordPress.com app,發現上次發佈文章竟已是4個月前的事了。回想起來,那差不多就是我被編入「產品包裝與定價」小組擔任開發領隊的時候。Harvard Business Review的文摘「For New Managers」有一段話說:

你本來以為成為管理者後會有更多自由和權限可以追求想做的事,但實際上你卻更加受限於整個組織複雜的人際網路中。

這幾個月來,關於這點我可說是用我的骨髓徹底體認到了。

久違的一人一車小放風

假期過到一半,向來頭碰到枕頭就開始咬牙打呼一覺到天亮的我,竟然也出現了睡眠品質問題。翻來覆去睡不著之餘,好不容易進入淺眠,卻又立刻醒來,就這樣斷斷續續不斷掙扎到外面天空微亮。回想起來,研究所時期也曾有過許多這樣因壓力而無法成眠的夜晚,那時我常常在天還沒亮就跳上我的125,往南寮或是寶山騎,不看地圖也不做任何計畫,只管讓未曾走過的巷道給我驚喜。有一次不小心騎到了氣象觀察站給工作人員一臉狐疑地盯著離開,還有一次騎到了山裡某個釣客聚集的小溪邊。比起有明確目的地,這樣隨意走走似乎更貼近旅行對我的意義。

這些日子來因為小孩在家上學,疫情升溫搭配滿天飛舞的流言攻擊弄得家人壓力山大,我又很剛好在帶時間緊迫的專案,身體和精神狀態在短短兩個多月間像雪崩一樣下滑,每天一張開眼睛就是在咬牙苦撐。上週發覺真的沒辦法再這樣撐下去,於是請了個12天的長假。就客觀角度來看,其實我已經很幸運了:疫情並未衝擊到我的收入,又已經是遠端工作老屁股了,我這樣竟然都覺得快撐不下去,連工作都受到衝擊的人究竟是過著怎樣高壓的日子呢?

「好啊,你是該放個假了,有什麼好玩的計畫嗎?」
「沒有喔,我哪裡都不去,只是會好好休息,當個全職家管而已。」

順帶一提,在和同事的對話中我們用的詞是"full-time nanny",覺得挺貼切的。12天的家裡蹲和本來的計畫當然是相差甚遠的,本來我計畫在今年6-8月請我的3個月sabbatical帶全家去歐洲壯遊,因為國外狀況仍然嚴峻就退一步安排了許多國內的活動,接著國內疫情爆發就再退一步變家裡蹲了。

DDIA閱讀紀錄(10) – 第三章總結:column-based storage

距離上次整10天了,閱讀進度愈來愈不穩定了啊啊啊啊啊。公司讀書會的進度其實已經到第6章,俺已經放棄追車尾燈,改成用自己的步調慢慢看了。

第三章的最後著重在解釋analytics資料庫在檔案的佈局上的一個有趣的實作策略:以資料欄為基礎(column-based)的序列化,而非一般transactional database的資料列為基礎(row-based)。所謂資料列為基礎的佈局,就是把每個資料列(row)一個接一個地寫到檔案中,而column-based就是反過來:把每個資料欄(column)一個接一個地寫到檔案中。會這樣做是因為硬碟的讀取頻寬有限,但統計分析經常要對百萬級以上的資料做運算,但同時又只需要少部分欄位即可。以資料欄為基礎去序列化,就可以有效做到只讀取需要的欄位了。

舉例來說,假設我們是個超級水果電商,我們可能會有長這樣的資料庫:

那麼,如果是資料列為基礎的檔案佈局概念上就長這樣:

那麼資料欄為基礎的佈局就大約是這樣:

從上圖也可以觀察到兩件事: 第一,資料列因為被以欄位打散到許多檔案中,因此一個資料欄檔中的順序是非常重要的,因為那是我們重建一個資料列的唯一依據。第二,因為一個欄位的值域通常不大,因此很容易壓縮,例如書中用的例子是run-length encoding。

但這樣一來column-based的資料庫寫入上會需要不同的策略。像B-tree那種會需要in-place寫入並維持排序的檔案結構自然是不行的,因為一個資料列現在可以橫跨數千個欄位檔,如果要從中間插入一個資料欄,那就意味著要去動那數千個欄位檔,保證機房人員整天換硬碟換到手軟,硬碟廠商笑開懷。前面的章節提過的log-structured storage便是一個解方:每次寫入只從檔尾附加(append),並適時進行壓實(compaction)。書上提到LSM-tree可以用,但我有點想像不出來這東西在記憶體中的SSTables(sorted-string tables)要怎麼建。如果是跟一般情形相同的平衡樹,因為本質上還是以資料列為單位,會不會造成什麼困難?還是會針對之後以欄為基礎的序列化做什麼特化?這些細節可能要去看實作才能知道了。

到此第三章終於堂堂結束,接著第四章為「Encoding and Evolution」,乍看之下應該是在說實際將資料序列化到檔案的實作策略 … 吧?這次第三章真的讀很慢,希望這次可以快一些。

DDIA閱讀紀錄(9) – 第三章續:從OLTP到OLAP

(進度:loc 2353 – 2540)

又一個星期沒寫了 … 恐怖,專案死線太恐怖了 …

這次讀的段落雖然觸及的主題很多,但重點其實是要從前段以線上即時應用為主的線上交易處理(OLTP,Online Transaction Processing),過渡到本章後段的主題線上分析處理(OLAP,Online Analytical Processing)。就個人目前粗淺的印象,那個"OL"真的是挺雞肋的,OLTP出生的年代線上與否是件大事,但OLAP就不一樣了,一方面線上或線下並不是重點,另一方面以其探討的架構來看自然是跟大型的資料中心有關,那就一定是線上的。或許只是因為和OLTP對稱,只好硬是冠個OL上去吧?

中間的過渡主題包括fuzzy indexes,full-text search和in-memory database,但都只是蜻蜓點水式帶過,尤其前二者並沒有太多深究,只有指出為何fuzzy indexes和full-text search會需要不同的索引結構。至於in-memory database,很有趣的是因為今日從database engine乃至OS都有自己的caching機制,導致in-memory database真正有效益的地方不在於查詢與讀取,反而是因為在寫入時它不需要轉換成硬碟需要的格式,例如序列化。

過渡之後,本章堂堂進入analytical data的世界。在本章開頭,作者就有指出transaction data和analytical data由於目的和資料量級的差異,存儲策略會完全不同。書中的這個表格總結得不錯:

簡單來說,資料分析的應用大多是一次抽出大量資料出來作統計分析,而當服務規模夠大,直接在production database上做這件事很容易造成整個服務停擺,弄得operation team森七七,系統部門和資料分析部門間烏煙瘴氣。為了兩邊都能做好自己的工作,才衍生出透過ETL程序(extract-transform-load),把資料定期轉到另外的"data warehouse",讓資料分析師們可以有個地方愛怎麼搞就怎麼搞,operation team保有內心的祥和,從此和氣生財,大家都過著幸福快樂的生活。

WordPress.com的作法大致上與書中相符。內部有自己維護的ETL程序會把最新的production data輸入到一個Hadoop cluster中,再透過Hue、Looker、以及N種自幹的資料分析工具去找出需要的資料。至於production database上則有作一系列的保護措施,盡量避免OLAP量級的query被某個沒睡飽的工程師跑到,但並沒有很完美就是了。

下個段落開始要提到analytical datastore的存儲策略,標題是「column-oriented storage」,希望不會又是一週後才寫了。

DDIA閱讀紀錄(8) – 第三章續:從底層檔案結構到索引結構

(進度:loc 1668 – 2353)

爆忙了一陣,竟然已經整整一週沒繼續寫這個系列了。恐怖,在家上學太恐怖了 …

這個部分首先從兩種database engine底層常見的檔案結構開始提起:LSM-tree與B-tree。這讓我回想起了大學時代修檔案結構(file structure)的血淚史,期末作業就是實作一個最基本的B-tree,後來太多人卡住,大家還聯合起來去向教授求情,才得以寬限一週。總結來說,LSM-tree(log-structured merging tree)因為針對硬碟的sequential性質去特化的存儲策略,對側重寫入的應用會有較佳的表現;但B-tree則是四平八穩,因為就是棵平衡樹,在讀取上通常表現不錯,寫入上因為隨機存取多的關係會比前者弱一些,且容易有空間破碎的問題。雖然概念上是這樣,到底何者對自身的應用才是最適合的,還是要靠實驗分析才有辦法知道。

其實就像學資料結構(data structure)一樣,許多資料結構雖然不明講,但大致上是基於von Neumann架構來設計的東西,所以實作與應用上其實都有考量到硬體性質。B-tree和LSM-tree也不例外,整個實作策略上精密地考慮了傳統硬碟的特性:存取時間長、循序讀寫佳、隨機讀寫不行,以及一定要考慮到當機復原,因為寫到硬碟裡的東西不像記憶體裡的大不了重開機治百病。

段落的最後以索引結構作結,簡單說就是這個key-value pair裡,value到底要存在哪。它可以是直接inline或說in-place跟key存在一起成為所謂的clustered index,也可以是一個heap file,也有可能是介於兩者之間,一部分在heap一部分跟index在一起成為所謂的covering index。這裡也順便提到以R-tree為代表實作的spatial index,可用於做multi-dimensional的range queries,這部份我就沒什麼實務經驗了。

下一個段落要進入Full-test search和fuzzy indexes了,這個部分和analytics data storage是我最想了解的部分,好興奮啊!希望明天不要又忙到沒時間看了啊啊啊啊啊。

DDIA閱讀紀錄(7) – 第三章:令人臉紅心跳的Storage and Retrieval

(本日進度:loc 1900 – 2032)

天啊,今天第一次開始讀第三章,只能說太精彩了。繼第二章走訪各data model的性質後,本章進一步深入到database engine的存取實作概念。雖然我現在才剛讀完一開頭一點點,但真的是讀到忍不住啊啊啊喔喔喔又喘又叫的,旁人看到搞不好以為我在讀的是官能小說。哼哼,誰說讀技術書籍不能高⬤的?

本章以一個「世界上最簡單的資料庫」開始,因為實在太精簡了,值得在這邊照抄一下:

#!/bin/bash

db_set () {
    echo "$1, $2" >> database
}

db_get () {
    grep "^$1," database | sed -e "s/^$1,//" | tail -n 1
}

這種append-only的讀寫策略很顯然寫入非常有效率,但讀取會是一場災難。從這裡,作者進一步帶出hash indexes的概念:透過一個在記憶體中的hash map去儲存從key到file offset的map來解決讀取效率問題,同時指出任何index都會增加寫入的overhead,這也是為什麼幾乎所有資料庫都不會預設index。這讓我想起以前年少不懂事,曾經搞出過index file比實際資料還龐大的烏龍。

由於是append-only,那代表任何對已存key的更新或刪除事實上是透過在檔案尾端新增一筆相同key的紀錄來完成。雖然概念上簡單,但書中指出這在實作上其實有很多挑戰,例如空間使用效率上需實作compaction來把所有相同key的records合為1個,以及把一個資料庫檔案切成多個"segment"等等。

既然有了這組map,那這代表我們可以直接in-place覆寫檔案來實作update嗎?作者在這裡回顧了上面的極簡資料庫,指出這種append-only的log structure其實出乎意料地有效,因為它是一種sequential operation,這在過去磁盤為主的硬碟尤其重要;上面提到的compaction若造成segment merge,也會是sequential operation。

實作以上hash indexes的代表性key-value store為Bitcask,稍微看了一下它的repo,似乎相關應用還不少。

段落的最後作者指出這種資料庫的兩大限制:

  1. 由於整組hash map必須都在記憶體中,如果鍵值太多塞不下就不適用
  2. Range queries不佳,例如找出kitty00000 – kitty99999間所有鍵值會需要把整個hash map巡覽一遍

以此為引,下一個段落要開始講沒有這兩項限制的SSTables與LSM-Trees了。

太興奮了啊啊啊啊啊啊啊啊!!

DDIA閱讀紀錄(6) – 第二章完:Datalog,總結

週末盡可能地找空閒時間讀,終於把剩下的最後一點點讀完了。

最後一段介紹Datalog,標題是「The Foundation: Datalog」,因為它是在1980年代從學術界開展出來的query language,盡管在當年並未在實務上獲得成功,作為QL的老前輩,其作為催生其他QL的基礎可謂功不可沒。

應該啦,書上這麼寫,我就這麼信了。

Datalog是一個類Prolog的logical language。大學時代在學Programming Languages時我就搞不懂,現在看了還是滿頭問號。所以請原諒我寫不出什麼像樣的心得,因為心得就只得一句花惹發

有意思的是學到有個叫Datomic的資料庫就是採用Datalog,看起來挺新穎的。這讓人聯想到因為Elixir重新讓世人認識的Erlang,又有點像超前時代太多而不受重視的藝術品,因緣際會等了數十年才得以重見天日。資訊科學的歷史中還有多少這樣靜待發掘知識珍寶呢?

下回第三章:「Storage and Retrieval」,要進入database engine的實作世界了,有種好硬好硬的預感 …