🔍 搜尋結果:git

🔍 搜尋結果:git

挑戰串接CodeLove的API

成品連結:https://codingdark.github.io/program/2023/09/18/API-Test.html ##第一步 架部落格 最初看到站長的貼文,提供了本站的API 並且鼓勵大家自架部落格,來嘗試串API 看到文章的當下,覺得有點難度(沒用過github page,API也不熟) 不過看到站長提供的關鍵字`setup a personal blog with github pages` 最終還是決定先google看看 查了之後,發現近年的gitbub簡化了很多 都可以自動部署,根本就是一鍵架站 外加原始碼開源,很多東西都能自己改 所以光是部落格就玩了一天XD 因為本站為CodeLove 愛寫扣 我就創了一個CodingDark 闇寫扣 表示致敬本站 & 本人的中二風格 ##第二步 串API 因為不熟的關係,所以決定先隨便串 呼叫API之後,把data印在console.log 大致上看了一下資料格式 使用上其實就類似陣列,非常方便 沒有想像中的難 確認API可以正常呼叫後 陸續加入一些功能 比方說,用Table把文章列表排整齊、加上[Read more]按鈕 先讓json資料,轉換成網頁能呈現出來的[資訊] ##第三步 程式碼優化 到這邊為止,網頁的畫面已經差不多定型了 剩下的就是回頭檢視程式碼 考量到後續維護 盡可能把重複的程式碼,包裝成function 或是把一群散亂的變數,包裝成object 最後,為了方便擴充文章列表 將原本是寫死的HTML Dom 改成動態產生 目前的部落格頁面 點進去會撈出站長、Tony,以及我的文章列表 後續若想要列出其他使用者的文章 只需新增`setTable(userAccount)`即可 ##結尾 感謝站長提供有趣的API 讓大家可以有練習的機會 雖然目前我在工作上,沒接觸過API 但經過這次的練習,以後若是真的有需要用到 可以更快上手

寫出 Clean Code 的一些技巧&原則

