OmniAICreator/Qiita-1.07M huggingface dataset:
PHP的（PHPStan）ジェネリクス型

PHPStanを使うとPHPでもジェネリクス型が使える

なのでこんな感じで書いてみたら...

```
<?php

interface Animal{
    /**
     * @template E of Food
     * @param E $food
     * @return void
     */
    public function eat($food): void;
}

interface Food {}

class Cat implements Animal {
    
    /**
     * @param Fish $fish
     * @return void
     */
    public function eat(Fish $fish): void
    {
        //うまいうまい
    }
}

class Fish implements Food{
    
}
```
Catのeat()がインターフェースのものと互換性がないと怒られます。

原因は簡単で、PHPは型境界を理解してくれないから
なので、仮引数型の宣言をやめて、PHPDocにだけ書くようにする。

```
<?php

interface Animal{
    /**
     * @template E of Food
     * @param E $food
     * @return void
     */
    public function eat($food): void;
}

interface Food {}

class Cat implements Animal {
    
    /**
     * @param Fish $fish
     * @return void
     */
    public function eat($fish): void
    {
        //うまいうまい
    }
}

class Fish implements Food{
    
}
```
これでよし
モバイルアプリで長すぎる文字を省略し、最大文字超過した時に「…」を表示する方法

# 目次
1. はじめに
1. 実装方法
1. まとめ

# はじめに
モバイルアプリの開発をしていて、
文字数が多い時に省略して「...」と表示したい場合があると思います。

Visualizerを使うと、
とっても簡単に文字の省略が実装できるので、ご紹介したいと思います！

※今回紹介する機能は、iOS,Androidの場合使える機能となります。

# 通常開発の場合
まずVisualizerを使わない通常の開発の場合、
CSSで対応する場合は、`text-overflow: ellipsis;`を追加する必要があります。
（参考）https://and-ha.com/coding/clamp/

または、JavascriptでIEを含む全てのブラウザに対応する場合は、
文末に追加したい文字「...」を変数定義し、
指定した文字数を超えた場合、１文字削って、追加したい文字を入れて・・というコーディングをしなければなりません。

慣れれば問題ないと思いますが、
コーディングに慣れていない初心者目線だと少しとっつきづらいですよね:frowning2:

Visualizerなら、GUIツールを使って**3ステップ**で対応可能です！
早速紹介していきたいと思います:relaxed::raised_hand_tone1:

# 実装

## 完成イメージ
今回の修正前と、修正後のイメージは以下となります。

修正前は、
一行に収まりきれず文字の見切れが発生してしまっています。。
修正後は、
一行に収まり、表示しきれない文字は切り捨てられ省略文字が表示できていますね！

|修正前|修正後|
|---|---|
|![IMG_1015 2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/19655c00-3a6c-c760-411b-69b73e171817.png)|![IMG_1016 2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/c29d20ba-fe3a-ef77-f8e9-b843b5c30d23.png)|

では実装に移っていきましょう！

## 実装方法
1. LabelのWidthを指定する<br>もし対象Widgetの幅（Width）が「preferred」になっている場合、<br>必ず幅数を指定してあげるようにしてください。<br>幅を指定してあげないと、最大表示数を1行に設定したとしても幅がどこまでも伸びて見切れてしまうことになります。<br>
今回は90%に設定しました。<br>![スクリーンショット 0004-09-06 11.08.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/0e571aae-6b61-b581-f9ee-e840f412599a.png)

1. Max Number Of Linesを「1」に設定<br>幅を指定したら、Labelタブを開き、何行まで表示するかを設定します。<br>今回は一行に収めたいので、「1」に設定します。<br>※備考欄など複数行表示したい項目がある場合は、10行にするなど適宜変更してください。![スクリーンショット 0004-09-06 10.57.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/c619a4af-1fc9-9ff5-6e95-7c665cbea193.png)<br>（Max Number Of Linesに値を入力すると、<br>自動的にText Truncate Positionが表示されるようになります。）<br>

1. Text Truncate Positionを「End」に設定<br>文字が切り捨てられた時に、省略文字「...」をどこに表示するかを指定します。<br>今回は、文字の最後に省略文字を表示したいため、「End」に変更しましょう。
![スクリーンショット 0004-09-06 10.58.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/43d99e5b-13db-846b-225f-d254ea560b9f.png)

以上で完了です！


早速動作を見てみましょう！
![IMG_1016.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/25bc9719-b8dd-f91c-c9f5-544497aa9be2.png)

文字の最後に省略文字が表示されて、
見切れが発生しなくなっていることがわかりますね:raised_hands_tone1:


:::note 
今日の一言:writing_hand_tone1: 
最大文字数での指定ではなく、行数指定にすることで、
幅の異なるデバイスでも1行に収まり切らない文字が切り捨てられるため、
**様々なデバイスに対応ができる**のも嬉しいポイントですね:relaxed:！
:::
# まとめ
1つもコーディングをすることなく、
設定値を変えるだけで省略文字の対応ができました:sunny:

利用シーンが多い機能ですので、是非活用してみてくださいね！

