(跑步拼圖)為何步頻要 180 ?

最早接觸到步頻的觀念,是在徐國峰的分享影片中開始的:

平常跟跑友交流討論時,也常常聊到嘗試將步頻提升到 180 以上的部份。

但是,為什麼呢?

我只知道在步頻提升到 180 以上後,節奏跟輕鬆度都有顯著的不同,但對背後原理不那麼清楚。直到我偶然看到 Terra Plana 影片後,才明白背後的道理。

View post on imgur.com

( 影片 5:40 ~ 6:40 片段 )

以原地跳躍為例,當我們以180以下較慢的節奏在跳時,我們可以感覺到大腿肌肉比較吃肌力,而當身體以180以上較快的節奏在跳時,其實會感覺到身體多了一股小腿的彈力。

也就是說,將步頻拉高到180以上,能激發身體在跑步中使用更多的彈力。而彈力是比肌力更具力學經濟性的動力方式。讓我們跑步能更省力更輕鬆。

這也就是為何一般建議步頻要 180 以上的原因。

了解背後的原理後,我們也不一定要拘泥在 180 這個數字,因為重點還是在於高步頻能激發彈力的運用,180 只是一個通用經驗值,並非死硬不可調整。(步頻若偏低的話,也不利於彈性機制的發揮)

此外,並非要步頻 180 以上才是正確的跑法,個人認為,跑步不同的步頻就好像變速腳踏車有不同的檔速一樣,只是跑步技術中的一個環節,每個人適合偏好不同,並不需要太過執著於誰對誰錯。

不過,若是能保持開放的心態,嘗試上手不同步頻的跑感,對跑步技術跟經驗的提升是有很大幫助的。畢竟同樣的不開車,有駕照而選擇不開車,跟沒駕照而不會開車,本質還是不同的。只要對身體無害,多接觸多學習總是好的。

(跑步拼圖)平衡板與骨盆平衡

平衡板是指這個:

View post on imgur.com

話說某次跟女友到迪卡儂逛街時,發現角落有這個玩具,幾個小孩子們在那邊搶著玩。小孩子們散去後,我跟女友也試著去挑戰看看,然後,我們就敗了一個帶回家玩了。

幾次練習適應後,雙腳很快就能站上手了,開始覺得有點無聊。後來突發奇想說,雙腳可以,那單腳有辦法嗎? 我來挑戰看看吧!經過 N 天,不斷的歪七扭八、自我安慰、挫折、憤怒、自我懷疑、不服輸、… 不斷的練習調整後,我終於抓到單腳站平衡板的訣竅了。最後達到左右腳都可以穩定站到 30 秒鐘以上的程度,平衡板真的可以單腳站,不唬爛

但更重要的是,我還得到了另一個最珍貴的發現,我發現右腳站跟左腳站的動作,骨盆的角度有”一點點”不一樣。右腳單腳站立的時候,我左邊骨盆習慣性的稍微偏低,而這似乎跟我右腳傷傷的問題有關!?

當時發現這個線索的當下,我立刻上網 google搜索。中文資料找沒有,改找”骨盆”的英文字 “pelvis” ,然後便發現了一些跑步跟骨盆平衡相關的影片和文章,發現的當下,有種恍然大悟的感覺,原來我右腿膝蓋傷的原因的源頭,是我的骨盆平衡出了問題了啊!(有興趣的人可上網google搜尋 pelvis+drop的資料)

讓我們來看看幾張圖片吧:

View post on imgur.com

(Run Analysis With Coach Jesse Kropelnicki )
來源: https://www.youtube.com/watch?v=27QgZYgHBcI

View post on imgur.com

(解剖列車 p.207 圖 9.51)

View post on imgur.com

(瑜珈解剖書 p.89)

在看了上面幾張示意圖之後,我想骨盆平衡跟跑步肌群結構的關聯性不言而喻。而我個人的經驗是,在我修正骨盆平衡問題後,右膝蓋內側的傷痛問題也漸漸消失了。

那麼,骨盆平衡怎麼修正呢? 其實答案很簡單,就是練習單腳站平衡板。(註: 閉眼單腳站的練習也有幫助,但平衡板的效果更顯著)

練到可以輕鬆穩定的站著,在靜態站上手了,之後再加上動態的擺臂抬腿盪腿,然後記住站平衡板的體感平衡的感覺,嘗試將那感覺也帶入跑步的感覺中。

