2017年5月31日 星期三

モノクローム・サイダー あの日の君とレトロゲームへ

モノクローム・サイダー あの日の君とレトロゲームへ

超好看阿阿阿阿阿
身為一個阿宅這根本是夢想中的愛情故事(?!)

內容是在講作者當初是怎樣透過電動認識現在的老婆,這本書用了很多電動梗來形容各種狀態,FF/DQ或是neogeo CD之類的都有出現過,看了我都想要買wonder swan玩gunpey了(算是男女主角的定情遊戲吧)。

當初在看的時候我一直都在想說~不知道會不會有女神轉生的梗呢~結果在最後的最後有出現,我好感動,嗚嗚嗚嗚...

裡面用詞也都很簡單,每個章節也都很短,日文不用多好應該也可以看得懂,總之超好看阿阿阿

第三次上五倍紅寶石rails課- end

結果後面的筆記被我拋棄了orz
(總之可以直接看龍哥寫的)

不過還是想說打一下上課的時候腦中浮現的以前的記憶。

雖然說我是資管畢業的,不過當初隔了那麼久才又去碰這些東西,其實真的很痛苦(也不是說現在就很上手啦XD)

首先因為完全沒有自己debug的能力,加上我又是打錯字之神,常常不小心就把程式炸了,雖然會試著想要自己修好,但這段時間老師講的東西當然就沒有進到我腦子裡去了。最後就是一直從github上抓code下來.....

還有一個很根本的問題,最一開始的時候連我現在要動的檔案在哪裡我都需要時間想一下阿阿阿阿,就算我知道我現在要改view,可是我可能要找一下他到底人在哪裡。

外加有一個是我到現在還是常常搞不清楚的,我其實記不起來現在這個變數裡面到底放了啥
x = 3這種我記得起來,但如果裡面是hash又array之類的我常常忘記現在裡面這種東西結構到底是這樣,雖然印出來看一下就知道了,可是好像其他人都記得起來QQ,不過我本人內建的ram很少這我倒是很有自知之明。




2017年5月24日 星期三

HiNative Trek快兩個月感想

https://trek.hinative.com/ja/trek/price

月費9800jpy
Daily English lessons for the price of a cup of coffee
(但我不喝咖啡)

之前一直都是加入英文會話型的服務,如果是要練會話當然還是線上會話比較實用,但就是要固定時間上線很麻煩,就算有些服務主打你可以臨時預約在線上的老師,可是通常比較好一點的老師的預約都是滿的,所以其實我也不太愛臨時找老師的形式。

外加其實一般線上課程的教材還是比較"課本",相對之下比較不貼近現實,想說試一下hinative的新服務好了,(但現在還沒有中文版,所以題目是日文的,而且當初我因為這樣子題目出不來呢www)

每個月的主題都不一樣,四月的時候是email,五月是面試,出的題目都很貼近現實,而且沒有標準答案,老師也都是依據你給他的答案幫你修改。(當你送出答案會馬上看的到標準解答,但老師會在依你的句子幫你修改)
星期一到五每天都會有一道題目,照它們網站所講的,從星期一到五出的問題會越來越複雜,你要甚麼時候回答都可以,累積到一定問題再一起回答也可以。
回答方式是text+audio(但我很少錄音就是了....因為常常是在旁邊有人的情況下回答)

題目大概像下面這樣(copy官網)
Type
Content
Sample
Level
Short Essay
Translate the following sentence into English.
御社のプロダクトはとても興味深いです。ぜひまた後でもっと詳しくお話を伺いたいのですが。
1
Q&A
Answer the following question in English.
Tell me more about what your company does.
2
Long Essay
Translate the following sentence into English.
業務を効率化することにより貴社の資金を大きく節約できるサービスを提供しています。
3
Essay + Q&A
Translate the following question into English and then answer it.
御社のサービスを導入すると、ユーザーのリテンション向上に、どういう風に効果がありますか?
4
Special
Reading & Listening Comprehension, etc.
This is a chance to review what you've learned throughout the week.
初対面の人に、あなたの会社の製品について説明しましょう。
???

不過一開始在email主題的時候我有點困惑呢,畢竟是要日翻英,但日文有一些其實翻不成英文的用法,比方說:
"お世話になります。"
恩...恩...恩??!!
這句的英文是甚麼??
後來發現範例回答的英文也沒有翻這句XD
之後我就無視這些其實英文信不太會這樣講的日文寫法了

另外一個每個月主題是固定的,碰到自己不太有興趣的主題不知道有沒有解決方法?暫停一個月?

p.s另外希望可以照主題來篩選出問題,依照現在的設計等加入時間變久出的問題變多,應該會不方便找到以前回答過的問題

2017年5月23日 星期二

還有說新手2,3個月就學很好的,通常那個人都不是真的新手。

2017年5月22日 星期一

不知道標題要叫啥

如果是說2個月學到別人2年的功力當然擺明是騙人的,不只是程式,所有東西都是這樣。除非哪天可以轉移別人的記憶。

但下面才是我真的想講的,
我覺得有一些人其實是看所有付費的課程不爽。(不分實體或是線上)

當你想付錢上任何的課,上網問值不值得,都會有人和你說不需要花錢,網上有很多免費資源。當然免費資源多是事實,
但要一個完全的白紙靠網路上任何免費的資源自己自學,其實有點殘忍。(天賦異稟的人除外)

如果曾經碰過好老師,你會知道有沒有一個會帶會教的人來講解差別有多大。(包括學校裡的),比方以前一樣都是會計,我碰過三個老師,真的上課感覺差很多。應該大部分人在當學生的時候都體會過這種感覺吧?

