OmniAICreator/Qiita-1.07M huggingface dataset:
プロ野球選手情報を返すREST APIを作った

# はじめに

Suibariです。

日本プロ野球の支配下および育成選手の最新成績を取得できるREST APIを作りました。
これは[プロ野球選手名鑑LINE bot](https://github.com/suibari/NPBmeikan_bot)の副産物です。

本APIは[日本プロ野球機構](https://npb.jp/)の情報を引用させて頂いています。

# 使い方

以下URLにアクセスしてみてください。
選手名はクエリパラメータで指定します。

https://npbmeikan-bot.fly.dev/json?q=牧秀悟

REST APIだとあまり意味ない機能ですが、チーム名と背番号での検索にも対応しています。

https://npbmeikan-bot.fly.dev/json?q=横浜2

返ってくるjsonの構造は以下です。
投手でも同じような感じです。

```json
{
    "url":"https://npb.jp//bis/players/13115153.html",
    "name":"牧秀悟",
    "team":"横浜DeNAベイスターズ",
    "no":"2",
    "kana":"まき・しゅうご",
    "photo_url":"https://p.npb.jp/players_photo/2023/180/db/002_13115153.jpg",
    "position":"内野手",
    "bt":"右投右打",
    "hw":"178cm／95kg",
    "birthday":"1998年4月21日",
    "career":"松本第一高 - 中央大",
    "draft_y":"2020年ドラフト2位",
    "stats_2023":{
        "game":"143",
        "ab":"559",
        "h":"164",
        "hr":"29",
        "rbi":"103",
        "sb":"2",
        "avg":".293",
        "slg":".530",
        "obp":".337",
        "ops":"0.867"
    },
    "stats_2022":{
        "game":"135",
        "ab":"509",
        "h":"148",
        "hr":"24",
        "rbi":"87",
        "sb":"3",
        "avg":".291",
        "slg":".507",
        "obp":".354",
        "ops":"0.861"
    },
    "stats_2021":{
        "game":"137",
        "ab":"487",
        "h":"153",
        "hr":"22",
        "rbi":"71",
        "sb":"2",
        "avg":".314",
        "slg":".534",
        "obp":".356",
        "ops":"0.89"
    },
    "stats_total":{
        "game":"415",
        "ab":"1555",
        "h":"465",
        "hr":"75",
        "rbi":"261",
        "sb":"7",
        "avg":".299",
        "slg":".523",
        "obp":".349",
        "ops":"0.872"
    },
    "age":25
}
```

# 仕様、制約事項

* NPBのデータを基にしているため、2024年入団選手は現在(2024/2/18)未対応。3月半ば頃対応かも
* 前日までの成績が常に反映されます。更新タイミングは毎日AM3時
* 検索で複数の選手がhitした場合、DB上で先頭の選手1名だけが返ります

# おわりに、問題性の自分なりの解釈

冒頭で述べた通り、このAPI(とLINE bot)はNPBサイトをスクレイピングして、その情報を返しています。
このためNPBサイトにある無断転載禁止規約には引っかかりうると思います。
そこについて自分の解釈を説明します。

* 単なる引用だけでなく、NPBサイトにない指標を計算して送信しており、「情報解析」が目的。[著作権法は情報解析目的以外で情報を利用した時に問われる。](https://topcourt-law.com/internet_security/scraping-illegal)
* スクレイピングは間隔を空けて実行しており、サイトに与える影響はない
* 影響力あるアプリやAPIならともかく、ユーザ数が少なく今後上がる見込みもない
* 4年間本botを運営しているがアクセス制限など措置や問い合わせなどのトラブルはなかった

とはいえ、**NPB様から連絡が来た場合にはAPIおよびbotは速やかに停止する所存です。**
自分は野球が大好きで、データを共有してみんなで楽しみたいだけで、誰かに迷惑をかけてまでやるつもりはありません。

記事を見た方でもコメントがありましたらぜひお願いします。
rex0220 計算式プラグイン ユーザー名からユーザー選択項目をセット

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、ユーザー名からユーザー選択項目をセットします。

# 概要

文字列項目に指定されたユーザー名からログイン名を求め、ユーザー選択項目をセットします。

- １ユーザー名
- 複数ユーザー名をカンマ区切りで指定

![2024-02-20_08h50_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/77f1804e-f8dc-31cc-4b6e-07d553f171cb.png)

# 計算式プラグイン設定

循環参照を許可、ユーザー情報をチェックします。

![2024-02-20_08h55_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/abd9ca71-ee76-b926-a83b-e2afb44763e2.png)

全ユーザー名を取得し、指定されたユーザー名の位置で、全ログイン名から対象のログイン名を取得します。

```.js
OPTION: 循環参照を許可, ユーザー情報

// ユーザー選択1 USER_SELECT
LET(name, ユーザー名,
  pos,INDEXOF(UINFO(,"name"),name),
  SET_CODE(NVL(ARRAY_GET(UINFO(,"code"),pos), ARRAY()))
)

// ユーザー選択2 USER_SELECT
LET(
  tnames, SPLIT(複数ユーザー名, ","), // 名前分割
  unames, UINFO(, "name"),        // 全ユーザー名
  ucodes, UINFO(, "code"),        // 全ユーザーコード
  tcodes, ARRAY_MAP(tnames, x,
    LET(
      pos, INDEXOF(unames, TRIM(x)), // 位置検索
      ARRAY_GET(ucodes, pos)         // コード取得
    )
  ),
  codes, ARRAY_FIL(tcodes, x, x),   // 空フィルタ
  SET_CODE(codes)                    // コードセット
)
```

# ユーザー名からログイン名の求め方
全ユーザー名を取得し、指定されたユーザー名の位置で、全ログイン名から対象のログイン名を取得します。

## 全ユーザー名を取得

UINFO(,"name") で、全ユーザー名をユーザーID 順に配列で取得します。
計算式ツールで、関数の実行結果を確認することができます。

![2024-02-20_09h00_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2713dca0-9d48-0bb9-0573-33f9139899e4.png)

## 全ログイン名を取得

UINFO(,"code") で、全ログイン名をユーザーID 順に配列で取得します。

![2024-02-20_09h03_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ed135d7d-fde6-e2a3-9d84-89777258f126.png)

## 計算式

INDEX 関数で、全ユーザー名での配列位置を求めることができます。
ARRAY_GET 関数で、全ログイン名の配列位置の値を取得すると、対象のログイン名です。
SET_CODE 関数で、ユーザー選択項目にセットする形式へ変換されます。

```.js
// ユーザー選択1 USER_SELECT
LET(name, ユーザー名,
  pos,INDEXOF(UINFO(,"name"),name),
  SET_CODE(NVL(ARRAY_GET(UINFO(,"code"),pos), ARRAY()))
)
```

![2024-02-20_09h15_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/dad60717-7742-0e4e-d24a-ee880c48e304.png)
HugoでWEBサイトを秒で構築する


# Hugoとは

https://gohugo.io/

ウェブサイトを構築するための世界最速のフレームワーク。
[Hugo](https://github.com/gohugoio/hugo) はGoのプロジェクトの中で、6番目にスターが多いプロジェクトである。テーマなど静的サイトのカスタマイズが、簡単に行うことができる。

# インストール

https://gohugo.io/installation/ で各々の環境に合ったものをダウンロードできる。

Macの場合だとbrewで以下のようにダウンロードできる。

```
brew install hugo
```

# サイトの作成

プロジェクトを作成する。

```shell-session
$ hugo new site mysite
```

すると、以下のようなmysiteディレクトリが作られる。

```
mysite
├── archetypes
│   └── default.md
├── assets
├── content
├── data
├── hugo.toml
├── i18n
├── layouts
├── static 
└── themes // テーマを格納する
```

```shell-session
$ cd mysite
$ git init
$ git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
$ echo "theme = 'ananke'" >> hugo.toml
$ hugo server
```

http://localhost:1313/ にアクセスすると、以下のような画面が出てくる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/57a61aa7-82c8-8c5c-e192-4026a1c61bad.png)

## コンテンツの追加

mysiteは以下で以下のコマンドを叩く。

```shell-session
$ hugo new content posts/my-first-post.md
```

すると、mysite/content/に下記のように *my-first-post.md* が追加される。

```
content/
└── posts
    └── my-first-post.md
```

作成された *my-first-post.md* を以下のように修正する。

```markdown:content/posts/my-first-post.md
+++
title = 'My First Post'
date = 2024-02-19T22:59:22+09:00
draft = true
+++
## hello

**こんにちは**! 初めての投稿です。

Hello [Hugo](https://gohugo.io)!
```

以下コマンドを叩いてhttp://localhost:1313/ にアクセスすると,
`draft = true`にすると下書きとなる。以下のように`-D`をつけることで、下書きのプレビューも含むことができる。

```
hugo server -D
```

![スクリーンショット 2024-02-19 23.22.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/d37d4a73-3738-2266-d5c5-fab2243d3729.png)

`read more`をクリックすると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/a45a3f17-a40b-73f4-c1b3-17c62f79cd93.png)

このように投稿されている。

## サイトの設定

mysite配下の *hugo.toml* を設定する。

```hugo.toml
baseURL = 'https://example.org/'
languageCode = 'ja'
title = '初めてのWebサイト'
theme = 'ananke'
```

```
hugo server -D
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/37e9669a-35c4-c881-511b-59e545dfa35b.png)

タイトルが変わった。


## サイトの公開(デプロイ)

AWSの場合は静的ページなのでS3で公開することができる。

詳細なデプロイ方法やAWS以外のやり方は https://gohugo.io/categories/hosting-and-deployment/ に載っています。

設定できると、`hugo`と叩くだけでデプロイできるようになる。

# hugoの使い方

## テーマの種類

テーマはhttps://themes.gohugo.io/ に色々載っている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/bce3c236-a01c-859f-ba61-d614b001ef7f.png)

## 変更の監視

ホットリロードする場合は`hugo server --navigateToChanged`を叩く。

## 設定ファイル

設定ファイルはtoml以外にもyaml, jsonが使用できる。
パラメータ等はhttps://gohugo.io/getting-started/configuration/に載っている。

# 終わりに

他にも色々カスタマイズもできるので、気になったら使ってみてください。
【備忘】Datadogとは？ダンな監視と分析のプラットフォーム

## Datadogとは
### 一言で表すと
クラウドインフラストラクチャーの監視、分析、および可視化を行うためのモダンなプラットフォーム

### 詳細
Datadogは、ITインフラストラクチャーやアプリケーションのモニタリングと分析を行うためのクラウドベースのサービス。
Datadogは、リアルタイムでのメトリクス、ログ、トレースデータの収集、可視化、アラート設定を可能にし、システムのパフォーマンスやセキュリティの問題を迅速に特定し、解決するのに役立つツール。

## そもそもモニタリングサービスとは
モニタリングサービスは、WebアプリケーションなどのITシステムがエラーなく、きちんと稼働しているか、また、ITシステムのユーザがきちんとシステムを利用できているかを監視するサービスのこと。

### モニタリングサービスの種類
大きく分けて以下3種類に分類される

**1.OSSを利用するもの**
＜特徴＞
・オープンソースのソフトウェアを無償で利用する形式。
・入手が無償である一方で、構築や運用のコストがかかってしまうという欠点あり。
・代表的なものとして、ZabbixやPrometheusがあたります。

**2.有償のソフトウェアを利用するもの**
＜特徴＞
・ベンダーが開発したソフトウェアを購入し、利用する形式。
・ベンダーから購入する必要がある分、サポートが充実していることが多いが、ソフトウェアによってはやはり構築や運用にコストがかかる場合あり。
・代表的なものとして、JP1シリーズやSitescopeなどがある。


**3.SaaSを利用するもの**
＜特徴＞
・クラウドでSaaSとしてモニタリングサービスを利用する形式。
・監視対象のデータやサーバを登録しておき、クラウド上にデータを送信するとSaaS側でモニタリングを実施可能。
・SaaSベンダーに利用料を支払う必要があるが、サポート等は十全にうけることができる。
・SaaSなので導入が非常にスムーズであることが多い。
・代表的なものとして、NewRelicやDataDogがある。


## Datadogの特徴とメリットデメリット
### 特徴
・**多機能性**:Datadogはメトリクス、ログ、トレースなど、さまざまなデータタイプを収集、可視化、分析する機能を提供。
・**リアルタイム監視**: データのリアルタイム収集と可視化により、問題を早期に検出し、迅速に対処可能。
・**スケーラビリティ**: 大規模で複雑なインフラストラクチャーでも、Datadogは高いスケーラビリティを実現可能。

### メリット:

・**リアルタイム性**: 問題を素早く発見し、迅速に対応できる。
・**多機能性**: メトリクス、ログ、トレースなどのさまざまなデータを統合的に管理できる。

### デメリット:

・**コスト**: フル機能を利用する場合、コストが高くなる可能性あり。
・**学習曲線**: 複雑な機能を十分に活用するためには、学習曲線がある可能性あり。


## Datadogと他社との比較
類似の監視ツールは数多くあるため、比較することは難しいが下記サイトにて比較できる状況。
https://www.capterra.jp/alternatives/135453/datadog-cloud-monitoring

また、一例として「AWS CloudWatch」との比較もあったため
＜AWS CloudWatch＞
1 分単位のデータに正規化された 1 分粒度のメトリクスをレポート可能
＜Datadog＞
秒単位のデータに正規化された 1 分粒度のメトリクスをレポート可能

参考情報：[AWS インテグレーションと CloudWatch のFAQ](https://docs.datadoghq.com/ja/integrations/guide/aws-integration-and-cloudwatch-faq/)

## 活用するのに向いている企業
主に以下2つに該当する企業に向いている可能性あり
・**クラウドネイティブ企業**: クラウドネイティブなアプリケーションやマイクロサービスを展開している企業に適している。
・**大規模企業**: 大規模かつ複雑なインフラストラクチャーを持つ企業や組織に適している。

## まとめ
Datadogは、**すばやいトラブルシューティングログを迅速に検索・分析して、トラブルの原因追求と解決が可能**なツールである
MiniAPI(十七)：Cache

キャッシュは、空間を利用して時間を短縮する手法であり、応答時間を効率的に短縮することができます。asp.net coreではローカルメモリキャッシュと分散キャッシュが導入されています。
まず、ローカルメモリキャッシュについて見てみましょう：
```csharp
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Internal;
var builder = WebApplication.CreateBuilder(args);
// メモリキャッシュサービスを注入し、キャッシュ容量を40に設定
builder.Services.AddMemoryCache(opt =>{
    opt.SizeLimit = 40;
});
var app = builder.Build();
// キャッシュを検索
app.MapGet("/get/{id}", (IMemoryCache memoryCache, string id) =>{
    var result = memoryCache.TryGetValue(id, out string timeStr);
    if (result)
    {
        return $"取得成功：{timeStr}";
    }
    return "取得失敗";
});
// キャッシュを構成し、サイズを10とする
app.MapGet("/set/{id}", (IMemoryCache memoryCache, string id) =>{
  var time = memoryCache.Set<string>(id, $"{id}、 {DateTime.Now}", new MemoryCacheEntryOptions
  {
      Size = 10
  }); 
  return $"設定された時間: {time}";
});
app.Run();
```
SizeLimit=40は総キャッシュ容量であり、Size=10はこのキャッシュが占有する容量です。毎回10の場合、最大で4つ生成できます。ここで問題があり、バグかもしれませんが、5番目を追加すると、5番目は成功せず、最初の1つが削除されます（最も長くアクセスされていないものが削除される）。この時、有効なキャッシュは3つのみで、再び5番目を追加すると、それが有効になります。
キャッシュの設定時には、SlidingExpirationとAbsoluteExpirationRelativeToNowを設定でき、以下のように使用します：
```csharp
var time = memoryCache.Set<string>(id, $"{id}、 {DateTime.Now}", new MemoryCacheEntryOptions{
    // 3秒間アクセスがなければ期限切れ
    SlidingExpiration = TimeSpan.FromSeconds(3),
    // 3秒以内に継続的にアクセスがあれば、30秒で期限切れ
    AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30),
});
```
複数のレプリカをデプロイする場合、メモリキャッシュは適していません。現在の主流は、redisのようなNoSQLデータベースを使用してデータを高速にキャッシュすることです。ここではredisを例に、ローカルのdockerでredisをインストールし、次のコマンドで起動します：`docker run --name some-redis -d -p 6379:6379 redis`。appsettings.jsonの設定は以下の通りです：
```
"ConnectionStrings": {
  "MyRedisConStr": "127.0.0.1:6379"
}
```
具体的な実装コードは非常にシンプルです：
```csharp
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Internal;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddStackExchangeRedisCache(options =>{
    options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
    options.InstanceName = "DistributedRedis_";
});

var app = builder.Build();
app.MapGet("/disget/{id}", async (IDistributedCache distributedCache, string id) => {
     var result = await distributedCache.GetStringAsync(id);
     return $"取得成功：{result}";
 });

app.MapGet("/disset/{id}", async (IDistributedCache distributedCache, string id) =>{
    var time = $"{id}、 {DateTime.Now}";
    await distributedCache.SetStringAsync(id, time, new DistributedCacheEntryOptions
    {
        SlidingExpiration = TimeSpan.FromSeconds(5),
        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30)
    });
    return $"設定された時間: {time}";
});
app.Run();
```
キャッシュの使用法は非常にシンプルですが、何がキャッシュに適しており、どのくらいの時間キャッシュするべきか、キャッシュが失効した場合にシステムにどのような負担がかかるかなどの問題を考慮する必要があります。

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247484959&idx=1&sn=d5ea5d74ccda5e24c01d1ef7ccfe5933&chksm=9f005935a877d02345d66c482771c4204225faf2724eb57d328d9316beac831b2a1540b6f9fc&token=877361727&lang=zh_CN#rd
デバイスアクセスの最初の一歩

デバイスのアクセスは正しい値が読み込める事から始めるべきです。

BCM5301XにはRobo SwitchとよばれるEthernet Switchが内蔵されていてMACはそれに接続されています。

Switch単体の場合はMDIOなどで制御しますが、内蔵のRobo Switchはレジスタがメモリアドレスに見えます。

BCM4707, 4708 and 4709 use ChipcommonB Switch Register Access Bridge Registers (SRAB)　to access the switch registers

NetBSDでこの処理で間違ったコードがあったので修正しました。

https://github.com/yamori813/netbsd-src/commit/045e743a54bbdc3b0a0c86c03dc858d7ca5385cf

~~NetBSDのカーネルマクロで__BITS(31,24)は31ビット目から24ビットとなるのですが、32ビットを越えていてなんのこっちゃです。~~

実は私の勘違いでした。すみません。

```
           __BITS(m, n)
                   Return a bitmask with bits m through n, inclusive, set.  It
                   does not matter whether m > n or m <= n.  The least
                   significant bit is bit 0.
```

修正したコードでビルドしたカーネルを実行すると以下のログが出ます。

```
[   1.0000000] bcmccb0: Robo Switch init 53011
```

~~Switchの設定を行っていますが、まったくきいてなかったと思われます。おそらくブートローダーが設定していて、問題なかったのかもしれません。値を読み込んで確認していれば、このような馬鹿げたバグはすぐにきがつきます。~~

確認は大切だってことで。

チップIDの53010は10進で入っているのにRobo SwitchのIDは16進で入っています。チップIDは16Bitの制約があったから元々16進だったのが10進になって、Robo SwitchのIDは32Bitなので16進なのだと思われます。出たとこ勝負満載ですね。

正しい値は以下のように調べました。

GPLのコードで同様の処理を探します。

```c:src/shared/bcmrobo.c
        /* Issue the write command */
        val32 = ((page << CFG_F_sra_page_R)
                | (reg << CFG_F_sra_offset_R)
                | CFG_F_sra_gordyn_MASK
                | CFG_F_sra_write_MASK);
        W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32);
