Sign in

雖然起點是為了精進數位行銷,但我在學習的過程中發現,比起將產品推廣給消費者的行銷工作,我更希望自己能參與開發一個好產品。

學習程式語言的起因是想要升級自己的數位行銷技能,沒想到接觸到網頁開發領域後,愈學愈有熱忱,再加上完成各種專案的帶給我的鼓舞,讓我發現比起將產品推廣給消費的數位行銷工作,我更喜歡自己開發產品的成就感,因此現在正努力朝著轉職全端/後端工程師的目標前進。

因數位行銷工作,萌生學習程式的念頭

我的第一份工作是在電商擔任數位行銷,主要負責數位廣告投放。我喜歡數位行銷是因為能夠分析消費者在網站及社群上的行為,進而針對不同受眾客製化行銷內容,提升行銷成效。而為了要不斷優化成效及效率,學點程式語言似乎是必須的。

工作期間,雖然我的廣告投放表現每個月都在提升,但我知道有些事可以做得更好。例如:我們使用第三方平台會為行銷活動建立專屬的 Landing Page,雖然不用寫程式可以完成,但也因為模板的限制,沒辦法把我們的創意發揮到極致。另外,我常常有埋設事件追蹤碼的需求要麻煩工程師,來回溝通都要花上不少時間,如果我懂程式就能自行完成,提高效率。

不管是工作上會用到的製作 Landing Page 、埋設廣告追蹤碼等等的需求,或是我在工作外想自我精進的 SEO,都需要學會一點程式語言才能做到更好,因此我開始慢慢摸索怎麼學習程式語言。

學習程式語言初體驗的撞牆與失敗

身為一個完全沒接觸過程式語言的小白,剛開始就碰到難關讓我差點放棄學習網頁開發,轉而學起跟廣告投放較有關聯的數據分析。

我在線上學習平台購買了幾堂評價很好的網頁開發課程之後,就開始興致勃勃的上起課來,沒想到模仿老師的寫法是很簡單沒錯,但到了要自己做作業刻一個簡單的網頁時,卻完全不知道該如何下手。

這樣的學習經驗讓我開始產生自我懷疑,是不是自己太笨才會不懂怎麼寫網頁?因此當時決定先暫時放下學習網頁開發的課程,轉而學習聽說新手較好上手的 Python,也剛好從事廣告投放會有分析數據的需求,所以決定先學好 SQL 和 Python。

為了精進數位行銷,再次挑戰學習網頁開發

儘管失敗過一次還是阻止不了我對網頁開發的好奇,因為學會的話對我的數位行銷技能絕對是大大加分,因此我決定趁離職之後較多空閒的時間來專心挑戰。既然一個人看線上課程的方式行不通,我決定換個學習方式,經過一番必較之後,我選擇有進度制、有助教批改作業又能遠端上課的 Alpha Camp。

第一個月的課程從程式入門開始教起,不是一開始就要你照著課程寫出一模一樣的畫面,而是先從怎麼畫流程圖、程式邏輯、切版等等的基本功開始教起。打好基本功之後,在寫練習看設計稿做出基礎頁面的作業時,我竟然不用看解答就可以自己刻出一個頁面,看著畫面逐漸成形時心中充滿感動,原來我並不笨啊!

Certificate of Intro Course of Full Stack Web Development Program

達成最初目的的同時,開始對網頁開發產生熱誠

學完一個月的基礎課程讓我對網頁開發更加好奇,因此毫不猶豫地報名為期三個月的第二學期。這個學期的重點為建立網路開發的能力,了解網路產品如何運作、如何打造網路產品及如何設計好的網路產品。過程中我也逐漸發現自己對網頁開發的興趣,已經超越當初設立的目標了。

學期二的內容相對更有挑戰,我學到許多會對數位行銷有幫助的技能,達成我最初想學習網頁開發的目的。例如:我學會使用 Bootstrap 快速打造出 RWD 網頁後就能自行建立 Landing Page,還有當學會操作 DOM 節點去監聽事件時,也終於了解以前常常使用的 Google Analytics 為什麼可以紀錄網站上使用者的行為了,往後若要埋設廣告事件追蹤就可以自己來了!