那練平衡感會有什麼樣的改變心得呢?分享如下:

(一)首先,我發現到臀中肌會被使用到,一般椅子坐久了,臀中肌大多退化了,而平衡板能有效激發臀中肌的使用,而臀中肌對骨盆平衡大有幫助。一旦臀中肌回位出力,那其他肌群的代償性出力就省下來了,肌群緊張緊繃減少,跑步感覺變得更輕鬆放鬆一些。

(二)其二是,進入平衡的關鍵是骨盆,只要骨盆穩了,整體就穩了。相對的,骨盆一歪,身體就止不住的傾倒。而膝蓋、腳踝則是試著讓人體自然反射調節,靠反射性反應速度才夠快,大腦控制是來不及的,只要避免受傷、別躁進即可。

(三)其三,人在失去平衡時,就會變得緊張緊繃,例如像是睡覺不小心掉到床邊的那瞬間,整個人會反射性的驚覺那樣。相對的,全身平衡時,也會自然呈現放鬆的感覺。簡單來說,平衡就是放鬆,放鬆就是平衡。所以,放鬆的訣竅就是抓對平衡,而要評估自己平衡的上手程度,只要看是否能在平衡板上輕鬆站上30秒以上,而且腳也沒有緊繃痠累的感覺即可評估。

(四)此外,一旦抓到能輕鬆站平衡板的訣竅後,你就永遠會了。就跟你學會騎腳踏車一樣,10年沒騎也許會有點生疏,但你的身體還是會記得如何騎腳踏車。

(五)骨盆平衡的跑姿會像什麼樣子呢? 如果你希望有個更具體的跑步參考對象,我建議可以參考 Paula 的影片:

我還記得我第一次看到 Paula 的影片時,第一印象只注意到搖頭晃腦,(跟大家常推薦的Dibaba比起來)怪不優雅的。直到我意識到骨盆平衡的重要後,再回頭看Paula的影片才驚為天人,她的平衡、節奏實在是經典中的經典。

而這樣的領會經驗也讓我明白,外觀上的分析常常只能提供部份的線索,跑步中的內在平衡只有跑者自己才真正知道。在觀察不同跑步style時,我們不妨多試著思索外觀背後的隱藏內涵,避免輕下斷言。

以上,是我個人的幾點心得。

希望這些分享對您有幫助 ^_^

備註: 平衡板迪卡儂有賣,其實不貴,約400-450TWD,如果能幫助讓你少進一次診所的話,實在不失為一筆划算的投資。(p.s. 好像漲價過2次了,而且常缺貨,有興趣快買一個吧~)

(跑步拼圖)彈簧動力理論

之前在某個投影片分享中看到這張圖,直覺這一定跟跑步關鍵原理非常有關

View post on imgur.com

後來我循線索找到原始論文

Biomechanics of walking and running: center of mass movements to muscle action

作者: Claire T. Farley , Daniel P. Ferris

看了內容之後,覺得真的是撿到了關鍵拼圖。

首先,論文提出在跑步中,腳是扮演像彈簧一樣的角色,來移動重心

View post on imgur.com

另外,也指出走路跟跑步的差別,在於正中間時跑步是重心最低,而走路是重心最高。

View post on imgur.com

及跑步速度快慢的差別

View post on imgur.com

最初看到這裡的時候,我心裡想,只是作個彈簧的比喻而已。

很多跑步的教學理論都有它們的示意圖,有比喻成輪子的啦,鐘擺的啦,各式想像都有,實在沒什麼好奇怪的

但事情不是只有這樣而已,

因為科學家透過測力板跟數據模擬分析,發現

View post on imgur.com

View post on imgur.com

實驗測量的結果,發現腳輸出力量的方式,跟彈簧動力模式吻合

也就是說…

彈簧動力模式並不是想像,而是真實的跑步運作模式

這在跑步原理的探索中,定下一個非常關鍵的基礎

想進一步了解彈簧動力理論的話,也翻閱參考下面這個簡介投影片

http://slideplayer.com/slide/9163240/

看到這裡,若對上述的內容細節不了解也沒關係,只要好好記住開頭的第一張示意圖

日後遇到討論跑姿或跑法的動力原理時,都可以回頭與彈簧動力理論對照檢視

步頻、步距、離地高度、抬腿、前傾、推蹬…等問題,都可從這張圖中去找關鍵的線索喔。

(跑步拼圖)前言

