l

2025年6月8日 星期日

學習總在課堂後

June 08 21:03~


Teddy身邊有許多對學習很有熱忱也很願意投資自己的朋友,花了不少金錢與時間到處上課。有一次有一個朋友問Teddy:「很多人說需要一萬小時的練習才可以變成專家,你認為呢?」

2010年Teddy寫過〈一萬個小時的練習〉,依據自己的經驗基本上也是認同這種說法。但是學習的目的並不一定永遠都需要重複花一萬小時然後才能夠變成專家,有了第一次一萬小時後之,在類似領域中,之後學習科目的時間可以有效縮短。

舉個例子,Teddy還在唸博士班的時候,學習大該可以分成四個階段:

一階段:三年

從博一到博三,這三年除了修課、考資格考以外,主要時間都花在第一個研究題目:「A Pattern Language for e-Learning」。因為這個題目讀了幾本建築師Christopher Alexander的書,了解GoF Design Patterns背後更高深的武功秘笈XD。

後來覺得自己略有小成,到美國參加PLoP研討會發表幾個e-learning design patterns,但回國之後卻決定改變研究題目。一方面Teddy自己覺得在台灣讀資工系做e-learning題目,總覺得「怪怪的」,還是想回頭做跟軟體開發直接相關的題目。另一方面到美國參加PLoP之後才更深刻發現,pattern寫得好,除了要對pattern所描述的領域很熟悉,還需要有很棒的表達與寫作能力。尤其自己的目標不是只整理1~2個patterns,而是幾十個e-learning patterns。要靠自己用英文寫作整理出這幾十個e-learning patterns而且每一個都要達到PLoP的國際水準,會不會最後搞得自己好像在念英文博士而不是資工博士哩?

***

第二階段:半年

決定換題目之後


對於

Teddy


。原本選擇的研究題目是「在Java語言中實作Design By Contract」,




和一位經常到處上課的朋友聊起這個話題…

Teddy:你到處上課學這麼多不同議題的東西,有辦法吸收嗎?

朋友:我上課的目的跟你不一樣,你可能想要把上課所學內化成自己知識的一部分,而我只是想要「快速吸收別人的經驗然後直接應用看看有沒有機會解決眼下的問題」。

Teddy:

Teddy:

Teddy:


上完課後




***

友藏內心獨白:。

2024年9月18日 星期三

重構既有系統,邁向整潔架構 (6):第三回合,在使用案例層讀寫分離

September 18 17:52~18:52

▲這一集換Eiffel上場

 

工商服務

想了解本系列文章完整內容,請參考重構既有系統:邁向整潔架構實作班。課程介紹與報名網址在此:https://teddysoft.tw/courses/refactor-to-ca/

***

前言

上一集<重構既有系統,邁向整潔架構 (5):第二回合,套用DDD戰術模式>在基本領域模型中套用領域驅動設計(DDD)的戰術模式(Tactical Design Pattern),找出聚合(Aggregate),達到封裝與決定交易邊界的目的。這一集要處理程式碼最多的TaskList。

***

分而治之

TaskList程式碼如圖1、圖2所示,這時候可以將execute mehtod所呼叫的哪幾個private method升等成Class,以簡化TaskList的長度,並且可以觀察原本這些private method與TaskList之間的耦合關係。

 

▲圖1:TaskList程式碼,1/2

 

▲圖2:TaskList程式碼,2/2

***

Use Cases Layer新住戶

Teddy將這些被升等成類別的private method放到usecase package,如圖3所示。現在Clean Architecture已經慢慢成形,最重要的兩層(entity與usecase)已經都有「住戶」了。

 

▲圖3:將TaskList的private method升等成類別

***

 

區分Command與Query

為了讓use cases layer的成員責任更佳明確,Teddy進一步套用CQRS設計模式。同時,利用use case來「吶喊」系統功能;請參考圖4。

 

▲圖4:在 use cases layer吶喊系統功能,並將讀寫分離。

***

接下來看一個Command的程式範例,圖5為AddTaskUseCase介面,這是一個in port,讓第三層的Rest Controller呼叫。

 

▲圖5:AddTaskUseCase介面

 

Teddy把實作Use Case介面的物件稱為Service,圖6為AddTaskService程式碼。

 

▲圖6:實作AddTaskUseCase的AddTaskService

 

Query程式與Command類似,差別在於兩者實作的介面不同,請參考圖7與圖8。

 

▲圖7:ShowUseCase介面

 

▲圖8:實作ShowUseCase的ShowService

***

剩下的execute

重構至此還沒討論圖1中的execute method,它的用途是用來呼叫use cases layer的那些Command與Query。Teddy一樣幫它座艙升等為類別,請參考圖9。但是這個升等之後的Execute class不像use case,比較像分派工作給不同use case的dispatcher。在架構上現在還妾身不明,Teddy先把它直接丟在use cases layer最外層。

 

請考圖9,Use case layer重構至此已經差不多了。其中有一些細節,像是Repository、Mapper、DTO、Presenter這些設計模式,全部寫出來內容太多。請容許Teddy偷懶一下,在此省略。有興趣又有錢的鄉民,歡迎報名參加重構既有系統:邁向整潔架構實作班,課程中會有詳細說明。

 

▲圖9:重構後的完整usecase package目錄結構

***

下集預告

重構至此Clean Architecture的四層已經完成了兩層,下一集要處理interface adapters layer。

***

友藏內心獨白:人口越來越多,物件村快變成物件「市」了。

2024年9月17日 星期二

重構既有系統,邁向整潔架構 (5):第二回合,套用DDD戰術模式

September 17 16:20~17:57

▲被封裝在聚合內部的咪咪

 

工商服務

想了解本系列文章完整內容,請參考重構既有系統:邁向整潔架構實作班。課程介紹與報名網址在此:https://teddysoft.tw/courses/refactor-to-ca/

***

前言

上一集<重構既有系統,邁向整潔架構 (4):第一回合,分層與移除基本型別依戀>已經形成了基本的領域模型,這一集要在領域模型中進一步套用領域驅動設計(DDD)的戰術模式(Tactical Design Pattern),找出聚合(Aggregate),達到封裝與決定交易邊界的目的。

***

領域模型: 決定Entity, Value Object與Aggregate

圖1是上一集重構後的領域模型,ToDoList, Project, Task是Entity,Project Name是Value Object。為了簡化起見,Teddy將整個領域模型包成一個ToDoList Aggregate。