除了達成最初設立的目標,我在學會更多進階技能如串接 API、使用 Axios 發送 Ajax 請求等等之後,發現自己愈來愈享受寫作業的過程,也會主動去觀摩其他人的程式碼,尋找優化的方向。這時候的我漸漸對網頁開發產生熱忱,開始不想止步於將所學的技能應用到數位行銷而已。

設立了更長遠的目標 — 轉職全端工程師

到了學期二的尾聲,完成多個小專案帶來的成就感,讓我發現自己比起將產品推廣給消費的數位行銷工作,我更希望自己能參與開發一個好產品。經過思考自己喜歡網頁開發的哪一個環節後,決定朝向擁有全端技能的全端/後端工程師的目標前進。

在這個學期,終於碰到期待已久的後端開發,一次性的學會了Node.js、Express、git、handlebars 等等新技術,我終於完成了第一個 CRUD 專案 — Expense Tracker。透過完成全端專案,我對怎麼打造一個網路產品有了初步的了解,詳細的專案介紹請參考:Expense Tracker 專案介紹

我發現自己很享受建立專案架構與操作資料庫的過程以及掌握資料處理邏輯來完成指定功能的感覺,也希望能有獨自打造具完整前後端功能網路產品的能力,因此設立了轉職全端工程師的目標,並馬上報名了為期八週的學期三。


題目:

You are given an integer array cost where cost[i] is the cost of ith step on a staircase. Once you pay the cost, you can either climb one or two steps.

You can either start from the step with index 0, or the step with index 1.

Return the…


Github Repo
Live Demo

原本的專案採用 server-side render 的全端模式,著重在後端的 CRUD 操作, 畫面則使用 Handlebars 來製作。一開始都用同步的方式渲染畫面,但為了讓使用者有更好的體驗,部分功能像是按讚、收藏有使用 Axios 加上 Handlebars compile 來改寫,但這種方式有些 …


LeetCode 124. Binary Tree Maximum Path Sum (Hard)

題目:

A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. …


LeetCode 236. Lowest Common Ancestor of a Binary Tree (Medium)

題目:

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the…


Simple Twitter 專案對我而言是很重要的里程碑,在過程中碰到了很多第一次,第一次團隊協作、嘗試前後端分離、設計 API 和資料庫結構、使用 Socket.IO 在三天內做出聊天室及即時通知功能等等,過程中需要大量溝通協作及解決問題,這些都是非常寶貴的經驗。

在開始之前先附上我們的專案成果吧:


Expense Tracker 首頁畫面
This project is Live here. You can use the test account below or register an account to login.email: user1@example.com/user2@example.com
password: 12345678

為何選擇這個專案?

因為想培養記帳的習慣,但一直找不到完全符合需求的記帳工具,於是在學會實作基礎的資料操作功能 CRUD 之後,決定打造一個專屬的記帳本,也期望未來能再加上更多進階的應用,開放給別人使用。

使用什麼技術?

前端使用 HTML/CSS/JavaScript 搭配 Bootstrap 框架加速頁面開發。

為了在後端也使用 JavaScript 開發,選擇了 Node.js 建立執行環境,搭配 Express 框架來幫忙接收 HTTP 的請求及做出回應、組織 MVC 架構,並使用 Express 內建的路由系統來實作 RESTful API。

Model 層面使用NoSQL 的 MongoDB 搭配 mongoose ODM,讓我可以直接用 JavaScript 物件導向語法來操作資料庫;View 層面使用與 HTML 結構相似的 handlebars 模板引擎協助將資料帶入樣板檔案並轉換成瀏覽器看得懂的 HTML 檔案。

打造使用者登入機制時,使用 Passport.js 套件來認證使用註冊帳號或 Facebook 帳號登入的使用者,搭配 express-session 套件儲存認證結果。另外為了保障使用者帳戶安全,使用 bcrypt.js 雜湊使用者密碼。

哪部分相對能掌握?哪裡花最多時間?

前端頁面因為設計簡單,再加上使用 Bootstrap 框架開發,是相對較能掌握的部分。

後端在建立基礎 MVC 架構和設定路由上也相對輕鬆,主要有三個地方花了較多時間:

  • 研究如何使用 Passport 套件認證使用者
  • 使用 mongoose 查找特定資料
  • 使用 async/await 及 Promise 重構種子資料