# 参考
[Label Widget](https://docs.kony.com/konylibrary/visualizer/viz_widget_prog_guide/Content/label.htm)
費用と利益

# 費用には固定費と変動費がある
### 固定費
```売上に関係なく```発生するお金

### 変動費
```売上と比例して```増減するお金

# 損益分岐点
### 損益分岐点
```損失（赤字)と利益(黒字)とが分岐```するところ。

### 損益分岐点売上高
```損益分岐点になる時の売上高```

# 変動費率と損益分岐点
### 変動費率
```損益分岐点売上だけを算出```するために使う値

### 変動費の求め方
```
変動費 = 売上高　* 変動費率
```
### 損益分岐点売上高の求め方
```
損益分岐売上高 ＝　変動費　+ 固定
            　＝（損益分岐点売上高　* 変動率）　+ 固定費
```

# 問題を解いた時の気づき
* もっと計算をしなければならない。
* 売上高の傾きが変動率の傾きよりも急だったら損益分岐点の変化は正比例しないのか。
91.Symbol

シンボルとは
＊プロパティの重複を避けるために『必ず一意の値』を返す関数。
＊文字列でもない、数値でもない、シンボル型という方
＊一位なので、比較をすると
#### シンボル型作成方法
```javascript
const left = Symbol("hello");
// シンボル型のhelloが返される
```
#### 同じhelloを左右で比較すると、、
```javascript
const left = Symbol("hello");
const right = Symbol("hello");
console.log(left == right);
console.log(typeof left)
```
// ビルドインオブジェクトを拡張するのは好ましくないので、今は確認のため
```javascript
String.prototype[left] = function(){
	return 'hello'+ this;
} 
const tom = 'Tom';
console.log(tom[left]())
```
【夏休み企画】#IT用語一問一答【毎朝投稿17日目】Beacon

# この記事を読むと、、
- 「関連用語」を使って「beacon」を説明できるようになる

# 関連用語
RUM / JavaScript tags / tracking pixel

[**復習用**] 記事の内容を見る前に上記の言葉で「beacon」を説明してみよう！

# 企画説明
- クラウドって何？って人に聞かれて説明してるけど俺もよく知らないや、、
- ドキュメント読んでみてるけど半分くらい何言ってるか分かんない、、
- 今日の夕飯はナスの炒めものにしよっかな〜、あれ、NASってなんだっけ？

みたいなことが結構あったので、知ったかしていたIT用語を毎日一個ずつちゃんと学んでいこうっていう企画です！

昨日の記事はこちら↓

https://qiita.com/acta/items/3da87a977cf89064624b

# beaconとは
beacon = Web beacon = emailやWebページの閲覧者を識別する技術

- RUMやemailの追跡に使われる
    - **RUM** = Real User Monitoring = ユーザーの実機でパフォーマンスを測定すること

- **JavaScript tags** = JSを使ったbeacon
- **tracking pixel** = clear GIF = imgタグを用いたbeaconの手法の一つ
    - 1px x 1pxの極小かつ、透明もしくは背景色と同じ色をしているので閲覧者には見えない
    - ページ閲覧時(画像読み込み時)にimgが保存されているサーバーにクライアントのホストを識別する情報とともにリクエストが送られる
- tracking pixelの他にもバナーやボタンなどの可視的な要素である場合や、frame, styleタグなどの大きさを持たない要素である場合もある
- 送られる情報は例えば以下のもの
    - 閲覧者ののIPアドレス
    - タイムスタンプ
    - 過去に送られたCookieの有無

# 参考資料
- https://en.wikipedia.org/wiki/Web_beacon
- https://developer.mozilla.org/en-US/docs/Glossary/beacon
Laravel Log::infoの使い方 ~ ログ出力

# 動作環境
・PHP: 8.1.10
・Laravel:9.27.0

# ファサード
```php:Laravel
use Illuminate\Support\Facades\Log;
use Log; // エイリアスでもいける環境もあるみたいですが、私のは無理でした。
```

# ログの基本
```php:Laravel
Log::info("ログ");
Log::info($request);
Log::info("ログ",['request_log' => $request]);

```

これでいけます。

# 出力先はこちら
storage/logs/laravel.log

他にもいろいろできるみたいです。
使用することがあったら追記します。
Linux timedatectl、hwclock、date、ntpdate、ntpd、Chronyについて（自分用メモ

●timedatectlコマンド
systemdの動作するシステムにおいてシステム時刻の表示や設定を行うコマンド。システムクロックとハードウェアクロックを同時に設定できる。

timedatectl [サブコマンド]

・status 現在の日付時刻や状態の表示(デフォルト)
・set-ntp yes|no　NTPによる時刻同期の有効｜無効
・set-time 日付|時刻　日付や時刻の設定。時刻を指定しない場合は0時0分0秒
・set-timezone タイムゾーン　タイムゾーンの設定
・list-timezones タイムゾーンの一覧表示

※set-timeサブコマンドでシステム時刻を手動で設定する場合は、NTP（Network Time Protocol）による時刻同期機能を無効にしなければならない（デフォルトでは有効）


●Linuxの動作するシステムで扱う時刻には、ハードウェアクロックとシステムクロックがある

・ハードウェアクロック　hwclockコマンド　PCに内蔵された時刻。電源OFF状態でも動作。
・システムクロック　dateコマンド　Linuxカーネルが持つ時刻。システム起動時にハードウェアクロックの値が設定される。

■hwclockコマンド

hwclock オプション

・-r ハードウェアクロックを表示(オプションなしと同じ)
・-s | —hctosys　ハードウェアクロックの時刻をシステムクロックに反映させる
・-w | —systohc システムクロックの時刻をハードウェアクロックに反映させる

■dateコマンド
date [MMDDhhmm[CC[YY]][.ss]]
（MMは月、DDは日、hhは時、mmは分、CCは西暦の上2桁、YYは西暦の下2桁、ssは秒）

何も指定せず、コマンドのみを実行すると現在の日付時刻が表示。
また、+に続けて日付時刻のフィールド文字を指定すると、指定した通りの日付時刻書式で表示


●ntpdate コマンド
手動でNTPサーバから正確な時刻を取得し、システムクロックに反映させるNTPクライアントとしてのツール。

ntpdate コマンド書式：

ntpdate [オプション] NTPサーバ名


●ntpdの各種設定は「/etc/ntp.conf」で行う。

「/etc/ntp.conf」の主な設定項目
・restrict ntpdへアクセス制限を行う
・server 時刻を取得するサーバを指定
・driftfile 自身の自国のずれを記録するファイルを指定


公開NTPサーバを利用する場合は、複数のNTPサーバ群で構成される「pool.ntp.org」プロジェクトに登録されている外部サーバ等を指定する。「pool.ntp.org」を利用すると、複数のNTPサーバから、負荷分散の技術の一つである「DNSラウンドロビン」を利用して時刻を取得する。例えば日本であれば「0.jp.pool.ntp.org」から「3.jp.pool.ntp.org」といったserverを指定することで、遅延の少ない、正確な時刻を入手できるようになる。

●ntpd の時刻同期状況は ntpq コマンドで確認できる。
ntpq コマンドの書式：

ntpq オプション 接続先サーバ

・-p serverに指定したサーバとの同期状態を一覧表示する。対話モード状態のpeersコマンドと同じ。
・-i 対話モードで起動する（デフォルト）


●Chrony（クローニー）
ntpdに代わるNTPサーバ/クライアント。Chronyのデーモンはchronyd、chronydのコマンドラインツールはchronycコマンド。
chronydはntpdに比べて、通信が不安定な状態でも良好に動作、高い精度で時刻を同期できる。必要な時だけCPUを使用し、メモリ使用量も少なく、CentOS7以降では標準システムとなっている。

Chronyの設定ファイルは「/etc/chrony.conf」

/etc/chrony.confの主な設定項目

・server 時刻を取得するNTPサーバを指定。サーバ/クライアントの関係。
・peer 時刻を取得するNTPサーバを指定。同じ階層(stratum)同士。
・pool 時刻を取得するNTPサーバのプール(複数アドレスを集約した名前)を指定
・driftfile 自身の時刻のずれを記録するファイルを指定
・rtcsync システムクロックをハードウェアクロック(RTC)にコピーする


●chronycコマンド
chronydの管理を行う

chronyc [サブコマンド]

・activity オン/オフラインのNTPサーバ数を表示
・sources 時刻のソースを表示
・sourcestats　自国のソースの統計情報を表示
・tracking トラッキング(時刻同期の詳細情報)を表示

※サブコマンドを指定せずにchronycコマンドを実行すると、対話モードで起動する
React Nativeで多言語化する

### React Nativeで多言語化

色々探してみたが、React Nativeで多言語化する記事が少なかったので記事にしようと思います。

使用するライブラリーは、react-i18nextを使用する
* [react-i18next](https://www.npmjs.com/package/react-i18next)
* [react-native-localize](https://www.npmjs.com/package/react-native-localize)

### インストール

```
npm install react-i18next i18next react-native-localize --save
```

### 言語ファイル

* ja.json

```
{
  "TITLE": "タイトル"
}
```

* en.json

```
{
  "TITLE": "title"
}
```

### 言語ファイルをi18nextで初期化

```typescript:i18n.ts
import i18n from 'i18next';
import {initReactI18next} from 'react-i18next';
import {getLocales} from 'react-native-localize';

import EN from './en.json';
import JA from './ja.json';

i18n.use(initReactI18next).init({
  resources: {
    en: {translation: EN},
    ja: {translation: JA},
  },
  lng: getLocales()[0].languageCode,
  fallbackLng: ['en', 'ja'],
  interpolation: {
    escapeValue: false,
  },
  compatibilityJSON: 'v3',
});

export default i18n;
```

上記で、React Nativeで多言語化する準備が出来ました。

### 実際に使ってみる

```typescript:App.tsx
import {useTranslation} from 'react-i18next';
import './src/translations/i18n';

const App = () => {
  const {t} = useTranslation();
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  return (
    <SafeAreaView style={backgroundStyle}>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
      <ScrollView
        contentInsetAdjustmentBehavior="automatic"
        style={backgroundStyle}>
        <Header />
        <Text style={styles.sectionTitle}>{`${t('TITLE')}`}</Text>
      </ScrollView>
    </SafeAreaView>
  );
};
```

```
t('TITLE')
```

この部分が多言語化されます。

---

あまりReact Nativeで多言語化の情報が少なかったので、参考になれば嬉しいです。
文字列の連結

C++ で文字列を連結をする関数テンプレートの記事を読みました。  `char*` と `wchar_t*` を統一的に扱うという試みです。

https://qiita.com/yuki_kitty/items/8c9670fd56ca5a2dbda1

この試みを更に一般化して文字列的な型について全般に対応しようとするとどのように書けるだろうかということを考えてみました。 そこで思い出したのは C++17 以降は文字列的なものは `std::basic_string_view` で受けとるのが基本ということです。 逆に言えば `std::basic_string_view` で受け取ることが可能なものは文字列的なものとみなすのは妥当な考えでしょう。

そして一旦 `std::basic_string_view` になったならば統一的なインターフェイスで扱えるので実装は簡単です。 ただ、 C++ の推論規則では直接的に仮引数を推論させることが出来ないので一旦は元の型で受け取る必要があります。 また、配列の先頭要素を指すポインタという形で表現された文字列は型システム上の例外として場合分けが必要なので少し回りくどい表現になります。

以上のような思考過程を経て以下のようなプログラムを書きました。 C++17 以降を想定しています。

```cpp
#include <algorithm>
#include <iostream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>

template <class T, class = void>
class is_string : public std::false_type {};

template <class T>
struct is_string<T, std::void_t<decltype(std::basic_string_view<typename T::value_type>(std::declval<T>()))>> : public std::true_type {};

template <class T>
struct is_string<T *, std::void_t<decltype(std::basic_string_view<T>(std::declval<T *>()))>> : public std::true_type {};

template <class T>
inline constexpr bool is_string_v = is_string<std::decay_t<T>>::value;

template <class T, class U = void>
struct string_element {
    static_assert(!sizeof(T), "Expected string-like type.");
};

template <class T>
struct string_element<T, std::void_t<decltype(std::basic_string_view<typename T::value_type>(std::declval<T>()))>> {
    using type = typename std::basic_string_view<typename T::value_type>::value_type;
};

template <class T>
struct string_element<T *, std::void_t<decltype(std::basic_string_view<T>(std::declval<T *>()))>> {
    using type = typename std::basic_string_view<T>::value_type;
};

template <class T>
using string_element_t = typename string_element<std::decay_t<T>>::type;

template <class T, class... U>
inline constexpr bool is_all_same_v = (std::is_same_v<T, U> && ...);

template <class T, class... U>
auto string_append(const T &head, const U &...tail)
    -> std::enable_if_t<is_all_same_v<std::decay_t<T>, std::decay_t<U>...> && is_string_v<T>, std::basic_string<string_element_t<T>>> {
    using char_type = string_element_t<T>;
    auto input_strings = std::initializer_list<const std::basic_string_view<char_type>>{head, tail...};
    std::basic_string<char_type> result;
    for (auto &x : input_strings) std::copy(std::begin(x), std::end(x), std::back_inserter(result));
    return result;
}

int main(void) {
    // char* 同士の連結
    const std::string foo = string_append("abc", "defg", "hi");
    std::cout << foo << std::endl;

    // wchar_t* 同士の連結
    const std::wstring bar = string_append(L"1", L"2345", L"678");
    std::wcout << bar << std::endl;

    // std::string 同士の連結
    const std::string baz = string_append(foo, foo);
    std::cout << baz << std::endl;

    // std::wstring 同士の連結
    const std::wstring qux = string_append(bar, bar);
    std::wcout << qux << std::endl;

    // その他の型の文字列の連結
    const std::u16string quux = string_append(u"あ", u"いう", u"えお");
    const std::u32string corge = string_append(U"いろ", U"はにほ", U"へと");
}
```

念のために強調しておきますが、これは文字列的なもの全般に対応するにはという前提を付けたときにはこう書くことも出来るという一例であって、不必要に一般化することを是とするものではありません。
記事を気軽に書けるようになった理由を考えた

2022/9/5現在でQiita記事の初投稿から約1年半になりました。
記事数は24本です。多いというわけではないですが、平均で1ヶ月1記事以上は投稿できています。
いつの間にか気軽に記事を書けるようになっていたのですが、理由を聞かれたときにうまく答えられないことに気づいたので、ちゃんと考えてまとめてみました。

# メモはとりあえずMarkdownで書く

多くの方は、調べものをしたり教えてもらったりしたら、自分用のメモを書くと思います。
私はそれを基本的にMarkdownで書いてます。VSCodeなどのエディタだと補完も使えます。
これには3つのメリットがあります。

- Markdown記法に慣れる
- 自然とメモの内容を要約する
- Qiita記事にコピペで使える

### Markdown記法に慣れる

Markdown記法に慣れておくと、Qiita記事を迷わずスラスラ書けて楽です。
逆に、Markdown記法の復習から始めなきゃいけないとなったら、それだけでやる気ゲージを大きく消費しますね。
 **「記事を書く」** 以外の壁は事前に取り除くことが大事です。

### 自然とメモの内容を要約する

Markdown記法で一番使うのは見出し(#を先頭につけるやつ)です。
つけないと違和感が出るので、自然と見出しをつけるようになります。見出しをつけるときは、同じ内容に関する文章を要約しますよね。
つまり、見出しをつけていれば自然とメモ全体の要約が完成していることになります。
記事にしたくなったら、見出しを骨子に再構成も簡単にできます。

### Qiita記事にコピペで使える

Qiita記事を書くことだけが目的だとしたら、一番のメリットと言っても過言ではありません。
メモを丁寧に取るタイプの人なら、そのまま投稿できる可能性すらあります。

# メモはそのときに書く

「○○をやってみた」「○○の使い方」のような記事を書くときには、まずは自分が実践すると思います。
私は基本的に同時進行でメモをしています。トライ＆エラーを繰り返すような作業の場合は、実行する前にメモに手順をまとめるときさえあります。
これには2つのメリットがあります。

- 「思い出せない」を防げる
- 「大した内容ではないから...」を防げる


### 「思い出せない」を防げる

同時にメモをしておかないと、つまづいたポイントや解決方法の詳細は忘れてしまうものです。後から思い返したときに「どうやって解決したんだっけ...」と思い出せなくて、「記事に書く内容が全然ない」という現象が起こりやすいです。
きれいにまとめる必要はないので、忘れないうちにメモを書くことをお勧めします。

### 「大した内容ではないから...」を防げる

体験談や解説記事はつまづいたこととその解決策が記事の重要なポイントになると思います。
しかし1回目でつまづいたことでも、2回目以降は特につまづくことなく乗り越えられることが多いです。そうすると記事を書くときは2回目以降になるので「大した内容ではないから...」と必要がないように感じてしまいます。
つまづいたことも、忘れないうちにメモを書くことをお勧めします。



# 60～80点で公開する

記事を書くときに限らず、創作活動は100点を目指したくなりがちですよね。
でも、明確な答えがないものを創るときって100点に近づけば近づくほど作業が非効率になります。
ですので、60～80点で公開してしまった方が良いでしょう。私は、「もし後から指摘やアドバイスが来たら、そのときに修正すればいい」くらいの気持ちでいます。

# いいねが1つでももらえたら素晴らしい

記事にいいねなどで反応がもらえるとモチベーションにつながりますよね。
Qiitaで普段見る検索でヒットした記事やトレンドの記事の大半は数十～数千のいいねがついています。しかし、実際に自分で書くとなかなかいいねはつかないものです。

そこで私は **「いいねが1つでももらえたら素晴らしい」** と考えてます。少なくとも1人はその記事が良かったと言ってくれているってことですよね。普段の仕事や生活で、誰かを助けたときに「助かったよ、ありがとう。」と言われたらとても嬉しいので、それと同じようにいいねがもらえたと考えてモチベーションにつなげます。

# 結果的に1番良い記事じゃなくてもいい

理想は **最良の事例(best practice)** でも良いですが、結果的に **最大限の努力(best effort)** でも十分です。実際に私も最良の記事を書こうとはしているものの、まだ書けたことはないと感じています。
[60～80点で公開する](#6080点で公開する)とも似ていますが、完璧主義になることが一番の敵だと考えているので、そのときの自分が全力で書いていればいいと思ってます。何なら6～7割の力で書くことがほとんどです。
とは言っても、たまに全力出して書いた記事にはいいねがつきやすい気がしてるので、モチベーションが維持できるなら全力をお勧めします。

# モチベーションに左右されない方法を身につける

私は「記事を書く」ことについて、モチベーションに左右されにくいために、いつでも気軽に書けるようになったと感じています。
以下はこれまでの記事投稿頻度です。
![月別記事数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1166959/094ca5ad-5ba8-d6ab-f626-54771471d053.png)
![四半期別記事数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1166959/e97ee4b4-dae9-e257-f51e-8f17f6cbc994.png)
このグラフを見る限り、1～6月はモチベーションが低いと予想できますが、四半期別でみると結構安定しています。
実際に2022年3～6月はかなりモチベーションが低かったですが、2ヶ月に1本は投稿できました。

**モチベーションに左右されない方法** として、**習慣化**することを意識しています。
例えば、私は以下の2つを頻繫に行います。

- 記事作成のことが頭に浮かんだら1行でもこまめに編集
- 記事を投稿し終えたら、同時に次の記事のタイトルを決めて下書きを作成

これだけでもほぼ毎日記事を書くことに繋がります。どこまでいけば「習慣化した」と言えるかは難しいですが、個人的には歯磨きと同レベルになったらいいかなと思ってます。(皆さんもモチベーションに左右されず、毎日歯磨きしますよね？)


# おわりに

「記事を書く」を習慣化することを目標に頑張っています。まだ完璧ではないですが、着実に習慣化してきているかなと思ってます。
私と同じようにこの記事で紹介したことでもいいですし、自分にあったコツを見つけた場合は、そのコツを無意識にできるようにしていき、さらに記事を気軽に書けるようになるといいですね。
MySQLってインデックス貼るときテーブルロックするの？

id以外に貼るインデックスのことをセカンダリインデックスと呼ぶらしい。
でそのセカンダリインデックスを貼る時に関して、下記のような記述があった。

>セカンダリインデックス
セカンダリインデックスを作成する: CREATE INDEX name ON table (col_list) または ALTER TABLE table ADD INDEX name (col_list)。(FULLTEXT インデックスの作成にはテーブルのロックが引き続き必要です。)
セカンダリインデックスを削除する: DROP INDEX name ON table; または ALTER TABLE table DROP INDEX name
InnoDB テーブルでのセカンダリインデックスの作成および削除では、MySQL 5.5 や InnoDB Plugin を含む MySQL 5.1 と同様に、テーブルコピー動作がスキップされます。
MySQL 5.6 以降では、インデックスが作成または削除されている間も、そのテーブルの読み取りおよび書き込み操作は可能なままです。CREATE INDEX または DROP INDEX ステートメントは、インデックスの初期状態にテーブルの最新の内容が反映されるように、そのテーブルにアクセスしているすべてのトランザクションが完了したあとでのみ完了します。以前は、インデックスが作成または削除されている間にテーブルを変更すると、通常はデッドロックが発生し、それによりテーブルでの INSERT、UPDATE、または DELETE ステートメントが取り消されました。

https://dev.mysql.com/doc/refman/5.6/ja/innodb-create-index-overview.html

5.6以降であればロックしれないようですね。
React開発を快適にするChrome拡張を公開したので見てください！

**React Inspector** というChrome拡張機能を作りました。

**Chrome上でインスペクタを起動し、クリックしたReactコンポーネントのソースコードをピンポイントでエディターで開きます。(現在はVSCodeのみ対応)**

[![CleanShot 2022-09-02 at 18 08 23](https://user-images.githubusercontent.com/24843808/188106077-ff409aeb-0145-4977-9be2-16d04809cc78.gif)](https://chrome.google.com/webstore/detail/react-inspector/gkkcgbepkkhfnnjolcaggogkjodmlpkh)

- Chrome web store: https://chrome.google.com/webstore/detail/react-inspector/gkkcgbepkkhfnnjolcaggogkjodmlpkh
- GitHub: https://github.com/hand-dot/react-inspector

Reactのソースコードに直接ジャンプできるのでUIからのコードの特定がすごく楽になります。

- 新しく入ったプロジェクト
- 多言語対応されたサイト
- 昔作ったアプリのメンテ

などで使ってもらえるとソースコードを特定する時間が削減されて便利だと思います。

---

## どうやって動いているのか

[React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)というReactチームが公式に提供しているChrome拡張機能はみなさんご存知かと思います。

React Developer Tools は `__REACT_DEVTOOLS_GLOBAL_HOOK__` というグローバル変数を設定し、その後Reactは初期化中にその変数と通信します。

`__REACT_DEVTOOLS_GLOBAL_HOOK__` には `renderers` というMapオブジェクトがあるのですが、その値に格納されている `findFiberByHostInstance` というメソッドを使ってWebページ上のHTML要素からReact Fiberを探すことができます。

FiberはReactの差分検出処理エンジンです。
**しかし差分処理に必要な情報以外にも、Fiberには開発ビルド時に追加されるデバッグに使える情報がいくつかあります。**
https://github.com/facebook/react/blob/f0efa1164b7ca8523b081223954d05c88e92053b/packages/react-reconciler/src/ReactInternalTypes.js#L193

**React Inspectorは Fiberに設定されている `_debugSource` という情報を使ってVSCodeでファイル名+行+列で開く ということをやっています。**

---

## 必要条件

上記で説明したように、React Developer Toolsの設定する `REACT_DEVTOOLS_GLOBAL_HOOK` と開発ビルド時のReact Fiberを利用して動作するため、下記の2点が満たされないと動きません。

1. [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) がインストールされている
2. Reactが開発用ビルドであること
  React DevToolで開発モードの React のサイトを訪れた場合、アイコンは下記のような赤い背景となっています。
  ![](https://storage.googleapis.com/zenn-user-upload/9dc1772acda4-20220905.png)
  
---

## インスペクタの起動方法

React Developer Toolsをインストールし、Reactの開発サーバーを立てた状態で、下記の3通りの方法でインスペクタを起動できます。

1. 拡張機能のアイコンをクリック
![](https://storage.googleapis.com/zenn-user-upload/5d0a54d3ef4c-20220905.png)
2. コンテキストメニュー
![](https://storage.googleapis.com/zenn-user-upload/2bbe83a46578-20220906.png)
3. ショートカット
Mac: `Command+Shift+X`
Win: `Ctrl+Shift+X`

---

## 作った感想

- Chrome拡張は https://crxjs.dev/ を使うとTSで楽に開発できる。
- Reactの内部構造を少し知れた。Reactのソースコードを読むといろいろ発見がある。
- [GitHubレポジトリ](https://github.com/hand-dot/react-inspector)公開しているのでアイデアや不具合があれば気軽にIssueください！

[![CleanShot 2022-09-02 at 18 08 23](https://user-images.githubusercontent.com/24843808/188106077-ff409aeb-0145-4977-9be2-16d04809cc78.gif)](https://chrome.google.com/webstore/detail/react-inspector/gkkcgbepkkhfnnjolcaggogkjodmlpkh)

- Chrome web store: https://chrome.google.com/webstore/detail/react-inspector/gkkcgbepkkhfnnjolcaggogkjodmlpkh
- GitHub: https://github.com/hand-dot/react-inspector
MYSQLで詰まった話

雑なメモ


サーバー起動できなずログ確認

なんか既に使っているって言ってたからそのプロセスを消すことにした。
でも探し方がgrepでは引っ掛からずに困ってた.

下記を実行したら探せた。
```
lsof -nP -i4TCP:3306
```

上記のコマンドで見つけたプロセスをkillした。
そしたらサーバー起動に成功
【Azure】ドメインに参加している仮想マシンに接続できない！【NLA】

# はじめに
どうも、ATLのヴィリアスです。

ある日、 Azure の仮想マシンに接続しようとしたらこんなエラーが出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/ee2c7fa4-7188-a4f8-5e26-1d6b83e6e1b5.png)

エラーが出た当初は
その日、初めて仮想マシンに接続しようとしていたので直前に作業をしていたわけではないし、
あまりに突然の見覚えのないエラーだったので少し焦りました。

結果的には、無事解決できたので情報を共有します。


**※免責事項(必ず、ご一読ください)**
　　本記事の情報により生じた、いかなる損害や損失についても、当社は一切の責任を負いかねます。
　　また、誤情報が入り込んだり、情報が古くなったりすることもありますので、
　　必ずしも正確性を保証するものではありません。ご了承ください。

# 前提

**Azure の仮想マシンが何らかのドメインに参加していること。**

# 今回のエラー原因

仮想マシンとドメインコントローラー間の**セキュアチャネルが破損**していたため。

# 解決方法

## 手順1: 仮想マシンの NLA を無効にする

:::note info
NLA を無効して、仮想マシンに接続できるようにします。
:::

Azure Portal から、**該当の接続できない仮想マシンのページ**を開きます。
左メニューから、 [**実行コマンド**] を選択します。
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/1a3ac6cc-4422-0bec-e5cb-606589093e68.png)

NLA を無効にしたいので [**Disable NLA**] を選択し、 [**実行**] ボタンをクリックします。
![画像6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/316ac2f1-0dd1-07ea-aa1a-79af33313fde.png)

**実行が完了すると NLA が無効になり、仮想マシンに接続できるようになります。**

## 手順2: ```Test-ComputerSecureChannel```でチャネルを修復する

:::note info
ドメインに参加していない状態になったので、
その間に破損しているセキュアチャネルを修復します。
:::

まずは、仮想マシンに接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/234ee71e-da71-ba5c-d7f7-ae9653e24ef4.png)

仮想マシンへの接続時、ユーザー名とパスワードを求められたら
そこでは**仮想マシン自身が持つ**ユーザー名とパスワードを入力します。

:::note warn
NLA が無効化されたことで**一時的にドメインに参加していない状態になっています。**
そのため、仮想マシン自身が持つユーザー名とパスワードが必要になります。
:::

続いて、**仮想マシン上の PowerShell でチャネルを修復**します。

```Test-ComputerSecureChannel```コマンドレットが今回の肝です。
これは、**セキュアチャネルの動作確認を行うコマンドレット**です。

https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/test-computersecurechannel?view=powershell-5.1

```-verbose```オプションを付与したコマンドで、**チャネルが破損していないかの詳細確認**を行います。

```powershell
Test-ComputerSecureChannel -verbose
```

私の場合、コマンド実行後「**チャネルが破損しています**」という旨のメッセージが出力されました。

メッセージ確認後、```-repair```オプションを付与したコマンドで**破損しているチャネルを修復します。**

```powershell
Test-ComputerSecureChannel -repair
```

これで**修復完了**です！

### 補足: ```Test-ComputerSecureChannel -repair```でエラーが出る

**ユーザー名またはパスワードが正しくありません。**
→```Test-ComputerSecureChannel -repair -credential [ドメイン\ユーザー名]```で明示的に資格情報を入力してください。

**サーバーは使用可能ではありません。**
→ドメインを管理しているサーバーが動作していないかもしれません。サーバーを起動してください。

## 手順3: 仮想マシンの NLA を有効にする

最後に、無効にした NLA を 有効に戻します。
以下のコマンドを仮想マシン上で実行します。

```PowerShell
REG add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v disabledomaincreds /t REG_DWORD /d 0 /f
REG add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v UserAuthentication /t REG_DWORD /d 1 /f
```

# 参考にしたもの

https://docs.microsoft.com/ja-jp/troubleshoot/azure/virtual-machines/cannot-connect-rdp-azure-vm#troubleshoot-domain-joined-vms
89.ビルトインオブジェクト

# ラッパーオブジェクト 
## ビルトインオブジェクトとは
コード実行前にJSエンジンによって、自動的に生成されるオブジェクトのこと
=例えば自分で new ~などで自動的に生成しなくても使えるもの

## ビルトインオブジェクトの一例
```javascript
1.String
2.Object
3.Number
4.Function
5.Math
6.Boolean
7.Date
8.Symbol
```
などなど
＊見分け方としてはWindowオブジェクトの大文字からはじまるコンストラクタなど

## ＜重要＞他の言語とは違って配列はオブジェクトの一種として扱われる
```javascript
const array = new Array(1.2,3,4)
console.log(array)

console.log(array.length) //出力される
console.log(array.Array.length) //出力されない
```
![スクリーンショット 2022-09-06 10.05.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/cbc3da1b-07b1-e398-0ede-11cb9708d54d.png)


なぜ、console.log(array.Array.length)はダメなのか？
```
// これのダメな理由が以下を生成した時点で
const array = new Array(1.2,3,4)
```
![スクリーンショット 2022-09-06 10.08.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/00d5c1dc-0b20-4927-0f68-a294af4671a6.png)
既に、プロパティ、メソッド、プロトタイプの生成は終わっているんだということ
```
Array.Array.length
```
という二重にオブジェクトを生成してしまっているのだ。

つまり、配列は作成した時点で、Arrayオブジェクトなるのだ

## 補足
ちなみにオブジェクトのメソッド自体（メソッド自体のソースコード）はC++で作られているらしい→中身は確認できない
Javascriptではプリミティブ型以外は全てオブジェクトである

# ラッパーオブジェクト 
## ラッパーオブジェクトとは？
プリミティブ値を内包するオブジェクトである。
##　どゆことなのか？
以前から伝えていたこと
プリミティブ型以外は、全てオブジェクトである！
といっていた
じゃあ、
文字列や数値は一切オブジェクトから生成させるプロパティやメソッドが使えないのか？
ということになる
そこで
ラッパーオブジェクトがプリミティブ型くんたちに言いました。

お前らだけでプロパティやメソッド使えないのはかわいそうだから
なんとかするよ。
と、プリミティブ型を包み込むようにオブジェクトっぽいことができるようになったのがラッパーオブジェクト

```javascript
const a = 'hello' /* 文字列 */
const b = 100			/* 数値 */

console.log(a.toUpperCase());
console.log(b.toExponential());
```
まるでビルトインオブジェクトのように、簡単に使えます。
オブジェクト型じゃないのに、普通にメソッドが使えるのはビルトインオブジェクトのおかげです
岩舘電気の中の人が、Windows 11 の右クリック問題を Active Directory の設定で解決してみた

　こんにちは、岩舘電気の中の人です。久々の投稿です。

　Windows 11 が企業にも徐々に入ってきていていますが、Windows 10 よりもなんとなく使いづらいなあ・・・と思っている人もいるんじゃないでしょうか。個人的には、Windows 10 に戻したいくらいの気持ちでいます。特に、右クリックが2段階メニューになってしまったのにはどうしても慣れることができませんでした。これについてはレジストリをいじることで設定が変えられるのですが、コンピュータの管理者としては Active Directory を使ってすべての社員の PC の設定を一括で変更してしまうのもよいかもしれません。

　岩舘電気では、拡張子の表示をさせるためにドメインユーザの設定を Active Directory を使って変更していますが、Windows 11 の右クリック問題も同様にして解決してしまうことにしました。

　ただし、Windows 11 以外の環境が混在している場合に影響がないとも言えません。Windows 10 に設定が適用されても動作に影響がないことは確認していますが、保証するわけではありませんので、ご理解のうえ読み進めていただければと思います。気になる方は、Windows 11 のときだけレジストリの編集をするようなログオンスクリプトを書いたほうが良いと思います。

　まずは、Active Directory サーバでグループポリシーの管理を立ち上げます。ドメインの中にあるグループポリシーオブジェクトのなかに、設定用のオブジェクトを一つ作成します。すでにADで何らかの設定をしている人はオブジェクトがあると思いますので、そのなかに追加してもよいでしょう。環境や目的によって適宜使い分けしてください。

　作成したグループポリシーオブジェクトを右クリックして編集を選択すると、オブジェクトの編集画面が現れます。この中の「ユーザ構成」を展開していくと、「レジストリ」という項目があります。この中にレジストリ変更用のオブジェクトを作成します。下のスクリーンショットでは 「Win11右クリック変更」という名前でオブジェクトを作成しています。

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61220/3e2055f6-7e0a-12ac-c29b-3fe70fa151a8.png)

このなかで、次のようなダイアログが現れるので編集を行います。

![タイトルなし.2png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61220/b7ef03b7-085b-d538-ea54-7a0811f16d45.png)

こちらの画面にあわせて編集をすればいいのですが、キーのパスは次の値を指定してください。

Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32

オブジェクトの作成が終わったらダイアログを閉じ、グループポリシーの管理に戻って、このグループポリシーオブジェクトの適用先のOUを指定してあげれば終了です。


Tips ですが、参考になれば幸いです。
axiosについて

# axiosとは
- HTTP非同期通信ライブラリー。
- バックエンドとデータを受け渡しをする際に使うライブラリー。
- バックエンドと通信できるURLに非同期でアクセスしてget, post, update, deleteの作業を行うことができる。

# axiosのメリット
- バックエンドとの通信時に自動的にデータをjson形式に変換する。
- リクエストをキャンセルすることができる。
- 幅広いブラウザー＆バージョンに対応。
- アップロードやダウンロード時に進行状況の情報を取得することができる。

# axiosのデメリット
- 外部のライブラリーであるため、インストールが必要

# axiosの特徴
- axiosから要請したレスポンスはPromiseのオブジェクトである。
- そのため、以下の使用方法のようにasyncとawaitを使って簡潔に記述することができる。


# axiosの使用方法
- axiosをインストールして以下のように利用することができる。

~~~javascript:javascript
async function getUser() {
  try {
    const response = await axios.get('/user?ID=12345') //非同期でURLにアクセスしてバックエンドからデータを受ける。
    console.log(response)
  } catch (error) {
    console.error(error)
  }
}
~~~

# 例外処理
バックエンドとのやりとり中にはさまざまな例外が発生するため、例外処理を行う必要がある。
やり方としては `try & catch` と `await & catch`が挙げられ、以下のように使うことができる。

#### try & catchパターン
~~~javascript:javascript
async function getUser() {
  try {
    const response = await axios.get('/user?ID=12345') //非同期でURLにアクセスしてバックエンドからデータを受ける。
    console.log(response)
  } catch (error) {
    console.error(error)
  }
}
~~~

#### await & catchパターン
~~~javascript:javascript
async function getUser() {
  const res = await axios.get('/user?ID=12345')
  .catch((err) => {
    return err
  })
}
~~~

# axios以外の非同期処理方法
実は非同期処理にはaxios以外にも複数あり、代表的には`fetch`, `jQuery`があり、それぞれ使い方は異なるが、基本概念は変わらない。なお、fetchはES6から使えるようになった非同期処理のためのjavascriptの内に組み込まれたAPIである。以下は、axiosとfetchの違いについてまとめたものである。

### axiosとfetchとの違い
||Axios|Fetch|
|--|--|--|
|インストール|必要|いらない|
|JSON変換|自動変換|手動的に変換する必要あり|
|requestのキャンセル設定|可能|不可能|
|ダウンロードプログレス|利用可能|不可能|

#### fetchの使い方
< GET >
~~~javascript:javascript
const url = '/user?ID=12345';
fetch(url)
    .then(response => response.json())
    .then(data => {
        console.log(data);
    })
    .catch(error => {
        console.log(error);
    });
~~~

< POST >
~~~javascript:javascript
const url = '/user?ID=12345';
const params = {
    name: '山田太郎',
    email: 'taro@example.com',
    password: 'secret'
};
fetch(url, {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(params)
})
.then(response => response.json())
.then(data => {
    console.log(data);
})
.catch(error => {
    console.log(error);
});
~~~

#### jQueryの使い方
< GET >
~~~javascript:javascript
const url = '/user?ID=12345';
$.get(url)
    .done(data => {
        console.log(data);
    })
    .fail(error => {
        console.log(error);
    });
~~~
< POST >
~~~javascript:javascript
const url = '/user?ID=12345';
const params = {
    name: '山田太郎',
    email: 'taro@example.com',
    password: 'secret'
};
$.post(url, params)
    .done(data => {
        console.log(data);
    })
    .fail(error => {
        console.log(error);
    });
~~~
Azure AppConfigurationでユーザー割り当てマネージドIDにアクセスするのに苦戦した話

 前回（[SpringBootのProfileとAzure AppConfigurationの組み合わせでハマった話](https://qiita.com/yukiko-bass/items/fb8771556c84b8e57e81)）の続きでさらに苦戦した（といってもそこまででもないけど）ので覚書を。
地味な罠多すぎ。

## 環境

- SpringBoot 2.6+
- Java 11
- Azure Configuration
- Spring Cloud Azure App Configuration version 2.5.0
- ユーザー割り当てマネージドID を作成する（もしくは権限がある人に作ってもらう）

## やること

- 作成したユーザー割り当てマネージドIDを AppConfiguration の ロール割当の追加から、マネージドIDを選択して、App Configuration データ閲覧者 ロールを追加する
    - [App Configuration へのアクセスの許可](https://docs.microsoft.com/ja-jp/azure/azure-app-configuration/howto-integrate-azure-managed-service-identity?tabs=core5x&pivots=framework-spring#grant-access-to-app-configuration)
- AppConfiguration の中から KeyVault の参照もしているようであれば、KeyVault のアクセスポリシーに ユーザー割り当てマネージドID を追加する必要がある
    - ないとAccessDenied になる
- bootstrap-${profile}.yml の記述方法を以下にする

```YAML
spring:
  cloud:
    azure:
      appconfiguration:
        managed-identity:
          client-id: <ユーザー割り当てマネージドID のclient id>
        stores:
          - endpoint: https://<AppConfiguration の Endpoint>-conf.azconfig.io
            selects:
              - label-filter: <任意のラベル>
```

## 補足

罠のハマりポイントとしては、Azure側のドキュメントのユーザー割り当てマネージドID のclient idの指定するプロパティが間違ってるっぽいところなんですよね。。
[マネージド ID の使用
](https://docs.microsoft.com/ja-jp/azure/azure-app-configuration/howto-integrate-azure-managed-service-identity?tabs=core5x&pivots=framework-spring#use-a-managed-identity)

>  注意
> ユーザー割り当てマネージド ID プロパティ spring.cloud.azure.appconfiguration.stores[0].managed-identity.client-id を使用する場合、ManagedIdentityCredential の作成時に必ず clientId を指定してください。

これに関しては、Spring Cloud Azureの公式のほうが正解です。
[5.2. User Assigned Identity](https://microsoft.github.io/spring-cloud-azure/docs/azure-app-configuration/2.5.0/reference/html/index.html#user-assigned-identity)

```
spring.cloud.azure.appconfiguration.managed-identity.client-id= <your client id>
spring.cloud.azure.appconfiguration.stores[0].endpoint= <URI of your Configuration Store>
```

全然違うやんけ。
もしかしたらSpring側がバージョンアップとかで変わった可能性はあるかもしれないですが。

## 雑感

yamlで書いてたんでインデント間違ってるのかとか色々やりましたが、結局は公式をよく読みましょうってところですね。SpringとAzureのドキュメントは少ないし、ググってもあんまり出て来ないし、だいたい英語で辛いところではありますが。

## 参考

[Spring Cloud Azure App Configuration](https://microsoft.github.io/spring-cloud-azure/docs/azure-app-configuration/2.5.0/reference/html/index.html)
エラーが発生した時に確認する記事まとめ

# 目次
1. はじめに
1. 記事一覧

# はじめに
Konyで開発をしていてうまく動かない場合や、
検索しても問題が解決しない場合は、下記に紹介する方法を試してみてください！

下記記事の内容は順次更新をしており、
**Konyで開発をしているメンバーがこれまでに遭遇したエラー**をまとめています。

記事に書いている内容はあるあるの内容なので、
是非ブックマークをしておくことをお勧めします:relaxed::raised_hand:

# 記事一覧

**「開発したいのにVisualizerが開かない・・！」**　という時に見る記事
エラーの原因を調査できるlogの見方などをまとめています。まずはこちらをチェック！👀
▶︎[Loading状態から開かない？｜プロジェクトが開かない時に試したい5つの対処法](https://qiita.com/Kony_Team/items/41c94e7d8225306eb1b4)

**「Visualizerでの開発が上手くいかない・・」** という時に見る記事（Web,iOS,Android共通）
▶︎[Konyでよく遭遇するエラーまとめ　＊Kony Visualizer 起動〜開発編＊](https://qiita.com/Kony_Team/items/0667ca2c8ee346f046d7)

**「アプリBuildが上手くいかない・・」** という時に見る記事
▶︎[Konyでよく遭遇するエラーまとめ ＊Build編（共通）＊](https://qiita.com/Kony_Team/items/4a1ac93faf43b2a92dc3)

**「iOSの開発が上手くいかない・・」** という時に見る記事
▶︎[Konyでよく遭遇するエラーまとめ ＊Build編（iOS）＊](https://qiita.com/Kony_Team/items/2dbb66b34c05e09369f7)

上記記事を見ても解決しないよ！という方は、
次に紹介するbasecampの使い方で公式ドキュメントを参照してみてくださいね:writing_hand_tone1:

# 次の記事

次は、Kony公式ドキュメントを検索する方法についてまとめています！
▶︎[basecampの使い方](https://qiita.com/Kony_Team/items/3ce70aa09c78465bc448)

記事一覧：
https://qiita.com/Kony_Team/private/4c922fa016ce95c58406

# 最後に一言
より読みやすい記事にしていきたいので、
「ここがわからなかった！」
「ここがもっと知りたい」
など、コメントいただけると嬉しいです！
Linux タイムゾーンと設定方法について（自分用メモ

国や地域ごとの標準時間帯をタイムゾーンという。タイムゾーン毎に協定世界時（Coordinated Universal Time: UTC）からの時差などが決められている。
Linuxの内部では、UTC 1970年1月1日午前0時0分0秒からの経過秒数であるエポック（epoch）時間で時間を管理しており、設定されたタイムゾーンにしたがってエポック時間から変換し、日付時刻を扱う。エポック時間はUNIX時間（Unix Timestamp）とも呼ばれる。

●タイムゾーンの主な設定方法。

1. 「/usr/share/zoneinfo/」ディレクトリ以下のバイナリファイルと「/etc/localtime」ファイルを使用する

「/usr/share/zoneinfo/」ディレクトリ以下には、国や地域ごとにタイムゾーンの情報がバイナリファイルとして格納されている。タイムゾーンの設定は、それらのバイナリファイルから、システムで使用したいタイムゾーンのものを「/etc/localtime」へコピーまたはシンボリックリンクを作成することで行える。

2. 「/etc/timezone」ファイルを設定する
vi /etc/timezone
Asia/Tokyo

3. 環境変数TZを設定する（各ユーザの設定）
例）システムのタイムゾーンを日本にする場合
$ export TZ=Asia/Tokyo

4. tzconfigコマンドを使用する（Debian系）
tzconfigコマンドは「/etc/localtime」と「/etc/timezone」ファイルをまとめて設定する。


●tzselectコマンド
環境変数「TZ」や「/etc/timezone」ファイルで指定するタイムゾーンの値を確認するコマンド
Xcodeでのsimulator起動時に文字入力でキーボードが表示されない時の解決法

Xcode Version 13.4.1 (13F100)
Swift version 5.6.1


スクール学習でメモアプリを作成練習中、シミュレーターを起動してキーボードの表示非表示の切り替えをする機能を実装していたら、キーボードが表示されなかったので表示させるための対応をメモ。

<h2>状態</h2>

![キーボードが表示されない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821821/c05d32d5-1511-2fd0-80cc-54edeb7d1b28.png)
<br>
iPhone画像の一番下にキーボード非表示ボタンの「Done」だけが表示されている状態。
<h2>やりたいこと</h2>

![スクリーンショット 2022-09-06 9.17.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821821/427a25de-c3ad-3a3f-4c9e-583e146dafe3.png)
みなさんがよく見る入力する画面。キーボードが表示され入力が可能

<h2>解決方法</h2>

![スクリーンショット 2022-09-06 8.59.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821821/ecf13062-3e3e-6847-1ade-b46656031036.png)
<br>
１：シミュレーターを開いた状態から、メニューバー「I/O」を選択<br>
２：「KeyBoard」にカーソルを合わせる。<br>
３：「Connect Hardware Keyboard」を選択し、チェックを外す。<br>
４：チェックを外しても変わらない場合、何度か付けたり外したりする。この時変更したら毎回iPhone画面をクリックしてみる。<br>
<br>
細かく説明すると、<br>
「I/O」：「Input/Output」の略で、キーボードやマウスなどのinput装置、ディスプレイやプリンターなどのoutput装置の設定<br>
「Keyboard」：キーボードに関する設定<br>
「Connect Hardware Keyboard」：PCでのキーボード入力にするかどうかをチェックマークをつける。<br>
このチェックマークをつけているとシミュレーター上の文字入力がPCのキーボードで可能になる。<br>
iPhone上だけでの文字入力をするためには「Connect Hardware Keyboard」を選択しチェックを外さないといけない。<br>

<h2>感想</h2>
・画像が大きくてすいません。
・正直iPhoneでの操作なんだから初期設定でiPhone上のキーボードを使用するようにしておいた方が助かる、、、と思ったんですが、どんな挙動を確認したくてシミュレーターを起動するかによるから設定方法を知っておくべきなんだなと思いました。<br>
初学者だから初期設定で固定する方法を知らないだけかもしれませんが、これは後日調べます！
ポータルエンティティフォームに追加設定

![1キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654080/9e7150d9-609f-95ba-d715-ac75027ecd01.png)

````
<div id="notescontrol">
  <div class="col-md-1 entity-notes" data-add-accept-types="*" data-add-enabled="True" data-attachmentsettings ="a78fsad7f6adsa">
  <div class="col-md-2 xxxx"></div>
  <div class="col-md-3 xxxx"></div>
  <div class="col-md-4 xxxx"></div>
  <div class="col-md-5 xxxx">
    <div class="col-sm-3"><a class="addnote btn btn-default" href="#" role="button" style="float: left;">ファイル選択</a></div>
  </div>
  </div>
</div>
```````
![2キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654080/d5c244c9-f38a-ee7a-35b2-375498708274.png)



```````

//画面②エンティティフォームの追加設定JS
$(document).ready(function () {

  //画面①のバリュー取得
  var value1 = window.parent.$("#new_value1").val();
  var value2 = window.parent.$("#new_value2").val();
  
  //画面①のメソッドを呼び出し
  //許認可証書類チェック
  var inputCheck = window.parent.checkInputData();
  
  //画面③画面の添付ファイルの表示名変更
  $(".entity-notes a.addnote").on("click", function () {
    $("#note_label_add").text("備考");
    $("button[class='primary btn btn-primary']").text("アップロード");
  });
});
````
Asyncio 互換の PostgreSQLドライバ asyncpg 

Pythonプログラムに速度を求めていろいろ**asyncio**を試しています。
**（関連過去記事）**
[Python Asyncio入門 - Qiita](https://qiita.com/sand/items/0e445a13d81d20ea33c3)
[Python Asyncio で作る Socket Server -Qiita](https://qiita.com/sand/items/4f27e62c7491b8e85d12)

Asyncio 互換の PostgreSQLドライバ **asyncpg** を試してみました。 特徴は速いことです。公式サイトで公開されている以下のパフォーマンスレポートをご参照ください。
[PostgreSQL Driver Performance Benchmark Report](https://github.com/MagicStack/asyncpg)




以下に**asyncpg**の簡単なサンプルプログラムを掲載します。



```Python:main.py
import asyncpg
import asyncio

GORILLA_CREATE_TABLE = \
    """
    CREATE TABLE IF NOT EXISTS gorilla(
        gollira_id SERIAL PRIMARY KEY,
        name TEXT NOT NULL,
        pos TEXT NOT NULL,
        age INT NOT NULL
    );"""
GORILLA_INSERT_TABLE = \
    """
    INSERT INTO gorilla (name, pos, age) VALUES ($1, $2, $3)
    """
GORILLA_DROP_TABLE = \
    """
    DROP TABLE IF EXISTS gorilla
    """
GORILLA_QUERY_TABLE = \
    """
    SELECT * FROM gorilla
    """

async def main():
    connection = await asyncpg.connect(host='127.0.0.1',
                                       port=5433,
                                       user='postgres',
                                       database='gorillas',
                                       password='xxxxxxxxxx')
    
    status = await connection.execute(GORILLA_DROP_TABLE)
    print(status)
    status = await connection.execute(GORILLA_CREATE_TABLE)
    print(status)
    await connection.executemany(GORILLA_INSERT_TABLE, 
            [('モモタロウ','父ゴリラ',24), ('ゲンキ','母ゴリラ', 35),
             ('ゲンタロウ','長男ゴリラ', 9), ('キンタロウ','子ゴリラ', 4)])
    golilla_list = await connection.fetch(GORILLA_QUERY_TABLE)
    for golli in golilla_list:
        print(f'ゴリラid: {golli["gollira_id"]}, 名前: {golli["name"]},'\
              f'地位: {golli["pos"]}, 年齢: {golli["age"]}')
 
    await connection.close()

asyncio.run(main())
```


実行結果です。

```
python main.py
DROP TABLE
CREATE TABLE
ゴリラid: 1, 名前: モモタロウ,地位: 父ゴリラ, 年齢: 24
ゴリラid: 2, 名前: ゲンキ,地位: 母ゴリラ, 年齢: 35
ゴリラid: 3, 名前: ゲンタロウ,地位: 長男ゴリラ, 年齢: 9
ゴリラid: 4, 名前: キンタロウ,地位: 子ゴリラ, 年齢: 4
```

今回は以上です。
SQLServerで分散トランザクションを利用するための手順（補足記事）

# 概要
SQLServerで分散トランザクションを利用するためにはいくつかの設定が必要です。
この手順が少し複雑だと感じたため、今回この記事で補足をしようと思います。
基本的な手順は、後述する**前提条件**にある記事を参考にしています。
またSQL Serverを提供している[Microsoftの公式ドキュメント](https://docs.microsoft.com/en-us/sql/connect/jdbc/understanding-xa-transactions?view=sql-server-ver16#configuration-instructions)や[IBMのドキュメント](https://www.ibm.com/docs/ja/bpm/8.6.0?topic=creation-configuring-xa-transactions)でも解説されており、この記事はそれらを私なりに補足しながらわかりやすくまとめなおしたものになります。

:::note warn
正確な情報は一次情報である公式ドキュメントを参考ください
:::

### 記事にしようと思った経緯
- 分散トランザクションに関するドキュメントが少ないこと
- 公式ドキュメントは補足事項が少ないと感じたこと
- SQLServerのバージョンが古い場合の対応方法がわからなかったこと



### 対象者
この記事では、主に下記の方が対象者となります。

- （SQLServerで）分散トランザクションを検討中の方
- 実装してみたが、SQLServerの設定をしておらず詰まった方


### 環境情報
|項目 |対象情報  |
|:-:|:-:|
|OS   |Windows |
|ライブラリ  |atomikos |
|言語  |Java |
|フレームワーク  |SpringBoot |




### 参考記事・前提条件
**手順はこちらの記事を参考にしています。**
[★1つのトランザクションで複数のDB(OracleとSQL Server)を更新するアプリケーションでAtomikosを利用してみた](https://www.purin-it.com/spring-boot-oracle-sqlserver-atomikos)

分散トランザクションの実装方法についてまとめた私の記事です。
[comming soon..]()

こちらは、下記の**手順3**で詰まった場合に参考になったGitHub issue上でのやり取りです。
翻訳すると、`xa_install.sql`に関する情報のやり取りが確認できます。
[sp_sqljdbc_xa_install と新しいドライバーリリースについて [GitHub issue]](https://github.com/microsoft/mssql-jdbc/issues/1514)



# 手順
前提条件となる[★参考記事]を基に下記手順を行ってみてください。
1. コンポーネントサービスからDTC(分散トランザクションコーディネーター)のXAトランザクションを有効にする
2. SQL Server 構成マネージャーを起動し、SQL Serverのサービスを再起動させる
3. `sys.sp_sqljdbc_xa_install`を実行し、分散トランザクションが利用できるようになる権限を付与する

:::note info
SQL Server 2017以降の環境だと上記手順のみで分散トランザクションが正常に実装・実行できると思われます。
その場合は、これより下の手順は不要となります。
:::


### 分散トランザクションを利用できる権限を付与する（手順3 別パターン）
SQLServerのバージョンが古いなどの理由で、`sys.sp_sqljdbc_xa_install`が存在せず、【手順3】が実行できない場合は下記手順が必要です。
**実はここからが、私が記事にして伝えたかったことになります。**
（私はSQLServer2012の環境で作業を行っていたため、下記の方法で行っています）

::: note info
この部分の手順については、公式ドキュメントにも一部記載がありますのでご一読ください。
- [Microsoftの公式ドキュメント](https://docs.microsoft.com/en-us/sql/connect/jdbc/understanding-xa-transactions?view=sql-server-ver16#configuration-instructions)
- [IBMのドキュメント](https://www.ibm.com/docs/ja/bpm/8.6.0?topic=creation-configuring-xa-transactions)
:::

#### 権限付与の手順
1. [MicrosoftSQL Server JDBC Driverのダウンロードページ](https://docs.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server?view=sql-server-ver16)からJDBC Driverをダウンロードする
2. ダウンロードしたzipファイルを解凍し、内部のxa ディレクトリ配下に、`xa_install.sql` と `sqljdbc_xa.dll` のファイルがあることを確認する
3. `sqljdbc_xa.dll`を分散トランザクションを使用する SQL Server インスタンス上の`/Binn`配下にコピーする
    例えば、`C:\Program Files\Microsoft SQL Server\MSSQLFOGEFOGE\MSSQL\Binn`に配置します
    ※`MSSQLFOGEFOGE`の部分は実際には`instanceName`が入ると思います
4. `xa_install.sql`をMicrosoft SQLServer Management Studioやコマンドプロンプトなどで実行する
5. プログラムを実行して挙動を確認する

ここまで実施することで、分散トランザクションは正常に動作すると思います。

# 補足

手順を何も行っていない時点でプログラムを実行すると、下記のエラーメッセージが表示されました。（期待値の参考までに）

```console
XA コントロール接続を作成できませんでした。エラー: "ストアド プロシージャ 'master..xp_sqljdbc_xa_init_ex'が見つかりませんでした。"
```


また、手順2番目終了時点でプログラムを実行すると、下記のエラーメッセージが表示されました。
```console
SQLServerException: XA コントロール接続を作成できませんでした。エラー: "接続は閉じられています。"
```
MacにUiPathをインストールする

# はじめに
UiPath（Studio/Robot）は、.NET Framework 4.6ベースのアーキテクチャであるため、登場して以来長らくWindows専用でしたが、v2021.4より.NET5（v2022.4からは.NET6）をサポートするようになり、もしかするとWindows以外でも動かせるようになるのでは？となりました。
そして、v2021.10のStudioでクロスプラットフォーム（.NET5）のワークフローを実装できるようになり、最新のv2022.4では正式にMac版Assistantがリリースされました。

ということで、今回はMacにUiPathをインストールしてみます。

# つかうもの
※ クラウド環境は2022年9月時点のもの
* UiPath Assistant　v2022.4
* Automation Cloud（Orchestrator）　※ Community版

# ハードウェア/ソフトウェア要件
以下の公式情報は、最新のv2022.4のハードウェア要件およびソフトウェア要件となりますが、見たところWindows版の条件のみだと思われます（ハードウェア要件は参考にしてもいいかも）。

https://docs.uipath.com/installation-and-upgrade/lang-ja/docs/robot-hardware-and-software-requirements

代わりにMac版のインストールに関する公式情報は以下となります。

https://docs.uipath.com/robot/lang-ja/docs/assistant-on-mac

これによると、現時点でMacにインストールできる製品は、AssistantのみでStudioは対象外となるようです。さらに、ハードウェア・ソフトウェア要件は、MacOS 10.15（Catalina）以降となり、その他の要件の記載はありません。

OSのバージョン以外何でもOKということで、10年前のMacBookが眠っていたので、これを使うことにします。
まずは、OSをCatalinaにアップデートしました。

:::note info
余談ですが、OSアップデート前（10.12 Sierra）に試しにインストールしてみましたが、インストールできたもののRobotサービスとの通信エラーで正常に動作できませんでした。
:::

# インストーラを手に入れる
まず、インストーラを入手します。
Automation Cloudにアクセスし、リソースセンターからダウンロードできます。
![インストーラ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/5c8eec6b-a71f-859c-5cd2-1855f156516d.png)

「おすすめのダウンロード」の中にある、macOS用Assistantの「インテルCPU」または「Appleシリコン（M1）」のどちらかを選択します。使用しているMacのCPUに合わせて選択してください。

インストーラは、.dmgファイルとなります。
![インストーラ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/5845d003-2b0e-2af6-a95a-1d38dc6783db.png)

# インストールする
.dmgファイルをダウンロードしたら、ファイルをクリックして展開します。
![インストール1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/2aa359a3-3581-6ddc-74d3-12104bcc2669.png)

UiPath Assistant.appをアプリケーションフォルダにドラッグアンドドロップすれば、インストール完了です。
![インストール2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/0d868d2e-53a5-29a8-9b00-3129f78ec010.png)

# Orchestratorに接続する
Mac版のAssistantは、ローカルパッケージフィードを使うことができません（スタンドアロンのAttendedでは使えないということになります）。Orchestratorとつなぎ、Orchestratorからパッケージをダウンロードする必要があります（Marketplaceからダウンロードする手もありますが、あまり使用する機会はないと思います）。
つまり、Orchestratorと接続しないと全く意味がないので、まず先にOrchestratorと接続します。今回の接続方法は対話型認証とします。
![OC接続1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/3ead4faf-db98-8971-112d-9ff56d724532.png)

Windows版と同様にサインインするとOrchestratorと接続し、ライセンス認証できました。
![OC接続2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/fd1d18fa-dda1-9567-4e7d-3323f2a9b530.png)
![OC接続3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/f30be763-99f6-5057-1b4f-39e4a6b6158f.png)

# Windows版との差異
Mac版とWindows版のAssistantについて、メニュー・機能面では大きな差異はありません。
ワークフローを動かしてみて、差異があれば次回の記事で書きます。

# おわりに
Windows版と比べ、インストール時のオプションが一切なく、とても簡単な作業でした。
そして、10年前のMacでも無事にインストールできました。

次はワークフローを動かしてみます。
OmniStudio / OmniScript Q&A


[omniscript 概要](https://qiita.com/Keiji_otsubo/items/01a0f7225813c7815b5a)


+ [OmniStudio 未解決](https://qiita.com/Keiji_otsubo/items/5cc159302bd1154a5791)

+ [Omniscript へのゲスト ユーザー アクセス](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000HDxwo)

:::note
Please follow the steps given in the link and it should work. Also ensure that sharing rules are in place for the objects you want guest user to access.

https://help.salesforce.com/s/articleView?id=sf.os_grant_digital_experience_guest_users_omnistudio_access_7519.htm&language=en_US&type=5
:::

# トレイルヘッド関係

+ [Start Routing with Omni-Channel not working](https://qiita.com/Keiji_otsubo/items/96e25446724bc5ebd9f8)

# 言語設定が英語しかデプロイできない？

[Has anyone experienced this error deploying an OmniScript to a community page?](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000DzPwb)


# 次と前のボタンをオムニスクリプトから非表示にするにはどうすればよいですか？

[How to hide the next and previous buttons from omniscript?](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Fxl3b)


# Omni Supervisor AllAgentsタブがロード時にスタックする

[Omni Supervisor AllAgentsタブがロード時にスタックする](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000FS2MI)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2058b401-343c-e6cc-dd10-2e54a0d32aff.png)

# Omniscript Step Select 要素に動的オプションを入力できません

回答: Apex と入力マップを使用して動的な選択オプションを入力することは、製品チームにとって既知の問題です。動的な Select オプションを設定するには、カスタム lwc を使用する必要があります。
[Unable to populate Omniscript Step Select element with dynamic options](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000JdTnI)
人生初のハッカソン感想と実装アプリ(Twitter取得・WordCloud・共起ネットワーク)

人生で初めてハッカソン出場したのでその感想と実装したアプリの概要です。

https://odhackathon.metro.tokyo.lg.jp/


# 動機
システム関連の仕事をしているので、人生で一回くらいやってみようと思い、参加しました。入賞は目指しておらず、経験してみよう、くらいな気持ち。

# 振り返った感想
ちょっとおもしろかった程度。人生で1回位経験してもいいが、ハマるほどではない。
自分自身が開発というプロセスや社会課題解決そのものにワクワクできない人だということを再確認できました。このハッカソンが珍しいのかわかりませんが、時間をかけようと思えばいくらでもかけられるので、仕事などとの線引きしないと厳しいな、と思いました。

# 学んだこと
以下の3つを学びました。基本的に急ぎでやるので、やり方ググってコピペするレベルの浅い学び方になります。仕事でやったりする場合には、ある程度深く学ぶのですが、ハッカソンではそこまでやらないですね。

- TwitterのTweet取得方法
- WordCloud出力
- 共起ネットワーク
- Firebase
- HTMLとCSS
- Bootstrap
- Vue.js

# 一人参加
チームビルディングのサポートがあったり、誰かを誘えばチームを組んで参加もできましたが、以下の理由で一人参加にしました。

1. マイペースでやりたかった
1. 課題解決に対してディスカッションをすることに魅力を感じなかった
1. 課題設定や設計・実装は一人でできる
1. 入賞目的ではないので、人数増やしてすごいものを作りたいと思わなかった

# つくったもの
「都議ログ」という名前で都議会議員の仕事内容を都議会議事録から可視化するWebアプリを作りました。Firebase上にHostingしています。

## 画面
### 一覧画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/42a572fe-dc3e-2a96-b1e3-fe5375ebbfee.png)

### 詳細画面
#### 詳細画面全体
サンプル(架空の人)です。下側に都議会議事録とTwitter検索結果の2種類をタブ表示。サンプルなので、都議会議事録の共起ネットワーク画面はなし(他議員はあり)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/4d780b91-898b-1f42-4f7e-e6439978a16c.png)

#### Twitter情報
木下ふみこ元議員の場合。サンプルではない中で一番有名な人です。「無免許」や「ガーシー」が印象的。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/7fbecdfb-02ca-168e-d735-e3ba85663e9d.png)

### おまけ
Twitter情報のWordCloudは、歴代総理3人と党代表3人だとこんな感じ。

#### 岸田さん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/e4d45b04-cab0-cfe1-3291-6a6f8a7e9c18.png)

#### 菅さん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/b6771fa2-a842-1a3f-ada1-92307c755c6b.png)

#### 安倍さん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/fe798d40-4fea-cdca-17e6-a171a33a9b26.png)

#### 泉さん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/3e15e666-99a9-22d1-20bb-2d92ee94bed3.png)

#### 松井さん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/72ecec75-755b-d576-a563-6f957386b547.png)
アジャイル開発は計画しない？


> チームが計画づくりに示す態度は両極端なものになりがちである。つまり、まったく計画しないか、計画が「絶対に正しい」と納得できるまで労力を費やしすぎるかのどちらかだ。[^1]

アジャイル開発について「計画しない」と誤解してしまうことが多いことがあります。

とくにアジャイル開発を **ウォーターフォール開発の反対** と捉えてしまうと、この誤解は正しそうに見えます。

なぜならウォーターフォール開発が「正しい計画をつくってから、ものをつくりはじめる」という特徴を持つのだから、アジャイル開発は「計画をせずに、ものをつくりはじめる」のだ。このように考えるのは不思議ではありません。

あるいは**ガチガチにコミットしてしまった計画**に疲れ果ててしまい、計画から逃げるための手段としてアジャイルに希望を見出すようなパターンもあるかもしれません。

しかしアジャイル開発においても、計画は必須の要素です。では何が異なるのでしょうか。

## 計画を「つくり続ける」ということ

アジャイル開発における計画は、計画以上に**計画づくり**に重きを置きます。

なぜ計画よりも計画づくりを重視するのか。それは、**計画することで見えてくる課題があるから** です。

> 立てた計画はじきに見直され、破棄されてしまう。しかし、計画づくりの過程で得た知識や洞察はずっと後まで残る。[^2]

計画づくりを続けることで、たとえばチーム内で次のような課題を見つけ、先回りして解消することができます。

- プロダクトが本当に解決すべき問題はどうやらAではなくBっぽそうだ。この仮説を検証する方法はあるか？
- このペースで進むと再来週には開発完了しそうだ。その場合、他チーム〜の件の進捗も確認しておかないといけなそうだ
- 半年後の目標をふまえると、いまのペースだと終わらない。スコープの縮小を検討しはじめよう

## 計画を見直す

計画をつくり続けるということは、つまり**計画を見直す**ことでもあります。

アジャイル開発は決して「その場しのぎの計画」をつくり続けるものでもありません[^3]。それぞれの規模の計画をつくり続けます。

> 目に見える範囲を大きく超えて計画を立てているにも関わらず、計画を見直す時間を組み込んでいないのであれば、そのプロジェクトは危険にさらされていることになる。計画には段階的な詳細化が不可欠である。[^4]

今週の計画が崩れたなら、来週や来月の計画に影響がないか考える。来月の計画が変更されるなら、今週の計画を変更すべきか考える。

一度立てた計画を壊さないように無理をするのではなく、立てた計画を変更できる状態を維持しながらふりかえりを続ける。

アジャイル開発は計画を軽視しているのではなく、むしろ**つねに計画とともにある**ような印象を受けます。

## 計画に対する姿勢のちがい

ここまで見てきたことをまとめると、ウォーターフォール開発とアジャイル開発の関係は対義ではなく、差異があると考えるべきでしょう。

これは「計画」においても同じで、計画に対する姿勢がそれぞれで次のように異なるとまとめられそうです。[^5]

| | ウォーターフォール | アジャイル |
| --- | --- | --- |
| **計画の有無** | 計画する | 計画する |
| **計画の頻度** | 最初だけやる | ずっと続ける |
| **計画にかける時間** | 長時間かける | 短い時間で頻繁に繰り返す |
| **計画の変更** | 変更しづらい | 変更しやすい |

アジャイルにおける計画の重要さが伝われば、とても嬉しいです。

## 参照

- [アジャイルな見積りと計画づくり | マイナビブックス](https://book.mynavi.jp/ec/products/detail/id=22141)

[^1]: Mile Cohn『アジャイルな見積りと計画づくり ～価値あるソフトウェアを育てる概念と技法～』、p26。

[^2]: 同、p34。

[^3]: テーマが異なるので詳細は別の記事で補足しようと考えています。

[^4]: 同、p53。

[^5]: 個人的にはウォーターフォールをいつもアンチパターンとして取り上げることに違和感を持っています。ただ説明としてはわかりやすくなると考え、このように表現させてもらいました。