エンジニアのサブルーチン

あまり注目されない組み込みのシステムエンジニアをやっています。エンジニア業界のこととか、勉強したこととかを不定期に更新していきます。

dockerのコンテナに入ったらダラーが表示されなくなった話

お仕事でdockerを触っている。お仕事中GitBashで以下のコマンドを実行するとダラーが表示されなくなった。

 docker-compose run {IMAGE}  bash

試しにダラーがない状態でlsコマンドを実行してみると、コマンドは実行されてる様子だった。
同じ現象が発生してもすぐに対処できるように備忘録として記事にする。

解決策

以下のように、コマンドの先頭に winpty をつける

 winpty docker-compose run {IMAGE}  bash

GitBashはターミナルエミュレーターとしてminttyを使用している。
windowsのnativeなコマンドをminttyなどのエミュレーターで実行すると仮想端末との非互換性や文字エンコーディングの比互換性の問題が発生することがあるらしい。
winptyはwindowsのコンソールプログラムとunix系の仮想端末を通信させるためのインターフェース。
簡単に言うと、minttyを代表とする仮想端末でコマンドを打つと、問題が発生しやすい。ということらしく、その問題を解消するのが、winptyコマンドということらしい。

エンジニアになって

エンジニアになって3ヶ月立った。

 

研修は最も一般的なものでだいたい3ヶ月であり、その研修を終えると正式に社員として各部署に配属となる。

かくいう俺も無事3ヶ月の研修を終えて近々配属となるわけだが、配属される前に今一度エンジニアとは何か、あくまで個人的な見解なので、賛否はあるだろうし、間違っていることもあると思うが、それを恐れずにここに書こうと思う。

 

エンジニアとは何か

エンジニアとは簡単にいうと「ものを作る技術がある人」の事をいう。

 

より厳密にいうと、工学系のもの(例えばハードウェアやソフトウェア)を作る技術のある人なのだが、本質は同じなので問題はない。

しかし、付け加えると、ただものを作るだけならそれはエンジニアとは言わない。なぜならそれはただの趣味であり、DIYとか工作の類でしかないからだ。

エンジニアは、依頼を受け、それを依頼者の納得のいく形で作ってお金をもらって初めてエンジニアと名乗れる。

 

依頼者の納得のいく形を作ることは容易いことじゃない。

 

依頼者の思い描いているものがいかに正確に、詳細にエンジニアに伝わるかでも、できるものの質は変わる。

つまり、依頼者が曖昧なイメージのまま依頼を出すと悪いものができるし、逆にエンジニアが依頼者のイメージを忠実に引き出せないのも悪いものができるのである。

実はいいものを作るにはこの部分がかなり重要になってきて、この業界でいうところの上流工程に当たるのだが、この上流工程はプロジェクトの20%~30%ほどをしめる。

 

エンジニアはプログラムをひたすら書いているとよく誤解されがちなのだが、実際はプロジェクト全体の2割程度で、だいたいはもう上流工程で決まっているので、プログラムはそれに沿って書くだけなのである。

 

 

エンジニアが最も恐れるもの

想像はつくだろうが、エンジニアが最も恐れるのはバグである

2004年以降発生したタカタのエアバッグ問題を覚えているだろうか

automotive.ten-navi.com

 

世界シェア第3位のエアバッグメーカーだったタカタが自社製品であるエアバッグの不具合が多発、死者18名を出した。最終的に約8100万台のリコールが発生しそれが大打撃となり倒産した。

 

この出来事を見てわかる通り、どんな大企業でもたった1つのバグで倒産まで追い込まれる。全世界のIT企業、エンジニアはこれを常に恐れている。

その表れとして、プロジェクト全体でテスト工程がしめる割合は約30%もある。

このことから、いかにエンジニアがバグを恐れるのかなんとなくわかってもらえるだろう。エンジニアがバグを恐れるのは自分の書いたコードが人を殺すかもしれないからなのだ。

 

優秀なエンジニアとは

よく誤解されるのが、優秀なエンジニアはいろんなプログラミング言語を知っているとか高度なテクニックとかを知っている人のことをさしていると思われている。

そんなことは実際はそこらへんに落ちている石ころくらいどうでもいい。

 

真の意味で優秀なエンジニアとは、経験や知識もそうだが、いかに自分の担当箇所に責任を持っているか だと思う。自分の設計やコードに責任を持てない奴なんて適当に書いてるに違いないのだから、会社にとっては害悪でしかない。

世の中には便利だからか、昔からの癖だからか知らないが極めて危険性の高い記法を使う人だっている。

先ほど話したと思うが、エンジニアは1つのバグで人を殺しかねない。仮にそれに至らないバグだったとしても、バグの内容にもよるが、それの原因究明、修正に何百人といった人員が割かれて何千万と言ったお金がかかるのだ。迷惑この上ない。

 