過程中碰到什麼困難?又如何克服?

當遇到不熟悉的語法(如 mongoose)、沒用過的套件(如 Passport)時,會去查找官方文件,但有時官方套件寫得比較生硬或沒有我要的使用情境時,通常善用關鍵字搜尋 Stack overflow 就能找到解決辦法。例如我不知道怎麼用 model.find() 的 mongoose 語法搭配 regular expression 和變數來查找資料,搜尋官方文件並沒有看到使用變數帶入的使用情境,後來用關鍵字找到Stack overflow 上的 How can I use a regex variable in a query for MongoDB 才解決問題。

過程中對哪個技術有特別深刻的學習?

首先,在建立登入機制時使用 Passport 套件,讓我有機會研究官方資料,了解每段程式碼的意義,並學會怎麼因應自己的使用情境來修改。除了 Facebook 登入驗證外,之後也會研究怎麼加入更多驗證策略來建立第三方登入功能來提升使用者體驗。

再來是在建立月份來篩選支出時,原本是使用 input type=“month”,結果發現竟然跟 safari 不相容,所以後來修改成下拉選單的方式。這是我第一次遇到瀏覽器不相容的狀況,之後也會提醒自己要注意這種情況。

最後,在建立種子資料時,因為非同步處理的流程問題,導致種子資料建立不完全,在研究 Promise 和 async/await 如何使用的過程中,對非同步處理有更深一層的認識,也完成挑戰把非同步的程式碼改寫成較好閱讀的 async/await 模式。


在餐廳清單的作業中,為了實作Cookie-based 憑證交換功能,保存使用者登入狀態,開啟一連串的找資料的過程。

實作前的摸索

首先,我透過作業的說明搞懂 cookie 和 session 的差別:Cookie 是在瀏覽器裡的儲存空間,而 Session 是在伺服器裡的儲存空間。 接著,我開始搜尋怎麼設定及讀取 cookie 和 session,發現有多種方法,其中利用 cookie-paeser 或 express-session 套件最方便且安全。

撇開安全性問題,因為這次作業是為了手刻憑證交換機制,所以我盡量不使用第三方套件,接下來就要用最人工的方法來實作了。

第一次出手與失敗

搜尋到 Sending and Receiving Cookies from Express.js 這篇教學之後,因為他也沒使用套件,所以我決定照著他的教學做一遍。做到一半後發現這個教學不符合我的專案,因為他是在使用者第一次到達網頁時就記錄 cookie,而我是想要在使用者登入後再紀錄,所以就打掉重練……

首先我在使用者成功登入後,使用 res.cookie(‘userId’, value) 設定 cookie,並建立 sessions 變數將使用者資訊用 sessions[userId] = { userInfo… } 的方式儲存在伺服器裡。

再來,我新增一個 getUserId function,用 res.header.cookie 的方式取得 cookie 資訊後,再用 split 的方法來拆解 cookie 取得 userId。接著在路由(home.js & restaurants.js)皆新增一個 middleware 使用 getUserId function,如果先前有設定 cookie 就會取得 userId。

前面的步驟順利完成,但在試圖取得 sessions 中的資料時遇到一個問題:由於我將 sessions 變數建立在 home.js 的檔案裡,所以我無法在其他檔案取得這個變數。

定義問題

原本在 home.js 的檔案裡就有用 module.exports 匯出路由,因此我再用一次 module.exports 想匯出 sessions 時無法執行。那有沒有其他辦法可以一次匯出多個變數呢?

尋找與嘗試

搜尋資料後看到 關於 module.exports 的兩三事 這篇文章,才發現其實module.exports 是個特別的物件,因此我試著使用 module.exports = { home, sessions } 匯出兩個變數,就成功在其他檔案取得 sessions 了。

回顧與發現

其實我一直都會使用 module.exports 來匯出變數,但因為我只是跟著課程的教學做,而之前都只有匯出過一個變數,導致我遇到要匯出兩個變數的時候就卡住了。幸好透過搜尋順利解決問題,透過這次經驗,也讓我學到會使用一個語法與真正深入了解他的差別,之後再學習時要更加謹慎!

