無気力生活 (ノ ´ω`)ノ ~゜

脱力系エンジニア。てきとーに生きてます。

おちんぎんを増やす技術

12月、年末ですね。今年もあと数日で終わりです。個人的にも2018年はしばらくITエンジニアから離れてたり転職したりで慌ただしい一年でしたヾ(:3ノシヾ)ノシ

12月といえば、賞与の査定が出たり、目標設定フィードバックで昇給などがあった人もいるかもしれません。賞与もらってから転職しようとしている方も、もしかしたらいるかも知れませんね(`・ω・´)



さて、今日は給与と仕事の話でもしようかと思います。おちんぎん、増やしたいですよね?増えなくてもいいという人は居ないと思います。

今日はおちんぎんの増やし方をポエムします(`・ω・´) あくまで社会人10年程度の中堅くらいのITエンジニアのほざきですので世間とは乖離している点があるかもしれません。ということを前置きとして。

「もらってる給与が少ないから頑張らない」

Twitterで情報収集すること多いのですが、たまーに上記のニュアンスに近いことがRTで流れてくることがあります。 まあ気持ちも分かります。給与少ないのに仕事が増えてもやる気なんて出ない。人間、報酬に見合わない働きをするのは嫌ですからねー(´・ω・`)

毎月の給与という短期的な面の話をすると、給与分の働きしかしないこと自体悪いことではないです。使用者との労働契約に基づき、労務を提供してその分の賃金をもらう。労働者の権利ですよね。



『短期的な面』と書きました。私個人的な考えとして、「もらってる給与が少ないから頑張らない」は勿体ないことをしているなー、と感じます。もらっている給与以上の仕事をするのは、毎月給与をもらうという面では損です。

しかし、給与以上の仕事をし続けることで大きな利益が手に入ります。それは『問題解決の経験値』です。

給与はどうやって決定されるのか

さて、ここで少し頭を切り替えましょう。一つ考えてみてください。給与はどうやって決定されているでしょうか?

すごく単純でみんなが知っている当たり前の話なのでサクッと進めますが、企業はその人が持っている能力にお金を払います。

では、その能力とは何でしょうか?もちろん業種や企業の大きさにより答えが変わる話なので、明確にこれだ!という答えはありません。

ただ、共通するのは『会社の問題を解決できる力』です。雑に言われる課題解決能力ですね。例えば、新規顧客を開拓するのがめちゃくちゃ旨い営業の方であれば既存顧客の売上が低迷している企業が欲しがりますし、例えば、我々ITエンジニアであればシステムの高速化・低コストを考慮した設計ができる人や、障害の調査復旧が早い人。といった会社が困っている問題を解決できる能力です。



もちろん、こんなスーパーな話だけではなく、検算が正確で絶対に数字間違わない、という人から見れば小さな能力でも企業が欲しがっている能力と一致していれば、それは課題解決能力として扱われます。

『問題解決の経験値』を得るためにやるべきこと

「もらってる給与が少ないから頑張らない」を貫き続けるとどうなるんでしょうか?

1番大きな問題は『問題に挑戦する機会が与えられないこと』です。振られた仕事だけを適度にゆったりこなしていく。会社としては契約どおりの仕事やってもらってるし、やりたがっているわけでもないのであれば、その手の仕事を与えることはありません。会社の問題を解決する仕事なので、解決に導ける人に渡すものですからねー。

(´・ω・`)まあ黒いところだと無理やり与えるなんてことありますけど(黒い企業出身者で、仕事出来ない人あんまり見ないのと関連あるかも)



企業は、会社の問題を解決できる能力にお金を払います。その経験を積めない以上、いくら長く勤めていても給与が大きく上がることはありません。(年数千円の昇給くらいはあるかもしれませんが)

冒頭で勿体無いと感じているのはこれが理由です。自分で自分の給与が上がらない選択肢を取っている。「もらっている給与が少ないから頑張らない」は給与を上げるために必要な経験を積み難いため、結果いつまで経っても給与が増えていきません。



こう考えてみると「もらってる給与が少ないから頑張らない」は、実は「頑張らなかったからもらってる給与がすくない」で因果関係が逆転しているのかもしれません。

結局どうすればいいのさ?

常にもらっている給料分のより多くの仕事をやることを意識しましょう(`・ω・´) あ、もちろん同僚の仕事が終わらないから手伝う系の仕事はなるべく避けることをオススメします。得るものが小さすぎるので。

