OmniAICreator/Qiita-1.07M huggingface dataset:
【Angular】Angular 18 アップデートで HttpClientModule たちが provideHttpClient に置き換わる

前回、記事を書いていて、
マイグレーション個別に取り上げた方が記事として読みやすそうと思ったので、今回は内容を絞ってお届けする。

https://qiita.com/shin_moto/items/b68ef3c78cbbd74eff08

というわけで、Angular 18 にアップデートする際、実行されるマイグレーションの一つに、`HttpClientModule`たちが `provideHttpClient` に置き換わる、というやつがあるので紹介する。

https://github.com/angular/angular/tree/main/packages/core/schematics/migrations/http-providers

文字通り `HttpClientModule` `HttpClientXsrfModule` `HttpClientJsonpModule`　たちは非推奨となるので、`provideHttpClient` `withJsonpSupport` `withXsrfConfiguration`に置き換わるという内容。
XsrfModule とか JsonpModule とかそもそも使ったことねえなあ、という感じではある。

- HttpClientModule
  - https://v17.angular.io/api/common/http/HttpClientModule
- HttpClientXsrfModule
  - https://v17.angular.io/api/common/http/HttpClientXsrfModule
- HttpClientJsonpModule
  - https://v17.angular.io/api/common/http/HttpClientJsonpModule
- provideHttpClient
  - https://angular.dev/api/common/http/provideHttpClient
- withJsonpSupport
  - https://angular.dev/api/common/http/withJsonpSupport
- withXsrfConfiguration
  - https://angular.dev/api/common/http/withXsrfConfiguration

## Http Modules

### Before
```ts
import { HttpClientModule, HttpClientJsonpModule, HttpClientXsrfModule } from '@angular/common/http';

@NgModule({
    imports: [CommonModule, HttpClientModule, HttpClientJsonpModule, HttpClientXsrfModule]
})
export class AppModule {}
```

### After
```ts
import { provideHttpClient, withJsonpSupport, withXsrfConfiguration } from '@angular/common/http';

@NgModule({
    imports: [CommonModule],
    providers: [provideHttpClient(withJsonpSupport(), withXsrfConfiguration())]
})
export class AppModule {}
```

## Testing
`HttpClientTestingModule`は`provideHttpClientTesting()`へと置き換わるようだ。

- HttpClientTestingModule
  - https://v17.angular.io/api/common/http/testing/HttpClientTestingModule
- provideHttpClientTesting
  - https://angular.dev/api/common/http/testing/provideHttpClientTesting


### Before
```ts
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('some test', () => {

    it('...', () => {
      TestBed.configureTestingModule({
        imports: [HttpClientTestingModule]
      })
    })
})
```

### After
```ts
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';

describe('some test', () => {

    it('...', () => {
      TestBed.configureTestingModule({
        providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
      })
    })
})
```
これらは動作的には互換性があり、非推奨になっている API たちはまだ削除されてないっぽいけど、これを機に置き換えておくと良さそうですね。
TailwindCSSをJITモードで使ってみる

# JITモードとは？
Just In Time（ジャストインタイム）の略で以下のようなメリットがあります。
- ブラウザのパフォーマンスが向上する
- variant（擬似クラス）を組み合わせて使える
- 任意の値でクラスを使いやすい

### JITモードを有効にする
tailwind.config.jsに`mode: 'jit'`を追記するだけで有効にできます。


 ```tailwind.config.js
  module.exports = {
   mode: 'jit',
    purge: [
      // ...
    ],
    theme: {
      // ...
    }
    // ...
  }
  ```

:::note warn
TailwindCSSのversion3系は、JITモードがデフォルトで有効になっています。
version2系を使っている人は上記のモード指定が必要です。
:::

### ブラウザのパフォーマンスが向上する
デフォルトでは10万行くらいあるファイルを読み込んでいるため、ブラウザからするとこの膨大なファイルを読み込むのはかなり重い作業でした。
JITモードでは使っていない不要なスタイルを削除してくれるのでファイルサイズが最小限になり軽くすることを実現してくれるみたいです。

### variant（擬似クラス）を組み合わせて使える
variantとは、:hover、:focus、:activeみたいなやつです。
今までは、**hover:bg-red-500**のように単体でしか使うことが出来ませんでした。
しかしJITモードでは、これを組み合わせて使うことが出来ます。
`<div class="text-blue-500 md:hover:bg-red-500">おはようございます</div>`
この場合は、画面幅がmd以上（768px）かつ要素がhoverされた時にbgがredになるということです。
このようにvariantを組み合わせることによって柔軟にCSSを適用することが出来ます。

### 任意の値でクラスを使いやすい
従来のtailwindcssでは、事前に定義されたクラスしか使用できませんでした。
**mt-113px**などの用意されていない任意の値を使う場合は、tailwind.config.jsに追記して設定する手間があり、若干めんどくさいです。
しかしJITモードでは、わざわざ設定ファイルに必要なクラスを追加する必要は無く、角括弧を使ってその場で定義することが出来るので、柔軟性が上がります。
`<div class="w-[111px] mt-[113px] mb-4"></div>`

### おわりに
最近、TailwindCSSのversion3系を使っていて、JITモードが自動的に適用されていることに気づきました。アップデートにより標準でJITモードが有効になっているみたいです。
まだ、TailwindCSSのversion2系を使っている人は、version3系にアップデートするかJITモードを有効にして使ってみてはいかがでしょうか :D
AWS Certified Solutions Architect - Professional (SAP-C02) 合格体験記

# 概要

2024年6月にAWS Certified Solutions Architect - Professional (SAP-C02) に合格したので、私が実施した学習内容を共有します。

# 自己紹介

- **氏名**　：あまるね
- **趣味**　：Youtube, ゲーム(PC, Switch)
- **出身**　：北海道(今は愛知)
- **職歴**　：とあるSIerの3年目社員。アジャイル/クラウド/UIUX領域に挑戦中

昨年度にAWS SAA, DVA, SOAを取得済みです。

# **AWS Certified Solutions Architect - Professional (SAP-C02) とは**

> 複雑な問題に対する複雑なソリューションの提供、セキュリティ、コスト、パフォーマンスの最適化、および手動プロセスの自動化における高度な知識とスキルを証明するために役立ちます。この認定は、組織がクラウドイニシアティブを実施するための重要なスキルを備えた人材を特定して育成するための手段です。
> 

