未来の社会人エンジニアに送る、知っておきたい色々なこと。

# はじめに
この記事は[アイスタイル Advent Calendar](http://qiita.com/advent-calendar/2016/istyle) 22日目の記事になります。  

今回はポエムっぽい何かを書こうと思いますエンジニアらしくなくてごめんなさい一応技術的なことも書きますごめんなさい。
僕は社会人始めてまだ５本の指にすっぽり余裕で収まるぐらいのぺーぺーなのですが、
社会人エンジニアになってから知っておけばよかったぁ、苦労したなぁって思うことを、少しでも未来とポテンシャルのある方々の力にしてもらえればと思いつつ、書いていきます。

# 知っておきたいこと
## 人間編  
### 何をやりたいのか、何に熱があるのか、真剣に考える。
別に体育会系になれ、という訳ではありませんw
ただタイトルの通り、
**何をやりたいのか、何に熱があるのか** を明確にこれだ！と言えるぐらいになるとよいでしょう。
ぼんやりとした未来像しかないと、色々苦労します！w
あと、どんな生活をしたいのか具体的に描くといいかもしれませんね
その具体像は後でアップデートできるものとして、今いったん決めておくと就活戦略も、その後の仕事人生でもどうしていこうかと前向きに計画を立てられるようになるかも。

何より、それが自分の **アイデンティティ** になって自信につながります。

何でもいいです。自分のテーマを見つけるだけでいいです。
例えば僕は「音楽 × IT × 楽しい」というのを自分なりに掲げています。
そのテーマに沿って生活水準やモデルを練り上げていきます。

形式知化すると尚いいと思います。積極的にやってみてくださいｗ

### 謙虚と卑屈、自信と慢心について
僕は色々不器用なので、謙虚が行き過ぎて卑屈になったり、
自信が行き過ぎて慢心になることがよーくありました。（過去形でいいのか
で、これが癖になると、 **今更自分がやったところで、大したことない** 
と考えて、インプットもアウトプットもしなくなります。
慢心に気付いて卑屈になって、立ち直ってまた慢心になって、、、まぁ僕だけかもしれませんがｗ
謙虚と卑屈、自信と慢心についてはよーく考えて、自分なりに知っておくと良いかもしれません。

**今更だけど自分やったら、そこそこ変わるじゃん！** と思えるようになるのがベストかもしれません。


## 技術編
### 単体テストや振る舞いテスト
僕はJava民です。にも関わらず、テストが苦手です。難しいです。
なので学生や独学中にぜひ、JUnitやNUnitなどの言語でデファクトスタンダードなテストツールを使ったテストを覚えてみてください。
今はIDEにそのままテストツールがバンドルされて有効化されてるものが多くあると思います。

で、正常系と異常系のテストを書きつつ、テスト網羅率を７，８割目指す、みたいな目標を立ててやると、
その知見が後々役立ちます。

あと、同様に振る舞いテストについても知っておくと良いです。
より自然言語に近い記述でテストをかけたりするフレームワークもあるので、調べてみると面白いかもです。

学校でテストについてのカリキュラムがある方は、ぜひ積極的に受けてみてほしいです。

### デザインパターン
Singletonだけしか知りません、は辛いです（血涙  
僕は [Java言語で学ぶ デザインパターン入門](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030) を今になって読んでます。
ライブラリの選定や学習、ソースリーディングなどにも役立ってます。
ただ、本読んで、なるほどこういうのが良いのかと思ってお仕事で愚直に使って爆死したアカウントがこちらになります
使い所が本当に難しいです。愚直に使うと、余計なソースが増えるだけになったりします。明瞭かつ確固たる目的の時に使うと思いますが、数年の社会人経験で上手く取り入れられた経験はまだないです。
プライベートだったら良いと思いますが、お仕事で下手の横好きにならぬよう。。

### リーダブルコード
本読むのが超苦手な僕でも唯一読破した本です。
これだけは頑張りました。
社会人になったら、完全に１人でお仕事するわけでもないし、
人間なので、あとで保守改修するってなった時に、なんじゃこりゃあああなソースがあると、
やる気も効率も下がって、時間と労力だけが浪費されていきます。つらい
今でもなんじゃこりゃー作ってる時あるので、知らなかったらもっとひどかったのかな・・・w

リーダブルコードと書いていますが、
これを読んで僕は、エンジニアにも人への優しさが大事だなって思いました。ほんとに
あと巡り巡って自分にも恩恵を授かることができます。
今回は具体的な考察などは書きませんが、ぜひ寝ながらでも、動画見ながらでもいいので、読破してみてほしいです。

[リーダブルコード](https://www.amazon.co.jp/%E3%83%AA%E3%83%BC%E3%83%80%E3%83%96%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89-%E2%80%95%E3%82%88%E3%82%8A%E8%89%AF%E3%81%84%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AE%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%A7%E5%AE%9F%E8%B7%B5%E7%9A%84%E3%81%AA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-Theory-practice-Boswell/dp/4873115655)

### Webサイトが動く仕組みや通信の仕組みを知る
いわゆる`OSI参照モデル`についてですね。
特に`TCP/IP`, `HTTP/HTTPS/HTTP2`あたりは知れば知るほど良いと思ってます。
Webの静的コンテンツや動的コンテンツがどういう流れ・仕組みを知っておくと、アプリやWebサービスを作るうえで、非常に役立ちます。
というより、「APIを叩く」にあたって必要になる知識です。

あと、`REST`の考え方についても知っておくと良いです。APIを設計するときに必要になる考え方だと思ってます。
僕もしっかり覚えたい！！

# 苦労したこと
## 人間編
### 社会人と仕事
僕はすでに一度転職を経験している身なので、前職のことについてお話しします。
新卒として入った会社さんでは、営業部門に配属されました。（一応技術部、的な部署名ではありましたが）
エンジニア職で入ったつもりだったので、営業に回った時はすごい衝撃でした。
今まで勉強してきたことがほとんど役に立たないのはもちろん、
何度やっても見積書や請求書一つも正確に作れなかったり、営業するために必要な商品知識も覚えが悪くて、何日何か月とかかってしまって上司や先方に迷惑をかけてしまったりして、
自分は **圧倒的な無力感** に襲われていました。
等身大のなーんにもできない自分を突き付けられましたね。。

その後、どうしてもアプリ作りたくて、技術職に転向して今がありますが、
とても貴重な経験だったなと、今振り返れば思います。

会社がどう回っているのか、数字はどう上がっていくのか、その流れを実務として肌身で経験できたのは、
様々な利益を追求する **仕事** としての意識がついてよかったです。
エンジニアは数字よりもより質量が求められる開発をこなして、作ったもので利益を得る、というのが筋だと思います。
が、どう回っているのか、数字があがっていくのかを理解すると、どうしたらユーザーにとっても、メーカーにとっても本質的にWIN-WINになれるだろうか、とほぼ常に自問自答できるようになるなと個人的には思ってます。ほぼ常に。

**他業種を経験しておく** と、**会社全体の視点** で、より **根本的なユーザーの視点** で、プロダクトをグロースしていけるんじゃないかなって思ったりしてますｗ

※あくまで僕の個人的な考えです。

### コミュニケーション
これはエンジニアとして、というよりは個性の問題になりますか。
いわゆる **コミュ力** というのが問われて来ます。
やっぱり話したことない人と仕事するより、よく話す人と仕事したいですもんね。ああ痛感 

コミュニケーションが得意なことに越したことは無いと思いますが、
僕は超苦手です。特に自分から話そうとすると頭真っ白になってしどろもどろによくなります。
あと **話題が出てこない** という点。これが一番つらい。

例えば上長の方と数分歩いて話すシチュエーションを考えてみます。
僕は話題が振られたら割と答えられるので、その点ではいいんですが、
**一方向のコミュケーション** によくなります。
一方で自分から話そうとすると、どの話題を振ればいいのか想像もできなくなってしまうんですね。

なので、僕は **話をかいつまんで質問する** ようにしています。
そうすれば、分からなくても話が続けられるので、初動は相手からかもしれませんが、
全く続かない状態より幾分、コミュニケーションが取れるんじゃないかなと考えています。

それを続けると、そのうち自分から話しかけることもできるんじゃないかなと。
今は割と楽観しています。

## 技術編
### DIとかインタフェースを使った疎結合プログラミング（とテスト）
依存と結合度の話です。  
最近は、疎結合でありたい、関係性を薄くしておきたいオブジェクトを外部から注入する
**Dependency Injection** というのが主流になっていたりします。
そこらへんを全く知らずに、愚直に具体的な関係性をそのまま表現する、
もっと言えば何でもかんでもnewするのは、特に **テストするときに苦しく** なります。
また、プロダクト全体の運用（改修など特に！！）や品質にも関わってきます。

DIなどを知らずに開発してきて、ぶち当たった時は結構苦労しました＾＾；

苦労したくなければ、 **凝集度と結合度** についてはしっかり覚えておきましょう（血涙
僕もしっかり覚えていきます。。！  

### アプリケーションの設計について
これに関しては、正直今一番苦労してます。
まず、 **ドメイン駆動設計** という大きな壁にぶち当たりました。
とにかく業務領域をコンテキスト（文脈）として明確に分離させましょうね、という設計思想（だと思っている）なんですが、うん、難しい。

それと、おそらくこれから、より **TDDの重要性が再認識** され始めると思います。
テスト駆動開発と呼ばれるものですね。  

で。 進行形で悩んでいるのが、 **「粒度の大きいタスクをどう設計していくか」** です。

今までは、「粒度の大きいタスク」を言われた通り動かすために「実装・コーディング」していました。
ただそれだと、気づいたら二郎系ラーメンのごとき大型Pull Requestが量産されては、御レビュアーに多大な御負担をかけてしまっていました。

例えば、「ユーザーを指定した任意の友達リストに追加する」というタスクを考えたとき

```java
package jp.co.fugaservice.domain;

class User {
    // ユーザーのなんたるかが表現されている
}

```

```java
package jp.co.fugaservice.dataaccess;

import jp.co.fugaservice.domain.User;

class UserClient {
    public void addUserToMyFriendList(User user, String dest) {
        // ユーザーを指定された友達リストに追加するAPI叩くみたいな実装
        User myself = User.getCurrentUser(); //　など行う。。
    }
}
```

というような実装を今までしてしまっていたんですね。
**「とにかく言われた通りに動く実装」**。 これが **よくない**。ごり押し実装とはこのこと。

これだと、外部から利用する際に柔軟性に欠けますし、メソッド単位の責任としては重すぎます。
また、ドメインの一部を知る必要が出てきて、密な結合になってしまってます。
これは保守性にも響いてくるので、もはや技術的負債です。猛省（血涙
特にdataaccess層は、サーバー側の機能単位もとい用意されたAPIに即した粒度の細かい設計にすることができるはずです。

そこで今は、「階層別に **機能を設計して、階層別の機能の組み合わせ** 」で、
「粒度の大きいタスク」を動かす実装、ということに挑戦しています。（まだまだ上手くないですがorz）
そして、機能を設計して実装したらレビューに出す、と細かく進捗を出すようにしようと思ってます。

## さいごに
色々書きましたが、僕はまだまだド三流エンジニアですし、若造です。
ただ僕よりもポテンシャルと未来あるルーキーには、下手くそなエンジニアの屍を超えて、大きく輝きながら良きサービスを企画して開発、提供していってどんどん楽しくなっていってほしいなって思います！

・・・と言いつつも、言ってて悔しいので、僕もがんばりますけども！！！
と、少しでもお役に立てられたらなと思います。

それでは、良きエンジニアライフを！


次は 23日目 @imaiy さんの記事です。お楽しみに！！