```

CFG_F_sra_page_RがSRA_PAGEでCFG_F_sra_offset_RがSRA_OFFSETのようです。実態は

```c:src/include/bcmrobo.h
#define CFG_F_sra_page_R                24
#define CFG_F_sra_offset_R              16
```

でした。

Broadcomのオープンソースはsharedやplat-brcmなどに独自のファイルがあります。

bcmとしたりbrcmとしたりして統一感がありません。
これだけは書いておきたい！C#のドキュメントコメント

# はじめに
プログラマーとして開発する場合、特に仕事ではたいてい複数人の開発になります。
そうした時に重要となるのはコードの読みやすさ、追いやすさですね。
この記事ではその中でも**最低限書いておきたいC#のドキュメントコメント**について取り上げようと思います。
※内容は個人の感想に理由付けされている程度です！実際にはチームの方針に従って開発してください。

# 最初に結論
先に結論ですが
- publicなメンバには必ずドキュメントコメントを書く
- 書いておきたいタグ
  - メソッド
    - summary
    - param
    - returns
  - その他
    - summary

だけは書いておきたいです！
こうすることでコードを辿ることなくエディタ上でクラスやメソッドが何者かわかります。

# なぜこれだけは書いておきたいのか
## summary
最重要タグです。クラスにメソッド、プロパティなど`public`であればどれにでも付けたいです。
多くの書籍では**名前をわかりやすくする**ことでコードの読みやすさを高めることを推奨していますし、それに越したことはないですが、僕の経験上名前だけで解決できないことはちょくちょく遭遇します。~~あと名付け戦争が起きることも~~
summaryを書くことによってエディタに何をするものなのか表示されるので必要以上に名前で悩む必要がなくなります。それと同時に注意点等も入れておけるので間違った利用を防げます。

## param
型と名前で推測できることは多いです。
ただ、引数はメソッドやプロパティと違って長くなるとメソッド定義自体が長く読みにくいものになります。
それであれば、名前は簡潔にしておいてparamタグによる説明で補足する方が全体として読みやすくなります。

## returns
メソッドの出力を表すので非常に重要です。
例えば**入力からどう作られたものなのか**や**処理に失敗した場合は何が返るのか**という点を記載しておくことで、読み手にメソッド内部の処理をある程度理解してもらえます。
特に後者は明確に書いてあることにより呼び出し元で成否判定する際、迷わずに済みます。

# 実例
ドキュメントコメントが真価を発揮するのはエディタ上なのですが実例で比較してみます。
例ではどこかの商店の取り扱い商品のリストを表すクラスと、商品名から商品の値段を取得するメソッドを書いています。
```csharp
// ドキュメントなし
public class ProductList
{
    public int GetPrice(string targetProductName)
    {
       int price = -1;
       // 商品名から探してpriceを取得する処理
       return price;
    }
}

