組織でエンジニアとして働く自分について振り返る(Team geekの感想)

letterneginr.hateblo.jp

先日こういうオチのない記事を書いた。 本当は設計の正について調べなければいけないし、結局先輩の伝えたかった事ってなんだったのかを書いていかなければならないところなんだけど、 一旦勧めてもらった本を元に技術的ではない方向性のアプローチを学んだ。

Team geekという本。自分がもし新卒のエンジニアだったらリーダブルコードと共に読みたい本だった。 内容は筆者とプロジェクトの仲間たちの体験談を交えて、表題の通りに進んでいくのでかなり読みやすい。早い人だと仕事をしながらでも3日もかからないと思う。

コードを隠す 有害な振る舞いの追放 人に対する基本的な姿勢 プロダクトはユーザーに必要とされるもの

これらが一番刺さったと思う。

コードを隠す

努力や泥臭い部分を隠して仕事する人が多いという話、 でも実際にコミットの切り分けが綺麗だったり、細かい記法によく気がついて整備されたコードを書く人がいると思う。

それに、年数が浅いのに大きな機能の実装をやり遂げられたりとか、自学でセンスのあるエンジニアリングをしている人を見かけると、つい自分のやってきた事に対して自信が持てなくなる。

でもそことの向き合い方は恥だと考えて誰かと共有しないっていうのは本当に成長しない。 昨年いた環境はそれが顕著で、近いエンジニアと「出来ない」を頻繁に共有できなかったし、作るものの方向性も違って、楽しい気持ちすら共有できなかった。

正直に言って細部を理解する事に拒否的で、あたかも作り上げた自分がエライみたいな雰囲気を出す人は苦手だけど、 実際にそのプロダクトのオーナーはその人自身だし、誰かを喜ばせているには違いないんだなって思う。その行為だけで価値がある。

少し話が逸れてしまった気がするけど、技術に特化してプロダクトを美しくデザインする事にこだわりを持つ人が好きだ。 見えないところにこだわりを持てる人は細部をわかっているし、説明もうまい。話し方が論理的なので非常に助かる。

今はそういうレビュアーがいるところで仕事が出来て、彼は今度去ってしまう予定なんだけど、自分の浅いところをたくさん見てもらえてよかったと思ってる。 建設的な批判が出来るので、その行為が後戻りをすることはない。

有害な振る舞いの追放

これは多くが自分に当てはまる。 人間自身が悪いという視点を持つのではなく、その振る舞いがチームにもたらすことを考えなきゃいけない。 まずは、周囲に不安や動揺をもたらす行動をしない。w これが他人であった場合に、その振る舞いの理由と追い出し方を考えることが重要。 バイステックの個別化と似ているような気がする。

人に対する基本的な姿勢

Humility, Respect, Trustが大事だと。

実例でいえば、向き合っている人のスキルにもっと目を向けてもいいんじゃないかと思った。 みんなのわかる言葉で、物事をシンプルにしたり、困ったらこちらから頼ったり、何かを共有する時間を増やせば自然と健全な職場環境は出来ていく気がする。 (ランチでもいいけど、個人的にはランチ中に仕事の話はしないでほしい笑)

今の会社にいて思うのは、ユビキタス言語がバラバラで、エンジニアである自分ですら、参入後しばらくプロダクト自体について勘違いをしていた。 社内の人はお利口さんが多いので、なんとなく質問するのが憚られていたけど、ある日「めんどくせ」ってなったのでCSに仕様を聞いてみたりした。 あとでエンジニアに確認したところ、微妙にプロダクトの仕様の歴史に齟齬があり、新たな誤解を生んだ。 学んだのは「自分の立場を忘れない」「話し相手と自分の想像の同期を忘れない」事。

プロダクトはユーザーに必要とされるもの

なんかもうまともっぽく書くの疲れたので、3年弱くらい見てきたエンジニアについてを3行くらいでまとめる。

基本的に自分に自信がない
マゾが多い
自己顕示欲がすごいもしくは病んでいる

こういった特徴を持つ人間が集まるとどうなるか。必ず揉める。

決まって技術マウントもしくは宗教的な話が始まり、どっかの言語のコミュニティの有り体を借りるなら、「お前なんて俺の父ちゃんのパンチで一発だ」みたいなやり取りは1回はあると思う。

でも私たちがvimEmacsかで揉めているうちにユーザーの成功体験の機会は失われるか減る。

