ベビーサンになりたい

勉強したことと思ったこととか

オブジェクト指向学び直し

software design2021年3月号を読んで

手続き型プログラミングは小さなものをシンプルに記述するときに向き、 オブジェクト指向プログラミングはより大きく複雑なものを分割して記述するときに向く

よくオブジェクト指向は大規模開発で使われる、って言われるけど、 初学者は大規模開発ってなんとなくわかるけどなんでそれを使うと嬉しいのかがちゃんとわからないと思うんだよな。 実際に現場でて、大規模システムに触れると「ああこうしてるから調査しやすいな」とか「なんでこれ密結合してんのよ」とか色々考えられるようになった。 まあ実際に開発してる時にコスト考慮した上で妥協することもあるんだけど・・・ 凡人以下の自分には机上の勉強だけじゃ全然足りなくて、現場で実物に触れてやっとわかるようになったな、って思う。

カプセル化はデータとロジックを1つのクラスにまとめる考え方

「getter/setterを作ってデータを不本意に編集されないようにする」みたいなのがカプセル化です、っていう認識だったからちょっとびっくり。忘れてくださいとまで書いてあって草。でも今なら納得。

StringクラスとLocalDateクラスを例にあげて説明してくれてた。 このクラス設計を真似するといいよ、って。カプセル化の超いい見本がこんな身近にあったとは。

手続き型のクラス設計は、データクラスと処理クラスを分ける方法なんだけど、今のPJこれなんだよな。 でも扱うデータ種類ごとにパッケージ分けてコンポーネントクラス作ってるからこれもこれで理にかなっているのか? システムの数だけ設計が存在する、を心に。

凝集度って他の本でもみたけど、凝集度の高いクラスを作るのはオブジェクト思考の基本。 いろんなデータ型を扱う登録系の処理をまとめるクラス作るより、特定のデータのみを扱うCRUD処理をまとめたクラス作った方がいいよ、ってことだよな。

オブジェクト指向ではイミュータブルな設計が主流。イミュータブルは、不変の意。 オブジェクトを生成した後に、その中身の値は変えないような設計にすると、処理が安定するらしい。 中身の値が変わらないから、意図しない動きしないからバグ減るので。 今のPJ余裕でミュータブルな設計だな。 本では「最近はイミュータブルな設計が主流」って書いてあったから、そりゃそうか。 でもちょいちょいイミュータブルしてる(?)処理みたことあるんだよな。

2021年の目標と今後の展望

まずは。

2020年のふりかえり

簡単にしたい。。。

現場

1~3月は、前の現場で心がダメになってしまって、2月下旬から待機になった。
自社の人の言うことってのもあるけど、リーダーとかメンバーとか雰囲気みたいなのの相性ってあるらしい。
参画初期は良かったんだけど、3ヶ月くらい経っても自分がいろいろできなすぎてギクシャクしてた。し、自分が全てに萎縮してなんかおかしかったと思う。
個人的には、割とどんな人ともうまくうやれる体質だからこれがキツかった。
あと今まで何があってもなんとか乗り越えられてきたから、これが人生初めての挫折だな。
でもそこで学んだことは、今めちゃめちゃ役立っているので前現場の方には大変申し訳ない&怖かった&感謝の気持ちでいっぱい。
待機中は春の研修の途中だった、jsp + Servlet で作ったECサイトをSpringFWにリプレイスするのをやった。
そしてAWSベースでインフラを勉強して、さっきのアプリをAWSのElastic Beanstalk っていう便利デプロイサービスにのせるのをやった。
わからないことたくさんだったけどできた。ちょっと自信がついた。

長くなってしまった。
4月からは、今の現場で要件定義からテスト、リリース後の稼働確認までやらせてもらえている。
要件定義といってもごく一部の作業で、顧客折衝をするわけではなくて要件を実現するための調査とかまとめ資料作るとかなんだよな。
大小様々な案件がパラで走っている現場なので結構楽しいのだ。
なんかかなりいい評価をもらっていて逆にこわいくらい。
まあ他の若手見るとなんか様子おかしい人とかできることが少ないいわゆるIT事務員みたいなのがいるから、相対的にワシが良く見えるんだろうな。