// ドキュメントあり
/// <summary>取り扱い商品のリスト</summary>
public class ProductList
{
    /// <summary>商品名から値段を取得する</summary>
    /// <param name="name">値段を取得したい商品名</param>
    /// <returns>商品が見つかればその値段、見つからなければ負数</returns>
    public int GetPrice(string name)
    {
       int price = -1;
       // 商品名から探してpriceを取得する処理
       return price;
    }
}
```

どうでしょうか？
ドキュメントコメントがあるだけで内部実装まで追わなくても`GetPrice`メソッドを安心して使えるのではないでしょうか。

# まとめ
publicな要素にはsummaryを、メソッドであればparamやreturnsも書いておきたいですね！

# 参考資料
https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/xmldoc/recommended-tags#param
【読書メモ】オブジェクト指向でなぜつくるのか

# 本記事について

この記事では、「オブジェクト指向でなぜつくるのかという」書籍を読んで、考えたことや要点などをまとめています。

本記事で述べていることは個人的な見解に過ぎません。　

### 私について

- 入社してから1年未満のiOSエンジニア
- 未だに雰囲気でコーディングしているスタイルから脱出したいと思っている　

# 書籍の概要

## どんな本？

- 一言で
  - プログラミング言語の歴史と発展の中でオブジェクト指向がどのようにして生まれ、なぜ必要とされたのかを掘り下げ、その仕組みと応用を幅広く解説
- 著者
  - 平澤 章
- 出版年
  - 2018年 第2版（現在は第3版まで出ています）


## どんな人におすすめ？

- なぜオブジェクト指向で作るのかを具体的に説明できない方
- 駆け出しレベルからステップアップしたい方
- コーディングはできるが、その背後にある理論まで深く理解していないと感じる方

# 所感

1〜5章が個人的に興味深いと思いました。

オブジェクト指向の利点や、それを使うことでプログラミングがどう改善されるのかを以前は上手く説明できませんでしたが、本書を読むことで理解が深まりました。

オブジェクト指向がどのような歴史的背景から生まれ、なぜ必要とされているのかを知ることで、その重要性についてもよりよく理解できるようになりました。

また、メモリの仕組みに関する部分も興味深く、値型と参照型の違いを理解する上で参考になりました。

# 個人的な要点

個人的に重要だと思った3点を軽く紹介します。

- OOPを理解する上での3つの課題
- 歴史的な背景からOOPを理解する
- OOPの役割

:::note info
Object-Oriented Programming、オブジェクト指向プログラミングの略
:::

## 要点1: OOPを理解する上での3つの課題

筆者は、以下の課題がOOPの理解を難しくしていると主張しています。

- 用語が多すぎること
- 比喩を多用すること
- すべてオブジェクトとして表現しようとすること

## 要点2: 歴史的な背景からOOPを理解する

OOPは、読みにくい機械語や、扱いにくいアセンブリ言語、保守性の低い高級言語といった歴史的な課題を解決する形で自然発生的に生まれました。

#### 機械語の使用
- 課題：16進数などの機械語は全く読めない。

↓

#### アセンブリ言語の導入
- 課題：人間にわかりやすい記号を使っているが、機械に依存する部分が多く、少しの記述ミスでプログラムが暴走する可能性がある。

↓

#### 高級言語の開発
- 課題：複数の機械に対応し、文法で扱えるが、保守性（理解しやすさや修正しやすさ）が低い。

↓

#### 構造化言語の採用
- 課題：順次進行、条件分岐、繰り返しなどに制限されるが、サブルーチン（関数やメソッドのようなもの）の再利用が難しく、グローバル変数の使用を避ける必要がある。

↓

構造化言語の問題点を克服するため、オブジェクト指向プログラミン（OOP）が開発されました。

## 要点3: OOPの役割

OOPの三大要素

- クラス（まとめる、隠す、たくさん作る）
- ポリモーフィズム（呼び出される側をたくさん増えても、呼び出す側は変わらない）
- 継承（共通化でコードの重複の無駄を省く）

構造化言語の問題点を克服するだけでなく、コードの整理整頓と無駄を削減し、保守性と再利用性が向上しました。


# 最後に

本書を読むことで、オブジェクト指向がどのようにして生まれ、どんな場面で使われるかを学べました。
今後は、オブジェクト指向から派生したSwift言語の「Protocol」について、深く掘り下げたいなと思いました。

- [文献情報 - オブジェクト指向でなぜつくるのか](https://www.amazon.co.jp/dp/4296000187)
- [著者のサポートページ](https://ahirasawa.com/how3/)
UI/UXって何？中学生にもわかるように解説

今日は「UI/UX」という言葉について話していこうと思います。この言葉、聞いたことはあるけどいったい何のこと？って思っている人も多いかもしれません。実は、このUI/UXというのは、私たちがスマホやパソコンを使うときにとても大切なものなんです。

## UI（ユーザーインターフェース）って何？
UIとは「User Interface」の略で、「ユーザーインターフェース」と呼ばれます。これは、簡単に言うと、人と機械（スマホやパソコンなど）との間でやり取りするための「窓口」みたいなものです。たとえば、スマホのアプリでボタンをタップしたり、パソコンでマウスをクリックしたりするとき、画面に表示されているボタンやアイコン、メニューなどがUIです。これらが使いやすくてわかりやすいと、私たちはスムーズに機械を操作できますよね。

## UX（ユーザーエクスペリエンス）って何？
次に、UXは「User Experience」の略で、「ユーザーエクスペリエンス」と呼ばれます。これは、UIよりもっと広い概念で、アプリやウェブサイトを使ったときの「体験」全体を指します。つまり、見た目だけじゃなくて、使いやすさや楽しさ、満足感など、使っているときの感じ方全体のことです。たとえば、同じような機能を持つアプリでも、使いやすくて楽しいアプリと、使いにくくてイライラするアプリがあったら、私たちは使いやすくて楽しい方を好むでしょう。それが良いUXを持っているということです。

## UIとUXの関係は？
UIとUXは密接に関係していて、良いUIが良いUXを生み出すことが多いです。でも、UIがきれいで使いやすくても、それだけでは十分なUXとは言えません。たとえば、アプリがすごく遅かったり、必要な情報が見つけにくかったりすると、使っている人は不満を感じるでしょう。だから、UIをデザインするときには、見た目だけでなく、使う人のことをよく考えて、使いやすさや満足感も一緒に考える必要があります。

## まとめ
UI/UXは、私たちがスマホやパソコンを使うときにとても大切なものです。良いUIと良いUXがあれば、私たちはもっと快適に、もっと楽しく機械を使うことができます。これからも、いろんなアプリやWEBサイトがさらに進化していくと思うので、UI/UXに注目してみると、新しい発見があるかもしれません。
初めてのタスクアサイン〜プルリクエスト！

# 初めてのタスクアサイン〜プルリクエストの手順

この記事は、新米エンジニアの僕が初めて業務をアサインされてプルリクエストをするまでに行った手順をまとめたものになります。
僕のようにチーム開発の経験がなく、初めてプルリクエストをする！という方の参考になればいいなと思います。

### 用語＆前提
・ローカルリポジトリ　→　自分のPCに入っているgitのリポジトリのこと
・リモートリポジトリ　→ github上に存在するチームで共有しているリポジトリのこと
・ローカルリポジトリには、リモートリポジトリの内容が`git clone`でコピーされている状態
・ローカルリポジトリもリモートリポジトリもどちらも`master`ブランチがメインのブランチ

### ①ローカルリポジトリに作業ブランチを生やす
まず、上司の方から業務をアサインされたら初めに行うことは、ローカルブランチで作業ブランチを生やすことです。
この作業ブランチというのは、自分の業務用のブランチのことを指します。つまり、自分が業務のためにコーディングや修正を行うブランチのことです。
ターミナルを開き、該当のフォルダに移動します。そして、下記のコマンドを実行します。

```
git branch 　　　　　　　　//masterブランチにいることを確認

