Total Pageviews

2020/03/01

[閱讀筆記] Learn to Think in Systems (3/7)

  1. Systems thinking language 的變數 (variable) 是一個名詞,代表的是系統行為模式隨著時間改變的元素 (element),例如收入、成本、贏得新顧客的成功率、客戶流失率、員工流動率、準時交付成功率等。
  2. Links 顯示兩個變數間的關係,其中一方的改變,會導致另外一方的變化。例如,當爭府想增加稅負來提高預算數字,有兩件事會發生:一、由於較高的 tax inflow 會增加政府稅收;但是,政府會受到公民壓力,既然被要求課徵更高的稅賦,就會要求政府提升施政品質。並且,提高稅負未必真的會收到更多的錢,反而會因為人民逃漏稅,結果卻收到更少的稅金。
  3. Direction of links:兩個變數間的方向,可能是相同的方向 (S, same direction),或是相反的方向 (O, opposite direction)。例如,口渴程度與喝的水量是相同方向,當你越口渴,你會喝得越多;喝的水量與口渴的感覺則是相反方向,當你喝的水越多,口渴的感覺則越少。當你在設計一份回饋或成因圖 (feedback or casual diagram) 時,最好要指出你的 links 的方向 (same or opposite direction)。如此一來,可以讓你的圖更加清楚,並且可以協助你發掘有無可能遺漏重要的變數。
  1. mental models 是我們或系統的信念 (接受某事物是否存在或為真)、行為準則與相信的事實,這些都是我們在研究系統行為的重要決定因素。當我們對造成系統績效低落的行為與思考方式做出結論,我們就需要思考如何針對行為與思考方式做出改變。
  2. 當我們試著解決問題時,常會傾向專注於有形的 (tangible) 事物 ,而非無形的 (intangible) 事物,例如信念、習慣等。忽視習慣與信念重要性的干預方式,會導致成本高昂且沒有效率。政府機構只有改變基礎設施,卻沒有改變民眾的信念,是無法成功的,例如:當政府間理器最現代的疫苗接種中心,但是民眾並不知道疫苗接種的目的或如何防範疾病,疫苗接種率一定很低。然而,只要對於疾病與存活率的信念改變,大眾認同對疫苗接種的重要性,接種率必定大增,並大幅降低因感冒引發肺炎、掛急診的機率。
  3. 當系統展現一個一致性的行為,就很有可能有一個機制在控制或創造這樣的行為,這種機制就稱之為 feedback loops。feedback loops 可以將 stock level 保持在某個範圍、或使其上升或下降。無論 feedback loops 的強度如何,inflows 與 outflows 會決定其 stock level。例如,不管 feedback 的強度多大 (ex. 利率),其對 stock (ex. 銀行帳戶) 都不會在短時間造成巨大的衝擊。換句話說,當我們帳戶只有 $100,即使利率 10%,都不會讓我們一夜之間變成百萬富翁;然而,當你現在的帳戶有一百萬,利率 10% 會讓你的財富成長更快。
  4. 當你可以找出導致 feedback loops 的 variables 與 links,你就可以畫出類似以下的 Acme 案例的 feedback loop diagram,從圖中你可以發現,由於前一個變數的改變,刺激下一個變數也發生改變:
  5. Feedback loops 分成兩種類型,一個 loop 不可能同時是 reinforcing 與 balancing loop,如果你無法決定是哪一種,代表你的分析不夠透徹 
Loop Type
說明
Reinforcing processes
  • 會導致成長或是衰退,常被稱為正向循環或惡性循環