現場以外

  • javaSilverの勉強をはじめた。
    10月くらいからだらだらやっているのだが、まだ正答率半分、、、
    自分なりに根拠持って回答できるんだけど、足りないんだよぁ。

  • Web技術の基本的な本をいくつか読んだ。
    去年よりグッと読みやすくて(理解できるレベルになった)ちょっと感動した。

  • 自分は技術が好きではないかもしれない。
    SEって技術好きじゃないとやっていけないんだろうけど、好きじゃないんだよな、多分。受け入れたくない自分もいるから、まだ「かも」。
    じゃあなんでこの仕事してんの、っていうと「システムで働く人を幸せにしたいから」なのだ。
    綺麗事ぽいけど、仕事始める前も、今もこれは変わらないなぁ。
    あでも仕事自体は普通に楽しくやっている。

2021年の目標

確実にできそうなのだけ。
さっき書いた通り、自分は技術が好きではないかもしれない自覚があるけど、今はまだ足場固めないとだから技術系の目標ばかり。

  • javaSilver取得
    • 3月中までにとる
  • 設計の勉強する
    • 有名な本2つくらい読む
  • GASでなんか作る
    • 全然思いつかないけど

今後の展望(24歳冬)

現場でもっと頼られるようになりたいな。業務知識はダントツで低いけど、調査しまくってるから着実についてきているはず。
今の現場では、商流的に作業しかできない(?)というか教育には関われないので、
次の現場では教育にも関わりたいな。。。
2021年いっぱいは今の現場いれるかな。だとしたら2022年かな。26歳。
あとは前も書いた気がするけど、PGとしてごりごり開発やりたい〜とか思う。(個人開発すればいいとかそういう問題ではなく。)

2020年11月の仕事のこと

すっごく久しぶりになってしまった。

最近グルグル頭の中で回ってるだけのことを言語化して、頭の中をすっきりさせる。

...

今の現場に来て半年以上経った。

前の現場でボロボロだったので何もかも自信がなくなっていた。
でも今の現場は、改善点が無いくらいにすごく良い評価をもらえて、めちゃびっくりした。記念カキコ。イエーイ。

なんでこんなに変わったのだろうって考えたけど

・現場が求めるスキルが低くなった
・自分のスキルが高くなった

んだと思う。

結果ちょうど良く落ち着いているんだなぁ、と。

でも今の現場は保守案件なんだけど、上から下までやらせてもらえているからかなりSE力がついてきていると思う。
SE力というか具体的には、「情報を資料にまとめる力」「根拠をもとに判断や提案をする力」とか。
あと前の現場では全然できなかったんだけど、期限を守れるようになった。
以前の自分がゴミすぎたってのもあるけど、これは本当に成長したと思う。
なんでできるようになったんだろ。
多分、SEとしての頭の基礎ができてきた?
なんか上司の言っていることがわかるんだよねえ。
「これやって」って言われたら、成果物がだいたい浮かぶし、それを作る過程がだいたい見当つくようになった。
これみんな当たり前なのかもしれないけど、自分にとってはかなり成長。

でもまだパッとわかんないことあるし、迷子になりかけることもある。
それでも自力で解決できること増えた。

あーでも業務知識が圧倒的に足りないな。
けど、これはリーダーも言ってたけど慣れなんだよなあ。

.

でもね、今の現場にずっといたら絶対に成長止まる気しかせんのよな。
あんまりコード書けないし、新規の設計とかできないから。
いや、今は今で「既存の仕様を元にベストな選択をして改善をする」っていう貴重な経験ができるので良いんだけど。
無い物ねだりなのかもしれないけど、次の現場は大規模とかのPGをやってみたいんだよなあ。半年で良いから。
とりあえず一つの責務を果たす系のをやってみたい。
ま、その前に勉強中のjava silverを取らないとな。