在DDD中,Aggregate與Repository是一對一的關係,一個Aggregate透過一個Repository存入資料庫。決定了Aggregate的邊界,之後如果有儲存領域模型狀態的需求(絕大多數的軟體系統都會有持久化的需求),只需要實作ToDoListRepository即可。

 

▲圖1:領域模型的四個類別

 

***

 

將Entity Id升級成Value Object

DDD的Entity是一個有「唯一識別符號(unique ID)」的物件,原本的ToDoList缺少這個id,因此新增ToDoListId value object作為它的id。Project可以用ProjectName當作它的id,至於Task有一個long id屬性可以當作它的id,但是考慮到以後Task id有可能是使用者自己指定的字串,因此一併幫它新增TaskId value object作為它的id。

增加兩個Value Object之後的領域模型如圖2。

▲圖2:領域模型現在有六個類別

***

 

封裝聚合

DDD的Aggregate是一個交易邊界,同時也是一個封裝單位。操作Aggregate內部物件的動作必須透過AggregateRoot,以避免客戶端破壞Aggregate Invariant。如果Aggregate回傳它內部Entity給客戶端,客戶端不可以直接修改這個Entity,以避免客戶端繞過Aggregate Root修改了Aggregate。

換句話說,Aggregate如果回傳內部Entity參考給外部物件,則這個Entity應該是唯讀物件

舉個例子,圖3是ToDoList(Aggregate Root)的getProjects()方法,回傳其內部的List<Project>。客戶端拿到這個List<Project>物件之後,有兩個途徑可能繞過ToDoList而破壞封裝:

  1. 直接在List中增加一筆Project。
  2. 直接修改某個Project的內容,例如在Project身上新增一個Task。

第一點可以透過回傳一個「不可修改的List」來避免,至於第2點就只能靠ToDoList將Project轉成自己設計的ReadOnlyProject來避免。

 

▲圖3:ToDoList::getProjects() 程式碼

 

ReadOnlyProject的實作很簡單,請參考圖4。它直接繼承Project,然後覆寫所有會改變狀態的methods,直接丟出UnsupportedOperationException。

▲圖4:ReadOnlyProject程式碼(部分)

 

Project與Task都需要一個唯讀版本,重構後的領域模型現在有8個類別,請參考圖5。

▲圖5:領域模型成長到8個類別

***

 

下集預告

經過一番努力,重構至此領域模型終於有物件導向領域模型的樣子。但是一開始看起來很「礙眼」的TaskList程式依然沒變,還是原本那個150行、看起來亂亂的樣子。沒關係,下一集Teddy再來對付它。

***

友藏內心獨白:重構也要價值驅動。

2024年9月16日 星期一

重構既有系統,邁向整潔架構 (4):第一回合,分層與移除基本型別依戀

September 16 17:48~18:40;19:49~20:39

▲從下層爬往上層的咪咪 (by 常玉)

 

工商服務

想了解本系列文章完整內容,請參考重構既有系統:邁向整潔架構實作班。課程介紹與報名網址在此:https://teddysoft.tw/courses/refactor-to-ca/

***

前言

前三集聊了:
  1. 重構既有系統,邁向整潔架構 (1):為什麼透過重構改善軟體架構很困難
  2. 重構既有系統,邁向整潔架構 (2):逆轉重構流程
  3. 重構既有系統,邁向整潔架構 (3):Task List Kata簡介
這一集終於要動手重構。
***

分層原則

Teddy在第二集提到要採用由上而下的方式來重構,首先套用Clean Architecture,確定架構分為四層,如圖1所示。
 
▲圖1:套用Clean Architecture的分層原則
 
其中Task這支只有不到30行的程式很明顯地屬於Entities Layer,將它移到entity package。150行的TaskList目前還不清楚屬於哪一層,先不移動它。
 
***
 
物件村沒人怎麼辦?
Teddy的重構目標是在架構上採用Clean Architecture,在Entities Layer與Use Cases Layer則是套用DDD(領域驅動設計)的戰略模式語言(Entity, Value Object, Service, Aggregate, Repository等)。現在「物件村(domain model)」只有一個Task,顯得有點孤單,要想辦法增加物件村的人口。
 
物件導向設計,顧名思義就是要透過物件(領域模型)來表達問題領域的業務邏輯。這個Task List Kata重構範例只有兩個物件,這種現象有一個可能性,就是設計者對於「基本型別依戀」,捨不得使用物件,只用了String, Int這些基本型別。因此,接下來Teddy要採用「只管移除基本型別依戀」的方式,來增加物件村的人口。
 
***
 
無腦移除基本型別依戀
請參考圖2,第17行Map<String, List<Task>> tasks,將它「座艙升等」成Tasks物件,如圖3所示。
 
▲圖2:TaskList程式碼片段
 
 
 
▲圖3:移除基本型別依戀,新增Tasks物件
 
***
套用Value Object
圖3中的Map<String, List<Task>> tasks,其中Map的key代表project name,因此將其座艙升等成Value Object,請參考圖4。
 
▲圖4:ProjectName value object,用Java record代表
 
***
 
引入共通語言(Ubiquitous Language)
請參考圖5,此時Tasks類別的第6行變成Map<ProjectName, List<Task>> tasks,這還是一個基本型別依戀。請問一個擁有一組Project Name對應到List<Task>的「概念」要怎麼稱呼它?在此Teddy將其稱為Project。因此我們進一步將Map<ProjectName, List<Task>> tasks重構成List<Project> projects,參考圖6。
 
▲圖5:Tasks類別
 
 
▲圖6:Project類別
 
 
最後,Teddy把Tasks類別改名成ToDoList,現在物件村已經有四個物件,請參考圖7。
 
▲圖7:物件村從1個住戶增加為四個住戶
 
***
 
下集預告
有了物件村的住戶(領域模型),下一集要在領域模型中套用DDD戰術模式(tactical design patterns),好好了解一下什麼叫做Aggregate, Entity, Value Object。

***

友藏內心獨白:只有一個物件變成全村的希望,這樣壓力太大。

 

2024年9月13日 星期五

重構既有系統,邁向整潔架構 (3):Task List Kata簡介

September 13 20:30~22:07

 

前言

