CS50 problem set 6 作業回顧

陳雁智 (Marat Y. C. Chen)
Manjeaneer
Published in
6 min readNov 5, 2017

--

2017 cs50 下半場專注於 web programming ,從透過 telnet 對網站送出 GET/POST 的 request ,解讀 response 重點欄位,http 協定,到 python flask 微框架 (micro-framework),後續將 css, javascript, jQuery, ajax 建構上去

和之前作業一樣,pset 6–8 已經設計好程式架構並將未完成的重點功能留給學員,過程中探索各個模組如何互動與物件方法使用,pset 6 要求使用 python 重新實作 pset 1–2 的部分程式 (crack, credit, mario) 進而熟悉 python 語法,另一個 sentiments 裡,先讀懂在 python flask 的框架下程式的全貌,大部分著重完成主程式引用的 analyzer 模組中的物件方法。

Python 在語法上相對於 c 是平易近人許多,完前第一部分後對 python 語法熟悉後,應該感覺作業難度相對容易(註: 2016 cs50 的 pset6 是用 c 完成實作 http server ),較花時間的部分可能是了解 flask 本身的使用方法與 jinja 的互動,還有整體結構。

程式本身相對單純,這次回顧著重在互動的細節,也就是當 flask run 執行後, 使用的過程在 server side 如何處理送進來的 request,首先,預設的根目錄 “/” 在 application.py 被定義了以下的函式

@app.route("/")
def index():
return render_template("index.html") // 回傳 jinja 處後的 index.html

將瀏覽器的開發者工具打開 network 頁面,確實也看到送出了一個 GET / 的 request,server 即回傳相對應的 html,如以下的簡圖所示,收到了 route 到 “/” 路徑,執行 index() 然後將 layout.html 套入 index.html 後回傳

Scheme of sentiment ( 2017 cs50 pset 6 )
search_name for cs50

接著將 cs50 鍵入搜尋列後送出,可以觀察到這次 search 後面加上了 ?screen_name=cs50 做為參數,相對應的程式前半段則檢查了是否有 screen_name:

@app.route("/search")
def search():
# validate screen_name
screen_name = request.args.get("screen_name", "")
if not screen_name:
return redirect(url_for("index"))

若無則回到 index

回到簡圖中,送出 request 到接收到 response 的過程呼叫了 search 執行:

  1. 讀入 positive-words.txt 及 negative-words.txt
  2. 用 1. 所建立兩個物件 positives 及 negatives 建立 analyzer 物件
  3. 呼叫 helper.py 的 get_user_timeline 代入 screen_name 取得推特文
  4. 逐行讀取 3. 取出的 tweets 並送入 analyzer 的 analyze_tweet 做分析 (each line in tweets)
  5. 呼叫 helper.py 的 chart ,並代入情緒分析後的推文數目 (counts((positive, negative, neutral)) 產出圖表
  6. 代入 chart 及 screen_name 將 search.html 產生回覆 (response)

以上將這次作業的兩個流程及相對應的物件做一個大概介紹,可能會在內文注意到物件持續出現,不同於 c 語言,python 設計本身是物件導向 (Object-oriented) 語言,幾乎所有東西都是物件, a = 1 裡的 a 也是一個物件,而可以單純到只有一個變數或複雜到一個包含其它物件的結構像是 analyzer。

除此之外,python 物件會通常伴隨相對應的操作方法,像是作業內 analyzer是用正負情緒單字產生的物件,而它提供了一個 analyze_tweets 方法來分析一段文字中正負情緒並傳出總和分數。

Python 成為當下流行的語言原因之一就是開發者們開源各式各樣的模組 (module) 甚至框架 (framework) 讓其它開發者能夠專注實踐自己的想法上,很多時候需要某個功能只要 google 或到 github 上查詢關鍵字就能下載並導入 (import) 進自己的程式使用。

關於資訊安全

最後有一點值得注意的是在 template 裡的 search.html 使用到 jinja 裡的 safe

...(skip)...{% block body %}
{{ chart | safe }} // with safe
<h1> Chart without safe </h1>
{{ chart }} // without safe
{% endblock %}
Comparison: top {{ chart | safe }} bottom {{ chart }}

根據文件 safe in jinja 裡的說明,jinja 預設會跳脫 (escape) 所有字元,也就是任何 html 的語法標籤都會被跳脫掉,左圖下半部示範了沒有加上 safe 時,反而顯示一段 html ,進而檢視原始碼會看到所有語法相關的符號像是 " & > 等被用 &#34 &amp &lt被替換掉,瀏覽器就把這些字元當一般字元顯示而非 html 處理

原因是 jinja 為了防範 XSS (Cross-site Scripting) DOM 類型攻擊,避免攻擊者注射 (inject) 惡意程式碼,更全面的介紹可以參考 ant 對資安防範的簡報。

題外 — 關於簡單架構圖

就以往工作經驗的體會,系統由於過於複雜及牽連較廣的技術層面,提高了團隊成員對整體架構了解的門檻,導致各個成員只關注負責的部分,在溝通上淪為各踢皮球,解決問題時不找出根因 (root cause),往後耗費更多時間在修正不徹底的解決方案,過程反覆後造就出一個恐怖平衡的怪物,若能有一張成員都能有共識的架構圖,相信對團隊溝通與解決問題會有相當幫忙。

--

--

陳雁智 (Marat Y. C. Chen)
Manjeaneer

project manager/savvy programmer/marathon runner/critical reader