而且一個完全沒有頭緒的白紙,真的會知道要如何開始嗎?恐怕很難。
一開始可能興緻勃勃的航向偉大的航道....... 然後很快就沉船了(合掌)。

因為一開始真的很無聊,而且會不知道這些東西和自己腦裡想要做的東西關聯性在哪,書上文字又單調,可能你一行行看過去,然後也跟著打一打,還是滿頭問號。
我認為有老師在比較可以減少前面摸不著頭緒的情形。

而且有老師就代表你會有同學,就算是線上課程,通常也會有討論區。當然你要去外面任何一個網站問也都可以,但是其實感覺是不一樣的,對我來說在課程討論區裡面問問題的壓力是很小的,因為我是學生,我就是不懂才會花錢上你這個課,問的問題就算很淺也是理所當然。

但是,如果是外面網站呢?就算沒碰到酸民好了,真的問題太簡單也有可能被說自己好好會去看書,或者這google一下就有了。這當然有可能是事實,可是新手會需要人解決他心中那些在老手眼中看起來淺到不行的問題也是事實。

如果什麼問題都是得到"你google就好了",這其實很讓人受挫,會讓人開始覺得"是我比別人笨嗎?是只有我才會有這些問題嗎?"
但是如果是課程的討論區,你會很容易發現其實大家一開始的問題都差不多,不是只有你一個人在同樣的地方卡關。這點我覺得在最一開始的時候是非常重要的事。

最後,有些人會說不會自學才需要那些線上或實體的課程,....... 這兩回事好嗎?需要人領進門的不代表他稍微自己有點底之後不會自學。

2017年5月19日 星期五

hinative trek

https://trek.hinative.com/
老實說出的題目都很實用,什麼時候回答也都是看自己很自由,不過主題是一個月換一次
如果某個月的主題自己沒興趣的話好像有點麻煩

2017年5月14日 星期日

第三次上五倍紅寶石rails課 5/14

service

要使用別的功能的時候可以把method定義在service裡面
不過這邊其實我沒作筆記囧
參考一下

routes

後面接path的話可以方便改變網址,而且不用特別改link_to裡面的path

  resources :candidates, path: 'users'
        Prefix Verb   URI Pattern               Controller#Action
          root GET    /                         welcome#index
    candidates GET    /users(.:format)          candidates#index
               POST   /users(.:format)          candidates#create
 new_candidate GET    /users/new(.:format)      candidates#new
edit_candidate GET    /users/:id/edit(.:format) candidates#edit
     candidate GET    /users/:id(.:format)      candidates#show
               PATCH  /users/:id(.:format)      candidates#update
               PUT    /users/:id(.:format)      candidates#update
               DELETE /users/:id(.:format)      candidates#destroy

:id

其實我最一開始不知道什麼時候才要在path後面加東西,後來才瞭解到網址後面有id的都需要,其實寫candidate.id也是一樣的,但因為rails會幫忙把id抽出來,所以寫短一點的就可以了
  <% @candidates.each do |candidate| %>
    <li>
      <%= link_to candidate.name, candidate_path(candidate) %>
      <%= link_to '編輯', edit_candidate_path(candidate) %>
      <%= link_to '刪除', candidate_path(candidate), method: :delete, data: {confirm: '刪除嗎??'} %>
      <%= candidate.party %>
      <%= candidate.age %>
      <%= candidate.politics %>
    </li>
  <% end %>
candidate_path(candidate)可以只寫candidate就好,只把物件給rails也會自己判斷,但我個人會因為搞不清楚我在幹嘛,所以會寫完整的。(編輯的path不能改)
實際上html會變成下面這樣,都會變成data-*, 所以method其實放在data裡面也可以(只是也沒必要),或者想要另外傳一些資料進去的時候也可以寫在data裡面
<a data-confirm="刪除嗎??" rel="nofollow" data-method="delete" href="/candidates/1">刪除</a>

path

因為下面那幾個的path是共用的,所以刪除資料的時候記得後面method要說是delete,不然會跑到show,這也是我當初常用錯的東西
     candidate GET    /users/:id(.:format)      candidates#show
               PATCH  /users/:id(.:format)      candidates#update
               PUT    /users/:id(.:format)      candidates#update
               DELETE /users/:id(.:format)      candidates#destroy

find / find_by

Candidate.find_by(id: 1)
Candidate.find(1)
上面這兩個找得到id的時候得到的結果是一模一樣的,但找不到的時候的情形會不一樣,看你喜歡nil,還是喜歡處理例外
會回傳nil
Candidate.find_by(id: 999)
丟給你ActiveRecord::RecordNotFound: Couldn’t find Candidate with ‘id’={:id=>999}
Candidate.find(999)

edit的form

和new是可以共用的,而且畫面上會出現已經填好的資料(驚嚇),因為rails會去判斷你丟給form_for的是新的物件還是從資料庫抓出來的
(不過前提是要new和edit的變數名稱要取一樣的)
然後生出來的html長這樣,雖然method是寫post,不過因為是要更新資料,所以會偷偷幫你模擬用patch(瀏覽器實際上沒有支援patch,所以都是用模擬的)
<form class="edit_candidate" id="edit_candidate_1" action="/candidates/1" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="_method" value="patch">

partial

盡量不要在partial裡用實體變數

比方說最一開市像下面這樣子寫
# new / edit
<%= render 'form' %>
#_form.html.erb
<%= form_for @candidate do |f| %>
  姓名: <%= f.text_field :name %><br/>
  政黨: <%= f.text_field :party %><br/>
  年紀: <%= f.text_field :age %><br/>
  政見: <%= f.text_area :politics %><br/>
  <%= f.submit %>