人に構われたくて、役に立ちたくて、喜ばれたくて技術を学んできたはずなのに、見えない状態になる。

この辺の話には深みが出るほどの経験は今の自分はしていない。思い出したら追記しようかと思う。

Angular初心者がルールを学びながらxlsx出力する

得意でない・興味のないものを触ると集中力が半減する私です。

そのようなテンションの中で、Angularを触れる機会があったので備忘録的に書いておきます。 かなりスカスカな内容なので繰り返し修正を入れていきたい。

構造

WebAPI(Rails) <--> Client(Angular2)

どこかのプロジェクトのAngularのプロジェクトの構造

hoge
 ∟hogeモデルのデータを行で表現している
 serviceから受信したデータの整形・Viewに干渉して変更を加える
hoges
 ∟hogeモデルのデータを集合で表現している、基本的な役割は上と同じ
models/hoge
 ∟hogeモデルのゲッタやセッタがある感じ
services/hoge
 ∟Web-APIと通信する層

悩みどころ

型を明示的に書かないjsしか経験がなかったので、フロントのノリで触るとしたらなかなかに馴染みにくい。

やりたい事はあるけれど、Angularにどのように適応させたら良いかが掘りづらい。(Angular(初代)の内容もよく引っかかるから) →Angular - Angular2などのマイナス検索が有効

正直公式ドキュメントだけでは実装への応用が難しいと感じる、手を動かしてから細部を理解する派なので。 何やってるかわかんないからコードを追うけど、よく迷ったりする。

基本テンプレ

html

  • *ngIf -> 条件分岐。
  • {{}}/{{| date:'yyyy/MM/dd'}} ->ディレクティブ。名の通りダイレクトに関数を呼び出せる。返り値がそのまま反映されるので、パイプでフォーマットの形式を指定できるらしい。nullにするとParser Errorを吐いてブチギレる。
  • (change) -> changeイベント。対象のhtmlを管轄しているモデルのメンバ・関数が呼び出せる。こいつらの値に変化があればイベントが発火する。
  • [(ngModel)] -> モデルのメンバを呼び出す。exportしているクラスの中にいるやつ。この値に干渉します。イベント発火マンと併用するといろんなことができるよ。
  • [hoge] -> モデルで定義したメンバを呼び出します。
  • #downloadLink -> href属性で飛ばしたい先として指定することができる。公式の引用先を見たことがないのでこの説明にはとても不安がある。

ts

  • @Input -> モデルとhtmlをバインドするところ。これにバインドされたコンポーネントからはimportした範囲のモデルロジックを呼び出すことができる。
  • @Output -> イベントを外へ伝搬させたいときに使う。メンバとhtmlをバインドさせて、関数でこのメンバに対して変更があった時に変化をもたせたいときに使える。 クラスのインスタンスを作って、同期もしくは非同期に描画するイベントを作ることができる。インスタンスに影響があったらViewにも反映できるってところが違いかな。 ex; @Output() modelChanged = new EventEmitter();ってのがあったら (modelChanged)ってhtmlにバインドできる

実装

やりたい事:チェックボックスにチェックした行データについて、xlsx形式でファイルをエクスポートする

苦労もしくはめんどかったポイントだけ

某UIフレームワークはlabel + inputの順で解釈しないとCSSを当てない点 ツールチップを作るのにそのUIフレームワークの名のprefixが必要(なんで???)

慣れないうちは純粋なjsで書いた方がいいのか、Angularで解決できる話なのか切り分けが難しかった -> 多分だいたいAngularさんはできる、うちはunderscore.jsが入っていたのでその辺を利用してデータを整形したりするなど。でもfunctionって長い…よね…

xlsxのMIMEタイプがよくわからないので受け渡しの仕方がモヤっとしている -> ポストする時responseType: ResponseContentType.Blobを利用する(多分あとで丁寧に書く)

お前の会話にはコミュ力が足りない

コミュ力ってなに

ここでは相手と疎通できる共通認識がある状態の事を指す。

業務上で意見聴取出来るし、困った事はない。

程度にもよるけど、よそのエンジニアと話す際に浮き彫りになった事例を下記に記す。(*お前=筆者を指す)




自分「イケてると思っていたAndroidアプリに設計のダメ出しをされた」
某氏「お前はどこがイケてると思ったん」
自分「ViewModelとかLiveDataとか使ってるし、画像のキャッシュも考慮して…」
某氏「それって当たり前やん?」
自分「!?!?」