The puzzles of running

自 2015/01/12 以來,連續維持跑步的習慣已經快2年的時間了。
我跟很多人一樣,也是從氣喘吁吁的1公里,慢慢成長到能輕鬆完成的10公里,過程中,經歷受傷、復健、打掉重鍊,慢慢成長一路上來。
我並有沒有上過跑步課程,也没有教練指導或遵循某些教材學派,
而是自己從跑步過程中,遇到問題時就記下來,自行上網找資料,還有從別人的經驗分享中,慢慢摸索研究。
這些心得,就像碎片一樣,東一塊西一塊,散落在不同角落。
隨著收集到的碎片越來越多,漸漸的發現有些碎片是可以接在一塊。
小碎片們變成了大碎片們。
一開始我想著,這些碎片們最後是不是會串起一條循序漸進的道路
直到有一天,我突然領悟到。
它們並不是一條路,而是一張圖
每個碎片都是這張圖中的獨立存在的一小部份,彼此沒有高低優劣, 誰先誰後,既是起點,也是終點
一開始完全沒頭緒,但隨著碎片們慢慢接合在一起,逐漸勾勒出輪廓的延伸再延伸
有時會發現原以為不好的症狀,其實是來自於人體的自癒機制
另有時會發現,某些訓練方式的原理,和另一項領域的問題研究相通
而隨著的輪廓逐漸連貫擴展開來,心中的視野與迷惑逐漸明朗,心情也莫名地開心了起來
就好像拼圖一樣,越到後面就越有感覺
常常有人問我說,為什麼我會喜歡研究這些東西,我想或許就是這種感覺吧.
回想這一路走來摸索跑步的成長過程,不正也像是在拼一張拼圖嗎?

你心中也有張想去完成的拼圖嗎?嘗試去發堀完成它吧!~

(跑步拼圖)習慣的開始

我不討厭跑步,甚至是蠻喜歡的,但高中畢業後,就很少跑步了,為什麼呢?

我總是以簡單的”懶惰”當理由來搪塞過去。

我老是把當年勇掛在嘴上,偶然1~2週多運動個幾次,但始終沒有持續下去。直到某次在百貨公司逛街遇到特賣會,買了條運動長褲後,跑步習慣就又再度恢復運轉起來,持續至今没有再中斷了。

真没想到,這樣的改變,僅僅是從買了一件運動長褲開始。事後想想,其實就只是因為,冬天很冷,早上醒來想到要穿短褲出門很被動, 就又放棄倒頭繼續睡。所以,一條不起眼的運動長褲,將這個阻力消除後,我就又再跑起來了,解決方法真出乎意料地簡單。

今日再回頭看時,才真正明白,跑步最困難的一段,不在於出門後跑多高多遠,而在於踏出門的這一步。

“出門30分鐘,起跑3秒鐘”

在出門前,有太多的因素讓我們駐足不前了。


* 今天好像會下雨?
* 衣服好像不適合跑步?
* 鞋子好像不適合跑步?
* 鑰匙錢包放口袋不好跑?
* 水壺不趁手?
* 褲子不好穿?
* 衣服清洗麻煩?
* 手機放哪?
* 天涼外套衣服放哪?
* …

然後,在我們在想說要不要出門跑步時,我們的大腦就在 0.333 秒的瞬間把所有因素掃描加總,最後得出一個感覺

“算了,下次再說吧~”

所以,要重拾跑步的習慣,我們不一定要立下什麼高遠目標才能作,其實我們只要試著將每一次出門前的潛在阻力都一一消除就好了。


Q: 今天好像會下雨?
A: 準備帽子跟防潑水衣物,或換裝配套。

Q: 衣服好像不適合跑步?
A: 給自己買件穿起來有自信的跑衣吧

Q: 鞋子好像不適合跑步?
A: 買一雙喜歡的跑鞋吧~

Q: 鑰匙錢包放口袋不好跑?
A: 找個跑步用背袋/腰袋/臂套

Q: 褲子不好穿?
A: 買條跑褲

Q: 水壺不趁手?
A: 換個水壺或找個水壺背帶

Q: 衣服清洗麻煩?
A: 找透氣易乾易洗的材質

Q: 手機放哪?
A: 買個跑步臂套或背帶吧~

Q: 天涼衣物放那?
A: 尋找健身中心,參加跑團互相幫忙顧東西,或放車上置物箱