<% end %>
雖然上面那樣也會動,因為他會自己去抓@candidate,但是如果controller裡面變數名稱不一樣就炸了,而且這樣子寫比較不好瞭解到底是在幹嘛。
比較清楚一點的方法是自己丟變數給他
#view
<%= render partial: 'form', locals: { candidate: @candidate } %>
#也可以這樣就好
<%= render 'form', candidate: @candidate %>
#_form.html.erb可以拿掉@了
<%= form_for candidate do |f| %>
  姓名: <%= f.text_field :name %><br/>
  政黨: <%= f.text_field :party %><br/>
  年紀: <%= f.text_field :age %><br/>
  政見: <%= f.text_area :politics %><br/>
  <%= f.submit %>
<% end %>

那如果是下面這種partial要拿掉@呢
<% @candidates.each do |candidate| %>
  <li>
    <%= link_to candidate.name, candidate_path(candidate) %>
    <%= link_to '編輯', edit_candidate_path(candidate) %>
    <%= link_to '刪除', candidate_path(candidate), method: :delete, data: {confirm: '刪除嗎??'} %>
  </li>
<% end %>
那render就改成這樣,然後上面把@拿掉就好了
  <%= render 'candidate', candidate: @candidates %>
但是這樣只是複製code貼上到另一個地方沒什麼意義,其實有辦法讓你連<% @candidates.each do |candidate| %>都不用寫
<%= render partial: 'candidate', collection: @candidates %>

#或者下面這樣,但因為精簡過頭我會不知道我在幹嘛,所以我不愛,記得第一次看到的時候整個滿頭問號

<%= render @candidates %>
#裡面一定要是單數candidate
<li>
  <%= link_to candidate.name, candidate_path(candidate) %>
  <%= link_to '編輯', edit_candidate_path(candidate) %>
  <%= link_to '刪除', candidate_path(candidate), method: :delete, data: {confirm: '刪除嗎??'} %>
</li>

view helper

所有的helper其實都會被載入,那如果不同helper裡面有同樣名稱的method會發生什麼事?
雖然大家都會被載進來,但是畢竟載入還是有先後順序的,而順序是照英文字母的排列a..z,所以放在檔名開頭字母順序比較後面的那個method會被執行

自訂action member / collection

有member和collection兩種方法,差別是前者會幫你帶id進來,後者不會
Rails.application.routes.draw do
  root 'welcome#index'

  resources :candidates do 
    collection do 
      post :vote1
    end

    #post :vote1, on: :member 其實只有一個的話這樣也可以寫
    member do 
      post :vote2
    end
  end
  # post "/candidates/:id/vote", to: 'candidates#vote'
end
#結果
vote1_candidates POST   /candidates/vote1(.:format)     candidates#vote1
 vote2_candidate POST   /candidates/:id/vote2(.:format) candidates#vote2

關聯

下面兩種寫法都可以設好Foreign Key,但我偶爾references會忘記加s=.=
另關聯其實是在model裡面做的,並不是在表格裡面做
#這兩個是一樣的
rails g model VoteLog ip_address candidate_id:integer
rails g model VoteLog ip_address candidate:references
如果是用下面那種寫法的話會幫你加以下的東西
class VoteLog < ApplicationRecord
  belongs_to :candidate
end

has_many

慣例上has_many後面會用複數,但其實用單數也可以正常跑(但是打一串完全無關的字是不行的),因為他會去找model名字或是類別,只是就會用動,還是照慣例走吧
#其實都會動
has_many :vote_logs
has_many :vote_log

counter cache

http://railsbook.tw/chapters/14-crud-part-2.html#step14-counter-cache
一般來說想要找出每一個candidate的vote_log的時候會需要去一筆筆的sql count查詢,像下面這樣
  Candidate Load (0.2ms)  SELECT "candidates".* FROM "candidates"
   (0.3ms)  SELECT COUNT(*) FROM "vote_logs" WHERE "vote_logs"."candidate_id" = ?  [["candidate_id", 5]]
   (0.3ms)  SELECT COUNT(*) FROM "vote_logs" WHERE "vote_logs"."candidate_id" = ?  [["candidate_id", 6]]
   (0.7ms)  SELECT COUNT(*) FROM "vote_logs" WHERE "vote_logs"."candidate_id" = ?  [["candidate_id", 7]]
   (0.1ms)  SELECT COUNT(*) FROM "vote_logs" WHERE "vote_logs"."candidate_id" = ?  [["candidate_id", 8]]
效能可能會比較不好,這時候可以用counter cache
先在Candadite新增一個欄位叫vote_logs_count
class AddCounter < ActiveRecord::Migration[5.0]
  def change
    add_column :candidates, :vote_logs_count, :integer, default: 0
  end
end
rails db:migrate之後在model裡面改成下面這樣

class VoteLog < ApplicationRecord
  belongs_to :candidate, counter_cache: true
end
然後在view裡面把count改成size,重新整理會發現sql變成只需要下面這樣
  Candidate Load (0.5ms)  SELECT "candidates".* FROM "candidates"

reset_counter

但會發現之前的票數不見了?!
可以直接進rails console去用,也可以寫個rake來執行
namespace :db do 
  desc "重置counter cache"
  task :reset_counter => :environment do 
    Candidate.all.each do |candidate|
      Candidate.reset_counters(candidate.id, :vote_logs)
    end
  end
end
執行之後票數就會正常了。
Written with StackEdit.