最後附上此次實作的程式碼:https://github.com/ivyhungtw/Restaurant-List/commit/01db501fbeecf323e8180be64f07a1279a1f053a

資源分享

Sending and Receiving Cookies from Express.js https://alligator.io/nodejs/express-cookies/

關於 module.exports 的兩三事 https://ithelp.ithome.com.tw/articles/10185083


踏入 AC 學期 2–1 的旅程,這四週以來學習到許多新知識,並透過完成許多大大小小的作業,實際應用所學到的知識。隨著作業難度上升,漸漸會有卡關的時候,但通常藉由查詢資料、觀摩同學作業和詢問助教,就能順利解決。AC 的社群模式真的對學習非常有幫助!以下紀錄這學期學到的新知識的重點:

JavaScript 核心觀念

  • 變數的作用範圍:用 let 和 const 宣告的變數只會作用在被宣告的區域,子層可以存取到父層宣告的變數,反之不成立,水平區域也不能互相存取。
  • 基本型別與物件的區別:基本型別包含 undefined、null、string、number、boolean、symbol,所有不屬於基本型別的類型,都屬於物件,包括 array 和 function。
  • 資料結構(data structure):透過特定順序和位置,將多個基本型別組合成某種結構,以便有效率地存取或修改。例如,陣列(有次序的結構)和物件(key-value 結構)
  • 函式(function):基本用途為將會重複使用到的程式封裝起來,以利後續使用。JaveScript 特殊的函式特性:可當成值傳遞、可當成函式的參數、callback 在特定事件中觸發函式。
  • 參數(parameter)和引數(argument):參數是指創建函式時括號內的內容,只會被定義一次,預設值為 undefined;當調用函式時,括號內的內容則為引數,用來為參數附值,可使用多種不同引數來調用函式。參數的值會隨著每次調用的引數而變,而引數是透過 call by value 傳遞給函式的。

好用的前端框架 Bootstrap

由 HTML、CSS 和 JavaScript 寫成,預先做好一套網站基礎建設,讓人可以在這基礎上快速開發,核心目標是達成響應式和行動優先網頁。重點要學會怎麼查找官方文件,也能趁機好好觀察架構,提升開發的能力。

RWD 響應式網站設計

透過 CSS 控制,讓同一份 HTML 文件能在螢幕尺寸改變時,自動切換 CSS 設定,提升使用者體驗。

  • 行動優先 (mobile first) 強調行動裝置的使用者優先,從最小螢幕尺寸開始設計,程式碼放在最前面,再思考隨著尺寸變大網站內容應該要如何增加。

製作 RWD 的基本動作:

  • 定義預設的 viewport(使用者用來顯示網頁內容的區域),目的是告訴瀏覽器 viewport 的寬度基準、跟 CSS 間的比例關係。
  • 使用 CSS 媒體查詢 (media query) 切換樣式,在 media type 外再加上用括號表示的 media feature 條件。
  • 設定分界點 (breakpoint),也就是螢幕尺寸改變時,CSS 切換的發生點。

打造互動式網頁的起點:DOM 操作

將 HTML 解析為 JavaScript 可以操作的文件物件模型,也就是 DOM (document object model),為樹狀結構,JavaScript 可以操作 DOM 中的任意節點,最後呈現我們看到的網頁。查找 DOM 元素的途徑有兩種:

  • Select:直接選出一個節點,例如 querySelector 用 CSS 選擇器來找元素
  • Traverse 遍歷:選出一個元素後,順著樹狀結構找出其他元素

事件驅動程式設計

設置事件讓網頁能判對使用者行為,當使用者觸發特定事件時,驅動函式改變網頁狀態。實務上常使用事件監聽器 (event listener) ,將事件監聽器綁在元素中的兩個好處:觸發事件的元素跟被監聽的元素不必是同一個、可以將多個事件處理器 (event handler) 綁在同一個元素上。


Flex Layout Box Model

When we use display: flex or inline-flex to create a flex container, the direct children of that container become flex items.

Unlike box model, flexbox has two axes — the main axis which is defined by flex-direction and the cross axis; start and end lines; and size.

An illustration of directions and sizing terms for flexbox when the flex-direction is row.

Properties applied to flex container

flex-direction

Flex-direction is…

Ivy Hung

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store