[AWS](https://aws.amazon.com/jp/certification/certified-solutions-architect-professional/)より

Solutions Architectの中では最上位の資格です。

また、対象はAWS でのクラウドアーキテクチャの設計とデプロイにおいて 2 年以上の実践的な経験を持つ方を対象にしている資格です。

# 学習

実務+演習問題の周回で合格することができました。

## 実務

（身バレ防止のためふんわり）

主にネットワークなどの低レイヤーからサーバレスまで一通り整備する役回りです。

Organizationsやオンプレ-クラウドの接続はあまり経験がありませんので、文字上の知識のみです。

## 演習問題

CloudTechさんの問題集(300問)を3か月で4周しました。時間にすると50時間ほどなので、だらだらと取り組んでしまったのは反省です。。。

# 試験当日

試験は180分で75問解くもので、オンラインで受験しました。

1問2~3分で解く必要があるので、長文の多いSAPでは時間配分を気にしつつ解く必要がありました。

以下、私が気を付けたポイントです。

- あるあるアーキテクチャを問われる問題(例：lambda+RDS → RDSProxy)は、すべて読まずキーワードと選択肢を見て即答。
- 長考が必要な問題は見直しフラグを立てて飛ばす。
- 少し自信がない場合も見直しフラグを立てる。
- 不正解を考えて選択肢を絞る。
- 都度、ペースが十分か残り時間を確認する。
- 一周後見直しフラグが立っているものを見直し
- 少し時間(20分ほど)が余ったので前の設問から順次見直し。

# おわりに

AWS SAPの学習内容を共有してみました。今後受ける方の参考になれば幸いです。

資格取得でもクラウドに関するご相談でもその他でも、Xで気軽に絡んでくれたらうれしいです。
Windowsでフォルダ同期を簡単に設定する

とある事情でWindows 11環境であるフォルダを別のフォルダに定期的に同期する必要があったため、簡単に実現する方法がないかを調査した。

### 結論

以下のバッチファイルを作成して、タスクスケジューラで定期実行するように設定すればよい。

```cmd
robocopy <コピー元> <コピー先> /COPY:DATSO /MIR /EFSRAW /NP /V /R:1 /W:1 /IT /LOG+:%~dp0\log.txt
```

### 参考

下記のサイトの解説がとてもわかりやすい。上記のバッチファイルでは、一般ユーザーの権限で実行できるように、いくつかのオプションを変更している。

* [robocopyを試してみた!(実践編) - Sight-R（サイタル）](https://sight-r.sts-inc.co.jp/infrastructure/robocopy-execution/)
Laravel開発でPHP Unit使ったテストをしよう

# はじめに
LavavelでPHP Unitを使ったテストのやり方について記載してみました。

## 前提
- Laravel 11を用いる
- ユーザモデルに対する以下の機能について基本的なテストを作成する
    - 新規登録機能（`/users/store`）
        - ログインを必要とする
        - ユーザ名とメールアドレスで登録する
        - 登録成功後は一覧画面（`/users`)にリダイレクトする
    - 一覧表示機能（`/users`）
        - ログインを必要とする
        - 登録したデータを一覧表示する 

## テスト実施
### テストケースクラスの作成

まずはテストケースを作成します

`php artisan make:test Http/Controllers/UserControllerTest`

UserControllerTestに対するテストとして作成を行いました。


実行すると`tests/Feature/Http/Controllers/UserControllerTest.php`が作成されます。

### テストコードを書く

```php:tests/Feature/Http/Controllers/UserControllerTest.php
<?php

namespace Tests\Feature\Http\Controllers;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class HogeControllerTest extends TestCase
{
    public function test_index(): void
    {
        // テスト用にユーザーを作成
        $user = User::factory([
            'name'  => 'テスト太郎',
            'email' => 'hoge@example.com'
        ])->create();

        // ログイン
        $this->actingAs($user);

        // テスト対象のURLにアクセスさせる
        $response = $this->get(route('users.index'));

        // 　テスト検証
        $response
            ->assertOk()                     // レスポンスに問題がないか
            ->assertSee('hoge@example.com'); // 一覧に指定したメールアドレスが表示されているか
    }

    public function test_store(): void
    {
        $data = [
            'name' => 'テスト太郎',
            'email' => 'test@example.com',
        ];

        // テスト対象のURLにアクセスさせる
        $response = $this->post(route("users.store"), $data);

        // 　テスト検証
        
        // 登録後のリダイレクト先が正しいか
        $response->assertRedirect(route("users.index"));

        // 登録データがDBに保存されているか
        $this->assertDatabaseHas(User::class, $data);
    }
}

```


### テストを実行する

今回は作成したファイルのテストだけを実行することにします。

`php artisan test tests/Feature/Http/Controllers/UserControllerTest.php`

```
$ php artisan test tests/Feature/Http/Controllers/UserControllerTest.php

   PASS  Tests\Feature\Http\Controllers\UserControllerTest
  ✓ index                                                        0.41s  
  ✓ store                                                        0.04s  

  Tests:    2 passed (4 assertions)
  Duration: 0.49s


```










# まとめ

LaravelにはPHP Unitが初めから導入されています。
せっかくなのでテストコード書いて、開発に役立ててみましょう。

# 参考
https://zenn.dev/nshiro/books/laravel-test-from-beginner/viewer/post-store

# 告知
最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを
募集しております。詳しくは採用情報ページをご確認ください。

https://eda-inc.jp/recruit/

みなさまからのご応募をお待ちしております。
Playwrightのインストール方法

# 事前準備

## Node.jsのインストール
以下のリンクを参考にNode.jsをインストールする

https://qiita.com/ryome/items/eec08b28aff294e8c3d6

# Playwright Testのインストール

## コマンドラインでPlaywright Testをインストールする
コマンドラインで以下のコマンドを実行して、Playwright Testをインストールします

```bash:コマンド
npm init playwright@latest
```

## ブラウザのインストール
- Playwright Testでは、Chromium、Firefox、Webkitの各ブラウザをテストに使用できます。
- 必要なブラウザをインストールするには、以下のコマンドを実行します

```bash:コマンド
npx playwright install
```

## テストコード作成
- テストコードを作成するには、以下のコマンドを実行します

```bash:コマンド
npx playwright codegen [URL]
```

- 以下のようにURLを指定して実行します

```bash:例
npx playwright codegen http://localhost:3000
```

- コマンドを実行後、画面操作を行うことで以下のようにテストコードが生成されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/fc8dde73-3954-460c-4b35-4eb0c45a7a80.png)

## テストの実行
- テストを実行するには、以下のコマンドを使用します

```bash:コマンド
npx playwright test
```

## テストレポートの確認
- レポートを確認するには、以下のコマンドを実行します

```bash:コマンド
npx playwright show-report
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/01bf355d-20ad-1da9-a2d4-1a33c1023857.png)
ComposeMultiplatformのチュートリアルをしてみる　〜その１〜

先週にComposeMultiplatformでプロジェクトを作成したのでチュートリアルを行い、理解を深めていきたいと思います。

# 前回

https://qiita.com/yuta317/items/6eede37a48830c9247dd

# 今回のチュートリアル内容ページ

https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-modify-project.html


# チュートリアル内容
日付を表示する実装みたいです。


`composeApp/build.gradle.kts`プロジェクトへの依存関係として追加します。


![スクリーンショット 2024-06-30 19.38.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/2e0f250e-dc58-fcc6-228e-7fc3cda98c3f.png)


```diff 
commonMain.dependencies {
    implementation(compose.runtime)
    implementation(compose.foundation)
    implementation(compose.material)
    implementation(compose.ui)
    implementation(compose.components.resources)
    implementation(compose.components.uiToolingPreview)
+    implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
}
```

`App.kt`ファイルに関数を追加します。
```App.kt
fun todaysDate(): String {
    fun LocalDateTime.format() = toString().substringBefore('T')

    val now = Clock.System.now()
    val zone = TimeZone.currentSystemDefault()
    return now.toLocalDateTime(zone).format()
}
```

チュートリアルと場所は違いますが、私はこちらにテキストを追加いたしました。
```diff
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
    Image(painterResource(Res.drawable.compose_multiplatform), null)
    Text("Compose: $greeting")
+   Text(
+       text = "Today's date ${todaysDate()}",
+       textAlign = TextAlign.Center
+   )
}
```
実行してみます。

![Simulator Screenshot - iPhone 15 - 2024-06-30 at 19.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/a38cfd48-fa91-8820-cbca-e0fe60e2d6bc.png)

このように日付が表示されました。

# 時間の表示もしてみる！

チュートリアルに無いですが、時間も表示してみようと思います。

こちらの関数を追加しました。
```App.kt
fun currentTime(): String {
    val now = Clock.System.now()
    val zone = TimeZone.currentSystemDefault()
    return now.toLocalDateTime(zone).hour.toString() + "時" +
            now.toLocalDateTime(zone).minute.toString() + "分" +
            now.toLocalDateTime(zone).second.toString() + "秒"
}
```

表示用のテキストを追加します
```diff
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
    Image(painterResource(Res.drawable.compose_multiplatform), null)
    Text("Compose: $greeting")
    Text(
        text = "Today's date ${todaysDate()}",
        textAlign = TextAlign.Center
    )
+    Text(
+        text = "Time ${currentTime()} ",
+        textAlign = TextAlign.Center
+    )
}
```
実行してみます。

![Simulator Screenshot - iPhone 15 - 2024-06-30 at 20.00.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/4484a929-73e3-7a61-58d7-3241a13e3e3f.png)


このように時間も表示されました。

時間や日付はOSごとの実装が必要だと思っていましたが、`kotlinx-datetime`ライブラリがあり、こちらを使用して実装できることに驚きました。
マイグレーションでNO FILEが表示された時の対処法

### マイグレーションファイルの確認
現在の状態を確認する。
```
$ rails db:migrate:status
```

この時以下のようにupになっているNO FILEが表示されている場合の削除方法。

```
Status   Migration ID        Migration Name
--------------------------------------------------
  up     xxxxxxxxxxx    ********** NO FILE **********
```

---

### 削除手順
1\. ダミーファイルの作成
Migration IDをコピペし、ダミーファイルを作成する。
最終的に削除するのでファイル名は適当でOK。
```
$ touch db/migrate/xxxxxxxxxxx_hoge.rb
```

2\. Migration Nameの確認
`$ rails db:migrate:status`を実行し、NO FILEになっていたファイルに上記で設定したファイル名が付与されていることを確認する。
```
Status   Migration ID    Migration Name
--------------------------------------------------
  up     xxxxxxxxxxx     Hoge
```

3\. down状態にする
```
$ rails db:migrate:down VERSION=xxxxxxxxxxx
```

`$ rails db:migrate:status`を実行しStatusがdownになっているか確認。
```
Status   Migration ID    Migration Name
--------------------------------------------------
 down     xxxxxxxxxxx     Hoge