2017年5月12日 星期五

第三次上五倍紅寶石rails課 5/12

http://railsbook.tw/chapters/13-crud-part-1.html
這次的課有點不知道要怎麼有條理的做筆記,所以只記了一些我當初最一開始搞不清楚的東西比方說裡面什麼東西都沒有可是會動的action,或是不知道打哪來的params,還有充滿謎的form_for

想當初我第一次看controller的時候都很疑惑為什麼有些裡面明明什麼都沒有寫,可是為什麼還是有作用,後來才知道有些是因為before_action做了,外加預設都會幫你去render同名的view出來
#像這種不知道幹嘛的action
  def show
  end
那如果今天我把上面的index action也砍掉會發生什麼事呢?
答案是什麼事都不會發生XD
他還是會顯示出index(驚)
原因是因為雖然你沒有action,但是他還是會繼續去找同名的view
所以如果今天一個action什麼特別的事都沒有做,是可以不寫action的。
(不過我應該還是會照寫XD)
另外public資料夾裡面的檔案的優先權會在最前面,因為他不需要經過routes,如果你今天放一個index檔案在裡面,你在首頁看到的會是public裡面的index,而不是view裡面那一個

params

  get "/candidates/:id", to: "candidates#show"
比方routes像上面那樣子寫的話,一開始的時候其實我知道params[:id]可以抓到id,但我並不知道那個id到底是哪來的,為什麼這樣子就可以抓得到,等我發現原來是url裡面有的已經是又過一陣子的事了….(遠目)
<ActionController::Parameters {"controller"=>"candidates", "action"=>"show", "id"=>"1"} permitted: false>
有一個是我這次上課才知道的事,像上面這種你會發現不管是params[:id]還是params[“id”]你都可以抓到1,這是因為rails有特別做一些處理讓你可以不管是字串還是symbol都抓的到id。
不然原本ruby的hash用字串或symbol是當成不同的key,因為內部是用”===”來比較key是否一樣

resource / resources

如果今天routes是用resources :candidates,會得到下面這樣
        Prefix Verb   URI Pattern                    Controller#Action
          root GET    /                              welcome#index
    candidates GET    /candidates(.:format)          candidates#index
               POST   /candidates(.:format)          candidates#create
 new_candidate GET    /candidates/new(.:format)      candidates#new
edit_candidate GET    /candidates/:id/edit(.:format) candidates#edit
     candidate GET    /candidates/:id(.:format)      candidates#show
               PATCH  /candidates/:id(.:format)      candidates#update
               PUT    /candidates/:id(.:format)      candidates#update
               DELETE /candidates/:id(.:format)      candidates#destroy
如果你改成resources :candidate上面的網址和controller都會變成單數,所以一開始生成controller的時候就要用單數的,不過慣例上controller是用複數
如果是用resource :candidates的話,和上面會長得差不多,但通通不會有:id接在後面

form_for

雖然很好用,但是想當初對我來說是最大的黑魔法,很多東西我都不知道怎麼來的,畢竟我連html都不熟
<%= form_for @candidate do |f| %>
  姓名: <%= f.text_field :name %><br/>
  政黨: <%= f.text_field :party %><br/>
  年紀: <%= f.text_field :age %><br/>
  政見: <%= f.text_area :politics %><br/>
  <%= f.submit %>
<% end %>
> f.class #=>ActionView::Helpers::FormBuilder
form_for建出來的表單裡面會包含一個authenticity_token,在下一個步驟的時候(比方new到create的時候)會是檢查這一串東西是不是自己生出來的,會被擋掉,可以某種程度上防止有人亂來
(等我知道有這東西大概是半年後了吧XD)
<input type="hidden" name="authenticity_token" value="nGETyiPlewIYWrhrWI2M60V0oSxzXjy7eiNhh9MQTuN/7vg++OLprwmk3E6BgYFwbrgFOFWKECYBRE/ZH9hbxw==">

form params的值

<ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"nMX+QtDWxq0wp/9gR9HAmF5VtG0cAqW4vI4BWVVQM8N/ShW2C9FUACFZm0We3c0DdZkQeTrWiSXH6S8HmZgm5w==", "candidate"=>{"name"=>"tests", "party"=>"fdsf", "age"=>"fds", "politics"=>"fds"}, "commit"=>"Create Candidate", "controller"=>"candidates", "action"=>"create"} permitted: false>
以前我並不知道這些params是哪來的
我只知道params[:candidate][:name] 可以抓到我剛剛在form裡面填的名子,但我不知道到底哪來的
到我自己發現原來是來自name,而name是form_for幫忙按照規則建好的又是好一陣子以後了。
當初我真的很搞不清楚各種params到底打哪來的,對我來說都像是莫名冒出來的。
<form class="new_candidate" id="new_candidate" action="/candidates" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="gbNo9SfPSRpfCjlOUC60LtHy6o08C0ZcVUQaGgFwoTWFWqHKwO+IO1GksoAVvQ8icy1CMdcE+0NZTpc9kERR8w==" />
  姓名: <input type="text" name="candidate[name]" id="candidate_name" /><br/>
  政黨: <input type="text" name="candidate[party]" id="candidate_party" /><br/>
  年紀: <input type="text" name="candidate[age]" id="candidate_age" /><br/>
  政見: <textarea name="candidate[politics]" id="candidate_politics">
</textarea><br/>
  <input type="submit" name="commit" value="Create Candidate" data-disable-with="Create Candidate" />
</form>

strong parameters

