OmniAICreator/Qiita-1.07M huggingface dataset:
キーボードとマウスとコーヒーと

# キーボード

## Helixキーボード

![IMG_4615.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/50992844-16bd-e761-140b-62acddda3486.jpeg)

アクリル5行版キット(Undergrow)を2020年6月くらいに作成。昔過ぎてビルドログは残ってない。表面実装ダイオードのはんだ付けが細かい+多いで大変だった覚えはある。
1年ちょっと使っていたけれど、上の方の行まで指が届かなくて「4行で十分じゃない？」ってなって2021年の夏くらいに改造した。今となっては「3行で十分じゃない？」ってなってて、Corne Cherryとか気になってる。

キースイッチはKailhのロープロv1の茶軸と赤軸(と白軸)。混ざってるのは最初に購入したとき在庫がなくてしゃーなしで買ってそのまま。赤軸が外端1列で白軸がPro Microの下に各1個。それ以外は茶軸。次で紹介するThinkPad Wireless Keyboard with TrackPointのforce-travel diagramが茶軸(タクタイル軸)に近かったことから茶軸をメインにしてる。
リアルフォースとかHHKBとか(この辺は静電容量無接点だけど)Razerとか？、あの辺のキーボードのストロークの深さが苦手でロープロを選んだ。最近はああいうキーボードにありがちがキートップが狭いのが嫌いなのかなと思って、XDAプロファイルのキーキャップを試してみたいなとか思ってる。

TRRSケーブルも一応自作。組紐メーカーでちまちまガワを編んで作った。中の導線は普通の。
見栄張ってこんなとこから自作せずに、遊舎工房のケーブル自作キット買って作ったほうがきれいなのできそう。

キーマップはこんな感じ。左上からZ字でレイヤー0から3。
この記事のためにキーマップ見直して、CapsLockとかPrintScreenがあることに気づいた。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/c81276c3-58f0-810f-d23e-9ab7c0c3c94d.png)



## ThinkPad Wireless Keyboard with TrackPoint

![IMG_E4630.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/d58ad9a9-75e2-8e50-1457-e4045648dccb.jpeg)
名機。