```

4\. マイグレーションファイルの削除
```
$ rm db/migrate/db/migrate/xxxxxxxxxxx_hoge.rb
```

5\. `$ rails db:migrate:status `を実行し、削除できているか確認。
開発チームで読書会を開いた話。

備忘録です。

## 概要
4~6月にかけ隔週で計5回のラーニングセッション(以下「LS」表記)を行いました。
- 時間は1回につき1時間
- 事前にページの範囲を決めて読んでくる
    - 9章構成だとすれば3章ずつくらいといった感覚でページ数を決めていました
- 意見や感想を各自miroに付箋で書き出しておく
    - 書き出すツールは本当に何でも大丈夫です◎
- LS当日、付箋をもとに意見を交わす

本の内容については、ぜひ各自で読んでいただけたらと思います。

## 選書
### 1冊目　UIデザイン必携
「デザインにも強いチームになりたい。」というのが通期に渡り自チームの目標でした。
とは言っても6人中4人はデザイン初心者のチームです。
そのため、チームでデザインを考えたり互いのデザインをレビューしたりするための第1段階として
- デザインの基礎知識を全員が得ていること
- デザイン知識がチーム内で共通化されていること

が求められていました。
#### LS前後での変化
- デザインレビューの質が向上した
    - 単純に意見の数が増えました
    - 「ここに『決定』ボタンっておかしくない？」というように、デザインの違和感に気づくようになりました
- 一つ一つの要素や配置等に対して理由づけができるようになった
    - なんとなく作成するのではなく「このような理由でこのデザインにしました」と言えるようになりました

意見共有会というよりは、デザインにおける要点の擦り合わせ、デザイン勉強会の側面が強かったと思います。
(というより、2冊目の本が「本来のLSの側面を成していない」と表現した方が正しい気がしています...^^;)
#### 結果
チーム全員がデザインをするための第1段階を突破できました。


### 2冊目　イノベーション・オブ・ライフ
LSで「人生設計」「働き方」のような内容の本を扱ってみてもいいんじゃないかという話から選書されました。
文中いくつかの問いが課せられており、それに対する意見は三者三様でした。
内容が内容なので、大変個人の思想に偏っていました。
正直「チームで読む本ではなかったかも...」というのが総意です。
ただ、その中でも「人生観について」意見を交わすという時間は、それはそれで面白く充実した時間だったように思います。
「人生観」に共通の明確な答えがあるわけないので、実際LSの進行は非常に難しかったのですが、面白かったというのもチームの総意でした。
互いの価値観を共有するという点に関しては、もしかしたらチームビルディングの部分でいくらか役立つかもしれません。
#### LS前後での変化
すぐに変化が表れるような内容ではないかな...自分自身の今後に期待です！
####  結果
LSの本来の目的である「チームの学習共有」という側面はないものの、個人的には今後の人生について深く考える良い機会になりました。
また他人の人生観に触れることで、新たな視点で自身の人生観について考えられたように思います。

## まとめ
個人的にはどちらの本も学びが多く、やってよかったように感じています。
「チームで」を考えると選書って難しいというのが本音ですが、意見を交わすという時間自体はチームとしても大変有意義な時間でした。
ぜひみなさんの開発チームでも読書会を開いてみてはいかがでしょうか？
その配色、イケてる？

# はじめに
配色あるある「せっかく色置いたのになんか違う~泣」
先月、この壁に10回近くぶち当たりました。ぜひ解消したいですね。

でも「配色ってセンスなんじゃ？」と不安に思う方もいるかもしれません。

実はそんなことないのです。
配色には、誰でも「これさえ知ってれば失敗しない」という一定の規則があります。
改めてデザインにおける配色のノウハウについて学んでいきましょう。

# 配色のメリット
配色を上手く活用することで、ユーザーの視認性を高められます。
視認性の悪いサイトはユーザーの認知負荷が高くなってしまいます。
ユーザーがWebサイトを見てすぐに情報を理解できることが望ましいため、そのためにも配色を工夫する必要があります。

# これができたら大丈夫◎
## 色による負荷を避ける
### 3色にしぼる
色数が多いと人間の脳に負荷がかかってしまいます。
デザインにおいて重要なことはユーザーに伝えたい情報が伝わることです。
色数が多い状態は、脳が処理するために負担がかかります。

無駄な情報による認知負荷を避けるために、基本的に色数は3色にしぼった方が効果的です。
3色にしぼった時、色の割合も工夫するとより良い配色になります。
ベースカラー、メインカラー、アクセントカラーをそれぞれ70%、20~25%、10~5%で置くだけでもグッと手慣れ感が出ます。

### 色の差分を作る
「似たような色を使ったらなんかパッとしないな~」「この色の組み合わせ、目がチカチカする...」
配色の最大の難所ではないでしょうか。
そうならないために、色の関係性や性質を押さえることが重要です。
####  純色を避ける
純色とは色相環の中で最も彩度が高く、白や黒の混じっていない色のことです。
純色は目への負担が高いため、使うときは他の色とのバランスが大事になってきます。
#### 明度に注意する
明度が対極にある色どうしを組み合わせると、強調したいものを目立たせられる効果があります。
そのため明度のコントラストを考慮することは非常に重要です。
一方で目への負担が高くなることも避けて通れません。
明度のコントラストを意識しつつ、明度が極端にかけ離れている状況は避ける必要があります。

※明度が対極にあると目立つので、一瞬で注意を引きたい時には非常に効果的です。
黄色(純色の中で最も明度の高い)×黒は注意看板とかにもよく使用される良い例ですね。
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576253/5990210f-cc7c-4cd7-5f00-5d9f3de2f6d9.png">

#### 色相を変えない
まだ明度の話は続きます。
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576253/f3ce0806-d14d-d6ea-da2d-c4dd24015e7c.png">
みなさんはこの違和感に気づきますか？
実は、この画像色相の違う青を組み合わせています。
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576253/f7300d82-f6d5-cb97-5f45-50b82a3b8eb9.png">
2枚目の画像を用意しました。
1枚目から明度は変更させていません。
色相を変えないことで「同じ青色のはずなのになんか変に感じる...」をなくすことができます。
これが明度差を出したい時の最後のポイントです。

同時にぜひ「明度は高く、彩度は弱く、色相は変えずに」を意識してみてください。
簡単に元の色より弱い色を作ることができます。

#### グレースケールにする
これは配色を確認する時の簡単なコツです。
有彩色をそのまま確認するより、グレースケールで確認する方が色のメリハリが確認しやすくなります。
「なんか見にくいな...？」を感じたら、ぜひ一度試してみてください。
(グレースケールへの変更はPhotoshopやCLIP STUDIO PAINTなどのソフトで簡単に行えます。スマホでもできるみたいなので、ぜひご自身の作業環境に適した方法で試してみてください。)


# 参考記事
- [エンジニアでも知っておきたいデザインの基礎知識](https://qiita.com/laineus/items/c43d302e974380993fca)
- [非デザイナーのための、ちょっと得する「色」のこと](https://qiita.com/watoson3/items/fcf62479557f74e6d325)
- [色彩検定１級が教える 🎨 カラーユニバーサルデザイン](https://qiita.com/azukisiromochi/items/0c399b85e528ced3d09a#%E8%AD%98%E5%88%A5%E3%81%97%E3%81%AB%E3%81%8F%E3%81%84%E8%89%B2%E7%9B%B8%E3%82%92%E6%8A%8A%E6%8F%A1%E3%81%99%E3%82%8B)

参考記事ではありませんが、下記の記事も非常に勉強になったため共有します。
もっとツールや数値で配色を考えたい人向け。
→[エンジニアが知っておきたい色についてのお話](https://qiita.com/megumu-u/items/554f3e9f8950ddddb03a)
戻り作業を防ぐために

# はじめに
戻り作業は未然に防げるなら防いでおきたいですよね。
そこで普段心掛けていることをまとめてみたいと思います。

# よくある戻り作業の原因

私の経験だと大体これかなと思います。

- 認識のずれ
- 確認不足
- いつもと違うことをする

# イメージを合わせよう

完成物、やることなど自分の頭の中でイメージしているものを可能な限り言語化して相手に伝えています。
言語化できていない場合は分かっているつもりになっているかもしれません。経験の豊富な人はこの言語化までに時間がかからない印象です。

# 途中経過をデイリーで伝えよう

随時テキストベースでも報告する試みをしていた時期があったのですが、報告相手が忙しい方だと内容は高確率で伝わっていませんでした。デイリーを有効活用して音声ベースで伝えるように心掛けています。

# いつもと違う状況の際は細心の注意を払おう
いつもと違う方が作業をした、いつもと違う手順で作業をした、などは見たことないエラーが出やすかったりしますので、いつもと違うところを探すようにしています。
ChatGPT×VSCode×StreamDECKが最強の自動化かも

# 結論
StreamDECKアプリのマルチアクション機能を使えば
エンジニアなら誰もが行う面倒な一連の動作が<font color="Red">**ボタン１つ**</font>に
開発スピードは<font color="Red">**筆者体感5倍**</font>に
* GPT起動からプロンプトを記載し生成
* VSCodeのローカル環境ビルドから```http://localhost/```へのアクセス
* 気になったワードのGoogle検索

色んな自動化を試すのが好きな効率厨ですがこの機能は今一番おすすめなので、まだ導入されてない方の目に触れたら嬉しいです
# 0.StreamDECKアプリとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/da3ef01b-2791-bf50-7fa7-88389a987ec1.png)
有名なのはクリエイターの中で人気のテンキーがついたデッキ版です。アプリ起動などを登録しておくと手元のボタンですぐ操作できます


https://www.elgato.com/jp/ja/s/stream-deck-mobile

今回はこちらの**アプリ版**を使って本当に便利なシステムを組んでいきます！

![スクリーンショット 2024-06-30 17.20.11.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/7a0618df-362c-b86b-f17f-980c103a9672.jpeg)
筆者の実際の操作画面がこちら。ここから１つ１つを紹介します！
まだ無料枠なので6個ですが、便利すぎるので永久版購入予定です
# １. GPT×StreamDECK