Balancing processes
  • 主要目的是將 stock 穩定地保持在某一個 level (自我矯正)
  • 由於條件限制,balancing process 常被視為目標尋求 (goal-seeking) 或限制 (limiting)
  • 負責自我修正 (self-correction) 或自我規範 (self-regulation)


  1. 惡性循環設計圖 (doom loop design) 的步驟
  1. 寫下你最關心的績效衡量指標或問題 (將其列在圖的中間)
  2. 思考並寫下三個造成此問題的成因變數 (將其列在圖的左邊)
  3. 指出一到三個後果 (將其列在圖的右邊)
  4. 分析成因與後果間,是否有因果關係,例如 Cause B 與 Coneequence Z 之間有因果關係,有效干預 B,就能有效率改善 Z


  1. 以下圖為例,可以發現有兩個 reinforcing feeback loops,R1 與 R2。由於日益增加的爭吵,導致 Alex 更不想回家,導致工時更長,雙方關係更加緊張;由於溝通不良,導致彼此誤解的空間更大,導致Alex 與 Jenney 間的相處壓力增加,由於低薪的壓力,導致財務造成的壓力更大。
  2. Reinforcing feedback loops 可以是正面或是負面的。若系統績效往想要的方向走,那就是正面,例如我們的銀行帳戶透過利息來獲得增長的效果,這就是正面循環;若系統績效往不想要的方向走,那就是負面的,例如 Alex 與 Jenny 有兩個惡性循環,其中一個變數 (i.e. 缺乏溝通) 會導致另外一個變數惡化 (i.e. 工時增長),其又會進一步使第一個變數惡化 (i.e. 氣氛惡化與關係緊張)
  3. Reinforcing feedbacks 的特性
  1. Reinforcing feedbacks 是不穩定的:外部的影響力可以輕易的讓正面循環變成惡性循環,反之亦然
  2. Reinforcing feedbacks 的成長是有限制的:沒有任何事物可以永遠成長或衰退
  3. Reinforcing process 所造成的改變,可以快速且出乎意料之外的突然發生:例如 2008 年的股災
  4. Reinforcing loops 所產生的緩慢的成長或衰退過程,都是默默進行,且容易被忽略:當我們了解系統有此 R loops 時,此 loops 以建立完成,stock 也累積非常大,即便即時干預也需要花費很久時間才能改變,例如臭氧層破洞
  5. Reinforcing loops 被 systems thinking language 稱為突然的巨變 (runaway changes,很小的動作,造成巨大的衝擊):例如雪崩 (avalanche) 的發生,即便是打個噴嚏、或是很小的動作,都可以造成數千磅的積雪崩下來


  1. Systems thinking 中的 causal link,可以標注 S 或 O,S 代表 same direction,例如產品賣得越好,行銷預算可以取得更多;O 代表 opposite direction,例如企業裁員,員工的自信心就會降低。
  2. Balancing process 的目標在尋求穩定,在給定的條件下維持穩定。我們可以將 balancing processes 歸因為目標尋求 (goal-seeking) 或成長限制 (growth-limiting)。balancing feedbacks 負責自我修正 (self-correction) 或自我規範 (self-regulation)。但是 balancing process 的強度也有其限制,以暖氣為例,大部分的設計都是應付一般常規的冬天,若遇到極地氣旋所產生的異常低溫,暖氣的 balacing power 可能就會力有未逮,無法將室溫提升到設定的溫度。
  3. 以下圖為例,在暖氣的情境中,會看到兩個 balacing processes,左邊 (B1) 會根據暖氣設定的溫度 (i.e. performance measure) 與實際室溫差異,當暖氣偵測到室溫低於設定溫度,暖氣就會啟動,讓是溫上升到設定溫度;右邊 (B2) 則是看房屋的隔絕能力,當室外溫度低於室溫時,室內的熱氣就會流逝,使室溫逐漸降低。兩個 balancing processes 會同時運作,當暖氣戰勝室外溫度 (B1 dominate B2),你就會擁有舒適的室溫。
  4. Balancing loops 需要至少兩個變數,一個是績效衡量指標 (performance measure, ex. 室溫設定 25 度),另一個是績效衡量指標的矯正行為 (corrective action, ex. 當室溫低於 25 度時,暖氣機會啟動供暖,讓室溫提升至 25 度)。
  5. 在自由市場中,也有兩股 balancing process 力量,當供給大於需求,價格就會下降;當供給小於需求,價格就會上升。當兩股力量趨於平衡,就是所謂市場的動態平衡 (market equilibrium)。