你會發現,每當消去一個阻力因素,要下出門的決定,變得越來越輕鬆,越來越不困難。跑步也漸漸從一個負擔,慢慢變成一個想走就走的娛樂。

當你不再需要用一個又一個目標來鞭策自己,而能自發性的輕鬆出門時,相信跑步這習慣,將長久地成為你生活中的一部份了。

(跑步拼圖)誤打誤撞的跑一休一

去年(2015)跑完臺北馬之後,覺得已完成了一個人生經歷了,不想再把練跑填滿行事曆的每一天,希望能以一個更舒服的生活節奏來享受跑步這件事。於是我給自己一個新的目標,7分之123456,意思是,每7天跑12公里3次,跑速維持4’56,大概就是週二、四,各跟團跑1小時,週末再抽空跑個1~2小時這樣。

雖然,依當時的體力跟身體狀況,每天跑不成問題,但每天這樣下去,跑量強度只會想越撐越高,跑步佔的時間也越來越多,最後生活中滿滿都是跑步。這並不是我想要的生活,所以希望去作點改變。

但作這樣的改變之前並不是沒有擔心的,因為”每天跑”跟”隔一天跑”,本質上其實是不一樣的,就好像每天上班的正職工作跟只上一半班的兼職工作的差別一樣,不只是時間上的差異,在興趣的專注度/習慣制約/生活比重/…上都有很大的不同。誰曉得我會不會從休一天,變成休兩天、三天,越休越久,最後失去了跑步的熱情呢?!我真的能克服這樣的人性關卡嗎?

10個月後的今天,我想我通過了這個考驗,在此也想說說自己在這改變之後的心得和發現:

1. 跑團的定期團練,對興趣的維持是很關鍵的力量,因為一個人跑難免感到孤獨。我很幸運,在這段時期,一直有週二的R2R中正團,週四的台北圓山團(前R2R圓山團),週四的熱血凸台的固定團練活動可以參加。能和喜愛跑步的跑友一起跑步聊天,真的是我持續跑步的一大動力,謝謝你們!

2. 開始跑一休一之後,我意外發現10KM的跑步表現沒有退步,反而進步了(緩慢但持續的進步)。以前跑步前常出現的疲累倦怠感也不見了,變成是一種身體想跑、心裡也想跑的雙重期待感。之前遇到下雨天會覺得好像撿到一個休息的藉口,想說反正每天跑,明天再補就好了,輕鬆之時卻又有點意志不堅的罪惡感。但現在跑一休一卻覺得有種”好像放假要被取消”一樣的難過,無論風雨都要拼一下,不然就要再等個兩天才能再跑了的珍惜感。

3. 雖然 10KM 進步了,不過長距離的有氧耐力確實有退步。不過這一點後來在週末補上 LSD 後,就改善了。

4. 更常遇到 DOMS(延遲性痠痛)。我一開始還以為是自己退步了,而且還退步的這麽快、這麼明顯。但幾次細心記錄體察後,發現並不是,我觀察到的現象是這樣,假設我週二晚上跑,隔天週三的早上腿可能感覺正常,甚至還有種剛充完電微微暖和的感覺,不過一到週三下午或晚上,就漸漸開始浮現延遲性痠痛的症狀,通常會在週四上午達最高峰,過週四中午後就逐漸消退,然後週四晚上退完剛好接上跑步。有趣的是,DOMS 難預測,有時週三早上覺得雙腿極好,殊不知晚上一樣痠痛,也常常發現 DOMS 出現在預料之外的位置,即使加強伸展收操,痠痛的感覺跟週期似乎依然故我,簡直就像開彩券對獎一樣,*BUT*(特別強調) 如果我週三早上或下午在痠痛出現前,有再一次跑步(20-30min以上)的話,晚上的痠痛就消失不見了!或許這就是常會聽到的”比賽完隔天緩和跑”的建議,是一樣的道理。不過,我並沒有這樣作,相對的,我甚至有點期待DOMS的出現,因為在DOMS期間,我常常會反覆去摸索定位痠痛點的位置,嘗試不同的分解動作跟姿勢,看看能不能找出是那個環節在作怪,借此修正我跑姿方法上的缺陷,就好像兇手留下的線索越多,就越容易破案一樣。DOMS留下的痠痛線索越多越明顯,我高興都來不及了,怎麼還會想把它抹去呢!? 相較於大多數的人對於DOMS,無不用盡各種方法,非得除之而後快。我這樣的想法,的確容易讓人覺得離經叛道吧。但我始終堅持下來,一直到我讀到解剖列車一書後,才發現自己這樣的堅持,竟誤打誤撞的得到另一個更大的益處。