## 介紹 編寫乾淨的程式碼是每個軟體開發人員的基本技能。乾淨的程式碼不僅使您的程式碼庫更易於維護和理解,而且還能促進團隊成員之間的協作。在這篇綜合文章中,我們將探討什麼是乾淨的程式碼、為什麼它很重要,並為您提供一組最佳實踐和原則來幫助您編寫乾淨且可維護的程式碼。 - 原文出處:https://dev.to/favourmark05/writing-clean-code-best-practices-and-principles-3amh --- ## 什麼是乾淨程式碼? 乾淨的程式碼是易於閱讀、易於理解且易於修改的程式碼。它是沒有不必要的複雜性、冗餘和混亂的程式碼。乾淨的程式碼遵循一組約定和最佳實踐,使其更加一致,使多個開發人員更容易無縫地處理同一個專案。 ## 為什麼乾淨的程式碼很重要? 1. **可讀性**:乾淨的程式碼易於閱讀,這意味著任何人 - 包括未來的你 - 都可以快速理解它。這減少了掌握程式碼功能所需的時間,從而加快了開發和除錯速度。 2. **可維護性**:程式碼的讀取次數多於編寫次數。當您編寫乾淨的程式碼時,隨著時間的推移,維護和擴展應用程式將變得更加容易。這在軟體開發生命週期中至關重要,因為專案經常發展和成長。 3. **協作**:簡潔的程式碼鼓勵協作。當您的程式碼乾淨且組織良好時,其他團隊成員就可以有效地處理它。這使得劃分任務和同時處理程式碼庫的不同部分變得更容易。 4. **減少錯誤**:乾淨的程式碼可以減少引入錯誤的可能性。難以理解的程式碼在修改或增強過程中更容易出錯。 5. **效率**:乾淨的程式碼就是高效率的程式碼。它通常執行速度更快並且使用更少的資源,因為它避免了不必要的操作和複雜性。 現在我們了解了為什麼乾淨的程式碼很重要,讓我們深入研究一些最佳實踐和原則來幫助您編寫乾淨的程式碼。 ## 編寫簡潔程式碼的最佳實踐和原則 1. **有意義的變數和函數名稱** 對變數、函數、類別和其他辨識碼使用描述性名稱。精心選擇的名稱可以傳達實體的目的,使程式碼更容易理解。避免使用單字母變數名或神秘的縮寫。 ``` # Bad variable name x = 5 # Good variable name total_score = 5 ``` 2. **保持函數和方法簡短** 函數和方法應該簡潔並專注於單一任務。單一職責原則(SRP)指出,一個函數應該要做一件事,並且把它做好。較短的函數更容易理解、測試和維護。如果函數變得太長或太複雜,請考慮將其分解為更小、更易於管理的函數。 ``` // Long and complex function function processUserData(user) { // Many lines of code... } // Refactored into smaller functions function validateUserInput(userInput) { // Validation logic... } function saveUserToDatabase(user) { // Database operation... } ``` 3. **評論和文件** 謹慎使用評論,當你使用評論時,要讓它們變得有意義。程式碼應該盡可能不言自明。文件(例如內嵌註解和自述文件)可協助其他開發人員了解程式碼的目的和用法。記錄複雜的演算法、重要的決策和公共 API。 ``` # Bad comment x = x + 1 # Increment x # Good comment # Calculate the total score by incrementing x total_score = x + 1 ``` 4. **一致的格式和縮排** 堅持一致的編碼風格和縮排。這使得程式碼庫看起來乾淨且有組織。大多數程式語言都有社群接受的編碼標準(例如,Python 的 PEP 8、JavaScript 的 eslint),您應該遵循。一致性也適用於命名約定、間距和程式碼結構。 ``` // Inconsistent formatting if(condition){ doSomething(); } else { doSomethingElse(); } // Consistent formatting if (condition) { doSomething(); } else { doSomethingElse(); } ``` 5. **DRY(不要重複)原則** 避免重複程式碼。重複的程式碼更難維護並增加不一致的風險。將通用功能提取到函數、方法或類別中以提高程式碼的可重複使用性。當您需要進行更改時,只需在一個地方進行即可。 假設您正在開發一個 JavaScript 應用程式來計算購物車中商品的總價。最初,您有兩個單獨的函數來計算每種商品類型的價格:一個用於計算一本書的價格,另一個用於計算筆記型電腦的價格。這是初始程式碼: ``` function calculateBookPrice(quantity, price) { return quantity * price; } function calculateLaptopPrice(quantity, price) { return quantity * price; } ``` 雖然這些函數有效,但它們違反了 DRY 原則,因為計算總價的邏輯對於不同的商品類型是重複的。如果您有更多的專案類型需要計算,您最終將重複此邏輯。為了遵循DRY原則,提高程式碼的可維護性,可以對程式碼進行如下重構: ``` function calculateItemPrice(quantity, price) { return quantity * price; } const bookQuantity = 3; const bookPrice = 25; const laptopQuantity = 2; const laptopPrice = 800; const bookTotalPrice = calculateItemPrice(bookQuantity, bookPrice); const laptopTotalPrice = calculateItemPrice(laptopQuantity, laptopPrice); ``` 在此重構的程式碼中,我們有一個calculateItemPrice函數,它根據作為參數提供的數量和價格計算任何商品類型的總價。這遵循了 DRY 原則,因為計算邏輯不再重複。 現在,您可以通過使用適當的數量和價格值呼叫calculateItemPrice來輕鬆計算書籍、筆記本電腦或任何其他商品類型的總價。這種方法提高了程式碼的可重用性、可讀性和可維護性,同時降低了重複程式碼引起的錯誤風險。 6. **使用有意義的空白** 使用空格和換行符正確設置程式碼格式。這增強了可讀性。使用空格來分隔程式碼的邏輯部分。格式良好的程式碼更容易瀏覽,減少讀者的認知負擔。 ``` // Poor use of whitespace const sum=function(a,b){return a+b;} // Improved use of whitespace const sum = function (a, b) { return a + b; } ``` 7. **錯誤處理** 優雅地處理錯誤。在程式碼中使用適當的 try-catch 塊或錯誤處理機制。這可以防止意外崩潰並為除錯提供有價值的訊息。不要抑制錯誤或在沒有正確響應的情況下簡單地記錄錯誤。 ``` // Inadequate error handling try { result = divide(x, y); } catch (error) { console.error("An error occurred"); } // Proper error handling try { result = divide(x, y); } catch (error) { if (error instanceof ZeroDivisionError) { console.error("Division by zero error:", error.message); } else if (error instanceof ValueError) { console.error("Invalid input:", error.message); } else { console.error("An unexpected error occurred:", error.message); } } ``` 8. **測試** 編寫單元測試來驗證程式碼的正確性。測試驅動開發 (TDD) 可以迫使您預先考慮邊緣情況和預期行為,從而幫助您編寫更清晰的程式碼。經過良好測試的程式碼更加可靠並且更容易重構。 ``` // Example using JavaScript and the Jest testing framework test('addition works correctly', () => { expect(add(2, 3)).toBe(5); expect(add(-1, 1)).toBe(0); expect(add(0, 0)).toBe(0); }); ``` 9. **重構** 定期重構你的程式碼。隨著需求的變化以及您對問題域的理解的加深,請相應地調整您的程式碼。隨著專案的發展,重構有助於保持乾淨的程式碼。必要時不要害怕重新存取和改進現有程式碼。 假設您有一個函數,可以計算購物車中具有固定折扣百分比的商品的總價: ``` function calculateTotalPrice(cartItems) { let totalPrice = 0; for (const item of cartItems) { totalPrice += item.price; } return totalPrice - (totalPrice * 0.1); // Apply a 10% discount } ``` 最初,此函數計算總價並應用 10% 的固定折扣。然而,隨著專案的發展,您意識到您需要支持可變折扣。為了重構程式碼使其更加靈活,可以引入折扣參數: ``` function calculateTotalPrice(cartItems, discountPercentage) { if (discountPercentage < 0 || discountPercentage > 100) { throw new Error("Discount percentage must be between 0 and 100."); } let totalPrice = 0; for (const item of cartItems) { totalPrice += item.price; } const discountAmount = (totalPrice * discountPercentage) / 100; return totalPrice - discountAmount; } ``` 在這段重構的程式碼中: * 我們在calculateTotalPrice函數中新增了discountPercentage參數,讓您在呼叫函數時指定折扣百分比。 * 我們對discountPercentage 參數進行驗證,以確保其落在有效範圍內(0 到100%)。如果不在範圍內,我們會拋出錯誤。 * 折扣計算現在基於提供的discountPercentage,使功能更加靈活,能夠適應不斷變化的需求。 通過這種方式重構程式碼,你提高了它的靈活性和可維護性。您可以輕鬆地調整該函數來處理不同的折扣場景,而無需重寫整個邏輯。這證明了隨著專案的發展和需求的變化定期進行程式碼重構的重要性。 10. **版本控制** 使用 Git 等版本控制系統來跟踪程式碼更改。這使您可以與團隊成員有效協作,在必要時恢復到以前的版本,並維護專案開發的清晰歷史記錄。 Git 提供了程式碼審查、分支和合併工具,促進協作和程式碼整潔。 ##結論 編寫乾淨的程式碼不僅僅是一套規則,更是一種心態和紀律。它是關於建立易於閱讀、維護和擴展的軟體。通過遵循這些最佳實踐和原則,您可以成為一名更熟練的開發人員,生成高質量的程式碼。投入時間仔細檢查其他工程師的程式碼庫,特別是在開源專案中,可能是一種啟發性的體驗。通過這種探索,您將獲得對不同編碼風格和策略的寶貴見解。這種接觸使您能夠提煉出編寫原始、可持續程式碼庫的精髓。請記住,乾淨的程式碼是一個持續的旅程,通過練習,它會成為第二天性,從而實現更高效、更愉快的軟體開發。