とか言いつつ最近「エンジニア向いてない…」って思うことも多いんだけど。
とりあえず明日も頑張ろうーーー

jsonデータの取得方法〜asXxxxとxxxxValueのちがい

jsonの値を取得する処理を調べながら書いてたら、asTextとtextValueが混在してて違いが気になったのでメモ。
リファレンスを読みながら、文字列・数値・ブール値を取得&出力するコードで結果を確認していく。

jacksonのバージョンは2.9。
リファレンスはこれ↓
JsonNode (jackson-databind 2.9.0 API)

以下の実験用jsonデータを読み取る

// sample.json
{
    "string": {
        "name": "apple",
        "price": "200",
        "isStock": "true"
    },
    "int": {
        "name": 100,
        "price": 300,
        "isStock": 0
    },
    "boolean": {
        "name": true,
        "price": true,
        "isStock": false
    },
    "null": {
        "name": null,
        "price": null,
        "isStock": null
    }
}

asText()

Method that will return a valid String representation of the container value, if the node is a value node (method isValueNode() returns true), otherwise empty String.

これは「値を参照する場合、コンテナ値の有効な文字列表現を返して、それ以外(=キー)を取得する時は空文字を返す」らしい。
コンテナ値ってなんだろって思ったけど、バシッとくる答え見つからなかった。
javaUtilクラスにある型っていうのかな。よくいう"普通の型"なら文字列に読み替えてくれるぽいな。
nullの時でもぬるぽにならないから、気づかずに画面にnullって表示されて初めて気づくのとか悔しいから気をつけないと。

// asText
String string_name_asText = root.get("string").get("name").asText();  //"apple"
System.out.println(string_name_asText); //apple

String int_name_asText = root.get("int").get("name").asText();    //100
System.out.println(int_name_asText);    //100

String boolean_name_asText = root.get("boolean").get("name").asText();    //true
System.out.println(boolean_name_asText);    //true

String null_name_asText = root.get("null").get("name").asText();  //null
System.out.println(null_name_asText);   //null

//キーを取得する時
String reading_key_asText = root.get("string").asText(); //"string": { "name": "apple", "price": "200", "isStock": "true" }
System.out.println(reading_key_asText); //"" (空文字)

textValue

Method to use for accessing String values. Does NOT do any conversions for non-String value nodes; for non-String values (ones for which isTextual() returns false) null will be returned. For String values, null is never returned (but empty Strings may be)

これは文字列以外が入ってたらnullが返される。
最後の文曰く、nullじゃなくて空文字が返されることもあるのか?これは謎だ。。。
これはキーを取得するとnullが返る。

//textValue
String string_name_textValue = root.get("string").get("name").textValue();    //"apple"
System.out.println(string_name_textValue);  //apple

String int_name_textValue = root.get("int").get("name").textValue();  //100
System.out.println(int_name_textValue); //null

String boolean_name_textValue = root.get("boolean").get("name").textValue();  //true
System.out.println(boolean_name_textValue); //null

String null_name_textValue = root.get("null").get("name").textValue();    //null
System.out.println(null_name_textValue);    //null

//キーを取得する時
String reading_key_textValue = root.get("string").textValue();   //"string": { "name": "apple", "price": "200", "isStock": "true" }
System.out.println(reading_key_textValue);  //null

asInt

Method that will try to convert value of this node to a Java int. Numbers are coerced using default Java rules; booleans convert to 0 (false) and 1 (true), and Strings are parsed using default Java language integer parsing rules. If representation cannot be converted to an int (including structured types like Objects and Arrays), default value of 0 will be returned; no exceptions are thrown.

文字列の値を取得する場合、数値に変換できたらその数を、変換できない時は0を返す。
どうやらブール値は0(false)と1(true)に変換されるらしい。