順序
價格
供給
需求
-
-
增加
上升
-
-
-
供應商開始加緊生產 (生產、交貨等都需要時間,這就是 delay)
-
-
-
當需求量小於供給量
下降


  1. Balancing feedbacks 的特性:
  1. 當系統績效與當初設定的目標有差異時,balancing processes 就會開始介入。
  2. 當績效改善時,balacning loops 的修正壓力就會減輕。
  3. Balancing processes 有其極限,當超過其極限,就會運作失敗。


  1. 不要浪費時間、精力與資源,將矯正措施施行於徵狀、而非對症下藥。每次的干預都是個案 (case-specific) 且需客製化 (tailor-made)。必須注意,在某一個案例施行成功的矯正措施,在另外一個案例未必同樣有效
  2. 阿罵的打掃效率,可以看到他的 balancing feedback loop 
順序
打掃效率
孫子的壓力
打掃方法
打掃效率越差
-
-
-
來自兒孫的壓力越大,開始送iRobot,幫助改善打掃效率 (O)
-
-
-
打掃方法改變 (S)
打掃效率改善 (S)
-
-
-
來自兒孫的壓力就越小 (O)
-


2020/02/29

2020/02/28

[Travel] 2020/02 嘉義


嘉義公園

嘉義公園

嘉義公園

嘉義公園

嘉義市立棒球場

2020/02/10

[Docker] 如何將預先準備好的 SQL 檔案,於啟動時匯入 Oracle Docker

1. 確認 Docker 所 mount 的 directory

2. 將準備好的 SQL file(s) 放到特定目錄下



3. 指定 volume,將 sql 所存放的路徑 (i.e. /Users/guojunyou/Documents/docker/local-initdb) 對應到 /etc/entrypoint-initdb.d
docker run -d --shm-size=2g -p 8080:8080 -p 1521:1521 \
-e NLS_LANG="TRADITIONAL CHINESE_TAIWAN.AL32UTF8" \
-v /Users/guojunyou/Documents/docker/local-initdb:/etc/entrypoint-initdb.d \
42dda6eba3ea


Reference
[1] https://hub.docker.com/r/orangehrm/oracle-xe-11g

2020/02/09

[Docker] 如何解決 Oracle Docker 匯入資料繁體中文亂碼問題

Problem
我有準備好 create table 與 insert data 的語法在指定目錄,並用以下指令啟動 docker:
docker run -d --shm-size=1g -p 8080:8080 -p 1521:1521 \
-v /Users/guojunyou/Documents/docker/local-initdb:/etc/entrypoint-initdb.d \
42dda6eba3ea

並成功啟動 Oracle docker
guojunyoude-iMac:~ guojunyou$ docker logs 4445b2acf933 --details
 Starting Oracle Net Listener.
 Starting Oracle Database 11g Express Edition instance.

 Database init...

 /start.sh: running /etc/entrypoint-initdb.d/data.sql

 Table created.

 1 row created.

 1 row created.

 1 row created.

 1 row created.

 End init.
 Oracle started successfully!

發現所 insert 的資料都是亂碼


How-To
這是因為編碼所導致的問題,在啟動指令增加一個參數
-e NLS_LANG="TRADITIONAL CHINESE_TAIWAN.AL32UTF8" 即可解決亂碼問題
docker run -d --shm-size=1g -p 8080:8080 -p 1521:1521 \
-e NLS_LANG="TRADITIONAL CHINESE_TAIWAN.AL32UTF8" \
-v /Users/guojunyou/Documents/docker/local-initdb:/etc/entrypoint-initdb.d \
42dda6eba3ea




2020/02/08

[Docker] Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection

Problem
As I tried to pull a docker image, I got the following error message:
F:\git
λ docker pull orangehrm/oracle-xe-11g
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: 
request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)


How-To
Configure proxy and restart docker