いえね、恩はうれるんですけどおちんぎんアップに繋がるかは運絡みです。(昔は手伝うタスクも喜んでやってたんですがあんまり感謝されないし、そのうち当たり前になるし、手伝った相手の手柄にされたりして自分のメリット薄かったので)

先輩や上司の”自分があまり経験したことないけど手伝える”ものを狙いましょう。給与は据え置きかもしれませんが、自分のやれることが増えていく。そうなると『問題に挑戦する機会』が与えられます。

そこで得た『問題解決の経験値』を武器に給与交渉するなり、転職の材料にするなり。その能力を欲しがる企業に対して売りつけられる自分の能力として使えるようにするのが大事(`・ω・´)

終わりに

実は私も最初給与少なくてですね、18で東京に出て来た時は手取り10万前半くらいで大変苦労しました(´・ω・`)

最初の会社に7年居て最初の5年位、もらっている給与分の仕事しかやれてなかったんですよね。結果25でも手取りは18万くらいで、残業代で生活する日々でした。6年めくらいから意識してやれることを増やしていくために、開発のテスト環境を整備したりセキュリティインシデントの社内共有等やってみたりしたんですよね。

そんな感じでやれることを増やし、率先してやったことないことに飛び込むことを続けた結果、今があるわけです。 こんなポエムを書いておいて、めちゃくちゃ高給なわけではないんですが、東京来た時と比較して今は3倍以上のおちんぎんをもらえています。大変ありがたいことです。

普段「もらってる給与が少ないから頑張らない」と思いがちな方。これ効きますよ!!高いおちんぎんをGETするためにぜひチャレンジしていただければと思います(`・ω・´)ゞ



あと、こんな話をしていると「年功序列で上がっていくから程々に働く」という論も出て来るんですよねー。こちらもうまく回っているうちは良いのですが、それなりに問題がある選択です。今日は長くなったのでまた次回にその話はしたいと思います。

2018/12/21 気になった記事まとめ

2018年も年の瀬。今年は一時期エンジニアやってなかったり、転職したり、転職したてですぐ炎上してたりと、仕事面では刺激的な一年でした。来年はもっといい一年になるといいなぁ、と思う次第。

面白いの評価は難しい

qiita.com

記事の本文見て真っ先に考えたのは、「面白いをどう判断するか?」の部分ですねー。 ダジャレに絞って言えば、似たような音韻を重ねるという特徴があるのでいわゆる分かち書きでやってるのかな?と思いましたが、それだとうまく解析できないケースがあるんですね。

しかし、以前に比べて機械学習もかなり普及してきましたねー。ちょっとした学習モデルを作るくらいなら特に難しい数式を使わずにできるようになってきてますね。近々画像の分類周りで触る可能性があるので試してみなくちゃなー(´・ω・`)

複数環境を docker-composeしているときよく困る

acro-engineer.hatenablog.com

可視化についての学び。こうしてすぐ試せる環境を作れるのもDockerの強さですね。DockerをECSでプロダクション運用する際のモニタリングに悩んでいたんですがこの辺参考にできそう。実際に自分で環境組んでみるのが一番効率よく理解できるので、年末年始でちょっと触ってみようかと思います。

非常に理解しやすい強化学習の実装面の話

speakerdeck.com

強化学習の資料をいろいろ目にする機会はあったんですが、ダントツに理解しやすい資料ですね。あんまり知識ない人でもこれなら雰囲気掴めるんじゃないんでしょうか?しかし、学習のやり方もいろいろありますねー

USキーボードを使い始めて半年がたちました