上一集<重構既有系統,邁向整潔架構 (2):逆轉重構流程>Teddy提到只要「大膽假設」不管你是開發什麼系統,就是要套用Clean Architecture就對了。如此一來,便可將重構從「由下而上」的設計方法轉變成「由上而下」的設計過程。

接下來這幾集,Teddy將以Task List Kata為例,說明如何將既有系統的架構重構成Clean Architecture。

***

Task List Kata介紹

Task List Kata是一個公開的重構練習,程式碼可參考:https://kata-log.rocks/task-list-kata。如圖1所示,它有8種不同的語言版本,Teddy使用Java版本。

 

▲圖1:Task List Kata支援的語言

 

如圖2所示,Teddy將Task List Kata複製到自己的repository,並將package name改成tw.teddysoft.tasks。

 

▲圖2:Task List Kata專案目錄

 

Task List Kata原本只有三支程:

  • Task:參考圖3,這是一支只有不到30行的程式,很簡單,好像沒什麼需要重構。
  • TaskList:參考圖4、圖5,這是一支約150行的程式,看起來很亂,感覺是重構的重點。
  • ApplicationTest︰整合測試,當重構進行時可以執行這個測試案例確定沒有感變舊有的程式行為。

 

▲圖3:Task.java程式碼

 

▲圖4:TaskList.java程式碼, 1/2

 

▲圖5:TaskList.java程式碼, 2/2

***

鄉民們怎麼重構

首先,了解需求。Task List Taka的介紹網頁提到 (用ChatGPT翻譯成中文):

 

***

任務清單

這是一個對基元(primitives)過度依賴的程式範例。

基元是任何具有技術性質且與您的業務領域無關的概念。這包括整數、字符、字串和集合(列表、集合、映射等),還有執行緒、讀取器、寫入器、解析器、異常處理等任何純粹專注於技術問題的事物。相比之下,這個專案中的業務概念,如「任務」、「專案」等,應被視為您領域模型的一部分。領域模型是您所運營的業務的語言,將其應用於代碼庫有助於避免使用不同的語言,從而幫助避免誤解。根據我們的經驗,誤解是造成漏洞的最大原因。

練習

嘗試實現以下功能,同時逐步重構以去除基元。在完全重構代碼以移除基元之前,儘量不要實現任何新行為,也就是說,只有在您即將更改的代碼已被重構後,才進行變更。不要重構無關的代碼。

一組判斷基元是否已移除的標準是,只允許基元出現在構造函數的參數列表、本地變量和私有字段中。基元不應該被傳遞給方法或從方法中返回。唯一的例外是基礎設施代碼——與終端、網絡、資料庫等進行通信的代碼。基礎設施需要將數據序列化為基元,但應視為特殊情況處理。您甚至可以將基礎設施視為一個獨立的領域,具有技術性質,其中基元是該領域的核心概念。

您應該嘗試將測試包圍在您正在重構的行為周圍。一開始,這些測試大多是高級系統測試,但隨著進展,您應該會撰寫更多的單元測試。

***

上述說明已經提示了重構方向:「優先考慮去除primitives」,也就是去除重構中提到Primitive Obsession(基本型別依戀)壞味道。但是一般人看到這個練習,直覺的想法是:「把大的拆成小的」。很多人會先把TaskList的private methods像是showaddsetDonehelperror等「座艙升等」,各自變成一個class,並套用Command設計模式,讓execute可以執行不同的命令。

接著,為了產生這些不同的命令,又套了Simple Factory。然後呢…….嗯,就沒有然後了。此時TaskList程式長度剩下原本的1/3,抽離出來的Command也符合單一責任原則,程式碼也很短,感覺好像沒什麼明顯地方需要重構了。

***

 

換你想

在正式談Teddy如何重構Task List Kata之前,請鄉民們也想想看,如果是你,你會如何重構?

***

工商服務

想了解本系列文章完整內容,請參考重構既有系統:邁向整潔架構實作班。課程介紹與報名網址在此:https://teddysoft.tw/courses/refactor-to-ca/

***

友藏內心獨白:搞錯順序只會徒然浪費時間。

2024年9月10日 星期二

重構既有系統,邁向整潔架構 (2):逆轉重構流程

September 10 07:38~08:08;11:30~11:49

      

▲圖1:Ada逆練九陰真經

 

前言

上一集<重構既有系統,邁向整潔架構 (1):為什麼透過重構改善軟體架構很困難>Teddy提到重構是一種「由下而上」的設計,而設計本身應該採用「由上而下」的過程,這也是為什麼透過重構改善軟體架構會如此困難的原因。

為了簡化重構軟體架構的難度,要想辦法將重構流程改成「由上而下」。

 

***

怎麼做?

要「逆轉重構流程」,其實很簡單,就是先確定架構目標就可以了。例如,假設鄉民是Uncle Bob的粉絲,不管手邊有什麼軟體,就是要想辦法無條件套用Clean Architecture就對了。如此一來,你就有了軟體架構重構的目標:Clean Architecture。

現在Teddy把架構重構的問題轉換成如何套用Clean Architecture,Teddy用Pattern Language的方式來解釋這個套用的過程,請參考圖1。有五個模式支撐Clean Architecture:

 

▲圖1:Clean Architecture底下有五個模式

 

上述五個模式的套用順序,先從Four Layers開始,將系統分成以下四層(四個不同的packages):

  • entity
  • usecase
  • adapter
  • io
      

有了大方向之後,接下來就是把你的既有系統想辦法塞入Clean Architecture這四層之中,如圖2。

 

      

▲圖2:Clean Architecture的四個階層

***

下一集Teddy將會以Task List Kata為例,說明如何將既有系統的架構重構成Clean Architecture。

***

 

工商服務

想了解本系列文章完整內容,請參考重構既有系統:邁向整潔架構實作班。課程介紹與報名網址在此:https://teddysoft.tw/courses/refactor-to-ca/

***

友藏內心獨白:道理很簡單,要做到卻不簡單。

2024年9月5日 星期四

重構既有系統,邁向整潔架構 (1):為什麼透過重構改善軟體架構很困難

September 5 21:02~22:06

▲Ada:我不會逆轉重構但我可以逆轉自己!

 

前言

今年四月Teddy開了一門新課程:【重構既有系統:邁向整潔架構實作班】。以往的開課流程Teddy總是先寫部落格文章,再設計課程,但這門課Teddy卻是直接設計課程而沒寫部落格文章。這系列文章算是「補寫」原本應該出現的文章,第一集先談為什麼軟體架構層級的重構很困難?