為了防止被亂塞東西進來,所以rails4之後有了strong parameter,只有允許的幾個欄位會被處理
params.require(:candidate).permit(:name, :party, :age, :politics)
不過下面這樣就不用管strong parameter了,因為不是整坨吃進去,但是一般不會這樣子寫就是了
name = params[:candidate][:name]
party = params[:candidate][:party]

驗證錯誤後的行為

通常會像下面這樣處理
  def create
    @candidate = Candidate.new(cadidates_params)
    if @candidate.save
      redirect_to candidates_path
    else
      render 'new'
    end
  end
為什麼不用redirect_to呢?雖然功能上不會有任何問題,但是資料會被清掉,這是很惹人厭的UX體驗。
render只是借用new這個action的template,action沒有被重新執行一次,你人還是在create裡,所以本來填的資料都還會在。
另外create本身不需要view,那為什麼要用實體變數呢?因為不這樣子的話你render “new”的時候就會炸掉了,因為new需要@candidate這個變數。
如果只是create本身的話你變數取什麼都不會有影響(其實我之前都沒想過這問題XD)
不過你可能會看到你的view好像歪掉了,因為form_for會在驗證錯誤的時候多塞了一個field_with_errors
<div class="field_with_errors"><input type="text" value="" name="candidate[name]" id="candidate_name"></div>
.field_with_errors {
  display: inline;
}
#config/application.rb
config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }
Written with StackEdit.

當初學ruby的時候一個小小的困擾

就是
就是我一直記不起來for迴圈怎麼寫
for num in 1..3 do
  print("num = ", num, "¥n")
end
print("End")
我就是一直記不起來QQ
應該說雖然我大學畢業之後就沒有碰程式了,但意外的當初學的東西很根深蒂固的在我腦袋,像下面這種寫法
    int sum = 0;

    for (int i = 0; i < 10; i++){
      sum += 2;
    }
所以我始終腦中都會浮現滿滿的++,一直到現在其實也還是有點不太習慣
Written with StackEdit.

幾年來的QA感想

先說這不是針對某家公司的心得,而是我在幾家不同公司當過QA之後心裡的感受。(同時我也不會講到任何公司的名字)

先說結論,我不會推薦人當QA,至少在臺灣是這樣

why?因為要先在意品質QA才有存在意義,這種公司QA講話才有力量,但台灣這種公司多嗎?有是有啦,如果你進去了,真心恭喜你。

我待過專門幫人驗證各種logo或是產品的公司,現在想一想那家公司的QA要負責的東西是最單純的,我是指在部門間的政治關係上。
因為每個部門負責的東西不一樣,客人也不一樣,所以不會有互相背後射箭的問題,你就是把你分到的東西測好就好了,至於你可以學到什麼,就看你的造化了,畢竟每個部門都不一樣,但我認為你本來在什麼部門會影響到你之後容不容易轉到別家公司。比方測電視 v.s 測電腦的部門,後者出路會比較多。


之後我待的都是oem廠,這就........讓我深深感覺到之前的環境有多單純,但面對的人/部門多,其實對自己是有好處的,你可以更加知道一個產品要出去之前到底會經過哪些東西,工作上需要和人溝通的機率也會增加,之前畢竟只是外包出去的測試公司,你能接觸到的流程有限,但在oem廠通常黑暗(?)面也會看得更多。

更正確說是會看到部門鬥爭,雖然要一家公司沒有部門鬥爭很難啦,但.....Q是一個遠永會被箭射到的部門,雖然PM也是,但是差別在哪裡呢?QA沒有更後面的人可以拉到你前面撐十秒,PM/RD,全世界都可以說“為什麼Q沒有測到“,但是Q沒有什麼人可以在推出來了。

“為什麼你沒有測到”“為什麼你沒有測到”
這是每個Q都會聽過好幾次的話,的確我們的職責是要把東西測好,但現實上也很難保證一個東西完全沒有任何bug了,我相信如果時間夠的話,不管是pm還是rd還是q都可以把事情做得更好,偏偏時間永遠不夠,但這種事,發生在不同公司處理方法卻會很不一樣。

為什麼沒有測到或是是一個必須要問的問題,因為知道為什麼才能預防下一次(即使有時候真的沒有為什麼)但有些公司會讓我覺得其實大家沒有真的很在意“這個問題為什麼會發生”而是在意“反正先把箭射到別的部門那邊去啦,然後順邊刷一下存在感”,於是重點就會在先找出代罪羔羊,而不是解決問題。

有時候也會發現有些部門的人在聽到比方說odm那邊回報bug的時候會不管三七二十一先子彈打到Q來,但稍微問一下你會發現它根本搞不清楚狀況,比方說別人根本用不對的版本測試,或是測試手法沒有寫清楚。其實他就是想要讓上面的人知道他有在做事而已,存在感++
甚至有些人你可以從他表情就看得出來一副見獵心喜的樣子。

於是我始終有一種,QA在某些公司的最大作用似乎是背黑鍋?
平常不被重視,出事的時候大家才想到你
這就是我為什麼做不下去的原因。

當然還是有天生很適合當Q的人,但是,真的很少很少,很多人去問其實會發覺可能
1.他想轉但也不知道要轉什麼
2.想轉,但是沒有機會
3.反正工作就這樣吧(攤手)
雖然我認識的Q很多,但是有轉職成功的真的不算多。
平心而論Q是一個很好入門的職業,但至少在臺灣,我覺得很少人想要一直做下去,很多做很久的人其實最後都是變成和公務員一樣。
但是我還是會覺得如果你內心對自己到底適不適合Q有疑惑,那還是想辦法出去看看吧。