//asInt
int string_price_asInt = root.get("string").get("price").asInt();    //"200"
System.out.println(string_price_asInt); //200

int string_name_asInt = root.get("string").get("name").asInt();  //"apple"
System.out.println(string_name_asInt);  //0

int int_price_asInt = root.get("int").get("price").asInt();  //100
System.out.println(int_price_asInt);    //100

int boolean_price_asInt = root.get("boolean").get("price").asInt();  //true
System.out.println(boolean_price_asInt);    //1

int null_price_asInt = root.get("null").get("price").asInt();    //null
System.out.println(null_price_asInt);   //0

intValue

Returns integer value for this node, if and only if this node is numeric (isNumber() returns true). For other types returns 0. For floating-point numbers, value is truncated using default Java coercion, similar to how cast from double to int operates.

これは数値でない場合は0を返す。bool値も変換してくれない。
double型の時は、intにキャストする時と同じように切り捨てて返す。

//intValue
int string_price_intValue = root.get("string").get("price").intValue();  //"200"
System.out.println(string_price_intValue);  //0

int int_price_intValue = root.get("int").get("price").intValue();    //300
System.out.println(int_price_intValue); //300

int boolean_price_intValue = root.get("boolean").get("price").intValue();    //true
System.out.println(boolean_price_intValue); //0

int null_price_intValue = root.get("null").get("price").intValue();  //null
System.out.println(null_price_intValue);    //0

asBoolean

Method that will try to convert value of this node to a Java boolean. JSON booleans map naturally; integer numbers other than 0 map to true, and 0 maps to false and Strings 'true' and 'false' map to corresponding values. If representation cannot be converted to a boolean value (including structured types like Objects and Arrays), default value of false will be returned; no exceptions are thrown.

これもasStringやasIntと同じように、trueまたはfalseに変換できるなら型が違くても変換してくれる。
asBooleanでは、
文字列の場合、"true"or"false"なら自動変換でそれ以外の文字列はfalse、数値なら0はfalse、整数はtrueへ自動変換してくれる。

//asBoolean
boolean string_isStock_asBoolean = root.get("string").get("isStock").asBoolean();    //"true"
System.out.println(string_isStock_asBoolean);   //true

boolean int_isStock_asBoolean = root.get("int").get("isStock").asBoolean();  //0
System.out.println(int_isStock_asBoolean);  //false

boolean int_price_asBoolean = root.get("int").get("price").asBoolean();  //300
System.out.println(int_price_asBoolean);    //true

boolean boolean_isStock_asBoolean = root.get("boolean").get("isStock").asBoolean();  //false
System.out.println(boolean_isStock_asBoolean);  //false

boolean null_isStock_asBoolean = root.get("null").get("isStock").asBoolean();    //null
System.out.println(null_isStock_asBoolean); //false

booleanValue

Method to use for accessing JSON boolean values (value literals 'true' and 'false'). For other types, always returns false.

ここまできたら予想通りだが、boolean型以外の値はfalseを返す。

//booleanValue
boolean string_isStock_booleanValue = root.get("string").get("isStock").booleanValue();  //"true"
System.out.println(string_isStock_booleanValue);    //false

boolean int_isStock_booleanValue = root.get("int").get("isStock").booleanValue();    //0
System.out.println(int_isStock_booleanValue);   //false

boolean boolean_isStock_booleanValue = root.get("boolean").get("isStock").booleanValue();    //false
System.out.println(boolean_isStock_booleanValue);   //false

boolean null_isStock_booleanValue = root.get("null").get("isStock").booleanValue();  //null
System.out.println(null_isStock_booleanValue);  //false

おまけ asXxxx(defaultValue)

asXxxx()をオーバーロードするメソッドもある。 これは値がnullの時に、引数に指定したdefaultValueが返る。
これ使えばnullチェックしなくて済むから便利、、、
ちょっとだけ例