5. 一般跑步受傷的,比例最高的是肌腱,也就是肌肉與骨骼的軟組織筋膜,一般跑步拉傷去看復健科時,或許你會發現診斷書上寫的就是肌腱炎。這說明,跑步環節中,肌腱所佔的關鍵腳色。然而,肌腱並不像肌肉一樣有血管通過,而是以膠原蛋白為主成分進行消耗與修補,速度緩慢很多。在”解剖列車”一書中提到,而人體在作完有強度運動後,膠原蛋白修補週期如解剖列車內中所提供的這張圖所示:

View post on imgur.com

在劇烈運動完後,肌腱內含的膠原蛋白會同時有分解跟合成的進行,有點像都市更新,一邊拆房子,同時也一邊在蓋房子。週期前半段是拆得比蓋得快,所以淨值是負的,處於虧損的狀態,一直到約 36 小時後,才終於轉虧為盈,然後在 72 小時後慢慢達到新的平衡。再細看一下圖表細節,合成分解的進行約在 24 小時達到最高峰,然後在 24~36 小時之間,淨值虧損慢慢減緩並轉虧為盈。咦!?,這週期還有現象時間順序,不正恰好就跟我經歷到的 DOMS 痠痛週期不謀而合嗎?!!! 意會到這一點的當下,心中似乎響起了一聲叮咚,而我跑一休一的節奏,也就是相隔48小時的時間,身體也正好處於自然修復後”盈餘”的狀態,沒想到當初自以為是的堅持,竟然不知不覺中恰好符合了身體自然修復的週期,這巧合實在令我不禁感動香菇。回想之前還在每天跑的時期,其實身體當下是正好處於 24 小時,膠原蛋白淨值虧損最大且正在積極自我修復的時候,會感覺倦怠且容易受傷,其實是再自然不過的事了。

6. 此外,解剖列車也提到(解剖列車 p.214),膠原蛋白的半衰期是1年,因此,肌腱筋膜的養復,不像肌肉成長3個月那樣快速,而是需要 6~24個月這樣長的時間,因此養護方式的不同,短期內是看不出來的,但隨時間增長,健康與受傷的兩者傾向之間的差距就會越來越大,也無怪乎書中所提的”需要溫和的毅力”了。

7. 在我慢慢發現跑一休一箇中的好處時,又意外發現背後的秘密原理之後,而我又是個雞婆之人,往往會想跟身邊的跑友一起分享心得,也熱切主動的想說服別人跟我這樣作,巴不得所有人也能跟我一樣得到有相同的好處而感到共鳴。不過,很不幸的,我似乎從來沒有成功過 XD。你也知道,要一個每天跑步的人,中間停下來休息個一天,簡直跟要死了一樣的難過,然而,當跑量過度受傷時,被醫生禁跑個2週(想當然爾,忍不到兩天就又開始偷跑了,呵),反覆輪迴如此實在矛盾。然而,對於我這樣一個雞婆的個性,常常忍不住一再出言提醒,卻往往也因此磨光別人的耐心而進了黑名單。其實我也曾受傷過偷跑過,何嘗自己也不知這種矛盾與難受呢? 幾次歷練下來後,我慢慢體認到,每個人的身體都是自己的,不管是愛惜還是虐待,都是每個人自己的選擇,而且這個選擇的背後,常常有太多我們不知道的因素,也許是某個承諾、某個信仰、某個成長背景…等等我們不了解的原因。而同樣的選擇,也許對我是最佳選擇,但對另一個人卻不一定是他的最佳選擇。所以我們應當謹記,尊重每個人對他自己所作的選擇,任何時候都是。

8. 承上,或許我的心得,不見得適用每個人,但我仍相信我的親身經驗,也許會對某個我完全不認識的陌生人有所幫助,這也是促成我寫下這篇文章的動力之一。如果你認同跑一休一的觀念,也幸運地能從中獲得好處,(謝謝,我很開心),同時又遇到跟我一樣的雞婆的困擾的話,我想引用 Jason Robillard 的 “更快更安全的赤腳跑步法”中的一段話 (The Barefoot Running Book, 徐國峰譯, p.161)
“””
如果所有的方法都失靈了,你就別管他了,自己跑得開心就好!臉上帶著微笑、好好地大笑,解放自我,全神貫注在赤腳跑步的體驗上,這會是宣導赤腳跑步的最棒方式。
“””