git switch -c <作業ブランチ名>       //作業ブランチの作成
```

これで、最後に確認でもう一度`git branch`を行い、新しい作業ブランチができていることを確かめましょう。

### ②実際に業務！
作業ブランチを生やせたら、次は実際にアサインされた業務を遂行しましょう！
そして、業務が終了したら、`git add .` → `git commit -m "〇〇"`をしてコミットしましょう。

### ③リモートリポジトリにpush!
ここからが新米エンジニアは、ドキドキするところですね。笑
ここで行おうとしていることは、実際に作業を行った作業ブランチをチームで共有しているリモートブランチに送ろうということです。それでは、以下のコマンドを実行してみましょう！

```
git push origin <ローカルの作業ブランチ名>
```

これで、githubの該当のリポジトリを確認すると「Compare & Pull Request」と現れるはずです。
これが現れていれば、push成功です。この段階では、チームで共有しているリモートリポジトリに結合はされないので安心してください。

### ④プルリクエストの作成！
「Compare & Pull Request」を押して、プルリクエストを作成しましょう。
このプルリクエストで重要なのが、リモートリポジトリのどのブランチに作業ブランチをマージさせるかという下記スクショの設定です。
ここは、チーム内でのルールがあるので必ず、上司の方に聞いておきましょう。
大抵は、`base: test` ← `compare: <作業ブランチ>`　となると思います。

![スクリーンショット 2024-02-20 8.19.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658371/7bb39362-c4eb-0ae9-5925-0ecd82d03290.png)

ここの設定が完了したら、レビュワーやプルリクの概要などを記述し勇気を振り絞り「create Pull Request」を押しましょう。笑

ここでも、レビュワーの方のapprove(承認)がなければリモートリポジトリにいきなりマージされることはないので安心して行いましょう。
Rails7系のAPIとPostgresqlをdockerで環境する方法

最近、Dockerを使ってrailsの環境構築にチャレンジしたので、まとめておきたいと思います。

はじめに新規作成したフォルダの下に４つのファイルを作ってください（ファイル名は全く一緒でお願いします！）
1. Dockerfile
1. docker-compose
1. Gemfile
1. Gemfile.lock
それぞれのファイルの記述を順を追って紹介します。
# Dockerfile
```
FROM ruby:3.1.2
RUN apt-get update -qq && apt-get install -y vim

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock

RUN gem update --system
RUN bundle update --bundler

RUN bundle install
COPY . /myapp

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
```
# docker-compose.yml
```docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - postgresql-data:/var/lib/postgresql/data
  web:
    build:
      context: ./rails
    command: bash -c "tail -f log/development.log"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
    tty: true
    stdin_open: true
volumes:
  postgresql-data:
```
ちなみの公式ドキュメントにあるコードに加えて、以下も記述している。
```
environment:
  - POSTGRES_PASSWORD=password
```
ポスグレのpasswordを設定しないとこの後、`docker-compose run web rake db:create`でデータベースを作成する際にエラーが起きます。

また、dbの方にもportを指定しています。こうすることによって、TablePlusを使えるようにします。

# rails/Gemfile
```rb:rails/Gemfile
source 'https://rubygems.org'
gem "rails", "~> 7.0.4"
```
railsのバージョンを指定しない場合、最新版がダンロードされます。

# rails/Gemfile.locl
こちらは空のままにしておきます
```rails/Gemfile.lock
```

# rails/entrypoint.sh
```sh:rails/entrypoint.sh
#!/bin/bash
set -e

rm -f /myapp/tmp/pids/server.pid

exec "$@"
```
# 準備完了！コマンドを実行
```
docker compose run --rm rails rails new . --force --api --database=postgresql --skip-action-cable --skip-sprockets --skip-turbolinks --skip-webpack-install --skip-test --skip-bundle
```
データベースをPostgreSQLに指定して、アプリケーションを作成します。
また、webpackなど不要なものをスキップしておきます
```
docker compose run --rm rails bundle install
```
これでbundle installできます。

## database.ymlを編集
database.ymlにhost,username,passwordを追加します
```
default: &default
  adapter: postgresql
  encoding: unicode
  host: backend
  username: postgres
  password: password
  pooling  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
```
## DBを作成
```
docker compose run web rails db:create
```
これで環境構築完了です。
【PHP】2次元配列をimplodeしたかった話

# はじめに

ある日こんなことを思いました。

2次元配列をimplodeしたい！

と。

# どういうことか
```
[[1,2,3],[4,5,6]]
```
こんな多次元配列を
```
1|2|3|4|5|6
```
こんな感じに変換したいということです。

# 試したこと① foreach

まずはシンプルにforeachを使って変換しました。

```php:
$array = [[1,2,3],[4,5,6]];

$result = "";
foreach($array as $value){
    $result .= implode("|",$value);
}

echo($result);

// 出力結果
// 1|2|34|5|6
```
3と4がくっついてしまいました。

implodeで変換したものをresultにくっつけるのではなく、１つの配列を作って一気に変換してみようと思います。

```php:
$array = [[1,2,3],[4,5,6]];

$resultArray = array();
foreach($array as $value1){
    foreach($value1 as $value2){
        array_push($resultArray, $value2);
    }
}

$result = implode("|",$resultArray);

echo($result);

// 出力結果
// 1|2|3|4|5|6
```

この書き方ならできるけど、foreachのネストが深くなってしまって読みにくいです。

どうしたものか。

調べてみると、PHPにはarray_mapというものがあるらしい。

これを使ってみます。

# 試したこと② array_map

>array_map — 指定した配列の要素にコールバック関数を適用する

https://www.php.net/manual/ja/function.array-map.php

公式にはこのように記載されていました。

つまり、foreachみたいに配列の各要素に対してそれぞれ処理できて、それを配列で返すことができるよってことだと思います。

これを使用して、まずimplodeした者同士の配列を作って、次にそれをimplodeしてみました。

`[[1,2,3],[4,5,6]]`
        ↓
`["1|2|3","4|5|6"]`
        ↓
`1|2|3|4|5|6`

こうやって段階的に変換していく作戦です。

```php
$array = [[1,2,3],[4,5,6]];

function imp($value)
{
    return implode("|", $value);
}

$result = implode("|", array_map('imp', $array));

echo($result);

// 出力結果
// 1|2|3|4|5|6
```

さっきのforeachよりは読みやすくなった気はしますが、implodeが2回使っているのも気持ち悪い気がします。

なんとかimplodeを１回で書く方法はないだろうか。

さらに調べていくと、array_reduceというものがあるらしいと分かりました。

# 試したこと③ array_reduce

>コールバック関数を繰り返し配列に適用し、配列をひとつの値にまとめる

https://www.php.net/manual/ja/function.array-reduce.php

公式にはこのように記載されていました。

つまり、配列すべてに対して指定した関数を実行してくれるらしい？

ということは、$arrayのすべてに対してarray_mergeかけて一気にimplodeできそう。

`[[1,2,3],[4,5,6]]`
        ↓
`[1,2,3,4,5,6]`
        ↓
`1|2|3|4|5|6`

こんな感じの作戦です。

```php
$array = [[1,2,3],[4,5,6]];