***

重構是一種設計

大部分鄉民應該都知道重構是在不改變程式碼外在行為的前提之下,藉由改變它的結構達到增進設計品質的一種方法。既然重構可以「改善設計」,因此可以將重構視為一種設計方法

Teddy將設計方法區分為兩種:

  • 由上而下:先決定設計目標,然後由上而下展開子目標,最後展開到一個可以施工的工作單元。例如,傳統的物件導向分析與設計就是一種由上而下的方法。先確定專案願景,然後展開需求、設計領域模型、軟體架構。
  • 由下而上:不確定最終目標是什麼,先從手邊可接觸到的「東西」著手設計,再慢慢將這些「東西」兜成更大的「東西」,透過這種方法完成設計工作。重構本質上就屬於這種設計方法。

***

 

設計應該是由上而下的過程

根據建築師Christopher Alexander的看法,設計是一種由上而下個過程。這就好比敏捷社群常說「以終為始」是一樣的道理,你希望達到什麼目標,就以這個目標當作設計的出發點。這樣講鄉民們可能還是覺得有點抽象,Teddy舉領域驅動設計中的戰術設計模式(tactical design patterns)為例,請參考圖1,Model-Driven Design模式是這個模式語言的「起點」,也是這整個設計最「頂」的模式,也等於這個模式語言的「目標」。

翻成白話文就是:領域驅動設計的戰術設計就是Model-Driven Design。如果看到這模式鄉民們就懂了,就開悟了,底下的其他模式也就無需再看。

 

▲圖1:領域驅動設計的戰術設計模式語言

 

***

再舉一個日常生活的日子,假設你晚上要請朋友吃飯,你要先決定「去那裡吃飯」?例如吃路邊攤、快炒、日式料理、韓式料理或是西餐等。如果是吃快炒,接下來才是決定要點什麼菜、什麼湯和飲料。這就是由上而下的設計思維。

***

由上而下那又怎樣?

重構作為一種由下而上的設計方法,用來達成區域改善是很有效的方法。例如,用Rename重構幫變數、method、class、package取個可以代表它們意圖的好名子。有沒有改善設計,當然有。改善後的設計對軟體架構的影響是什麼?不知道(不明顯)!

同理,用Extract Method把Long Method變短同時又用有意義的method name來代表程式碼的意圖。有沒有改善設計,當然有。改善後的設計對軟體架構的影響是什麼?不知道(不明顯)!

這就是透過重構要達到改善軟體架構很困難的原因。要採用由下而上的方式改善軟體架構並非不可行,但這類似演化的作法,需要一段很長、很長、很長的時間,以至於在一般專案中變得不切實際。因為鄉民們沒有那麼長的時間可以透過演化的方式「長出」一個好架構出來。

***

怎麼辦?

答案就在前文中。其實很簡單,就是要想辦法將重構改成由上而下的設計方法。只要做到這點,透過重構改善軟體架構就變得不再那麼遙不可及。

今天先聊到這個,下一集Teddy再來談如何「逆轉重構」,把它改成由上而下的設計方法。

***

工商服務

重構既有系統:邁向整潔架構實作班課程介紹與報名網址:https://teddysoft.tw/courses/refactor-to-ca/,有興趣的鄉民歡迎參考。

***

友藏內心獨白:好久沒出來亮相了。

2024年3月10日 星期日

2024 新課程:【重構既有系統:邁向整潔架構實作班】

March 10 21:59~23:14

▲實作Clean Architecture需要了解的「設計模式」

 

前言

2023年七月Teddy開始每天錄製一則YouTube影片之後就荒廢了部落格寫作,這兩天有鄉民提醒Teddy:「blog也重要,文字也是好東西」。鄉民說得有道理啊,還是要分配點時間給blog才對。

2024年第一篇blog,就先打個廣告,介紹泰迪軟體的最新課程:【重構既有系統:邁向整潔架構實作班】。

***

課程介紹

Teddy在幾年前開過軟體重構的課,當初的想法是完整介紹Refactoring這本書,從Bad Smells出發,然後舉很多小例子說明不同的重構方法如何移除這些壞味道。這種重構方式固然有用,但Teddy總是覺得有點「小打小鬧」的感覺,對於整個系統的架構改善有限。就好像「你花了時間把家裡整理乾淨,但對於整個市容其實沒什麼影響,還是一樣中華民國美學:斑駁的外牆、陽台外推,以及到處都是鐵皮屋加蓋的違建。」

軟體架構層面的「大規模重構」,一直是很困難的一件事。去年Teddy與ezKanban團隊著手開發ezDoc:一個Living Documentation(活文件)系統,功能性需求開發完成之後,這幾個月花了很多時間在重構系統。一開始團隊也是採用傳統「由下而上」的重構方式,重構完成之後,可能是受到這幾年深入研究整潔架構(Clean Architecture)與領域驅動設計(Domain-Driven Design)的影響,Teddy突然有一個想法:「設計應是由上而下的過程,如果反過來先確定就是要把軟體系統重構成Clean Architecture,接著再依據Clean Architecture的架構指導原則並套用DDD戰術設計模式來重構系統,會有怎樣的結果?」

Teddy與ezKanban團隊把ezDoc的兩個主要功能:Living Readme(活自我說明檔)與Living Glossary(活字彙表)依據這個想法重構,期間Teddy另外找了Task List Kata這個很經典的重構範例來驗證這個做法,發現的確比傳統由下而上的重構方式要好很多。

Teddy整理了一套「整潔架構驅動重構方法(Clean Architecture-Driven Refactoring)」,就誕生了這個課程(還是要想辦法賺錢XD)。在這個課程中,Teddy以Task List Kata作為範例,逐步說明Teddy所發明的「整潔架構驅動重構方法」。這門課不使用紙本講義,Teddy會先引導學員思考一個核心的設計問題:「為什麼軟體架構重構很難?」,接著Teddy用實作的方式,藉由重構Task List Kata,把逐步將「整潔架構驅動重構方法」介紹給學員。在這個過程中,主要由Teddy在課堂上引導設計思考與重構程式碼給學員看,學員則採用mob programming的方式,以組為單位撰寫Teddy所安排的練習範例。