寫單元測試的五個技巧分享

測試程式碼是軟體開發最重要的方面之一,因為它可以確保產品的品質、可擴展性和可靠性。 但是,如果沒有任何指導,編寫有效的測試可能會很困難。測試程式碼可能比實際功能的程式碼更複雜、更難維護! 原文出處:https://dev.to/one-beyond/the-5-principles-of-unit-testing-1p5f ## 1.精簡和準確的測試 測試程式碼必須**簡單且易於使用**。任何查看測試的人都應該立即知道測試的內容及其目的是什麼。開發測試應該以很少的精力和時間投入帶來巨大的價值。 > _您是否需要超過 30 秒的時間來閱讀和理解您的測試?重寫它!_ 測試“覆蓋率”是重點嗎?不! **僅測試必要的部份就好**。為了敏捷性和簡單性,最好放棄一些測試,**只測試主要業務邏輯和主要邊緣情況就好**。 ## 2.測試行為,而不是元件實作 不要檢查程式碼中的每一行和內部變數。測試時,您應該**專注於結果**。即使方法內的程式碼被重構,結果也應該永遠保持不變! 這樣,如果程式碼庫發生更改,您**不需要重寫測試**。 ``` // Wrong ❌ - Test behaviour describe('Evaluation Service', () => { describe('Register Students', () => { it('Should add new students to the evaluation service', () => { const studentJosh = { id: 1, name: 'Josh McLovin', average: 6.98, } evaluationService.addStudent(studentJosh) expect(evaluationService._students[0].name).toBe('Josh') expect(evaluationService._students[0].average).toBe(6.98) }) }) }) ``` ``` // Right ✅ - Test behaviour describe('Evaluation Service', () => { describe('Register Students', () => { it('Should add new students to the evaluation service', () => { const studentJosh = { id: 1, name: 'Josh McLovin', average: 6.98, } evaluationService.addStudent(studentJosh) expect(evaluationService.getStudentAverage('Josh')).toBe(6.98) }) }) }) ``` ## 3. 關於命名和結構:AAA 模式 您是否曾經遇到過名為“_它應該[...]正確_”的失敗測試,但花了幾分鐘才找到問題所在? 良好命名和結構可以讓您快速且準確地找到任何失敗的測試,最終節省您的寶貴時間。因此,讓我們深入探討兩個關鍵原則,以便在下次測試時牢記: ### 3.1 經過深思熟慮的測試命名: 在命名您的測試時,請嘗試合併以下資訊:   - **正在測試什麼**?   - **什麼情況**?   - **預期結果**是什麼? ``` // Right ✅ - Test naming // 1. What is being tested: describe('Evaluation Service', () => { describe('Evaluate Students', () => { // 2 & 3. Context and expected result it('If the student grade is below the minimum grade, student should be suspended', () => { const students = [ { name: 'Mark', grade: 4.25 }, { name: 'Colin', grade: 6.7 }, { name: 'Ben', grade: 5.3 }, ] const result = evaluationService.evaluateStudents({ students, minGrade: 5 }) expect(result['Mark']).toBe('suspended') }) }) }) ``` ### 3.2 測試程式碼結構的AAA模式: 如果您想維護一個可讀且易於理解的測試套件,請按如下方式建立測試: - **安排**:設定模擬所需情況所需的所有程式碼。這可以包括初始化變數、模擬響應、實例化被測單元等。 - **行為**:執行正在測試的內容,通常在一行程式碼中。 - **斷言**:檢查得到的結果是否為預期的結果。與上面的一樣,這應該只需要一行。 ``` // Right - AAA Testing Pattern describe('Evaluation Service', () => { describe('Average Calculation', () => { it('Should calculate the average grade of all the students', () => { // Arrange: create an object with the student names and their grades const students = [ { name: 'Mark', grade: 4 }, { name: 'Colin', grade: 10 }, { name: 'Ben', grade: 7 }, { name: 'Tim', grade: 3 }, ] // Act: execute the getAverage method const avg = evaluationService.getAverage(students) // Assert: check if the result is the expected one -> (4+10+7+3)/4 = 6 expect(avg).toEqual(6) }) }) }) ``` ##4。確定性和隔離測試 如果一個失敗的測試使您的整個套件變紅,那麼您可能沒有以正確的方式處理它! 測試應該**獨立和隔離**,一次針對並處理一個特定邏輯,從而完成更快、更穩定的測試套件。 **如果您不**獨立編寫測試會發生什麼? - 您將無法找出錯誤和問題的**確切原因和位置**。 - 重構測試時,您必須**更新和同步多個測試**。 - 您將無法以任何順序執行測試,這可能會導致**破壞或跳過某些斷言或期望**。 ## 5。基於屬性的測試和真實資料 厭倦了在測試中編寫大量可能的輸入?基於屬性的測試可以為您做到這一點!……那是什麼? 基於屬性的測試建立了數百種可能的組合,強調了測試並**增加了發現以前未被注意到的錯誤的機會**。這種方法甚至可以傳回可能導致意外結果的輸入。 [JSVerify](https://github.com/jsverify/jsverify) 或 [Fast-Check](https://github.com/dubzzz/fast-check) 等函式庫提供了促進基於屬性的測試的基本工具。 但是,如果您不想深入進行如此廣泛的測試,那麼盡可能利用**真實資料**至關重要。像“abc”或“1234”這樣的輸入可能會在實際失敗時錯誤地通過測試。 ``` // Wrong ❌ - False Positive - Test that passes even though it shouldn't class EvaluationService { _students = []; addStudent(student) { // Add the student if the name has no numbers if(!student.name.matches(/^([^0-9]*)$/)){ this._students.push(student); } } } describe('Evaluation Service', () => { describe('Register Students', () => { it('Should add students to the Evaluation service', () => { const mockStudent = { id: 2, name: 'username', average: 7 } // Won't fail because the name is a string without number -> We are not checking what happens if the user // inputs a name with a number. evaluationService.addStudent(mockStudent) expect(evaluationService.getStudentAverage('username')).toBe(7) }) }) }) // In the example above, we are making a test so the test passes, instead of looking for edge cases with realistic data ``` ##額外提示! 如果您在測試元件中的任何邏輯時遇到困難,這可能反映出您也許應該將元件邏輯分解為更小、更容易且可測試的程式碼片段! 總而言之,遵循此最佳實踐可能會帶來一種新的、可讀且可維護的方法來測試您喜愛的生產程式碼。 > 經過測試的應用程式才是可靠的應用程式!