### <img width="60" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/2c9f6233-100b-bd37-96a9-c77f6211d1ca.png">　エラー文章をGPTに渡して解決策を提案してもらう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/991f7b7d-b9c9-12b0-e91a-f4ccd75c55f9.png)

:::note info
上添付の設定の通り、コピペ→立ち上げ→いつものプロンプトを追記→生成・・・
までをボタンひとつで出来るようになりました！
:::
定型分のプロンプトを書き溜めて、それもコピペされている方でしたらかなりの時短になります。自動で行うと本当に早く汎用性のある設定です。


### <img width="60" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/6018b022-f502-49eb-6ba2-72efbccd4e50.jpeg">　英文をGPTに渡して翻訳してもらう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/0e40961b-feac-b8f6-a49b-1a6bb6f2f05d.png)

### <img width="60" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/3c2c81a4-640b-ceb9-a614-75732410e5e2.png">　なんでもOK!選択した文字をGPTに渡して、聞きたいことをその場で追記する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/256f247c-658a-59e1-9303-3402dcced261.png)
こちらは敢えて最後に自動でEnterが押されない設定にして、その時に好きなプロンプトを追記できるように用意したボタン

# 2. VSCode×StreamDECK

### <img width="60" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/9fb200b4-e50b-bf23-96e6-d464b162e35a.png">　開発中にローカル環境でビルド```http://localhost/```にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/3a092072-4a2f-e841-c80a-a61483552df1.png)

:::note warn
先に立ち上げていたターミナルのクリア```http://localhost/```へのアクセスを行ってくれるのが地味に便利！
:::

私の環境だとすでに起動しているターミナルがあると閉じる操作がこれまで必要だったので、全ての操作を組み込みました
ターミナルを閉じるコマンドは難しかったので簡単なものにカスタムしています

# 3. Google×StreamDECK

### <img width="60" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/213698a6-8f02-dcfc-4dd1-127b77a07e56.png">　選択している文字をGoogle検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790276/4594ac65-1e00-97d1-43b3-9cd10f095a96.png)
気になった文字を選択した状態でボタンを押せば自動でぐぐってくれます


:::note info
1日に何度も行うGoogle検索がボタンひとつに
:::

# 最後に
最後まで読んでいただきありがとうございます！
今回は開発に便利な設定をしてみましたが、汎用性が高そうなのでもっと便利な設定が見つかったら追記しようと思います。
エンジニアは開発意外にいかに頭を使わないようにするかが開発に注力する大事だと思い毎日頑張っています。
アイコンは自作したものに設定しているだけなので、お好みにカスタマイズ可能です！
もっと便利な方法があれば教えてもらいたいです。
まだ特に何もされていない方は、この記事が少しでも参考になれば嬉しいです！

本記事はQmonus Value Streamの投稿キャンペーン記事です。
Calamares を試してみる

Calamares を試してみる

# 環境

- Debian Testing (Debian 13 ： 2024/6/30 時点 )


# インストール

デスクトップ環境にインストールしたらどうなるかな?

```

# apt install calamares

```

インストール後、メニューには出てくるけれど、選択しても特に変化ありませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7398d8be-697c-b0fb-6a33-2ee5b88e64cb.png)


CUIで見るとこのようなエラー

```
QSocketNotifier: Can only be used with threads started with QThread
19:08:58 [1]: static Calamares::Settings* Calamares::Settings::init(bool)
    ERROR: Cowardly refusing to continue startup without settings. 
     "/etc/calamares/settings.conf" 
     "/usr/share/calamares/settings.conf" 
19:08:58 [1]: static Calamares::Settings* Calamares::Settings::init(bool)
    ERROR: FATAL: none of the expected configuration file paths exist. 
```

何か追加設定が必要らしいですね。

先のメニューの下の方に「ソフトウェア」のインストール候補にあるのでそれを選んでみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7398d8be-697c-b0fb-6a33-2ee5b88e64cb.png)

インストールして、「開く」とすると Debian のインストーラが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/959468d9-2434-fe30-aa9c-fe9dff2dc39b.png)

パッケージ何が必要だったのかな?
```

# apt list --installed | grep calamares

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

calamares-settings-debian/testing,now 13.0.6-1 all [installed]
calamares/testing,now 3.3.7-1+b1 amd64 [installed]
```

一旦ソフトウェアマネージャから削除して、calamares 関連のパッケージを調べてみます。


```
# apt-cache search calamares
calamares - distribution-independent installer framework
calamares-extensions - Mobile module for Calamares installer framework
calamares-extensions-data - Mobile module for Calamares installer framework - data files
calamares-settings-debian - Debian theme and settings for the Calamares Installer
calamares-settings-mobian - Calamares branding and configuration for Mobian
libkpmcore-dev - KDE Partition Manager Core development files
libkpmcore12 - KDE Partition Manager Core
```
試しにコレを入れてみました。

```
# apt install calamares-settings-debian

```

ソフトウェアマネージャからインストールしたのと同様に動きますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6b2b9daf-0c2f-6f97-8222-ef2f2eebf151.png)


# カスタマイズ

別記事にまとめました。
「Calamares のカスタマイズ」
https://qiita.com/nanbuwks/items/25b9053609a327817bf7
EC2インスタンスにSession Manager経由でSSH接続する

# EC2インスタンスにSession Manager経由でSSH接続する

## Session Maneger経由でSSH接続することのメリット
- 接続対象のインスタンスにPublic Ipを付与する必要がない
- 踏み台Instance（Bastion）を必要としない　→ Private Subnet内のインスタンスに直接接続可能
- AWSによるCredential認証と公開鍵認証の2段階認証になる
- Cloudtrailに接続ログが残る

## EC2インスタンス側で必要な設定
### EC2インスタンスを作成する
- キーペア（公開鍵）を作成する
    - 必ずpemファイルをダウンロードしておくこと
    - 既存のキーペアがある方は流用してもOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136317/c614f159-1551-a8f1-79ac-d18ca711eb78.png)

- EC2インスタンスをインターネットにアウトバウンド可能に
    - 適切な Vpc，IGW，SGの設定を行う（ここは他記事に譲る）
    - Public Ipを取得する必要はない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136317/3ce27351-567c-14be-6cde-ac13b01b6aca.png)

- EC2インスタンスにSSM Agentを立ち上げるためのInstance Roleを付与する
    - 基本的には`AmazonSSMRoleForInstancesQuickSetup`をアタッチ
    - カスタムなRoleが必要な際にはそのRoleに`AmazonSSMManagedInstanceCore`をアタッチした上で作成すること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136317/5ba5c157-3619-698f-bb74-beface27e4b2.png)


## クライアント側で必要な設定
### awscliのセットアップ
**インストール**
- [公式ドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)などを参考に,awsコマンドを実行できるようにする