$result =  implode("|", array_reduce($array, 'array_merge', []));

echo($result);

// 出力結果
// 1|2|3|4|5|6
```

お、いい感じにまとめられました！

# おわりに

同じ出力結果を出すだけでも様々な方法があるので、一回できたらあきらめるのではなく、もっといいやり方を探すのが大事なんだなと思いました。

今後とも自分の気づきなどを記事にして行けたらなと思います。

最後まで読んでいただきありがとうございました！
BizとDevの間に壁ができる理由とその解消法を考えてみた

# はじめに

Biz（ビジネスサイド）とDev（開発サイド）の分断はプロダクトにおける難しい課題の一つであり、特にマネージャー職の方々は試行錯誤し、日々頭を悩ませていることと思います。

明確な解決方法を提案している記事が少ないこと、そして私が働くスタートアップでも、このような状況になった経験があることから、今回自身の振り返りと体験談として記事にすることにしました。

私自身、BizとDev両方の立場に立った経験があるので、どちらの気持ちも理解した上で、BizとDevの間に壁ができる理由とその解消法を考えてみます。
決してどちらか一方を批判する趣旨の記事ではありません。

※あくまでも15名程度の少人数のスタートアップでの経験談ですので、それを踏まえて参考程度にお読みいただければ幸いです。

# BizとDevの役割を考える

BizとDevでは役割やミッション、作業プロセスや思考プロセスなどが大きく違ってきます。
まずは何がどう違うのか分かりやすく明確にしてみます。

## Biz（ビジネスサイド）
### 役割とミッション：

ビジネスサイドの主な役割は、市場分析、新規顧客の獲得、売上の最大化、ブランド価値の向上などがあります。
ミッションとしては、サービスや製品の収益を上げて企業を成長させることです。

### 作業プロセス：

サービスや製品の戦略立案、マーケティング、販売戦略、顧客関係管理（CRM）など、非技術的なプロセスが中心となります。
 
### 思考プロセス：

ビジネスサイドは、ROI（投資収益率）、市場シェア、顧客満足度などの数値を用いた分析が中心です。
また、市場の動向や競合分析に基づく戦略的な考え方が求められます。

## Dev（開発サイド）

### 役割とミッション：

開発サイドの主な役割は、ソフトウェアの設計、開発、テスト、保守などがあります。
ミッションとしては、ユーザーのニーズに合った製品やサービスを、高品質かつタイムリーに提供することにあります。

### 作業プロセス：

コーディング、テスト、デバッグ、ドキュメントの作成など、技術的なスキルと知識を要する作業が中心となります。

### 思考プロセス：

開発サイドはプログラミング言語や技術スタックに精通している必要があります。
とくに問題解決に向けた論理的かつ創造的な考え方が求められ、コードの品質や効率性、拡張性などに重点を置きます。

# BizとDevの分断によって起こる不利益について

次に、両者の違いとそれにより生じる不利益について考えてみます。
先に挙げたように、そもそもBizとDevの間には、目標とする成果や業務の性質が全然違います。
このため思考のフレームワーク自体が異なり、それによってちょっとした誤解や期待の不一致を引き起こすなど、コミュニケーション面での障壁が生じやすいと言えます。

実際に、BizはDevに対して技術的な知識がないため無茶な要望をする、もしくは逆になにも言えない、DevはBizの無茶な要望に対して不満を募らせたり、なにも言われなければ自分達で好き勝手なものを実装するなど、負の連鎖に陥ります。

このような状態が常習化してしまうと、ユーザーに対して良いサービスや製品の価値提供を行うことは、極めて難しくなります。

# この問題を解消するためにはどうすればいいのか？

これを解消するには、BizとDev間で定期的にミーティングを開催し、プロジェクトの進捗や課題、目標について情報共有を行うのが良いかと思います。

私が現在、プロダクトマネージャー（PdM）を務めている金属加工の商取引プラットフォームの「Mitsuri」チームでは、毎週BizとDev混合での定例ミーティングを開催しています。
主にカスタマーサポート、マーケティング、開発といった各チームの担当者が、今週行なったタスクの進捗を説明しています。

これにより、お互いの作業状況を理解し、期待のズレを防ぐことができます。

この状況を実現するためには、自分達のサービスや製品についてのコンセプトやチームの行動規範のような常に意識するべきことを、チーム全員が共通認識として腹落ちできるようにしておくことがとても重要です。(これがめちゃめちゃ難しい)

他にも知識共有セッションやワークショップなどを開催して、Bizが技術的な基礎知識を、Devがビジネス戦略や市場理解を、それぞれ深める機会を設けてみるのも効果的かと思います。

チームビルディングとしては、ヒエラルキー型の組織でこれを実現するならば、BizとDevどちらも経験したことがある人をリーダーに据えたり、そうでなければティール型組織のような自走できるチームの構築を目指すのが良いかもしれません。

ちなみに弊社の「Mitsuri」チームでは、後者を目指しています。
興味がある方はご応募お待ちしております。

https://open.talentio.com/r/1/c/catallaxy/homes/2947

# まとめ
BizとDevの間に壁ができる理由とその解消法を個人的な見解で考えてみました。

やはりBizとDevのメンバーがお互いの領域に対して壁を作らない、すなわちクロスファンクショナルなチームを目指すということが大事だと思います。

適切なコミュニケーションと相互理解を深めれば、お互いを補完し合うことで強みに変えることが可能です。両サイドが協力して目標に向かうことで、企業全体の成長と成功を実現することができると思います。

この記事が皆さんの参考になれば幸いです。
大学生として一年実務経験を積んで学んだこと

問題の特定：

コーディングへ飛び込む前に、取り組んでいる問題と開発しようとしている解決策を把握することが重要

- 要件定義書をしっかり読んで、全体の意味を理解しましょう

MVP（最小限の実行可能な製品）の到達：

- プロジェクトの基本的な運用に不可欠なものを優先し、最初は主要な機能に焦点を当てる

完成とフィードバック：

- MVPの完成は、プロジェクトの核心の完成を基本的に意味します
- フィードバックを集め、ユーザーのニーズと希望に基づいて次の機能を特定する

ソフトウェアエンジニアの視点から：

- 最も熟練したプログラマーは、最も間違いを犯す人たちです。なぜなら、間違いはプログラミングに不可欠な側面だから
- 決して失敗しないと期待することは非現実的
- エラーは、あなたが開発者としての能力を定義するものではなく、正しい解決策を見つけるための重要なステップ
- エラーメッセージは、失敗の兆候としてではなく、正しい道へと導くガイダンスとして捉えるべき
- 最初の試みで完璧にコードが実行されることは、安心よりも警戒すべき
- プログラミングは、新しくユニークな課題に取り組むことを含みます。そこでは、間違った解決策に遭遇するのが普通
- 間違いを犯し、助けを求めることは全く問題ありません
- 失敗への恐怖は、世界の終わりを意味するわけではないことを認識することが重要
- コーディングプロセスは、書く、デバッグする、そして望ましい結果が得られるまで改良を繰り返すこと。失敗は成功への基盤です
- 実際のコーディングには、忍耐力、学習、成長を要求する課題が不可欠
- 重要な側面を他人に任せるだけでなく、協力と相互支援を育むことが重要
2024/2/20主にITとかセキュリティの記事

マルウェアに感染したデジタルビデオレコーダーから大量の不審な通信、確認を - JPCERT/CC(2/18)
https://news.mynavi.jp/techplus/article/20240218-2884851/

【書評】「コンテナセキュリティ　コンテナ化されたアプリケーションを保護する要素技術」(2/18)
https://dev.classmethod.jp/articles/review-book-with-container-security/

AIで「全身スキャン」を迅速化、予防医療の革命に挑むスタートアップ　ただし専門家は懸念も(2/18)
https://forbesjapan.com/articles/detail/69183

DAO（自律分散型組織）とは？概要からWeb3.0との関係について解説
https://xrcloud.jp/blog/articles/business/1085/

DXの課題、過剰なツール／データで生産性低下のリスク、生成AIによる課題解決の取り組みも(2/18)
https://news.yahoo.co.jp/articles/d2585a7c664874ae4ba312e5dc8cd87ce24a87da

テスト成績の画像をLINEに投稿　釧路市、学校職員の処分検討(2/18)
https://news.livedoor.com/article/detail/25896882/

【注意】iPhone初の脅威「GoldPickaxe」から財産を守る5つの対策(2/18)
https://iphone-mania.jp/news-575414/

HTMLのaタグとキーボードによるサイバー攻撃発見、注意を(2/18)
https://news.mynavi.jp/techplus/article/20240218-2885458/

iOSとAndroidから顔認証データ盗むマルウェア「GoldPickaxe」、口座に不正アクセス(2/18)
https://news.mynavi.jp/techplus/article/20240218-2885669/

「Google フォト」は正しく使わないと危険!?無料で使える写真アプリのメリットとデメリット(2/18)
https://dime.jp/genre/1736598/

エンジニアに人気のおもちゃ｢Flipper Zero｣でできる10の遊び(2/18)
https://www.gizmodo.jp/2024/02/flipper-zero.html

世界経済について楽観的に見る7つの理由(2/18)
https://zuuonline.com/archives/276082

楽天やデジタル庁などのデータ保護担当者集結、個情法見直し議論の「論点の1つはAI」(2/19)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/08919/

量子暗号（Quantum Cryptography）(2/19)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/021500161/

日本のAI創薬を加速　「Tokyo-1」が始動(2/19)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/021400168/

中規模FPGAに異変、Intel・AMDが戦線変更(2/19)
https://xtech.nikkei.com/atcl/nxt/mag/ne/18/00001/00414/

ネット出願にGmailが使えないトラブル　原因特定の難航で復旧に1カ月
神奈川県教育委員会(2/19)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600011/021500150/

トヨタグループ不正の構造問題　ITによる現場力の統制が必要だ(2/19)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600007/021500159/
Docker で Lisp のインタープリターを呼ぶ

# はじめに

急に Lisp がやってみたくなったので、 Docker の練習がてら環境構築してみた。

今回は Steel Bank Common Lisp(SBCL) をインストールします。

この記事では下の記事のインストール部分を参考に、最新版の SBCL をインストールする Dockerfile を作成します。
- [とほほのLISP入門 - とほほのWWW入門](https://www.tohoho-web.com/ex/lisp.html#write-line)

## 環境

```shell
$ docker --version 
Docker version 20.10.18, build b40c2f6
```

## Dockerfile

```dockerfile
# Use the official Ubuntu 22.04 base image
FROM ubuntu:22.04