Github Desktop 新手入門教學:第7課 ── 能夠從 Github 抓專案下來

## 課程目標 - 能夠從 Github 抓專案下來 ## 課程內容 我們在上一課發佈專案到 Github 了 這次來學習把專案從 Github 抓下來吧! 首先來把電腦上的專案刪掉,模擬我們今天拿到一台新電腦的情境 在主視窗點選 `Current Repository` 會秀出專案列表 對著我們的專案 `my-first-repo` 按右鍵,然後選 `Remove` 刪除,確認視窗繼續按 `Remove` 會發現 Github Desktop 變回初始畫面了! --- 但目前只是 Github Desktop 停止追蹤專案而已,那個資料夾其實還在電腦上喔 請在電腦上,直接前往那個資料夾,會發現檔案都還在 請把 `my-first-repo` 整個資料夾刪掉,這樣才是真的模擬拿到新電腦 --- 現在來試著把專案從 github 抓下來吧! 點擊 `Clone a Repository from the Internet` 因為已經登入 github 了,應該會顯示專案列表 找到上次發佈的 `my-first-repo` 專案 (如果專案沒出現,畫面上有一個重新整理的按鈕,按一下) 然後 `Clone` 按鈕按下去 成功囉!專案回來囉! `History` 分頁按下去,看看是不是跟之前都一模一樣? 軟體工程師在跨裝置工作(使用多台電腦)、或是多位工程師合作時,就是這樣同步專案內容的! ## 課後作業 接續前一課的作業,專案已經傳到 github 了 現在來模擬你拿到新電腦,第一次從 github 抓專案的情境 請把原本電腦上的那個專案資料夾,整個刪掉 這時去看 Github Desktop,應該會顯示「Can't find」開頭的提示 請將 Github Desktop 視窗截圖,這是本次作業的第一張截圖 截圖完畢之後,點擊畫面上的 `Remove` 將這個專案刪掉 --- 現在電腦上已經沒有專案了,就當作你今天拿到一台新電腦,準備開始工作,要把 github 上的專案抓下來 請點擊 `Add` 然後選 `Clone Repository...` 接著找到你在 github 上的專案 把剛剛那個專案整個抓下來之後,你應該會發現,剛剛整個刪掉的專案資料夾,現在內容又通通出現囉! 請將 Github Desktop 視窗截圖,這是本次作業的第二張截圖 --- 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 請把第一張、第二張截圖,分別貼到留言區

