OmniAICreator/Qiita-1.07M huggingface dataset:
soql中相同order by的项目，可能最终排序结果不同

可以参考这个文档
https://safe.menlosecurity.com/docview/viewer/docND1DE72BB11D45dd7b440f77084e4ef4bf6e9667c5e9fd5094579dd637f74bfaa968aec905ec5
的27页

```
ORDER BY

Use the optionalORDER BYin aSELECTstatement of a SOQL query to control the order of the query results, such as alphabeticallybeginning with z. If records are null, you can useORDER BYto display the empty records first or last.

You can use ORDER BYin aSELECTstatement to control the order of the query results. The syntax is:[ORDER BYfieldOrderByList{ASC|DESC} [NULLS {FIRST|LAST}] ]

Note:There’s no guarantee of the order of results unless you use an ORDER BYclause in a query.And even if you useORDER BY, the order of results can vary if there are duplicate values for the fields you’re using in theORDERBYclause. 

For example, if there a multiple Account records with the same Industry, the order of the results for this query can vary:SELECT Name, Industry FROM Account ORDER BY IndustryTo avoid this issue, 

add the Id (or any other field that is unique in the results) to theORDER BYclause. For example:SELECT Name, Industry FROM Account ORDER BY Industry, Id
```
エンジニアの勉強法ハックLT- vol.6に参加して

今回は**エンジニアの勉強法ハックLT- vol.6**に参加してきました。
直接的な技術系の勉強会ではありませんが、現職のエンジニアや駆け出しの新人、学生さん、またエンジニアコンサルティングの方など幅広い側面からの視点で、エンジニアにおける勉強法やモチベーションキープの方法についてを聞いてきました。
その中でも、私が共感したもの特に気になったものについてまとめていきます。