**credentialの設定**
- `aws configure`を実行して，credentialなどを設定する
    - この際に，アクセスキーやシークレットアクセスキーが必要
    - 未取得の人は　→ [公式ドキュメント](https://zenn.dev/akkie1030/articles/aws-cli-setup-tutorial)など参照
    - これが完了すると，`~/.aws/config`と`~/.aws/credentials`が作成されているはず

### SSHの設定
**pemファイルの配置**
- `~/.ssh/xxx.pem`などわかりやすい場所にEC2インスタンスにアタッチしたキーペアのpemファイルを配置

**EC2インスタンスの確認**
- 作成したEC2インスタンスのinstance-idを確認しておく（eg. i-0220655452xxxxxx）

**configの作成**
- `~/.ssh/config`を作成する
    - 内容はいかを参考に
```:~/.ssh/config
Host {YOUR_PREFERRED_NAME}
  HostName {YOUR_INSTANCE_ID}
  # EC2インスタンスのOSに依存（Ubuntu： ubuntu，　amazon-linux:　ec2-user)
  User ubuntu 
  IdentityFile {YOUR_PEM_FILE_PATH}
  # 接続を切れにくくするための設定
  ServerAliveInterval 60
  ServerAliveCountMax 5
  ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
```

### 接続確認
- `ssh {YOUR_PREFERRED_NAME}`で接続可能
    - `{YOUR_PREFERRED_NAME}`は自身で設定したconfigを参照すること

## うまくいかないときは？
sshのログを以下で吐き出し可能
`ssh -vvv {YOUR_PREFERRED_NAME}`

また，以下の項目を確認すべし
### EC2インスタンス側
- EC2インスタンスに適切なRoleがついているか？
- そもそもインターネットにアウトバウンドできるか？

### クライアント側
- awscliがインストールできていて，パスは通っているか？
- aws configureで正しく設定できているか？
    - そのcredentialに対して，SSMの権限が付与されているか？
- pemファイルのパスは間違っていないか？
- instance-idは正しいか？
React学習のアウトプットとしてアプリ作成

# はじめに

はじめまして、miu-Yです。
知識0の状態からReactを勉強しており、その途中のアウトプットとしてReactを利用したWebアプリを作成しました。

# 作成したもの

最初の課題として、学習記録を付けられるアプリを作成しました。
機能と環境は以下の通りです。

## 機能

* 学習タイトル・時間の登録機能
* 登録した記録の一覧表示機能
* 未入力時のエラーメッセージ表示
* 学習時間の合計を表示

## 環境

* javascript
* React
* VSCode
* Vite

## 

# 感想・学んだこと

個人で機能を持ったWebアプリを作るのは初めてなので、色々と学べる事が多かったです。
今回は技術的な点以外に以下の事を学べました。

## 手を動かして自分で作る事の大切さ

今回の感想、これに尽きます。
私は、将来的に個人開発でWebアプリを作りたい、また仕事でWeb系をやりたいと考えています。
ですが、その為に何を勉強すればいいのかが全く分かりませんでした。

最近はUdemyやYoutube、その他プログラミング学習サイト等で動画を見て写経できるプラットフォームも増えています。
もちろん高品質な動画の講義も数多くありますが、今までは大抵「見て写経するだけ」で満足してしまい、目標までのハードルが高い壁のような物に思えておりました。

今回は小規模でも「自分で1から作る」経験を積めたことで、**自分がどこまで理解しているのか** や **どこで躓くのか** ということを明確にできました。

今までは高い壁だった目標も、一歩足の置き場を見つけた事で階段だと思えるようになりました。
今後も定期的に自分で手を動かして作ろうと思います。

## 勉強時間を作る事

とにかく毎日勉強することです。
一つでも機能を作る、一行でもコードを書くなど…

私は特にそうなのですが、一日放っておいたら二日三日と先延ばしにしてしまい、結局自分のやりたかった事が出来なくなる方も多いと思います。
（最近はYoutubeやTikTokなど、時間を浪費しがちなコンテンツも多いです）

私も今回のアプリに手を付ける際、最初は全く時間を作れませんでした。
なので、まずは「毎日やること」と「いつなら出来るか」を決めました。

結果、「平日は朝、休日は夜にやる」というルーティンを作り上げて完成まで辿り着きました。
体調やその時の環境にもよりますが、働きながら勉強する上ではこういう事をしっかり決める必要があるなと実感しました。

# 最後に

技術的な事も学べましたが、何より勉強やアウトプットをする習慣を身に着けることが出来ました。
皆様もぜひ「学習したらアウトプット」に取り組んでみてください。

私はJISOUというアウトプットを中心とした学習サービスを利用しています。
学習以外にもカウンセリングやキャリア相談等も出来るとのことなので、興味のある方にはおすすめです！

## JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからライン登録お願いします👇

https://projisou.jp
【JavaScript】Ajaxの書き方あれこれ

どうもこんにちは。

今回は、使用するライブラリによって書き方が変えられるAjaxについてメモとして残そうと思います。

# JavaScriptの場合（ライブラリなし）

```javascript
fetch(`/users/${userId}`, {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute('content')
    },
    body: JSON.stringify({
        user_data: {
            name: nametext
        }
    })
})
.then(response => response.text())
.then(data => {
    console.log("Ajax request successful.");
    eval(data);
})
.catch(error => {
    console.error('Error:', error);
});
```

# jQueryの場合

```javascript
$.ajax({
    url: `/users/${userId}`,
    type: "POST",
    contentType: "application/json",
    headers: {
        "X-CSRF-Token": $('meta[name="csrf-token"]').attr('content')
    },
    data: JSON.stringify({
        user_data: {
            name: nametext
        }
    }),
    success: function(data) {
        console.log("Ajax request successful.");
        eval(data);
    },
    error: function(jqXHR, textStatus, errorThrown) {
        console.error('Error:', textStatus, errorThrown);
    }
});
```

# Reactの場合

```javascript
import React, { useState } from 'react';

function UserComponent() {
  const [nametext, setNameText] = useState('');
  const userId = 'your_user_id';

  const handleInputChange = (event) => {
    setNameText(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();

    fetch(`/users/${userId}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
      },
      body: JSON.stringify({
        user_data: {
          name: nametext
        }
      })
    })
    .then(response => response.text())
    .then(data => {
      console.log("Ajax request successful.");
    })
    .catch(error => {
      console.error('Error:', error);
    });
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input 
          type="text" 
          value={nametext} 
          onChange={handleInputChange} 
          placeholder="Enter name"
        />
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

export default UserComponent;
```

以上
HTML と CSS だけで立体的な要素をスクロールに合わせてアニメーションさせる

## この記事の概要

最近の CSS は進化しているから、色々な要素を組み合わせれば JavaScript なしに 3D っぽい要素をアニメーションさせられるのでは？と思って、試してみた記事です。

なお、記事内に出てくる正四面体の作り方は以下の記事をご覧ください。

https://qiita.com/xrxoxcxox/items/dfb369d4d82bf2f71357

:::note warn
この記事を書いている 2024 年 6 月 30 日時点では Chrome と Edge でのみ動くコードです。Safari と Firefox では動きません。
:::

## 完成形

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/48f5d9c4-b38c-234f-54b0-b82494f6d155.gif)

スクロールにあわせて正四面体が回転しています。[^dummy-contents]

[^dummy-contents]: スクロールしているのが分かりやすいように背景に文字を配置していますが、実際にこのとおりに実装したら読みづらくて仕方ないので、良い具合にアレンジしてください。

## HTML

HTML は非常にシンプルです

```html
<body>
  <div class="dummy-content">Dummy content for scrolling</div>
  <div class="scene">
    <div class="regular-tetrahedron">
      <div class="face face-1">1</div>
      <div class="face face-2">2</div>
      <div class="face face-3">3</div>
      <div class="face face-4">4</div>
    </div>
    <p>
      <!-- ダミーのテキスト -->
    </p>
  </div>
  <div class="dummy-content">Dummy content for scrolling</div>
</body>
```

`regular-tetrahedron`の中の要素が正四面体を形作っています。

## CSS

要素を 3D にするためには`transform-style: preserve-3d;`を指定します。

この記事では正四面体のそれぞれの面の角度や位置などの指定方法は省略しています。
気になる方は[記事冒頭で紹介したこちらの記事](https://qiita.com/xrxoxcxox/items/dfb369d4d82bf2f71357)をご覧ください。

```diff_css
  .regular-tetrahedron {
    /* 見た目を再現するためのコード */
+   transform-style: preserve-3d;
  }
```

次にアニメーションを定義します。

```diff_css
+ @keyframes rotate {
+   from {
+     transform: rotateX(0deg) rotateY(0deg);
+   }
+   to {
+     transform: rotateX(360deg) rotateY(360deg);
+   }
+ }

  .regular-tetrahedron {
    /* 見た目を再現するためのコード */
    transform-style: preserve-3d;
  }
```

そしてアニメーションを実現するためのコードを書きます。

よくある CSS アニメーションだと`何秒間でアニメーションするか`や`何回アニメーションするか`などを指定しますが、スクロールにあわせてアニメーションする場合は少し書き方が違います。

`animation-timeline`を使い、`scroll()`や`view()`で細かな指定をします。[^scroll-driven-animation]

[^scroll-driven-animation]: 今回は簡単なアニメーションを例示するだけなのでこの指定だけで終わらせています。更に知りたい方はこちらの記事に詳しくまとまっているので、よろしければどうぞ。 https://qiita.com/degudegu2510/items/9fa70a8b5284e37f2fe3


```diff_css
  @keyframes rotate {
    from {
      transform: rotateX(0deg) rotateY(0deg);
    }
    to {
      transform: rotateX(360deg) rotateY(360deg);
    }
  }

  .regular-tetrahedron {
    /* 見た目を再現するためのコード */
    transform-style: preserve-3d;
+   animation: rotate;
+   animation-timeline: view();
  }
```

あとはちょっとした調整で、正四面体の位置を調整します。

```diff_css
  @keyframes rotate {
    from {
      transform: rotateX(0deg) rotateY(0deg);
    }
    to {
      transform: rotateX(360deg) rotateY(360deg);
    }
  }

  .regular-tetrahedron {
    /* 見た目を再現するためのコード */
    transform-style: preserve-3d;
    animation: rotate;
    animation-timeline: view();
+   position: sticky;
+   top: 25dvh;
  }
```

たったこれだけの指定で、HTML と CSS のみでアニメーションする 3D 要素を実現できました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/48f5d9c4-b38c-234f-54b0-b82494f6d155.gif)
GoのSliceとMapをforループで回すときのnilの扱いを動かしながら調べた


Goのfor rangeでSliceやMapをループ処理を行うことがたくさんあると思います。

rangeの対象のlengthが0やnilの場合、どのような挙動をするのかが気になったのでサンプルコードを書いて動かしてみました。

## Slice

釈迦に説法かもですが、Sliceとは可変長の配列のことで全ての要素の型は同じです。

```go
	ints := []int{1, 2, 3, 4, 5}
	fmt.Println("[]int{1, 2, 3, 4, 5}のlen:", len(ints))
	fmt.Println("[]int{1, 2, 3, 4, 5}のrange")
	for i, v := range ints {
		fmt.Println(i, v)
	}
