演講摘要: 我今天要講三個大主題:多工(Multitasking)、延伸大腦(Brain Extender)、決策(Decision Making)。 不過在開始之前我想先說一下為什麼我寫了這本書,過去十年的神經科學發現了許多「為什麼大腦對某些事情注意、而對其他事情忽略的」的原因。我相信大多數人都可以用這些資訊來更好的組織時間、家裡的事物、工作環境。 講了現代資訊過載的問題,一堆數字...。 我們可以怎麼做?大部分人想嘗試多工,不過現在的研究顯示,多工在人大腦是不存在的,大腦只能快速的在循序中切換。多工會造成釋放和壓力相關的...,幾個小時多工後會很累。大量多工的工作(航管員、同步口譯員) 都會安排中間休息的時間。根據研究,多工會降低產出。但大腦會欺騙自己多工也許是有用的,就像喝醉酒之後覺得自己很好一樣。 那我們要怎麼辦,我們可以像航管員、同步口譯員一樣中間休息一下。研究顯示這樣會讓員工有更好的生產力和更好的產出。像是每幾個小時就有15分鐘的休息。小睡一下很有用,白天小睡15分鐘有時候等於夜裡睡一個半小時的效力,能提高你的IQ 10點。小睡一下會讓大腦補充用完的 glucose;而中間休息可以讓你進入另一個不同的注意力模式。 人類大腦有兩種主要的注意力模式:中央主導模式(task positive network)、白日夢模式(default mode of brain / task negative network / mind wandering mode)。在白日夢模式你會開始覺得事物開始連結、以非線性思考的方式。所以在兩個模式交互切換是很重要的。 注意力切換(attention switching)和決策(decision making)會消耗大腦中的燃料。明確的說,會消耗讓葡萄糖(glucose),讓葡萄糖是神經元運作代謝需要的物質。而且讓葡萄糖並不能無限量供應,不管是大決定還是小決定都會消耗這個燃料。即使在挑選筆的顏色,你也在消耗人生重要決定的燃料。而切換到白日夢模式會讓你的大腦回到預設模式,讓葡萄糖(glucose)重新恢復。小睡一下、小中斷、去渡個假都很有幫助。當我說小中斷(take a break)指的並不是回電子郵件、去看個電視,這樣並不是中斷(break)。而是真正的中斷,讓你的大腦可以真正的做白日夢(really wander)。而我們每個人都有自己的方式可以開始白日夢模式。這個方式也許是,運動、在自然中散步... 像是快思慢想的作者,每天的下午都會找一段時間在史丹佛校園中散步,據他所說大部分的好想法都是那段時間產生的,這不是巧合,這是一個恢復的行為。 根據研究,那些一週工作六十小時的人的產出只有比一週工作四十小時的人的產出多七個小時。想一想是不是值得多花二十小時得到多七個小時的產出。 所以我們該怎麼辦,怎麼專注的做事情?一件專家會做的事是「強迫有生產力的時間」(enforce productivity hours)。他們會在一天中找一段時間,讓那段時間完全不會被中斷、打擾,關掉電子郵件軟體、甚至關掉手機。讓他們能進入全神貫注的狀態。如果你無法關掉電子郵件軟體,因為可能會有突發狀況進來,那試著開一個私下的帳號,告訴其他人有緊急的事才用這個郵件位置。不緊急的事請,送到那個公開不常開的帳號。 很多成功的執行長、藝術家都這樣的切分人生的時間,一次只做好一件事。 接下來我將切換到談,大腦延伸器(Brain extender)。這是一個簡單的想法。如果你想要有生產力,不要把不需要的東西放進大腦裡。像是聽到明天會下雨,與其在腦袋記著說要帶傘、要帶傘,還不如把這個資訊放到環境裡面去,像是把傘從櫃子拿出來放到門邊,然後它就會在你出門時提醒你。另一個例子是設計心理學中門的例子,為什麼人要記得門要推開還是拉開,直接用設計隱藏預設用途就好(拉的話放門把),像是廁所的門。另一個方式外部化是我們把事情寫下來。而把事情寫下來,其實比打字下來更適合,因爲寫字時的引發的神經活動是不同的,大腦會更深入的去處理這個資訊。最後一個例子是 Google,我們不用記得細節,只要記得關鍵字,就可以找到我們要的資訊。 最後我想說的是決策(Decision Making),我們現在擁有的資訊,能讓我們做出以前不能做出的決策。特別是在醫學上資訊的過載,而醫生並沒有受過大量資訊決策的訓練,像是取得和分析。我覺得我們的教育應該要開始改變,要教導資訊處理(information literacy),而不是之前教育的大量事實。教導他們要如何有創意的使用這些事實來幫助他們去解決真實世界中的問題。判斷資訊到底是否可信。舉例了醫生決策有多複雜,因為每種藥都有有效率、多種副作用的成功率。我覺得像這種判斷應該從八歲開始教。 —— 29:30 開始 Q&A。 做決策的時候先把事項排優先順序,在狀態好的時候把大事情處理完。 注意力缺失症?他們的白日夢模式很強,也就是說他們創意很強,但沒法做不完事情,也許他們可以和其他過度專注的人合作,會很成功。 Motor learning怎樣會有效率?光只是重複性的運動並不是很有效,你必須有意識地、有目的的做那件事。音樂家叫這個故意練習(deliberately practice)。鋼琴家想像練習時不光只有想像手指怎麼動,還要思考音符的意義.... blah blah practice mindfully. 夜晚六到十小時的睡眠,會經過一個記憶鞏固(memory consolidation)的過程,神經元會重新重現、處理白天有過的神經活動,然後想辦法讓它進入長期記憶、連結、 儲存他們。如果你白天很努力的工作四到五個小時,取得很多的資訊。這時候小睡一下,大腦會進入睡眠階段,開啟了神經元重啟的按鈕,讓某些迴路變的放鬆,你會預先處理一些資訊讓晚上再做後續處理。
2016年6月1日 星期三
大腦超載時代的思考學 The Organized Mind: Thinking Straight in the Age of Information Overload
2016年5月28日 星期六
使用者故事對照/地圖演講摘要 (User Story Mapping)
摘要: 「使用者故事地圖」是一種資訊架構。其目的是讓人們在設計的過程中更容易「透過溝通來建立共識、對系統有全盤理解」。結構的設計讓人可以持續修改、組織、引用、溝通設計的想法,重視呈現每個想法間的相互關係。是「便利貼技巧」+「使用者中心設計」+「敏捷開發」的整合運用。 — 講者:Jeff Patton, 來自敏捷的社群、當過軟體工程師、專案經理。 在當專案經理的時候,接觸到使用者故事 (user story),當時覺得這個名字很蠢,為什麼要用這個字。過了十年之後才了解故事(story)的意義。故事地圖(story map)是一個說大故事的簡單方法、它把大故事分解成更小的部分。然後對每個部分,實作的人會加上更多的細節把產品做出來。 我從2000年就開始用故事 (story) 這個字。故事這個字從一開始就被誤解,我接下來會說明故事代表的意思。故事會解決軟體開發中兩個問題,但這兩個問題都不是寫更好的需求 (requirements)。 第一個問題:寫文件沒啥用 (Documents - just don’t work) 第二的問題:太多東西要做 (Too much to build) 想像一個簡單的電話對話。blah blah 講了光靠電話描述,麵包店做出了許多奇怪的蛋糕。類似事在軟體公司也經常發生。文件寫完之後,做出來的產品就是不對。這邊的問題是,當我們分享、同意和簽署的文件,我們只能相信每個人是理解的(意指每個人其實理解的都不同)。之後 Kent 就想出了解決文件問題的方法,那就是不要寫、不要交換文件。用「告訴我你的故事」取代:如果我們能直接討論這個,我們可以一起想辦法 (figure it out together)。 如果你想說什麼,寫在一張卡上。然後你會找到負責實作的人,一起討論、知道到底做出來會怎樣。用故事這個名字的原因來自「我們怎麼使用它」(how we use them) 而不是「我們怎麼寫它」。有多少人用 Scrum?backlog? 問題在現在的 Scrum 會議中,許多人來參加、許多人都在做自己的事,「故事」本來想要帶入的有效溝通早就被忽略了。常常的情況是幾個人會說話,大部分人就只是在聽、在發呆,沒有相互溝通每個人理解到的是什麼。因為每個人心中的思考是無法被觀察的,只有當我們說出自己的思考、畫些圖片,我們才能察覺到每個人思考的差異,這時候我們才能真的達成共識 (really get it)。如此在這個會議之後,當我們說到同樣的東西,才會代表同樣的意思、代表同樣的事情。不然會議中的共識,其實完全沒有達到共識。 光分享文件、並沒有分享理解 (Shared documents aren’t shared understanding) 透過文字、圖片的討論會讓每個人建立共同的理解。在 Atlassian,他們在牆上貼的不是工作列表,他們把那些放到 JIRA 軟體。他們貼在牆上的是一堆便利貼 / 草圖 / 線圖稿,每個都代表一個故事。他們討論故事。每個團隊,都有各自的故事們,然後做站立會議中,他們指著牆上的便利貼說,我今天做這個 JIRA Ticket。指的同時也指出了這個 JIRA Ticket 在整個大故事的位置,回憶起細節、為什麼現在要做它。那張便利貼就像一張在夏威夷的照片,你可以說出照片外的細節,因為便利貼是你們一起討論出來的。 第一個問題的解法:我們靠說故事 (story telling) 來建造共同理解 (shared understanding) --- 我們的工作不是建造軟體,我們的工作是改變這個世界。這聽起來也許有些誇張。但這邊我們講的不是世界和平、非洲的飢荒之類的事。這邊說的世界指的是我們身邊、我們有能力去改變的事。這個世界的邊界是我們的產品,透過看著會使用產品的人,我們有了新的想法,產生新的需求。需求 (requirements) 的目的就是我們背後有了好想法能夠幫助用產品的人。把現在的世界畫一個圈,有產品後的新世界的畫一個圈,我們要觀察現在世界的產出(output)、新世界有這個產出後的結果 (outcome),像是產品的使用心得、影響 (Impact)。先前說的想法 (idea) 的問題是「每個人都有想法」。所以每個人的想法就會轉成越來越多的事情要做。我們的目標不是加快產生出垃圾(our job is not to build more crap faster),我們的目標是做更少的產出 (our goal is to build less)。當你做更少的產出,你試圖最小化產出 (output) ,同時最大化結果 (outcome) 和影響 (Impact)。 之前工作的時候,知道了下一次產品發行的需求列表後,去問他們「使用者是誰?解決了使用者什麼問題?」。得到的答案是:「這些是需求 (requirements)」,當時我就知道需求還有另外一個意思 — 那就是閉上嘴 (shut up)。他們真的以為需求列表,就真的如同字典上的意思代表了必須要做的事。實際上它們並不是... 因為不可能實作所有的需求,光只有需求沒法最小化產出、最大化結果。故事是需求 (requirements) 的解毒劑。 引用 Kent:「軟體開發已經被需求 (requirement) 這個字導入的錯誤的方向,這個字在字典裡被定義為需要做的事 (something mandatory or obligatory)。這個字帶有絕對和永久的一役、抑制了擁抱變化。需求 (requirements)這個字完全是個錯誤」 我們要說誰做什麼、怎麼做、為什麼做 (talk about who doing what and why)。討論和協作要專注在誰會用這個產品和他們拿到這個產品之後會怎麼使用它。基本上,你必須要想通整件事。舉了一個漂亮的嬰兒形狀蛋糕的例子,蛋糕看起來很漂亮,但要吃的時候就必須把嬰兒切開,這應該是沒有把事情想通的做法。 第二個問題的答案是:透過理解產品是為了誰、做什麼、為什麼這樣做,來最小化產出。 如果正確的使用故事,就可以解決這兩個問題。 但我們會碰到一個問題,很多很棒的想法,怎麼轉變成 scrum 中開發的故事裡 (1~3天可完成、可被估計、可測試、可被展示...)。這邊講一個故事,Rachel 是90年代的一個專案經理,當他去跟工程師問說每個的工作項目是為了誰、為什麼要這樣做的同時?發現工程師瞬間就開始說這個東西好像不是一定要做、也許在別的地方做會更好。很多人根本就沒把事情想通。於是,Rachel 就寫了一個聰明的溝通小卡: 標題:寫一個好的故事 As (who)to (do what) so that (why) 的例子,當作一個容易開始討論的起點 (conversation starter) 就這樣定義出了常見使用者故事的格式(story template),但如果用這個格式當作 scrum 中的 backlog 項目,應該會覺得有些卡卡的,因為這個格式本來不是拿來這樣子用的。它本來是在探索階段,拿來引導討論那些大的好想法的,那些要被分成更多 backlog 的項目。 這邊舉了一個 Gray 用敏捷開發流程開發音樂服務網站的例子,Gray 把所有要做的代辦事項排序之後,就從最優先的事情開始做,進度一直都有進展,但一段時間過去,開始覺得事情做不完,而且無法估計什麼時候整個系統可以上線完成。Gray 這時候就問了,有沒有其他不用敏捷開發流程的方法。這是我碰到他當時的情況。我們一見面談的不是開發方法,而是討論定義想法(Frame the idea)、為什麼要做這個產品、對使用者的了解、使用者的目標是什麼。開始討論想法,寫下想法在便利貼上、移動想法、組織想法。討論使用者一整天會怎麼使用這個產品。Gray 說、然後我用便利貼紀錄下來,這是 Gray 第一次看到整個產品看起來會是怎樣子。之後才開始探索細節,分成更多步驟、替代方法、UI的設計、技術細節。之後就可大概估時間,挑出核心的部分來做,發現這些核心都是之前用待辦事項開發幾個月沒做的部分!!!之後這個產品就順利上線了~ 以上是影片前55分鐘的摘要,後來開始用影片舉例子,還是直接看影片吧~ 你會看到許多使用者故事地圖開發的過程和樣子。後來還有說 MVP 的概念,提早驗證、提早學會。把 MVP 分成數個階段,讓每個階段都能透過驗證來學習、改變產品方向。和一些其他秘訣... 像是油畫草稿和 protyotyping和迭代的重要性。 作者的總結: 1. 改變你工作的方式:跟別人說故事,而不只是寫故事 2. 用簡單的視覺化去代表你說的故事 3. 要把整個故事都放到地圖上,來找出最重要的部分 4. 把事情想通:減少產出、增加結果和影響 5. 建立最小可行產品測試,來學到什麼是市場中最小的和可行的 6. 用疊代和漸進的(原型 / 草稿式)的方式來建造產品 有效率的故事們能幫助每個人朝向產品成功而工作 Q & A 從一小時二十分開始 — 就結構來說是把敏捷開發流程中的待辦事項列表用一個某種可變網狀系統資訊結構取代。
2016年4月28日 星期四
資訊架構學是什麼?
這邊試著用解構的方式來說明資訊架構 (information architecture) 這門學問。 設計活動就是在某些限制下,生出某個東西來達成某個目的的過程。 所以可以理解「設計資訊架構」的過程中,設計出來的某個東西指是「架構/結構 (architecture / structure)」、而且這個架構的改變對象是「資訊」(information),接著透過新產生的「資訊互動」達成我們的目的。 簡單說,資訊架構透過設計「結構」、讓人和「資訊」有不同的互動,來達成我們背後期望的目的。 舉例來說: 1. 程式碼的資訊架構 結構:檔案命名、目錄名稱、放的位置、如何引用、設計模式 資訊:程式碼 目的:讓程式碼容易被理解、容易修改、容易查找、容易維護 2. 網站的資訊架構 結構:搜尋列、標籤、sitemap、瀏覽列、超連結、分頁... 資訊:文章、圖片、服務、功能 目的:讓人能找到想要的資訊、讓購買率上升、讓使用者達成他想做的行為 3. 書本的資訊架構 結構:段落、內容的順序、章節、標題、註解 資訊:文字、圖 目的:讓人更能透過閱讀能理解內容 4. 愛買的資訊架構 結構:商品走道的規劃、服務台的位置、結帳的位置 資訊:商品、愛買提供的試吃服務 目的:賣出更多商品 5. 臥室的資訊架構 結構:物品的擺放位置 (櫥櫃裡、牆面) 資訊:物品 目的:主人想... 資訊是相對的 對不同的人,同樣的資料會是不同的資訊;在不同的環境(context)下,同樣的資料會是不同的資訊。資訊不光只有資料、在電腦科學裡,功能/函數也是資訊的一種。 設計的目的是多方向的 有設計者本身的目的、有對使用者的目的、有對其他關係人的目的。也就是說,只要是跟人相關的活動都要理解這些人想要的是什麼、目標是什麼。和使用者中心設計 (User-Centric Design) 一樣。 設計模式 (Design Pattern / Design Principle) 只要是設計就會有比較好的設計模式來增加設計的成功率。所以通常我們在資訊架構中所學的就是這些「架構的設計模式」,對不同的資訊、不同的目的、不同的人都會有不同的「架構的設計模式」。評估一個「架構的設計模式」的方式就是觀察資訊擺在這個架構下,資訊到底會有什麼不同,能達到什麼不同互動。 被架構後的資訊 資訊經過架構後還是資訊,資訊的不同點不外乎就這些:資訊容易不容易「理解、瀏覽、找到、關聯、傳遞、同步、容錯、不失真、記住、更新、處理、新增、刪除...」 根據不同的設計目的,設計不同結構,讓原來的資訊的這些面向變得不同,以達成我們的目的,這就是資訊架構學的使用方法。 Domain Knowledge 架構的設計模式太多了、資訊也太多種類、人也太多種,細節就看相關領域的書吧~ 只是時時記得,有「變動世界的架構」的選項,變動後一切就會變得不一樣。就像 google / facebook,完全改變了人們和資訊的互動方式、產生方式。 facebook的資訊架構 結構:News feed & notification 系統 & 好友列表 資訊:發文、按讚、分享、加入社群的行為、閱讀時間 目的:讓世界變得充滿萬惡的讚能量、讓人都只看到自己想看的 最後說一下,其實設計流程是結構的一種、結構也是資訊的一種,從資訊流動來看世界是不是越來越有趣了呢?下圖是資訊架構和其他領域的關係。
在使用者經驗分層中,每層都是息息相關的,如果哪一層壞了,整個就壞了。所以從上圖我們可以知道:要做好資訊架構,我們必須做好設計研究、對內容有了解、對功能有能力去實作;要展現好的資訊架構,我們必須做好互動、介面、資訊、視覺設計,不然光只有好的架構,使用者經驗不會好。所以... 工作的時間到了。 參考: 1. Eight Principles of Information Architecture, 2010 - Dan Brown 2. Information Architecture 100, 2013 - 長谷川敦士 3. The Elements of User Experience, 2010 - Jesse James Garrett 4. Information Architecture: blueprints for the web, 2009 - Christina Wodtke and Austin Govella
2016年4月10日 星期日
”redux.js --- 可預測的狀態容器“ 的 API 使用說明
這邊只會透過理解 Redux 的 API來簡介如何使用 Redux。這邊假設讀者都知道 web 中 event / listener 的 pattern。
如果想要知道 redux 背後的實作細節、原理、動機、Flux、Design Pattern、如何和 UI App 做連結,請看 Dan 的 Redux gitbook、Redux tutorial on EggHead。
redux 是一個狀態容器 (state container / state machine)
狀態容器要提供幾個功能
1. 初始容器狀態 by Redux.createStore(reducer)
2. 取得現在的狀態 by store.getState()
3. 狀態改變時,通知相關的程式 by store.subscribe(listener)
3. 接收事件發生的通知、改變狀態 by store.dispatch(action)
4. 建立之後改變事件處理方式 by store.replaceReducer(reducer)
5. 由小的狀態容器組成全域狀態容器 by 只能透過 combineReducers 來組成 root reducer,再用它來建全域狀態容器
Flux 專有名詞:store、action、reducer。
store := 一個狀態容器
action := 一個像 Event 一樣有 type 屬性的 javascript object
reducer := 一個輸入 state 和 action、回傳新 state 的函數, (state, action) -> new_state
但 store 是 redux 中唯一一個狀態容器的名字。其實 API 等同於下方這樣子
1. by Redux.createStore(reducer) 等於 by Redux(reducer)
2. by store.getState() 等於 by Redux.getState()
3. by store.subscribe(listener) 等於 by Redux.addListener(listener)
3. by store.dispatch(action) 等於 by Redux.dispatch(action)
4. by store.replaceReducer(reducer) 等於 by Redux.replaceReducer(reducer)
5. by 無直接 API,只能透過 combineReducers 來組成root reducer,然後用 root reducer 來建全域 store
一個狀態容器 = 狀態 + reducer,但 reducer 中可以指定初始狀態、所以一個 reducer 其實可以定義一個狀態容器、等同於一個狀態容器,所以 API 等同於下方這樣子
1. by Redux.initContainer(reducer) 等於 by Redux(container)
2. by Redux.getState()
3. by Redux.addListener(listener)
3. by Redux.dispatch(action)
4. by Redux.replaceReducer(reducer) 等於 by Redux.container.replaceReducer(container.reducer)
5. by 只能透過 combineReducers 來組成 root reducer,再用它來建全域狀態容器 等於 Redux.combineContainer
把 combineContainer 用 addContainer 取代,API 可以改寫成這樣子
1. 初始容器狀態 by Redux()
2. 取得現在的狀態 by Redux.getState()
3. 狀態改變時,通知相關的程式 by Redux.addListener(listener)
3. 接收事件發生的通知、改變狀態 by Redux.dispatch(action)
4. 建立之後改變事件處理方式 by Redux.getContainer(name).replaceReducer(reducer)
5. 由小的狀態容器組成全域狀態容器 by Redux.addContainer(container)
6. 建立小的狀態容器 by Redux.container(name, initialState, reducers)
所以翻譯過後 redux api 的使用流程就會變成
let addReducer = (state, ADD_ACTION) => state++
let subtractReducer = (state, SUBTRACT_ACTION) => state--
counterContainer = Redux.container(
'counter',
0,
[addReducer, substractReducer]
)
Redux.addContainer(counterContainer)
class CounterComponent {
constructor(props) {
this.stateChangeListener = (state) => this.setState(state)
Redux.addListener(this.stateChangeListener)
}
componentWillMount() {
this.setState(Redux.getState().counter)
}
onAddButtonClick() {
Redux.dispatch(ADD_ACTION)
}
onSubtractButtonClick() {
Redux.dispatch(SUBSTRACT_ACTION)
}
...
}
總結,可以看出來 redux 最大的特點就是用 reducer 來定義 container state 的處理範圍,不能用 event callback 的概念去理解它,一個 reducer 對應到“一組” state、多個 actions。
所以在 Redux 中 reducer 差不多是 container state scope 等價。也因此在 Redux 中 sub-container / sub-store 的名字完全被省略了,你只能用 reducer 的名字來找到他們影子。只要知道這個規則大概就能夠理解 Redux 了。
reducer := (state, action) -> new_state (你找不到 container 的名字、它被省略了)
老實說,我覺得這樣子的開發者經驗很不舒服 (bad UX)
---
不知道 re-frame 的 UX 會不會比較好?
2016年3月4日 星期五
如何讓程式可維護 / 重構的方向 / 程式開發中的互動設計
要解決的問題:
I. 當要程式中增加功能、解決 bug 時,能:
1. 有概念知道「要修改的地方們」在哪
2. 能快速切換到「要修改的地方們」
3. 能在「要修改的地方們」之間快速切換
4. 「修改的地方們」很容易修改
5. 「修改的地方們」不多
II. 當程式要重構時,能:
1. 測試重構後,外部行為是否一樣
2. 輕易搬移搬動程式、不產生 bug
解法:
把程式切成小區塊,每個區塊只負責單一功能,幫這些區塊建立資訊架構,架構中設計狀態的流程管理。對應工作內容規劃工作環境。用多次微重構,代替大改。先重構、再解 bug、最後才寫新功能。在多人開發、或經常重構的專案,對穩定的外部 API 建立自動化測試。
好習慣:
把程式切成小區塊 ( ex: 4 - 30 行的小 chunks)
好處:
好理解、好修改、也容易增加新功能、能塞進人腦的工作記憶裡
方法:
每個程式區塊 = 一個檔案 or 一個 function or 一個 folding
每個區塊行數 (after folding),大於一個螢幕可以顯示時就要 Refactoring
每個區塊只負責單一功能
好處:
容易重複利用、減少 dependency、容易理解、容易找到 debug
方法:
多寫純函數 / Stateless API、良好函數/模組命名、註解輸入/輸出參數
建立程式碼的資訊架構
好處:
容易找到要修改的地方 (在人很有限的 short-term memory 消散之前)
方法:
把程式碼區塊分類
依功能:模組 / MVC / 前後端 / 測試 / Layout or 細節 / Stable or Develop / Web or iOS or Android
依架構:樹狀主從架構 / 分階層 / Data Layer / Rendering Layer
依時間:version
在架構設計中使用流程管理
好處:
增加可預測性、減少程式碼依賴
方法:
單向資料流、State Machine、Single Source of Truth
對應的工作內容建立環境
好處:
在程式碼區塊 / 外在環境中移動時,大腦不會 context switch
Web 互動環境設計:
1. 要規劃在下列環境簡單移動的方法 (環境一樣要有架構、資訊權重)
a. editor & browsers
b. shell / server / database / git
c. editor 中的不同檔案
d. 同個檔案中的 區塊、行、字母
e. MDN / stack overflow / Google Search / Github Search
2. IDE / shortcut switch / 多螢幕環境 / 切割螢幕畫面
3. Font / Syntax Highlight / AutoComplete / 文法檢查
Micro-Refactoring
好處:
一次改一點比較好測試、失敗的損失也比較低
改程式碼的優先順序:重構 > 修 bug > 增加功能
好處:
重構會讓修 bug 變簡單、修完 bug 會讓增加新功能變得簡單
為不常改變行為的外部 API 建立自動化測試
好處:
每次重構時能夠確定沒有破壞這些 API
—
Simplicity is the prerequisite for reliability — by Dijkstra.
因為我們是人類,只有相當有限的注意力、短期記憶和工作記憶空間。
2016年2月7日 星期日
從買蘋果看工程師和設計師的差別?
高中的時候,有個留級的朋友問我,你會不會覺得唸這些東西一點用都沒有。書呆子的我,帶著疑惑問:「為什麼會這樣覺得?」但現在過了 15 年,我真的很想問那時候的我,為什麼不會這樣覺得。 工程和管理的訓練是解決問題,而設計師受的訓練是發現真正的問題。 --- from 設計的心理學 by Donald A. Norman聽到「幫我買一顆蘋果」這個問題,工程師會這樣做。
工程師:花一小時,找出一大堆的購物網站,列出各種蘋果的價格和評價,然後請你挑最好的一個。 妹子:我只是想和你見個面聊個天,為什麼我必須要看那麼多資料... 而且還要我上網訂、見不到面,還是放棄治療好了。聽到「幫我買一顆蘋果」這個問題,設計師會這樣做。(這邊設計師不含 VD)
情況一: 問:你為什麼要買蘋果? 答: 因為想幫房間增加一點紅色。 問: 為什麼想幫房間增加一點紅色? 答: 因為想把房間變漂亮? 解: 設計師把房間的燈從冷色系換成暖色系。 情況二: 問:你為什麼要買蘋果? 答:因為我肚子餓。 問:可是你不是剛剛才吃完飯? 答:嗯,對喔。(OS: 我只是看你太閒,要給你一點事做。) 情況三: 問:你為什麼要買蘋果? 答:因為要吃。 問:你為什麼要吃? 答:我每天都要吃一顆,今天沒帶。你廢話那麼多要幹麻?(OS: 這個下屬理由很多。) 工程師和管理把問題往下展開。 設計師把問題往上展,如果找到更簡單的問題再往下展。工程師:直接把問題往下展開:
優:能最快速找到這個問題的解法。 缺:你解決的可能根本不是重要的問題。設計師:把問題往後回推,找新問題解
優:也許能找到真正需要解的問題、花更少的時間就能解決問題。 缺:別人會以為你不想理他在找藉口。老闆會以為你在故意質疑他。如果原來的問題本來就是對的問題,你只是在浪費時間。理性與感性
「現階段的實際工作中,設計師們無論是在方案的設計還是方案的表達上,往往都顯得感性有餘、理性不足。」 --- by 汪方進 @ 阿里巴巴 1688用戶體驗部 一個設計師,不光只有同理心、邏輯推理能力、各種知識也很重要。沒有知識不能推理啊... 所以工程師們快和我一樣跳進來吧~~~ 當設計界的理性之光。其實就演算法的角度來看,就是兩種不同的方法,各有各的使用時機、各有各的風險報酬,如果要能解決生活中的問題,這兩個都很重要。所以也別分什麼工程、設計、商業,如果有需要就學吧。大學四年可以學一個專業,但人生有多少個四年啊... 是不是該多學幾個專業 XD 註: 把視覺設計師(VD)和程式設計師特別切出來的原因是:他們的工作都偏向在給定的問題中找解法、做的是實作中一定要做的事。但真正優秀的會去觀察使用者。(工程師的話推薦看:程序員的修煉、駭客與畫家,都有提到這點) 註:上面的對話都是我的想像舉例,別太認真。想知道真正答案的話,或是測試這個人的工程設計傾向,可以請他幫你買顆蘋果看看。
2016年1月29日 星期五
淺談函數式編程和 React
函數是有定義介面的運算單元。 介面有用的地方是抽象化,你只需要知道輸入什麼(Input)、會得到什麼輸出(Output),你不用知道它細節是怎麼做到的。其實有個超能力在背後,也沒關係。當然這是在沒有碰到 bug 和有良好文件、不需要修改它的前提之下。 再強調一次,你只需要理解輸入(input)會對應到什麼輸出(output)就夠了。問題來了,怎樣的輸入和輸出的對應「介面」會容易讓人理解?
1. 有意義的函數名稱 2. 多寫沒有副作用的純函數 1. 有可預測性: 每次輸入得到相同的輸出、函數內部不存狀態 2. 沒有副作用: 運算過程中不會改到外界的變數,像是不改傳進來的參數、不改可以存取的全域變數。 3. 顯式(Explict): 函數和外界溝通的管道只有,傳進來的參數和回傳值。 3. 簡化參數、對資料結構的 Information Architecture 做良好設計 4. 用函數來定義函數 1. 柯里化(Currying): 透過不同給參數來產生新的函數 2. 合成(Compose): 透過 pipeline 串接函數的input和output、隱藏參數,產生新的函數。函數式編程為什麼強大、有彈性?
1. 把每個函數切得很小,容易更新、維護、平行處理、多人共同開發、被理解 2. 透過合成(Compose)把小函數變成大函數,比用繼承有彈性的多 3. 對集合實做 Functor 介面,讓一般函數都可以對集合操作。(array, matrix, tensor) 4. 把純和不純的函數分開來管理,容易找到問題點。函數式編程為什麼難寫?
因為函數式編程想要把程式變簡單。但大家都知道「變複雜是簡單的、變簡單是複雜的」。所以這種方式寫程式需要設計、思考,你會是一個程式「設計師」。但如果你現在的專案寫完之後沒人會看、不會再改、不用維護、規模不大,也許函數式編程並不能幫到這個專案多少。寫 React 就是實踐函數式編程
1. 透過自定義元件,定義畫 View 的抽象化函數樹 2. 透過 JSX 語法把小函數組合成大的函數 (等同於 compose) 3. 鼓勵大家寫 dumb 元件、也就是純函數 4. 用唯讀的 props,限制大家不能改傳進來的參數、減少副作用 5. 透過導入 flux,把純和不純的函數分開來管理 1. 純的 (對資料只做讀的動作):每個元件中的 render function 2. 不純的 (對資料做讀和寫的動作): flux中對 action 的 callback、redux 中的 reducer、父元件傳給子元件的 callback 3. glue code:元件中其他的 javascript從函數式編程的角度看 React 的問題?
1. 沒有什麼高階的集合操作方法: 1. 把 lodash.js 集合操作拉進來用? 2. 用 lenses 的方式來穿透深長不露的 states? 2. 沒有簡單的 currying 語法 1. 像是傳不同參數給 html5 input 元件,生出各式各樣對數字的、email、submit、text的自定義元件。最簡單寫法應該是 2. export function NumberInput(props) { 角括弧input type=“number” {…props} /> } 3. PS: function 一定要有名字不然 debug 會很慘。 3. 雖然集中管理了不純的函數,但還是很難寫:現在透過修改 store 中的 state 來控制元件,這邊 action 觸發的都是不純的函數,如果元件架構一深,還是會很難改。有解嗎?這邊還沒找到什麼 coding guideline… 1. 多個 container smart 元件 2. flux 的多個 store 3. redux 的階層式 reducers ----------- 延伸閱讀: deku: functional alternative to react how to use classes and sleep at night (in a functional way)
訂閱:
文章 (Atom)