イベント詳細： [エンジニアの勉強法ハックLT- vol.6](https://rakus.connpass.com/event/223691/)

## 教えるを通して学ぶ
トップバッターの [kabo36さん](https://connpass.com/user/kabo36/)のお題です。
こちらの方は、入社３年目にして後輩を指導する経験をされたところから得た知見を発表していただきました。

### 教えるには３つのサイクルがある
#### 学ぶ
自分がわからないことは相手にも教えることはできない。
まずは学ぶ。方法はなんでもいい。
#### 教える(伝える)
ただ学んだことをそのまま伝えるだけでは教えることにはならない。
伝える相手のレベルに合わせた噛み砕き方が必要
自分が伝えたいことより**相手が知りたがっていることを軸に**伝えることが重要
#### 残す
教えた時の気づきや改善点をメモしておく
課題はメモにするだけではなく「タスク」にする

教えることは何よりの学びということがよく言われるように、実際に勉強するインプットよりもアウトプットによって気づけることがたくさんある。

## うるせぇ！！！やろう！！！
こちらは３人目の登壇者の [ganyariyaさん](https://connpass.com/user/ganariya/)の発表でした。
ganyariyaさんは現在大学院に在籍し、来年度から新卒社会人として活躍される方でした。
彼が大学在籍中や普段から意識していることを中心にお話しいただきました。

### うるせぇ！！！やろう！！！とは？
有無を言わずにチャンスには手を伸ばそう
お誘いを受けたらとりあえずやってみるとか
→意外と何とかなる

学生時代でも社会人になってもふとした時に大きく成長できるチャンスが転がってるかもしれない・・・

### チャンス＝成長の機会
当然、新しいことや未経験なことは怖いし恥ずかしい
→やらないよりはやったほうがいい
**声をあげない人よりかは確実にひよっことしても成長できているはず**
#### →悩んだらとりあえずやってみよう

私個人としてはganyariaさんの発表が一番納得いきましたし、すごいいいこと言うなとも思いました。

## 〇〇駆動と心理学　〜あなたの欲求はどこから？〜
こちらは最後の登壇者の[Dame Nianchさん](https://note.com/xparams/n/nd483d50eab94)の登壇でした。
心理学を勉強した経験から、学習をするに当たっての行動の向き先やその人なりのきっかけについてお話しいただきました。

### 学習とは
学習は勉強という行為に属している一つの行動に過ぎない。
また学習することによって、経験を得たり変化をもたらすことができる。

この方は学習について４つの分類分けをして説明していただきました。

|  |経験|行動の変化|
|:--:|:--:|:--:|
|なまけもの|x|x|
|ポンコツ|o|x|
|えらい|o|o|
|神|x|o|

#### なまけもの
経験もしないし、よって行動の変化も起きない最低なライン。

#### 神
経験を得なくても行動に変化が出るしメキメキ成長する。
もはやそんな人は存在しない。（いるのかもしれないけどそれは本当の神）

```
勉強してないけどある日ロシア語が読める！話せる！
何もしてないのに神アプリ作っちゃってぼろ儲け！
```

#### ポンコツ
経験はしたけど行動の変化が伴わない人

```例
ロシア人美女とお友達になりたいからロシア語勉強しました。
でもダメでした
→経験と変化先の不一致（身の丈に合っていない）
```

### でもポンコツでもいいじゃない
何かしらの行動を起こすことによって経験は得られるし、身の丈にあってくれば行動にも変化が伴ってくる。
原理としては うるせぇ！！！やろう！！！ と同じかもしれない。
HTMLメールで隙間が出来たときに試すこと（画像間のスペース）

# 背景
* HTMLメールをコーディングしていました
* ブラウザでは問題なく表示
* 広告メディアへ出稿すると「画像間に隙間があります」と返答アリ
* 広告メディアからのスクショを見ると、確かにスペースが入っている
* デザイン上、そのままでは不都合

# どうしたか（誤魔化した）
* HTMLメールは`table`組みされることが多いが、問題の箇所は`div`に置き換えた
* 画像要素を`div`でラップし、その`div`に**background-color**をかけた（要は隙間を不自然じゃないように塗りつぶした。隙間自体は存在したまま）

```html:htmlメール例

<!-- Before -->
<table cellspacing="0" cellpadding="0" border="0" style="width: 100%">
  <tr>
    <td style="padding: 0"><img src="img01.jpg" width="600" style="max-width: 600px; width: 100%" alt="画像１" /></td>
  </tr>
  <tr>
    <td style="padding: 0"><img src="img02.jpg" width="600" style="max-width: 600px; width: 100%" alt="画像２" /></td>
  </tr>
</table>

<!-- After -->
<table cellspacing="0" cellpadding="0" border="0" style="width: 100%">
  <tr>
    <td>
      <div style="background-color:#000"> <!-- 例えばスペースを黒に塗りつぶし -->
        <div style="padding: 0">
          <img src="img01.jpg" width="600" style="max-width: 600px; width: 100%" alt="画像１" />
        </div>
        <div style="padding: 0">
          <img src="img02.jpg" width="600" style="max-width: 600px; width: 100%" alt="画像２" />
        </div>
      </div>
    </td>
  </tr>
</table>


```



# 他のHTMLメールを見て気づいたこと
* キレイに出来ている（スペースがなさそうな）HTMLメールのソースを確認したところ、画像１つ１つに`height`が設定してあった。しかも`style`属性ではなく、`height`属性として...
* 試してないけど、スペースに悩んでいたら、試す価値はあると思う

```html:htmlメール例２

<!-- 画像にheight属性を追加 -->
<table cellspacing="0" cellpadding="0" border="0" style="width: 100%">
  <tr>
    <td>
      <div style="background-color: #000">
        <div style="padding: 0">
          <img src="img01.jpg" width="600" height="512" style="max-width: 600px; width: 100%; height: 512px" alt="画像１" />
        </div>
        <div style="padding: 0">
          <img src="img02.jpg" width="600" height="426" style="max-width: 600px; width: 100%; height: 426px" alt="画像２" />
        </div>
      </div>
    </td>
  </tr>
</table>

```
【CSS/HTML】class属性とid属性について

# class属性とid属性とは
class属性とid属性は、特定の要素に対して指定を行いたい場合、HTMLのタグに名前を付けるために使用される。CSSでは、特定の要素をセレクタで指定するために```id```や```class```で付けられた名前を用いる。
■ ***classとidの違い***
```class```：1ページの中に何度も同じ値（名前）を使うことができる。（重複可）
```id```：1ページの中に同じ値（名前）一度しか使うことができない。（重複不可）

また、```id```と```class```ではCSSでのスタイルが適用される優先順位が決まっており、***classよりもidのスタイルが優先される***。

# CSSでのセレクタ指定方法
CSSにおいてidやclassで名前を付けた要素をセレクタに指定する場合は、idは```#```、classは```.```を付けて以下のように記述できる。
しかし、スタイルシートでは***idセレクタを使用すべきではない***。

```css
/* idセレクタの場合 */
#<id名>{
    <プロパティ>: <値>;
}
/* classの場合 */
.<class名>{
    <プロパティ>: <値>;
}
```
React（Next.js/GraphQL）からHasuraを使ったCRUD操作のためのクリックイベントの処理の作成

## はじめに

CRUD操作のための処理部分をこれまで作成してきました。

詳細👇

https://qiita.com/ryosuketter/items/d9106135dd81bee3c038

前回は、Stateの定義やformコンポーネントの作成をしました。

https://qiita.com/ryosuketter/items/ce645c491f6df4e0688b

今回からは、ブラウザを通じでCRUD操作を行うためのインターフェイス部分を何回かに分けて作成していきます。

具体的には下記を作成していきます。

- Stateの定義
- クリックイベントの処理 👈 本記事はコレについて書いてます
- コンポーネント（レイアウト）の用意
    - form部分
    - ユーザーの一覧を表示させる部分

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## クリックイベントの処理

前回の記事で、formコンポーネントのonSubmit処理には関数`handleSubmit`をセットしましたね。

今回は、その中身を作成していきます。

場所は、そこまでこだわりありませんが、コンポーネントをreturnするすぐ上にでも書いてみましょう。

```jsx:pages/hasura-crud.tsx
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
  e.preventDefault()
  if (editedUser.id) {
    try {
      await update_users_by_pk({
        variables: {
          id: editedUser.id,
          name: editedUser.name,
        },
      })
    } catch (err) {
      alert(err.message)
    }
    setEditedUser({ id: '', name: '' })
  } else {
    try {
      await insert_users_one({
        variables: {
          name: editedUser.name,
        },
      })
    } catch (err) {
      alert(err.message)
    }
    setEditedUser({ id: '', name: '' })
  }
}

if (error) return <Layout title="Hasura CRUD">Error: {error.message}</Layout>

return ()
```

`async`, `await`の詳細は下記を参照してください。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function

非同期処理に関しては下記を参照してください。

https://qiita.com/ryosuketter/items/dd467f827c1b93a74d76

引数とその型（`(e: FormEvent<HTMLFormElement>)`）は見たままって感じなので説明省きます。

リロードしちゃうので、`e.preventDefault()`しています。

で、次の条件文ですが、ユーザーのidがあれば、更新、無ければ新規作成という条件分岐になっています。

![Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f2e675a4-538f-b55f-4e55-e0959de9ca06.png)

更新用の関数は `update_users_by_pk` を定義したので、こちらを実行しています。

```tsx
const [update_users_by_pk] = useMutation<UpdateUserMutation>(UPDATE_USER)
```

`update_users_by_pk`関数の引数は

更新対象のユーザーのidと名前です。

```tsx
await update_users_by_pk({
  variables: {
    id: editedUser.id,
    name: editedUser.name,
  },
})
```

そして、通信中などでエラーが発生した場合はcatchで補足して、alertして、ダイアログ上にエラーメッセージを表示できるようにしておきます。

最後に、更新処理が終わったらStateを元に戻しています。

```tsx
setEditedUser({ id: '', name: '' })
```

else 以下、 `{}`の中は、新規作成ですね。実行する関数は`insert_users_one`です。

```tsx
await insert_users_one({
  variables: {
    name: editedUser.name,
  },
})
```

引数 variables内はnameだけを受け取れるようにします。

エラー処理と、Stateの初期化部分は更新処理と同じです。

## エラー時のレンダリング

上でしれっと書いてありますが、👇 コレです。

```jsx:pages/hasura-crud.tsx
if (error) return <Layout title="Hasura CRUD">Error: {error.message}</Layout>
```

`error`がtrueなら、`return`の右側が表示される仕組みです。

次回は、ユーザーの一覧を表示させる部分を見ていきます。

今日のところは以上です。

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
React（Next.js/GraphQL）からHasuraを使ったCRUD操作のためのStateの定義やformコンポーネントの作成

## はじめに

CRUD操作のための処理部分をこれまで作成してきました。

詳細👇

https://qiita.com/ryosuketter/items/d9106135dd81bee3c038

今回からは、ブラウザを通じでCRUD操作を行うためのインターフェイス部分を何回かに分けて作成していきます。

具体的には下記を作成していきます。

- Stateの定義 👈 本記事はコレについて書いてます
- クリックイベントの処理
- コンポーネント（レイアウト）の用意
    - form部分 👈 本記事はコレについて書いてます
    - ユーザーの一覧を表示させる部分

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## Stateの定義

CRUD操作をお好なうと、ユーザーの新規作成や、更新の処理が発生します。

ここでは、ユーザーの編集用のStateを作成します。

`useState`を使います。

```tsx:pages/hasura-crud.tsx
import { VFC, useState, FormEvent } from 'react'
// 省略

const HasuraCRUD: VFC = () => {
  const [editedUser, setEditedUser] = useState({ id: '', name: '' })
  // 省略
  return (  // 省略 
)}
```

初期値は`id`と`name`を空文字で定義しています。

## コンポーネント（レイアウト）の用意

form部分とSubmit部分を作成していきます。

```jsx:pages/hasura-crud.tsx
<form
  className="flex flex-col justify-center items-center"
  onSubmit={handleSubmit}
>
// ユーザーが情報を入力できるinputフォームを作成予定
// submitボタンのコンポーネント作成予定
</form>
```

formコンポーネントのonSubmit処理には関数`handleSubmit`がセットされています。

処理内容は次回紹介します。

それでは、formコンポーネントの中に、ユーザーが情報を入力できるinputフォームを作成していきます。

```jsx:pages/hasura-crud.tsx
<form
  className="flex flex-col justify-center items-center"
  onSubmit={handleSubmit}
>
  <input
    className="px-3 py-2 border border-gray-300"
    placeholder="New user ?"
    type="text"
    value={editedUser.name}
    onChange={(e) =>
      setEditedUser({ ...editedUser, name: e.target.value })
    }
  />
  // submitボタンのコンポーネント作成予定
</form>
```

`onChange`の内容を見ると、Typingのたびに、先ほど定義た`setEditedUser`関数が実行されます。

中身の説明をすると、オブジェクト`{}`の中で既存の要素`...editedUser`はそのままに、`name: e.target.value`こんな感じで名前だけを追加しています。

それでは、formコンポーネントの中に、もう一つ、submitボタンを作成します。

```jsx:pages/hasura-crud.tsx
<form
  className="flex flex-col justify-center items-center"
  onSubmit={handleSubmit}
>
  <input
    className="px-3 py-2 border border-gray-300"
    placeholder="New user ?"
    type="text"
    value={editedUser.name}
    onChange={(e) =>
      setEditedUser({ ...editedUser, name: e.target.value })
    }
  />
  <button
    disabled={!editedUser.name}
    className="disabled:opacity-40 my-3 py-1 px-3 text-white bg-indigo-600 hover:bg-indigo-700 rounded-2xl focus:outline-none"
    data-testid="new"
    type="submit"
  >
    {editedUser.id ? 'Update' : 'Create'}
  </button>
</form>
```

`disabled`を見ると、`disabled={!editedUser.name}`要するに空の場合は

`disabled={!''}` → `disabled={true}` になるのでボタンが押せなくなります。

その時のstyle（tailwindcss）も作成しておきます。

```
className="disabled:opacity-40 my-3 py-1 px-3 text-white bg-indigo-600 hover:bg-indigo-700 rounded-2xl focus:outline-none"
```

ボタン内の文言は、`editedUser.id`が

- 存在すれば更新 （`'Update'`）
- 無ければ、新規作成 （`'Create'`）

という条件で出し分けられるようにします。

次回は、formコンポーネントのonSubmit処理の関数`handleSubmit`の内部処理を見ていきます。

今日のところは以上です。

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
VisualStudio2012でnugetに繋がらない現象の解決

# NuGetパッケージの管理が接続できない
いつしかWindows7+VisualStudio2012環境で、[NuGetパッケージの管理]から、nuget.org( https://www.nuget.org/api/v2/ )に接続できなくなって、VisualStudio2012ソリューションでnugetが利用できなくなってしまって困っていた。

極小ソリューションはVisualStudio2019にまで上げたけど、少しごちゃごちゃしてるソリューションだと気が引けて、諦めていた。

# 問題
よくわからんが、VisualStudio2012では、TLS1.0でしか接続しないらしい。
つまりはもはやサポートされていないセキュリティ設定で接続しようとするからダメなんだよ、ということみたい。

# 解決方法
1. 表示 -> その他のウィンドウ -> パッケージマネージャーコンソール を開く。
1. コンソールで次のコマンドを実行する。

```
[Net.ServicePointManager]::SecurityProtocol=[Net.ServicePointManager]::SecurityProtocol-bOR [Net.SecurityProtocolType]::Tls12
```

1. [NuGetパッケージの管理] を開く。

# 注意
コマンドはVisualStudioを起動している間しか有効にならないため、起動の度にコマンドを実行しなければならない。
少し手間だし、そんなコマンドする忘れるし、作業者が複数人いるとそれを注意しなければならない・・・。
助かったけど、nugetパッケージ使ってると初めてのリビルドのタイミングからこれを意識しなければならないのでちょっと勝手が悪い・・・。
開発畑でない開発マネジャーのお仕事？

こんにちは。

社内の発信から、アドベントカレンダーの参加オファーを受けたことをきっかけに、Qiitaを始めました。

今回は、自分のテストを兼ねて、「開発畑でない開発マネジャーのお仕事」について書いてみます。

私は、プロフィールに記載したようなキャリアなのですが、そんな私だからこそできること、苦悩していることを書きます。もちろん、両方たくさんあるのですが、その中から一つずつ取り上げます。

①できること

開発部門に来てしばらく過ごして、最も強く感じたのは、「開発者にとって、学び、遊びがとても重要」ということです。

コンサルタント部門では、目の前のお客様の対応に追われる日々でした(※もちろん喜びもありましたが)。開発部門にも、そこへの支援を求めてきたと思います。はい、これは実際、かなり強く求めてきました。当時から、うるさいだろうなという自覚はありましたし、今でも、これはこれで必要なことであるとも思っています。

しかし、開発者が100%、そこにフォーカスしてしまうと、解決策がどうしても場当たり的なものになり、プロダクトが抱える根本的な問題の解決が、二の次、三の次になってしまいます。問題を根本から解決する機能の追加やリファクタリング、製品の技術的負債の解消などです。

これを繰り返すと、開発者は「場当たり的な問題解決のスキル」が向上していきます。結果、それを繰り返す方が楽で、根本解決は大変だからやらない、という方に傾いていってしまうのです。

「それで回っているなら良いのでは？そういうもんじゃない？」という意見もあるかも知れませんが、この点は今回、割愛します。私は、それではダメだと判断しました。

そこで、一例として、自部門内で「Bukatsu」という取り組みを始めました。これは、簡単に言うと「業務時間の10%程度を、学びのための時間に当ててください」というものです。これにより、今使っている技術や言語、機能に寄った発想に限らない問題解決のアプローチを見出せる開発者を育てたい、そういう開発組織にしたいということです。

アイディア自体はありふれたものと思いますが、一つは、これを「開発畑でない人間が立ち上げた」ことに意味があると思っています。

開発畑の開発者が、「開発者にとって、学び、遊びがとても重要」と主張することは、もちろん可能です。しかし、それを他の部門の人間はどう感じるでしょうか。また、開発者本人もそれを感じて、声を大にして主張することは難しいかも知れません。

しかし私の場合、「あいつが立ち上げた」という時点で、既にある程度、他の部門の人間の納得を得ることができます。もちろん、それでも納得できない人もいるかも知れませんが、その場合も、その声を私が受けることができます。

こういった、「ときに第三者目線」でいられるからこそ言い易いことを発信し、出せる価値を出していくことは、仕事の一つであると思っていて、日々の活動でも意識しています。

②苦悩していること

できることで尺を取ってしまったので(汗)、今回はシンプルにいきます。

端的に言って、コーディングスキルでメンバーに敵わないので、殆どのコードレビューで、中堅以上のメンバーにレビュワーとして同席してもらう形になっています。

そうでなくてもレビュワーは複数いるべきだよね…説もありつつ、若手メンバーが書いてきたソースの書き直しの具体案などもそういったメンバーに出してもらったりしていて、まぁ、ここは正直複雑なところもありますね…。

では、今回はこの辺で。
JavaScriptを基本からまとめてみた【19】【Reactを使うために知っておきたいJavaScriptの基本②】

####モダンJavaScriptの機能に触れる

##const、letの変数宣言

- ほぼ全部constで定義できる
- 数え上げのみletを使用する
- varはほとんど使わない

####let, const, varの特徴
|　  | l e t |const | v a r  |
|---|---|---|---|
|再代入|⚪︎ |×  |⚪︎  |
|再宣言  |×  |×  |⚪︎  |
|ブロックスコープ  |⚪︎  |⚪︎  |×  |
|関数スコープ|⚪︎  |⚪︎  |⚪︎  |

##テンプレート文字列

####テンプレート文字列とは
テンプレート文字列はテンプレートリテラルとも呼ばれ、テンプレート文字列で書くとプレースホルダーを記述することができ、文字列の中で、+を用いた結合を使わずに変数や定数を表示させることができる。

```
構文: const str = `テンプレート文字列`;
```

##分割代入とは

####分割代入とは

分割代入とは配列やオブジェクトから値を取り出して、変数に代入してくれるJavaScriptの機能。





##参考サイト
[モダンJavaScriptの基礎から始める挫折しないためのReact入門]
(https://www.udemy.com/course/modern_javascipt_react_beginner/learn/lecture/21899196#overview)
[【JavaScript】var / let / const を本気で使い分けてみた]
(https://qiita.com/cheez921/items/7b57835cb76e70dd0fc4)
[テンプレート文字列とは？モダンJavaScriptの勉強]
(https://programmer-life.work/javascript/template-leteral-modern-javascript)
Azure ADによる適応型アクセス制御の現在

#適応型アクセス制御とは
セキュリティではよく認証認可という言葉を聞くと思いますが、認証と認可（アクセス制御）の違いはご存じでしょうか？一般的には認証と認可（アクセス制御）は以下のように定義されています。

>認証：ID に紐づいたパスワード/生体情報などで本人性を確認すること
>認可（アクセス制御）：認証された本人であることを前提にリソース（サービス/データなど）に対する権限をコントロールすること

当記事では認可（アクセス制御）の分野で注目されている「適応型アクセス制御」について解説します。
従来アクセス制御はユーザ属性やロールを元に実行されていました。それに加えていわゆるコンテキスト情報を元に制御する技術があります。アクセス元の IP アドレスやデバイスの状況といった静的なコンテキスト情報を元に判断するリスクベースアクセス制御（リスクベース認証と呼ぶベンダーもあり）に加え、最近では AI による脅威分析などを組み込んだ動的なリスク判定も可能となっています。動的なリスク判定を含むアクセス制御を**適応型アクセス制御**と呼んでおり、NIST SP 800-207 ゼロトラストアーキテクチャにおいても必要な機能と記載されています。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/54f3576d-fdc2-51f9-bcca-93cdfc4ee2b8.png)

#Azure Active Directory における適応型アクセス制御
Azure Active Directory （以降 Azure AD) ではリスクベースアクセス制御を「条件付きアクセス」と呼んでいます。 Azure AD Premium Plan 1（以降 P1 ) の条件付きアクセスでも、静的なコンテキスト情報によるリスクベースアクセス制御は可能で、社内ネットワークからのアクセスか否か、組織のポリシーに準拠したデバイスか否かなどの条件で、多要素認証の要求/アクセスのブロックを設定できます。更に Azure AD Premium Plan 2 (以降P2）に含まれる Identity Protection を利用することで、より高度な適応型アクセス制御が可能となります。
Azure AD Identity Protection では、ID にかかわるリスクを「サインインリスク」「ユーザーリスク」に分類し、一日約 6.5 兆件検知される様々なシグナルを機械学習で分析することで高度なリスク判定を可能としています。具体的には下表のイベントを検出し、そのリスクスコアに応じた対処をアクセスポリシーに組み込むことが可能です。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/c5257eea-ddce-92bf-b2bc-05d5572f16cb.png)
参考リンク：リスクとは Azure AD Identity Protection | Microsoft Docs
https://docs.microsoft.com/ja-jp/azure/active-directory/identity-protection/concept-identity-protection-risks

アクセスポリシーは独自に設定することも可能ですし、プレビュー（2021/11時点）として提供されているテンプレートを元にすることもできます。Identity Protection に関連するものとしては以下の２つのテンプレートが提供されています。
Azure Portal から、条件付きアクセスのポリシーを作成する時に、「テンプレートから新しいポリシーを作成」を選択、テンプレート カテゴリの選択は 「ID」を指定してください。
![図2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/f35fc511-8108-1a5b-19b0-95b8b9a6b319.png)
![図2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/a282d0f3-5dfe-989f-9471-bb9cf13cecd9.png)
#Azure AD Identity Protection によるリスクの自動修復
Azure AD Identity Protection は、検知されたリスクに対しポリシーを強制するだけでなく、修復の自動化まで組み込むことができます。例えば以下のシナリオでは不正アクセスと思われるログイン試行をブロックし、次回正規ユーザがアクセスした際に多要素認証を要求した上でパスワード変更を強制することで、攻撃者が入手したパスワード情報を意味のないものにすることも可能です。更に Sentinel や Splunk を始めとした SIEM (Security Information and Event Management) やSOAR （Security Orchestration, Automation and Response）ソリューションを使うことで、アプリケーション含めた広範なログ分析や、より複雑な対応を組み込むことも可能です。
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/54c183c7-38b8-2d94-1760-f463e3a284e9.png)

#まとめ
条件付きアクセスとAzure AD Identity Protection を使うことで最新の適応型アクセス制御を容易に組み込み、ID にかかるセキュリティの高度化を図ることが可能です。また対応を自動化することで、高いセキュリティレベルを維持しつつ運用コストの最適化にもつながります。在宅勤務などでリモートアクセスが増加している場合には、すべてのシステム利用の起点となる認証アクセス制御の強化を検討してみませんか？

次回の記事では「 パスワードレスってどんな技術 ? 」を掲載する予定です。

投稿内容は私個人の意見であり、所属企業・部門とは関係ありません。
Java 17で追加されたHexFormatクラス

この記事は[SRA Advent Calendar 2021](https://qiita.com/advent-calendar/2021/sra)の1日目の記事です。

こんにちは！　関西事業部の佐々木です。

#3年ぶりのLTSバージョン
2021年の9月にリリースされたJava 17は、2018年リリースのJava 11以来のLTSバージョンになります。
（実際にLTSとするかどうかはJDKのディストリビュータによりますが）
LTSなので当然適用されることも多くなりそうなJava 17ですが、どのような変更点があるのか気になるところです。
JDK 11からの全ての追加APIを知りたい場合は
https://docs.oracle.com/en/java/javase/17/docs/api/new-list.html
を参考にしてもらうとして、この記事では個人的によく使うことになりそうな **HexFormt** クラスを紹介したいと思います。

#16進数表記用のクラス
ここ数年私が関わっているプロジェクトでは「16進数表記」を使う機会がとても多く、バイト配列と16進数文字列の変換なども頻繁にコーディングしています。
そのような場合、今までは外部のライブラリを使うことが多かったのですが、Java 17からは **HexFormat** クラスを使えばよさそうです。
ちなみにHexFormatクラスはimmutableでスレッドセーフです。

#HexFormatの使い方
HexFormatクラスを使うにはstaticメソッドの `of()` でオブジェクトを取得します。

```java
HexFormat hex = HexFormat.of();
```

バイト配列から16進数文字列に変換するには `formatHex()` メソッドを使います。

```java
byte[] bytes = {0, 1, -1, 10};
String hexString = hex.formatHex(bytes);
//hexString ==> "0001ff0a"
```

16進数文字列をバイト配列に変換したい場合は `parseHex()` メソッドを使います。

```java
byte[] bytes = hex.parseHex("0aff");
// bytes ==> byte[2] {10, -1}
```

引数に渡す16進数文字列は大文字でも小文字でも、混同しててもOKです。

```java
byte[] bytes = hex.parseHex("0AfF");
// bytes ==> byte[2] {10, -1}
```

バイト配列を **大文字の** 16進数文字列に変換したいときは `withUpperCase()` メソッドを使ってHexFormatオブジェクトを取得します。

```java
HexFormat hex = HexFormat.of().withUpperCase();

byte[] bytes = {0, 1, -1, 10};
String hexString = hex.formatHex(bytes);
//hexString ==> "0001FF0A"
```

他にも色々メソッドがありますが、よく使いそうなのはこれらになると思います。
複数バージョンのRを共存させ、Rsutdioでスイッチして使う

R(v4.1.2)をインストールしてRstudioから作業を行っている。
このバージョンのRに対応していないパッケージがあり、古いバージョン（v3.6.3）のインストールを行う。
インストールは通常通りここから行った。https://cran.r-project.org/bin/windows/base/old/3.6.3/

インストールの際にこのプログラムを呼び出す際の名前をデフォルトの「R」から「R363」に変更して、あとは通常通り行った。
Rは通常のR（v4.1.2）とR363(v3.6.3)の2つがインストールされている状態になった。

最後にRstudioでマウントするRのスイッチは、Tools > Global Options > General を選択し、R:versionのプルダウンリストから切り替える。
GitHubでリリースノートをいい感じに作る

どんなプロダクトもそうですが、リリース作業をしていると「あれっ、このバージョンってこの修正入れてたっけ？」といったことが起こってきます。

一人で管理していても起こりますが、複数人のチーム開発をしているとなおさらです。
リリース（デプロイ）を行うごとにリリースノートを細かく書いていけばよいのですが、なかなかそこに労力を費やすこともできません。

できるだけ自動化できないかなということでスクリプトを作成してもらいました。




```release_note.bash
#!/usr/bin/env bash
set -e
# 差分を取りたいバージョンを２つ指定してください
# e.g. $ release_note.sh v1.7.6.2 v1.7.6.3

# 1 各種バージョンに分ける
# 2 差分ごとの結果を表示する

PRE_VER=$1
CURRENT_VER=$2
RESULT=""
GIT_HUB_API_TOKEN="xxxxxxxxxxx" # GitHubのトークンを指定
REPO_PATH="yousan/testrepo"

function markdown() {
  # git logからIssue番号を抜き出す
  numArray=($(git log ${PRE_VER}...${CURRENT_VER} | grep "Merge pull" | awk '{print substr($4,2,5)}'))

  # Releaseノート用、Markdown形式
  for issueNum in "${numArray[@]}"; do
    ISSUE_TITLE=$(curl -sH "Authorization: token ${GIT_HUB_API_TOKEN}" https://api.github.com/repos/${REPO_PATH}/issues/${issueNum} |
      grep title | tr ':' '\n' | sed -n 2P | sed -e 's/ \|"\|,//g' | sed -e 's/",$//g' | sed -e 's/ "//g') # issueのタイトルを取得
    ISSUE_DESC="[#${issueNum}](https://github.com/${REPO_PATH}/pull/${issueNum}) ${ISSUE_TITLE}"
    echo ${ISSUE_DESC}
    RESULT+=${ISSUE_DESC}$'\n'
  done
}


# パターン
# 1. 比較対象バージョンのみ指定 relese_note.sh v1.7.6.2
## v1.7.6.2 と現在の差分を取る => CURRENT_VER: HEAD, PRE_VER: v1.7.6.2
# 2. 指定なし relese_note.sh
## 一つ前のバージョンと現在の差分を取る => CURRENT_VER: HEAD, PRE_VER: v1.7.6.2
if [ -z "$CURRENT_VER" ]; then # 未設定の場合には
  CURRENT_VER="HEAD"
fi

if [ -z "$PRE_VER" ]; then # 未設定の場合には
  PRE_VER=$(git tag | sort -V | tail -1)
fi

echo "## [${PRE_VER}](https://github.com/${REPO_PATH}/releases/tag/${PRE_VER}}) -> [${CURRENT_VER}](https://github.com/${REPO_PATH}/releases/tag/${CURRENT_VER})"

markdown
```

動かし方としては
1. `git log` で２つのバージョン間の差分（PR）を取る
2. 差分の詳細をGitHub APIで取ってくる

という流れになっています。
UIViewのドラッグ (生)

タップ検知方法は、
生のタップ情報から任意イベントを検知をする自由度が高い方法と、
UIGestureRecognizerが用意した基本タップイベントのテンプレートを使う方法
の主に二つがあるが、
前者の生でもドラッグ検知だけなら簡単ということがわかったので、試してみた。

## 実装

```DraggableView.swift
import UIKit

// ドラッグだけ実装したヴュー
class DraggableView: UIView {
    // ドラッグ検知メソッド
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {// このビューへのタップ取得。ちなみにデフォルトではマルチタップのプロパティはfalseになってるので、ここではfirstのみ考えればおk。
            assert(false)
        }
        let loc = touch.location(in: self.superview)
        let oldLoc = touch.previousLocation(in: self.superview)// 動かす前の座標
        // 前の位置と差分をとって、その分ヴューを動かす。
        let diffX = loc.x - oldLoc.x
        let diffY = loc.y - oldLoc.y
        
        var center = self.center
        center.x += diffX
        center.y += diffY
        
        self.center = center
    }
}
```
## 動作
![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252245/aa5e71ba-6822-9817-0786-4dd2fcdbf0e0.gif)

## 原理
ざっくりいうと、
・デバイスで検知したタップイベント情報（座標、タップ状態（開始、ステイ、ドラッグ中、終了）、等）をアプリケーションが受け取って、
・アプリケーションはそれをタップ対象のviewに渡して（厳密にはUIViewが継承してるUIResponderに渡して）、
・view側ではタップ状態に対応した(UIResponderの)メソッドが呼ばれるようになっている（今回で言うとドラッグ中→touchesMoved（））

ということみたい。

拡大など複数の指による操作も、touchesMoved（）以外のタップ状態に対応したメソッドも駆使すればできる模様
ただ、このように生のタップイベント情報を使って実装するとコードが複雑化していくので、ドラッグなどの単純なタップイベント検知はUIGestureRecognizerにテンプレートが用意されているので、UIGestureRecognizerの方を使った方がいいとのこと。

UIGestureRecognizerでのドラッグも試した：

https://qiita.com/Zousaaaaaan/items/70c7f701aaa8f2c8c09c

# 参考文献
https://www.amazon.com/Programming-iOS-13-Controllers-Frameworks/dp/1492074616
UIViewControllerのviewにxibを使用する

# 概要
xibfileから、UIViewControllerのviewのoutletを紐付ける。

# 手順
1.xibfileのfile's ownerをViewControllerに指定する。これで、ViewControllerのviewのoutletがxibfile側から見えるようになる。
2.ViewControllerのviewのoutletに、xibfileのrootviewを紐付ける。
3.storyboardに紐づいているViewControllerの場合、storyboard側の実装が優先されるので、storyboard側ではViewControllerのviewを削除しておく。
Frameworks/dp/1492074616![スクリーンショット 2021-04-24 18.36.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252245/2658a1a6-f504-03dd-d855-1218026f4367.png)

# 感想
こういうやり方もあるのかーと言った感じ。

個人的には、XibviewのoutletがViewController内に洗われるのが嫌なので、XibviewをViewControllerのVIewとして使う場合は、xibfileのfileOwnerにUIView指定して、そのUIViewをViewControllerのloadView()内でviewに指定する方が好きかな、と思う。

## 参考文献
https://www.amazon.com/Programming-iOS-13-Controllers-
Azure Filesでの NFS 4.1 サポートが開始されました

今まで、Azure FilesはCIFS共有のみをサポートしていました。以下のコマンドを使用して、CIFS共有をマウントできます。

```
$ sudo yum install cifs-utils -y
$ sudo mkdir -p /cifs
$ sudo mount -t cifs //mystorage.file.core.windows.net/share /cifs -o vers=3.0,credentials=$HOME/.credentials,dir_mode=0777,file_mode=0777,serverino
```

残念ながら、CIFS共有はPOSIX権限をサポートしていませんでした。
したがって、すべてのファイルは同じユーザーが所有し、同じ権限を持っている必要があります。
uid/gidオプションを使用してマウント時に所有者を変更でき、file_mode/dir_modeオプションを使用してマウント時にファイルモードを変更できます。

```
$ ls -l /cifs
total 1
-rwxrwxrwx. 1 root root 180 Nov 17 05:03 file1
-rwxrwxrwx. 1 root root 180 Nov 17 05:03 file2

$ sudo chown omi:omi /cifs/file2; sudo chmod go-rw /cifs/*

$ ls -l /cifs
total 1
-rwxrwxrwx. 1 root root 180 Nov 17 05:03 file1
-rwxrwxrwx. 1 root root 180 Nov 17 05:03 file2

```
ご覧のとおり、chownコマンドとchmodコマンドは効果がありません。 

昨日（2021-11-16）からNFS4.1プロトコルを使用してAzure　Files上のファイル共有にアクセスできるようになりました。

Linux VMからこのような共有をマウントする場合の大きな利点は、NFSがPOSIXパーミッションをサポートすることです。
これは、所有者と権限をファイルベースで変更できることを意味します。 

以下は、NFS共有をマウントするコマンドです。

```
$ sudo mkdir -p /nfs
$ sudo mount -t nfs mypremiumstorage.file.core.windows.net:/mypremiumstorage/share /nfs -o vers=4,minorversion=1,sec=sys
```

これで、共有内の個々のファイルの所有権と権限を変更できます。

以下のとおり共有には2つのファイルがあります。所有者だけがファイルを読み取ることができるようにアクセス許可を変更してから、file2の所有者をomiに変更します。 

```
$ ls -l /nfs
total 1
-rw-rw-r--. 1 job job 180 Nov 17 01:33 file1
-rw-rw-r--. 1 job job 180 Nov 17 01:33 file2

$ sudo chown omi:omi /nfs/file2; sudo chmod go-rw /nfs/*

$ ls -l /nfs
total 1
-rw-------. 1 job job 180 Nov 17 01:33 file1
-rw-------. 1 omi omi 180 Nov 17 01:33 file2
```

ここで、両方のファイルをjobユーザーとして読み取ろうとすると、file1をjobユーザーごとに読み取ることができますが、omiユーザーが所有するファイルを読み取ろうとすると、「Permission denied・アクセスが拒否されました」というメッセージが表示されます。

```
$ whoami
job

$ cat /nfs/file1
マイクロソフト（英: Microsoft Corporation）は、アメリカ合衆国ワシントン州に本社を置く、ソフトウェアを開発、販売する会社である。

$ cat /nfs/file2
cat: /nfs/file2: Permission denied
```

NFSはLinux / Unixにネイティブです。主にLinuxVMで共有を使用している場合は、NFSを使用することをお勧めします。

Azure FilesでNFS共有を設定するには、次のドキュメントを参照してください。 
- [NFS 共有を作成する方法](https://docs.microsoft.com/ja-jp/azure/storage/files/storage-files-how-to-create-nfs-shares?tabs=azure-portal)


以上です。
Androidのレイアウト概要

# はじめに
普段は、iosエンジニアなのですが、androidも書きたくて、まず参考書を読むことにしました。

Androidはなんとなく全体像は知っているので、一番気になるレイアウトの章から読みました。

全部読み終えてから、改めてまとめるつもりなので、
この記事では、その時用のメモのようにラフにまとめます。

# ビューのヒエラルキー
ViewGroupeだけがサブビューを持てる。
iosではどのviewもsubviewsプロパティにサブビューを格納できるので、汎用性はiosの方が高いか。


# レイアウト
仕事としてはmeasureパスとlayoutパスがあり、
measureパスはサイズ、layoutパスは座標を決定する。

measureパスが終わってから、layoutパスがよばれる。
つまり、ビューヒエラルキー内のビューのサイズを全て決定してから、適当な座標に置いていく感じか。

## measure()
Viewクラスにはmeasure()メソッドがあり、自身のサイズをこの中で決定する。
`measure()`メソッド内で、`onMeasure(int widthMeasureSpec, int heightMeasureSpec)`がよばれ、さらにその内部で`setMeasuredDimension(int measuredWidth, int measuredHeight)`がよばれる。

こんな感じ
`measure()` > `onMeasure()` > `setMeasuredDimension()`

後の２つのメソッドの役割は、
`onMeasure(int widthMeasureSpec, int heightMeasureSpec)`:
引数に親ビューからのサイズ制約を受け取り、自身のサイズを決定する。
`setMeasuredDimension(int measuredWidth, int measuredHeight)`:
自身のサイズを引数に受け取って申告する。

### layout三態
`onMeasure(int widthMeasureSpec, int heightMeasureSpec)`の引数で受け取る値には、制約パラメータが入っていてこんな感じ。
EXACTLY: 親ビュー値は数値のハードコード。（このビューではこの親ビュー数値以内でメジャーしないと見切れる）
AT_MOST: 最大でもこの値以下でメジャーしてね。
UNEXPECTED: どんな値でもいいよ。（親ビューがwrap_contentとか。）

### ViewGroupのmeasure()
onMeasure()内で、
まず子ビューのmesure()を全て呼び出し、全ての子ビューのサイズを確定させる。その後、子ビューのサイズと自身の設定をもとに、setMeasuredDimension()で自身のサイズをで申告する。

子ビューのonMeasure()では、ViewGroup自身の制約とViewGroupがonMeasure(int widthMeasureSpec, int heightMeasureSpec)で親から受け取った値をいい感じに合わせて、受け取っている。

### ViewGroupでないViewのmeasure()
onMeasure()の引数と自身の設定(wrap_contentなど)を基に、setMeasuredDimension()でサイズを申告する。
必ず末端のviewなので、子ビューを考慮する必要なし。

## layout()
サイズの決まったviewを親ビューから良き座標に置いていく。
特にいうことなし。

# 参考文献

https://www.amazon.co.jp/dp/B07JGWLM7F/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1
iOS概論

# 目次
[1. View](https://qiita.com/Zousaaaaaan/items/1d32dece850d1be707e9)
2. Inteface　※準備中
3. Framwork　※準備中

# モチベーション

まず、きっかけから話します。

わからない時にその都度調べるというのが、大部分のプログラマーの知識の獲得方法かと思います。
しかし、それでは体系的な知識が身に付いていかない体感があったので、ios業務のために一冊オライリーの参考書を読むことにしました。
結果、結構良かったです。体系的な知識が身に付きました。
また、本という枠に入った知識を知ることで必要な知識の輪郭が明確になった感じがしました。
これは個人的にはとても良くて、”技術者としての最低限知識はこの範囲。これ以上は都度調べればOK”と安心して割り切れるようになりました。

 
ということで本記事のモチベーションですが、
<b>iosの仕組みを概要的に説明すること</b>です。
細かい実装テクニックなどは他の記事に任せて、仕組みをだーっと書いていきます。
また、ほぼ参考書からの知識になりますが、大部分を省略しています。
1200ページくらいあって全部有用な内容ではあるのですが、説明が長いと理解の妨げになるので、仕組みのエッセンスだけを採用しました。

この記事を読んだ人にも、知識の輪郭ができれば嬉しいです。

# 参考文献
読んだ参考書です。

https://www.amazon.com/Programming-iOS-13-Controllers-Frameworks/dp/1492074616
コードで作るContainer View Controller

# はじめに
この記事の目的は、コードから、Container View Controllerを作れるようになることです。
子ViewControllerが一つである単純な例で説明を行います。
参考文献の書籍の内容です。

ちなみに、storyboardからも、ContainerView(確かこんな名前のWidget)を使えばContainer View Controllerを作成可能です。

# Container View Controllerとは
ViewControllerの中に他のViewControllerを表示するとき、
親になっているViewControllerをそう呼びます。

UINavigationControllerやUITabBarControllerなどは、Container View Controllerにあたります。

androidだとFragmentを持つActivityのようなものです。

# 方法
UIViewControllerでは、子ViewControllerを格納するための`children`プロパティが用意されていますが、プロパティを直接扱うことは非推奨です。
childrenプロパティに子ViewControllerを格納するには決まったお作法があり、技術書によれば、作法を破ると手痛い仕打ち（バグ）を受けるとのこと。
つまり、Container View Controllerの作成は、このお作法に則って行う必要があります。

## お作法
### add 子ViewController

1. 親になるView Controller（以降親VCと呼称）の`addChild(_:)`をコール。引数は子ViewController（以降子VCと呼称）。
2. 親VCのview.addSubview(_:)によって、子VCのviewを加える。
3. 子VCの`didMove(toParent:)`を引数親VCでコール。

※1. 子VCが親VCの`children`に格納されるだけでなく、自動で子VCの`willMove（toParant:）`が引数親VCで呼ばれる。

### remove 子ViewController
本記事の例では扱いませんが、一応removeも。
1. 子VCの`willMove(toParent:)`を引数nilでコール。
2. 子VCのviewを親VCのviewから除外する。
3. 子VCの`removeFromParent()`をコール。

※3. 子VCが`children`から除外されるだけでなく、自動で子VCの`didMove（toParant:）`が引数nilで呼ばれる。

# 具体例
子としてPageViewControllerを持つcontaner view controllerを作成します。
初期画面のボタンを押すと、contaner view controllerに遷移するようにしました。

```InitialViewController.swift

/// 初期表示画面。この画面の上にcontainer view controllerを表示してみる。

class InitialViewController: UIViewController {

~

// buttonのタッチイベントアクション。container view controllerを作成し、表示する処理を書きます。
    @IBAction func onButton(_ sender: UIButton) {
        // 親vc(contaner view controller)と子vcの作成
        let pvc = UIViewController()
        let cvc = MyPageViewController()// 前もって作成済みのもの。ペラペラめくれます。

        // 色を分けて見やすく
        pvc.view.backgroundColor = .white
        cvc.view.backgroundColor = .blue

        // addのお作法
        // 1
        pvc.addChild(cvc)
        // 2
        cvc.view.translatesAutoresizingMaskIntoConstraints = false
        pvc.view.addSubview(cvc.view)
        NSLayoutConstraint.activate([// 親vcの下半分に子vcを表示してみる
            cvc.view.leadingAnchor.constraint(equalTo: pvc.view.leadingAnchor),
            cvc.view.trailingAnchor.constraint(equalTo: pvc.view.trailingAnchor),
            cvc.view.bottomAnchor.constraint(equalTo: pvc.view.bottomAnchor),
            cvc.view.heightAnchor.constraint(equalTo: pvc.view.heightAnchor, multiplier: 0.5)
        ])
        // 3
        cvc.didMove(toParent: pvc)

        present(pvc, animated: true)
    }

~

}

```
![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252245/18af436a-3dbc-4915-b82e-120818e9a581.gif)




# 参考文献
より詳しくはこちら。

https://www.amazon.com/Programming-iOS-13-Controllers-Frameworks/dp/1492074616/ref=pd_lpo_14_t_2/138-1185879-7650908?_encoding=UTF8&pd_rd_i=1492074616&pd_rd_r=59ae1150-c71a-4e21-adde-09330e96c901&pd_rd_w=MqOLR&pd_rd_wg=8C01s&pf_rd_p=a0d6e967-6561-454c-84f8-2ce2c92b79a6&pf_rd_r=T8X1CD08RETYRB12BPHS&psc=1&refRID=T8X1CD08RETYRB12BPHS


再利用可能なContainer View Controllerはこちらの記事が良さげでした。

https://qiita.com/mitsuyoshi/items/93682c4d8ce0e4096bf6
【個人開発】都道府県同士を対決させるサイトを作った

#【個人開発】都道府県同士を対決させるサイトを作った
はじめまして。@nura0927と申します。
私は旅行が好きで、その影響で地理に興味を持つようになりました。

そして今回、「地理バト」というWebサイトを作りました。
http://chiribt.com/

サイトのTwitter
https://twitter.com/chiribt

地理に関する投票を行い、リアルタイムでのランキングを見れるサイトになっています。

このサイトの特徴は投票。
対決形式での投票というのがこのサイトの1番の特徴です。
![スクリーンショット (2519).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1207272/aef7c0c7-849e-a605-1568-4d936911a8f8.png)

対戦形式での投票は、ひろゆき氏の「萌えネコ・萌え犬写真館」を参考にしました。
https://www.itmedia.co.jp/news/articles/0807/07/news049.html

#使用した技術

| 対象 | 技術 | 
| :--- | :---: | ---: |
| フロントエンド | HTML、CSS | 
| バックエンド | PHP | 

#まとめ
今後は投票ネタをどんどん追加しようと思います。

今回作ったサイトが自身2作目でまだまだ初心者ですので、サイトのことに関しましていろいろなアドバイスを頂けたらと思います。

こんな暇人企画もやってるので気が向いた方は覗いてみてください。
https://note.com/yuraku0927/m/m028fe480b4d1
Githubに接続するとfailed: knownhosts: key mismatch

## 現象

Goのプロジェクトで、Githubのprivateリポジトリのパッケージが読み込めなくなってて困った。
少し前までは問題なく出来てたような記憶があるが...。

```shell
$ go mod
clone repository is failed: ssh: handshake failed: knownhosts: key mismatch
```

## 原因

Githubのセキュリティ変更により、RSAキーのSHA-1署名は非対応になったらしい。
https://github.blog/2021-09-01-improving-git-protocol-security-github/

## 対応

EdDSAで鍵情報を新規作成し。

```shell
$ ssh-keygen -t ed25519 -C "mitsuaki1229@example.com"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/mitsuaki1229/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/mitsuaki1229/.ssh/id_ed25519.
Your public key has been saved in /Users/mitsuaki1229/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:daipa+ReMakeHAyoYAritaiKaeritaikyouhapoke/Q mitsuaki1229@example.com
The key's randomart image is:
+--[ED25519 256]--+
|    .To.. o   .  |
|   . o.o + P O o |
|  N * = I + S   o|
|   M * K . A A   |
|  o S . A .   .  |
| . + A + K V +   |
|  . E + o. .A o  |
|  OR   O.    .   |
|  AS     .ox xx  |
+----[SHA256]-----+
```

GithubのSSH keysに登録

```:.ssh/config
Host github.com
 User git
 IdentityFile ~/.ssh/id_ed25519
```

```shell
$ pbcopy < ~/.ssh/id_ed25519.pub
```

[SSH keys](https://github.com/settings/keys)

![Screen Shot 2021-11-19 at 13.49.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25578/bb8d8bd7-fcc6-6822-d42b-9675c94c7202.png)

## 確認

問題なく取得出来る事を確認。

```shell
$ go mod

~省略~
```

## 参考

* [Improving Git protocol security on GitHub](https://github.blog/2021-09-01-improving-git-protocol-security-github/)
【Pytorch】kaggle notebookでPytorchのGPUのコードをTPUのコードに書き換える【GPU→TPU】

##0,はじめに
下記を書き換えることで、2021年11月19日現在は動作することを確認しましたが、cudaのversionなどの問題で動作しなくなることがあります。
その場合はおそらくpytorch-xla-env-setup.pyのversionを変更することで動くようになると推測しています。

【執筆時のcudaのversion】

```.py
!nvcc --version
>Cuda compilation tools, release 11.0, V11.0.221
>Build cuda_11.0_bu.TC445_37.28845127_0
```

##1,ライブラリをimportする前に

```.py
!curl https://raw.githubusercontent.com/pytorch/xla/master/contrib/scripts/env-setup.py -o pytorch-xla-env-setup.py
!python pytorch-xla-env-setup.py --version 1.7 --apt-packages libomp5 libopenblas-dev
```


##2,必要なライブラリをimport

```.py
import torch_xla.core.xla_model as xm
import torch_xla.distributed.parallel_loader as pl
import torch_xla.distributed.xla_multiprocessing as xmp
```

##3,cudaではなくxm.xla_device()を使う

```.py
device = xm.xla_device()
```

一応確認。

```.py
print(f'Using device: {device}')
>Using device: xla:1
```

##4,optimizerによる更新
optimiser.step()の代わりに 

```.py
xm.optimizer_step(optimizer,barrier=True)
```


##5,環境変数の設定

```.py
os.environ["XLA_USE_BF16"] = "1"
os.environ["XLA_TENSOR_ALLOCATOR_MAXSIZE"] = "100000000"
```

##6,samplerを使う

```.py
train_sampler = torch.utils.data.distributed.DistributedSampler(
train_dataset,
num_replicas=xm.xrt_world_size(),
rank=xm.get_ordinal(),
shuffle=True)

valid_sampler = torch.utils.data.distributed.DistributedSampler(
valid_dataset,
num_replicas=xm.xrt_world_size(),
rank=xm.get_ordinal(),
shuffle=False)

train_dataloader = DataLoader(
train_dataset, batch_size=batch_size,
num_workers=num_workers, pin_memory=True,
sampler=train_sampler
)
valid_dataloader = DataLoader(
valid_dataset, batch_size=batch_size,
num_workers=num_workers, pin_memory=True,
sampler=valid_sampler
)
```

ここでDataLoaderの引数としてshuffle=Trueを付け加えるとエラーが出ます。
DataLoaderの引数にsamplerが存在していることに注意してください。


##7, modelのsaveには普通のtorchではなくtorch_xla.core.xla_modelライブラリを使う

xmとしてはじめにimportしてます。

```.py
xm.save(model.state_dict(), "model.pth")
```

##8, modelをloadするとき

```.py
model.load_state_dict(torch.load(model_name))
```

##最後に
問題があれば大変恐縮ですが、ご指摘いただけますと幸いです。
ネームスペース取得する方法色々

アセットをリファレンスして作業する前提でサポート用のツールを作る際、
ネームスペースを取得して色々行ったのだけども、そのときの紆余曲折をまとめ

namespaceInfoで問い合わせ
-
    allNameSpace = []
    ignorList = ['UI', 'shared']
    allNameSpace = cmds.namespaceInfo(listOnlyNamespaces = True)
    allNameSpace = list(set(allNameSpace) - set(ignorList))

シーン内のネームスペースを全部取得してくれる。

全部返してくれるので　['UI', 'shared'] といったデフォルトのネームスペースも含まれる。
**unload状態のリファレンスで使用しているネームスペースも返してくれる。**
そのネームスペースがリファレンスで使用しているのか否かが判らない。


referenceQuery で問い合わせ
-

    allNameSpace = []
    refNodes = cmds.ls(type = "reference")
    for refNode in refNodes:
         if refNode == "sharedReferenceNode":
             continue

         allNameSpace.append(cmds.referenceQuery(refNode, namespace=True,,shortName  =True))


別のノードを渡しても取れるが、**リファレンスで使用しているネームスペース**を取得したいと考えるとreferenceノードのほうが都合が良かった。
リファレンスされていないノードを渡すとエラーになる。


fileで問い合わせ
-

    allNameSpace = []
    allRefFiles = cmds.file(q =True ,reference =True)

    for refFile in allRefFiles:
        allNameSpace.append(cmds.file(refFile,q =True ,namespace = True))

シーン内でリファレンスで使用しているネームスペースを取得できる


リファレンスノードにロード状態を問い合わせる
-
    cmds.referenceQuery(refNode,isLoaded=True)




これらを組み合わせてフィルタリングしてみる

ロードされているリファレンスのネームスペースを取得する
-

    allNameSpace = []
    allRefFiles = cmds.file(q =True ,reference =True)

    for refFile in allRefFiles:
        refnode = cmds.file(refFile,q =True ,referenceNode = True)

        if cmds.referenceQuery(refNode,isLoaded=True):
            allNameSpace.append(cmds.file(refFile,q =True ,namespace = True))


リファレンスに使用されていないネームスペースを取得する
-
    allNameSpace = []
    ignorList = ['UI', 'shared']
    allNameSpace = cmds.namespaceInfo(listOnlyNamespaces = True)
    allNameSpace = list(set(allNameSpace) - set(ignorList))

    allRefFiles = cmds.file(q =True ,reference =True)

    referenceNameSpace = []

    for refFile in allRefFiles:
        referenceNameSpace.append(cmds.file(refFile,q =True ,namespace = True))

    allNameSpace = list(set(allNameSpace) - set(referenceNameSpace ))
Azureでの「yum update」のエラーについて

Azure RHUIサーバーへのアクセスは[AzureデータセンターのIP範囲](https://www.microsoft.com/download/details.aspx?id=41653)内に制限されています。

AzureでRedHatイメージを使用してVMをデプロイし、**yum**コマンドが失敗した場合は、①プロキシをセットアップしたか、②NSGルールを制限したか、③またはExpressRouteトンネリングを使用しているかを確認してください。

以下３つの点について説明します。

①プロキシサーバーを使用している場合は、このプロキシサーバーはAzureでホストされていることを確認してください。

②**NSGルール**を制限している場合は、[RHUIサーバーのIPアドレス](https://docs.microsoft.com/ja-jp/azure/virtual-machines/workloads/redhat/redhat-rhui#the-ips-for-the-rhui-content-delivery-servers)ごとに例外を追加してください。

③**ExpressRouteトンネリング**を使用している場合は、RHUIサーバーのIPアドレスごとにUDR（User Definited Route）を必ず追加してください。

## RHUI の情報
Azure RHUIのIPアドレスは以下の通りです。プロトコルは「HTTPS] 、ポートは「443」です。

```
# Azure Global
13.91.47.76
40.85.190.91
52.187.75.218
52.174.163.213
52.237.203.198
```

Azure RHUIのURLリストは以下の通りです。


```
https://rhui-1.microsoft.com/
https://rhui-2.microsoft.com/
https://rhui-3.microsoft.com/
```

以上です。
テストの種類と、その観点

# はじめに
どんなテストを実施すれば良いか？
テストで絶対に実施すべきポイントは何か？
テスト実施者をどうやってアサインするか？
そんなテストの悩みについてまとめてみました。

# ◆機能に関するテスト
システムが仕様通りに動くことを確認するためのテスト。
目的や実施者や実施タイミング別に分類すると下記のようなテストが求められる。

## 1.ホワイトボックステスト
システムやコードレベルの構造を確かめるためのテスト。
実施者：コーダー　もしくは　詳細設計をした人
実施単位：ソースコード
実施タイミング：モジュール完成時、ソースレビュー時
例）以下のような分岐を実装している場合は19歳、20歳でテストを実施する

```php
if( $age< 20){
  $group = "未成年";
}else{
  $group = "成人"
}
```
参考：循環的複雑度、条件網羅、分岐網羅

## 2.ブラックボックステスト
システムの内部構造を知らないが、仕様通りに動くことを確かめるためのテスト
本来入力が発生しないようなデータを入力してエラーや想定外の動作が起きないこともこのテストで確認する
実施者：設計者（アドホックテスト）、新人SE（モンキーテスト）
実施単位：モジュール、画面
実施タイミング：モジュール完成時
例）年齢にマイナス値が入らないことを確認
例）データが0件の場合にエラーが起きないか確認

## 3.シナリオテスト
実際の業務の通りにシステムを利用するシナリオを作り、予定している業務を実施できることを確かめるためのテスト
顧客にヒアリング、または用意してもらった年間業務スケジュールに則してテストをするのが望ましい
実施者：要件定義実施者、顧客
実施単位：業務単位、年間業務
実施タイミング：顧客レビュー

▶参考：人事労務の年間スケジュール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172765/5d88b471-cd8b-6a47-00d7-051035db38ec.png)
引用：https://hrnote.jp/wp/wp-content/uploads/2017/07/26431155c8eb92f99a305e705a223f2c.jpg

# ◆非機能に関するテスト
仕様として明言されていない性能面のテストや、システム稼働を継続した際のデータ増加などによるレスポンス悪化に問題が無いことなどを確認するためのテスト

## 負荷テスト
アクセス負荷を与えたり、一定期間（3年分など）で蓄積されるデータを用意してテストをする。
自社で実装したシステムと外部システム間で連携が発生する場合や、システム稼働で膨大なデータが蓄積されていくシステムの場合は必須
実施者：要件定義実施者
実施単位：業務単位
実施タイミング：機能完成、納品前
### アクセス負荷テストで検知できるもの
ApacheやNginxのメモリ設定値、サーバースペックが適正かどうか
### データ負荷テストで検知できるもの
RDBのインデックス貼り忘れ、不適切なリレーション
VirtualBox 6.1.28 にアップデートしたら vagrant 環境にネットワーク接続できなくなった問題の解決

ふと気付くと、vagrant up した環境にネットワーク接続できなくなっていました。

ホスト上で ifconfig 見ると、なぜか vboxnet0 ネットワークが無くなってる。

調べた結果、原因は VirtualBox が許容しているデフォルトの IP アドレス範囲が変わったからでした。

ユーザーマニュアルの 116 ページ
https://download.virtualbox.org/virtualbox/6.1.28/UserManual.pdf

```
On Linux, Mac OS X and Solaris Oracle VM VirtualBox will only allow IP addresses
in 192.68.56.0/21 range to be assigned to host-only adapters. For IPv6 only link-local
addresses are allowed. If other ranges are desired, they can be enabled by creating
/etc/vbox/networks.conf and specifying allowed ranges there. For example, to allow
10.0.0.0/8 and 192.168.0.0/16 IPv4 ranges as well as 2001::/64 range put the following lines
into /etc/vbox/networks.conf:

    * 10.0.0.0/8 192.168.0.0/16
    * 2001::/64
```

今まで 192.168.33.x を使っていたので、上記の通り 192.168.0.0/16 に変更することで解決しました。
【Ruby】抽象クラスを作る

##環境
Ruby 3.0.2
Rails 6.1.4.1

##抽象クラスとは

抽象クラスは、その特徴としてクラス自身はオブジェクトの実体、インスタンスを生成できない。
抽象クラスは主にそのクラスを親クラス(基本クラス)とした子クラス(派生クラス)を定義(継承)する前提で作製されるクラス。

Rubyではサポートされてないけどそれっぽいものを作れる。


```ruby
class Parent
  def method_1
    raise 'implement this method in subclass'
  end
end

class Child < Parent
  def method_1
    'hogehoge'
  end
end
```

```ruby
parent_class = Parent.new
parent_class.method_1
# => RuntimeError: implement this method in subclass

child_class = Child.new
child_class.method_1
# => 'hogehoge'
```


https://gimo.jp/glossary/details/abstract_class.html

http://ackintosh.github.io/blog/2012/10/23/abstract-method-in-ruby/
HTMLのタグを調べる

#概要
HTML初心者のための備忘録。（ほぼ自分のため）

#HTML5入れ子チートシート
タグに対して、どのタグを内包することができるか調べる。
https://yoshikawaweb.com/element/

#HTMLクイックリファレンス
使うタグを調べたり、タグの意味を調べる。
http://www.htmq.com/
Vue + Electronで行う腰痛改善　- IT技術者の腰を守りたい！ -

# IT技術者人生は腰痛との戦いである
歴戦のIT技術者になればなるほど、腰痛に悩まされている人は多いと思います。
私も月に1回は整体に行かないと、腰が痛くて仕事ができません。

# Vue+Electronで行う腰痛改善
本記事はそんなIT技術者に向けて投稿しました。

:::note info
Vue + Electronで腰痛改善を促すアプリを作ってみた
:::

:::note info
腰痛改善アプリを題材とした Vue + Electron の実装の紹介
:::

ちなみに私はVueもElectronも全くの初心者です。

# IT技術者が腰痛になりやすい３つの理由
まずは、毎月通っている整体の先生から聞いた３つの理由をご紹介。

## その１ デスクワークで猫背になっている
左の図の様に猫背に座ってしまうと、体を支えるために腹筋や背中の筋肉が無駄に緊張してしまい腰痛を招きます。右の図の様にしっかりと骨盤を立てて座りましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489752/7fed9e73-46d7-f6d2-27d8-2ba32a74d5e9.png)

## その２ 頭が前に出ている
ディスプレイの位置が適切でない場合やその位置に合った座り方をしていない場合、どうしても頭が前に下がり首が前傾してしまいます。人間の頭は体重の10%程度の重さがあります。体重70kgの人の頭の重さが7kgです！それくらいの重さのものを支える時、前傾角度が大きくなればなるほど負荷が大きくなることは M = F × L × sinθ でなんとなく想像できますよね。

その負荷を支えるのは首や背中の筋肉です。首や背中の筋肉疲労や緊張が腰痛を招きます。キチンと背骨の上に頭を乗せて支えましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489752/bce2c0c7-5a71-b306-8202-e9072fe596f2.png)


## その３ ずっと座りっぱなし
猫背や首が前傾した姿勢のまま長い時間座っているほど、筋肉疲労や緊張が加速してしまいます。最低でも30分～1時間に一度はトイレ休憩や簡単な体操を取り入れないと腰痛がどんどん酷くなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489752/9fa35ce1-b4c8-d241-29dd-1669a783030d.png)

# 腰痛改善へのアプローチ
上記３つの理由を理解していても、仕事に没頭していると絶対に忘れてしまいます。そのため、下記要件のデスクトップアプリで腰痛改善を図ります。

- ＰＣを起動すると自動でアプリが立ち上がる
- 一定時間経過すると、アラートを表示しトイレ休憩や軽い体操を行う様に促す
- 再度作業を開始する際、正しい姿勢に戻すことを促す

このデスクトップアプリは**"IT技術者の腰の調子を整えて欲しい"**という思いを込めて **腰Tune（Youtune：ヨーチューン）** という名前にしました。

↓↓こんなイメージです↓↓

![countdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489752/8f54b769-bb3b-eb88-9b93-4190bba9912a.png)

![complete.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489752/937c43b8-0774-3f2b-98ff-15ad3f24663e.png)

# 腰Tuneを使ってみて
デバッグとかも含めて2週間くらい自分で使ってみましたが、**腰痛はかなり軽減されました**！

さらに定期的に腰痛のことを気にするようになったことでその他の健康にも気を使う様になりました。

例えばいつもならお菓子を食べていたところをガムで我慢したり、などの副次的な効果も表れた感じがします！

**やっぱ健康に気を使うってめっちゃ大事。**


# 使ってみたい方は・・・・・
https://github.com/nagatani-hase/youtune

githubからソースを取得して、ビルドしてみてください！
腰痛に悩めるIT技術者の方であれば、vue & Electronのビルドくらいはできますよね・・・・？？(笑)

また、私が開発した際に vue & Electron を触ってみて苦労した点はソースコードに落としてあります！

- Electronでウィンドウメニューの制御をする。
- PCログインで自動起動する。
- Vue + Vuetify で画面作る。
- ・・・

等々できる限りコメント書いたりやコミットを分けながら対応しているので、良かったら見てみてください。

# まとめ
IT技術者の健康問題は本当に大きな課題であると思っています。腰痛があるかないかだけで作業効率も大きく変わってきます。

ただ、社員の健康を本当の意味で意識している会社は少ないと思います。目線の高さが合っていないディスプレイや体に合わない椅子を使っているだけで健康被害は出てきます。また、まだまだ前時代の文化的に「健康よりも仕事」みたいな風潮が残っているところも少なくないと思います。

今回、IT技術者を始めとした働く人々に、健康への意識を持ってもらえると良いなと思い、こういった視点でアプリを作ってみました。

# さいごに・・・・
あくまで Vue も Electron も初心者が作ったアプリなのでバグや変なコーディングはご了承ください。。。。逆に色々ご指摘いただけると幸いです！

また、もし使ってみた感想とかいただければ今後ブラッシュアップしてみたいなと思うのでぜひぜひ。
【RSpec】スタブとモック

##スタブ
オブジェクトのメソッドをオーバーライドし、事前に決められた値を返します。つまりスタブは、呼び出されるとテスト用に本物の結果を返す、ダミーメソッドです。スタブをよく使うのはメソッドのデフォルト機能をオーバーライドするケースです。特にデータベースやネットワークを使う処理が対象になります。
(引用:Everyday Rails - RSpecによるRailsテスト入門)

- メソッドの中のメソッドをスタブしてテストしたいとき


```ruby
user = User.new
allow(user).to receive(:full_name).and_return('user')
```


##モック
本物のオブジェクトのふりをするオブジェクトで、テストのために使われます。モックはテストダブル(test doubles)と呼ばれる場合もあります。モックはこれまでファクトリやPOROを使って作成したオブジェクトの代役を務めます(訳注:英語の“double” には「代役」や「影武者」の意味があります)。しかし、モックはデータベースにアクセスしない点が異なります。よって、テストにかかる時間は短くなります。
(引用:Everyday Rails - RSpecによるRailsテスト入門)


```ruby
user = double("user", name: "Fake User")
# => #<Double "user">
```

- 引数やメソッドの呼び出し回数をチェックする

https://qiita.com/jnchito/items/640f17e124ab263a54dd#%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E5%9B%9E%E6%95%B0%E3%82%92%E6%A4%9C%E8%A8%BC%E3%81%99%E3%82%8B

####注意点

モックは実際の実装が変わったときでもテストがパスしてしまうので、なるべく```instance_double```や```class_double```などの検証機能付きのテストダブルを使ってテストしたほうが良い。

```ruby
user = instance_double("User", name: "Fake User")
# => #<InstanceDouble(User) (anonymous)>
```
私がJPAよりMybatisを薦める理由

JavaでRDBにアクセスするなら、
大きくこの二つの選択肢があるでしょう。

- JPA
  - ORMの仕組み
  - Javaのオブジェクトを使って情報の永続化（データ保存）や情報の取得をするもの
  - 複雑な情報取得のためにJPQLというSQLに似た書き方もできる
  - JPA自体は仕様で実装物としてはHibernateが有名（Hibernateの機能をJavaが仕様として取り込んだ）
- Mybatis
  - ORMというよりSQLマッピングの仕組み
  - SQLをJavaではない外部ファイルに書くことができる
  - SQLの結果やバインドパラメータ ⇔ JavaのBeanの間で自動詰替えをしてくれる

私は初学者やほとんどの開発プロジェクトでMybatisの採用を薦めています。
その理由について個人的な意見を記載します。

ただ、JPAは正直あまり使ってないので見当違いがあるかもしれません。

# JPAのいいところ

### 単一テーブルへのアクセスが簡単

単一テーブルや単純な親子関係のテーブルの結合ぐらいなら、とてもシンプル書けるので使いやすいです。
単純な更新系処理（INSERT文UPDATE文DELETE文）はめっちゃラクチンです。

# JPAの嬉しくないところ

### SQL自動生成がブラックボックス

JPAではSQLが自動生成なので実際にどんなSQLが動いているのか把握しづらいです。
ログ出力すれば見れますが個人的には読みづらいと思っています。

#### 参考:

- https://blog.tagbangers.co.jp/2015/09/08/how_to_display_hibernate_sql_parameters
- https://ice-black.hatenablog.com/entry/2018/04/29/164233

### 無駄な情報取りすぎ（結合テーブルの情報）

結合する情報をすべて取ってくるのは無駄なメモリを使うことになるかなと思います。

### 特定項目のみの更新しんどい

Entity単位の更新で、基本的には全項目更新します。
SQLのように指定されていない項目は上書きされないという安心感がありません。

### サブクエリ（副問い合わせ）が使いづらい

使えないわけではないけど正直SQLよりしんどいです。
複雑なクエリはSQLツールで試しまくって準備するはずなので、できればそのまま使いたいです。

単純なものでもSELECT UPDATEとかSQL1発で実行したいこととかあるじゃないですか。

### メンテナンス性悪い ※これが一番の問題

ほとんどの設計者やプログラマがテーブルをもとにデータが実際に正しく取得できるかをSQLツールなどで試しているはずです。
頭の中だけで組み立てられる強者は少ないですよね。
せっかくSQLツールで試したSQLをわざわざjavaコードやJPQLに変換して書くのは非効率的と考えています。
頑張って一度JPAで書いたとしても不具合がある度にSQLに書き換えてSQLツールで試してまたJPAに書き換え・・・つらすぎます。。
このメンテナンス性の悪さが最も致命的と考えています。

あとから参画した人が手直しするのもMybatisでSQL書かれてる方が把握しやすいしメンテナンスしやすいと思います。

### 学習コスト高い

「SQLを知らなくても使える」「SQL学習がつらいので」という人もいますが、それは簡単なシステムに限る話かなと思います。
実際には複雑な情報アクセスの必要があり、SQLからは逃げられないです。
結果的にSQLは学習することになるはずです。

情報系エンジニアとしてSQLは必須なのでどっちみち勉強することになりますが、
JPAを使うとなるとSQL + JPAのJavaでの書き方 + JPQLを学ぶことなるので学習コストが高いと思います。

JPAはEJB仕様から独立した仕様とされているようですが、
EJBまで把握しようとするとさらに難易度が高くなりそうです。
EJB使うプロジェクトは最近はあまり見かけないので仕事でも触れる機会ないですからね・・・

# JDBCではなくMybatisを使う理由（箇条書き）

- Javaコード内にSQLを混ぜないので、修正時にSQLツールで試しやすい（メンテナンス性高い）
  - とはいえ、動的SQLだと、そのままコピーしてSQLツールでは試せないのはつらいところ
- 動的SQL書きやすい（Javaコードにif文条件で文字列結合しながらの動的SQL本当につらい）
- 「SQLの結果やバインドパラメータ ⇔ JavaのBeanの間で自動詰替え」がとても嬉しい
  - JDBCだととても面倒くさい部分をカバーしてくれている

# 総じて

単純なSELECTやINSERT/UPDATE/DELETEをわざわざ書く必要があっても、
これらを書くのは難しいわけではないし
複雑なSQLはタダでもつらいのにさらにJPAに変換して使うのに苦労するぐらいなら
全部SQLで書くことを選びます。

また、SQLはかなり利用頻度の高い技術なので
どのプログラム言語を学ぶ初学者にもおすすめしたいところです。

# おまけ

以前、INSERT/UPDATE/DELETEはHibernateを使って、
SELECTはMybatisを使ってくださいというルールにしたことがあります。

結果、プロジェクトでは混乱が起きました。（猛反省）
とくにHibernate利用の部分を一元管理する動きになって、
数百もあるテーブルを一人が管理することになり高負荷になった上に各機能ごとの都合に合わせられなって
結局各機能ごとにSQLを書いてしまうという残念な結果になりました。

失敗した経験から言いたいことはひとつ、
「混ぜるな危険」
です。
2021.11.19現在 → nRF9160 にて https で FOTA を実装する際の注意点

# 症状

ncs v.1.7.1

HTTP なら成功するのに、HTTPS を利用すると FOTA に失敗した。

ダウンロード処理の初回でサーバーから強制切断されるのだ。

サーバー側のログを見ると、暗号化通信は正常、分割ダウンロードのログも正常にでていた。

# 対策

公開鍵の設定やサーバー証明書まわりの問題かと一晩悩んだが、

原因は、暗号化することでダウンロード時のフラグメントサイズの上限を超えてしまっていたことだった。

nRF9160 は、ダウンロード時の フラグメントの大きさが 2048bytes を超えるとエラーになるのだ。

FOTA や　DOWNLOD のサンプルプログラムのデフォルト値が 2048bytes なので、そのまま HTTPS に対応させようとすると、必ず失敗する。

prj.conf に

```
CONFIG_DOWNLOAD_CLIENT_HTTP_FRAG_SIZE_1024=y
```

を追加すれば不具合が解消する。


* * *
以上。
* * *
Unity初心者 「親子関係」豆知識

## 関係の取得
親オブジェクトが何か

```
[調べたいオブジェクト].transform.parent.gameObject;
```

## 動的に親子関係を変える
親子にするときは方法１、解除する時は方法２　でも大丈夫です！

### 方法1
親子にする

```
 [子にしたいオブジェクト].transform.parent = [親になるオブジェクト].transform;
```
親子解除する

```
 [子にしたいオブジェクト].transform.parent = null;
```

### 方法2
親子にする

```
 [子にしたいオブジェクト].transform.SetParent([親になるオブジェクト].transform, true or false);
```
※スケールや位置を崩したくなければtrue

親子解除する

```
 [子にしたいオブジェクト].transform.SetParent(null);
```

## 動的な親子関係で相対位置やスケールが崩れてしまうことがある
その原因は、親以前のスケールが関係しています。

スケールxyzの値がすべて(1, 1, 1)のように同じであればおかしくならないのですが、
yだけ違うなどの場合は、モデルを比率があるように作るか、
下記のようにして空オブジェクトを間に挟んでスケール調整をしてください。
回転時にうまくいかず歪むなどの時もこれで解決します。

```
親 (1, 0.1, 1)
  調整用空オブジェクト (1, 10, 1)
    子 (1, 1, 1)
```