//asText(defalutValue)
String string_name_asText_defalut = root.get("string").get("name").asText("secret!");  //"apple"
System.out.println(string_name_asText_defalut); //apple

String null_name_asText_defalut = root.get("null").get("name").asText("secret!");  //null
System.out.println(null_name_asText_defalut);   //secret!

おわりに

シンプルだけどひとつずつ調べると、使い勝手が良くなるようによーく考えてAPI作ってくれてるんだな〜って思った。

「悩む」と「考える」は全然違うんだって

最近、友人がインフラ関係のスクールに通い始めたらしい。

それで、インフラはじめましての章というか、本当の最初の段階でどうしてもエラーが解決できず、私に助けを求めてきた。

友人は「なんでできないんだろう……」ばかり言ってて完全に悩んでるモードだった。

自分自身もそうだったのだけど、 「考えるのではなく悩みがち」
だな〜と思った。

「考える」と「悩む」 の違い

これは前の現場で先輩に言われたことなんだけど、「考える」と「悩む」は違うってことを知った。

goo辞書の一番上の意味はそれぞれ以下。
考える … 知識や経験などに基づいて、筋道を立てて頭を働かせる。
悩む … 決めかねたり解決の方法が見いだせなかったりして、心を痛める。思いわずらう。

https://dictionary.goo.ne.jp/

つまり「考える」は「ゴールに向かう方法を組み立てる」ことで、
悩む」は「ゴールに向かう方法が分からなくて悶々とする」ことなんだな。

悩むって完全に人間の感情に対する現象というかコトなんだな〜〜
仕事に持ち込むのよくないよね感情って。

悩んでたら先に進めない

仕事でも意識しなきゃだなと思うけど、何かについて考えている(と思っている)時は「悩んでいるだけかもしれない」と自分を客観視してみるの大事だな、って思った。
答えが出ない「悩み」に時間を使うなんて勿体無いもんね。

Yahoo!ショッピング商品検索(v3)APIで取得したjsonから利用したい情報だけ取得する方法

Yahoo!ショッピングAPIで商品検索して取得したデータの中から、利用したいデータだけ取得する方法のメモ。

前提

java 14.0.1
jackson 2.9.10
ショッピング:商品検索(v3) - Yahoo!デベロッパーネットワーク
↑は結構単純な内容なので、公式ドキュメントに苦手意識があっても理解しやすいと思います。

jsonデータを取得する

公式で紹介されている、以下のURLをリクエストURLに指定します。

https://shopping.yahooapis.jp/ShoppingWebService/V3/itemSearch?appid=<あなたのアプリケーションID>&query=nike

すると、以下のようなデータが取得できます。
(正確には「結果を読み取ってJsonNodeに変換する処理」を実装する必要がありますが、実装方法については省略します)
また、正確なデータだと文字数多すぎて見にくいので一部省略しています。

{
    "totalResultsAvailable": 482351,
    "request": {
        "query": "nike"
    },
    "hits": [
        {
            "index": 1,
            "name": "Nike ナイキ ウィメンズ エアフォース 1 ",
            "description": "ナイキの顔であり、世界中で絶大な人気を誇るエアフォース1。",
            "url": "https://store.shopping.yahoo.co.jp/topcrept/nike240.html",
            "image": {
                "small": "https://item-shopping.c.yimg.jp/i/c/topcrept_nike240",
                "medium": "https://item-shopping.c.yimg.jp/i/g/topcrept_nike240"
            }
        },
        {
            "index": 2,
            "name": "ナイキ NIKE スニーカー Nike Air Force 1",
            "description": "海外輸入商品となりますので、外箱にキズやヘコみ等がある場合がございます。",
            "url": "https://store.shopping.yahoo.co.jp/topcrept/nike220.html",
            "image": {
                "small": "https://item-shopping.c.yimg.jp/i/c/topcrept_nike220",
                "medium": "https://item-shopping.c.yimg.jp/i/g/topcrept_nike220"
            }
        }
    ]
}