Github Desktop 新手入門教學:第6課 ── 能夠發佈專案到 Github

## 課程目標 - 能夠發佈專案到 Github ## 課程內容 我們已經在上一課成功連線 Github 了 這一課,來把我們的專案發佈到 Github 吧! 如果是跟同事合作,處理公司的專案,我們稱為 `Private repository` 如果是開源專案,發佈給全世界工程師使用,我們稱為 `Public repository` 在 Github Desktop 主視窗,會看到 `Publish repository` 按鈕 點下去,會看到 `Name` 預設就是專案名稱,`Description` 可以省略不填 下面的 `Keep this code private` 預設是勾選,也就是私人專案,把這取消掉,就是開源專案了 最後的 `Publish Repository` 按鈕按下去,視窗會自動關閉,代表發佈成功了! 回到 Github,右上方點擊自己的頭像,`Your repositories` 點下去,會看到剛剛發佈的專案! 以我的範例來說,我的專案在這邊,可以看到專案的各種檔案內容 https://github.com/howtomakeaturn/my-first-repo 然後這邊可以看到 commit 歷史記錄 https://github.com/howtomakeaturn/my-first-repo/commits/main 很酷吧! ## 課後作業 接續前一課的作業,現在你打算把專案上傳到 github,當做雲端備份,也方便自己在桌電、筆電上都能工作 請點擊 `Publish repository` 將專案發佈到 github 發佈之後,你應該會在 github 網站上面,找到剛剛發佈的專案、看到專案的程式碼、也能看到多筆 commit 歷史紀錄 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 請把 github 專案連結,貼到留言區

Github Desktop 新手入門教學:第4課 ── 學會重置指令

## 課程目標 - 學會重置指令 ## 課程內容 來學一個強大的指令:重置 上一課的取消功能,是針對修改到一半的檔案 這時很自然會浮現一個問題:如果是之前已經提交過的內容,有辦法取消嗎? 點開 `History` 分頁,假如我們今天對「上上次的提交內容」不滿,也就是 `add another work` 那筆 commit 不滿意,怎麼辦? 其實很簡單! 請把滑鼠游標移到 commit 上面,點擊右鍵,選擇 `Revert Changes in Commit` 你會發現 `History` 多了一筆 commit! 這筆 commit 內容跟原本的 commit 內容完全相反,也就是會抵銷掉那筆 commit! 打開資料夾看一下,會發現 `my-document-3.txt` 檔案整個不見了! 這就是 git 強大的地方:不只是正在修改的檔案內容,連之前修改的內容,都可以追蹤、回溯、管理! --- 看到這邊你可能會心想:為什麼要多一筆 commit? 怎麼不把那筆 commit 直接刪除掉就好? 其實,這是因為 git 通常是「團隊在使用」的工具 已經送出去的 commit,通常已經同步到很多人的電腦上了 如果這時工程師 A 刪了這筆 commit,工程師 B 刪了那筆 commit,那最後同步起來,大家電腦上的 commit 歷史記錄,到底長怎樣?很亂吧? 所以,git 就一律設計成:想要回溯,就也是加一筆 commit!只是會自動進行相反的變化! 這樣大家電腦上的 commit 歷史記錄,同步起來,就單純很多了!commit 數量永遠都是加法,不斷加上去而已! 很聰明的設計吧! ## 課後作業 這次來模擬實際工作的時候,你突然對之前的 commit 內容不滿意,想要把檔案內容還原的過程 繼續修改我們的履歷表專案吧! 目前裡面有 `me.txt` `about.txt` `background.txt` `goals.txt` 四個檔案 你突然又有點反悔,覺得 `about.txt` 跟 `background.txt` 很多餘,想要把內容移回 `me.txt` 裡面 開發專案時,像這樣反反覆覆其實很正常,git 就是為了處理這種情境而生的 請切換到 `History` 分頁,找到之前把 `me.txt` 檔案改寫的那個 commit 然後使用 `Revert Changes in Commit` 功能來還原 commit 內容 還原之後,你可以看一下資料夾內容,應該會發現變回之前的樣子了! 然後在 `History` 分頁應該會看到,多了一筆 commit,是用來記錄那筆還原的 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 請直接截圖 Github Desktop 視窗的內容,上傳到留言區

Github Desktop 新手入門教學:第3課 ── 學會簡易的檔案變化操作