Pull again 
F:\git
λ docker pull orangehrm/oracle-xe-11g
Using default tag: latest
latest: Pulling from orangehrm/oracle-xe-11g
cb56c90f0b30: Pull complete
0acc551e5716: Pull complete
8956dcd35143: Pull complete
908242721214: Pull complete
b44ff14dd3bb: Pull complete
81ac3d025953: Pull complete
b555aeaf1117: Pull complete
e1896669ff82: Pull complete
9437119349eb: Pull complete
96e36910991c: Pull complete
2de589c896ac: Pull complete
c5510f7fcb03: Pull complete
c09e52e19f4b: Pull complete
abbfadca26af: Pull complete
c14464a9caeb: Pull complete
4468bbe36672: Pull complete
85cfa88ee1f2: Pull complete
d4831108a661: Pull complete
0821dd9b7524: Pull complete
b19f8225db0a: Pull complete
3001b1e31fbc: Pull complete
585b27c5a8cb: Pull complete
4977c21ef050: Pull complete
acf12f209883: Pull complete
51a0fc043bdd: Pull complete
47759cd1519f: Pull complete
Digest: sha256:b56c95bb59dfef4ee8d373713209105dedb52f09d56c82f94edb29f1fac3b60c
Status: Downloaded newer image for orangehrm/oracle-xe-11g:latest
docker.io/orangehrm/oracle-xe-11g:latest

2020/02/07

[Mac] 無法打開XXX,因為它來自未識別的開發者

Problem



How-To
到安全性及隱私權


強制打開


2020/02/06

[Docker] error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/version:

Problem
When I try to get my docker version, I get the error message as bellows:
F:\git\doodle\cheers2019 (master -> origin)
λ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:22:37 2019
 OS/Arch:           windows/amd64
 Experimental:      false
error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/version: open //./pipe/docker_engine: The system cannot find the file specified.
 In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.

How-To
Start up docker


Check again:
F:\git\doodle\cheers2019 (master -> origin)                     
λ docker version                                                
Client: Docker Engine - Community                               
 Version:           19.03.5                                     
 API version:       1.40                                        
 Go version:        go1.12.12                                   
 Git commit:        633a0ea                                     
 Built:             Wed Nov 13 07:22:37 2019                    
 OS/Arch:           windows/amd64                               
 Experimental:      false                                       
                                                                
Server: Docker Engine - Community                               
 Engine:                                                        
  Version:          19.03.5                                     
  API version:      1.40 (minimum version 1.12)                 
  Go version:       go1.12.12                                   
  Git commit:       633a0ea                                     
  Built:            Wed Nov 13 07:29:19 2019                    
  OS/Arch:          linux/amd64                                 
  Experimental:     false                                       
 containerd:                                                    
  Version:          v1.2.10                                     
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339    
 runc:                                                          
  Version:          1.0.0-rc8+dev                               
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657    
 docker-init:                                                   
  Version:          0.18.0                                      
  GitCommit:        fec3683                                     




2020/02/05

[Intellij IDEA] How to build project automatically

By default, Intellij IDEA doesn’t compile classes automatically. 

But, you can enable the auto compile feature by following steps :
File => Settings => Build, Execution, Deployment => Compiler => Checked "Build project automatically"


2020/02/04

[Java] [Freemarker] Generate Text file from FTL - example 2

Requirement
I would like generate text file as bellows:
FreeMarker Template example: Hello World!

        ===================(Page:0001)
        ======  County List   ======
        ========================
        1. 台灣
        2. Japan
        3. The Netherlands


        ===================(Page:0002)
        ======  County List   ======
        ========================
        4. United Kingdom
        5. France
        6. Canada


        ===================(Page:0003)
        ======  County List   ======
        ========================
        7. United States
        8. Italy

------------------------------
Number of Record(s): 0000000008
Print date: 19 Nov 19

FTL file
<#-- 設定 locale,讓日期印出來是英文
     https://freemarker.apache.org/docs/ref_directive_setting.html  -->
<#setting locale = "en_US">

<#-- 宣告變數用來儲存總筆數與頁數
     https://freemarker.apache.org/docs/ref_directive_assign.html -->
<#assign total = 0>
<#assign page = 1>

<#-- 取得現在日期 -->
<#assign dateTime = .now>
<#assign date = dateTime?date>

FreeMarker Template example: ${message}

