changyuheng 積分 2 編輯於

我想的方向不太一樣。有一種重複,是像開發 Android app 這樣,每一個開發 app 的人都要繼承 Activity (或 Service etc),並部分 overwrite parent 特定的實作。當很多使用 API 的開發者都在一樣的地方做相同的 overwrite 時,也可以看作是重複。

不當的抽象可粗分為二,一為對抽象對象的錯誤解讀造成的不正確的抽象架構設計或不貼切的描述,另一種是為了避免重複而做的過分集中的抽象。我們當然能避免重複,而不重複的方法就是在抽象層做統一的描述,但這同時也造成了收斂。收斂和僵化是一體兩面,因此收斂的同時也減少了彈性;實務上的影響就是未來擴充的東西,一定要能夠被抽象描述表達,這其實是一種畫地自限。

舉個簡單的例子,幾乎所有繼承 Activity 的 app 都要 call onCreate() 的 super(),這也是一種重複,那為何不在 Activity 中就統一做掉?相信這除了是原設計 Activity 的人,希望能在 Activity class 中擁有足夠凝聚的描述,也是希望使用 API 的開發者能對 Activity 的使用有一個制式的規格可以遵循。

建構程式就像拼拼圖,抽象集中的程度好比拼圖塊的大小,較集中的抽象就是較大塊的拼圖,而拼圖塊如果都太大,可能就沒辦法拼成想要的樣子。但拼圖塊太碎,也同樣不好用,而且經驗淺的程式設計師面對太小的碎塊可能會無所適從。我覺得要做出好的取捨的心法是,朝兼顧彈性、易用性但又不鬆散的方向做設計,而不是單純考量如何讓抽象層最凝聚、濃縮 (過度抽象) 或讓使用者做最少操作 (彈性最差)。

chchwy 積分 3 編輯於

抽象都要有明確目的,而不是盲目看到重複就抽象

對我來講,成功的抽象需要符合下面兩點之一

  1. 抽完 code 要變得容易理解
  2. 改動、增加新功能變得容易

簡單講,要反過來思考:已經確定抽象「真的有幫助」,才去進行抽象。

如果沒幫助,那就擺著很長的 if-else 沒差。

IngramChen 積分 2

所以要寫 test

如果比較好測,那通常是比較好的設計。你通常也只會重構到測試不會太難寫這樣,不會太過頭。(class 太多就測試更多,想到這你就會懶得抽這麼多層了)

測試可以引導設計,再加上一些經驗的累積大概不會錯太多。

當然如果寫的是 library ,會放出來給別人用,那又是另一種規則。

j0n 積分 0

這對我來說一直很兩難,原本單純易懂的 if-else 抽成複雜很難 trace 的 class/interface,究竟是真的有幫助還是炫技?

IngramChen 積分 2

這篇又浮上來了

method 加上參數,裡面多寫個 if 進行擴充 -- 這大概工程師每天都在做

所以我覺得這類型的還好,它要累積到一個程度之後,才要重構,看是要回到重覆或是抽得更多層。

出現問題的大部份都是太多參數,就是作者說的,抽象化錯了方向。另一種錯誤是太早將單純的 if 抽成更複雜的 class/interface,也不能說一定錯,但新需求多半不可預知,所以八成都是抽錯方向,不如不抽。

然後更難得問題是,這些修改不一定是同一個人做的…

IngramChen 積分 1

每次只要有機會用到 micronaut, 就有一種清爽的感覺

小, 簡單, 又快. 然後還大部份和 spring 很像

如果 spring 沒有包伏然後重開機的話, 大概就是 micronaut. 而不是現在的 spring boot.

但是你就是知道它不會變 spring 成為主流, 所以只能在小專案玩玩而已...

caterpillar 積分 3

還在慢慢寫中,也算是跟手機開發沾上點邊 … XD

changyuheng 積分 1 編輯於

答案是什麼 😂 第二個 number 要改成 1 嗎?

koji 積分 1

想到 這個1這個2 ,雖然上面有人提到IDE可能對 return heap 機會不多,但還是期待呀XD

chchwy 積分 1

被整碗端走,慘。但是說實話,我之前根本沒聽過 AppGet。

目前市場的領頭羊是 Chocolatey,Winget 能搶走多少市場還是未知數。

IngramChen 積分 1

還要到 java 15 才能用, 等不及了

除了 low pause 外, 用不到的 heap 還可以還給 OS, 這簡直是為了 intellij ide 設計的啊

koji 積分 0

阿對齁,他必須得讓 ThreadLocal 在 virtual thread 中行為像之前一樣,了解了。

IngramChen 積分 1 編輯於

他是說以前一定要寫 finally 去回溯/移除 自己放在 ThreadLocal 的變數,因為 Thread 多半有 pool,是大家共用的。

之後用 virtual thread 就沒人在共用了,所以 ThreadLocal 不用怕碰到別人塞的值,也不用 finally 去處理。

而你講的 sharing 是該 thread 被用的當下,很多人都想塞變數,這個的確沒變,要靠 Scope Variable 的結構減少忘記互蓋的問題。

koji 積分 1 編輯於

比較在意 ThreadLocal 關聯的應用場景..

Scope Variables1

var oldValue = myTL.get();
myTL.set(newValue);
try {
  ...
} finally {
  myTL.set(oldValue);
}

Without this imposed structure, when a thread is shared among multiple tasks, one task’s TL values might leak into another. Virtual threads solve that problem by being lightweight enough to not require sharing.

沒看懂,為何 lightweight 就不用 sharing.

IngramChen 積分 0

6MB heap == 一百萬 virtual thread

sweet!

IngramChen 積分 0

對對,沒錯

jdbc 應該沒人會去開 thread

實例應該是從 tomcat 那層開始開 virtual thread 就好,app 通通不用動

koji 積分 1 編輯於
應該可以像這樣?
web request virtual thread->
      socket -> (virtually blocking)
      business logic ->
      jdbc request -> driver socket -> (virtually blocking)

除非是為了 structured concurrency,不然可以不用再自己看到一層 virtual thread?

等等來看看他的 EA 能不能玩

IngramChen 積分 0

Even basic control flow, like loops and try/catch, need to be reconstructed in “reactive” DSLs, some sporting classes with hundreds of methods.

RxJava 就是你

一個 class 有上百個 method 就是錯錯錯,沒什麼好說的

能夠寫正常的程式的話,誰要寫 reactive,誰要寫 async/await

Project Loom 走在正確的道路上,成功後就會換其他平台來學

IngramChen 積分 0

virtual thread 真是讓人興奮

所以 jdbc driver 都不用改自動就會變 virtual thread ?

  web request ->
      socket virtual thread -> (virtually blocking)
      business logic ->
      jdbc request ->
          driver socket virtual thread -> (virtually blocking)

然後在兩次的 virtual block 中,背後 OS thread 可能已經換過,或是沒變這樣?