しかもその危険な記法を使っているのが40代のベテランおっさんエンジニアというんだから殴りたくなる。正直今すぐエンジニアと名乗るのをやめてほしい。そしてこの先の人生で一度たりとも「昔エンジニアとして働いてた」と語るのも辞めてほしい。

 

本当の意味での優秀なエンジニアは、こう言ったバグを生み出す原因でしかない危険な記法を避けるだけでなく、自分の作ったものを誰がどう使っても問題のないように、そして誤解されないように作っている。

 

例として、一時期話題になったのだが、ニンテンドースイッチのソフトである

www.businessinsider.jp

子供が間違ってゲームカードを飲み込まないように苦味成分を塗っているのだ。

もし子供が間違って飲み込んだら?これも、最悪死に直結する大事件に発展してしまう。

これと似たような事がエンジニア業界でも発生しうるのだ。

 

こう言った事から、要は、誰から見てもわかりやすいコードをかき、どう使っても問題ないようにしっかりと対策を施す。優秀なエンジニアとして評価されるのは、こう言ったところから始まっていくと俺は思っている。そのためにも、なんどもいうが、自分の担当箇所に責任を持つことは大事なのである。

 

 

 

最後に

最近は給料が高いからとか、自分にあったスタイルの仕事が選べる。とかでエンジニアを目指し始める人が多いように見受ける。

実際に俺も新卒なら考えられないくらいもらっている。(これは社風にもよるかもしれないのだが...)

けれど、給料が高いのは技術職だからでなく、人のプライバシーや生命に関わる責任の大きい仕事だからでもあるのだ。

もしあなたがエンジニアを目指しているなら、いや、エンジニア業界に限らず、そう言った責任の重さを背負っていかなければならないという事を覚えておいてほしい。

 

俺も3ヶ月の研修でエンジニア業界について片足突っ込んだ程度のことしかしらないし、優秀なエンジニアどころか、まだエンジニアの最底辺に位置していると思っている。これからは常に責任を感じながらの仕事になるだろうし、正直辞めたいって思うときもこれからでてくるだろうが、一歩一歩それを乗り越えて日本を代表できるエンジニアになっていけたらと思っている。

個人アプリ開発記録3

開発規模縮小

開発規模縮小に至りました。なぜその結論に至ったか、経緯を説明したいと思います。

運営費用があり得んくらい高い

 まず運営料金がどれくらいかかるか調べたかったので、csvファイルを読み込むときにどれだけメモリを食うか調べてみた
f:id:code_sugar:20191125101738p:plain
これは4gbほどの大規模なcsvファイルを基準にしている。
応答時間を考えるとcsv読み込みにはPickleを選択したいがメモリを最大28GBも使用することになってしまう

なので、この中でもっともパフォーマンスがいいDaskでcsvファイルを読み込む事を想定して、話を進めていく

 まずECS Fargateの月額料金(ドル)は
合計メモリ料金 = タスク数 × メモリ (GB) × 1 GB あたりの料金 × 1 日あたりのメモリ使用時間 (秒) × 日数

コンテナは4gb タスク数1、を想定して作る。
1gbあたりの料金は現在0.0052ドルなので1日フル稼働した場合の月額料金は日本円にして

約620万円



無理に決まってる。料金はフル稼働した場合の話だけど実際はさらにかかってもおかしくないし、そんなにかからないかもしれない

今後の方針

 1ヶ月試行錯誤を重ねてきて、ここにきてやめるわけには行かないので、規模を縮小してローカルで動かしたり、BASIC認証をかけてデプロイして知り合いに声かけして遊んでもらう(クローズドベータテスト?)ようにする。もっと明確にはっきりとしてから今後を決めていきたいし、無理そうなら小規模で個人アプリとして発表したい。

個人アプリ開発記録2

Dockerいらないかも?

理由

  • コンテナ化するスクリプトを実行するのに必要なライブラリは、どのコンテナも全て一緒なので、無駄が多い

f:id:code_sugar:20191124120131j:plain

  • RailsからECSのコンテナ作成をしたかったけど、どうもできないっぽい(リサーチ不足でできるかもしれない?)

代替案

f:id:code_sugar:20191124115733p:plain

同じPython実行ファイルを並列実行できればいけそう?

課題と疑問点

  • 並列実行のパフォーマンスが未知数
  • 1つのプロセスに多数のユーザーがリクエストするから重たい?(nginxのワーカープロセスシステムのようなものを想像すれば、実現できそうな感じもする)
  • そもそも特定のプロセスにアクセスするなんて可能なのか?
  • プロセスで管理してたらサーバー落ちたらルームデータ全部消えるから、ルームデータをDBでうまく管理したい

個人アプリ開発記録1

作りたいもの

自己学習型Chatbotをユーザーが手軽に学習、公開でき、それを手軽に遊んでもらえるサービスを作りたい。

システム構成図

構想初期

f:id:code_sugar:20191123020800p:plain