課程涉及Clean Architecture與領域驅動設計的以下內容:

  • 分層原則:將軟體架構分為四層。
  • 建立Entities Layer:透過移除基本型別依戀壞味道尋找物件,建立通用語言。並使用DDD戰術設計模式,遵守Aggregate Root設計原則。
  • 建立Use Cases Layer物件、區分Command Use Case與Query Use Case(在使用案例層讀寫分離)、依賴反轉、依賴注入、套用Repository、Controller、Presenter、DTO(Data Transfer Object)、Mapper等設計模式。。
  • 在Interface Adapters Layer形成Controllers、依賴注入、Presenter設計模式的使用方法討論。
  • Main Component,使用Spring Boot作為依賴注入框架。
  • 在Interface Adapters Layer增加Web Controllers (使用Spring Boot)。
  • 使用Persistent Object 以滿足跨層原則,重新設計Repository介面與Mapper。
  • 使用關連式資料庫,透過 JPA (Java Persistence API) 使用Spring Boot連結H2資料庫。

課程練習範例Task List Kata有C#, Go, Java, Kotlin, Python, Ruby, Scala, Typescript這幾種語言,上課練習Teddy用Java語言示範,團隊mobbing也是使用Java。使用不同語言的學員在了解「整潔架構驅動重構方法」並看過一次Java重構範例後,在課後可選擇自己熟悉的語言重新練習一次,將你所常用的語言範例版本重構成整潔架構。

▲Teddy套用Clean Architecture重構後的Task List Kata,包含測試案例由3個Java程式變成106個。

***

報名網址

本課程今年上半年兩個班次已經確定開課:

  • 2024年4月22、23日(一、二)
  • 2024年5月25、26日(六、日)


課程介紹與報名網址:https://teddysoft.tw/courses/refactor-to-ca/,有興趣的鄉民歡迎參考。

***

友藏內心獨白:一個課程四種享受—Refactoring、Clean Architecture、DDD與Teddy。

2023年9月23日 星期六

練好基本功

September 19 21:00~21:35

 

今天跟ezKanban團隊mobbing,Teddy說:「我這兩天跟別人講理,你們有沒有注意到一件事情,就是平常mobbing我會一直問你們定義。我知道定義,所以我不怕跟別人講理。」

定義,很重要,也很無聊。想走捷徑的人,只看到別人光鮮亮麗的表皮,看不到別人蹲馬步時的付出。抄襲了皮,外表漂漂亮亮,骨子裏還是Teddy的指導教授常說的那句話:「只有薄薄的一層,一刮就掉」

這不是,Teddy才說一句話,一個定義,一刮就掉。

Teddy在北科上課會告訴學生:「Teddy和學生之間是平行關係,不是上下關係,Teddy只是在課堂上扮演老師的角色而已。上課Teddy會問你們很多問題,你們對我說的話如果有疑問,也可以直接說。如果我說錯了,最好可以打臉我。」

Teddy帶的學生,應該都覺得Teddy很嚴格,甚至嚴厲。Teddy常跟他們說:「實驗室很單純,外面世界很黑暗,壞人很多。你不把專業能力練好,出去很容易被壞人唬得一愣一愣的。」我好歹也是在業界工作的人,先讓你們體驗一點人性險惡,以後出校門才有抵抗力。

壞人的專業能力不會比你好,但他強在「夠壞」。這一點,我們永遠比不上,也不想比上。

***


Teddy在外面開課,都是先寫部落格文章,然後再整理成上課教材。Teddy可以說,收費課程的教材內容,絕大部分我都放在部落格上。Teddy做事不會留一手,知道什麼寫什麼,並提供參考資料。我巴不得鄉民們追朔源頭,多讀書。

沒錢上課的學員,只要肯學,把「搞笑談軟工」部落格文章讀完、讀懂,Teddy相信在軟工這一塊,絕對可以排進台灣軟體工程師的前10%。付費上課的學員,是Teddy的衣食父母,沒有他們,泰迪軟體就經營不下去。

這就是Teddy照顧小白、普通人、大神、有錢人、沒錢人的方法。

所以,Teddy不主動參加社群活動,把時間留下來專心讀書、寫作、寫程式,還有這幾個月開始新的嘗試:錄製YouTube影片。以前的敏捷高峰會和這幾年的DDD TW年會,都是主辦單位看得起Teddy,主動邀請參加。不邀請了,人家不需要了,也就不參加了。

台灣的社群活動,主辦單位很辛苦,也有很負責的講師。但是也有一群人,Teddy沒有實際測量過,但希望是一小群人,到處刷存在感、打知名度。這種人,空殼子又想出名收割韭菜,先搞小團體,放一些稻草人,再互相取暖。


這也是一種Pattern,叫什麼、什麼神來著?

***

2023年9月22日 星期五

改行寫網路小說算了(25)

September 20 07:39~09:34;11:16~11:48

  

▲畫面來源:電影「九品芝麻官」

 

上課

開場旁白:不知道是不是因為教改的緣故,這些年學生的造句能力越來愈差,今天國文課小明老師來幫同學做個造句練習。

***

小明老師:請同學依據以下句型,在空白處填入你覺得最合適的文字,老師會依據同學的作答內容來評分,選出第一名給予表揚。

我當然也是讀了_______的文章加入_______,也有拜過碼頭,但我沒錢上_______的課,所以得到了屬於我自己的見解(大多數和_______的見解是一樣的,但少數是不同的)。

我跟_______一樣的見解是_______,不同的見解是_______

***

水豚君同學造句練習

小明老師出完題目之後,班上最聰明的班長水豚君同學第一個跳出來作答。

水豚君:老師,我想好了,以下是我的造句。

我當然也是讀了愛因斯坦的文章加入物理系,也有拜過碼頭,但我沒錢上愛因斯坦的課,所以得到了屬於我自己的見解(大多數和愛因斯坦的見解是一樣的,但少數是不同的)。

我跟愛因斯坦一樣的見解是E = mc²,不同的見解是物理的「理」就是品質

***

稻草人同學造句練習

水豚君話音剛落,副班長稻草人同學接著說:

我當然也是讀了Kent Beck的文章加入TDD陣營,也有拜過碼頭,但我沒錢上Kent Back的課,所以得到了屬於我自己的見解(大多數和Kent Beck的見解是一樣的,但少數是不同的)。

我跟Kent Beck一樣的見解是先寫測試再寫程式,不同的見解是TDD的「Development」就是品質