マジでぶっちゃけると、TrackPointがめちゃくちゃ使いやすいとかはないんだけど(使用感としては、Macのトラックパッド>そこら辺のWindowsのトラックパッド=TrackPoint>>>>>Let's noteのトラックパッド)、なんだかんだ使える。色んな人が言ってるけど、ホームポジションで完結するのが楽かな。
最近はiPad用のキーボードとして役目を果たしてくれている。ちょーとばかし重いけど。

難点はファンクションロック周り。僕は文字変換でファンクションキー(というかF10)を多用するので、これが使えないキーボードは論外なんだけど、ThinkPad Wireless Keyboard with TrackPointは論外の方。なんたらかんたらというソフトを入れたら**Windows**ではファンクションロックできるみたいだけど、Macだと無理。
あとは、Bluetoothでしか繋げない上に同時接続台数が少ないのもちょっと困る。Bluetoothのビミョーな遅延が嫌いで、無線なら2.4GHzのやつのほうが好き。
新しい方はBluetoothと2.4GHzの2台同時接続ができるみたいだけど、切り替えスイッチが背面にしかないのが玉に瑕。クリックの背が低くなったのもあまり好きじゃない。ファンクションキーが4個区切りになったり、ファンクションロックがキーボード側でできるようになったってのはいいけど。

~~こんだけ難点あるのに名機ってホンマか？~~

# マウス

![IMG_4616.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/61137336-7de1-36b3-f819-cf3e2b901cb4.jpeg)

ロジクール ERGO M575。これまた完璧なトラックボール。

上位機種(？)のMX ERGOってのがあるけど、充電式(しかもMicroB！)ってのがダサい。入力機器は電池式がいい。充電時だけとは言え、せっかくの無線を邪魔したくない。

ケンジントンの大玉トラックボールと悩みはしたけど、実機を触って一番しっくり来たのはM575だった。Macで使うマウスに5ボタンは少ないかなって思ったけど、結構こと足りてる。
ボタンのカスタマイズはこんなん。中央クリックはいじってない。
![スクリーンショット 2021-11-23 2.01.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/488f814b-6745-342f-f54b-1aea3af69ede.png)
![スクリーンショット 2021-11-23 2.01.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/776b67a2-f173-32c4-01b5-b3c19a328236.png)

難点はビミョーにガタつくこと。電池ボックス周りにラバーソールがないせいだと思う。瞬間接着剤を適当に盛っていい感じの高さにしたら解決した。リセールバリューは落ちたけどね。

![IMG_4617.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/efdfd70b-a9c8-f33c-0f81-eb8fda57e711.jpeg)

# コーヒー

コーヒーは友人から誕生日にもらった丸山珈琲のドリップパックアソートを最近は飲んでる。
あとはチャイ。鍋で牛乳と茶葉とシナモンを一緒に煮込んで、最後に生姜を入れる。寒くなってきたし丁度いいね。コーヒーを豆挽くところから淹れるのより手間かかってるけど。

とは言え、普段は紅茶もコーヒーもボダムのでかいフレンチプレスに突っ込んで雑に飲むことが多い。
【Ruby】グローバル変数を使わずにメソッドの外のスコープにあるローカル変数を使う方法

## はじめに
メソッドの外にある変数を利用したいがために、グローバル変数を使っているコードを見かけた。
今回はこういったコードに対してグローバル変数を使わずに済む方法を考える。

## 題材となるコード
題材となるのは以下のコードだ。

```ruby
def test_Processor_runメソッドのタイムアウトの検証
  p = Processor.new

  # 重い処理にする
  $process_time = 5
  def p.process
    sleep $process_time
  end

  start_time = Time.now
  p.run(4) # 4秒でタイムアウトする
  end_time = Time.now

  # タイムアウトになるのは重い処理にかかる時間よりも早いはず
  assert((end_time - start_time) < $process_time)
end
```

`Processor#run`に指定したタイムアウトの時間で処理が終わるかどうかを確認しているようだ。

`Processor#run`からは`Processor#process`が呼ばれるため、そのメソッドを特異メソッドで再定義し、長時間の`sleep`を入れることで擬似的に重い処理を行うようにしているようだ。

`$process_time`というグローバル変数が使われており、今回はこのグローバル変数を使わないようにしたい。

## なぜグローバル変数を使っているのか
そもそもなぜグローバル変数を使っているのだろうか。
`$process_time`を`process_time`に変更してローカル変数にしてみよう。

```ruby
def test_Processor_runメソッドのタイムアウトの検証
  p = Processor.new

  # 重い処理にする
  process_time = 5 # グローバル変数をやめてローカル変数にした
  def p.process
    sleep process_time
  end

  start_time = Time.now
  p.run(4) # 4秒でタイムアウトする
  end_time = Time.now

  # タイムアウトになるのは重い処理にかかる時間よりも早いはず
  assert((end_time - start_time) < process_time)
end
```

これを実行すると以下のようなエラーが表示される。

```
undefined local variable or method `process_time' for #<Processor:0x0000000000a7b520> (NameError)
```

特異メソッド内で参照している`process_time`がメソッドとして解釈されてしまっている。
これはRubyでは`def`から`end`までの間がスコープと解釈され、そのスコープ外のローカル変数を参照できないからだ。

以下のようなサンプルコードで確認してみよう。

```ruby
my_var1 = "1"
def sample_method
  my_var2 = "2"
  local_variables
end

p local_variables
p sample_method
```

実行結果

```
[:my_var1]
[:my_var2]
```

`Kernel#local_variables`を呼び出すことで、現在のスコープで定義されているローカル変数を確認することができる。
実行結果を見てわかる通り、`sample_method`というメソッドのスコープではその外にある`my_var1`はローカル変数に存在しないことが分かる。


## グローバル変数を使わずにメソッドの外にあるローカル変数を使う
`def`を使ってしまうとそこからスコープが始まってしまうため、ローカル変数にアクセスできない。
こういう場合は`define_method`を使ってブロックを使ってメソッドを定義するようにする。（今回の場合は特異メソッドを定義するため、`define_singleton_method`を使う。）

```ruby
def test_Processorのrunメソッドのタイムアウトの検証
  p = Processor.new

  # 重い処理にする
  process_time = 5 # グローバル変数をやめてローカル変数にした
  p.define_singleton_method(:process) do
    sleep process_time
  end

  start_time = Time.now
  p.run(4) # 4秒でタイムアウトする
  end_time = Time.now

  # 重い処理にかかる時間よりも早く終わるはず
  assert((end_time - start_time) < process_time)
end
```

こうすることで、`process`メソッドを定義する際は`process_time`が定義されたスコープと同じスコープとなるため、ローカル変数のまま使用できる。

## まとめ
グローバル変数を使わずにメソッドの外のスコープにあるローカル変数を使う方法についてまとめた。

グローバル変数は無闇に使い出すと、どこで変更されているのか分からない保守性の低いコードができてしまうため、グローバル変数を使わない方法があるのであればそちらを採用してほしいと思う。

それではまた。
TomoProg

## 参考
- [メタプログラミング Ruby 第4章 ブロック](https://www.oreilly.co.jp/books/9784873117430/)
Pythonのテスト patch()関数のautospec指定でパッチ対象の関数/メソッドの仕様を保証する

Pythonでテストコードを書いていると, ときどきこんな問題に遭遇します.

* テスト対象の関数のなかで呼び出されている関数をパッチしてテストを成功させる
* 実はテスト対象の関数のなかでパッチした関数の呼び出し方が間違っていて, アプリケーションとして動かすまでそのことに気づけない

パッチするときに `unittest.mock` にある patch() 関数を使いますが, このとき autospec引数にTrueを渡しておくと, この問題を回避できそうなことに気づきました.


# 問題のコード

実際のコードで説明します.
はじめに実装コードを示します.

```python:app.py
def items_impl(type_):
    item_table = {
        "fruits": ["apple"],
        "meets": ["beef"],
    }
    return item_table.get(type_, [])


def items():
    return items_impl()

if __name__ == "__main__":
    print(items())
```

このアプリケーションは実行時エラーが発生します.
items() 関数のなかで items_impl()関数を呼び出していますが, ここで必要な引数 type_ が指定されていないためです.

> TypeError: items_impl() missing 1 required positional argument: 'type_'

次にテストコードを示します.

```python:test_app.py
import unittest
from unittest import mock
import app


class AppTest(unittest.TestCase):

    @mock.patch("app.items_impl", mock.MagicMock(return_value=["baseball"]))
    def test_items(self):
        self.assertListEqual(app.items(), ["baseball"])

if __name__ == "__main__":
    unittest.main()
```

このテストは成功します.
items_impl() 関数をMagicMockオブジェクトでパッチしているためです.

この程度のシンプルなコードでパッチが必要になることはありませんが, それぞれの関数で評価/テストしたいときや, items_impl() 関数が未実装であったりするときに, パッチしてテストする必要があるケースはそれなりにあります.

で, 実装コードの誤りを見落としました.


# patch() の autospec=True 指定で解決する

パッチするときに使う patch() 関数で autospec=Trueと引数を加えると, パッチした関数の仕様にあわない呼び出し方をすると, エラーにすることができます.

```python
@mock.patch("app.items_impl", autospec=True)
def test_items_2(self, mock_items_impl):
    mock_items_impl.return_value = ["baseball"]
    self.assertListEqual(app.items(), ["baseball"])
```

> TypeError: missing a required argument: 'type_'

(失敗/FAILEDではなくエラー. 実行時エラーなので)

次のように create_autospec() 関数と組み合わせることもできます.

```python
@mock.patch(
    "app.items_impl",
    mock.create_autospec(app.items_impl, return_value=["baseball"]),
)
def test_items_3(self):
    self.assertListEqual(app.items(), ["baseball"])
```

これで実装コードであげた問題をテストコードで検出できそうです.


# 参考

ドキュメントながめてて知りました.

https://docs.python.org/ja/3/library/unittest.mock.html#auto-speccing
WeAct STM32F411CEU6 Core Board で遊ぶ - Micropython編 追記あり

情報少ないですし，自分の過去記事と重複する内容もありますが...

# まずはファームを書き込み

https://qiita.com/numeru55/items/d90b4da142fc0fb58d75#micropython

# Macでの見え方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/cc7d3760-4f2b-f683-ccce-5ad379ae2b07.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/d5d2fb14-6c26-76ee-bc38-1948c15cbf34.png)

# Thonnyで操る

![無題の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/0f63b8a3-e2e3-da80-6f2b-21d697dd92c1.png)

# Board定義

pyboardに似ていますが，ピン名は本家STMに合わせてあるようです。以下が参考になります。

https://github.com/WeActStudio/WeActStudio.MiniSTM32F4x1/blob/master/General%20document/MicroPython%E9%83%A8%E5%88%86%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%20_WeAct%E5%B7%A5%E4%BD%9C%E5%AE%A4.pdf

# せっかくなので拙いサンプルを...

```main.py
# https://github.com/WeActTC/MiniSTM32F4x1
# https://micropython-docs-ja.readthedocs.io/ja/latest/pyboard/quickref.html

# GPIO demo includes LED drive

from pyb import Pin
C13 = Pin('PC13',Pin.OUT_PP,Pin.PULL_NONE)
print(C13) # print C13 definition
C13.low()
print(C13.value())

# Alternate LED access

pyb.delay(1000)
pyb.LED(1).off()

for i in range(11):
    pyb.delay(100)
    pyb.LED(1).toggle()

# [KEY] Access for WeAct Board

from pyb import Switch
sw=Switch()
sw.callback(lambda:pyb.LED(1).toggle())
```

`Switch`はチャタリング処理もしているようです。

# STM32 Bootloaderを起動する

```python
import machine
machine.bootloader() 
```

Bootloaderを起動して，他のfirmwareを書くとき用。

# SSD1306を使ってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/2f60856a-0978-2e8a-ab50-d7254505f50b.png)


```64_string.py
# SSD1306 128x64

# driver
# https://github.com/SuperThunder/STM32F411CEU6-BlackPill-MicroPython-Examples

# text 16(w)*8(h) letters  

from machine import I2C
import time
import ssd1306

i2c=I2C(1,freq=400000) # hardware I2C1 SCL-PB6, SDA-PB7
oled=ssd1306.SSD1306_I2C(128,64,i2c)

def printText(s,l):
    # s:string l:line 0-7
    oled.fill_rect(0,l*8,128,8,0)
    oled.text(s, 0, l*8)
    oled.show()

printText("Hello World!", 0)

time.sleep(2)
printText("Loooooong text", 2)

time.sleep(1)
printText("0123456789012345678901234567890123456789", 4)
printText("0         1         2         3", 5)

time.sleep(2)
printText("Speed text", 2)
printText("", 4)
printText("", 5)

time.sleep(1)
for i in range(100):
    printText("  count "+str(i),4)

printText(" Done.",6)
```

# 参考URL

https://elchika.com/article/3991eab6-dc97-486c-9b95-cbb0441ac743/

https://github.com/WeActTC/MiniSTM32F4x1/blob/master/General%20document/MicroPython%E9%83%A8%E5%88%86%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%20_WeAct%E5%B7%A5%E4%BD%9C%E5%AE%A4.pdf

以上です！
過去に自分のちょっと困ったを解決した話

過去に自分でちょっと困ったを解決した話。

勢いで「Advent Calendar 2021 身の回りの困りごとを楽しく解決！」に登録してしまった。
何を書こう・・・と思ったのですが、Qiitaに書いた過去の解決記事を紹介していこうと思います。

# その① micro:bit v2のケースがないからMI:pro保護ケースを加工してみたら・・・

記事は以下になります。

https://qiita.com/krohigewagma/items/17c4c388ccb65a1d16cb

これ、micro:bit v2が出たばかりでケースがまだ出ていなかったころ。
剥きだして置いておくのはちょっと心もとないと思って、v1用のケースを加工した話です。
タミヤのピンバイスで穴をあけ、ニッパーで切り取り、地道にやすり掛けをしました。
この加工ケースは今でも使っています。

まぁ、ケースが出るまで待てばいいだけの話なんですがｗ

# その② ELECOM TK-SLP01のファンクションキーがどうしても慣れなくてどうにかした話

記事は以下になります。

https://qiita.com/krohigewagma/items/6f14955a3e9185c483d4

別にELECOM TK-SLP01じゃなくても使えそうな気もしますが、ELECOM TK-SLP01しか試すものがないので・・・
ファンクションキーがFnキーと組み合わせないと使えない(Fn+F1みたいな)ことがすごくイライラしたので作ったツールです。
（ググっで出てきたコードをちょっと変えたりして作っただけですが・・・)
こんなツール作るよりも多分もっといいツールがありそうですが、会社でなにかツールを使う場合申請が必要で、選別する暇があったら自分で作って申請したほうが早いという作った理由の一つでもあります。

WindowsのHookを使っているので、似たようなことをしたい人には参考になるかもしれません。
最近はやらなくなりましたが、Windows APIを使ってごちゃごちゃやるのが好きな時がありました・・・

ちなみに、コロナで在宅になり、メカニカルキーボードを買ってしまったので、このツールを使う頻度が劇的に減ってしまいましたｗ


#その③ Ingress PrimeのAgent StatsのテキストをGoogleスプレッドシートで扱う

記事は以下になります。

https://qiita.com/krohigewagma/items/0bb6878b1503a7723522

これ、数回くらいしか使わなかったツールです。
Ingressのイベント、ファーストサタデーで集計係をよくやっていたんですが、Ingressがバージョンアップして、いままで画像でしか取れなかった実績情報をテキストで取得できるようになりました。
で、そのテキストで実績を登録してもらうGoogleフォームを作って、スプレッドに記録。
で、ワークシート関数で文字列を分割して集計するものです。

ちなみに、Ingressのイベントで得たGoogleスプレッドシートの知識は仕事でもプライベートでも役に立っているので、ゲームで学ぶことはまだまだあるかと思っています。

# 最後に
なんか、内容が薄くなってしまったかもしれませんが、誰かの何かの参考になれば幸いです。
Springにおける複数テーブルを結合したentityの書き方

## 

###  カスタムエンティティを作る
```:Java
@Entity 
public class customEntity {
    @Cplumn(name = "id")
    private int id;
}
```

>結合した結果が複数テーブルのカラムを含む場合、取得対象カラムすべてに対応するプロパティをもったエンティティクラスが必要です。

>使用するDaoのメソッド定義は次のとおりです。

```Java:
@Select
List<EmployeeDepartment> selectAllEmployeeDepartment();
```

>戻り値のListの要素であるEmployeeDepartmentが結合した結果に対応するエンティティクラスです。 このエンティティクラスは、結合のベースとなるテーブルに対応するエンティティクラスを継承すると比較的に簡単に作成できます。

複数のテーブルを結合した結果に対応するエンティティを作ろうとしているが、
テーブルAとテーブルBに同一のカラム名がある場合はどうすれば良いのだろう。。
下記の場合、nameがテーブルAとテーブルBにもある。それぞれデータを独自に持っている。 

```Java
@Entity
public class ContractorWithParents extends Contractor {

    @Column(name = "app_id")
    String appId;

    @Column(name = "name")
    String name;

    @Column(name = "name")
    String departmentName;

    ...

}
```
ここに答えが載っていた。

>このクラスは、Employeeクラスを継承し、DEPARTMENTテーブルのNAMEカラムに対応するプロパティを持ちます。 @Columnのname要素に指定されている「DEPARTMENT_NAME」はSQL上でDEPARTMENTテーブルのNAMEカラムの別名になります。

```Java:
@Entity
public class EmployeeDepartment extends Employee {

    @Column(name = "DEPARTMENT_NAME")
    String departmentName;

    ...
}
```



>Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectAllEmployeeDepartment.sqlです。 SQLは次のように記述されています。

```sql
select
  e.*,
  d.name department_name 
from 
  employee e 
left outer join 
  department d 
on 
  e.department_id = d.id 
order by 
  e.id
```

>Daoのメソッドは次のように呼び出します。

```Java
List<EmployeeDepartment> list = dao.selectAllEmployeeDepartment();
```



### 参考
+ [Doma公式](http://doma.seasar.org/reference/entity.html)
+ [Doma公式 - チュートリアル - 検索 - 結合した結果を取得する検索](http://doma.seasar.org/tutorial/select.html#%E7%B5%90%E5%90%88%E3%81%97%E3%81%9F%E7%B5%90%E6%9E%9C%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E6%A4%9C%E7%B4%A2)
+ [**doma2で複数のテーブルを結合した結果を取得する**](https://m-shige1979.hatenablog.com/entry/2017/01/30/080000)
+ [3.1.4.(JdbcTemplate)(複数テーブルの結合) Spring+MVC+DB+Test構築サンプル](http://www.mitchy-world.jp/java/spring/3_1_4.htm)
#100DaysOfCodeのススメ

#はじめに
本記事は株式会社Works Human Intelligenceのアドベントカレンダーの16日目の記事です。

はじめに、私は社会人4年目の2021年11月（本記事執筆の一か月前）に株式会社Works Human Intelligenceにエンジニアとして中途入社しました。
実は、私はエンジニアとしての実務経験はまだたったの一か月で、いわゆる~~駆け出しエンジニア~~ です。
まだエンジニアと名乗るのもおこがましいくらい絶賛駆け出し中ですので「駆け出しエ」ぐらいに名乗らせていただきます。

この記事は、前職の業務とエンジニアになるための勉強を両立していた時に、モチベーションの維持と向上をするために取り組んだ#100DaysOfCodeについて書きます。

エンジニアの多くの方は#100DaysOfCodeを既にご存じかもしれませんが、特に当時の私のように未経験でエンジニアを目指す人でモチベーション維持に課題を感じている方に向けて共有できればと思います。

#自己紹介

私は社会人4年目の2021年11月に株式会社Works Human Intelligenceにエンジニアとして中途入社をしました。
現在は開発者として働いていますが、実はこの会社に入社するまでは開発側ではなく、ビジネス側の人間として働いておりました。
大学も理系ではありませんでしたが、新卒で入社した会社のプログラミングの基礎研修をきっかけに開発に興味を持ち始め、趣味で少しコードを書いたりしていました。

最初は趣味で取り組んでいたものの、次第にエンジニアとしてのキャリアを歩みたいと思うようになり本格的に勉強を始めたのですが、何せ独学だったためモチベーションの維持に苦労しました。そんな時に出会ったのが**#100DaysOfCode**でした。


# #100DaysOfCodeとは？
その名の通り、100日間コードを書くチャレンジです。

### ルール
[100DaysofCodeの公式サイト](https://www.100daysofcode.com/rules/)に記載の通りルールは主に2つだけです。

> 1．100日間、毎日1時間以上コードを書く
> 2. #100DaysOfCodeのハッシュタグをつけて毎日進捗状況をツイートする

### はじめかた

ソーシャルメディア等お好きなプラットフォームで#100daysofcodeを始めることを宣言します。
私の場合はツイッターのアカウントがなかったので、アカウントを作成して初めてのツイートをしました。
ちなみに、#100DaysofCodeは世界的なチャレンジなので、英語で発信を行っていました。

![Screen Shot 2021-12-15 at 21.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634267/8bbc95a2-f81b-2180-2f89-7eda09b1f272.png)


#おすすめする理由
### とりあえず１時間コードを書けば目標が達成できる
独学を始めて間もない頃は、知識が少ないながらもコードをきちんとかけたときは達成感を得ることができていました。ただ、当たり前ですがなかなかうまくいかないことも多く、一つのエラーに何日も時間をかけてしまったり、エンジニアのコミュニティが狭かったので問題に直面した時になかなか必要なサポートを得られませんでした。うまくいかないとモチベーションも下がってしまい、パソコンを開かなくなることもありました・・・

そんな中で、#100Dayofcodeはとにかく毎日最低１時間コードを書くことをルールとしています。
この時間ベースの目標を通して、進捗に関係なくとりあえず１時間コードを書くことでゴールを達成できるので、モチベーションを落とさずに勉強を継続することができました。

### 続けることで習慣化できる
このハッシュタグは100日間を達成するまで、勉強した日を毎日積み重ねて記録していきます。
自分の中では毎日積み重ねていけるように予定が重なっている日であっても１時間コードをするため時間を確保しようという意識付けになりました。
これを続けていくうちに自分の中で意識せずとも勉強の時間をとれるようになり、プログラミングスキルを磨くことを日々の習慣にできるようになったと感じています。

### 各国のエンジニアと互いに研鑽し合える
ルールの２つ目に「自分の進捗状況を発信する」というものがありますが、ハッシュタグの発信を通して同じ取り組みをしているエンジニアから応援の言葉をもらったり、同じハッシュタグを使って発信しているほかのユーザーを見て自分のモチベーションの源にしたりしていました。

また、Githubのコードを公開することでより直接的なフィードバックをもらうことを公式サイトも推奨しています。

#おわりに ―自戒の念を込めて―
100Daysが終わり、目指せ300Daysをしていたのですが、こちらが私の最後のツイート。
![Screen Shot 2021-12-15 at 21.25.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634267/b9e4015d-2abe-d7c0-02c7-c3c98e6f598a.png)

とういうことで、こちらの記事は自戒の念を込めて、執筆させていただきました。
（むしろ自戒の念しかないです）

続ける、というのは難しいですが、「継続は力なり」という言葉にあるようにコツコツと続けることで確実なスキルアップを図れるだけでなく、自分が勉強してきた軌跡を残すことができエンジニアとしての自己肯定感を高めることにもつながると感じています。

現在は、実務において優秀なエンジニアの皆さんに囲まれて、一日でも早く追いつきたいと最大限のモチベーションで毎日開発に取り組んでいます。
実務を通しての自分のスキルアップの過程を振り返るためにも、この記事を機にまた一から#100DaysofCodeを始めたいと思います。

最後までお読みいただきありがとうございました。
C++/CLIでC# DLLを環境変数PATHから検索

#1.はじめに

C#のDLLをC言語から呼び出すために、C++/CLIでラッパーを作ったのですが、その場合、まっとうに配置すると、

  - C言語のexe
  - C++/CLIのラッパーDLL
  - C#のDLL

を、同じディレクトリに配置することになります。

C++/CLIのラッパーDLLは、環境変数PATHが通ったディレクトリに配置できますが、C#のDLLはexeと同じ場所でなければなりません。
業務の都合上、これを避けるために、C++/CLIのラッパーDLLで環境変数PATHからC# DLLを検索するようにしました。

#2.自前PATH検索

ハンドルのグローバル変数への保存は、[C++/CLIでグローバル変数にハンドルを保存する方法 - Qiita](https://qiita.com/mayo00/items/b1d55963cf22d9d79210)を使用しています。
実際に使用したコードでは、これに加えて、Win32 MutexによるflagInitializeの排他、環境変数PATHの前に呼び出し元exeのディレクトリの追加を行っています。

```main.c
#include <stdio.h>
#include "dll1.h"

int main(int argc, char** argv) {
	int ret = test1(2, 3);
	printf("ret=%d\n", ret);
}
```

```dll1.cpp
#define DLLMAKE
#include "dll1.h"

using namespace System;
using namespace System::IO;
using namespace System::Reflection;
using namespace System::Runtime::InteropServices;
//using namespace Test::DLL2;

#define DLL_NAME "Test.DLL2.dll"

static bool flagInitialize = false;

static GCHandle gct;
static GCHandle gcmi;

int test1(int a, int b) {
	if (!flagInitialize) {
		System::String^ path = Environment::GetEnvironmentVariable("PATH");
		array<System::String^>^ pa = path->Split(';');
		bool found = false;
		for each (System::String ^ dir in pa) {
			System::String^ filename = Path::Combine(dir, DLL_NAME);
			if (File::Exists(filename)) {
				Assembly^ a = Assembly::LoadFrom(filename);
				Module^ m = a->GetModule(DLL_NAME);
				Type^ t = m->GetType("Test.DLL2.TestClass1");
				MethodInfo^ mi = t->GetMethod("Test1");
				gct = GCHandle::Alloc(t);
				gcmi = GCHandle::Alloc(mi);
				found = true;
				break;
			}
		}
		if (!found) {
			// エラー
		}
	}

	Type^ t2 = safe_cast<Type^>(gct.Target);
	MethodInfo^ mi2 = safe_cast<MethodInfo^>(gcmi.Target);

	array<Object^>^ params = gcnew array<Object^>{2, 3};
	Object^ obj = mi2->Invoke(t2, params);
	int ret = (int)obj;

	//return TestClass1::Test1(a, b);
	return ret;
}
```

```dll1.h
#ifndef __DLL1_H__
#define __DLL1_H__

#ifdef __cplusplus
extern "C" {
#endif

#ifdef DLLMAKE
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif

DECLSPEC int test1(int a, int b);

#ifdef __cplusplus
}
#endif

#endif
```

```TestClass1.cs
using System;

namespace Test.DLL2
{
    public class TestClass1
    {
        public static int Test1(int a, int b)
        {
            return a * b;
        }
    }
}
```

#3.参考

[C++/CLIでメソッド名を指定して実行する - プログラムを書こう！](https://www.paveway.info/entry/2020/06/25/cli_invokemethod)
【AWS】CloudWatchのまとめ

# はじめに

こんにちは。
この記事は[GFAMアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/gfamz)の６日目の記事です。
CloudWatchについてまとめてみました。

# CloudWatchの概要

CloudWatchはAWSリソースの情報（メトリクス）を収集、監視し、アクションおよび分析を行います。

* 収集： メトリクスを収集する
* 監視： 閾値を超えるかどうかを監視、超えた場合アラームを発砲する
* アクション： アラームの発砲に基づいた（事前に設定されている）アクションを行う
* 分析： 収集した情報を可視化する

## メトリクス

メトリクスとは、CloudWatchで取得、監視した項目のことです。
EC2のメトリクスには以下の２通りがあります。

* 標準メトリクス：AWSが用意したメトリクス（CPU、ネットワークトラフィックなど）
* カスタムメトリクス：ユーザが独自に設定したメトリクス。CloudWatchエージェントを導入して、メモリ使用率、ディスク使用率など標準メトリックス以外の情報を収集する

以下に、CloudWatchの機能を紹介します。

## CloudWatchエージェント

カスタムメトリクスを収集、監視するにはCloudWatchエージェントを導入する必要あります。

# CloudWatch Alarm

CloudWatchで監視している項目が閾値を超えた場合、アラームとアクションを起動することができます。

# CloudWatch Events

AWS上のリソースの状態を監視し、あるイベントをトリガーにアクションを実行する機能です。

# CloudWatch Logs

AWSサービスのログを統合的に収集するサービスです。

# おわりに

CloudWatchは、あらゆるサービスと密接に連携されているサービスです。また、開発時やテスト時にも有効に使える機能となっています。この機能を使いこなせば、あらゆる面で助けになってくれること間違いなしです。
次回はS3について学習します。

# 参考

* [BlackBelt](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/)
【Laravel Mix】webpack で Bootstrap Icons をバンドルして使う

# バージョン
* Laravel 7
* bootstrap-icons 1.7.2

# 前提
js と css をそれぞれ webpack で1つのファイルにまとめて `public` 以下に置いています。

```webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');
```
```resources/js/app.js
import './bootstrap';
```

```resources/sass/app.scss
@use "./base/bootstrap";

@use "./modules/btn";
@use "./modules/footer";
```

# まず bootstrap-icons をインストール
```
npm i bootstrap-icons
```

すると、`node_modules` 配下に `bootstrap-icons` ディレクトリができます。

```
node_modules/
└── bootstrap-icons/
    ├── font
    │    ├── fonts/
    │    ├── bootstrap-icons.css
    │    ├── bootstrap-icons.json
    │    └── bootstrap-icons.scss
    ├── icons
    │    ├── ***.svg
```
この `bootstrap-icons.scss` を 先ほどの `app.scss` に追加します。

```resources/sass/app.scss
@use "./base/bootstrap";

@use "./modules/btn";
@use "./modules/footer";

// ここに追加
@use "bootstrap-icons/font/bootstrap-icons";
```

ここで **エラー発生**
`GET http://localhost/css/fonts/bootstrap-icons.woff2?30af91b...
net::ERR_ABORTED 404 (Not Found)`

# 原因
`bootstrap-icons.scss` の冒頭で `fonts` ディレクトリを参照していました。
しかも **相対パス** で...

```node_modules/bootstrap-icons/font/bootstrap-icons.scss
$bootstrap-icons-font: "bootstrap-icons" !default;
$bootstrap-icons-font-src: url("./fonts/bootstrap-icons.woff2?30af91bf14e37666a085fb8a161ff36d") format("woff2"),
url("./fonts/bootstrap-icons.woff?30af91bf14e37666a085fb8a161ff36d") format("woff") !default;
```


# 解決方法
`public/css` 以下に `fonts` ディレクトをコピーすればいいのですが、
構造が気持ち悪いので **js 側で読み込むことにしました。**

### 必要なモジュールをインストール
```
npm install url-loader
```
### webpackに設定

```webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

mix.webpackConfig({
    module: 
        rules: [
            {
                test: /\.(woff|woff2|eot|ttf|svg)$/,
                use: {
                  loader: 'url-loader',
                }
            }
        ]
    }
});
```

### js 側で読み込む

```resources/js/app.js
import './bootstrap';

// ここに追加
import 'bootstrap-icons/font/bootstrap-icons.css';
```

すると **エラーが変わって**
`GET http://localhost/fonts/bootstrap-icons.woff2?30af91b...
net::ERR_ABORTED 404 (Not Found)`
となるので、`public` 以下に `fonts` ディレクトリを設置すればいけそうです。

### フォント設置
Laravel Mix の便利な `copy` メソッドを使用します。
ビルド時に bootstrap-icons の `fonts` ディレクトリを `public` 以下にコピーします。

https://readouble.com/laravel/7.x/ja/mix.html
> copyメソッドは、ファイルやディレクトリを新しい場所へコピーします。これはnode_modulesディレクトリ中の特定のアセットをpublicフォルダへ再配置する必要がある場合に便利です。

```webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    .copy('node_modules/bootstrap-icons/font/fonts', 'public/fonts'); // 追加
```

これで無事にアイコンフォントが使えるようになりました👼

```index.html
<i class="bi-alarm"></i>
```

# 参考
https://moewe-net.com/nodejs/bootstrap-with-webpack
簡単！ERC20トークン発行

# はじめに

ERC20はEthereum上で発行される最もポピュラーなトークンです。

TestnetのRopstenで簡単にERC20を発行してみましょう。

使うソースコードはこちら。

https://github.com/shu-kob/erc20/blob/master/Erc20.sol

Ethereum上でデプロイするコントラクトを記述するsolidityのコードです。

https://remix.ethereum.org

solidityをWebブラウザ上で実行できるremixを用います。

Erc20.solなどファイルを作成し、Githubのソースコードをコピって、remixに貼ります。

![スクリーンショット 2021-12-15 23.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194002/ae58185a-a519-306e-f2db-815219e77e61.png)

```Erc20.sol
    string public name = "Orangebeam Token";
    string public symbol = "ORB";
    uint256 public decimals = 18;
    uint256 public totalSupply = 21000000000000000000000000; // 1,000,000 x 10^18
```

上からトークンの名前やシンボル、小数点以下の桁数、総発行量です。
適当に設定してあげましょう。

Google ChomeなどのブラウザでMetamaskを設定しておき、
Ropstenをいくらか入れておきます。

ENVIRONMENTで`Injected Web3`を選択し、Metamaskと接続します。

![スクリーンショット 2021-12-15 23.38.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194002/8e17b940-634c-aad8-6ec5-f39d41b19ff5.png)

`Deploy`ボタンを押します。

![スクリーンショット 2021-12-15 23.39.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194002/12db3892-3b84-0087-0463-1e812deeeb51.png)

`確認ボタン`を押します。

デプロイできました！

`transfer`のところに、`"0x000000.....000", 1000000000000000000000000`
というように、アドレスと金額を入れるとトークンの移動ができます。

![スクリーンショット 2021-12-15 23.41.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194002/a46f9b86-0469-cefe-2c5f-8670b5297c8b.png)

`transfer`ボタンを押すと、Metamaskの確認画面が出ます。

![スクリーンショット 2021-12-15 23.44.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194002/d3c7e78d-f53c-2ea2-bc88-46681df6e5b5.png)

`確認`ボタンを押すと送金できます。

![スクリーンショット 2021-12-15 23.46.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194002/36593065-3b73-2361-794e-793d69a3f960.png)

宛先にERC20トークンが送られていることが確認できました！
C#でカノジョをつくる（15日目）

お疲れ様です。たなしょです。
今日はGUIアプリを使ってテキストエディタを作成しました。
今まで作成してきたものより少し大掛かりになっています。

## テキストエディタ
### 保存機能
1. 文字を書きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/b7affc8f-c08b-02d4-3f14-5b824f872828.png)
2. 「ファイル」→「保存」を押すと下記のように「名前つけて保存」ダイアログが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/79848727-107e-a503-6bbe-8543d102a27d.png)
3. ディレクトリを見に行くと保存されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/03296c48-db2e-f941-859f-29aed86a4a4c.png)

### 開く機能
1. test.txtの中身を書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/4182a1e9-e7ed-7900-a1ac-96436c0d9435.png)
2. 「ファイル」→「開く」を押すと下記のように「開く」ダイアログが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/9de2dfb8-c0e8-8da5-6fa7-57b2b0526e1f.png)
3. ファイルをクリックするとファイルが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/04c78cd9-c9cc-67c5-41e6-1ac979c354b2.png)

### 閉じる機能
1. 「ファイル」→「閉じる」を押すとテキストエディタを終了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268048/7c8ab568-4292-09e3-a438-e7e38d638ac2.png)

上記の機能がMenuStrip,textbox,SaveFileDialog,OpenFileDialogのパーツだけでテキストエディタが作れるのは驚きました。

各処理の大事な機能について少し記載していきます。
## 保存機能について
1. 「保存」ボタンが押されたらファイル名を取得します。

```c#
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
    filePath = saveFileDialog1.FileName;
}
```
2. StremWriteクラスでファイルを書き込みます。

```c#
StreamWriter textFile = new(
    new FileStream(
        filePath,
        FileMode.Create)
    );
textFile.Write(textBox1.Text);
textFile.Close();
```
## 開く機能
1. 「開く」ボタンが押されたらダイアログで選択されたファイル名を取得します。

```c#
if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
    openFilePath = openFileDialog1.FileName;
}
```

2. StreamReaderクラスでファイルを読み込みます。

```c#
StreamReader textFile = new(openFilePath);
textBox1.Text = textFile.ReadToEnd();
textFile.Close();
```
## 閉じる機能
1. 閉じるボタンは簡単でExitメソッドを使えば実装できます。

```c#
Application.Exit();
```

## 最後に
簡単ではありますがテキストエディタを作成しました。
パーツを組み合わせてちょっと手を加えればできるのでとてもお手軽です。
自分で作ったテキストエディタなので愛着もわきますね！
明日はテキストエディタに「印刷機能」を付けていきたいと思います。
各クラウドベンダーが提供しているWAFのリクエストボディをチェックする際の制限が気になったので調べてみた

### AWS
~~[「AWS WAF のクォータ」のページ](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/limits.html)に「検査できるウェブリクエストボディの最大サイズ」として「8 KB」との記載あり。
また、[「ウェブリクエストコンポーネント設定」のページ](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-rule-statement-fields.html)では「リクエストボディの最初の 8 KB（8,192 バイト）のみが、検査のために AWS WAF に転送されます」、「AWSWAF は、ボディが 8 KB を超えるウェブリクエストのコンテンツ全体の検査をサポートしていません」と説明されている。~~

[「本文検査のサイズ制限の管理」のページ](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/web-acl-setting-body-inspection-limit.html)に以下の記載あり。
- Application Load Balancer と の場合 AWS AppSync、制限は 8 KB (8,192 バイト) に固定されます。
- CloudFront、API Gateway、Amazon Cognito 、App Runner、Verified Access の場合、デフォルトの制限は 16 KB (16,384 バイト) で、どのリソースタイプの制限も 16 KB 単位で最大 64 KB まで増やすことができます。設定オプションは 16 KB、32 KB、48 KB、および 64 KB です。

サイズ制限を超えた場合にどのような処理を行うかについては「[AWS WAFでのオーバーサイズリクエストコンポーネントの処理](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-oversize-request-components.html)」をご参照ください。


### Azure
~~[「Web アプリケーション ファイアウォールの要求サイズの制限と除外リスト」のページ](https://docs.microsoft.com/ja-jp/azure/web-application-firewall/ag/application-gateway-waf-configuration)に「最大要求本文サイズ フィールドはキロバイトで指定されます。このフィールドでは、ファイルのアップロードを除く、全体的な要求サイズの制限が制御されます。 このフィールドには、1 KB (最小値) から 128 KB (最大値) までの値が指定されます」、「要求本文の検査をオフにすると、128 KB を超えるメッセージを WAF に送信できるようになりますが、メッセージ本文の脆弱性が検査されません」との記載あり。~~

[「Azure Application Gateway の WAF エンジン」](https://docs.microsoft.com/ja-jp/azure/web-application-firewall/ag/waf-engine)のページに「要求本文のサイズ制限が 2 MB に増加」との記載あり。

### GCP
Google Cloud Armorの[「セキュリティ ポリシーの概要」のページ](https://cloud.google.com/armor/docs/security-policy-overview)に「Google Cloud Armor は、リクエスト本文を含む HTTP リクエスト タイプのうち POST リクエストのみを処理します。検査は POST 本文の最初の 8 KB に制限され、URL クエリ パラメータのようにデコードされます」との記載あり。
Lightship ARDK タッチ位置の取得方法

[前回](https://qiita.com/FumiyaHr/items/0c7b7f3c90e87131b1f0)はベースプロジェクトの作り方を書きました。    
今回は Lightship ARDK のタッチ位置の取得方法を記載します。

## ゴール

この記事では画面のタッチした位置を取得して、タッチした位置に文字を表示するアプリを通して、タッチ位置の取得方法を記載します。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ARDKでタッチした位置を表示するだけのサンプル <a href="https://t.co/7BNYHzNieA">pic.twitter.com/7BNYHzNieA</a></p>&mdash; FumiyaHr (@fit51) <a href="https://twitter.com/fit51/status/1467512186574876672?ref_src=twsrc%5Etfw">December 5, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

https://github.com/FumiyaHr/ARDKSample/tree/main/TouchInput

## タッチ位置を取得するAPI

ARFoundation でタッチ位置を取得するには、Input.GetTouch() を使用しますが、ARDK ではクロスプラットフォームに対応した ARDK の API である PlatformAgnosticInput を使用してタッチ位置を取得します。

[Niantic AR Development Kit (ARDK): PlatformAgnosticInput](https://lightship.dev/docs/class_niantic_1_1_a_r_d_k_1_1_utilities_1_1_platform_agnostic_input.html)

## 取得方法

1. [ベースプロジェクトの作り方](https://qiita.com/FumiyaHr/items/0c7b7f3c90e87131b1f0)の通りプロジェクトを作成します。
1. タッチした位置に表示する Text を作成します。今回は下図のようにしてみました。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/ccd49906-a67e-2238-5250-5ede3882ad58.png)

1. スクリプトを作成し、下記のコードを書きます。

    ```csharp:TouchManager.cs
    using Niantic.ARDK.Utilities;
    using UnityEngine;
    
    namespace TouchInput
    {
        public class TouchManager : MonoBehaviour
        {
            [SerializeField]
            private GameObject _obj;
    
            private void Start()
            {
                _obj.SetActive(false);
            }
    
            private void Update()
            {
                // タッチされた数を確認
                if (PlatformAgnosticInput.touchCount <= 0)
                {
                    return;
                }
    
                // スクリーン0のタッチインスタンスを取得
                var touch = PlatformAgnosticInput.GetTouch(0);
                // タッチかどうか判定
                if (touch.phase == TouchPhase.Began)
                {
                    _obj.SetActive(true);
                    _obj.transform.position = touch.position;
                }
            }
        }
    }
    ```

1. 作成したスクリプトを適当なオブジェクト（空オブジェクトから作成したTouchManager等）にアタッチします。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/f7c77538-3036-aac4-8192-d34f14ec77be.png)

1. InspectorでTouchManagerスクリプトのObjにテキストを設定します。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/1c95bc4e-a14d-5546-d350-8bb58d9b12ed.png)

1. デバイスで実行します。
1. 画面をタッチすると、タッチした位置に文字が表示されます。

## 応用先
- 平面検知と [IARFrameのHitTest](https://lightship.dev/docs/interface_niantic_1_1_a_r_d_k_1_1_a_r_1_1_i_a_r_frame.html) を組み合わせればタッチした平面を取得できます。
- Semantic Segmentationと [IARFrameのHitTest](https://lightship.dev/docs/interface_niantic_1_1_a_r_d_k_1_1_a_r_1_1_i_a_r_frame.html) を組み合わせればタッチしたピクセルのチャネルを取得できます。

## まとめ
タッチを取得するときは PlatformAgnosticInput を使用すると取得することができます。
RESTfulとは

RESTfulとはRESTの原則に則って構築されたWebシステムのこと。

REST（REpresentational State Transfer）とはWeb設計における考え方の一つ。


# RESTの原則
### 1. インターフェイスが統一されていること

Webであれば情報のやりとりは全てHTTP（Hyper Text Transfer Protocol）を使用していること

HTTPとはWebブラウザとWebサーバー間でWebページをやりとりする手順のこと
（具体例：GET、POST、PUT、DELET）


### 2. アドレスに可読性があること

Webブラウザから要求するときのアドレスは全て一意性を持ち、URIで表現できること


### 3. 接続性を持つこと

やりとりされる情報の中にハイパーリンクを持っていること


### 4. ステートレスであること

ステート（状態）がレス（無い）ということでWebブラウザとWebサーバーのやりとりは一回ごとに完結し、個々のやりとりが他のやりとりに影響を与えない


# 参考文献
[この一冊で全部わかるWeb技術の基本](https://www.amazon.co.jp/%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88%E5%9B%B3%E8%A7%A3%E5%BC%8F-%E3%81%93%E3%81%AE%E4%B8%80%E5%86%8A%E3%81%A7%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8BWeb%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%B0%8F%E6%9E%97-%E6%81%AD%E5%B9%B3/dp/4797388811/ref=sr_1_1?adgrpid=109564933910&gclid=Cj0KCQiAweaNBhDEARIsAJ5hwbdgfUjxmS_nWOM4eRWgPe383Z8N2KxRztBfFAfX1KHXVgKzEX-c8soaAs0SEALw_wcB&hvadid=554795909513&hvdev=c&hvlocphy=1009333&hvnetw=g&hvqmt=e&hvrand=7042424207584003392&hvtargid=kwd-1173425888792&hydadcr=1554_13431688&jp-ad-ap=0&keywords=web+%E6%8A%80%E8%A1%93+%E3%81%AE+%E5%9F%BA%E6%9C%AC&qid=1639578643&sr=8-1)
[キタミ式イラストIT塾 基本情報技術者](https://www.amazon.co.jp/%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88IT%E5%A1%BE-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E4%BB%A4%E5%92%8C04%E5%B9%B4-%E3%81%8D%E3%81%9F%E3%81%BF-%E3%82%8A%E3%82%85%E3%81%86%E3%81%98/dp/4297124513/ref=sr_1_4_sspa?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85&qid=1639578749&sr=8-4-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExTzBXOEU4VlVOQUZGJmVuY3J5cHRlZElkPUEwNzI0ODYxTlVXT1BMOVRQTVUwJmVuY3J5cHRlZEFkSWQ9QTE2WkxMMzlSNTZUQTEmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl)
勉強する中で知った「Go言語には○○がない」を理解する

こんにちは。Goのアドベントカレンダー17日目の記事です。
普段はPHPをメインに開発していますが、せっかくの機会なので勉強中のGoで記事を投稿に挑戦してみました。

Goを勉強していてPHPや他の言語に比べて２つの「○○がない」という言語仕様に戸惑いました。それは

- Go言語には継承がない
- Go言語には例外処理がない
です。

この２つの仕組みは他の言語ではよく活用しており、可能なら使った方が良いと思って使い続けてきていたので、とても違和感がありました。
なぜGoにはこの２つの仕組みがないのでしょうか。少しでも言語理解を深めるために自分なりに調べてみました。

# さきに結論

- 構造体の埋め込み、インターフェースを利用しよう
- errorインターフェースを利用しよう

# Go言語には継承がない
## そもそも他言語で継承が使われている理由はなぜなのか？
「継承」とは、クラス定義に共通している部分を別のクラスとしてまとめる仕組みのこと。継承を利用することで同じようなクラスを一から作り直す手間がなくなり、共通している部分はまとめて変更するが可能になります。なので、継承を上手く使うことで全体のコード量を減らすことが可能になり、共通の処理を変更する際も１箇所で済みます。

## なぜGo言語には継承がないのか
https://go.dev/doc/faq#inheritance
Goの公式FAQ「Why does Go not have assertions?」の項目をざっくりと要約しますと、Goでは多重継承による複雑さを避けるためにインタフェースの活用を推奨している。
たしかに継承によって階層化されてしまったクラスは結合度が高くなってしまい、基底クラスの変更がサブクラスで予期しないエラーが発生させてしまうことがありますよね


Goとは直接関係ありませんが、継承じゃなくてインタフェース使えば問題ないよねと解説されている記事が分かりやすかったので、リンクを貼っておきます🙋‍♂️
[Why extends is evil](https://www.infoworld.com/article/2073649/why-extends-is-evil.html)

## ではどう実装するのか
Goのinterface定義の内容はメソッドリストのような形になります。
PHPのように実装（implements）と明示的に宣言する必要がなく、interfaceに定義されているメソッドをすべて実装していれば、interfaceを利用することができるようになっています。
PHPerの自分としては少し不思議な感覚です。。

```golang
package main

import "fmt"

// Interface を宣言
type Accessor interface {
	GetName() string
	SetName(string)
}

// Accessor を満たす実装
// 明示的な宣言は必要なく、実装と完全に分離している
type User struct {
	name string
}

func (u *User) GetName() string {
	return u.name
}

func (u *User) SetName(name string) {
	u.name = name
}

func main() {
	// Userのインスタンスを直接変更しても値渡しになってしまうのでポインタを使用
	var user *User = &User{}
	user.SetName("user")
	fmt.Println(user.GetName())
	
	//Accessor Interface を実装しているのでAccessor 型に代入可能
	var acsr Accessor = &User{}
	acsr.SetName("accessor")
	fmt.Println(acsr.GetName())
}

```



#  Go言語には例外処理がない
## そもそも他言語で例外処理が使われている理由はなぜなのか？
例外処理を実装することで得られるメリットは

- コードの可読性が上がる
- エラー内容を呼び出し側に伝えることができる

などが上げられると思います。


## なぜGo言語には例外処理がないのか
https://go.dev/doc/faq#exceptions
Goの公式FAQ「Why is there no type inheritance?」の項目をざっくりと要約しますと、try-catch-finallyのように例外を制御構造に結びつけると、コードが複雑になるから、Goでは例外処理を用意していない。Goではerrorインタフェースを使うことを推奨しているとのことです。

## ではどう実装するのか
継承の話でインターフェースについて触れましたが、errorはGoでよく利用されるインターフェースの１つです。異なる型に共通の性質を付与することでerrorを利用することができます。
処理中のエラー有無はerrがnilか否かで判定することになっています。

```golang
package main

import "fmt"

// 独自定義のエラーを表す型
type MyError struct {
	Message   string
	ErrorCode int
}

// errorインターフェースのメソッドを実装
func (e *MyError) Error() string {
	return e.Message
}

func RaiseError() error {
	return &MyError{Message: "エラーが発生しました。", ErrorCode: 1234}
}

func main() {
	err := RaiseError()
	if err != nil {
		//エラー時の処理（RaiseErrorで代入したのでこちらに処理が流れる）
		fmt.Println(err)
		fmt.Printf("%T\n", err)
	}
}

```

# まとめ
新しい言語を学習すると普段慣れ親しんでいる言語とのギャップから新しい気付きや学びが得られて面白いですね。Go公式FAQには今回の２つ以外にもなんでこの言語仕様になったのか解説がまとめられています。また新い学びがあれば記事にしていこうと思います。


### 参考記事
https://go.dev/doc/faq

#### Go言語には継承がない
https://qiita.com/tenntenn/items/e04441a40aeb9c31dbaf
https://www.infoworld.com/article/2073649/why-extends-is-evil.html


#### Go言語には例外処理がない
https://qiita.com/nayuneko/items/3c0b3c0de9e8b27c9548
https://zenn.dev/nobonobo/articles/0b722c9c2b18d5
Android StudioとGit Hubの連携時の操作方法（ローカルリポジトリ作成→リモートリポジトリへプッシュまで）

#前提条件
#####クライアント側
　・Gitをインストールしていること（Gitコマンドが使えること）
　　参考：[Git](https://gitforwindows.org/) ※Windows環境用
　・Android Studioインストールされていること
　　参考：[Android Studio](https://developer.android.com/studio/install?hl=ja/)
#####その他環境
　・Git Hubアカウントを作成済みであること
　・Git Hubに対象のリモートリポジトリが作成済みであること
　　参考：[Git Hub](https://github.co.jp/)

#1.ローカルリポジトリ作成
1.「VCS」→「Create Git Repository」を選択します。
![①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/69544565-a90b-2843-9c72-a1ccfc43ddd5.png)
2.対象のプロジェクトを選択し、OKボタンを押します。
![②_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/7daf5b03-02cc-465b-0d66-8513cd7e0dac.png)


#2.対象のファイルをAddして、コミット
1.ツール ウィンドウ「Commit」を選択します。
![③.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/b9a4d1fb-1c28-c9bd-1fe6-40a7c042d2c5.png)
2.リポジトリにアップロードするファイルを選択します。
![④.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/41572972-bdab-a371-fc34-102d45f9d014.png)
3.コミットする内容を入力し、「Commit」ボタンを押下します。
![⑤.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/8e81ad8e-c780-bb15-95ec-d1d95e76ada2.png)

#3.リモートリポジトリを設定し、ローカルリポジトリをプッシュ
1.メニューバー「Git」→「Push」を選択します。
![⑥.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/252cf6dd-c200-8f9a-297a-691ab56b99be.png)
2.「Define remote」を選択します。
![⑦.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/ae1d3cc8-2039-4f61-1dd0-bbec7b0bc9f0.png)
3.「URL：」を入力し、「OK」ボタンを押下します。
![⑧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/26100636-44f1-4f79-6cda-6082b7443531.png)
4.「Push」ボタンを押下します。
![⑨.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270902/f8a097a3-fd03-5e59-4193-3a78b0454e38.png)


#参考
[Android StudioとGitHubを連携する方法](https://blog.codecamp.jp/programming-androidstudio-github)
[Android Studio最速入門～効率的にコーディングするための使い方](https://gihyo.jp/dev/serial/01/android_studio/0024)
[Android Studio の概要](https://developer.android.com/studio/intro?hl=ja)
英文リーダーアプリを作った


この記事は[個人開発Advent Calendar](https://qiita.com/advent-calendar/2021/personal-project)の16日目の記事です。昨日は@itizawaさんの[N1分析と個人開発](https://qiita.com/itizawa/items/0437d2c24743d0e152f9)でした。

こんにちは

個人で[AnnoReader](https://annoreader.com/)という英文リーダーのサービスを運用しています。今年Flutterでスマホアプリをリリースしましたので、サービスの紹介とその実装についてお話ししたいと思います。

## どんなサービス

英文にいろいろな注釈を付けて読みやすくするサービスです。私のような英語の学習者が、日常的な英文リーディングの時に補助ツールとして使うことを想定しています。

https://twitter.com/hironobu_s/status/1123600996368707584

スマホアプリはiOSとAndroidに対応しています。

https://twitter.com/hironobu_s/status/1469529551269433347

エンジニアをやっていると、英語を読む機会はとても多くなります。仕様書であったり、README.mdであったり、論文であったり、色々なタイプのドキュメントを読む必要があります。

ただネイティブでも帰国子女でもなく、後から勉強している人（私です）にはなかなか大変なんですね。特に長文や複雑な文になると理解に時間がかかる/内容を理解できないと言ったことがよくあります。

長文読解では単語を知っていることはもちろん、文の構造も正しく読み取らないといけません。学校の授業でやった「SVOCの5文型」や「主節と従属節」のような話です。それが分かっていないと文意を正確に把握できません。

この「英文の構造を把握する」作業をサポートしてくれるツールが欲しくて開発したのがこのサービスです。

例えば、このアプリを開発するのに使った[Flutterのトップページ](https://flutter.dev/)にある以下の文章、

> Flutter is an open source framework by Google for building beautiful, natively compiled, multi-platform applications from a single codebase.

これをAnnoReaderを使うとこうなります。

![screenshot7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44152/db1ef9dc-c21e-2a47-2b3d-370bc1886b7e.png)

フレーズの区切りが点線の枠で表示され、複合語(複数の単語で一つの意味になるもの)や名詞のかたまりには、まとめてアンダーラインが引かれました。またフレーズ毎に日本語訳も表示されています。このような補助的な情報を加えることで、英語リーディングをサポートしていくのがこのサービスの狙いです。補助情報はタップ一つでOn/Offできるので、困ったときだけOnにするような使い方もできるようになっています

こういったテキストに対して付随する補助的な情報のことを[アノテーション(Annotation)](https://www.google.com/search?q=annotation&source=lnms&tbm=isch)と言います。AnnoReaderのサービス名はここから来ています。


## 仕組み

このサービスの仕組みですが、

1. 英文をNLPライブラリを使って構文解析して
2. その結果をもとに色を付けたり、線を引いたり、枠で囲ったりする箇所を特定して
3. 見やすくアウトプットする

といったことを行っています。

NLPはNatulal Language Processingの略で自然言語処理と呼ばれています。たとえば単語の品詞(名詞、動詞など)を特定する処理や、単語間の修飾関係(Dependency Parsingといいます)を導いたりする処理があります。Qiitaにも[専用タグ](https://qiita.com/tags/nlp)があって多くの記事がありますね。このサービスではオープンソースのNLPライブラリ[spaCy](https://spacy.io/)を利用させてもらっています。

spaCyを使うとどんなことができるのか、以下のサイトでオンライン上で試してみることができます。実行するとわかりますが、英文に関する非常に多くの情報が取れます。

[Demos · Explosion](https://explosion.ai/software#demos)

spaCyのおかげで簡単に英文に関する品詞情報や修飾情報が取れるようになりました。後はそれを元に、フレーズの修飾関係を導いたり複合語をまとめたりと言った処理を実装します。ここは自分でロジックを実装しています。

そして、今回スマホアプリを開発するに当たって[Flutter](https://flutter.dev/)を利用しました。FlutterはGoogleが開発しているオープンソースのアプリケーション開発フレームワークです。

Flutterを採用したのは、iOSとAndroidを一つのコードベースで開発できることに魅力を感じたからです。私の守備範囲は主にWebアプリ開発からサーバーサイド開発で、アプリの開発経験はほぼなかったので、Flutterなら学習コストをあまり上げずに両方のプラットフォームにアプリを提供できると考えたのです。

実際にコードを書き始めて初期版のリリースまで3ヶ月ほどでした。Flutterは学習効率の良い優れたフレームワークだと思います。

# リリース後

このサービスはもともと自分用に作った個人用ツールでした。その後、サービス名を付けてドメイン取って公開したのがスタートです。Webサービスとしてリリースしたのが2019年でしたので、2年くらい運用していることになります。

一方でスマホアプリは今年の5月にリリースしてましたが、今のところ1500くらいのインストール数です。国別では日本が8割、その他の地域が2割で、OS別ではiOSが6割、Androidが4割くらいです。流入経路は主にannoreader.comのウェブサイトです。

今後も時間を見つけてサービスのブラッシュアップを進めていきつつ、せっかくFlutterを学習しているので他のプラットフォーム向けの開発、Macアプリとかも面白そうですね。

## おわりに

個人でのサービス開発は、すべて自分の責任で好きに作れるのでとても楽しいですね。新しい技術を学ぶきっかけにもなりますし。

最後に、もしAnnoReaderが皆さんの英語学習のお役に立ったのでしたら、開発者としてとてもうれしいです。良かったら試してみてください。

[AnnoReader - Text Annotation Tool](https://annoreader.com/)
手軽に始めるスクレイピング

[う　え　き　ぷ　に　き　あ　く　ん　笑 Advent Calendar 2021](https://adventar.org/calendars/6939 "うえきです")　15日目です

##環境
macOS Catalina 10.15.7
Python 3.9.7

##この記事について
本記事では、スクレイピングを今すぐしたいけどよくわからない！とりあえずコピペで動くものを使いたい！！！
みたいな方に向けたものです。
また、本記事での"スクレイピング"は"Webスクレイピング"を表します。

##スクレイピングについて
そもそもスクレイピングとは、特定の情報を取得することを目的としてWebページを自動的に巡回することです。
本記事では、Python3を用いて実装していきます。

##実装
本記事内では、モジュールとしてPython標準のurllib.requestモジュールを使用します。
以下、ページ内容の取得の実装部分になります。

```python
from urllib import request

URL = "https://www.google.com/"
res = request.urlopen(URL)
content = res.read()
res.close()
html = content.decode()
```
1行目でurllib.requestを読み込みます。
4, 5行目で指定したURLのページのHTMLをバイト列として取得します。
6行目で通信を終了し、7行目でバイト列として取得したHTMLを文字列にデコードしています。

以下、本記事内では、

```python
def urlopen(URL):
    from urllib import request
    
    res = request.urlopen(URL)
    content = res.read()
    res.close()
    html = content.decode()
    
    return html
```
として実装されているものとしています。

次に、取得したHTMLから特定のデータを取得する部分の実装です。

```python
URL = "https://www.google.com/"
html = urlopen(URL)
def element_get(HTML, TAG):
    HTML += ">" # データの取得がしやすいよう、末尾に>を追加
    tag_start = "<"+TAG+">"
    tag_end = "</"+TAG+">"
    ret = []
    splited_html = html.split(tag_end)
    for ind,element in enumerate(splited_html):
        if ind+1 == len(splited_html):
            continue
        ret.append(element.split(tag_start)[-1])

    return ret
```

流れとしては、HTMLタグを引数から作成し、

```html
<tag>
</tag>
```
その後、タグの終了で分割を行い、その結果に対してタグの始まりで分割をすることで要素の取得を行います。

##唐突な終わり
ここまで書いたのですが、特にぼくはスクレイピングでしたいことがないため、これ以上は書けません。有意義なプログラムを作成することはとても難しいですね...

最終的なプログラムは以下の通りになります。ぜひ有効活用してみてくださいね！（お願いしますほんとに）

```python
def urlopen(URL):
    from urllib import request

    res = request.urlopen(URL)
    content = res.read()
    res.close()
    html = content.decode()

    return html

def element_get(HTML, ELEMENT):
    HTML += ">"
    ele_start = "<"+ELEMENT+">"
    ele_end = "</"+ELEMENT+">"
    ret = []
    splited_html = html.split(ele_end)
    for ind,ele in enumerate(splited_html):
        if ind+1 == len(splited_html):
            continue
        ret.append(ele.split(ele_start)[-1])
    return ret
```

明日の記事はうえきさんらしいので、ぜひぜひ〜
[rails]git pushした後ローカルファイルを削除したらテーブルが作成できなかった話。

# 経緯

cloud9でrailsをかたかた。
↓
git push。
↓
ec2の作成をしていたため、無料利用枠ぎりぎりに。「git hubにあげたし、まあええか」とファイルごとcloud9を削除。
↓
gitからファイルを引っ張って、ec2の環境構築。
↓
無事死亡

# もう少し具体的に話すと

```
$ bundle exec rails db:create RAILS_ENV=production
```
でproductionのデータベースを作成しようとしたところ、
`ActiveSupport::MessageEncryptor::InvalidMessage`と言われる。

答えは全て以下の記事にありました。
>参考
>[【Rails】ActiveSupport::MessageEncryptor::InvalidMessage](https://qiita.com/suzy1031/items/64598d44b428ccd7abc5)
>[Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage](https://qiita.com/scivola/items/cc06ddbfd94d3118f693)
>[Railsのmaster.keyで泣くほどハマった・・](https://yukitoku-sw.hatenablog.com/entry/2020/02/04/145331)

参考にさせて頂いた記事の内容を簡単に言うと、5.2以降のrailsのセキュリティに自分でひっかかってしまったという話のようです。
`rails new` をすると`master.key`が自動で作成される。
これは`.gitignore`によって、pushしても反映されない。
つまり、リモートから引っ張ってきたファイルでは`master.key`が存在しないため、`credentials.yml.enc`の復号ができない。よってエラーが発生する。

ローカルのファイルが手元にないと、どうにもならない！！！

`EDITOR=vim bundle exec rails credentials:edit`で新たに`master.key`を作成したとしても、既存の`credentials.yml.enc`の鍵ではないため、なんの意味もないということです。

#  対処方法

本番環境に、元の`master.key`をコピペすれば済む話。

私と同じようにローカルファイルを削除してしまった場合は、

チーム開発など複数人での開発であれば、ローカルのキーを教えてもらい、`config/master.key`に書き込めばそれで完了です。

独り身の方は大人しく諦めましょう。
もしくは、`credentials.yml.enc`に大したことを書いていない場合は、新たに作り直すことでどうにかなるようです。

# 実際にやってみた。

``` 
$ rm credentials.yml.enc
$ EDITOR="vi" bin/rails credentials:edit
```
エラーが発生。鍵の方もこの世から消し去ることにする。

```
$ rm master.key
$ EDITOR="vi" bin/rails credentials:edit 
```

今度は成功。以下のことを言われる。

```
Save this in a password manager your team can access.

If you lose the key, no one, including you, can access anything encrypted with it.

      create  config/master.key

File encrypted and saved.　  
```

`cat`で`config/credentials.yml.enc`と`config/master.key`を確認。
どちらも新たな内容が作成されている。

というわけで、今度こそデータベースを作ってみる。

```
$ bundle exec rails db:create RAILS_ENV=production

Mysql2::Error::ConnectionError: Access denied for user ユーザー名　(using password: NO)　
```
パスワードが違うと怒られる。
パスワードはAWS SSMのパラメータストアから引っ張ってきていて、設定も完了していた。

`printenv`で確認。
環境変数の反映が消えている。
`aws configure list`で確認。
aws configureの情報は保持されている。

パラメータストアのbashファイルの設定をやり直してみる。

```
$ export 名前=$(aws ssm get-parameters --リージョン --name 名前 --query "Parameters[0].Value" --output text)
```

`printenv`でもう一度確認。
環境変数にパスワードが反映されている。

今度こそいきたいところ。

```
$ bundle exec rails db:create RAILS_ENV=production
```

成功！

# おわりに

リモートにファイルがある＝ローカルを削除してもよい、
というわけではないんだな、と。

というかファイルに限らず、不用意な削除は禁物ですね。

.gitignoreってすごい。
shellスクリプトに触れてみた話

### 最近こんなことがありました
仕事で数日に一度DBにアクセスして、とあるSQLを流さなければいけない。<br>
ただ、そのまま流せばいいというわけではなく一部を書き換えなければいけない。<br>
どこを書き換えるかは決まっているがその都度生成されるuuidに書き換えるので、具体的に何に書き換えるのかは決まっていない。<br>
なので、書き換える値をコピーしてローカルに置いてあるSQLを開いて、編集して、DBにアクセスして、流す。<br>
一回ならまだしも定期的にとなると面倒で面倒でならない。<br>
少し楽をしたいなと思いました。<br>

### というわけでターミナルでポチっとできるようにしてみました
```shell
#!/bin/zsh 

if [[ $1 =~ [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} ]]
then
    QUERY=$(sed -e "s/hogehoge/$1/g" $HOME/query.sql);
    psql "DB名" -c "$QUERY";
    echo 'done'
else
    echo 'uuidが無効です'
fi
```

こんな感じ<br>
まず引数がuuidの体を成しているか確認して、<br>
QUERYに書き換えたsqlを格納して、<br>
psqlコマンドで実行。<br>
.zshrcに<br>

```
alias script='~/script.sh'
```
こんな感じでaliasを作ってどこからでも触れるようにしてひとまず完成。<br>
また面倒になったら改良しようかと思います。
ECMAScript モジュールファイルが import された際に、そのファイルの上から下まで処理が走ることを確認

# はじめに
ECMAScript モジュールファイルが import された際に、そのファイルの上から下まで処理が走ることを確認してみました。
※ 動的インポートではなく、標準のインポート

以下の記事を参考に自分でも実践したみた記事になります(suin様に感謝)

https://qiita.com/suin/items/a106289e2d1d8d9c1490

import の仕様:
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import


# ファイルの用意

ここに置きました。
https://github.com/nnashiki/esmodule-load-sandbox

```
$ tree 
.
├── 1.mjs
├── 2.mjs
├── esm.mjs
└── main.mjs

```


``` esm.mjs
console.log("esm.js 1")

export const fnc_mjs = () => {return "this is fnc_mjs"}
import {fnc_1js} from "./1.mjs";
export {fnc_1js}
import {fnc_2js} from "./2.mjs";
export {fnc_2js}

console.log("esm.js 2")
```

```main.mjs
console.log("main 1")

import {fnc_mjs, fnc_2js, fnc_1js} from "./esm.mjs";
console.log(fnc_mjs())
console.log(fnc_1js())
console.log(fnc_2js())

console.log("main 2")
```


```1.mjs
console.log("1.js 1")

export const fnc_1js = () => {return "this is fnc_1js"}

console.log("1.js 2")
```

```2.mjs
console.log("2.js 1")

export const fnc_2js = () => {return "this is fnc_2js"}

console.log("2.js 2")
```

## 実行結果

ECMAScript モジュールファイル は import された際に、そのファイルの上から下まで処理が走ることを確認できました。

```
$ node --version
v14.18.1

$ NODE_DEBUG=esm node main.mjs
ESM 18751: Storing file:///file_path/main.mjs in ModuleMap
ESM 18751: Translating StandardModule file:///file_path/main.mjs
ESM 18751: Storing file:///file_path/esm.mjs in ModuleMap
ESM 18751: Translating StandardModule file:///file_path/esm.mjs
ESM 18751: Storing file:///file_path/1.mjs in ModuleMap
ESM 18751: Storing file:///file_path/2.mjs in ModuleMap
ESM 18751: Translating StandardModule file:///file_path/1.mjs
ESM 18751: Translating StandardModule file:///file_path/2.mjs
1.js 1
1.js 2
2.js 1
2.js 2
esm.js 1
esm.js 2
main 1
this is fnc_mjs
this is fnc_1js
this is fnc_2js
main 2
```