## 課程目標 - 學會簡易的檔案變化操作 ## 課程內容 來學一點簡單的檔案變化操作吧! 打開 `my-document-1.txt` 然後多加下面這行字 ``` 是一段亂打的字 ``` 你會在 Github Desktop 再次看到 `my-document-1.txt` 檔案出現了,然後內容變化會在右側出現 假設我們今天對這次的變化內容不滿意,想要整個取消,該怎麼用 git 做到呢? 請把滑鼠游標移到檔案上面,點擊右鍵,選擇 `Discard Changes...` 會跳出確認視窗,跟你確認真的要捨棄這些變化嗎?點擊 `Discard Changes` 會發現檔案消失在 `Changes` 分頁囉! 代表檔案內容又變回去了,所以目前沒有任何變化~很酷吧! 軟體工程師在工作時,常常會一口氣修改很多檔案,然後常常改到一半又對某些修改反悔,這時就可以這樣快速取消變化! ## 課後作業 這次來模擬實際工作的時候,檔案改到一半,反悔了,然後取消的過程 繼續修改我們的履歷表專案吧! 首先,你想補充更多學歷資訊 請先在 `background.txt` 加入以下資訊 ``` - 國小:開心國小 - 國中:快樂國中 ``` 你應該會在 `Changes` 分頁看到變化的部份出現 請將 Github Desktop 視窗截圖,這是本次作業的第一張截圖 --- 想了一下,你突然又覺得,國中國小學歷,應該沒人關心,還是別放進去好了 請使用 `Discard Changes...` 功能把 `background.txt` 檔案變回原樣 這時再看 `Changes` 分頁,應該又乾乾淨淨了,裡面沒有東西 請將 Github Desktop 視窗截圖,這是本次作業的第二張截圖 --- 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 請把第一張、第二張截圖,分別貼到留言區

Github Desktop 新手入門教學:第2課 ── 學會基本指令

## 課程目標 - 學會基本指令 ## 課程內容 繼續上一課的內容,這次在同個資料夾內,再新增一個檔案 `my-document-2.txt`,裡面放入以下內容 ``` 我的第二個筆記檔案 ``` 接著打開 Github Desktop 看看狀況 會看到 `Changes` 分頁下面,現在有兩個檔案 分別點選檔案,可以在右側主視窗看到內容 --- 在 git 的觀念裡面,git 預期我們每次工作,都會修改到很多檔案 每次工作到一段落時,要提交進度給團隊時,都會一口氣將這些檔案變化送出去 這個所謂的「提交」,在 git 中稱之為 `Commit` 所以,你會很常聽到工程師說「這個 commit」、「那個 commit」、「上次的 commit」、「你昨天的 commit」 來試試看提交我們的第一次版本紀錄吧! 每次提交,都需要打一段提示訊息,方便日後翻閱,大致知道每個提交的內容 請在左下角的 `Summary` 輸入 ``` this is my first commit, i am so happy! ``` `Description` 可以省略,不用輸入 接著點擊 `Commit to main` 你會發現 `Changes` 分頁列表清空了!本來的兩個檔案不見了 這是因為 `Changes` 代表「這次正在修改的檔案」,送出 commit 代表「本次修改完成並提交」了,所以就不再有「這次正在修改的檔案」了 請點選旁邊的 `History` 分頁,會看到剛剛的 commit,點選 commit 可以看到相關的檔案內容變化,很酷吧! --- 讓我們多提交幾次檔案,試試看多次提交的感覺! 先建立新檔案,請建立 `my-document-3.txt` 並放入以下內容 ``` 我的第三個筆記檔案 ``` 然後在 `Summary` 輸入 ``` add another work ``` 之後就 `Commit to main` 直接點下去!又送出一筆 commit 囉! --- 來,我們再建立新檔案一次,請建立 `my-document-4.txt` 並放入以下內容 ``` 我的第四個筆記檔案 ``` 然後在 `Summary` 輸入 ``` add one more work ``` 之後就 `Commit to main` 直接點下去!又送出一筆 commit 囉! --- 點開 `History` 分頁看看吧! 會看到剛剛的三筆 commit 記錄都在裡面 點擊不同的 commit 可以看到對應的 commit 內容 Git 會追蹤整個資料夾內的所有變化!包括:建立新檔案、檔案內容的增加、檔案內容的減少、檔案被刪除 這些變化也會在每次提交 commit 時被記錄下來,所以都可以在 `History` 分頁看到記錄,很強大吧! ## 課後作業 接續前一課的作業,你的專案目前有一個 txt 檔案 這次要來模擬實際工作的時候,反覆修改檔案、增減檔案的過程 請按照以下順序送出 commit **第一個 commit:** 請把目前的 `me.txt` 檔案放進 commit 裡面。 **第二個 commit:** 你改變心意,覺得拆成多個檔案比較清楚,之後分別寫內容比較好 請把 `me.txt` 檔案的內容清空,改放以下內容 ``` 我是XXX,請參考其它檔案,瞭解更多我的介紹與背景。 ``` 新增 `about.txt` 以及 `background.txt` 兩個檔案 並且把 `我是誰` 的內容放進 `about.txt`,把 `我的學歷` 的內容放進 `background.txt` **第三個 commit:** 你靈機一動,覺得在履歷寫一些個人的大目標,會讓人感覺氣勢很強 新增一個 `goals.txt` 檔案,裡面放入以下內容 ``` 我的目標,是成為貴公司的 CTO(技術長)。 ``` --- 最後,點開左側的 `History` 分頁,應該會看到以上三個 commit 的訊息! 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 請直接截圖 Github Desktop 視窗的內容,上傳到留言區

Github Desktop 新手入門教學:第1課 ── 學會專案初始化