***

蔣孝華同學造句練習

第三位作答的是班上的開心果,蔣孝華同學。

蔣孝華:老師,各位同學,我的造句和前兩位同學不同,比較生活化且呼應時事。

我當然也是讀了唐綺陽的文章加入星座趨勢分析,也有拜過碼頭,但我沒錢上唐綺陽的課,所以得到了屬於我自己的見解(大多數和唐綺陽的見解是一樣的,但少數是不同的)。

我跟唐綺陽一樣的見解是本周天蠍座的朋友水星逆行,須提防小人,不同的見解是星座趨勢分析的「分析」就是品質

***

王同學造句練習

我當然也是讀了_______的文章加入_______,也有拜過碼頭,但我沒錢上_______的課,所以得到了屬於我自己的見解(大多數和_______的見解是一樣的,但少數是不同的)。

我跟_______一樣的見解是_______,不同的見解是_______

***

小明老師:王同學。

小明老師:王同學、王同學,老師在叫你怎麼不回應?

王同學:(抬頭望著老師)

小明老師:這個練習,你為什麼不作答?

王同學:老師…..這個句型…..我……不會寫(啜泣聲)

小明老師:王同學,沒關係。來,老師秀秀,不哭、不哭。

小明老師:這樣吧,老師看水豚君同學造句表現最好,一開頭就搬出舉世聞名的諾貝爾獎得主愛因斯坦大神當例子(豹子頭:先嚇嚇他),整個氣勢、高度與企圖心就是不同。而且水豚君同學居然可以在碼的多重宇宙,只花不到10秒,就同步發現愛因斯坦花了一輩子才想出來的E = mc²公式,堪為全班表率、台灣之光。

小明老師:這樣子,老師請水豚君同學下課後來教你,好不好?

王同學:….好….好……..喲……謝..謝..老.師…..

***

下課

小明老師:好,各位同學,今天課就上到這邊,等一下中午吃營養午餐,今天的主食是韭菜水餃,請值日生稻草人同學跟蔣孝華同學到廚房領取。對了,記得要多拿一點,不要讓集體肚子餓著了。

小明老師:下課。

水豚君同學:起立、立正、敬禮。

全體同學:謝謝老師。

***

友藏內心獨白:找水豚君來教王同學,這個小明老師,是GTO嗎?。

2023年9月20日 星期三

鐵帽子王事件的Teddy觀點

September 20 12:30~14:43 

▲先看個貓照片消消火 XD

 

緣起

Teddy明明是一位被鄉民認證過的文人,這幾天卻搞得好像變成武將一樣。Teddy就再講一個文人與水球潘的故事,扳回點文人的形象。

幾年前,水球潘加Teddy FB好友。認識Teddy的鄉民應該知道,Teddy基本上不加沒在真實世界見過面的人為好友,但Teddy加了水球潘。為什麼?因為看到Teddy的指導教授鄭老師,也是水球潘的好友。

Teddy看了一下水球潘公開在FB的基本資料,事隔多年如果記憶有錯請更正,他是銘傳大學畢業,當時正在唸台大資工碩士

Teddy知道鄭老師認識台大資工系的老師,於是自己腦補:「會不會是教授們彼此有交流合作,因此當時還是學生身份的水球潘,才會認識鄭老師?」

Teddy也不會為了這麼小不拉機的事跑去跟鄭老師求證,於是就加了水球潘好友。

這中間,如果沒記錯,Teddy應該沒有跟他有什麼互動。一直到疫情期間的某一天水球潘分享一個Clean Architecture範例。Teddy也在教Clean Architecture,因此下載來參考看看。這是一個很小的專案,Teddy覺得水球潘的Repository設計有可以改善之處,於是留言告訴他。

當時Teddy對於水球潘的反應就覺得有點奇怪,說不上來,有一點他不太歡迎Teddy給他的建議的感覺。

***

第二次接觸

第二次是水球潘在「搞笑談軟工臉書社團」跟Teddy討論Value Object,Teddy覺得水球潘對於DDD Building Block的一些基本認知,從Teddy的角度來看,是錯的。一開始Teddy很有耐心地跟他討論,但後來對於他那種幾乎可以說是詭辯的態度,真的受不了,放棄。

認識Teddy的人應該看得出來,Teddy對水球潘的耐心,已經超過對一般鄉民的耐心。為何?還不是看在鄭老師的面子上,自己腦補說,總是老師認識的學生,就包容一些。

接下來就是今年8/11~13,Teddy在上「Design Patterns這樣學就會了–入門實作班」,有學員跑來問Teddy是否認識水球潘?他用跟Teddy一樣的講法也在教Design Patterns。

 

 

 

這事件,因為「鐵帽子王」事件(水球潘在搞笑談軟工FB社群送給Teddy的幾頂帽子)發生後,Teddy才在FB公開。如果Teddy在意,在八月上課當下就馬上在FB發文了酸水球潘,不會忍到前幾天。Teddy當時笑笑地告訴學員「我知道這個人,他有加入搞笑談軟工社團,我跟他不熟,印象中是很認真(我知道他有弄社群活動)的人,也很有主見。之前他跟我在FB討論過事情,但雙方看法不同。」

當時問Teddy問題學員,好像有參加水球潘的活動,如果有看到,可以出來佐證。

當時Teddy對於水球潘,一句不好聽的話都沒說,甚至還小小小的誇他。

為什麼?還不是看在鄭老師的面子上。

***

現況

再來就是這幾天發生的事。上禮拜日下午,因為禮拜六剛參加完DDD TW 2023年會,想說在YouTube找看看有沒有更新什麼影片上去,於是下了DDD關鍵字,就看到水球潘的影片。點開一看,一開頭解釋DDD的Design,Teddy覺得基本觀念就錯了。以下是Teddy當時的貼文:

閒來無聊在YouTube找DDD的影片,看到這個影片中說到:DDD的「Design的意思其實就是品質。」
Domain-Driven Design的「Design」不是在講品質,而是「決定邊界」,這是基本中的基本。

我只聽到這裡,後面的內容我就沒聽了。

 

 

水球潘一開始非常強勢,覺得Teddy是「文人相輕」故意找他麻煩。但他卻後來又自己承認,他的說法應該稍加修正。一般人遇到這種情況,就說聲:「噯呀,口誤」,這不就沒事了。