某氏「設計はどうしたら良かったと思う?」
自分「モジュールに切り分けて…APIを分割して…」
自分「アッあのライブラリ使えばよかったな…」

某氏「なんで?」
自分「MVVMっぽくない」
某氏「MVCでよくね?」


某氏「君はなぜにMVCとMVVMという設計手法があるんだと思う?」

自分「っえーー……」(カス)
自分「MVVMはガベージコレクションを考慮されたなんたらでえ…」

某氏「Railsはファットモデルが良しとされてるよね?
これはドメインに合わせてスケールが出来るようにという意図があるみたいだけど」

自分「あーそうみたいですね。自分はあまりいいとは思えないです」

某氏「え!?!?!?」


↑↑↑
自分:基底クラスを継承しているにも関わらず、改修が冗長的になった事例を思い浮かべている(悔しい記憶)
某氏:プロダクトに必要なものを具体化出来るDDD手法について思い浮かべている



某氏「ていうか今そういう観点で話してへんやん?」

自分「…」


(この後某氏による認識合わせの時間が入る)


個人的まとめ

絶望的に会話が噛み合わない

- なぜならお前の言葉の定義が薄っぺらいから

想像力が足りない

- この後の話題の展開まで想像できていない
- 思いついた言葉を舌に乗せている
- なんか感情が先行している気がする

コミュ力を上げる為に(小2の発想)

- みんなが読んでる本を読む
- エンジニアと話す
- お利口さんぶって細かい技術の話をしない。みんなが知ってる話題(概念的なの)を取り上げる。




思いついたら追記する。コミュ力は個人的に永遠のテーマだ…。

今更Vue + github pagesに触れてみる

デプロイの度に真っさらなページが出ていたので、まずはアセットを読み込んで表示するところまでやってみた。

冬に比べてだいぶ記事が出回っているので既出感あるが…。

自分の場合、ルートパスにvue.config.jsを置いておくのを忘れていて、こちらをgithub pagesのドメインと合わせるのを忘れていました。後、ビルド後のディレクトリをdocsにしたものの、プロジェクトの設定でそれを有効にしてなかった。

githubpages-deploy-settings

デプロイ自体は5分足らずで終わった印象。

jelly

ぼよんぼよ〜ん

こうやって無駄に動きをつけるのが好きです。
display: flex大好き人間なんですが、デフォルトのタグでv-flexなどが用意してあるのが良かった(小並感)

なんかコピペでそれっぽいのを作れてしまうので恐怖感はある。
デプロイ先はこちらです。



引用元:

Deployment | Vue CLI

Kotshi+MVVMをカジュアルに採用してみた。

GWも過ぎて、ハイテンションで迎えた令和もすでに鬱々とした気分で過ごす日々です。
今回はKotlinでアウトプットする機会があったので、便利ライブラリを簡単に紹介します。



ネイティブアプリケーション開発においては、バックエンド側のWeb-APIRailsなどで用意することが多く、Kotlinで開発するクライアント側はリクエストを送信し、レスポンスに乗っているJsonを整形することで表示するデータを取得します。


しかし、null許容を搭載しているKotlinにおいてはKotlinJsonAdapterFactoryなるものを追加しない場合に空のJsonをパースする際にぬるぽが発生したり、
Moshiなるアダプターを使用するもののリフレクションを搭載している為に解釈が遅いといった問題があります。


Jsonを解析する時の問題

まだこれらの利点を払拭するような実感は得ていませんが、今回はKotshiというライブラリを使用することにしました。

よくある画像とコメントをリスト形式でレスポンスするAPIを例に、下記のようなクラスを実装しています。


Response