## 課程目標 - 學會專案初始化 ## 課程內容 在開始之前,我先再次說明一下 Git 與 Github Desktop 的不同 Git 是軟體工程師每天都會用到的,強大的專案版本管理工具,本身是命令列工具,要一直在終端機打指令 Github Desktop 是 Github 公司,為了方便入門者,所開發的 GUI(圖形化介面)工具,用起來簡單很多 本課程會交替使用這兩個名詞,前者代表 Git 正在發揮作用,後者代表正在操作 Github Desktop 功能 有點分不清楚沒關係,反正就知道有這差別即可,日後經驗更多,會越來越清楚 --- 讓我們開始玩玩看 Github Desktop 吧! 請先前往官網下載並安裝 https://desktop.github.com/ 在登入 Github 帳號的步驟,先選 `Skip this step` 跳過就好,我們後面課程再登入就好 --- 進入到 Github Desktop 主畫面之後,首先我們要設定一下 git 基本資訊 也就是在用 git 管理專案紀錄時,每次提交變化時,當筆提交的「作者資訊」 請在 Github Desktop 上方的導覽列,選擇 `Preferences` 然後選擇 `Git` 把 `Name` 跟 `Email` 欄位填寫一下,然後點擊 `Save` 按鈕,就可以囉! --- 來建立第一個用 git 管理的專案吧! 在主畫面,點選 `Create a New Repository on your Hard Drive` `Name` 就輸入 `my-first-repo` `Description` 可以省略不填 `Local Path` 隨便選一個方便的路徑 其餘的選項都保持預設就好,不用勾選 `Create Repository` 點下去,就建立第一個專案資料夾囉! --- 請在電腦上,直接打開那個資料夾,然後在資料夾裡面新增一個檔案 `my-document-1.txt`,裡面放入以下內容 ``` 我的第一個筆記檔案 ``` 接著打開 Github Desktop 看看狀況 會看到 `Changes` 分頁下面,有出現 `my-document-1.txt` 這個檔案 然後右側的主視窗,有顯示出檔案內容 這代表 git 已經發現它的存在了 我們成功使用 git 開始追蹤專案的歷史變化了! 這是一個很好的開始,本課先做到這樣就好! ## 課後作業 假設你正在準備履歷表,整理一些自我介紹、經營個人品牌的檔案 請建立一個名為 `my-resume` 的資料夾,並使用 git 開始追蹤這個資料夾 請在其中建立一個 `me.txt` 的文字檔案,裡面放入以下內容 ``` # 我是誰 - 我是XXX,目前在自學程式設計 # 我的學歷 - 高中:積極高中 - 大學:品質大學 ``` 你應該會在 `Changes` 分頁看到檔案出現 然後在右側主視窗,看到文字檔案的內容 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 請直接截圖 Github Desktop 視窗的內容,上傳到留言區

在家上班 WFH 反而壓力變很大?分享四個溝通技巧!