問題点
  • メッセージを送信するたび、apiサーバーから実行ファイルを起動し、S3からcsvファイルを持ってこないといけないので、処理が重い。
  • オーバーヘッドが大きい


学習データはcsvファイルで格納するが、ファイルサイズが4gb、5gbになると想定すると、メッセージを送信するたびにファイルパスを参照して実行ファイルを起動する方法は望ましくない

構想途中経過

f:id:code_sugar:20191123020809p:plain

 実際に利用してみないとわからないことは多いが、問題点はDockerで全て解消できるはず。FlaskAPIをコンテナ化して、それを各ユーザーが起動して使用する流れ。

問題点
  • docker run すると指定したイメージを自身のdockerホスト上からimageを探し、なければダウンロードするらしい。dockerホストとは本番環境だとec2の仮想マシン上のことをさすのかな?ここら辺がよくわかっておらず、開発が難航している。

最終課題の反省点

 チームが二人しかいないから通常チームの倍の作業量を仕事しながらこなすというハードスケジュールもあって、ブログの更新も完全にやめてました。
ですが先日、納期1週間前に全てOKをもらいだいぶ余裕がある期間でメルカリの作成を無事終えれました。
 
 今回はそんな最終課題の反省会というか、「こうしておけばよかったなぁ...」と思ったことを書いていきたいなぁと思います。

メンバーと必ず意見交換をする。

 最終課題開始当初は、チームが2人しかいないというのもあってか、作業内容が違うしそこまで密な交流は効率が落ちるのですべきではないと考えていました。
しかしそれが災いしてか、開発で使う画像が別の名前で二つあったり、部分テンプレートがあるのにコードベタに書いたり、開発において非効率、冗長な記述が目立って悪戦苦闘していました。

なので、メンバーとの意見交換は濃密すぎるといっていいほど、できるのであればほぼ毎日するべきだと思います。

メンバーのプルリクは目を通すべきだった

 大規模な開発環境になると全メンバーのプルリク把握なんてできるのか?と思っちゃうけど、再利用可能な関数とか変数の見落としが減るので、作業効率は上がると思います。最終課題のチームなら出来るだけ目を通すべきなんじゃないかなぁと思います。

Github上でのメンバーとの交流を増やすべきだった

 前述につながるのですが、コードレビューをする時視覚的にわかりやすいのでガンガン使うべきだと思います。

Gitのコミット粒度を細かくするべきだった

 Gitのコミット粒度は細かくしておかないと、コミット履歴を確認したりする時、大変見辛いです。あとコミット名もしっかりしておかないとダメだったなぁと後悔してます。

まとめ

 大事なのはメンバーの報・連・相を短いスパンで定期的に行うこと。Github関連は見やすくなるように心がけること。

 そしてなにより当たり前のことなので書かなかったのですが、絶対にチームメンバーとの関係を悪くしてはいけないことです。嫌いだからといって絶対にその人だけ辛く当たらないでください。他のチームでたまにいらっしゃるので、チーム外の人間から見ても見苦しいです。やめてください。

Python100本ノック 6問目

f:id:code_sugar:20190826000429p:plain

自分のコード

def ngram(n,list):
  return [list[i : i + n] for i in range(len(list) - n + 1)]

lettersX = "paraparaparadise"
lettersY = "paragraph"

X = set(ngram(2,lettersX))
Y = set(ngram(2,lettersY))

print(set.intersection(X,Y)) #積集合 set.intersection(X,Y) == X & Y
print(set.union(X,Y)) #和集合  set.union(X,Y) == X | Y
print(set.difference(X,Y)) #差集合 set.difference(X,Y) == X - Y

print("Xに'se'は含まれるか")
if 'se' in X:
  print("True")
else:
  print("False")

print("Yに'se'は含まれるか")
if 'se' in Y:
  print("True")
else:
  print("False")

反省点

そもそも('se' in X)は真偽値で返すから単純にTrueかFalseかをprintで返すんだったら、print(str('se' in X))を使えばよかった

#リファクタリング前
print("Xに'se'は含まれるか")
if 'se' in X:
  print("True")
else:
  print("False")

#リファクタリング後
print("Xに'se'は含まれるか" + str('se' in X))

後print(X&Y)のように式を直接print内に書き込んでたけどこれも可読性が悪いんでやめたほうがいいと思います。 多少コードが長くなってもいいのでここを避けていくほうがいいですね。

学んだこと

集合

set()を使うことで引数内にリストや文字列、辞書などを集合に変換する。

set('aabbccdef') #文字列を集合に変換
# ==> {a,b,c,d,e,f} #重複が削除される

set(['a','bb','ccc','a','dddd'])#リストを集合に変換
# ==> {'a','bb','ccc','dddd'}

set({"hoge": "fuga", "hogehoge": "fugafuga"})#辞書を集合に変換
# ==>{'hoge','hogehoge'} #キーのみが集合に入る。

6問目のコードでも書いてるけど。setの色々なメソッドを使うことで積集合、和集合、差集合を扱えたりする。