後續水球潘的回應,就是給Teddy扣帽子、潑髒水。更有趣的是,水球潘還自爆內幕:



既然他都自爆他向Teddy「致敬」的內幕,那就不好意思,水球潘已經用完鄭老師面子點數

***

內心話

這中間還穿插一些,從Teddy的角度來看,屬於幼幼班行為的事情,就不提了。

事情演變至此,問題已經不是原本討論關於「Design」定義。Teddy早上去復健,吊脖子的時候在想,以Teddy的身分,在台灣軟工界,不敢說是大佬,好歹也是小佬:

Teddy寫文章、經營泰迪軟體、寫書、辦C. C. Agile社群活動(曾經XD)、經營臉書社群,都已經十年以上,還有最近釋出DDD、DBC與BDD/SBE開源軟體、錄製YouTube頻道等。另外,Teddy的學歷,再怎麼不濟,好歹也是個本土博士(北科大資工)以及北科大兼任助理教授。

Teddy這樣的人,水球潘都敢跑到Teddy經營的「搞笑談軟工社團」來鬧。如果Teddy這次又包容水球潘,日後一般軟體工程師對於水球潘的分享如果有任何疑問,誰還敢發言啊?

看到有些鄉民的思維,有時Teddy都會懷疑:這是在台灣還是在中國?喔,你放在網路上公開廣告的教材內容,不准任何人公開提出疑問?那你不會不要放廣告膩,這樣就沒人會批評了啊!

***

若干年前神收割了一波小白韭菜,很抱歉當時Teddy實力不夠,也不懂神的技術,幫不上忙。但Teddy自己偷偷覺得,應該有小小阻擋了一下神的勢力蔓延到Agile這邊。賣東西卻不允許別人討論產品內容,態度還這麼囂張,這是什麼樣的生意可以這樣?想想這些轉職者與技術小白,真的是挺可憐的,想要努力變好,還要被騙。有種海龜寶寶破殼而出,努力爬向大海的途中,還有一堆海鳥等在旁邊要吃他們的即視感。

***

友藏內心獨白:我不入地獄,誰入地獄。

改行寫網路小說算了(24)

September 19 16:10~18:50

 

炸神誕生

約莫2500年前,羅剎國的土地上出現了一位傳說中的神級人物。其出生地、父母、生日與姓名均不詳。因成年後的職業為農夫,且養馬,江湖人稱馬農

馬農雖為農夫,但並不耕作,專以收割別人土地上長出的韭菜為生。因為騎馬,跑得快,上面坐個老太太 眾多受害農夫想抓馬農久已,可惜連他的馬尾燈都看不到,反倒吃了滿嘴灰。於是農夫們集體討論想出一個辦法,準備很多鞭炮,當馬農出現時,用鞭炮炸他身體,把他轟下馬。

某日,馬農出現在羅剎國的霄霄村,準備再次收割別人農田中的韭菜。就在此時,一位正好在田邊樹陰下大便的農民發現馬農。農夫顧不了WIP,稍微施力剪斷大便,立馬讓WIP歸零。農夫緊接著來到工作間拿出準備以久的鞭炮丟向馬農,並大喊:「炸他身體、炸他身體」。無奈,馬農騎術優良,能打勝仗,一轉眼就消失在樹林中,隱姓埋名,從此江湖中再也無人見過馬農。此後,農夫們改稱馬農為炸身---炸他身體的簡稱。炸身、炸身,農夫們希望喊久之後,下次再見到馬農,可以炸他身體,一炮斃命。

若干年後,炸身的傳奇故事,傳來傳去,不知怎麼地居然被神格化。炸身被尊稱為炸神,持續保有一群忠實信徒,不離不棄。

***

主角小刀

本故事主角,小刀,是村民所認證的三字經知識權威,以三字經教學為生。小刀平日閉門在家讀經,鮮少涉足農田,自然不知曉炸神這號人物。小刀第一次看到神的名字,是在「小刀讀經班」的課堂上。

消失多年的神,再次下凡化身為一位普通書生。神在課堂上的表現,並沒有特別引人注意。上課當時,小刀有眼無珠,還不知道眼前這位平凡書生,就是大名鼎鼎的炸神(奏樂,噹噹)!

在課堂上的經文討論活動中,神總是特立獨行。不是默默不語,自顧自的下著他帶來的一盤大旗(當下流行的一種虛擬挖人礦桌遊),就是大言不慚地發表一些驚世駭俗的言論。難道是神覺得小刀的三字經講解的不到位,所以故意搗蛋引發關注嗎?好像也不是這樣,因為神還報名了一次夜間讀經活動,應該是對小刀的三字經有信心才是。神在課堂上的表現實在是太平凡了,完全沒有神該有的樣子,小刀一直以為神就是個普通書生,還好心告訴神一些關於讀經的建議。

直到多年後,才有高人在夢中告訴小刀,當年那位在課堂上不起眼的書生,其實就是神,大名鼎鼎的炸神!

***

所有的大神都有一個共同特點,就是具備一擊必殺的神邏輯。神用神的視野「發現」平常人老早就已經知道的東西,並將其宣稱為神發明。例如,神再次發現了火,可以煮飯;水,可以喝;屎,可以施……….肥。多麼了不起的的發明啊!一般人類,是無法用人邏輯與神溝通。因為,神,活在神界!

神邏輯還可以不必遵守人間一切物理定律。

神說智慧,就有了智障

 

不可以質疑你的神!

***

有人說,神的口才很好,擁有大批信眾。每逢初一、十五,信徒提供大量韭菜供養神,讓神過著優渥的生活。關於神的好口才這個傳聞,小刀無法證實。因為在短短兩次聆聽神諭的機會中,化身為書生的神,是那麼的低調。涉世未深的小刀,著實體察不出神的嘴砲神功之威力。

有了信徒的供養,神此後不用再騎馬割韭菜。神賣掉了馬,出門改搭屋駁,一種有蓋子的轎子,負責在霄霄村內短期通勤之用。

又過了幾年,神再度轉趨低調,眾多信徒們已有多年沒有神的消息。

***

神蹟再現

此刻,神再次降臨。本番下凡,雖然神的性別不明、長相不同,但能力依舊。

神在下凡時大喊一聲:

萬能的天神,請賜與我葛雷堡神奇的力量!

神說獨創,就有了模仿

可憐,凡間

小白盛開的田裡

韭菜塗炭

***