希望以上的分享,也對您有幫助

後記:
10個月後的今天,我發現我已經好一段時間沒有受傷了。當然,這段期間我所作的改變不只有跑一休一的部份而已,在伸展/赤足/平衡/… 都作了些不同的嘗試和調整。最近也首次達到了”連續三次跑後隔天完全沒有DOMS症狀”的狀態,雙腳感覺越跑越健康、強壯,腳傷的陰影也已漸漸散去,跑步時我甚至忘了腳曾經跑步受過傷這件事,身體彷彿已準備好要接受另一個階段的挑戰了。

註: 我並非醫師或專業教練,並不一定是 100% 正確無誤的。跟您一樣,我也有許多未解的問題跟謎團,也仍在摸索學習中,若您有任何建議or指正,都歡迎您的 feedback/交流喔,謝謝 ^_^

從零星的 copy fork 演進為 upstream 持續更新模式

繼上文 “git 分支運作模式之我見” https://6bcf7279.info/2015/07/Ok29jGJM/ 的論述後,下文繼續深入軟體開發面臨的問題與解決模式。

一個軟體有很多客戶使用,客戶A要客製化功能p+x, 客戶B要客製化功能q+y, 客戶C要客戶r+x+y, …。因應不同時期不同的客戶需求,同一套軟體可能因此有多個 fork branches。每個 branch 主體大致上是相同的,但可能約有 5~10% 左右是依客戶需求而特別訂製的。這樣的需求趨動下,常常會伴隨幾個特性狀況如下:

特性: copy fork
假設今天多一個客戶想要客製功能 r+y ,那麼可能就會找跟這個需求最接近的客戶C ( r+x+y ) 的程式,複製一份出來用,再去掉 x 功能。這樣子作最快最方便。

特性: 版本交錯
承 copy fork 的特性,因為是取最接近的而不是最新的,所以常常會有新舊版本交錯的問題。很多時候,新版本還有開發中,不甚穩定,所以此時進來的客戶需求,常常改以較穩定較有把握的舊版本來應付,再額外套上一些新開發的功能。此時,產生的分支常常是新舊版本交錯的狀況。

特性: bug重覆出現
承 copy fork 的特性,當複製了某一個功能時,同時也將該功能的 bug 也複製了。今天很可能客戶 A 的功能 x 出問題了,於是開發人員花了點時間將 A 的 x 功能給修正了。但基於種種原因,並未修正到 C 客戶的 x 功能。結果,過一段時間 C 客戶的 x 功能也出問題了,導致開發人員又花了重複的時間去修正 C 客戶的 x 功能。重複的問題,不但重複耗損開發人員的時間,同時也減損了整體的自信心。

特性: 修正更新狀態不一致
承 bug重覆出現 的特性,因為採取遇一個 bug 修一個的策略,導致多個分支之間的版本跟修正程式碼是不一致的。使得程式裡的特例越來越多,比如說,修正客戶 A 的 x 功能時,是以 A 的使用方式考量下設計。而修正客戶 C 的 x 功能時,則依 C 的情境作調整。那麼同樣的 x 功能,就又產生了 2 個分支。

形成狀態
根據上述種種特性,最終整個專案就難以避免的進入,bug散佈交錯,修正更新狀態紊亂不一致,程式碼交錯充斥 workaround,整體的開發複雜度持續增加,開發人員窮於應付不斷冒出的 bug 跟地雷,對於軟體品質的提升只是個偶然振作,而重複的問題一再複發卻束手無策。

落入這個狀況時,很多人第一直覺的反應常常是,”不夠努力”,或是覺得”程式寫得不夠好”,所以解決的方向常常是”要求要更努力地將程式寫得更好”,而這樣的想法就催生了 “重新開發新版 2.0” 的策略。然後,這樣的策略常常是失敗的。

重新開發新版 2.0 陷入的困境
因為在舊版中,長期累積的 bug & workaround hell,常是開發人員的夢魘。因此,另外成立一個新版本,並宣誓立即擺脫 bug & workaround 陰影,往往讓開發人員立刻感受到解放而有希望的感覺。然而,隨時間演進,卻常常陷入另一種困境,如下。

1. 重新開發的版本,往往不夠成熟,而沒辦法穩定上線。

