回傳純值的函數
1 | //return value |
回傳物件的函數
1 | //return object |
科里(Curry)化函數
1 | //return function, execute foo7(1,2)() |
(fin)
1 | //return value |
1 | //return object |
1 | //return function, execute foo7(1,2)() |
(fin)
這是 2021 年 3 月的一些隨筆, 不知何故沒有整理上傳 Blog,
剛好最近翻到,作一次反芻並且記錄。
常常聽到舒適圈、學習圈、恐慌圈, 再搭配上下圖
這個圖,我覺得比例不對,
所謂的 Growth Zone 應該只有簿簿的一層,
大多數的時候我們只能延著這層膜多踏出一步是一步。
偶有突破,才能擴大 Comfort Zone
我覺得下圖比較適合,你要找到正確的方向突破
才能從 Comfort Zone 連結到 Success
那個縫縫才是你成長區(膜)
突破是困難的,一但突破了,紅色的部份就會自動補上,這就是它神奇的地方
恰巧 2022 也有類似的事件
最重要的是價值,價格只是落後指標,
你應該持有資產(農田、房子、工廠、生意、股票),
錢只是流通的工具,只有被消費掉的時候會產生價值。
月費 600 元的運動中心,假設每次去 3 小時,
只去一次的話,那一次就價值 600 元,
當次數變多的時候,每次的時間成本不變,現金成本卻是下降的,
運動中心能帶給我的價值,具體量化的話有
背後的抽象目的可能包含:
這些「目的」與「價值」就是所謂的「效應」,
並不是越多越好,而是取得平衡*(參考系統思考)
比如說,運動過量反而會受傷變得不健康。
下表顯示,當我第一次去運動中心時,
性價比是最高的,單次的價格是 600 元,
隨著次數的提昇,單次的價格是持續下降的,
理論上每天一次的話,單次價格會下降到 20 元/次
次數 | 均價 | 時數 |
---|---|---|
1 | 600 | 3 |
2 | 300 | 6 |
3 | 200 | 9 |
4 | 150 | 12 |
5 | 120 | 15 |
6 | 100 | 18 |
… | … | |
10 | 60 | 30 |
20 | 30 | 60 |
30 | 20 | 90 |
但價值就不是這樣衡量的,
一開始的價值遞增的,但是當超過了某個奇點,
價值就會開始遞減。
那麼錢呢?
其實錢只是一個交流價值用的媒介,
以物易物本身是價值的交換,
但是會耗消很大的時間,才能找到等價的物品,
比如一頭牛可以換多少的白米呢?
更不用說是情感需求等抽象層面的東西。
所以當有了代幣、指示物(Token)、貨幣將抽象的價值具象化,
(背後要有強而有力的組織支持,如:國家,強而有力的信用才能維持貨幣價值),
不同的國家有不同的貨幣,錢則是這些貨幣的代稱。
所以真正有價值的東西並不是錢,錢只有在需要交易之時才有用,
真正有價值的是一首好聽的歌,(太好聽了,怎麼才能反覆聽呢?)
一顆蘋果、一段關係…
一直持續對社會有益的組織
ex:
我很左,但是極致的左是不夠務實的,
我要務實,為了實現某些左邊的理想,
我要右,極致的右才能帶來極致的左,
這樣我還左嗎?
就像跳舞或走路一樣,單足難行千里,
我們總要左右才能前行。
重要的是平衡與推動力。
https://www.books.com.tw/products/0010653417
https://pttcareers.com/Soft_Job/1WQm1aXz
(fin)
有機會在 GCP 上實作了兩種不同方式的靜態網站部署,
一種是透過 Artifacts Registry 與 Cloud Run,
另一種是透過 Google Cloud Storage 與 Load Balancing
特別記錄一下。
build 建置網站, EX: flutter build web
、npm rub build
…
build/web
react-scripts build
靜態檔位置在 build
底下開發上會有不同環境需
預設執行 react-scripts build 會建置出 production 的靜態檔,
故需要透過套件 env-cmd 來幫我們建立不同的靜態檔,
請參考以下的 package.json > scripts
1 | "build": "react-scripts build", |
截至 2021 年 12,nodejs LTS 版本為 v16.13.1
Latest Features 為 v17.3.0
如果 nodejs 的版本在 v17.*.*
以上
執行 react-scripts build 會發生以下錯誤
1 | Error: error:0308010C:digital envelope routines::unsupported |
解決方法,執行以下語法
export NODE_OPTIONS=–openssl-legacy-provider
或是將 node version 換回 v16.*.*
的版本
nvm use v16.13.1
如果選擇 Artifacts Registry 與 Cloud Run 的 solution
必須撰寫 Dockerfile 來建立 Docker Images
dhttpd 是 Dart 的靜態網站解決方案,
不過在部署到 Cloud Run 時會發生錯誤,
更多資訊請參考 stackoverflow 的提問與 issueTracker 的後續
加上 dart global activate 指令,這會在執行前啟用 dhttpd 的服務,
RUN 是建立鏡像檔的語法, CMD 才是 docker image 啟動時會執行的語法,
所以應該將 activate 指令放在啟動
1 | FROM docker.io/dart |
參考聯結
暫解是使用其它的靜態網站服務或套件 ,EX: NGINX 、 npm 的 serve 套件,或是其它你熟悉的靜態網站服務。請參考以下 Dockerfile
1 | # pull official base image |
參考部份的 .gitlab-ci.yml
1 | script: |
接下手動設定 Cloud Run(這部份應該也可以自動化,未實作故無記錄)
缺點是每次 CI 跑完 Image 推上 Artifact 後,仍要手動到 Cloud Run 執行 Deploy。
這個步驟應該放在 CI Server 上(即使是需要手動觸發也是),才不會有斷點。
(fin)
我想完成什麼 ?
如何用最佳解完成全端應用的開發 ?
這次我們專注在第 3 點的 CI/CD 上,為了第 1 點,我建置的專案為 flutter
選用的 CI/CD Server 為 Gitlab , 我將會在這裡作較多的著墨,
最終的產出物是 flutter app image, 並推送到 image registry 上 。
如上圖,每個多邊型都應該可以被置換,
首先需要 Gitlab Account ,我們選用 Gitlab 作為 CI/CD Server,
這個階段我們只會作到持續整合,而未部署,相當於只有 CI 的部份。
理論上也可以選用其它的 CI/CD 服務,像是 Azure 或是 GitHub , 這裡就不作過多的展開。
Docker , 簡單說我們的工作只有兩個步驟
我們要在 docker 建立來執行 gitlab Runner
Create the Docker volume:
1 | docker volume create gitlab-runner-config |
Start the GitLab Runner container using the volume we just created:
1 | docker run -d --name gitlab-runner --restart always \ |
Register Docker Runner
依序輸入 Gitlab URL、gitlab-ci 的 token、runner 說明/名稱、Runner 的 tag、executor、docker image
1 | docker run --rm -it -v gitlab-runner-config:/etc/gitlab-runner \ |
docker:stable
gitlab-runner run
驗証 runner 狀態是否 alive
gitlab-runner verify –delete
移除 gitlab-runner
gitlab-runner unregister –all-runners
在 RUNNER JOB 中執行 flutter pub get 時$ flutter pub get
發生錯誤訊息如下,當我換了一個 intel 晶片的 MacBook 當作 RUNNER 就不會有問題了。
1 | Running "flutter pub get" in rettulf... |
我們的 Gitlab-Runner 是執行在 Docker 上,
而當我需要 build Docker Images 時,我會在 Container 中建立 docker
這時 Container 所使用的 Image 會是 Docker Image
就被稱為 DIND (Docker In Docker)
參考以下的 .gitlab-ci.yml
1 | before_script: |
$ echo -n $LOGIN_KEY | docker login -u _json_key_base64 –password-stdin https://xxxx-docker.pkg.dev
Error: Cannot perform an interactive login from a non TTY device
主因是讀不到 $LOGIN_KEY
的環境變數,使用 Gitlab-CI 的話要注意 Protect Variable
在 RUNNER JOB 中執行 docker push
時
錯誤訊息如下:
dial tcp: lookup docker on x.x.x.x:53: no such host error runner inside docker on armhf
這裡要修改 RUNNER 中的設定檔 config.toml
, 路徑參考如下:
You can find the config.toml file in:
- /etc/gitlab-runner/ on *nix systems when GitLab Runner is executed as root (this is also the path for service configuration)
- ~/.gitlab-runner/ on*nix systems when GitLab Runner is executed as non-root
- ./ on other systems
在 [[runners]] > [runner.docker] 加入 image = docker:stable
或是 privileged = true
這可能不是一個正確的 solution , 可以更多的參考這篇討論
如上題,我們需要在 container 之中編輯文件,
這裡我會使用 vim,
不過安裝前記得先更新 apt-get
不然會出現以下錯誤
E: Unable to locate package vim on Debian jessie simplified Docker container
1 | apt-get update |
這裡都以台灣的 region 為範例,
所以都是 ‘asia-east1-docker.pkg.dev‘ 不同的 region 請再參考 GCP 文件
記得要先登入
docker login -u _json_key_base64 –password-stdin https://asia-east1-docker.pkg.dev
推上去
docker push “asia-east1-docker.pkg.dev/{env_name}/docker/{project_name}:{version_tag}
需要先調整 Docker configuration file 取得授權,請參考
gcloud auth configure-docker asia-east1-docker.pkg.dev
再執行
docker pull asia-east1-docker.pkg.dev/{env_name}/docker/{project_name}:{version_tag}
註冊
(fin)
新工作配發了新的 MacBook 搭載最新的 M1 晶片,
沒想到反而遇到了許多問題, 不會有太多的文字說明,
僅用來記錄我實作有效的解決方法
當執行以下語法時,
1 | docker pull mysql |
會得到錯誤訊息如下
no matching manifest for linux/arm64/v8 in the manifest list entries
docker pull mysql/mysql-server:latest
docker run -d –name mysql -p 3306:3306 mysql/mysql-server:latest
docker logs mysql 2>&1 | grep GENERATED
[Entrypoint] GENERATED ROOT PASSWORD: mysql_password_shows_here
docker exec -it mysql bash
mysql -u root -p
Enter password:
輸入原始的 root 密碼後,
會看到畫面如下:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 25
Server version: 8.0.27Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective owners.Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.
ALTER USER USER() IDENTIFIED BY ‘password’;
CREATE USER ‘root‘@’%’ IDENTIFIED BY ‘root’;
GRANT ALL ON . TO ‘root‘@’%’;
flush privileges;
ALTER USER ‘root‘@’%’ IDENTIFIED WITH mysql_native_password BY ‘password’;
flush privileges;
(fin)
本文內容大量參考此系列文章, 僅作記錄之使用。
在學習 React 的過程中, 我們需要處理瀏覽器的網址(URL)與頁面之間的關係,
目前(2021 年)主流的作法,就是使用 react-router 這個 library,
其中有三個類似的方法
使用方法:
1 | <Route path="/" component={Home} /> |
這個方法的缺點是並沒有提供傳遞 props
的 API
1 | const Home = (props) => { |
Render 這方法要求你使用一個傳入一個回傳 component 的方法,
我們可以透過方法參數傳遞 props
1 | <Route |
基本上使用方式與 render
並無二致,
最大的差異在染渲邏輯,children
在路由不匹配的時候, 仍然會顯示,
以下例子在使用者輸入 /
會顯示 Portfolio
與 Contact
1 | <Route path="/" exact component={Home} /> |
(fin)
多語系是國際化的專案很重要的一部份,
這次有機會接觸到國際化的前端的案子,
記錄一下前端主流的 i18next 如何設定。
安裝 i18n
1 | npm |
準備多語系 JSON 檔, 為 Key-Value 形式, Value 為 string
允許巢狀, 範例如下:
1 | { |
起始設定
1 | import i18next from "i18next"; |
追加 React 設定
1 | import React from "react"; |
在 React 中使用
1 | import ReactDOM from "react-dom"; |
其它 Framework 請參考
(fin)
2021 年 3 月, 看到了一則新聞, 指出 LastPass 將改變它們的經營策略,
免費版本將只支援一種裝置, 行動裝置或電腦。
產品收費是天經地義, 但消費者找尋更高性價比的產品也是。
讓我想離開 LastPass 的主因在於, 突襲式的宣布讓我幾乎沒有反應時間,
免費版的限制太過苛刻, 一樣在限制裝置的功能上,
EverNote 這款筆記軟體也是逐步降低免費版本可跨平台的數量。
但是 LastPass 更狠, 瞬間降到僅限一種, 這基本上是在玩文字遊戲,
因為大多數的人應該都同時具備手機與個人電腦, 一般上族班只能被迫選擇電腦,
或是付費了事。付費當然不是問題, 但宣告期極短且粗爆的方式讓人覺得被當韭菜割。
當我稍微作了一下功課, 發現這類的服務已經多如繁星, 甚至內建在作業系統或是瀏覽器之中。
再進一步比較功能, 與自已所需要的功能(密碼保管、密碼產生器、跨裝置etc…)
有更多免費的軟體已經能滿足我的需求,比如說: BitWarden
BitWarden 的好處,
最後一點我是覺得最吸引我的地方,這表示如果你有一定的程式語言能力,
你將可以自行搭建一個密碼管理的伺服器,這點甚至對企業也是有相當的吸引力,
而 BitWarden 使用的語言為 TypeScript、C# 與 Python。
在轉換上是非常容易的,可以在一小時內完成這項作業,
實務操作上也沒有遇到太大的困難,除了原本 LastPass 右鍵產生密碼的方式,在 BitWarden 上面沒有外,
其它功能或是外觀設計上,我都覺得 BitWarden 的表現更加優秀,
甚至有點相見恨晚的感覺。
至於沒有的功能,不是什麼大事,而且開源專案誰都可替他加上這個功能。
但對我來說,我已經忘了 LastPass 有什麼優點,
轉移到了 BitWarden 6 個月,從未再次開啟,於是今天正式將帳號刪除了。
(fin)
新的工作有機會接觸到微軟的 Azure Cloud 服務,
包含 AWS 、 GCP 的話,世界的三大雲服務都碰過一輪了,
不過也只是皮毛而已, 紀錄下來免得遺忘 .
說明一下需求,在實作授權的
在這裡我會使用到 Azure Cloud 的三個服務,
說明一下我理解的三個服務:
Azure Functions 是微軟無伺服器(Serverless),
Serverless 的概念是讓開發人員專注開發, 減少對伺服器維運的成本,
並且提供極度彈性的可擴展性,並且可以使用更少的資源(更低的成本),
最大的限制是運算時間(timeout),
但就我個人而言的 Best Practice 在 300 秒內完成不了的運算, 應考量整體架構的瓶頸在哪裡,
而不是採取無限制的付費方案(Plan Type)。
稍微作個 ORK 評量,應該在 0.2 | 10 | 300 秒內完成計算。Managed Identity 是微軟用來作身份認証與授權的服務,
與其它雲服務最大的差別應該是它是基於 Azure Active Directory (Azure AD) 之上,
一般來說會建議使用遵循(Role-based Access Control),
下面的圖片很好的說明了其概念。
Key Vault 是個相對簡單的概念, 在開發中我們會接觸到需多的密鑰、証書、連線字串等等資訊…
這些資訊有敏感性, 但對開發過程又不是最重要的東西,
這些資訊在單體架構(Monolithic)時常常面臨開發與資安的兩難,
而 Key Vault 可以解決這個問題(當然不同的 Cloud 也有類似的解決方案)
這次的案例,使用者會在瀏覽器提供給我們一組 Token ,
而我們會拿這組 Token 與第三方互動換回我們需要的 Key,
最後我們會把這組 Key 存進 Key Vault 給其它服務使用.
你可能會好奇, 在上圖中 Managed Identity 扮演的角色為何 ?
就是在 Function Apps 存取 Key Vault 這一段,
我們將提供一組 Identity 給 Function Apps 讓它有權限存取 Key Vault .
我將步驟大致分為以下幾步
讓我們開始吧.
開始前先作名詞解釋, 因為微軟的命名會讓剛接觸的人十分混淆
建立 Function Apps 的步驟較為簡單,請依照微軟文件即可,
接下來選擇 Function Apps > 選擇剛剛建立的 Functions App > Create > Http Trigger C#,
選擇這個範本我們將以 C# 語言實作,授權等級我選擇 Anonymous .
建立好後,可以在 Code + Test 裡面查看預設的程式.
這裡建立的是 C# 指令碼, 開發上的細節請參考官方文件
1 | using System.Net; |
移動到 Functions Apps 的 Settings > Identity,
可以看 System assigned > Status 將它切換為 On
.
這一步的設定是為了讓服務之間可以受到 AAD 控管而不需要你自行處理.
在建立之前也是需要一些名詞解釋,
找到 Key Vault > key vault section > Settings > Secrets , 建立一組 Secret
點選剛剛建立的 Secret 並且選擇 CURRENT VERSION 取得 Secret Identifier(複製下來, 待會會用到)
一樣在 Key Vault > Settings > Access policies > Add access policy ,
在 Select principal 找到剛剛建立的 Function App,
在 Configure from template (optional) 我們直接套用 Secret Management,
這允許我們的 Function App 會取得管理 Key Vault Secret 的權限.
移動到 Function App > Settings > Configuration > Application settings
我們要在這裡新加一個 Application Setting
Name 自已取但是請記得,我們稍後就會用到,這裡我先命名為 TestKV
,
Value 請參加下面的範例, 將前面步驟取得的 Secret Identifier
填到 SecretUri 之後.
1 | @Microsoft.KeyVault(SecretUri=https://mykv.vault.azure.net/secrets/RefreshToken/xxxx) |
這裡有小朋友問我, 那為什麼不把資料設定在 Function App Configuration 就好,
這樣子開發人員也碰不到資料, 要修改也是很有彈性的.
我的回答是, 這樣子其它的服務也需要這個資料怎麼辦呢?
Copy-Paste 會造成維護上很大的困難, 我們會希望維持一組就好.
放在 Key Vault 可以讓我們不同的服務共用.
反思 Best Practice 應該怎麼作???
設定檔散落在不同的層級, 還是應該集中管理, 再用 Config 橋接???
下列我們用 TestKV
這組設定與 C# 作為範例 :
透過環境變數取得 Key Vault 的資料
1 | // Get |
而如果你需要寫入請使用 Azure SDK Client Library
1 | using Azure.Identity; |
其它語言可以參考
(fin)