QA和QC有什麼差別?這個嘛......反正很多時候兩邊都是一大塊部分重疊的,所以自己google一下,反正只是參考答案,現實很難那麼理想。

最後我還是想強調一下,我不是討厭這個職業,只是真的要待對公司,然後那個公司要活得久。






2017年5月11日 星期四

到多有多少個“等於”?_?

程式裡面總是有很多長得很像的東西
== , === , eql? , equal?
比方像上面這四個不知道想搞死誰

==

https://ruby-doc.org/core-2.2.0/Method.html#method-i-3D-3D
應該是最常用的一個,可以用來判斷到底值是不是一樣。
浮點數和小數會自動轉換,所以下面這個會是true
1 == 1.0 #=> true
但是不會幫你轉換數值和字串,所以下面是false(記得javascript的話這樣是true)
1 == "1" #=>false

eql?

https://ruby-doc.org/core-2.2.0/Method.html#method-i-eql-3F
基本上和==大部分的時候都是一樣的動作,但對於數字的行為不一樣
1.eql? 1.0
 => false
看起來如果只是要比較兩邊值一不一樣的時候用==就好了,如果需要更嚴謹一點的判斷,比方說hash內部用來判斷key到底一不一樣的時候就是用eql?

equal?

檢查是不是同一個object
cat1 = 'cat'
cat2 = 'cat'

puts cat1.object_id # => 70301044011860
puts cat2.object_id # => 70301043992280

puts cat1.equal?(cat2) # => false
puts cat1.equal?(cat1) # => true

===

嗯…不同地方作用不一樣的樣子,感覺有點討厭(?!)
case裡面用來比較的方法就是用===,所以下面這兩個是相等的
case x
when A
  puts "AAAA"
when B
  puts "BBBB"
else
  puts "meow~"
end
if A === x
  puts "AAAA"
if B === x
  puts "BBBB"
else
  puts "meow~"
end
如果是數值或是字串的話行為和==是一樣的,不過還有一些不一樣的情形
#たのしいruby裡面的範例
p /zz/ === "xyzzy" #=> true
p String === "xyzzy" #> true
p (1..3) === 2 #=> true
如果有些錯的地方麻煩各位大大可以指正我
Written with StackEdit.

2017年5月10日 星期三

第三次上五倍紅寶石rails課 5/10 - TDD

今天上的是TDD,範例其實很簡單,但就算這樣想當初第一次上的時候我因為完全沒有這個概念,所以滿頭問號,畢竟那個時候我連更基礎的東西其實都還沒搞懂。

所以我其實很羨慕現在幾乎旁邊都有排一個實習生坐在旁邊的設計。
(不過我當初那個樣子我其實也不知道該從哪邊問起好,大概就像一個一般國中數學也2266的人你突然講微積分給他聽,就算他聽不懂也不知道該從哪問好差不多(?))

不過TDD讓我覺得很有親近感,大概因為我是QA出身?,雖然這是兩個不同的概念(p.s QA要做什麼依公司不同可能沒有有些人想的那麼單純,不過這邊省略介紹XD)

http://railsbook.tw/chapters/24-testing-with-rspec-part-2.html
存錢功能 原本帳戶有 10 元,存入 5 元之後,帳戶餘額變 15 元 原本帳戶有 10 元,存入 -5 元之後,帳戶餘額還是 10
元(不能存入小於等於零的金額) 領錢功能 原本帳戶有 10 元,領出 5 元之後,帳戶餘額變 5 元 原本帳戶有 10 元,試圖領出 20
元,帳戶餘額還是 10 元,但無法領出(餘額不足) 原本帳戶有 10 元,領出 -5 元之後,帳戶餘額還是 10
元(不能領出小於或等於零的金額)
RSpec.describe BankAccount do 

end
執行會出現下面錯誤,因為還沒有BankAccount這個class
NameError:
  uninitialized constant BankAccount

硬讓他過的方法

既然他是說找不到BankAccount這個常數,那我給他一個不就好了==+
反正他就只是一個會指到BankAccount這個class的常數
但是這樣寫code review的時候大概會被打…
BankAccount = 1

RSpec.describe BankAccount do 

end

番外篇

讓class用小寫的方法,雖然實務上用不到..
這邊cc就只是一個指向class的變數
同理上面的RSpec.describe BankAccount的BankAccount也是一樣的概念,就一個指到BankAccount class的常數
cc = Class.new do 
    def hello
        puts "hello"
    end
end

c = cc.new
c.hello

開始寫吧