利用したい情報だけ取り出す

JsonNode json = 読み取ったjsonデータ;

// 総検索ヒット件数を取得したい
int allHitCnt = json.get("totalResultsAvailable").asInt();

// 検索クエリを取得したい
String serchedQuery = json.get("request").get("query").asText();

// 検索結果1件目の名前を取得したい
String serchedQuery = json.get("hits").get(0).get.("name").asText();

// 検索結果2件目の画像(小)を取得したい
String serchedQuery = json.get("hits").get(1).get.("image").get("small").asText();

おわりに

jsonはただのデータフォーマットだから、他のAPIから取得したり自作のjsonデータを取得したりする時に応用できるな。
でもまだ課題があって、
jsonNodeオブジェクトのアクセサメソッドget,pash,withの違いと、 asTextとtextValueの違いを調べないと。

参考文献

https://blog.kymmt.com/entry/jackson

【VirtualBox】CentOS6で外部ネットワーク接続するためにインターフェース設定ファイルを修正する

VirtualBoxで外部ネットワークの接続を試みたがエラーになってしまったので、その解決策と解決するためにいじった設定ファイルについて調べた。

環境

VirtualBox 6.1
CentOS 6

前提

「VirsualBoxのブリッジ接続は不安定」という情報が多かったので、 NAT + ホストオンリーアダプター + ポートフォワーディング の組み合わせで接続設定をした。

以下を参考に進めた。ありがとうございます。
www.sps-katoh.com

疎通してみるが失敗する

# ping 10.0.2.2
connect: ネットワークに届きません

解決法

結論からいうと、
インターフェース設定ファイルで、ONBOOTというパラメータの設定値をyes(有効)へ修正する。
場所はetc/sysconfig/network-scripts/ifcfg-eth0
eth0は設定ファイルで制御するデバイス名のことなので、環境によって異なる

インターフェース設定ファイルとは

公式さんに詳しく書いてあった。

インターフェース設定ファイルは、個々のネットワークデバイスのソフトウェアインターフェースを制御します。

access.redhat.com

うーん……
まだまだ公式ドキュメントだけで理解できるアタマがないのでもう少し調べてみよう。

まず、ネットワークデバイスというのは、NICというネットワーク通信をするための機器を指す。
NICとは、ネットワークインターフェースカードの頭文字を取ったもの。
NIC」で画像検索するとわかるのだけど、有線でインターネット接続するときにLANケーブル挿すところから繋がってるPC内部の部品というか機器なのね。
ということは無線用のNICは、単純に無線で接続できるタイプの機器がPCに埋め込まれているのだな。

この物体、「NIC」という呼び名だけでなく、ネットワークインターフェースコントローラー、イーサネットカード、LANカード、ネットワークアダプター、ネットワークアダプターカードなどとも呼ばれるらしい。現場とかの環境によって呼び方だろうからなんとなく覚えておきたい。

本題に戻って…… インターフェース設定ファイルとは、このNICが起動する時の設定が書き込んであるファイルのこと。なんだな〜。

ONBOOTとは

ONBOOTについての公式の説明↓

ONBOOT=回答
回答 が以下のいずれかの場合です:
yes — このデバイスはブート時にアクティブにされる必要があります。
no — このデバイスはブート時にアクティブにされる必要はありません。

文中に出てくる「ブート時」は、「起動時」に読み替えると理解しやすいな。

つまるところ、ONBOOT=yesは、「起動時にNICを使える状態にする」ってことなのだ。

設定ファイルを編集する

# vi  ifcfg-eth0

ONBOOT=no

になってたので

ONBOOT=yes

に修正し保存。

そして疎通再チャレンジしたらできた〜!めでたし。

参考:

ネットワークインターフェイスカードとは-NICの定義、機能、種類 | FSコミュニティ