想想,舊版本在過去不斷的測試跟修正,並調整成使用者能接受的程式,中間花了那麼長一段時間。新版本想要在那麼短的時間內,完成這個過程,談何容易。

2. 因為無法上線,而無法產生收益。

在沒有收益下,開發新版本的這條路,是一條以燒錢來爭取未來轉機的道路。相較於開發新版本的燒錢,改回舊版本提供給客戶,很快就能取得收益,而且時間越長,兩者相差的機會成本越大。在這樣的情境下,開發新版本受到的支持度越來越低,而回守舊版本的支持度越來越高。

3. 回守舊版本

此消彼長之下,最後仍決定回守舊版本。專案全體人員士氣大受打擊,因為努力振作一段時間,但最後一無所獲。更糟的是,開發人員開始意識到,在各項環境條件沒有大改變的情況下,永遠沒有脫離困境的一天。

另一項思路
有兩篇文章給我很大的啟發
* 約耳趣談軟體的 “CH24|你絕對不應該做的事之一”
* 約耳續談軟體的 “CH30|洗刷刷、洗刷刷”

根據上述的問題種種,我想提出另一個想法。

並不是我們不夠努力,也不是我們程式寫得不夠好,而是,我們的方法錯了。

陷入困境的關鍵因子
讓我們陷入 bug & workaround hell 的那個因子,其實是來自於 copy fork 那瞬間所產生的”無法一致更新的分支複本”。

也就是說,分支複本隨時間越來越多,版本跟不一致的狀況越來越嚴重,於是不斷增長的複雜度跟層出不窮的狀況,必然最後就壓垮耗盡了開發人員的時間跟腦力。

只要是 “無法一致更新的分支複本” 的問題存在,即使上述所採行的 “2.0新版本” 開發成功,還是很有可能在未來落入相同的困境。

所以,解決方向應該是針對 “無法一致更新的分支複本” 的這個環節來解決。

這個解決方法是存在並真實可行的,目前我得出的解決方法過程如下:

建立更新共同體

step1. 首先,先要考察所有分支的分支祖譜關係。

step2. 選定其中一個開發能量最集中,且跟各分支相容性佳的那個分支作為標竿,訂為 upstream

step3. 讓所有分支和 upstream 建立第一個 merge 關係。
注意, 是用 merge -s ours 來建立第一個 merge 關係,這一點非常重要。
因為,目標是建立連動關係,而不是一開始就要達成一致。

這三個步驟並不需要什麼大決心、大力氣。但已足夠讓所有分支俱備連動關係了。接下來的,就是一步一步的執行小改善的動作如下:

step4-1. 遇到一個 bug , 先假設這個 bug 是 email 寄送程式相關的問題好了。

step4-2. 研究出這個 bug 的根本原因,還有 dependency 狀況 ( 包括函式庫、影響到的程式有那些、那些分支有相同狀況 )

step4-3. 根據上述研究內容,製作一個可徹底解決問題、且能共通於其他分支的修正程式 patch

step4-4. 將這個 patch 提交進 upstream 分支

step4-5. 讓所有分支從 upstream 分支拉新的 merge update
在各分支拉 upstream 的 update merge 時,有的可能會順利 merge 成功,有的可能會 merge conflict。但預期的難度會在可控制的範圍內。主要原因是:
a) 因為一開始已經建立了 merge 關係,所以此次 merge 會從前一次的 merge base 參考點出發,也就是說,衝突的部份只會在這個 patch 的修改範圍內,而不會是一大群 conflict 列表
b) 一般來說, patch 相容性作的好的話,衝突的比例可降低。例如,20個分支,只有3個分支有嚴重衝突(即 15%),此時再針對這3個分支作針對性處理即可。

step4-6. 完成此次連動更新的修正。
在完成上述的動作後,預期所有分支的這個 bug ,並進行了一次”連動一致性”的修正。這個過程可能比往常多花了一些力氣跟時間(ex: 1.5倍或是 2~3倍),但是俱備下述性質。

a) 雖然多花了點成本,但因修改範圍相對較小,所以可控制在”覺得多作點工,但在可以平常心承受”的範圍內
b) 單次修正的成本雖然較高,但因為修正的較完整而徹底,這個 bug 可能就一次解決後就永遠的被修正而不再複發了
c) 修正的效果,重複了 N 個分支。其 impace 是 N 倍放大。
d) 因為是連動式的全體更新,所以在修正的範圍內,消減了一次複本問題下的複雜度。