以前から度々チャレンジして来てしっくりこなかったUSキーボード。7月の転職を機にUSキーボードに切り替えて半年使った結果、今では逆にUS以外だと操作がおぼつかなくなってます_(:3」∠_

今回使い始めたのも割と偶然で、それまで仕事で使っていたキーボードが寿命を迎え、新しく買い直す必要に迫られたんですよね。使いやすくて良いキーボードだったんですが、充電式電池の流通が減ってきたのと、基盤がヘタって電源切れたり入ったりを繰り返すようになったので廃棄処分(´・ω・`)

せっかく買うなら自宅と同じキーボードにしたくなるわけですよ。家と仕事の環境はなるべく合わせるの大事ですし(`・ω・´)



今の会社に転職した翌々日くらいに時間に余裕ができたので秋葉原まで足を伸ばし、いくつかの店舗を覗いた結果、まあ普通にヨドバシが(ポイント加味したら)最安値なので、サクッと購入。 このキーボード、値段が比較的お安いんですがしっかりしたキーボードで、本体が重めでどっしりして安定して入力できるため、大変好みです。

購入した翌日、梱包そのままにして会社に持ち込み、出社後即開封を決めます。

封を開けたら鎮座するUSキーボード( ゚д゚)

見事に買い間違えてました。新たな職場に投入される慣れないUS。一瞬返品しようと思ったんですが、ぶっちゃけ自分の過失で買い間違えた結果なので、申し訳なくそのまま使うことになったんですよね( ̄・ω・ ̄)

最初はキー配置が完全に頭に入ってなかったので、キートップを見ながら入力する始末だったわけなのですが、それを繰り返していった結果USの方が入力早くなりました、やはりITエンジニア稼業、記号入力がしやすいUSが大正義だったわけですね。(`・ω・´)

なれていないツールでも使い続ければ順応していくんだなぁ、と改めて感じた学び。あとはカーソルキー依存体質さえ脱せれば、気の迷いで買ったっきり使ってない、この変態キーボードも使えるようになるのではないか?

たぶん(´・ω・`)

2018/12/20 気になった記事まとめ

日課の投稿です。欠かさず習慣化大事( ・`ω・´)

うちの四歳児に期待して買ったことがある(´・ω・`)

goodegg.jp

うちも子どもにこれさせようと思って、ラズパイ3が鎮座しております_(:3」∠)_ 当時四歳児にはまだ無理でした。そりゃそうだ。小学校入った後くらいに再試行しようかと思ってます。

コンピュータの教育の取っ掛かりとしてとても良く説明された投稿ですね。( ・`ω・´)しかし、最近の子供達は何かと恵まれてますね。人類の進化が急速に発展していっている気がします。彼らが大人になったころにはどんな世の中になってるんでしょうかね?楽しみです。

プロダクトを運用している以上避けられないSREとの付き合い方

speakerdeck.com

基本的な考え方や、何をするべきか?についてまとまっている記事。ここにはあんまり触れられはいませんでしたが、システム運用の自動化や運用フローの整備といった業務改善を積極的に行うことも含まれます。

そもそも問題が起きにくい作りにして信頼性を高める。意図的に(サービス影響ない程度の)障害を引き起こして常日頃から復旧に慣れておく。等、やるべきことは数多く(´・ω・`)

そういった体制や環境を常日頃整備して行けば、運用に手を取られずビジネス要件の開発に集中できるため、結果として安定した高速でリリースし続けられるプロダクト開発が実現できるようになります。

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

家具のレンタルサービスって正直どうですか?

subsclife.com

来年引っ越す予定なんですが、家具費用に回せるお金がなかった時に、一時的に使おうと思います。 購入だとどうしても気に入ったものが見つかるまで手が出せないんですが、これならテキトーに借りて生活しつつ、気にいるものが見つかったら即切り替え、みたいな使い方ができるかなぁと( ・`ω・´)

AuroraからOutfile S3で出力したpartファイルを1つに結合したかった話

# 本記事の環境
ruby: 2.5.0
Rails: 5.1

Amazon Auroraには、実行したクエリの結果をそのままS3に出力する機能があります。

docs.aws.amazon.com

Aurora v1.13くらいから使えるようになった機能で、弊チームではデータ分析基盤に流し込むために使っています。Selectした結果をTSVにしてS3として保存してくれるので、出力さえしてしまえば世の中の大方の分析環境で使えるのがいいですね( ・`ω・´)

実際に使うときは、こんな感じ(Aurora側にS3に吐き出すための権限が付与されているかつ、SQLの実行ユーザーにSELECT INTO S3のGrant設定をする必要があり。詳しくは↑のリンク)

SELECT *
FROM table
WHERE created_at > DATE_ADD(CURRENT_DATE(), interval 1 day)
INTO OUTFILE S3 's3-us-west-2://bucket/dir/key' 
OVERWRITE ON

楽ちん。これだけでS3にファイルをはきだせるので、ちょっとしたデータをサクッと集めたいときに便利そうですね。

この機能を使って全テーブルの全データを一日1回S3に投げつけようとします。Railsであれば対象となるModelに対し、columnsを駆使してSQLを組み立てればいけます。

model = User
query = <<~SQL
SELECT #{model.columns.map(&:name).join(',') }
FROM #{model.table_name}
INTO OUTFILE S3 's3-us-west-2://bucket/dir/#{model.table_name}' 
OVERWRITE ON
SQL

model.connection.execute(query)

確かこんな感じで行けるはず( ・`ω・´)

適切な権限があり、Bucketが作成済みであればこれでS3にファイルが出力されます。17000行、6.2MBくらいのデータで出力に700msほど時間がかかりましたが、そこまで遅くはない印象。

今回の困ったこと

さて、今回の本題はここから。 この方法で、例えばbucket/dir/usersとして出力した場合、実際には以下の名前で出力されます。

bucket/dir/users.part_00000

名前の後ろに勝手にpart_xxxxxがついてしまいます。S3への出力オプションを見ても制御する設定はなかったので、おそらく常にこの形式の名前で吐き出される模様(´・ω・`)

名前を見て想像できる通り、データセットのサイズが大きすぎる場合にファイル分割して出力されます。Amazonのドキュメントに記載されている内容をみると、

Amazon S3 バケットに書き込まれるファイルの数は、SELECT INTO OUTFILE S3 ステートメントで選択したデータの量と Aurora MySQL のファイルサイズのしきい値によって異なります。デフォルトのファイルサイズのしきい値は 6 GB です。ステートメントで選択したデータがファイルサイズのしきい値より少ない場合は、1 つのファイルが作成されます。それ以外の場合は、複数のファイルが作成されます。

とあり、6GBを閾値としてファイル分割するみたいです。

複数ファイルに分かれてしまう。特に事情がなければそのまま使ってもいいんですが、複数ファイルに分割すると分析基盤に取り込む際に考慮しなくてはいけないので、可能な限り1ファイルに固めたいもの。

そこで、マルチパートアップロード

S3には、大きすぎるファイルを転送する際、ファイルを複数に分割して送信しS3側で1つにまとめる『マルチパートアップロード』という機能がサポートされています。今回の1ファイルに固める際はこれを使います。

docs.aws.amazon.com

マルチパートは、基本的に以下の手順でファイル送信 + 結合を実現しているようです。

  1. AWS::S3::Client.create_multipart_uploadで、バケット名と出力ファイル名を渡す。実行結果として1つのMultipartを指すOrderIdが取得できる
  2. AWS::S3::Client.upload_partでファイルを送信する。保存できたらetagという固有のIDを返却する。
  3. ファイルをすべて転送した後、2で取得したetagとpart_numberを送信して、ファイルを結合する

これが基本の流れ。Auroraから吐き出したデータをこれに食わせて1ファイルに結合できればすべて解決できそうな気がします。Railsから試すには、gem aws-sdk-3をGemfileに追加します。

まず、今回はAuroraからS3への出力を行っているため、ファイルが存在しています。2の工程はスキップできそうです。後、3の工程で必要なetagですが、以下のコードで取得できます。

def bucket
  @bucket ||= Aws::S3::Resource.new(
    client: ::Aws::S3::Client.new(region: "us-west-2")
  ).bucket("bucket")
end

# キー名をprefixに指定すると、.part_xxxxxの要素が引っかかる。それのetagとpart_number
etag_and_partnum = bucket.objects(prefix: "dir/users").to_a.map{|obj| {etag: obj.etag, part_number: obj.key.match("\d+$").to_s.to_i})

この取得したetag指定してmultipartを実行します。

shared_options = { bucket: bucket.name, key: "dir/users" }
create_result = bucket.client.create_multipart_upload(shared_options)
# complete_multipart_upload: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#complete_multipart_upload-instance_method
bucket.client.complete_multipart_upload(
    shared_options.merge(
        multipart_upload: { parts: etag_and_partnum },
        upload_id: create_result.upload_id
    )
)

これでいけるかと思いきや、無残に失敗します(´・ω・`)マルチパートのetagじゃないぞ、というお怒りだったはず。

やはり正しく1,2,3の工程を実施する必要はありそうです。upload_partでファイルを送信し直すなんで、なんのためにOutfile S3をやったのかという気持ちになりますね(´・ω・`)

そんな折、こんなQiitaをみつけました。

qiita.com

つまり、upload_part_copyメソッドを用いて、バケットに存在するOutfile S3で出力したファイルをcopy_sourceに指定することで、改めてファイルを送信せずに目的にことが実現できる、ということになります。

最終的に、以下のコードで実現できました。

  def join_multipart_object(s3_path_key)
    # upload_part_copyのcopy_source指定のため、出力キーの一覧を取得しておく
    upload_object_keys = bucket.objects(prefix: s3_path_key).to_a.map(&:key)
    return if upload_object_keys.blank?
    
    shared_options = { bucket: bucket_name, key: s3_path_key }
    crete_result = bucket.client.create_multipart_upload(shared_options)
    begin
      # 一度上げたものを結合することはできないので、コピーを元に生成する
      etag_and_partnum = upload_object_keys.map.with_index(1) do |updated_key, idx|
        upload_result = bucket.client.upload_part_copy(
          shared_options.merge(
            copy_source: "#{bucket.name}/#{updated_key}",
            part_number: idx,
            upload_id: crete_result.upload_id
          )
        )
        {etag: upload_result.copy_part_result.etag, part_number: idx}
      end

      # 分割したファイルを結合する
      bucket.client.complete_multipart_upload(
        shared_options.merge(
          multipart_upload: { parts: etag_and_partnum },
          upload_id: crete_result.upload_id
        )
      )
    rescue
      # 処理失敗の場合は、abortを叩いてマルチパートを終了させる
      bucket.client.abort_multipart_upload(
        shared_options.merge(upload_id: part_struct.upload_id)
      )
      raise $!
    end

    # マルチパートを合成したら、元のファイルを削除して完了
    bucket.delete_objects(
       delete: {
         objects: upload_object_keys.map { |key| {key: key} }
       }
    )
end

def bucket
  @bucket ||= Aws::S3::Resource.new(
    client: ::Aws::S3::Client.new(region: "us-west-2")
  ).bucket("bucket")
end

2018/12/18 気になった記事まとめ

ここ数日の日経の調子が良くなく、私の懐具合も寂しくなってきました_(:3」∠)_含み損がっ!

バッチ高速化よくあるネタ

watson.hatenablog.com

遅いバッチの理由の割と大きな部分を占める、配列のincludesが大量に呼ばれる問題。よくありますね(´・ω・`)前職でも散々振り回されました。

素数が増えるに従って線形に遅くなっていくんですよね...大方Hashにすれば改善されるのもよくある話で。

しかしDTrace便利ですね。Stackprofとか言う手もありますが、Dtraceはプロセスに対して外から計測できるのがポイント高い。あ、調べたいな、と思ったときに即取れるのは強い(`・ω・´)

サクッと社内ツールを作るのに使えそうなjavascriptライブラリ

www.moongift.jp

自力で実装しようとするとかなり大変な機能がサクッと適用できるのはありがたいですね。前職ではw2uiとか使っていたんですが、あれもそれなりに便利でしたねー。

w2ui.com

ただ使い勝手とか見るに、tabulatorの方がモダンで良さげです。新しくなにか作るときはこれ使うと思います。

セキュリティコードの入力制限は意味を持ちませんでした(´・ω・`)

Visaカードの有効期限やセキュリティコードを数秒で割り出す「分散型推測攻撃」 - CIOニュース:CIO Magazine

PayPayの不正利用等で話題になっていた施行回数制限。複数のWEBサービスに分散させて処理させればいくら1サービスで制限かけても意味がないという記事。カードブランドのシステム単位で制限しないと結局は何度も施行されてしまいますな(´・ω・`)

なお、MasterCardだけは一元管理しているらしく、並行して複数のサイドでセキュリティコードトライしても弾いてくれるそうです。

2018/12/17 気になった記事まとめ

特に書くことがないときの日課です。 今年もあと数日出勤すれば終わりという現実が見え隠れしており、一年すぎるのマジ早くなったなーと感じる次第です。(´・ω・`)

アカウント削除をどう考えるのか

qiita.com

意味がない、という記事。実際にはデータの保持義務なりいろいろあるので、完全削除は現実難しいですな。論理フラグが良い、実削除が良い、と色々意見がある話ではあるのですが、一番は、

ユーザーは退会してどうなってほしいのか?

を真っ先に考えることですかね。サービスなりシステムを提供している相手が一番メリットを感じられることをやることを目指しましょう、というのが私の考え方です。

なので、自分なら

  • 決済履歴等、保持義務があるものはそのまま保持
    • 保持期限なくても、後から返金できるか?みたいな問い合わせくることあるのでつらい
  • サービス利用に関わる情報で個人が特定できる情報をマスクして、履歴を別ディスクに退避(例えばS3)

みたいにやるんじゃないかなーと考えてます。

Non-attribute arguments will be disallowed in Rails 6.0 えっ?

qiita.com

この記事で知りました(´・ω・`) 記事の内容より、タイトルで上げたことが気になって仕方ありません。あんまり使ってる所ないとはいえ、全部書き換えるの面倒だなぁ_(:3」∠)_というお気持ちに。

記事の本文についてですが、結論、SQLインジェクションを防ぐために、paramsの値を直接where条件に突っ込むのやめましょうねーって話だと認識してます。

入力値は必ずFormオブジェクトを作成してvalidationし、そこから引っ張る形を取るようにしています。あとでテストも書きやすいのでおすすめです。

class xxxForm
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :aaa, Integer
  attribute :bbb, String

  validates :aaa, presence: true, numericality: {only_integer: true, greater_than_or_equal_to: 0}
  validates :bbb, presence: true

  def initaialize(**params)
    params.each {|k, v| send("#{k}=", v) }
  end
end

# controller
if (form = xxxForm.new(params)).invalid?
 raise InvalidParamError(form.errors)
end

多分こんな感じ(動かしてない)

キモは事前に入力値を検証して正しいものだけ通す。これができていれば後工程で雑に扱ってもある程度は防げると思います。ただし、文字列をActiveRecordの条件式にする場合はちゃんとplaceholder を使いましょう(´・ω・`)インジェクションこわい

機械学習のコスト計算で考えたいこと

techlife.cookpad.com

学習はGPUほぼ必須なのは理解していましたが、学習結果を元に推論するだけならCPUで十分いけるんですね、という学びがありました( ・`ω・´)

それにしても1500万/yearの削減は凄まじいですね。わりとコスト計算おざなりになりがちなので、必要十分な性能をうまく見極められるスキルがほしいですねー(´・ω・`)

トランザクションとか、クラッシュ時対応とか、胃が痛くなりそうな設計

qiita.com

個人開発であれば、この内容でも、まあ動くとは思います。自分はやりたくないけど。

バックアップとかどうしてるんですかねー。巨大なしかも書き込みロックされているcsvをまんまコピーとか、タイミング次第では地獄を見そうな予感しかしないんですが_(:3」∠)_

とあるユーザーの決済履歴の一覧を表示させたいとして、どうやって探すんでしょうかね。全文検索ですかね。

と、いろいろつらみを感じさせそうな設計。何事もなく運用できることを祈ってあげたいお気持ちです。