```

こんなコードを書いたときにlenは5、for文は5回繰り返します。

アウトプットは以下のようになります。

```
[]int{1, 2, 3, 4, 5}のlen: 5
[]int{1, 2, 3, 4, 5}のrange
0 1
1 2
2 3
3 4
4 5
```

次からSliceがnilだったり、lengthが0だったりしたときの挙動を見ていきます。

### nilの場合

さて、以下のコードがあった時にはどうなるでしょうか。

```go
	var nilSlice []int
	fmt.Println("nilSliceのlen:", len(nilSlice))
	fmt.Println("nilSliceのrange")
	for i, v := range nilSlice {
		fmt.Println(i, v)
	}
```

ここで補足ですがnilSliceの形は[]intですが、中身はnilです。

アウトプットは以下のようになります。

```
nilSliceのlen: 0
nilSliceのrange
```

ここでのポイントはrangeにnilが入っているときはエラーにならずにfor文が一度も実行されないということです。

### lengthが0の場合

次にlengthが0の場合を見ていきます。

```go
	emptySlice := []int{}
	fmt.Println("[]int{}のlen:", len(emptySlice))
	fmt.Println("[]int{}のrange")
	for i, v := range emptySlice {
		fmt.Println(i, v)
	}
```

こちらに関しては自明かもしれませんが、lengthが0の場合はfor文が一度も実行されません。

アウトプットは以下のようになります。

```
[]int{}のlen: 0
[]int{}のrange
```

## Map

次にMapについて見ていきます。

基本ですがMapのループのサンプルを示すために以下のコードを見てみます。

```go
	kv := map[string]int{"a": 1, "b": 2, "c": 3}
	fmt.Println("map[string]int{\"a\": 1, \"b\": 2, \"c\": 3}のlen:", len(kv))
	fmt.Println("map[string]int{\"a\": 1, \"b\": 2, \"c\": 3}のrange")
	for k, v := range kv {
		fmt.Println(k, v)
	}
```

こちらを実行すると以下のようなアウトプットが得られます。

```
map[string]int{"a": 1, "b": 2, "c": 3}のlen: 3
map[string]int{"a": 1, "b": 2, "c": 3}のrange
a 1
b 2
c 3
```

### nil/lengthが0の場合

こちらもSliceと同様に以下のコードを考えます。

（Sliceと似ているのでまとめて書きます）

```go
	var nilMap map[string]int
	fmt.Println("nilMapのlen:", len(nilMap))
	fmt.Println("nilMapのrange")
	for k, v := range nilMap {
		fmt.Println(k, v)
	}

	emptyMap := map[string]int{}
	fmt.Println("map[string]int{}のlen:", len(emptyMap))
	fmt.Println("map[string]int{}のrange")
	for k, v := range emptyMap {
		fmt.Println(k, v)
	}
```

こちらを実行すると以下のようになります。


```
nilMapのlen: 0
nilMapのrange
map[string]int{}のlen: 0
map[string]int{}のrange
```

## まとめ

nilのSlice/Mapに対してrangeを使うとエラーとならずにfor文が一度も実行されないという動きになります。

ある関数やメソッドの返り値がnilの可能性がある場合でも、rangeを使う前にはnilチェックを行わなくてもエラーにならないので、その点は便利だと感じました。
FlutterでIntegrationTestしてみた

# 導入
過去に私はモバイルアプリエンジニアとしてFlutterでアプリを作っていました。
当時は、「実装する」ことがメインになっていたので、テストコードを書いていませんでした。
(バックエンド側はユニットテストコードを書いていましたが、モバイル側は意識していませんでした。)

今になって色々調べてみると、Flutterには、

- Unit Test
- Widget Test
- Integration Test
の3種類があるということを知りましたので、
試しにこれらを実装してみることにしました。

まず今回はWidget Testを実装してみたので、その解説をしていきます。

# 今回実装したアプリ

## 起動時
画面右下にFloatingActionButtonがあるだけです。
<img width='200' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655179/a3821d5c-c15d-4d93-27b1-69e54b09263c.png' />


## ボタン押下
FloatingActionButtonを押すと、そのタイムスタンプのContainerが画面に表示されます。

<img width='200' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655179/2c9bfa06-9d50-4999-d22b-582983a079c2.png' />

今回は初期表示から、このボタン押下後の動きのIntegration Testを実装しました。

# テストコード

※今回、他の詳細な実装は省きます。
UTとWidgetTestは以下の記事を参照してください。

https://qiita.com/phibi-soon/items/04a7018e3a1205ad0137

https://qiita.com/phibi-soon/items/1f381464c7ea0a98e420

```dart:main_test.dart
void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('show views', (tester) async {
    app.main();
    await tester.pumpAndSettle();
    final fixedTime = DateTime(2024, 6, 30);
    final expected = fixedTime.toString();

    // 初期表示時には表示されないことを確認
    expect(find.text(expected), findsNothing);

    await withClock(Clock.fixed(fixedTime), () async {
      await tester.tap(
        find.byKey(const Key('add_date_button')),
      );
      await tester.pumpAndSettle();

      // add_date_buttonのボタンを押した後に表示されることを確認
      expect(find.text(expected), findsOneWidget);
    });
  });
}

```

簡単に重要な部分の解説です。

## 描画が完了するまで待機する処理

タイトルの通りですが、Buildが走って再描画された時に、その完了を待つための処理です。
初期描画にも記述するものになります。

```dart
await tester.pumpAndSettle();
```

## 特定のボタンをタップする処理

この場合、[add_date_button]というKey名のボタンをタップするという動作を行うための処理です。

```dart
await tester.tap(
    find.byKey(const Key('add_date_button')),
);
```

このほかにも文字入力であったり、スワイプであったり、一般的な動作に関するメソッドがあるため、テストに合わせて、必要なメソッドを実装していくことになります。

# 終わりに
これで、Unit Test・Widget Test・Integration Testの全てについて実装することができました。
今回のIntegration Testは実行時間が他の2つに比べて長くなるため、自動化する際の実行タイミングを適切に判断する必要があると思われますが、いずれのテストにおいても重要であるのは確かです。
これからFlutterのテストコードを書こうと思っている人の役に立てば嬉しいです。
ElixirでDJコントローラー から値を取得する

# 前提条件
* DJコントローラー DDJ-FLX4
* OS Ubuntu22.04
* portmidiをインストールできる環境（他のOSでもできるかも）


# 環境作成等はこちらを参考

https://qiita.com/t-yamanashi/items/38e4cd7124c4daac111f

# コードを書く

https://github.com/ymn-t-yamanashi/ddj-flx4_led

完成版はgithubに有ります

前回からの差分

```elixir:lib/hoge2.ex
defmodule Hoge2 do
  @moduledoc """
  Documentation for `Hoge`.
  """

  def hello() do
    {_, input} = PortMidi.open(:input, "DDJ-FLX4 MIDI 1")

    # MIDIデータの受信準備
    PortMidi.listen(input, self())

    # 受信部分
    midi_in(input)

    PortMidi.close(:output, input)
  end

  def midi_in(input) do
    
    receive do
      # PLAY/PAUSE　ボタンを離したら、プログラム終了
      {^input, [{{144, 11, 0}, _}]} ->
        IO.inspect("end")
        # 受信待機はしない

      # {176, 34, 63}の形式のデータの表示
      {^input, [{event, _}]} ->
        IO.inspect(event)
        # 再度受信待機
        midi_in(input)

      # 上記以外
      a ->
        IO.inspect(a) 
        # 再度受信待機
        midi_in(input)
    end
  end
end