繼續重複回到 step4-1.

在上述的流程下,我們進行一回合又一回合的清洗,每次清洗一點,進步一點。慢慢的,就會發現整個專案程式從雜亂無章的複本分支中,漸漸形成出跨越分支的一致性。

標準化、參數設定化、模組化

在上述建立更新共同體之後,已能抑制複雜度的增加,並逐漸收斂出一致性。不過收斂的速度有快有慢,收斂效率的關鍵在於軟體程式本身。

方法之一,參數設定化:

舉例來說,如果一些功能設定是寫死在程式裡面,像是 API Key/URL/… 的值之類的,那麼每次設定值一變更,程式就要修改,改來改去永遠無法固定下來。其實,解決方法很簡單,只要程式增加讀取設定檔的功能 ( ex: Preference/Setting/Configuration/… 功能 ),那麼,設定有變化時,只要改設定檔就好,程式都不用再改。簡單來說,就是將會變動的設定跟參數改由外部讀入,不但程式不需要再頻繁更改,也增加了程式的彈性。

方法之二,標準化

不同分支之間雖然各有差異,但仍有許多共同函式庫跟共用程式。然後,這些共用部份,可能因為函式庫的版本差異或是共用程式的不同小修改,而產生不同的邊際效應,而且這些共用程式常常廣泛的散佈在程式之間。若能將這部份的差異去除掉,那麼就能讓分支間的複雜度快速收斂下來。具體的作法,就是利用上述更新共同體的機制,一次更新某一函式庫至同一版本,一回合一回合地的清洗函式庫與共用程式,直到所有分支的基礎核心都同步一致。此時,各分支間的歧異性,就會因為有同步一致的基礎而有效控制下來了。

方法之三,模組化

當主體核心程式的變動越來越少,不免就會想到,客製化的延伸功能,是否能也像設定檔一樣,由外部載入而不需要更動主體程式。這樣的軟體方法就是模組化,舉例來說,外掛/插件就是模組化的設計,他讓軟體主體在不用更改程式下,能以動態外部載入的方式來增加新的功能。這個軟體方法能大大的降低程式主體的分支複雜度,讓主體核心越來越收斂越,並讓客製的複雜度有效的控制在個別的區域範圍內。

撇除上述三者的不同標題名稱,其實本質都是一樣的,就是如何在不更動程式的前提下,能透過動態設定的方式滿足需求。

Syntax sugar

另外,程式語法的微調跟一致性,也有助於複雜度的收斂。

例如,透過一些 coding style 的 policy 或是 linter ,能有效減少 space/whitespace/quoting/… 之類的歧異。

此外,程式的寫法有也差異,比如說:

CFG=”aaa bbb ccc”

增加一項 “ddd” 的設定時,會變成

CFG=”aaa bbb ccc ddd”

這個變動在 diff 工具的比對下,比較不那麼順手。另一種變形的寫法如下:

CFG=”aaa bbb ccc”
CFG=”$CFG ddd”

或甚至是一開始就是
CFG=””
CFG=”$CFG aaa”
CFG=”$CFG bbb”
CFG=”$CFG ccc”
CFG=”$CFG ddd”

這樣子的寫法,在 diff 工具下,就是呈現一行一行的差異,而且,不易產生 merge conflict 的問題。不管是 mark 註解到,重新排列,或是增加減少,都相對容易處理。

Ask, Do, Commit

受到姿勢跑法(Pose Method)將跑步簡化為 Fall,Pose,Pull 三個動作的啓發,我在想,寫程式是否也能有這樣的簡化?

回想了一下,自己寫程式的過程,似乎也可簡單分成幾個:

1. Ask
先問自己一個問題,或是從 issue tracker 裡挑一個問題。

2. Do
在問題的驅使下,開始去作一些事,如寫程式、調整設定,或是研究資料之類的。

3. Commit
作到某個階段就作個 commit ,可能是版本控制的 commit ,或是筆記的儲存。有點像是玩 RPG 遊戲時”遊戲進度存檔”的功能。

備註:
其中,我覺得第一步是最困難的,很多時候不知那根筋不對,腦筋就是無法進入專注。我發現到,我自己似乎比較常在被問問題,(尤其是有趣的問題),而腦袋開始想東西時,那瞬間好像有什麼開關被打開了一樣。