昨天在我們新手寫程式 LINE 群組,有幾個業界工程師&剛轉職的新手在討論: 公司有實施 WFH 在家工作制度,但沒人可以詢問、經常怕自己漏看訊息、整天感覺更焦慮了,怎麼辦? https://line.me/ti/g2/nipkjq2WoZPKX5dTn9tE9266aEOt6EOICFGa1g 這主題很好,我決定單獨寫一篇文章討論這件事情,跟大家分享 --- 首先,我認為 WFH 是一種「團隊技能」,也就是説:這不是一個人就能做好的事情,需要整個團隊的合作 再來,因為是技能,這不是每個人一入職就會的東西,需要經過訓練 總體來說,我認為要習慣「新的四種溝通方式」,分別說明如下 # 批次溝通 在辦公室大家可以隨時找同事討論、發問,也可以臨時團隊開會之類的。 遠端工作很難這樣做。因為人與人溝通的頻率被迫降低了,所以每次溝通的內容量要提昇。 建議養成批次溝通的習慣。也就是一次詢問多個問題、一次安排多個工作事項。 舉例來說,大家早上團隊視訊/語音開會的時候,不要只是每個人安排一天的工作量,最好把一整週的工作事項都先預排好。 這樣一來,當你手上的任務卡住,需要詢問別人問題、等待答覆、等待別人工作先做完時,可以先改做其他待辦任務。 這會讓負責安排工作任務的主管,工作難度提高不少。但習慣一下會發現效果很不錯。 發問的時候也是一樣。可以拿筆記本、或是在電腦開個檔案,整個早上陸續遇到、想到的問題,都記錄下來。 下次終於有機會跟同事通話時,一口氣問清楚。 就算只是用聊天室也一樣。 我常常一口氣丟出好幾個不同事項的不同問題。反正同事有空再逐一回答即可。 # 過度溝通 遠端工作絕對要避免這個狀況:因為溝通誤會,導致做了整天的白工。 絕對不可讓這種情況發生。平常在辦公室,隨時都能知道同事在幹嘛、有疑問也可隨時跟主管確認。在家工作可不行。 所以要養成過度溝通的習慣。我自己習慣是剛剛視訊時已經講過的事情,結束前我會再統整一遍、然後每件事描述確認一次。 結束之後,還會把我剛剛確認的事情打成幾個待辦,貼到聊天室讓對方再看一次。等於每件事我都跟對方確認2-3次。 我甚至會把同樣幾件事情,換個方式、換個角度再重新描述幾次,讓相關人都同意,我才放心沒有做錯方向。 有留紀錄的話,事後出問題也比較容易討論責任歸屬。 總之,在家默默工作幾天,然後才發現通通在做白工,是絕對不可以發生的。 如果你發現在家工作之後,自己會一直跟同事確認事情,或是同事會多次重複確認同樣的事情,好像大家變得有點神經質? 別擔心,這不但是很正常的現象,還是很鼓勵的現象。 # 被動溝通 拍同事的肩膀問問題、叫他過來開會、打電話給他…等等,屬於主動式溝通:以發問的人優先,被問的人配合發問的人的時間。 貼便條紙給同事、張貼事項在公告欄…等等,屬於被動式溝通:以被問的人優先,發問的人配合被問的人的時間。 被動式溝通以被問的人、接收訊息的人為主,有空時才答覆、做出反應。 遠程工作的團隊一定要習慣被動式溝通,否則遠程工作就沒有意義,也沒有效率,會變成很痛苦的事情。 網路時代讓被動式溝通輕鬆許多,只要採取多層次溝通就行了。 # 多層次溝通 多層次溝通指的是依照主動/被動程度的不同,分成至少3-4層溝通工具。舉例來說: 即時溝通:見面、手機/Skype/Hangouts/Zoom 通話 通訊軟體:Skype、Line、Facebook Messenger 工作聊天室:Slack 任務管理軟體:Bitbucket/Github、Trello 即時溝通是最主動的一種,碰面開會、打電話等等都算。在很多情況下,還是需要用這種方式討論、腦力激盪。最好每天約個固定時間線上通話一下。 通訊軟體則是次之的溝通方式,但因為訊息通知會一直跳出來,還是有點干擾。 工作聊天室是最常發生溝通的地方。這類工具的特色在於,忙著工作的人,可以直接把聊天室關掉,就不會被打擾。有空時再打開來看看有什麼需要回答的、討論的。 任務管理軟體是大家一起紀錄工作待辦事項的地方。需要日後方便翻閱的東西都記在這裡。 其它工具軟體像是 Google Docs、Google Sheets、hackmd 也都非常好用。 --- 以上是四種 WFH 個溝通方式,另外有兩點補充 # 被動式溝通優先,非必要不使用主動式溝通 上面提到的多層次溝通模型,越上面是越主動,越下面是越被動的溝通方式。團隊成員要慢慢習慣,非必要別使用主動式溝通。沒那麼急著得到答覆、急著需要處理的事情,就盡量用被動的手段溝通。 話雖如此,每天慣例性地在固定時段通話一次,可以大幅增加團隊的安全感。 # 每次開會都做線上筆記,所有檔案都對所有人公開 因為大家沒待在一起,開會完忘記會議細節的話,會需要一直詢問同事,很浪費時間也很煩。 所以開會時建議使用 Google 文件、hackmd 或是其他可以共同編輯的軟體,開會的時候一邊做線上筆記。 然後這些文件最好公開給整個團隊的人看到,讓全部資訊同步到全部人腦中。 這些技巧熟練之後,團隊成員不但可以專心工作,溝通能力也會全部上升。 像是跟客戶、合作廠商溝通這種本來就需要遠端溝通的任務,remote 工作者也比一般的工作者更知道怎麼溝通、避免溝通誤會。 # 結論 這些工作方式有點違反一般的工作直覺,所以容易被忽略。 但只要習慣一下,一定會發現遠端工作的好處,工作效率甚至比在辦公室更高。

Laravel 5.8 升級到 8.83 版本心得&筆記分享

手上有多個網站 都是 Laravel 5.8,放在一台 Ubuntu 18.04 的機器上(租用 Linode 機器) 四、五年了,一直沒去更新,最近終於下定決心來更新 首先把 Laravel 5 -> 6 -> 7 分多次升級,然後部署 都還算順利,官方的 upgrade guide 很清楚,簡單照做就完成 但是無法升到 laravel 8 因為需要 php 8 我那台 ubuntu 18.04 安裝 php 8 一直失敗 直接升級 OS 也失敗,一堆問題會出現 最後決定,在 Linode 租一台新的 Ubuntu 22.04 然後把專案通通搬過去 --- 因為專案中很多「用戶上傳的圖片」放在 local,所以都需要一起搬運 最後是用 scp 硬搬檔案 然後用 mysqldump 搬運資料 才終於順利升級到 laravel 8.83 了 詳細用到的指令大概像這樣 ``` scp -r [email protected]:/{PATH}/{FOLDER} /{PATH} scp -r [email protected]:/etc/apache2/sites-available/{CONF_FILE} /etc/apache2/sites-available/ a2ensite service apache2 reload create mysql user & database with phpmyadmin mysqldump --column-statistics=0 --default-character-set=utf8mb4 -h xxx.xxx.xxx.xxx -u {USER} --single-transaction -p{PASSWORD} {DATABASE} > /home/dump.sql; mysql -u root -p{PASSWORD} {DATABASE} < /home/dump.sql artisan down legacy site composer install -> new site is now online ``` --- 簡單筆記分享一下,希望能幫到一些人~ # Refs - https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-22-04#how-to-find-your-server-s-public-ip-address - https://itslinuxfoss.com/install-laravel-ubuntu-22-04-lts/ - https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04 - phpmyadmin password left blank, so it's random now - https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-on-ubuntu-22-04 - skip the whole Step 2 — Adjusting User Authentication and Privileges - `ssh-keygen` because I need a public key