```
# 動作動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/WjnrB9SR4v4?si=SqGCOcdOt8jvyfsy" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
【Java SE 11 Silver】合格体験記

# 1. はじめに
### 自己紹介
初めまして、コマと申します。春から社会人になりました。
研修の一環でJava Silverの取得が必須ということもあって、受験をすることになりました。
この度、晴れて本番で9割取ることが出来たので、試験勉強過程などで学んだことなどを交えながら、記事を書き進めていきたいと思います。
![GQ0JdvWbkAAFGZ1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3338199/1529f5c2-bf58-b69c-d862-4c22d1eb611e.jpeg)
# 2. 試験の概要
Java SE11 Silverは、Oracleが提供するJavaプログラミングの認定試験です。概要は以下の通り。
問題数: 80問
試験時間: 3時間
合格ライン: 63%
受験料: 37730円
###### 出題範囲
+ Javaテクノロジと開発環境についての理解
+ 簡単なJavaプログラムの作成
+ Javaの基本データ型と文字列の操作
+ 演算子と制御構造
+ 配列の操作
+ クラスの宣言とインスタンスの使用
+ メソッドの作成と使用
+ カプセル化の適用
+ 継承による実装の再利用
+ インタフェースによる抽象化
+ 例外処理
+ モジュール・システム
# 3. 使用教材・学習期間
使用教材・学習期間などは以下の通りです。
会社にいる間はずっと自主学習だったので、1ヶ月間みっちり勉強に費やしました。
+ 徹底攻略Java SE 11 Silver問題集［1Z0-815］対応 (黒本)
+ オラクル認定資格教科書 Javaプログラマ Silver SE11(試験番号1Z0-815) (紫本)

学習期間: 1ヶ月
学習時間: 250時間ほど
# 4. 学習の要点
学習期間も受ける段階である程度決められていたので、効率よく身につく方法は何かを模索するところから始めました。
結論から言うと、黒本や紫本の問題(特に模擬試験問題)を解く際に、該当する記号を書いて終わりではなく、
+ 問いに対しての解法を自分の言葉でアウトプットする
+ 解説を見て自分が答えた解法と比較する
+ 答えが正で解法が誤の場合、解説を見て正しい解法を理解する
+ 答えも解法も誤の場合は、解説を見て正しい解法を理解し、後日その問題を解く

という学習法で問題を解き進めていました。
こちらの学習法は、見事自分にマッチし、得点率を上げる要因になったと考えています。
何度も反復をしていると、答えの番号を暗記してしまったり、別の形で出題された際に頭が真っ白になってしまいがちですからね。その懸念点をある程度防ぐことが出来る方法なのかなと思っています。
また、解法を見ても腑に落ちない問題に関しては、ChatGPTやWebサイトを利用したり、自分で問題のコードを打ち込みました。8割以上の問題は、即座に見て解答・解法を即答できるぐらいには仕上がっていたと思います。
# 5. 試験当日
試験当日の問題割合としては、黒本4割、紫本5割、初見問題1割でした。
直前に解いていた問題や前日に解いていた問題がそのまま出題されていたりと、出題運に関して、正直かなりラッキーでした。
ただ、そういう問題をほぼ落とすことなく取りきれたのは、偉かったなと実感しています。

# 6. まとめ
以上が私の合格体験記となります。稚拙な文章で申し訳ございません。
これから実務に入っていくので、虎視眈々とスキルを磨いていきながら、ゆくゆくはJava Goldなどにも挑戦していきたいと考えています。
論理演算子の秘密：&&と||をマスターして、コードを魔法のようにシンプルに！

## 論理演算子の考え方
### && (AND)について
こんな記述があるとして
```
result = a && b;
```
aとbがtrueならtrueを返すって認識だったんですが、間違いらしいです…

&&（論理AND演算子）は、左から右に向かって評価します。つまり、次のような流れです：

最初に左側の式 a を評価します。
a が偽（falsy）であれば、その時点で評価を停止し、a の値が結果となります。
a が真（truthy）であれば、次に右側の式 b を評価します。
b も真であれば、全体の結果は true となります。一方、b が偽であれば、全体の結果は false となります。

要するに、`&&`は両方の値が`true`のときにだけ`true`を返しますが、最初の値が`false`の場合には、もう一方の値は無視されて`false`が返されるということです。

### 例
```
let a = true;
let b = false;

let result = a && b;  // 結果は false
```

この例では、`a`が`true`なので、次に`b`が評価されます。`b`が`false`なので、結果は`false`になります。

```
let a = false;
let b = true;

let result = a && b;  // 結果は false
```

この例では、`a`が`false`なので、その時点で結果は`false`になります。`b`は見てもらえません。

このように、論理AND演算子`&&`の評価順序とショートサーキット評価について理解しておくことが重要です。

### 発展編：文字列の比較

文字列の比較でも同様のルールが適用されます。例えば、以下のような記述を考えてみましょう。

```
let a = "hello";
let b = "world";

let result = a === "hello" && b === "world";  // 結果は true
```

この例では、`a`が`"hello"`と等しいかをまずチェックします。`a`が`"hello"`であれば、次に`b`が`"world"`と等しいかをチェックします。両方が真なら、結果は`true`になります。

もう一つの例として：

```
let a = "hello";
let b = "earth";

let result = a === "hello" && b === "world";  // 結果は false
```

この場合、`a`が`"hello"`と等しいため次に`b`がチェックされますが、`b`は`"world"`と等しくないため、結果は`false`になります。

また、次の例では：

```
let a = "hi";
let b = "world";

let result = a === "hello" && b === "world";  // 結果は false
```

`a`が`"hello"`と等しくないため、その時点で結果は`false`になり、`b`はチェックされません。

文字列の比較でも、論理AND演算子`&&`の評価順序とショートサーキット評価のルールが適用されることを覚えておきましょう。

### 実務での利用例

論理演算子は実務でもよく使われます。例えば、ユーザー入力の処理やデフォルト値の設定などです。

#### ユーザー入力がない場合のデフォルト値設定

ユーザーが入力を行わなかった場合に、デフォルト値を設定する場合、以下のような記述が使われます。

```
let userInput = null;
const userName = userInput || "guestUser";
console.log(userName);  // 出力: guestUser
```

この例では、`userInput`が`null`の場合、`||`（論理OR演算子）を使って`"guestUser"`が代入されます。`userInput`が空や`null`であるときにデフォルト値を設定する便利な方法です。


### Null 合体演算子の利用例

`null` や `undefined` の場合に限定してデフォルト値を設定する場合、Null 合体演算子 (`??`) を使用することが推奨されます。例えば：

```javascript
let userInput = null;
const userName = userInput ?? "guestUser";
console.log(userName);  // 出力: guestUser
```

この例では、`userInput` が `null` 及び`undefined` の場合に限り、`userName` に `"guestUser"` が代入されます。


#### 複数条件のチェック

また、複数の条件を同時にチェックする場合にも論理演算子が役立ちます。

```
let user = {
  isLoggedIn: true,
  isAdmin: false
};

if (user.isLoggedIn && user.isAdmin) {
  console.log("Welcome, admin!");
} else {
  console.log("Access denied.");
}
```

この例では、`user`がログインしており、かつ管理者である場合にのみ特定のメッセージが表示されます。それ以外の場合は「Access denied.」が表示されます。

論理演算子をうまく使うことで、コードを簡潔かつ効率的に記述できるようになります。実務での利用シーンを考えると、理解を深めやすいです。
Linuxの基本コマンドの備忘録

stat ファイル名
ファイル名のアクセス時間などを表示

touch -a ファイル名
ファイルのアクセス時間を変更できる

ls -1
ファイルの一覧を表示できる
ls -tl
作成時間の昇順で表示

ls -ltr　※よく使う
作成時間の降順で表示


ls file*
file＊を表示できる　前方一致

pwd 
カレントディレクトリーを表示

mkdir -p dir1/dir2/dir3
-p　オプションで 存在しないディレクトリ内にもフォルダを作れる


cd ~
ホームディレクトリに移動

cp file1 file2
file1の内容をfile2にコピー

cp -f:コピー先に同名のファイルがあっても強制的に上書きしてコピー
cp -i:コピー先に同名のファイルがあれば、コピーするか確認する
cp -p:コピー元のファイルの属性（所有権、アクセス権、タイムスタンプ）もコピー
cp -r:ディレクトリをコピー

cat:ファイルの中身をディスプレイ上に表示する。catはconcatenate(連結する)が由来
cat file.txt
cat -n:すべての行に行番号をつけて表示
cat -b:空白行以外の行に行番号をつけて表示

cat file1.txt file2.txt >> file3.txt
faile1.txtとfile2.txtを連結したfileにしてfile3.txtを出力できる。
reset, revert, rebaseの違いと触ってみた

reset, revert, rebaseの違いご存知ですか？
サクッとまとめました！

## reset
- Gitリポジトリ内のコミット履歴やインデックスを変更するためのコマンド
- 特定のコミットまで戻したり、インデックスをクリアしたりする場合に使用する
- 作業ディレクトリやステージングエリアの状態を変更する

```
コマンド
git reset [--soft | --mixed | --hard] [commit]

--soft 活用例：直前のコミット内容を修正したい時に使う
--mixed 活用例：ステージしたものを取り消したい
--hard 活用例：ひとつ前のコミットまでまるごと消したい