# Set the working directory
WORKDIR /usr/src/app

# Update package list and install necessary dependencies
RUN apt-get update && \
    apt-get install -y wget bzip2 make rlwrap && \
    wget http://prdownloads.sourceforge.net/sbcl/sbcl-2.4.1-x86-64-linux-binary.tar.bz2 && \
    bzip2 -cd sbcl-2.4.1-x86-64-linux-binary.tar.bz2 | tar xvf - && \
    cd sbcl-2.4.1-x86-64-linux/ && \
    sh install.sh

# Cleanup unnecessary files
RUN rm -rf /usr/src/app/sbcl-2.4.1-x86-64-linux* && \
    apt-get autoremove -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Set the default command to run sbcl
# sleep が無いとエラーを出る
CMD ["bash", "-c", "sleep 0.05; rlwrap sbcl"]
```

CMD の `sleep` は `rlwrap sbcl` ではエラーを出るために追記した。

`rlwrap` はコマンドラインを読み取り履歴機能などを追加してくれるソフト。これがないと誤字を消すために左矢印を入力すると `^[[D` が表示されたりする。

### docker を使いたくない人へ

普通に `apt install sbcl` で古いバージョンがインストールできます。

```shell
$ apt show sbcl
# Package: sbcl
# Version: 2:2.1.11-1
# Priority: optional
# Section: universe/devel
# Origin: Ubuntu
# Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
# Original-Maintainer: Debian Common Lisp Team <debian-common-lisp@lists.debian.org>
# Bugs: https://bugs.launchpad.net/ubuntu/+filebug
# Installed-Size: 46.3 MB
# Provides: lisp-compiler, sbcl-fasl-loader-78
# Depends: libc6 (>= 2.34), zlib1g (>= 1:1.1.4)
# Recommends: binfmt-support
# Suggests: sbcl-doc, sbcl-source, slime
# Breaks: cl-asdf (<< 2:3.3.3-4~), cl-cffi (<< 1:0.22.1-1~), cl-nibbles (<< 20210520.gitdad2524-1~)
# Homepage: http://www.sbcl.org
# Download-Size: 10.6 MB
# APT-Sources: http://jp.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages
# Description: Common Lisp コンパイラおよび開発システム
#  SBCL は ANSI Common Lisp 言語向けの開発環境です。 ネイティブコードコンパイラと統合デバッガを提供し、さらに ANSI
#  仕様の全機能 も提供しています。
#  .
#  SBCL には、外部関数インターフェース (FFI)、疑似サーバ API、ユーザ拡張可能な
#  ストリーム機能、メタオブジェクトプロトコル、外部プロセスを実行する機能を含 む、ANSI 仕様への他の拡張も含まれています。
#  .
#  SBCL のソース定義を開発環境と共に閲覧するには、sbcl-source パッケージをイン ストールしてください。SBCL
#  の使い方や内部についての文書は、パッケージ sbcl-doc で提供されています。

```

## Hello World

```log.txt
$ sbcl 
This is SBCL 2.1.1.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (write-line "HelloWorld!")   
HelloWorld!
"HelloWorld!"
* 
```
プリザンターでPostmanを使ってRestAPIを使う方法

# はじめに
ローカル環境で[プリザンター](https://pleasanter.org/)を[Postman](https://www.postman.com/)で利用するための方法をまとめてみました。

<details><summary>環境</summary>

OS：Windows 11 Pro
データベース：SQL Server 2019 Express
プリザンター：1.4.0.1
</details>

<details><summary>Postman for Windows</summary>

バージョン：10.23.1
UI バージョン：10.23.1-ui-240213-0705
デスクトッププラットフォームバージョン：10.23.0
アーキテクチャ：x64
OS プラットフォーム：win32 10.0.22631
</details>

# [STEP1] APIキーの作成

RESTAPIを利用するために、プリザンター側からAPIキーを生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/ff538616-ea9a-a75e-3502-a6fd8011afb2.png)

再作成を行いAPIキーを作成し、APIキーをコピー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/a2147678-7e46-1c91-994b-422b5ece7250.png)

# [STEP2] テーブルを作成し、サイトIDを取得する。
[開発者向け機能：API：APIのURL](https://pleasanter.org/manual/api-url)のドキュメントより、テーブルを作成してサイトIDを取得します。IDの場所がサイトIDです。

```
http://{サーバー名}/{パス}/api/{コントローラー名}/{ID}/{メソッド名}
```

新規作成 → 記録テーブル → 作成を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/7673bb37-878a-ffb7-65f3-6f6f23bdf7f6.png)

タイトルを付けて作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/d7a40385-ebcc-aa28-282f-834103531876.png)

作成した[Restテスト]を選択し、URLの値を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/a9842f06-a239-c3d8-c7e0-fa0ef7b037c4.png)

[Restテスト]のサイトIDは10034となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/4159b1ca-0210-5d2e-73b1-5d4f97b30998.png)

# [STEP3] Postmanの設定
今回はデータの取得と登録を試します。

#### 試すAPI
* [複数レコード取得](https://pleasanter.org/manual/api-record-get-multi)
* [レコード作成](https://pleasanter.org/manual/api-record-create)

### 初期設定
ヘッダーの初期値であるContent-Typeのチェックを外し、一番下にContent-Typeを新たに追加します。
値は**application/json**を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/65210b38-9f37-812f-1fea-3c9a079f717a.png)


## [STEP4] データの取得（get）
[複数レコード取得](https://pleasanter.org/manual/api-record-get-multi)の内容から、POSTに変更してURLをgetにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/185ef80e-42c6-9742-8a16-2ad356d043d3.png)

```
http://localhost/api/items/10034/get
```

ボディ → Raw を選択し以下のように値をセット。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/cc2eb91e-f0ac-bd7b-2a1c-b27847abd07e.png)

```json
{
    "ApiVersion": 1.1,
    "ApiKey": "プリザンターで作ったAPIキーを入れる"
}
```

## [STEP5] データの登録（create）
[レコード作成](https://pleasanter.org/manual/api-record-create)の通りにデータを作る。POSTのままでURLを以下に変更。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/39ea26ab-45c7-1be4-743d-0e8737842f3a.png)

```
http://localhost/api/items/10034/create
```

JSONの値も変更する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/e96ff5ac-c7b4-3931-8ae4-2182b357c1d0.png)

```json
{
    "ApiVersion": 1.1,
    "ApiKey": "プリザンターで作ったAPIキーを入れる",
    "Title": "テストほげほげ",
    "Body": "内容",
    "CompletionTime": "2024/2/20"
}
```

送信ボタンを押した結果でステータスコード200が返ってくれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119455/7280bd05-3e3b-808d-0c58-964a5bb1fb2a.png)
【Composer】インストールから基本コマンド紹介まで

## 導入
PHPでWebアプリケーションを開発する際、純粋なPHPのみで実装するケースってほぼほぼないですよね。
なにかしらのライブラリを導入したり、フレームワーク・CMSを利用するかと思います。

そんな時に、使用するパッケージ・ライブラリのバージョン管理を行ってくれるのが**composer**です。

今回の記事ではこれさえ知っとけばどうにかなるんじゃないかという**composer**の基本コマンドをご紹介します。

## composer 本体のインストール
手順は[公式ドキュメント](https://getcomposer.org/download/)に書いている通りで恐らくスムーズ行きます。
（M2・Macでは問題ありませんでした。）

以下を順番に実行してください。
```bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'edb40769019ccf227279e3bdd1f5b2e9950eb000c3233ee85148944e555d97be3ea4f40c3c2fe73b22f875385f6a5155') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```
Globalでcomposerを利用するために、こちらも実行しましょう。
```bash
sudo mv composer.phar /usr/local/bin/composer
```

### Homebrewで一括管理
MacユーザーはHomebrewで管理してもいいですね。（**筆者は試してません**）

```bash
brew install composer
```
[Homebrew/composer](https://formulae.brew.sh/formula/composer)


## コマンド集
それではコマンドの紹介です。

と、その前にセットアップをしましょう。
### 0. セットアップ
```bash
# 1. プロジェクトディレクトリを作成します。
mkdir composer-sandbox
# 2. プロジェクトルートに移動
cd composer-sandbox
```
セットアップは完了です。

### 1. ``composer require``
とりあえずなにか入れてみましょうか。Guzzleとかがいいんですかね？
```bash
composer require "guzzlehttp/guzzle: 6.5.8"
```

恐らく、実行後に以下の「ファイル/ディレクトリ」が作成（インストール）されたのではないでしょうか？
```tree
├── composer.json
├── composer.lock
└── vendor/
```

Packageの**インストール成功ですね。**


### 2. ``composer install``
GPT的には、「composer.json に定義された依存関係をもとにパッケージをインストールします。」とのことです。
行けそうですか？とりあえずやってみましょう。

先ほど作成した``composer.json``を編集します。
```diff
{
    "require": {
-         "guzzlehttp/guzzle": "^6.5.8"
+         "guzzlehttp/guzzle": "^6.5.8",
+         "symfony/yaml": "^7.0"
    }
}
```
こんな感じですかね。

準備はOKです。
それでは、実行してください。
```bash
rm composer.lock
composer install
```

#### 少し細かい議論ですが、
※ 直接``composer.json``ファイルを調整することについては実際はあまりしないです。
``composer.lock``ファイルもgit管理することがBetterです。
- 「環境間でのpackage管理が楽になる。」
- 「大規模開発や、長期プロジェクトでのアップデートにも対応しやすい。」
- 「``rm composer.lock``は不要。」
と、思っています。

「違うよ。」があればコメントください。

### 3. ``composer update``
GPT的には、「パッケージのバージョンを更新します。composer.json のバージョン指定に従い、可能な限り最新のバージョンに更新されます。」とのことです。

### 4. ``composer remove``
インストール済みのPackageの削除を行います。
```bash
composer remove "symfony/yaml"
```

以下のように``composer.json``が書き換わったら成功ですね。
```diff
{
    "require": {
+         "guzzlehttp/guzzle": "^6.5.8"
-         "guzzlehttp/guzzle": "^6.5.8",
-         "symfony/yaml": "^7.0"
    }
}
```

## 参考

https://getcomposer.org/

https://packagist.org/


## まとめ
今回はcomposerの基本コマンドを紹介しました。

続編も執筆しましたのでよければお時間があればご覧ください。

https://qiita.com/umekikazuya/items/198ad202ccf6b46c09bb
`raspberry pi5`上で`xdotool`が効かなかった時の解決方法備忘メモ

`raspberry pi5`上で`xdotool`が効かなかった時の解決方法備忘メモです

# 準備
- [raspberry pi5](https://raspberry-pi.ksyic.com/)
- HDMI(micro) - HDMIケーブル　１本
- USBキーボード、USBマウス １個づつ
- 電源（USB-typeC接続） 1個
- 何かしらのディスプレイ

# OS imageの更新

以下を参考に、`rpi-imager`からOSイメージを更新する

> https://zenn.dev/karaage0703/articles/8fe578dba4857a
>
> ```bash
> sudo apt install -y rpi-imager
> ```

# `xdotool`が効かない...

`xdotool`が効かない...と思って色々調べていたところ、
Display設定がデフォルトでは`Wayland`になっているようなので、X11に切替える。
具体的には以下から設定する。

```
sudo raspi-config
```

`Advanced Options --> Wayland --> X11` を選択する。
設定時に再起動が求められるので再起動すればOK。再起動後に`xdotool`が効くようになりました。

https://forums.raspberrypi.com/viewtopic.php?t=364116
> Re: Using python script to run xdotool command
Quote
> xdotool does not work with the now default Wayland.
> You can use sudo raspi-config (advanced menu) to switch back to X11.

https://zenn.dev/karaage0703/articles/8fe578dba4857a

https://gigazine.net/news/20231102-raspberry-pi-5-install-boot/

# 参考

https://support.apple.com/ja-jp/guide/disk-utility/dsku365552c7/mac

https://moewe-net.com/ubuntu/mount-sd-on-ubuntu
Paper プラグインでカスタムヘッドを描画する[Minecraft]

# 環境
- Paper API : `1.20-R1-SNAPSHOT`
- JDK : `JDK 17`

:::note warn
Paper API は基本的に Spigot API と互換性がありますが、一部機能については独自の実装がされています。
そのため、本記事に掲載しているコードをそのまま使用しても動作しない恐れがあります。その場合は Spigot の公式 JavaDoc をご確認の上ご利用ください。
:::
# カスタムヘッド(Custom Head)とは?
プレイヤーの頭やゲーム内に存在するモブ以外の絵柄の頭のこと。
[Minecraft-Heads](https://minecraft-heads.com) などに多数掲載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2403016/457da152-6360-68cc-61da-d0527e54d7d2.png)

# 頭を描画するには
(実在する)プレイヤーの頭を描画するには以下のコードだけで済みます。
```java
// name = プレイヤー名を示す文字列
ItemStack head = new ItemStack(Material.PLAYER_HEAD);
SkullMeta skullMeta = (SkullMeta) head.getItemMeta();
skullMeta.setOwningPlayer(Bukkit.getOfflinePlayer(name));
head.setItemMeta(skullMeta);
```

# カスタムヘッドを描画するには
最終的に `SkullMeta#setPlayerProfile(profile);` でプレイヤー情報 (`PlayerProfile`) を SkullMeta へ登録することになります。
そのために
 - [PlayerProfile](https://jd.papermc.io/paper/1.20/com/destroystokyo/paper/profile/PlayerProfile.html) の作成
 - [PlayerTextures](https://jd.papermc.io/paper/1.20/org/bukkit/profile/PlayerTextures.html) の作成
 - SkullMeta へ情報を登録

の3段階を踏む必要があります。

## PlayerProfile の作成
PlayerProfile はプレイヤーの UUID, 名前、テクスチャなどのデータを持つクラスです。

```java
PlayerProfile profile = Bukkit.createProfile(null, UUID.randomUUID().toString());
```
`Bukkit#createProfile` より取得します。第 1 引数はプレイヤーの UUID, 第 2 引数はプレイヤーの名前を示します。
今回は実在しないプレイヤーのデータを作成するので UUID を入れておきます。
(`Bukkit#createProfile` は 2 つある引数のどちらかが null 以外であれば大丈夫なので、適宜設定してください。)

::: note info
これらの引数は画像データをキャッシュとして保存する際のキーとして、また、完成時の「~~~ の頭」というアイテム名に使用されます。
(そのため、ランダム性を持った UUID を使用することが好ましいです。)
:::

## PlayerTextures の作成
文字通りプレイヤーのテクスチャに関するデータを持つクラスです。
スキンの種類(CLASSIC, SLIM)、マント、スキンに関してのデータを持ちますが、後ろ 2 つに関しては生の画像データではなく、画像が置かれている URL になります。

---

カスタムヘッドの絵柄を指定するにはMinecraft-Heads の For Developers セクションの Value を使用するのですが、これはテクスチャが置かれている URL を含んだ json データを Base64 でエンコードしたものになります。
そのため、Base 64 でデコードしてから正規表現で URL のみを抜き出しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2403016/108560f9-f0f0-84b8-ec68-deb1258efe85.png)

```java
// urlStr = 描画したいカスタムヘッドの URL (Base64 でエンコード済み)
PlayerTextures texture = profile.getTextures();
URL url;
try {
    String prepare = new String(Base64.getDecoder().decode(urlStr));
    // {"textures":{"SKIN":{"url":"テクスチャの URL"}}}
    Matcher matcher = Pattern.compile("[\"{a-zA-Z:]+(http://[a-zA-Z0-9./]+)[}\"]+").matcher(prepare);
    if (!matcher.matches()) return;
    url = new URL(matcher.group(1));
} catch (Exception e) {
    e.printStackTrace();
    return;
}
texture.setSkin(url);
```

## SkullMeta と PlayerProfile に情報を登録する
作成した PlayerTextures を PlayerProfile に設定し、そのまま SkullMeta に登録します。

```java
profile.setTextures(texture);
meta.setPlayerProfile(profile);
head.setItemMeta(skullMeta);
```

終わりです。

# 終わりに
初めてカスタムヘッドを呼び出す際にデータを取りに行ってキャッシュを作成する時間 (1 秒くらい?) があるので、可能であればプラグインの起動時にまとめてロードさせると良いでしょう。

<br>
やり方を調べてみても海外勢が「自分のライブラリを使って！」としか言っていなかったので、1時間ほど JavaDoc とにらめっこしながら書きました。詳しく書かれているわけでもなかったのでかなり疲れました。
【イベント】Game Speed Hackathonに参加した話【雑記】

# 自己紹介
「伸びしろですねぇ！」なUnityエンジニア志望の大学生

# Game Speed Hackathonとは
Cyber Agentさん主催のオフラインイベント。詳細はリンクを確認してください。

https://www.cyberagent.co.jp/careers/students/career_event/detail/id=29603

## 内容
パズルゲームのロジックを問題を解きながら実装して、そのスピードを争うハッカソンです。

Unityを用いた競プロのような形で、Unityの知識は1ヶ月触ってれば足りると思います。

# 感想
### 率直に
**ロジック実装できないよ！！！！**
いやぁ、「CA Tech Accel」もベストチーム賞を頂き、メンターさんにも認めてもらい…めちゃめちゃUnityに関して自信ついてきたんですが全て打ち砕かれましたね。

### ちょっと言い訳
実は一度ほぼ答えと同じコードを書いていたのですが、`for`のネストが深くなりすぎてもっとちゃんとしたアルゴリズムあるはず！と思って全部消しました。

ああ、、、言わないでください。
全方位から「そんなこと気にせずとりあえず動かせ」という声が聞こえてきます。
本当にね。その時の自分に声かけてやってください。

### 学び
これまでしっかりとしたロジックを作ってこなかったこともあって`for`のネストが2回ぐらいが限度かなぁという認識でした。
しかし、こういった場合`for`も`while`も躊躇せずに使うべきという学びでした。
やはり仕方ない時は仕方ないんですね。

また、イベント終了後色々調べてみると、今まで`for`を使わずに出来ていたロジックなども実際はメソッドの中で`for`を使っていて目に見えてなかっただけということも気づきでした。
重要なのは`for`を使わないことではなく、メソッドなどに適切に分割して目に見えないようにすることという学びがありました。

# 「自分の強み」とは
今回のイベントで、ゲーム実装に置いて私の実力では全く歯の立たない分野があることが証明されました。
もちろん、アニメーションや揺れものなど全く触れたことがない部分はあるのでそこは歯が立たないと思っていました。
しかし、ロジックの実装はいわば「プログラミング」です。ずっとやってきたことなはずなのです。
それが出来ないということはとても悔しかったです。

一方で、弱点が見えたことで自分の強みにも気がつくことが出来ました。
Unityの知識は自信があるし、それを応用することには自信があります。
また、Unity的なプログラミング、`Transform`や`uGUI`などそういった"機能"を応用する力が自分の強みであることが分かりました。

## 「専門分野」と「興味分野」
今回のイベントでは懇親会があり、現役エンジニアの方と色々お話しさせてもらいました。
その際に専門分野を持つ必要はないが、興味分野を持つべきだというお話をしていただきました。

**「確かに」**

そんな感じでしたね。
その方は専門分野を持った方が良いという話もしていました。
しかし、Accelのメンターさんから専門分野を持っても就職すればもっと凄い人が必ずいるという意見を聞いていたため、どっちなんだろうとエンジニアさんにぶつけると、この返答が返ってきました。

就職した際にどの分野で活躍したいか、それは絶対に言えた方が良いということでした。

## 自分の好きな分野って何だろう？
うーん、結構なんでも好き。
でも、アニメーションとか揺れものとかそういうのはあんまり好きじゃないかも。
作っててあんまり楽しくない。

かといってグラフィックスは作るの楽しい。VFX Graphとかシェーダーは触ってて凄い楽しい。

あとは設計や最適化、基盤制作（エディター拡張の制作）も結構好き。

あれ、ほぼ好きやん。で、ひとつ気がつきがありました。

### デザイナーさん・プランナーさんと連携したい。
私は将来的にはマネジメントもやるエンジニアになりたいと思っています。
そのため、エンジニアだけでなく様々な人と関わりゲーム全体に大きな影響力のあるような人になりたい。

これは今課外活動でリーダをしていてマネジメントやチーム作りなどにも力を入れている自分の強みを活かせると思います。
分かる人にしか分かりませんが「CirKit（リーダーをしている団体名）のリーダーと趣味のUnityを1つにしたような立ち位置」が私のベストな立ち位置だと思いました。

なんだが、技術的な話から相当遠ざかってしまいました。
でも、これが「技術だけじゃない！」これが自分の強みでありその正解だと思います。

## 今後
もちろんエンジニアですから技術は必要です。
今回弱点に気がついたのを放置しているわけにはいきません。
今、エディター拡張を作っているためこの製作を終わらせたら、オセロ・将棋この２つを作ってみようと思います。
これでロジックの苦手意識を克服していきたいですね。

# さいごに
だいぶ「Game Speed Hackathon」の話からはそれてしまいましたが思ったことを率直に書きました。
またイベントの詳細を書くと、大人から怒られかねないのでまぁこんな感じになりますね。
Tech Accel中は次自分のなにを伸ばせばいいんだろうと思ってましたが、最近いくらでも思いつきます。

https://twitter.com/KaidoAtsuya/status/1758157950722744503

https://twitter.com/KaidoAtsuya/status/1758776516958409184

自己分析も進めて興味分野も決めたいですねぇ。
では、また。。。最強になります。
【AWS CLF】AWS Certified Cloud Practitioner 合格体験記

# 概要
AWS Certified Cloud Practitioner (CLF-C02) に知識ゼロの状態から合格したので、合格までの道のりやもっとこうしておけばよかったと感じていることを記録します。

# 受験までの勉強
- インプット
    - 書籍
    『AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー』(https://www.sbcr.jp/product/4797397406/)
    定番書籍。受験を決めてからすぐに購入しましたが、個人的にはあまり使用しませんでした...
    マネジメントコンソールの画像なども使用して細かな部分まで解説されているため、詳細まで理解したい人にはお勧めです。
    合格さえできればいいという方は購入しなくてもいいかなと思います。
    - 動画
        - AWS Skill Builder（公式）
        https://explore.skillbuilder.aws/learn/course/external/view/elearning/1875/AWS-Cloud-Practitioner-Essentials-Japanese-Na-日本語実写版
        網羅的に説明されています。たとえ話なども多く、AWSの概念やサービスについてほとんど知らない状態からでも入りやすいと思います。初心者なら見ておくべき一本ではないでしょうか。
        - YouTube
        https://youtu.be/ELVAXUVFZaM?si=Bp_qe87QvOA7E6zg
        Skill Builderは文章を読んだり画面操作をしたりする必要がありましたが、YouTubeなら流しっぱなしにできるので手が離せないときのインプットとして利用しました。CLF-C01の対策動画ということもあり、すべての内容を網羅しているとは言えないかもしれませんが、各サービスについての理解が深まりました。
- アウトプット
    - Web問題集
        - Cloud License (https://cloud-license.com/exam/clf/)
        有料です。4080円で90日間の制限付きでした。あまり本気になっていない時期に購入してしまったので十分には使用できませんでしたが、問題数・解説・機能など充実していたように思います。
        - AWS認定資格 無料WEB問題集＆徹底解説 (https://aws-exam.net/clf/)
        無料です。Cloud Licenseの期間が終了してから利用していました。400問程度あり、1周した後に間違えた問題を復習して、再度1周しました。
    - Udemy
    https://www.udemy.com/course/aws-4260/
    セール時に1200円で購入しました。基本レベルと本番レベルがありましたが、実際の試験は基本レベルの少し上程度のレベル感でした。
    - 公式練習問題
    https://explore.skillbuilder.aws/learn/course/external/view/elearning/16792/aws-certified-cloud-practitioner-official-practice-question-set-clf-c02-japanese
    20問しかありませんが一応公式の問題を解いておこうと考えました。
- その他
    - クラウド導入フレームワーク（CAF）の暗記
    CAFに関する出題が一定数あるという口コミを見たので、前日に各パースペクティブの機能を暗記して行きました。

# 今から最短で勉強するなら
1. AWS Skill Builder の動画を1回見る
[AWS Cloud Practitioner Essentials (Japanese) (Na) 日本語実写版](https://explore.skillbuilder.aws/learn/course/external/view/elearning/1875/AWS-Cloud-Practitioner-Essentials-Japanese-Na-日本語実写版) (6h)
1. 問題集でアウトプットする
[AWS認定資格 無料WEB問題集＆徹底解説](https://aws-exam.net/clf/) で解説も読みながら400問の9割程度正解できるようにする。（問題演習が足りないと感じたらUdemyも）
1. クラウド導入フレームワーク（CAF）の各パースペクティブの機能の暗記

最短とは言えないかもしれませんが、知識0から理解した上での合格を目指すのならこの程度の勉強は必要ではないかと思います。

# まとめ
以上、AWS初学者による AWS Certified Cloud Practitioner (CLF-C02) 合格体験記でした。
最後までご覧いただきありがとうございました。どなたかの参考になれば幸いです。
クリーンアーキテクチャ個人的まとめ（Ⅲ部）

## クリーンアーキテクチャⅢ部
### 個人的概要
- SOLID原則
    関数やデータ構造のクラスへの組み込み、クラス間の相互接続のルール
- SOLID原則の目的
    以下の性質を持つモジュールの構造を作る事
    - 変更に強いこと （ = 拡張性）
    - 理解しやすい事（ = 可読性）
    - コンポーネントの基盤として，多くのソフトウェアで利用できる事（ = 汎用性）
- 5つの原則
    - 単一責任の原則
    - オープンクローズドの原則
    - リスコフ置換の原則
    - インターフェース分離の原則
    - 依存関係逆転の原則

### ポイント
SOLID原則の5つの項目
- 単一責任の原則
    モジュールはたった一つのアクターに対して責任を負うべきである
    （モジュールの変更理由は１つだけになるようにするべし。）
- オープンクローズドの原則
    完成された既存の成果物を変更せずに拡張できるようすべきである
- リスコフ置換の原則
    クラスを継承する時、継承先と継承元の振る舞いは同じである
    （異なる振る舞いのものは継承先に混ぜない）
- インターフェース分離の原則
    必要としないモジュールに依存しないようにインターフェースは切り分けること
    （変更した内容と関係ない部分もデプロイ、コンパイルしないようにすること）
- 依存関係逆転の原則
    変化しやすいモノには依存しないこと
    （ビジネスルールが含まれるような内容は変化しにくい抽象的なものに依存すること）