<#list countries as country>
    <#-- 一頁三筆資料 -->
    <#if total % 3 == 0>
        <#-- 第二頁開始才在表頭增加兩行空白 -->
        <#if page gt 1>


        </#if>
        <#-- 將 page number 格式化 -->
        ===================(Page:${page?string["0000"]})
        ======  County List   ======
        ========================
        <#assign page = page + 1>
    </#if>
        ${country_index + 1}. ${country}
        <#assign total = total + 1>
</#list>

------------------------------
Number of Record(s): ${total?left_pad(10, "0")}
<#-- https://freemarker.apache.org/docs/ref_builtins_date.html -->
Print date: ${date?string["dd MMM yy"]}


Test Case
package com.test.batch;

import com.test.batch.exception.FtlException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class FtlTest {

    private Configuration cfg;

    @Before
    public void init() {
        cfg = new Configuration();
        // 設定到 classpath 讀取 ftl file
        cfg.setClassForTemplateLoading(this.getClass(), "/");
    }
    
    @Test
    public void testCountriesFtl() {
        try (Writer file = new FileWriter(new File("C:/ftl_countries.txt"));) {
            Template template = cfg.getTemplate("ftl/countries.ftl");

            Map<String, Object> data = new HashMap<>();
            data.put("message", "Hello World!");

            List<String> countries = new ArrayList<String>();
            countries.add("台灣");
            countries.add("Japan");
            countries.add("The Netherlands");
            countries.add("United Kingdom");
            countries.add("France");
            countries.add("Canada");
            countries.add("United States");
            countries.add("Italy");

            data.put("countries", countries);

            template.process(data, file);
        } catch (IOException | TemplateException e) {
            throw new FtlException("fail to generate file from ftl file : " + e.getMessage(), e);
        }
    }

}



2020/02/03

[Java] [Freemarker] Generate Text file from FTL - example 1

Requirement
I would like to generate text file as bellows:
分行代碼  貸款代碼   客戶代碼  流水號
808      12345678   0000001   111                           
303      87654321   0000002   222                           
123      45678912   0000003   333                           
-------------------------------------------------
Number of Record(s): 0000000003


FTL File
<#assign total = 0>
<#if rows??>
分行代碼  貸款代碼   客戶代碼  流水號
<#list rows as row>
<#-- https://freemarker.apache.org/docs/ref_builtins_string.html#ref_builtin_right_pad -->
${row.branchId?right_pad(16)}${row.custLoanNumber?right_pad(11)}${row.custId?right_pad(10)}${row.ext1?right_pad(30)}
<#assign total = total + 1>
</#list>
<#else>
No Data Found!
</#if>
<#-- https://freemarker.apache.org/docs/ref_builtins_string.html#ref_builtin_left_pad -->
-------------------------------------------------
Number of Record(s): ${total?left_pad(10, "0")}


Test Case
package com.test.batch;

import com.test.batch.exception.FtlException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class FtlTest {

    private Configuration cfg;

    @Before
    public void init() {
        cfg = new Configuration();
        // 設定到 classpath 讀取 ftl file
        cfg.setClassForTemplateLoading(this.getClass(), "/");
    }
    @Test
    public void testBankFtl() {
        try (Writer file = new FileWriter(new File("C:/ftl_bank.txt"));) {
            Template template = cfg.getTemplate("ftl/bank.ftl");

            Map<String, Object> data = new HashMap<>();

            List<Row> rows = new ArrayList<Row>();
            rows.add(Row.builder().branchId("808").custLoanNumber("12345678").custId("0000001").ext1("111").build());
            rows.add(Row.builder().branchId("303").custLoanNumber("87654321").custId("0000002").ext1("222").build());
            rows.add(Row.builder().branchId("123").custLoanNumber("45678912").custId("0000003").ext1("333").build());

            data.put("rows", rows);

            template.process(data, file);
        } catch (IOException | TemplateException e) {
            throw new FtlException("fail to generate file from ftl file : " + e.getMessage(), e);
        }
    }

    @Getter
    @Builder
    public static class Row {
        private String branchId;
        private String custLoanNumber;
        private String custId;
        private String ext1;
    }

}