上面class也用好之後執行rspec會看到很多像下面那種訊息,說找不到method
NoMethodError:
       undefined method `deposit' for #<BankAccount:0x007f9b0b6121c0 @amount=10>
要解決很簡單~給他一個就好了~就算裡面是空的也可以
def deposit(amount)
end
把該加的method都給他之後,現在錯誤訊息應該會像下面這樣
       expected #<Fixnum:31> => 15
            got #<Fixnum:21> => 10
原因也很簡單,因為現在method都是空的,裡面沒有做任何的運算,當然數字不會變成15,正確應該要改成這樣
class BankAccount

  def initialize(amount)
    @amount = amount
  end

  def deposit(amount)
    @amount += amount
  end

  def balance
    @amount
  end
end
這樣子”原本帳戶有 10 元,存入 5 元之後,帳戶餘額變 15 元“就會pass了
可是存款不可能存負得值進去,所以要加一下判斷
 def deposit(amount)
    @amount += amount if amount > 0
  end
這樣子“存錢功能”兩個就都會pass了。
領錢和提錢的概念差不多,下面是完整的樣子
class BankAccount
  def initialize(amount)
    @amount = amount
  end

  def deposit(amount)
    @amount += amount if amount > 0
  end

  def balance
    @amount
  end

  def withdraw(amount)
    # ">0"可以用positive?代替,可是這樣多打好多字
    if amount > 0 && enough?(amount)
      @amount -= amount
    end
  end

  private
  def enough?(amount)
    balance >= amount
  end
end


RSpec.describe BankAccount do 

  describe "存錢功能" do 
    it "原本帳戶有 10 元,存入 5 元之後,帳戶餘額變 15 元" do 
      account = BankAccount.new(10)
      account.deposit 5
      expect(account.balance).to be 15
    end

    it "原本帳戶有 10 元,存入 -5 元之後,帳戶餘額還是 10 元(不能存入小於等於零的金額)" do 
      account = BankAccount.new(10)
      account.deposit -5
      expect(account.balance).to be 10
    end
  end

  describe "領錢功能" do 
    it "原本帳戶有 10 元,領出 5 元之後,帳戶餘額變 5 元" do 
      account = BankAccount.new(10)
      account.withdraw 5
      expect(account.balance).to be 5
    end
    it "原本帳戶有 10 元,試圖領出 20 元,帳戶餘額還是 10 元,但無法領出(餘額不足)" do
      account = BankAccount.new(10)
      account.withdraw 20
      expect(account.balance).to be 10
    end

    it "原本帳戶有 10 元,領出 -5 元之後,帳戶餘額還是 10 元(不能領出小於或等於零的金額)" do 
      account = BankAccount.new(10)
      account.withdraw -5
      expect(account.balance).to be 10
    end
  end

end

哎~可是好像很多一樣的code出現了好幾次,看起來好討厭

let

可以用let解決這個問題
let(:account) { BankAccount.new(10) }
雖然看起來像是變數,實際上他是幫你定義一個account方法所以如果你把測項裡的account改成account(),他還是會動,所以他真的是個method,只是在ruby裡面小括號是可以被省略的。
    it "原本帳戶有 10 元,存入 -5 元之後,帳戶餘額還是 10 元(不能存入小於等於零的金額)" do 
      account().deposit -5
      expect(account.balance).to be 10
    end

before

也可以用before來解決這個問題,但是因為必須要用實體變數下面的測項才有辦法用,所以要記得除了把本來每個測試裡面的account = BankAccount.new(10)刪掉以外,也要記得把account改成@account
  before :each do 
    @account = BankAccount.new(10)  #要用實體變數
  end

all

另外除了before也有all可以用,但all只會在最一開始被執行一次

完整版
class BankAccount
  def initialize(amount)
    @amount = amount
  end

  def deposit(amount)
    @amount += amount if amount > 0
  end

  def balance
    @amount
  end

  def withdraw(amount)
    # ">0"可以用positive?代替
    if amount > 0 && enough?(amount)
      @amount -= amount
    end
  end

  private
  def enough?(amount)
    balance >= amount
  end
end


RSpec.describe BankAccount do 

  let(:account) { BankAccount.new(10) }
  # def account
  #   @tmp ||= BankAccount.new(10)
  # end

  # #all只會跑一次
  # before :all do 
  #   puts "hi @ all"
  # end

  describe "存錢功能" do 
    it "原本帳戶有 10 元,存入 5 元之後,帳戶餘額變 15 元" do 
      account.deposit 5
      expect(account.balance).to be 15
    end

    it "原本帳戶有 10 元,存入 -5 元之後,帳戶餘額還是 10 元(不能存入小於等於零的金額)" do 
      account.deposit -5
      expect(account.balance).to be 10
    end
  end

  describe "領錢功能" do 
    it "原本帳戶有 10 元,領出 5 元之後,帳戶餘額變 5 元" do 
      account.withdraw 5
      expect(account.balance).to be 5
    end
    it "原本帳戶有 10 元,試圖領出 20 元,帳戶餘額還是 10 元,但無法領出(餘額不足)" do
      account.withdraw 20
      expect(account.balance).to be 10
    end

    it "原本帳戶有 10 元,領出 -5 元之後,帳戶餘額還是 10 元(不能領出小於或等於零的金額)" do 
      account.withdraw -5
      expect(account.balance).to be 10
    end
  end

end
Written with StackEdit.

ARGV

很一開始就會學到的東西,不過因為我不常用所以還是忘了,簡單筆記一下順便恢復一下記憶。
借一下範例
http://www.rubyist.net/~slagell/ruby/examples.html
# Program to find the factorial of a number
# Save this as fact.rb

def fact(n)
  if n == 0
    1
  else
    n * fact(n-1)
  end
end

puts fact(ARGV[0].to_i)
執行的時候
% ruby fact.rb 1
1
% ruby fact.rb 5
120
ARGV會把執行的時候後面給他的參數以字串存成陣列
所以就算上面只傳一個1給他,在程式裡面還是要ARGV[0],然後因為通通會被存在字串,所以還要to_i轉成數字才可以
Written with StackEdit.

2017年5月9日 星期二

MemeMaker

長輩圖製作(誤)
總之就是可以動態組合圖片和文字的東西(果然就是長輩圖啊)
https://github.com/telsaiori/memeMaker/blob/master/MemeMaker.html
主要就是redrawMeme裡面的code
    function redrawMeme(image, topLine, bottomLine) {
      // Get Canvas2DContext
      var canvas = document.querySelector('canvas');
      var ctx = canvas.getContext("2d");
      // Your code here
      if(image != null){
        ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
      }
        //text attributes
      ctx.font = '30pt Impact';
      ctx.textAlign = 'center';
      ctx.strokeStyle = 'black';
      ctx.lineWidth = 3;
      ctx.fillStyle = 'white';
      if (topLine != null) {
        ctx.fillText(topLine, canvas.width / 2, 40);
        ctx.strokeText(topLine, canvas.width / 2, 40);
      }
      if(bottomLine != null){
        ctx.fillText(bottomLine, canvas.width / 2, canvas.height - 20);
        ctx.strokeText(bottomLine, canvas.width / 2, canvas.height - 20);
      }
    }
先判斷有沒有圖,有的話就畫出來
設定文字字型和顏色……
topLine有輸入字的話就畫出來
bottomLine同上
其實這部份很短,但我用了很久…….
不知道為什麼寫javascript的時候我的錯字率高到有點可怕(遠目)
然後
關於下面這兩行
   window.topLineText = "";
   window.bottomLineText = "";
我其實不懂為什麼我需要給他們一個”“,於是跑去論壇問了一下,下面是他們給我的回答
This is considered “good practice” to initialize variables which are
supposed to hold a string with an empty string. It also prevents
errors when we pass the variable as an argument and the argument is
supposed to be a string.

然後因為這個題目我才知道
原來javascript的if如果只有一行的話不一定要有{},雖然大家都強烈建議不要省略{}
http://stackoverflow.com/questions/7117873/do-if-statements-in-javascript-require-curly-braces
Written with StackEdit.

2017年5月8日 星期一

碎唸碎唸

老實說當初我說我想要學ruby的時候,有些人會和我說
“為什麼要學那個”
“你以後是用的到嗎”
“你要想你學了之後能幹嘛”

其實我當然知道如果是php或是c#能找到的工作比較多,用的人也比較多。
但既然我已經不像當學生一樣選課只能從學校開的課裡面選,那我當然是選一個讓我有動力的東西去學。

不過我有時候還是會想,叫別人不要去學某個東西是對的嗎。
或者說用一副“蛤?那是什麼?可以吃嗎?”的語氣是對的嗎?
就是一種潑冷水的概念。
當然你用的語言是真的比較多人學,工作也多很多啦。
只是我覺得實在也沒必要對想要學東西的人那樣說,
至少在我身邊那種真的很喜歡程式,
喜歡到你聽他在講相關東西的時候會覺得眼睛在發光,
頭上有音符在跳的人反而都不太會這樣子講。

不過,我在大學的時候就覺得就算一樣是寫程式的人,有些人其實真的很愛”文人相輕“,用詞正不正確我不清楚,但我想這種感覺很好理解。

番外篇:
不過勒,其實有人在我找工作一直撞牆的時候和我講過一些特例,像剛學rails的某人因為一直找不到rails的工作,因為門實在太窄,然後跑去投PHP結果反而上了的例子。
應該是因為php的工作多,人也比較好找,所以願意帶新人的公司也比較多吧。
然後說我也可以去試看看php或是node.js之類的。
當然站在他們公司的角度講這種情形其實某種程度上是很反應現實的。
我也真的認真想過我要不要也試看看好了,不過...........
對我的頭腦來說有困難
因為我是個有點難回頭的人XD
該怎麼說好勒,就是我覺得這樣子突然轉彎好像對不起我自己(?)
而且我都花那麼久時間了(還有錢)
我可以接受穩定之後學別的語言,但是要我在ruby on rails還沒搞好之前突然轉彎去別的同類型的語言,我還是不太願意這樣....
對我來說那可能回去老本行意願還高一點




HTML5 Canvas

下面是課程裡面最初步的code,就只是用canvas顯示一張圖出來而已
不過對我這種javascript菜鳥還是有一些不明白的地方,我一直都不確定到底什麼東西會在什麼時候被執行
也就是我搞不清楚程式執行的順序,就會傻傻以為都上到下

image.src = "222050-22rdf.jpg";
比方我不懂上面這個為什麼要放在onload的下面

這是一開始我心中最上面那段程式的的定義

  1. 建立image object
  2. 用onload去設定圖片讀完之後要做什麼事
  3. 用用canvas顯示在網頁上
  4. 然後最後才和他講圖片在哪裡?_?(黑人問號臉)
然後去論壇找一找有人問了類似的問題,發覺我最根本上會錯意了囧
因為,你沒有和他講圖片在哪裡之前圖片根本不會被load,所以onload根本不會執行
也就是
image.src = "222050-22rdf.jpg";本來就該放在後面啊~傻傻der~
借用一下udacity論壇上老師的解釋




2017年5月7日 星期日

還是不太好在blogger上用markdown

本來是覺得用stackedit的話可以很方便發佈文章到這裡,不過還是會因為這邊css的關係讓排版跑掉變很醜。
上一次想說乾脆整篇都用gist,但是會有外框好醜。
而且blogger的app只要上傳圖就會當掉,實在很悲劇。
但是又不知道哪邊比較好orz

第三次上五倍紅寶石rails課 5/7

2017年5月3日 星期三

寫履歷

寫履歷一直都是我最討厭的事情之一,因為我一直很討厭講自己的事。
其實用討厭這個詞不太精準,但也想不到要用什麼比較適合。
對我來說好像有一種把自己攤開來給人看的感覺(? )
我一直對於講自己的事給別人聽覺得很苦手。

反過來說,如果問我最不適合給誰面試,那答案一定就是"給本來就認識我的人面試"

好難整理...

之前有些程式相關的東西是用gitbook來記錄
比較短的會直接寫在這邊
結果變成有時候好難找東西囧
怎樣整理比較好勒