{
params: {
total: 100, # 総レコード数
offset: 50, # オフセット
limit: 5 # リクエスト時指定の取得数
},
album_records: [
{
"image_url": "https://album-records.herokuapp.com/images/hoge.jpg",
"comment": "Hoge",
"tag": "programming",
"recorded_at": "2019-05-10 00:04:00"
},
{
"image_url": "https://album-records.herokuapp.com/images/fuga.jpg",
"comment": "Fuga",
"tag": "programming",
"recorded_at": "2019-05-10 10:12:50"
},
...

Client


// 実際にJsonを解析するアダプタークラス
@KotshiJsonAdapterFactory
data class Album(
@field:Json(name = "params") var params: GetDataParams,
@field:Json(name = "album_records") var albumRecords: List
) {

companion object {
val INSTANCE: AlbumRecord.Companion = AlbumRecord
@ToJson fun toJson(writer: JsonWriter, value: AlbumRecord, stringAdapter: JsonAdapter) {
stringAdapter.toJson(writer, value)
}
}
}

// 取得したいインナークラス(album_recordsの中身)
data class AlbumRecord(
val image_url: String?,
val comment: String,
@Json(name = "tag") val tag: String?,
val recorded_at: String?
)

// リクエスト時のパラメータ(今回は使わない部分)
@JsonSerializable
data class GetDataParams(
val total: String,
val offet: String,
val limit: String
)

// レスポンスを格納するViewModel
class AlbumRecordViewModel: ViewModel() {
val albumRecoLiveData = MediatorLiveData>()
}




@field:Json(name = "params") のように指定することで、Jsonを解析してくれる名前を与える事が出来、後置の名前でクラスのメンバとして振る舞います。
Kotlinのdata classはtoStringなどが備わっているので、パースで入り用の際にはデータを処理するメソッドを用意する手間を無くし、憂鬱な気持ちも軽減してくれます。


今回はリスト形式のオブジェクトが含まれていた為に、クラスを切り分けつつうまく解釈してくれるような構造にしました。不必要な部分については無視してくれる便利なアノテーションも存在しますが、下記のエラーに対応していて実装はしませんでした。


Exception in thread "main" java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 16 path $.response
https://stackoverflow.com/questions/41649731/gson-expected-a-string-but-was-begin-object
つまりはStringとして期待されたメンバはオブジェクトでやってきちゃったよ!
どうしろ言うんじゃい!!!

と言うKotlin(もといJava)様の叫びです。
これは上のようにparamsとalbum_recordを切り分けずにひとつのクラスで解析しようとしていたところ頻発して、メンバ宣言の位置変えをしてみてもうまくいきませんでした。


で、実際に解析をしたいメンバを連ねるだけではダメで。
companionに書かれている専用解析変数&メソッドが鍵となります。
解析したいクラスの情報を渡して、そこではどんな感じにパースすんのと言うメソッドもimplementします。(書かなければ@FromJsonか@ToJson実装しないとこれ使えへんでと言われる)


リクエストをどうするか問題

今回リクエストに使うライブラリはOkHttp3にしてみました。触った事なかったから。
こいつはGETする時にはパラメータを変えたいなと思った時に、インスタンスがイミュータブルなもので、もうひとつ新たなものを用意しないと調整ができないと言うものでした。

Web触っていた時にはerbさんが非同期でリクエスト取ってきてくれていたものだけど、今回扱ってるものは小さなパソコン、Androidなので極力パフォーマンスも考慮して実装していきたい。

そこで画面回転があろうとインスタンスを死守してくれるViewModelさんの力を借りました。

プライベートアプリなのであらかじめ全てのデータを取得して、適当にページングして少しずつ見せる感じに。画像の表示はPicassoを使ったのでスマートにキャッシュを持ってくれて、表示もサクサクです。



諸事情でデモやコードは上げてないですが、許可が取れたら上げてみます。
今回の反省点はと言うと、なんだかんだと困ったらすぐに検索してしまい、ライブラリのソースコードをきちんと読むことを疎かにしていたって事です。ライブラリもコードなの、ああそういえば昔参加してる勉強会でひたすらコードリーディングしてる人いたけど、あれが正なのかなあ…




(イケてる開発者のトレンドはまだまだ理解できないよ…)

基本情報技術者を受けてきた

お疲れさまです。今年の本命枠とも言える資格試験を受けてきましたが、惨敗の結果に終わりました。。

理由は明白で、午後試験の対策をぬかっていたところだと思います。
基本情報技術者(以下基本情報)は午前と午後科目に分かれており、両方の試験で6割以上を期待され、それを超えることによって初めて合格となります。

本年の講評的に、万遍なく計算問題などは出題されていたものの、ハードウェアやトリッキーな問題は出ず(回路もすごく無難なものが出た)、他年度に比べて平易だったと言います。。
自己採点では午前は6割を超える事が出来ましたが、午後は50%程度しか得点できず、悔しい結果となりました。

午後試験問題の反省点

ソフトウェア設計(WebAPI)、アルゴリズムでの大コケ

一番痛かったのは、認めたくはないですがWebAPIでの大コケです。

DB, WebAPIの仕様が羅列されており、これを要約した内容に解答したり、
機能実装の例に解答するような問題です。
絵を描いて関連を把握したのは悪くなかったとは思うのですが、実際に動作するところまでを冷静に想像する必要があったと思います。ただ前提の内容を真に受けるようではダメ…

1番最初の問題はとっても基本的な問いです。
認証関連WebAPIと、登録ツールからアクセスできる。よって、申し込みDBに格納されている情報は_________である。


ここは申込者IDと解答しましたが、正解は申込者情報と検査農産物情報なのでした。(5)検査管理システムに登録された検査結果を確認して、申込者に検査結果を報告する とあるので、検査農産物テーブルは中間テーブルの役割をしていたと考えられます。

申込者←→検査農産物←→検査結果情報

こんな感じで参照することができた。


アルゴリズムについては正直テンパりながら問題を読んでいたので、お絵かきと表が全然合わなくてさらにテンパっていた

後半に進むにつれて時間が全然足りなくて、焦りが次第に諦念に変わった感じだったな…

解答の順番はこんな感じでした。
(プログラミング)Java→情報セキュリティ→DB→ネットワーク→ソフトウェア→プロジェクトマネジメント→アルゴリズム


午後問題のよかった点

データベースとマネジメントはしっかりと得点できていた

といっても上記以外の基本的な問題の得点はしっかり得られていたと思います。
業務でも触った事があったLIKEや前提に解答が書いてあるものは簡単に感じました。(ギリギリで=でワイルドカードが使えるのかを迷ってしまったのは内緒。)
主キー=UNIQUEやろ!!みたいな思い込みが失点の原因となってしまいました。

マネジメントは計算もピッタリと合っていて、利用部門から仕様変更の依頼などは業務内でもよくある光景なので
「あーうちもこんな感じでふるいがいればいいのにな…」と感想が出るくらいには問題と向き合う余裕がありました。

午前は?

午前については再帰的呼び出し、dpiの計算、ホストアドレスの個数などを落としてしまったのが悔しかった。機械学習関連の問題だったり、メル●リ的なプロダクトについて問題が出たのは今時だったな。
HEMSについてはニュースで見たから解答できた。

個人的総評・令和第1回目に向けて

時間に追われて得点を落としてしまったので、この先に必要なのは特に問題の読み込みに対する慣れと、アルゴリズム問題に対するアレルギーをなくすことだと思ってます。

午前の計算問題に対しても理解を伴って解答できればさらに得点できるかも。
とはいえ、次回の難度は上がりそうなので覚悟を決めてもう一度学習に取り掛かろうと思います。アルゴリズムは本当に対策しないと大変だぞー…


ちな勉強法

・参考書、過去問1冊
道場

Nuxtの環境構築をDockerでサクッと実現する

時間がない人の為のDockerfile

FROM node:10-alpine

RUN apk add git emacs

RUN npm install -g vue-cli
WORKDIR /app
ENV HOST 0.0.0.0
EXPOSE 3000
version: '3'
services:
  app:
    build: .
    tty: true
    volumes:
      - "./../app:/app"
    ports:
      - "3000:3000"



足りないものは自分で継ぎ足してね(・ω・`) 要らないもの然り。
brewなど入れてあるのでgitでpushやら最低限のことはできるはず
今回はベンチマーク取ってないけど、 体感的にAlphineを使ったほうが適当なイメージをpullしたり、拾ったDockerfileを使うよりもファンが昂ぶらなくて良いと思った。 OSって色々詰まってるんだね。
npm触り出すとすぐ依存性とか詰まるから、今の所は助かってる。。

docker-compose build

docker-compose up

docker ps (idチェック)

docker exec -it (container_id) sh brew入れ方はLinux Brewのページを参照する

uname -a (動いているサーバのお名前頂戴) Linux e8aa47ead274 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 Linux
appプロジェクト配下で npm i --save npm run dev




うわあああああん!!(別案件)

f:id:letterneginr:20190408100348p:plain
docker内でvueのエラーする図

ご参考 https://github.com/Linuxbrew/brew/wiki/Alpine-Linux https://techblog.zozo.com/entry/docker_image_slim_in_alpinelinux https://qiita.com/tukiyo3/items/247f853c81bf00e82c11