後人寫詩一首以茲紀念:

智慧曰智障

獨創模仿

施展神邏輯

引燃自爆彈

***

友藏內心獨白:橫批--集體智障。

2023年9月19日 星期二

創業初期的陳年往事

September 19 05:01~06:17

 

▲就好像吃飯睡覺一樣,還不是你做什麼他也做什麼

 

緣起

上周六Teddy參加了DDD TW 2023年會活動,禮拜天下午閒來無事在YouTube上找DDD的影片來看。滑到某個影片,沒想到因此發生了一連串讓人哭笑不得的事,細節Teddy就不重複描述,今天想聊一件陳年往事。

***

永遠的泰迪之友

十年前泰迪軟體剛成立沒多久,有一位YA先生主動找Teddy聊天。YA先生早年也經常出現在「搞笑談軟工部路格」文章,當時他在新創公司上班,遇到一些問題。因為敏捷開發是當時泰迪軟體的主要業務,YA先生想了解導入敏捷開發能不能對他的工作有所幫助。

YA先生是一位非常熱心的人,幾年前他去了德國工作,是Teddy心目中永遠的泰迪之友。因為YA先生是泰迪軟體成立之後第一位找Teddy「諮詢」的客戶,Teddy當時也是剛創業的菜鳥一隻,雙方約在北科大對面的伯朗咖啡聊聊天。Teddy並沒有跟YA先生收費,只是讓他請了一杯飲料。可能是因為這樣,YA先生覺得過意不去,好心找Teddy去跟他們公司的新創顧問談一談,看看對Teddy的創業有沒有什麼幫助。

***

Teddy記得對方是一位長相帥氣的年輕ABC(以下就以ABC稱呼這位先生),對話的時候英文、中文交錯使用,好像在美國某創投公司待過。由於年代久遠,細節Teddy已經記不清了。ABC聊到創投的一些生態,他說以前他們常常看很多新創的案子,因此衍生出一些快速篩選案子的原則。就好比大公司HR每天可能收到幾百份履歷,總不可能每份都逐一閱讀,因此用學歷、畢業學校作與工作年資為條件,快速過濾掉不符標準的求職者。

ABC:有一種case,就算是business model再棒,我們絕對不會投。

Teddy:為什麼?

ABC:因為非法!

ABC:我們看過一個case,公司計畫從YouTube下載各種影片、音樂,然後再提供服務給第三者。

ABC:侵權、非法的case,就算他們現在活耀的使用者數量再多,我們都不考慮,這是底線。

Teddy原本以為新創公司因為新的業務模型,遊走在法律邊緣是很常見的,不然當年YouTube一開始營運上面不是有很多非法的影片。不知道是這位ABC待過的創投比較不一樣,還是這是一個業界標準,當時Teddy也沒多問。

***

結論

老美對於做生意不可剽竊他人智慧財產這件事,相對而言還是比較嚴肅看待。在美國念書,如果作業被抓到抄襲,是一件很嚴重的事情。

抄襲者為什麼要抄襲別人?因為可以彎道超車,自己不用花很多時間,就可以看起來好棒棒。抄襲的過程中,不只被抄襲的人受害,消費者也受害。

先幫「小白」默哀三秒!

***

友藏內心獨白:用新的謊去圓舊的謊,就容易自爆。

2023年7月10日 星期一

搞笑談軟工YouTube頻道開張

July 10 18:24~18:36

 

▲用講的好像比用打字寫部落格文章還要簡單啊

緣起

6月20日Teddy舉辦「你就是寫太多測試才會沒時間: 在領域驅動設計與事件溯源架構中使用合約式設計」線上活動,並錄影。活動結束後Teddy準備把影片放到YouTube上,原本泰迪軟體就有一個YouTube頻道但是都沒有經營,只放了兩個影片。想一想,這幾年Teddy比較少寫部落格文章(常寫文章打太多字、用太多滑鼠,很容易肩頸痠痛),幹脆試著錄影用講的,看看能不能吸引到另外的客群幫泰迪軟體拉點生意。

於是,就開了搞笑談軟工YouTube頻道。目前打算先來個一年的每日更新,Teddy每天放一個影片,分享一些Teddy覺得對軟體開發人員會感到有趣且有用的知識(常識XD)。 

頻道網址在此:https://www.youtube.com/@TeddyChen,歡迎舊雨新知幫Teddy訂閱、按讚、分享、開啟小鈴噹 XD。

***

友藏內心獨白:影片一刀不剪,因為我也不會剪。

2023年7月4日 星期二

買到還不錯用的筆電收納架

July 04 18:48~19:22


  

▲圖1:把兩台筆電立起來收納

前言

Teddy有兩台筆電,第一台是2018年從Amazon買的LG gram 15,這台筆電非常棒,很輕續航力又強,這的是沒什麼好挑的。唯一的問題是年華老去,速度有點跟不上,去年不知哪根神經不對勁,居然買了Asus UX5401Z。Asus 這台筆電,才14吋但體感重量比起LG gram 15,有種沉甸甸的感覺。如果是買水果沉甸甸也就算了,買筆電沉甸甸真的不優。

不過今天不是要談筆電,而是要談筆電收納。Teddy平常在家中工作,使用的是2019 iMac 27”,筆電只有外出上課時才會用到。這兩台筆電,平時就被Teddy丟在不同的位置,平躺著有點占空間。前天晚上在PChome上面隨意選了「YUNMI 重力感應筆電直立式收納支架」,收到之後沒想到還不錯用。今天介紹這個支架,提供有需要的鄉民做為參考。

***

非廣告


 ▲圖2:PChome的產品介紹畫面

 

502元,價錢還可以。Teddy以前曾經想買一個筆電收納架放Apple Air與MacBook Pro,但後來換了iMac之後就作罷。這次是整理書桌,順便把找個架子收納筆電。看到這個產品,可以收納多台筆電,抱著可能採雷的覺悟,就買了。

 

▼開箱之後就一個塑膠做的架子,長成下面這樣。


  

▼準備放下兩台筆電,還沒放到底部,此時筆電架還沒有夾緊


▼放到底部之後,筆電架就將兩台筆電夾緊。

   

▼空拍圖


***

結論

▼收納之後將筆電放在書桌後方,留一條Type C線讓兩台筆電輪流充電,還行。

 

***

友藏內心獨白:可能因為難得沒採雷所以特別高興。