```
### お試し_soft → commitした状態からadd(ステージング)状態に戻す
![soft.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/68120fbd-9259-76de-ba5f-8e64fa9b54f2.png)
### お試し_mix → commitした状態から作業状態に戻す
![Mix1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/4e0bfa9f-f612-441c-04a0-23ad68fd08b4.png)

### お試し_hard → commitした状態から無に戻す
![Hard1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/ce8aabc0-f19c-8e91-f387-e75494ccc4d1.png)
![Hard2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/1c75f4da-8d0b-3e6e-5771-5c40f01a784a.png)


## revert
- Gitで特定のコミットを取り消すために使用されるコマンド
- 過去のコミットを取り消し(履歴は残る)、その取り消しを新しいコミットとして履歴に追加する
- 履歴を安全に変更するために使用する
```
コマンド
git revert [commit]
```
###　特定のコミットを取り消す
![revert commit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/49a3506f-668d-d7bd-26f8-0ded728b3356.png)

### コミットメッセージ編集

![revert2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/9d52bd2e-bf74-0cfc-a14f-848d4065a9b7.png)

#### revert --edit叩いた後の画面遷移
![revert1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/c93c9e98-d648-98b2-6590-bf50e82bb724.png)



## rebase
- Gitの分岐を調整し、コミット履歴を整理するためのコマンド
- ブランチをベースにしている他のブランチの変更を取り込む
- コミットの履歴を綺麗に整理する

```
コマンド
git rebase [branch]
```
![スクリーンショット 2024-06-30 18.37.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/a4bd2ae7-d70d-dc7a-f200-8eb735854da0.png)


### git pull との違い
- 履歴が直線的になり、読みやすくなる。
- マージコミットが生成されないため、履歴がクリーンになる。
- 自分の作業ブランチをクリーンに保ちたい場合。
    - 共有ブランチや複数人での共同作業では、git pullがいいかも

### 参考
reset https://www.r-staffing.co.jp/engineer/entry/20191129_1
revert https://qiita.com/chihiro/items/2fa827d0eac98109e7ee
rebase https://zenn.dev/tana0102/articles/475d8952933af6
なぜあなたの仕事はしんどいのか

こんにちは。
こちらの記事に興味を持っていただきありがとうございます。

不定期に読書感想文をプログラマーにとって有益になるように
まとめています。

今回は大ベストセラーとなっているこの本、
「嫌われる勇気」をご紹介します！


嫌われる勇気は仕事・恋愛・友人関係などあらゆることに関して
悩みを持っている人にとって必要な行動指針書です。

概要としてはアドラー心理学を哲人・青年の対話形式で紹介するもの。

原因論・目的論や共同体感覚など、とても大事な概念・考え方が
たくさん紹介されていますが、今回は「課題の分離」の概念を紹介しつつ
「なぜあなたの仕事はしんどいのか」の話をしていきます。


私自身、課題の分離を少しずつ実践してきたおかげか、
人の愚痴を言うことなんてまずなくなりましたし、
どれだけ長く働いても、どんな仕事に就こうとも
しんどいと感じることはほとんどなくなりました。


# 課題の分離とは？

一言でいえば、
「これからどうするか？」を考える姿勢です。

もうこの一言だけで人の愚痴を言うなんて思考は
どこか空の彼方へ行ってしまうと理解できる人も多いと思います。

もう少しかみ砕くとすれば、
自分の課題（やるべきこと）と相手の課題（やるべきこと）を
見分け切り分けること。


恋愛で考えるとわかりやすいです。
あなたには好きな人がいるとします。

その好きな人と付き合いたい。
その目標がある場合、あなたの課題は
「好きな人に告白する」
ですよね？

そしてここが肝心で、
「告白相手に自分と付き合うことを承諾させる」ことは
決してあなたの課題ではありません。
これは相手の課題です。

あなたの告白を受け取った相手が決めること。

これをあなたの課題としてしまうと、ひどければ
相手が承諾してくれるよう脅迫・いやがらせしてしまったり、
相手がもし断ってきたときに立ち直れないほど落ち込んでしまったりしまいます。

下手すれば「あぁ私はモテないんだーーー」と
端からみればありえない解釈すらしてしまいかねません。


一方で、課題の分離がしっかりとできていれば、
「これからどうするか？」を考えるので、
例えば振られた人にもっと自分の魅力が伝わるように努力してみたり、
あるいは別の人へアプローチできるように切り替えたりできます。


課題の分離ができていれば自然と
「これからどうするか？」を考えられるようになります。


# 「しんどい」の定義

ここで抽象的な言葉である、「しんどい」を
定義しておきます。

しんどいとは以下の状態を指します。
- 今自分が何をすればわからない
- 問題解決の糸口がつかめない
- うまく物事が進まない

経験上プログラマーにとってはこの状況が
しんどいなと感じます。

単純に作業量が多いだけであればやるだけであり、
無心になって作業でき、気づけば完了できている分、
そこまでしんどくない印象です。


# なぜあなたの仕事はしんどいのか

さて、ここまで「課題の分離」の概念と「しんどい」の定義を
お話ししてきました。


ここまでを統括していえることは、
**あなた自身が仕事をしんどくしてしまっている**
ということです。

しんどい理由は上司がありえない量の仕事を振ってくるからだとか、
あの人が私に高圧的な態度をとってくるだとかでは決してありません。


「そんな考え方、まるで人間をロボットとして扱っているみたいじゃないか！人間には感情があるんだぞ！」
と反論が聞こえてきそうですが、そうではありません。

複雑に考えてしまうからしんどくなるんです。

もっとシンプルに考えてみませんか？という話です。

仕事はお客様の問題解決ですよね。
問題解決をするために中間地点の目的がたくさんあります。

その目的を一つずつ愚直に達成していくだけ。

本当にシンプルだと思っています。
シンプルに考えれば自分が何をすればよいか明確になりやすいです。

自分が何をすればよいかわかればあとはやるだけ。
しんどくないですよね？


カップラーメンの作り方がわかれば
カップラーメンを作るのにしんどさは感じないように、
仕事の目的を達成するための手順がわかれば
その仕事をすることに対してしんどさなんて感じません。


正直言って一朝一夕で理解し使いこなせるような概念ではありませんが、
少しでも良いと感じられたらぜひ明日から試してみてください。

本当にいいですよ。
プロジェクトメンバーへの連絡ツールの検討

# はじめに
「チームや組織内でのコミュニケーション」については、私はツールに頼りながら、円滑に進められるように環境を整備すべきであると考えています。(何らかのメゾットを実践しようとしても結局挫折してしまうため)
...ということで、私が中心となって立ち上げようとしているプロジェクトでのコミュニケーションツールについての検討をしましたのでそれについて書いておきます。

# 前提
- 学校からMicrosoft365 Educationのアカウントを支給されている
- メンバーは学外の人を含む7人
- 学校からPCが貸与されている(アプリインストール可)
- 全員が同じDiscordサーバーに属している

# 1. Web会議ツール

## 候補
- Google Meet
- ZOOM
- Microsoft Teams
- LINE
- Discord
- Slack

## 詳細
### Google Meet
- 提供元:**Google**
- 無償版では40分の制限
- 機能は抑えめ
- シンプルで直感的

### ZOOM
- コロナ禍で一気に普及した
- 無償版では40分の制限
- Web会議で使いそうな機能は一通り揃ってる
- ミーティングへの参加のときにアプリが必要？なようでわかりにくい

### Microsoft Teams
- チャットツールと統合されている
- 無料版では40分の制限
- 機能は若干煩雑
- Officeファイルの共有に強い

### LINE
- 操作はかんたん
- グループで通話する場合、必ずそのメンバーグループが必要
- 機能が貧弱
- LINE Works版ならギリギリ実用に耐えうるが...

### Discord
- 時間制限なし
- 最低限の機能はある
- アイスブレイクに使えそうな機能は多い
- コミュニティサーバーであればウェビナーみたいなこともできる

### Slack
- 1:1であれば時間制限なし
- 3人以上だと40分の時間制限
- 結局試せていない

## 結論

- 普段の話し合い->Discord
- 外部の人を交えた話し合いやファイル共有->Teams

を使おうと思います

# 2. チャットツール

## 候補

- Discord
- Slack
- LINE Works
- Teams

## 詳細

### Discord

- ゲーマー向けのチャットツール
- 権限設定がきめ細かく可能
- Linuxにも対応
- Web会議にも使える(画面共有可能)
- botも自作可能

### Slack

- ビジネスチャットツール
- あまり細かい権限調整はできない
- Web会議も可能
- Linux対応
- Auto-Replyが設定可能

### LINE Works

- ビジネスチャットツール
- 権限周りはアクセス権くらいしか設定できない
- Web会議も一応可能
- PCからはWeb上で利用可能
- 使いなれたLINEの操作が可能

### Teams

- ビジネスチャットツール
- ファイル共有がしやすい
- Web会議も可能
- Web上でも利用可能
- よくバグる

## 結論

- 普段の連絡->Discord
- ファイルの共有->Teams

を利用しようと思います

# まとめ

今回の条件下では、DiscordとTeamsを併用するのが最適であると思いました。

様々なツールを使ってみて、
- Discordはゲーマー向けというのもあり気軽に書き込める
- Teamsは「投稿」という仰々しい書き方故に書き込みにくい？
- LINE Worksは使いやすいが機能的には貧弱で管理がしにくい

と感じました。

このようなプロジェクトでは、各々が意見を出し合うことが重要だと思うので、気軽に書き込める、というのは大きなアドパンテージだと感じます。ゆえに、今回はDiscordを採用しました。
一方で、Discordはファイル共有が弱いというのも感じたので、Teamsを使うことでそれを解決しようと考えました。Teamsはちょっと書き込むのに敷居が高いですが、それを逆に活かして、書類とその関連連絡専用にすれば良いと思いました。TeamsはOneDriveとの連携でファイルを共有フォルダの中に入れることができるので管理もしやすいです。

このように、それぞれの用途に適したツールを選定するのも、チーム内でのコミュニケーションの円滑化につながると思います。

加えて、Discordは「コミュニティサーバー」とし、ルールを作ることで、「本当にここに送っていいのかな」という不安も少しは払拭されると考えます。ルールは人を「縛る」ものであると同時に、人の「安心」につながるのではないか、とも思いますが、どうでしょうか。

いずれにしても、適切な設定を行うことで、トラブルを防止し、円滑なコミュニケーションを取れるのではないでしょうか。