OmniAICreator/Qiita-1.07M huggingface dataset:
Qiita Daily Survey memo 2021.03.10

# Qiita Daily Survey memo 2021.03.10
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。
おさぼり気味だったので今日から頑張るぞぃ！

## [海外のスライド共有サービスがやる気ないので自分で作ってみた](https://qiita.com/ku_suke/items/7702c7b25aa31672a2bf)
Yusuke Kawabata(ku_suke)さんの記事。
スライド共有サービスを作った！という記事になります。
主題のサイトは私もよく利用させていただいていました。（読む専ですが！）
個人的には、そんなに利用頻度が高くないことと、内容が面白いものにしか当たっていないため、そこまで強い不便は感じませんでした。
モチベーションの項目にある通り、不便を感じられた + モチベーションがあるので作成されたとのこと…！
構成図も分かりやすく、開発に当たって大変だった部分も記載いただいています。

サイトに飛んでみましたが、シンプルで使いやすく、新着スライドも興味深いものが多かったのでブックマークしました。


## [開設後３週間で収益１０万円を得た個人開発サイトに立ち向かった話の全部を公開する](https://qiita.com/nuko-suke/items/652366597ce2ce0a91f9)
nuko-suke さんの記事。
記事内で紹介されているテックブックさんのサイトを参考に「自分だったらこうする」を追加して、サイトを作成された記事になります。
すごいなー…の言葉しかでないです…。
実際に手を動かして開発をされた方の言葉だから、響くんだろうなーと思います…。
「vsモチベーション」は、まったくもってその通り。
特に、簡単に手に入る娯楽が多い時代、時々怠けちゃうのはいいと思いますが、自分を律してモチベーションをコントロールするのが大事なんだろうなーと思います。
そのための心構えとかも書いてくださっています。
うー…うー…といった感じ！かっこいい！！


## [【個人開発】ファラオが情報共有し現代社会を生き抜くアプリ作りました](https://qiita.com/HBKK/items/45a50e8f67bf8e9d6a0b)
なかい ひびき(HBKK) さんの記事。
ファラオの皆さんがヒエログリフで情報を共有できるアプリを開発された、という記事になります。
デュエルなモンスターズをぱっとイメージして記事を開きましたが、イメージとは異なったイケてるサイトになっていると思います。
「Unicodeはヒエログリフに対応しているので」は、大変勉強になりました…。
クスッと来るようなサイトでも、作って公開して記事まで書いているので、SUGOI。


## [Slack社はSlackをどう使っているのか - Slack利用ガイドラインの話](https://qiita.com/e99h2121/items/71f607a0b46de5013730)
Nobuko YAMADA(e99h2121) さんの記事。
そのサーベイ力はどこから来ているのか、どれだけアンテナが広いのか…。
今回の記事は、タイトルの通り Slack をどう使うのがいいか、という話になります。
いくつかの記事を引用されて、よい使い方について他の方の意見を交えて説明してくださっています。
コミュニケーションツールの使い方難しいですよね…確かに、コミュニケーションツールを作った人たちの言葉を聞くのが良いと言われればその通りだなーと思いました。
詳細は記事を参照していただきたいですが、個人的にはアンチパターンが参考になりました。
また、参考にされたQiitaの記事のほうも勉強になりました。
null の可能性がないことを TypeScript コンパイラに伝える方法

次の TypeScript コードはコンパイルエラーが発生します。

```tsx
import { useEffect, useRef } from 'react';

const MyComponent = () => {
  const ref = useRef<HTMLDivElement>(null);
  useEffect(() => {
    const div = ref.current;
    console.log(div.style.display);
  });
  return <div ref={ref}></div>;
};

export default MyComponent;
```

コンパイルエラーは次のような内容です。

```
TypeScript error in /Users/.../MyComponent.tsx(7,17):
Object is possibly 'null'.  TS2531

     5 |   useEffect(() => {
     6 |     const div = ref.current;
  >  7 |     console.log(div.style.display);
       |                 ^
     8 |   });
     9 |   return <div ref={ref}></div>;
    10 | };
```

`ref.current`の型が`HTMLDivElement | null`であり、`null`の可能性があるため発生したエラーだとわかります。

しかし、上記コードでは`ref.current`が`null`になることはありません。理由は、レンダリング時に`ref.current`に値が代入され、`ref.current`の参照場所である`useEffect(() => { /* ここ */ })`は必ずレンダリング後に実行されるからです。

`null`を`null!`に変更することでコンパイラエラーを抑制できます。

```tsx
import { useEffect, useRef } from 'react';

const MyComponent = () => {
  const ref = useRef<HTMLDivElement>(null!);
  useEffect(() => {
    const div = ref.current;
    console.log(div.style.display);
  });
  return <div ref={ref}></div>;
};

export default MyComponent;
```

このように`null!`と書くことで、TypeScript コンパイラに「この変数には一時的に `null` を入れているだけであって、参照時に `null` になることはない」と伝えることができます。

次のページを参考にしました。

[React+TypeScript Cheatsheets](https://github.com/typescript-cheatsheets/react)
Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)は何している？

```
Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
```
上記の内容が理解があいまいで、まとめる。
user_id IN (?)がfollowing_ids に対応。user_id = ?がid に対応？
一応私の認識としては以下を考えてます。
↓
micropostのカラムからwhereのものを取得。
以下where内
user_id IN (?)はfollowing_idsの中にあるuser_idをとってくる。
例えば、following_ids =[“2”,“3",“4”,“5"]だった場合、user_id IN(?) でmicropostのカラムからuser_id=2, 3, 4, 5のみを取得。
user_id = ?は現在ログイン中のid(インスタンス変数かセッションから取得？)のuser_idを取得
例えば現在ログイン中のidが1の場合user_id=?の?に1が入るイメージ
http.HandlerFunc は、型の名前 !!


何かと分かりにくかった `http.HandlerFunc` について、まとめました。

## まとめ

* `http.HandlerFunc` は型の名前
    * __注意__: [Go 1.9 から使える Type Alias](https://golang.org/doc/go1.9#language) ではない
* `http.HandlerFunc(関数)` とすることで、関数を `http.Handler` インターフェースを満たした型として扱える
* その関数は、`func(http.ResponseWirter, *http.Request)` という形 (シグネチャ) でないといけない


## Go 言語の基本をおさらい
下記のように、独自の `int` 型を作れるように、あるシグネチャを持った関数も独自の型として定義できます。

```golang
type MyInt int
type MyFunc func(int, string) string
```

そうなんです。関数も型にできるんです。

そして、`T(x)` ([参考: Go言語の仕様](https://golang.org/ref/spec#Conversions})) とすることで、型変換ができます。
(`T` は変換したい型、`x` は変換する型)

```golang
func Index(i int, s string) string {
	return fmt.Sprintf("Int: %d, String: %s", i, s)
}

testInt := MyInt(1)
testMyFunc := MyFunc(Index)

fmt.Printf("The value is: %v\n", testInt) // The value is: 1
fmt.Printf("The value is: %v\n", testMyFunc(3, "hello")) // The value is: Int: 3, String: hello
```

どんな型になっているか念のため確認

```golang
fmt.Printf("%T\n", testInt)     // main.MyInt
fmt.Printf("%T\n", testMyFunc)  // main.MyFunc
```

関数を独自に作った型にでき、関数としても使えることが確認できました。


## `http.HandlerFunc` を見てみる

[Go のドキュメント: HandlerFunc](https://golang.org/pkg/net/http/#HandlerFunc) から

```golang
type HandlerFunc func(http.ResponseWriter, *http.Request)
```

となっている。ふむふむ。

ということで、__`HanlderFunc` は、型である__ ことが分かります。

また、`HandlerFunc` は、`func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)` のメソッドを持っているので ([Go のドキュメント: type Handler](https://golang.org/pkg/net/http/#Handler))、`http.Handler` インターフェースを満たしています。

なので、`func(http.ResponseWriter, *http.Request)` という形(シグネチャ)の関数は、`http.HandlerFunc(関数)` とすることで、`http.Handler` 型として扱えるようになるということです。

## では、どう使うのか？

middleware として使うことができ、ある処理の前に別の処理を実行させることができます。

下のコードは、画面に `hello world` と表示する前に、`log.Println` を実行する例

```golang
package main

import (
	"fmt"
	"log"
	"net/http"
)

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}

func Log(h http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		log.Println("Log is called")
		h(w, r)
	}
}

func main() {
	http.Handle("/", Log(Index))
	http.ListenAndServe(":8080", nil)
}
```

* Log 関数は、`http.HandlerFunc`型を受け取り、`http.HandlerFunc` 型を返す関数
* Index 関数 は、`http.HandlerFunc` 型になるための形(シグネチャ)になっている
* なので、Log 関数は、Index 関数を受け取り、独自の処理(`log.Prinln`) のあと、そのまま受け取った関数 (= Index 関数) を実行する

## `http.HandleFunc` は内部で `http.HandlerFunc` を実行している

`http.HandleFunc("/", 関数A)` とすることで、トップページへのリクエストがあった際に "関数A" を実行しますが、内部の実装をみると `HandlerFunc` が実行されています。

```golang
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
```

あー、すっきりした。
Rails のlink_to メソッドにHTML タグを含める

# はじめに

Bootstrap を使用したフロントの構築に必要だったので備忘録です

# 環境

* macOS 10.15.6
* Ruby 2.5.7
* Rails 5.2.3

# 参照

[link\_to \(ActionView::Helpers::UrlHelper\) \- APIdock](https://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to)

# 目標

`link_to` メソッドを使ったリンクの生成にHTML タグを含めたい

```HTML
# 目標とするHTML
<a href="path_to_login"><span>Login</span></a>
```

# 解決策

`link_to` のブロック構文を使ってHTML を内包する

```Ruby
# 一般的なlink_to の使い方
<%= link_to "Link Text", path %>

# ブロック構文を使ってHTML を含ませる
<%= link_to path do %>
  含めたいHTML
<% end %>
```

目標とするHTML のように`<a>` タグの中に`<span>` タグを含める場合は下記のように記述する

```Ruby
<%= link_to login_path do %>
  <span>Login</span>
<% end %>
```

# 学び

フロントは全然触っていないので慣れないですが色々とやってみるしかないですね...!
異常検知、関連。論文『Modeling the Distribution of Normal Data in Pre-Trained Deep Features for Anomaly Detection』への違和感。

#概要

論文『Modeling the Distribution of Normal Data in Pre-Trained Deep Features for Anomaly Detection』に関するQiita記事が、いくつか、あったので、それを契機に興味をもって、論文を読んでみた。
（いいですね、Qiita。でも、Qiitaを離れる方もいるので、それは、ちょっと、残念ですね。。いまは、そんな季節？。完全な余談でした。）

この記事は、感想の記事です。
前提。あくまで、ほぼ、素人レベルです。

無駄記事になっている可能性がありますが、、、、その場合、末尾の「完全な余談」が役立つ可能性２％。

論文：
(https://arxiv.org/abs/2005.14140)
Rippel, Oliver, Patrick Mertens, and Dorit Merhof. "Modeling the distribution of normal data in pre-trained deep features for anomaly detection." arXiv preprint arXiv:2005.14140 (2020).

#論文を読んだ感想

面白いという気分で読み始めたが、とりあえず、最終的には、気分としては、
**何か、当たり前のことが書かれている**と感じた。
どうも、画像認識とかの世界が、それらの**アウトプットの実用的な利用方法の提供が、未成熟**な感じがした。
**マハラノビス距離を、、、**みたいな部分が、**えっ、そっちに行く？**、という感じが、素人的にはする。

#論文のアブストラクトと結論の訳文

##アブストラクト（DeepL訳）

画像の異常検出(AD)はコンピュータビジョンの基本的な問題であり、画像や画像の部分構造が正常値から大きく乖離しているものを特定することを指します。一般的なADアルゴリズムは、タスク仕様のデータセットを使用してゼロから正規性のモデルを学習しようとするのが一般的ですが、大規模な異常へのアクセスが困難であることと、異常の出現が曖昧であることから、通常のデータを使用した半教師付きのアプローチに限られています。我々は別のアプローチを採用し、大規模な自然画像データセット上で識別モデルによって学習された深層の特徴表現が正規性を記述し、伝達学習の設定では微妙な異常であっても検出するのに適していることを実証した。我々の正規性モデルは、正規データのみを用いてImageNet上で学習された分類ネットワークの深部特徴表現に多変量ガウス（MVG）を与えることによって確立される。その後，マハラノビス距離を異常スコアとして適用することで，MVTec社のADデータセットにおいて，現在の技術水準を上回る性能を示し，全15クラスにわたって95.8±1.2%（平均±SEM）の受信機動作特性曲線下面積を達成した．我々はさらに、主成分分析を用いて、学習された表現がなぜADタスクに対して識別性があるのかを調査する。その結果、正常データの中で分散の少ない主成分が、正常と異常インスタンスを識別するために重要な成分であることがわかった。このことは、正常データのみを用いてゼロから訓練されたADアプローチのパフォーマンスがしばしば劣っていることの説明を与えてくれる。MVGをこれらの最も関連性の高い成分のみに選択的に割り当てることで、ADの性能を維持しながらモデルの複雑さをさらに減らすことができる。また、MVGの仮定に基づいて、許容可能な偽陽性率のしきい値を選択することで、ワーキングポイントを設定することも検討している。コードは https://github.com/ORippler/gaussian-ad-mvtec で公開されています。



##結論(DeepL訳）

我々は，ImageNet上で事前に学習されたクラスタから抽出された深部特徴量表現を用いて，MVTec ADの公開データに対して最先端の性能を達成した．我々のアプローチはシンプルでありながら効果的であり，マハラノビス距離を異常スコアとして用いて，事前に訓練された深部特徴量表現の中でMVGを正規データに変換することで構成される．我々のアプローチが有効である理由をさらに検討した。PCAを用いて、正常画像と異常画像を区別するために必要なのは、正常画像の分散が少ない主成分であることを明らかにした。我々は、これらの特徴量を正規データのみでゼロから学習するのは困難であることを主張し、MVG分布を仮定した伝達学習を用いて大規模な識別訓練によって生成された特徴量を用いることを提案する。今後の画像ADの研究では、(I)事前に学習した特徴の一般化可能性の向上、(II)少ないデータセットを用いた転写表現の微調整、(III)マルチモーダルな正規データ分布を持つADタスクへのアプローチの拡張に焦点を当てていくべきである。

⇒コメント：『・・・PCAを用いて、正常画像と異常画像を区別するために必要なのは、正常画像の分散が少ない主成分であることを明らかにした。・・』。何か、こういう部分が当たり前感が出てしまうー。

#まとめ
**画像認識とかで、それらのアウトプットの実用的な利用方法の提供が、未成熟な感じがした。**[再掲]
（少し違う例でも、率の表現で、猫99.93%とかの出力が得られるが、この率の意味もよくわからない。。。というか、利用方法が難しいと思う。）
逆に、このような論文が、アウトプットを充実したものにしようとされているのだと思うが。。。

#完全な余談

Google scholarにて、
（https://scholar.google.com/）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/9283e24d-de4e-f60c-6678-c850b333e659.png)

をたたくと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/cb87db0f-f0d7-5df2-e294-72a854525b8b.png)

のような表示が出る。
便利だと思う。
【Flutter】モバイルアプリ高速開発プラットフォームをさらに爆速化するTips

インドネシアの[PT.AQ Business Consulting Indonesia](https://aqi.co.id/)でFlutterのエンジニア兼アドバイザーをしております菊池と申します。

本記事はZennで出版しております[flutter chips](https://zenn.dev/tetsukick/books/06ee607e30e243)のchapter2-1の内容の一部になります。(本記事が2,000字程度、Zenn記事が10,000字程度)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/5183aafc-d1d7-534f-f618-031f10790fdc.png)

## Flutter向けAndroidStudioプラグイン
Flutter向けに作成されているAndorid Studioのプラグインの中から便利なものを少しだけ紹介いたします。フルVerはZenn記事にて。

### Android Studio プラグインの導入方法
プラグイン設定を開く ﻿
設定 / 環境設定ダイアログ ⌘, で、プラグインを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/4083898c-f974-e137-299a-26d375370249.png)


## Flutter Enhancement Suite
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/fa9daa27-79fd-3ceb-3b06-3034eda4f7e2.png)

ライブラリ導入時の候補表示用プラグインです。
[Flutter Enhancement Suite](https://plugins.jetbrains.com/plugin/12693-flutter-enhancement-suite)

実際に動作させている様子が以下になります。
![](https://plugins.jetbrains.com/files/12693/screenshot_20461.png)

`pubspec.yaml`上でライブラリの名前を入力すると候補を表示してくれて、最新のバージョンを自動で入力してくれます。

## Flutter Pub Version Checker
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/9c0bc51e-9fba-4aad-0495-ef07d79c6141.png)

`pubspec.yaml` 上のライブラリが最新かどうかを自動で確認してくれるプラグインです。
[Flutter Pub Version Checker](https://plugins.jetbrains.com/plugin/12400-flutter-pub-version-checker)

導入した際の実際の様子がこちらです。
`firebase_core`のライブラリを私のプロジェクトでは `0.4.4+3`のバージョンを使用していますが、すでに `1.0.1`がリリースされているので、更新を勧めてくれます。

`Opt`+`Shift`+`Enter`キーで自動で最新のバージョンに修正してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/26924d70-f0f6-525f-0bb6-11bce7ed4030.png)

## flutter-img-sync
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261934/25510833-afa4-6217-7be8-21f4ffba61f9.png)


画像をインポートしてくれて、ファイルパスや画像のプレビュー表示を行ってくれるプラグインです。
[Flutter-img-sync](https://plugins.jetbrains.com/plugin/12585-flutter-img-sync)

実際に動かしている様子がこちらです。

![](https://raw.githubusercontent.com/Leo0618/flutter-img-sync/master/androidstudio-play.gif)

r.dart形式で画像ファイルが管理され、Typoを防ぐこともできます。

## 参考記事
- [Flutterアプリ開発高速化Tips (プラグイン編)](https://speakerdeck.com/korodroid/flutterapurikai-fa-gao-su-hua-tips-puraguinbian)
- [Flutterアプリ開発高速化Tips](https://qiita.com/korodroid/items/38a702190e10e0007630)
エンジニアの初期学習において大切だと最近思ったこと

## 概要
この記事では技術ではなく学習の進め方を記述しています。

業務と独学の違いを踏まえてどのようにすると続いたか、また技術が身についたか記述していきます。


## なぜこの記事を書いた？
最近業務では携わっていない技術でアプリ開発を行っているのですが、がむしゃらに手をつけるとモチベーションと作業の進捗が著しく下がることに気づいたため、この気持ちを忘れないために備忘録的な意味を込めて作成しました。

またあわよくば、初学者の方のつまづきを減らすことにつなげることができたらいいなとも思っています。


## 主張したいこと
**一番最初はできる限り自分で考えずに動くものが作れるように、手順を記載している記事を探して実践するべし**

上記の理由なのですが、エンジニアの最初のシステム作成は挫折させるためにあるのかと思うくらい初見殺しのエラーが多発します。
そのため、局所的ではなく一連の答えを書き連ねた記事に従うことで、エラーに出会う回数を減らし挫折を防ぐべきだと思ったからです。


#### 筆者が考える理想的な手順

1. 作りたいものに似ている完成までの手順を書いてる記事を探す（そのような記事自体が少ないためここが最も難しい。例 : [過去に筆者が作った記事](https://qiita.com/KONTA2019/items/1471e0a8c16811179d65) ）
2. まるまる物真似をして手元で動かせるようにする（ソースコードの挙動を視覚的に確認し理解する）
3. 自分が作りたいものにアレンジする
4. 0から作れるようになりたければ、1~3を終わらせて戻ってこれる指標があるこの状態ではじめて作成する（急がば回れ）



## 以下余談なので気になる方だけご覧ください

#### 初期段階でつまづく要因
大抵行き詰まるときは複数のことが原因で動かなくなってしまい、１つは解けているのに依然として動かないということがあります。

サポートがない独学だと、調べ出した解決案のどれが正しいか分からないため、全ての解決案の組み合わせを試さなければなりません（解決するまでに下記の試行錯誤を実施しなければならない）

`つまづいている原因Aの解決案×つまづいている原因Bの解決×つまづいている原因Cの解決案×...`

例えばこれがそれぞれA~Cまで３通りずつgoogleで調べられたとして、１箇所（１行）の実装に27回試行錯誤を行わなければならないということになります。

また、頻度は初期段階ではアプリ完成までに（約1万行記述までに）これが10行に１度起こるイメージとなります。

それだけならなんとか根性で乗りきれなくもないのですが、解決案が全て間違っているというパターンもままあり、上記の例で言えば２７通り実施して全て動かないということがまあまあな頻度で起こります。

そのため答えが絶対に見つからないものだと思い込んでしまい心が折れて挫折してしまいます。

過去の自分を含めてここで大抵の人がドロップアウトしてしまうのではないかと思います。

上記のようなことがつまづく要因となっています。

（一応独学での解決策としては、ここで奮起してさらに解決案を検索して3通り見つけて27×３通りをためして、だめならまた検索して...となります。
そして本当に０の０で（お手本なしで）やる場合だと、上記の突破という奇跡を起こせた人だけがアプリを作成することができます。）




#### 業務と独学の違い

###### 業務
- 作るべきものについて、経験豊富なエンジニアができるだけ失敗しないようにお膳立てをしてくれたやり方で明確なゴールに向かって実装を行う

- 会社用のqiita・slackの過去のやり取り・リポジトリ内の類似の実装 があるため真似をすることで大抵悩まずに実装することができる

- 仮に上記からヒントを得ることができなくても上司・先輩がおり、誰かしら解決の経験からピンポイントの答えを持ち合わせているため、つまづいたとしても９９％解決できる

- 上司・先輩に質問するとにつまづいた要因以外に、自分では気づけていないつまづいている要因まで見こした解決方法を教えてもらえるため、絶対にできないという絶望感を感じることがない

###### 独学

- 技術的縛りがないため自分がやりたい技術を使える

- 誰も助けてくれないので、正しいかどうか分からない記事を自分で使えるか判断して試行錯誤しなければならない

- やり方を間違えると絶対に直らないと思えるエラーに出会える。

#### 業務以外でアプリ（システム）の作成・スキル取得はほぼできないのか？
最初の主張に戻りますが、戻れる指標（参考にできるシステム構築の経験）があればつまづきを大きく減らせます。

なので、業務につく前の人はいかに挫折しないかを第一で考えることで学べば、業務でなくても無事スキルを身につけることができ、アプリ作成もできると思います。

#### これまで筆者が出会ってきた一連の手順を記載してある記事

- https://reffect.co.jp/laravel/finally-understand-laravel-on-docker

- https://gihyo.jp/book/2020/978-4-297-10973-8

- https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%83%BB%E5%80%8B%E4%BA%BA%E3%81%A7%E4%BD%9C%E3%82%8C%E3%82%8B-%E3%82%B9%E3%83%9E%E3%83%9B%E5%90%91%E3%81%91Unity-%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%82%B2%E3%83%BC%E3%83%A0%E9%96%8B%E7%99%BA%E3%82%AC%E3%82%A4%E3%83%89-%E5%B9%B3%E9%87%8E%E8%A3%95%E4%BD%9C-ebook/dp/B083Z2Z6PH

- tech::expertの教材（接客対応は多少違和感を覚えるところはありましたが、教材はなかなかよかったです。多岐の技術を横断する一連の手順書でここまでのものはまだ他に見つけていないです。）

- プロゲート（一応一連の流れを学べるのだが、一番つまづく環境構築を飛ばしたところからスタートで、かつ手元に完成品が残らずアレンジを試せたりしないため筆者としてはいまいち身につかない感触でした。）

- 記事を見ながらの作成動画（例:https://www.youtube.com/watch?v=u5BAt0hLgsk ）
AWS Device Farm で実機を利用したウェブアプリのテストを行う(リモートアクセス版)

## はじめに
新規実装した画面のUIをさまざまなデバイスでちょっと確認したいとか一部のデバイスでのみ発生するバグの再現確認をしたいという場合がWebアプリケーションの開発を行っているとたびたびあります。

AWS Device Farmのリモートアクセスを利用することで比較的簡単にさまざまなデバイス/OSで画面や挙動を確認することができたので、方法をまとめます。

## AWS Device Farmとは
下記の公式の説明にあるようにAWSのクラウドを通じて、実機のiOS/ Androidの端末にアクセスできるサービスです。
2021年現在は、us-west-2 (オレゴン) リージョンでのみ利用できるようです。

>Device Farm は、実際に Amazon Web Services (AWS) によりホストされている電話やタブレットで、Android や iOS、およびウェブアプリを物理的にテストしてやり取りできるアプリテストサービスです。
 
参考:[AWS Device Farm 開発者ガイド](https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/welcome.html)

## 手順

1 AWSコンソールにログインし、AWS Device Farmのサービスを開きます
2 下記のような画面が表示されるので"Create a new project"をクリックします

![create_project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584011/e706dbcb-dc9f-4ef3-cb20-90242cf92c8d.png)

3 ダイアログにプロジェクト名を入力して、"Create project"をクリックします

![create_device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584011/2efb350a-f87c-5117-d7f3-bff27a9181eb.png)
 
4 プロジェクトの中で、"Remote Access"のタブを選択します

![remote.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584011/4d15b26c-173e-5a7c-c518-32ebe42ab723.png)

5 "Start a new session"をクリックすると、デバイスの選択画面が表示されます

![select_device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584011/034bf258-6565-3b0a-a27f-84e884a00354.png)

6 リモートアクセスを行いたいデバイスを選択し、"Confirm and start session"をクリックすると対象のデバイスへのアクセスが開始されます(この時点から課金対象となります)

![device4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584011/cc3df635-7292-02d9-e882-2cb6b750a4bd.png)

7 操作後は、"Stop session"をクリックします(ここで課金がストップします)

8 操作時のlogやVideoなどを完了後の画面で取得することができます

#### 注意点
* クリップボードの共有はできないのでwebのURLなどは手打ちで入力が必要です
* iOS/AndroidのNativeアプリをダウンロードする場合は別途ダウンロードする作業が必要です
* 専用デバイスを利用しない場合、混雑状況によってはすぐに利用できないことがあります
* 操作時のVideoが自動で録画されるので個人情報などの入力はしないほうが良いです

## 料金
プランとしては、2021年現在では下記の3種類あるようです。

* 従量課金 0.17USD/デバイス分
* 月額250.00USDで使いたい放題
* 月額200USD~でアカウント専用にデプロイされた専用デバイスを利用

参考：[AWS Device Farm の料金](https://aws.amazon.com/jp/device-farm/pricing/)

従量課金の場合は最初に1000分の無料アクセス枠があるので、まずは従量課金で自分のプロジェクトに合うかどうかを試してみてから利用するかどうかを決めると良いと思います。

## 社内のファイアウォールの内側にテスト対象のアプリケーションが存在する場合
54.244.50.32–54.244.50.63 および 99.78.197.0/29 の IP アドレスがAWS Device Farmでは利用されているようです。

これらのIPアドレスからのリクエストを許可することで社内ファイアフォールに構築されたアプリケーションに対してもAWS Device Farmが利用できそうです。(ファイアウォールの内側へのアクセスは当方、未検証なので、ご指摘あればご連絡ください。)

参考：[AWS Device Farm の IP アドレスの範囲を教えてください](https://aws.amazon.com/jp/premiumsupport/knowledge-center/device-farm-ip-range/)

## 最後に
スマートフォンはOSもデバイスも進化が激しく、全てのデバイスを自社で保持しておくのが困難なのでこのように簡単にさまざまなデバイスでの実機検証ができて便利だなと思いました。

今回は簡単に触ってみることのできるリモートアクセスについてのみ記事をまとめましたが、CIツールと組み合わせた自動テストなどで本領を発揮すると思うので、そちらについてもまたタイミングをみてまとめようと思います。

それでは、素敵な開発ライフを。

## 参考リンク
* [AWS Device Farm のアップデート – デバイスにリモートアクセスしてインタラクティブなテストが可能に](https://aws.amazon.com/jp/blogs/news/aws-device-farm-update-remote-access-to-devices-for-interactive-testing/)
* [AWS Device Farm 開発者ガイド](https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/welcome.html)
* [AWS Device Farm の料金](https://aws.amazon.com/jp/device-farm/pricing/)
Visual Studio 2019でのwin32APIを使ったデスクトップアプリケーションのプロジェクト作成方法

## はじめに
Visual Studio 2019によるWin32APIを用いたアプリケーション開発をおこなう際に、プロジェクトの作成から手間取ったので、ここに記しておく。

## プロジェクトの作成

### 新しいプロジェクトの作成を選択
![win32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567302/0e50202b-aeb7-3f42-aa3a-aff38b213528.png)

### テンプレートの選択

テンプレートの中から「Windows デスクトップ ウィザード」を選択して、次にボタンを押す。
![win32_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567302/4645d310-c589-0d46-c570-67d435198d93.png)

### プロジェクト名・保存場所・ソリューション名を決める

プロジェクト名、保存場所、ソリューション名を決めて、作成ボタンを押す。
頻繁に使うプロジェクトの場合、保存場所はDesktopにした方がいいかも。。。
![win32_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567302/5066afe4-d353-338b-02ef-4466674984d3.png)

### アプリケーションの種類とオプション選択

アプリケーションの種類でデスクトップアプリケーションを選択して、追加のオプションはからのプロジェクトにしておく。

![win32_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567302/d4187ed8-673b-9b80-4758-a99e302f8291.png)

後は、新しいファイルを作るなりして、進めていけばいい。
Selenium Proxyの設定はどこに書くのが正解なんですかねぇ、、という話

# Deprecation Warning
Selenimu + browsermob-proxyの動作をいろいろ試してみて。
いくつかのサイトを参考にさせていただくと、一回profileを作成し、そこにproxyとしてbrowsermod-proxyを設定し、それをwebdriverに食わせる、という方法を取ります。

それはそれでちゃんと動くのですが、以下のアラートが出ます。

```
"This method has been deprecated. Please pass in the proxy object to the Driver Object",
```

「その機能、使わせてはあげるけど、新しい方法用意してあるからそっち使ってね」というものですね。
じゃぁ、ちゃんと正しい方法とやらを使ってみますか、、と思ったらそうは行かなかったという話です。

# 言うとおりにしてみると、、
profile経由でproxy設定を与える場合、こんな感じになります。

```python
from browsermobproxy import Server
from selenium import webdriver

# browsermob-proxyの設定
server = Server("./browsermob-proxy-2.1.4/bin/browsermob-proxy")
server.start()
proxy = server.create_proxy()

# proxyleの設定
profile = webdriver.FirefoxProfile()
profile.set_proxy(proxy.selenium_proxy())

# profile経由で、webdriverにproxyを設定
dirver = webdriver.Firefox(firefox_profile=profile)
```

一方、（おそらく）推奨の方法だと。

```python
# 直接webdriverにproxyを設定
dirver = webdriver.Firefox(proxy=proxy.selenium_proxy())
```

で、コレで実行すると、、、browsermob-proxyからharが出せない！！
seleniumがproxy通さずに通信しちゃってるっぽい。。。。

実際にコードを見てみると、、
一応ifの一部条件ではproxyの値を参照するのだけど、保持してない＝使ってないっぽいですね。。
https://github.com/SeleniumHQ/selenium/blob/selenium-3.141.0/py/selenium/webdriver/firefox/webdriver.py

# 結局どうすりゃいいのさ、、
pipで導入されるバージョンは3.141.0で、最新のバージョンだと4.0系があるのですが、これ4.0系でもwebdriverが引数で取るproxyは、取るだけ取って使ってないっぽい。。
4.0だとそもそもprofile自体が非推奨になり、optionsを使うようになるのですが、こちらもprofile同様にproxyの値を受け取れます。

seleniumを最新の4.0.0b1にあげて、optionにproxyを与えて、それをwebdriverに食わす方法を取ると、、OK。

```
$ pip3 install -U selenum=4.0.0b1
```

```python
from browsermobproxy import Server
from selenium import webdriver


server = Server("./browsermob-proxy-2.1.4/bin/browsermob-proxy")
server.start()
proxy = server.create_proxy()

options = webdriver.FirefoxOptions()
options.set_preference('browser.privatebrowsing.autostart', True)
options.set_preference('browser.privatebrowsing.dont_prompt_on_enter', True)

proxy=proxy.selenium_proxy())
options.proxy = proxy.selenium_proxy()
driver = webdriver.Firefox(options=options)
```

ちゃんとproxy通る通信になるし、Deprecationエラー”は”、でなくなりますね。
でも、今度はchardetとurllib3のバージョンが、OS側とpip側で会ってないよというアラートが。。
ちなみにこれselenium 3.141.0で実行すると、optionでエラーが出て、実行できません。

# まとめ
まぁアラートの話なので、無視するとわりきりゃいいっちゃいいんですけどね、、
Depricatedって言うなら、正しい方法ちゃんと動くようにしてからにしてほしいなぁという話でした。
私が意味取り違えてるのかもしれませんけれど、なんともなぁ。。
【C#】internalクラスに対してテストコードを書く方法

## はじめに
`internal`クラスに対してテストコードを書こうとした場合、アクセス制限に引っかかりテストコードが書けない。
この記事ではその場合の解決方法をまとめる。

## 現象
あるプロジェクトで以下のようなコードがあったとしよう。
`Calculator`というクラスに2つの値を渡し、足し算した結果を表示するプログラムだ。

```cs:Program.cs
namespace InternalClassSample
{
    class Program
    {
        static void Main(string[] args)
        {
            var calculator = new Calculator(1, 2);
            Console.WriteLine(calculator.DoAddition());
        }
    }
}
```

```cs:Calculator.cs
namespace InternalClassSample
{
    internal class Calculator
    {
        private readonly int _left;
        private readonly int _right;

        public Calculator(int left, int right)
        {
            _left = left;
            _right = right;
        }

        public int DoAddition()
        {
            return _left + _right;
        }
    }
}
```

どうやらこの`Calculator`クラスは同一アセンブリ内でしか使用されていないため、`internal`クラスとして定義されているようだ。

さて、このたびプロジェクトでは品質を上げるためにテストコードを書くことになったとしよう。
早速、`Calculator`クラスに対してテストコードを書くため、テストプロジェクトを用意してテストコードを書いてみた。

```cs
namespace InternalClassSample.UnitTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void Test_DoAddition()
        {
            var calculator = new InternalClassSample.Calculator(1, 2);
            Assert.AreEqual(3, calculator.DoAddition());
        }
    }
}
```

早速コンパイルしてテストを走らせてみよう。

```
error CS0122: 'Calculator' はアクセスできない保護レベルになっています
```

残念なことにエラーになってしまった。
`Calculator`クラスが`internal`であるために、新しく追加したテストプロジェクトからはアクセス制限に引っかかってしまうのである。

プロジェクトの方針としてテストコードを書かなければならないが、このままではテストコードを書けない。
このエラーを何とかして回避する方法はないだろうか？

## 解決方法
私がこの記事で伝える解決方法は以下の2つだ。
**1. アクセス制限を緩める**
**2. 特定のアセンブリにだけinternalクラスを公開する**
それぞれについて詳しく解説していこう。

### アクセス制限を緩める
こちらの方法はかなり単純な方法だ。
`Calclator`クラスのアクセス修飾子が`internal`だから見えないのだから、よりアクセス制限が緩い`public`に変更し、テストコードのプロジェクトからも見えるようにすれば良い。

具体的には、コードを以下のように変更する。

```cs
// アクセス修飾子をinternalからpublicへ変更する
public class Calculator
```

この方法のメリットはinternalからpublicへ変えるだけなので、修正が簡単であることだ。
ただし、デメリットとして今後はどこからでも利用可能となるため、使用するべきではないところから呼び出されてしまう可能性が出てくる。
特にコードが膨大になっている場合、アクセス制限を緩めてしまうと、今後、様々な場所から呼び出されてしまい、変更が困難になる可能性もある。

### 特定のアセンブリにだけinternalクラスを公開する
こちらの方法は先程のデメリットを抑えつつ、修正もそれほど多くないためオススメの方法だ。
`InternalsVisibleToAttribute`を使い、テストプロジェクトにだけ`internal`クラスを公開すれば良い。

具体的には`Calculator`クラスが含まれるプロジェクトの`AssemblyInfo.cs`に以下のコードを追記する。

```cs:AssemblyInfo.cs
[assembly: InternalsVisibleTo("InternalClassSample.UnitTest")]
```

こうすることでテストプロジェクトにだけ`internal`クラスが見えるようになるため、アクセス制限を緩めたりせずにテストコードを書くことができる。
また、上記の1行を追加すれば良いだけなので、修正もそれほど多くならないはずだ。

## まとめ
今回は`internal`クラスに対してテストコードを書く方法ということで、その方法をまとめてみた。
この記事を書くにあたって`InternalsVisibleToAttribute`を初めて知ったが、今後テストコードを書く際に使えそうな機能なので覚えておきたいと思う。

それではまた。
TomoProg
docker-composeを使ってPostgreSQL環境を構築する

## 概要

目的：postgresqlの環境をローカル環境に依存しないdocker-composeだけで実現する。

経緯：OSアップデートをしてBig Surにした結果Homebrewが使えなくなり、psqlコマンドでpostgresqlサーバーを立ち上げることが非常に困難になった。（おそらく復旧は不可能ではないが、めちゃくちゃ時間がかかると思われる。）



## docker-composeファイルの中身

以下の内容ですぐにpostgresql環境を構築することができます。

```docker-compose.yml

version: '3'

services:
  postgresql:
    image: postgres:10.5
    container_name: postgresql
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD:
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
    hostname: postgres
    restart: always
    user: postgres
    volumes:
      - "./data/psql:/data"

```

## 注意点

このpostgresqlサーバーを立ち上げる際に、psqlコマンドを使う場合はきちんと下記のhost名、port番号、postgresqlのユーザー名を指定する必要があります。


## まとめ

ローカルでの開発環境はなかなか難易度が高い + OSなどの他の要素に依存する部分があり、「ある日急に使えなくなった」なんてことが起こりえます。

実際に自分もBig SurにOSアプデした時に経験してます。。。

僕と同じような境遇の方は、ぜひこのdocker-compose.ymlファイルを使ってみてください。
vscodeでpandasが補完されない

## VSCodeでPandasを使っていたら、補完が全然効かなかった。
reなどの内部モジュールやpdから呼び出すときは問題なく効いていたIntellisenseがpd.Dataframe型のオブジェクトに対しては全く効かなかった。

## 【結論】変数に型ヒントを書こう。
```python

df: pd.DataFrame = pd.read_csv(hogehoge)
```
としてやることでdfに対してIntellisenseが効くようになった。参考にしたtelatailの投稿によれば、大規模モジュールの場合名前解決に時間がかかりすぎてタイムアウトになっているのではということだった。

## やったけど関係なさそうだったこと
setting.jsonにPathを追加してみたが、解決しなかった。
当然だよね…Pathに問題はなかったからね…。

https://qiita.com/kusanoiskuzuno/items/fc6a32ef32dd9500f746

　　
　　
　　
**とかく、型ヒントを変数に与えるということで解決できたので一件落着。**


## 参考ページ

https://teratail.com/questions/117685
Vimことはじめ

#はじめに
たまにVimを使うが、コマンドを調べた端からどんどん忘れるので、Vimの理屈とともに、よく使う順にメモ。

大文字アルファベットは`Shift+英字`の意味。
また、`:`から始まるコマンドは最後に`Enter`が必要（後述）。

#1.超基本(これだけできれば最低限なんとかなる)
VimはCUIエディタなので、基本的にはマウスが使えない。マウスを使わない編集をしやすくするため（むしろ昔はこれしか手段がなかったわけだが）、Vimは**ノーマルモード**（文書中の移動やコピーなどの操作）と**挿入モード**（文字の直接入力）、**コマンドモード**（Vimそれ自体の操作）といった**モード**を使い分けて編集作業を進める。

| コマンド | 動作 | メモ |
|:-:|:-:|:-:|
|（コマンドモード時に）`i`|挿入モードに移行| これがないと始まらない。以降特記しない場合は、コマンドはコマンドモードで入力する |
|（挿入モード時に）`Esc`|コマンドモードに戻る| 変なコマンドを打ってしまいなんか変なことになったら連打すれば大抵コマンドモードに戻る |
|`:w`|保存|末尾に"!"をつけると強制的に（読み込み専用で開いていても）書き込む|
|`:q`|Vimを終了|末尾に"!"をつけると強制的に（編集を保存せずしていなくても）終了する|
正確には`:`はノーマルモードからコマンドモードに移行するためのコマンドで、`w`や`q`はコマンドモード下で有効なコマンドだが、以降は特に区別せずよく使う（？）順にまとめていく。

#2.基本(基本的な編集・移動)
流石に上のだけだと大変なので、もうちょっとエディタらしい操作をしたくなる。そこでこいつら。

| コマンド | 動作 | メモ |
|:-:|:-:|:-:|
|`gg`|先頭に戻る|`g`は（多分）gotoの頭文字で、二文字で組み合わせて使う。gotoを表す`g`が２回なので、一番基本な移動、すなわち文章先頭に移動|
|`G`|末尾に移動|`Shift`を組み合わすと大抵補助的な動作を表す。gが文書の最初を起点として移動していくのに対し、`Shift+g`はその反対、すなわち末尾に移動|
|`yy`|一行コピー|二文字組み合わせ系その二。yank（引っ張る）の頭文字。2回繰り返して最も基本的なコピー動作、すなわち単行コピー|
|`p`|ペースト|pasteの頭文字|
|`dd`|一行削除|二文字系その三。deleteの頭文字で、繰り返しで最も基本的な単行消去|
|`u`|ひとつ前に戻す|undoの頭文字|

#まとめ
気が向いたら随時更新します。
Vagrant・Docker上でPHPのバージョンが５系だった時の対処

Dockerfile上で
RUN yum -y install —enablerepo= remi-php72 php php-mbstring php-mysqlnd php-pdo
と記述し
docker-compose build
とコマンド打ち込むもDocker上のPHPのバージョンが5.4.45のままだった。
![スクリーンショット 2021-03-07 9.32.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1190042/5f5cc750-baa3-c267-a028-8cc589656f31.png)

docker ps -a
で現在Docker上に出来ているコンテナを確認し、

docker rm （コンテナID）

や

docker images
docker rmi (イメージID)

を実行し、ガベージファイルを削除した後にもう一度ビルドしても結果は変わらず。そんなことを2度、３度繰り返しても埒が明かないまま一夜がすぎそうになったが解決したのでここに方法を記したい。

RUN yum -y install —enablerepo= remi-php72 php php-mbstring php-mysqlnd php-pdo

を

RUN yum -y install --enablerepo=remi,remi-php72 php php-mbstring php-mysqlnd php-pdo

としたところ解決しました。ちゃんちゃん。
![スクリーンショット 2021-03-10 0.09.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1190042/8459da2f-437e-04bc-d0ec-ec04823eee0e.png)
Goでembedパッケージ使って大事なものを埋め込んではいけない

# TL;DR
* Go 1.16からファイル内容をバイナリに埋め込むembedパッケージやディレクティブが追加された
* ただ、パスワードやAPIトークンなどのバレたらまずいデータは埋め込まないこと
    * 実行ファイルにそのまま埋め込まれているので
    * どうしても埋め込みたいなら予めcryptoパッケージでハッシュ化しておいた内容を埋め込むなどする
        * ~~それでもバレるときはバレる~~
* これはGoに限った話ではない
    * Windowsでいう[リソースファイル](https://docs.microsoft.com/ja-jp/cpp/windows/resource-files-visual-studio?view=msvc-160)の仕組みと同じようなもの
* センシティブな情報は安易に埋め込まない

# embedの使い方

以下のコードで `embed_data.json` の内容を実行バイナリに含むことができる

```golang:main.go
package main

import (
	_ "embed"
	"encoding/json"
	"fmt"
)

//go:embed embed_data.json
var embedData []byte

// UserData ユーザーデータ（例：API実行用のユーザー）
type UserData struct {
	Key1 string `json:"user"`
	Key2 string `json:"password"`
}

func main() {
	userData := UserData{}

	err := json.Unmarshal(embedData, &userData)
	if err != nil {
		panic(err)
	}

	// 試しにデータを見る
	fmt.Printf("%v\n", userData)
}
```
```json:embed_data.json
{
    "user": "hogehoge",
    "password": "fugafuga"
}
```

```sh:実行結果
$ ./embed_test.exe 
{hogehoge fugafuga}
```

# 実行ファイルを覗くと・・・？
* しっかり生データが実行バイナリに埋め込まれている
    * つまりバイナリを覗かれると大事なデータが引っこ抜かれる可能性がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102564/7c8730bd-d88a-f085-2422-31162143aa56.png)

# embedは何に使うべきか？
色々あると思うが、個人的には以下がぱっと思いつくもの

* テンプレファイル
    * 自動でMarkdownやテキストデータを出したいときの下地を埋め込む
* デフォルト設定ファイル
    * ユーザーの設定ファイルがないときに使用する設定ファイル
* 依存データを無くしたいときのデータ埋め込み手段
    * 「とにかくバイナリのみで動かしたい！」というとき
* etc...

# 参考文献
* [Go 1.16からリリースされたgo:embedとは](https://future-architect.github.io/articles/20210208/)
vSphere 7 Update 2 登場

2021年3月9日、vSphere 7 の新しい Update 2 の登場したので、ブログに記事を書きました。
以前作成していた「vSphere 7 へのアップグレード」の資料も、そちらにvSphere 7 Upgrade 2対応したものを載せてあります。


https://imaisato.hatenablog.jp/entry/2021/03/09/235342
「[python]約数を列挙するプログラム」を参考にWolframAlphaとSymPy Liveでやってみた。SOで教えてもらった。

(オリジナルポスト)

https://qiita.com/tokki7127/items/bde22d8c0fdafbe531e3

#WolframAlphaで

https://ja.wolframalpha.com/input/?i=30%E3%81%AE%E7%B4%84%E6%95%B0

入力解釈:
約数 | 30
約数:
1 | 2 | 3 | 5 | 6 | 10 | 15 | 30 (8 個)
素因数分解:
30 = 2×3×5 (異なる素因数3個)

##SymPy Liveで
以下サイトに、print文を貼り付けて下さい。

https://live.sympy.org/


print(divisors(30)) 
[1, 2, 3, 5, 6, 10, 15, 30]

又は

divisors(30) 


#SOで教えてもらった
https://ja.stackoverflow.com/questions/74430/%e7%b4%a0%e5%9b%a0%e6%95%b0%e5%88%86%e8%a7%a3%e3%82%92%e7%b4%84%e6%95%b0%e3%81%ab%e3%81%99%e3%82%8b-%e3%83%ab%e3%83%bc%e3%83%97-%e7%b5%84%e3%81%bf%e5%90%88%e3%82%8f%e3%81%9b%e3%81%ae%e6%96%b9%e6%b3%95%e3%82%92%e6%95%99%e3%81%88%e3%81%a6%e4%b8%8b%e3%81%95%e3%81%84
STM32F103C8のArduinoでの時計,DS1307で時刻表示OLED,OLED096UNO-A


stm32g031,stm32l010用に最軽量化したもの

x時間合わせは、別
x大幅に説明を省略

1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

```c++

#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h> //I2C library

//f103
#define sdaPin PB7    // ArduinoA4
#define sclPin PB6    // ArduinoA5

#define ADDR    0x68  // 2進数 1101000

U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE); 	      

int     ii;           //ループカウンター
int     jj;           //ループカウンター
int     cursor1;      //カーソルの位置
char    data_read[8]; //i2cバッファー

//時間をoled表示形式に変換
char ch_hex_a_b[4];
char *ch_hex_a(int l_num)
{
    ch_hex_a_b[0] = '0' + (l_num >> 4);
    ch_hex_a_b[1] = '0' + (l_num & 0xf);
    ch_hex_a_b[2] = ':';
    ch_hex_a_b[3] = 0;
    return(ch_hex_a_b);
}

void i2c_oled_w(char *s)
{
            //文字の表示
            u8x8.drawString(
            ((cursor1-0) & 0x07  )*2, // x
            (cursor1>>3)*2,           // y
            s);
            cursor1=cursor1 + 3; 
} //i2c_oled_w

void setup(void)
{
  delay(2000);
    
  u8x8.begin();

  u8x8.setFont(u8x8_font_px437wyse700a_2x2_r);
  
  cursor1 = 0;
  i2c_oled_w("START");
  delay(500);

  //画面のクリア
  for(jj=0;jj<4;jj++){
    //              x    y   12345678
    u8x8.drawString( 0,jj*2,"        ");
  }//enf for
  //カーソルのクリア
  cursor1 = 0;

  //Wire.begin(sdaPin,sclPin); //f103
  Wire.begin(); //f103
  
}

void loop()
{
  //行のクリア
  //              x    y   12345678
  //u8x8.drawString( 0,jj*2,"        ");
  //カーソルのクリア
  cursor1 = 0;


  // レジスタのアドレスを先頭にする
  Wire.beginTransmission(ADDR);
    Wire.write(0x00);
  Wire.endTransmission();

  // I2Cスレーブに8byteのレジスタデータを要求する
  Wire.requestFrom(ADDR, 8);

  // 8byteのデータを取得する
  for (ii = 0; ii < 8; ii++) {
    while (Wire.available() == 0 ) {}
    data_read[ii] = Wire.read();
  }//for

  //画面に表示
  i2c_oled_w(ch_hex_a(data_read[2]));
  i2c_oled_w(ch_hex_a(data_read[1]));
  ch_hex_a(data_read[0]);ch_hex_a_b[2]=0;
  i2c_oled_w(ch_hex_a_b);

  delay(1000);  //1秒待つ

}//loop


```

時間合わせ

```c++

#include <Wire.h> //I2C library

#define ADDR    0x68  // 2進数 1101000

char    data_read[8]; //i2cバッファー

#define HH  12
#define MM  34

void setup()
{
  Wire.begin(); //uno

//i2c書き込み
  Wire.beginTransmission(ADDR);

  Wire.write((char) 0    ); //0 レジスターの位置は0
  Wire.write((char) 0    ); //1 秒
  Wire.write((char) ( MM /10)*16+( MM %10) ); //2 分
  Wire.write((char) ( HH /10)*16+( HH %10) ); //3 時

  Wire.write((char) 3    ); //4 曜日
  Wire.write((char) 1    ); //5 日
  Wire.write((char) 1    ); //6 月
  Wire.write((char) 0x20 ); //7 年

  Wire.endTransmission();

} //end setup

void loop()
{

} //loop


```


![i2c_oled_ds1307_F103_ar_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3d830aab-8779-6f5b-2d83-62c04fd8caad.jpeg)


![i2c_oled_ds1307_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/716d120d-386c-9d2b-10cc-fb3279adcf5f.jpeg)
Railsチュートリアル最速完遂します。


#経緯
エンジニア歴は１年半。主にJavaの簡単なWebアプリ開発とテスター。
だがぶっちゃけ今まで大して勉強せずに過ごしてきた。


勢いで運良く3月にWeb系企業に転職したものの、レベルが違いすぎていきなりお荷物。
しかも同月に娘を授かり、いよいよ家族を養う立場に。市場価値が低いままではいられない。
頑張れ俺...!!

来月以降に着手予定のRails案件に向けて、
まずは今月中にRailsチュートリアルを完遂していく。



#学習の方法
毎日8時間、いや自由時間は全部フルコミットします。
得た知見をQiitaでアウトプットして理解を深める。
Qiitaの毎日投稿は1年は続ける。

できるだけ毎日。
毎日学び、成長し、その過程を楽しむ、という癖をつける。


#終わりに
Qiitaの投稿システムよくわかっていないので、日々更新の中で習得していきたい。
間違っている部分などあればバシバシ突っ込んで頂ければと思います。
よろしくお願いします！
レイアウトテンプレートについて

#レイアウトテンプレートとは
アプリケーションにおけるビューファイルをまとめたものです。
レイアウトテンプレートにheadの情報などの共通部分をまとめるで、
各ファイルで同じことを記述する必要がなくなります！

Railsの場合はapplication.html.erbというファイルがレイアウトテンプレートになります。
以下は新規アプリケーションを作成した時のapplication.html.erbファイルの中身です。


```ruby:qiita.rb

<!DOCTYPE html>
<html>
  <head>
    <title>タイトル</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

```

このようにhead要素、body要素があらかじめ作成されているので、中身を修正して使用します。
繰り返しになりますが、ヘッダーやフッターなどの共通部分はここに書いてしまえば、ビューファイルの全てに同じような書き込みをする必要がなくなり、記述ミスの削減・可読性の向上が見込めます！

なぜここに書き込めば他のファイルで記述する必要がなくなるかというと、
body要素内にあるyieldが関係しています！

#yieldメソッドについて
yieldメソッドとは、レイアウトテンプレートを各ファイルに展開するためのメソッドです！

この部分ですね。

```ruby:qiita.rb
<body>
  <%= yield %>
</body>
```

このyieldという部分に、indexアクションが起きればindex.html.erbが、newアクションが起きればnew.html.erbファイルの内容が集約されるため、head要素やヘッダー・フッターの内容などを書く必要がなくなるというわけです。


以上がレイアウトテンプレートについての概要です。
続いてCSSファイルを適用するための記述になります。


#stylesheet_link_tagメソッド
この部分についてです。

```ruby:qiita.rb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
```

CSSファイル読みこむヘルパーメソッドです。
CSSファイルはapp/assets/stylesheets/というディレクトリに配置します。

stylesheet_link_tagの引数にapplicationと書いてあるため、app/assets/stylesheets/ディレクトリ内のapplication.cssというCSSファイルが読み込めます。

#まとめ
①レイアウトテンプレレート使えば、共通の記述をひとまとめにできる
②yieldメソッドが記述されてるため、各ファイルに共通の記述が展開できる
③stylesheet_link_tagはCSSを読みこむメソッド
iPhoenのSafariのエラーでしょ？？それ「remotedebug_ios_webkit_adapter」で解決できるよ

皆さんこんにちは！

皆さんは開発するときになんのPCを使っていますか？？？

僕はお金ないので学校で配布されたWindowsを使用しています。

メモリも4GBとDockerで開発するときは結構止まったりします。

めちゃめちゃMac欲しい。。。

これだけの問題ならいいのですが、何と言っても本番環境のSafariのエラーほど苦しむものはない！

今日はそんなWindowsで開発している方でSafari特有のエラーログをChromeで見る裏技をご紹介します！

Windowsユーザーの皆さん、**打倒Safari**と行きましょう！！！

#セットアップ#

まずはSafariをデバッグするためのセットアップを行いましょう！

##iTunesをインストール##

[こちら](https://www.apple.com/jp/itunes/)からiTunesをインストールしてください。

iTunesをインストールしないとデバッグできませんのでご注意を

##Safariの設定##

お使いのデバイスの「設定」→「Safari」→「詳細」から「Webインスペクタ」を「ＯＮ」にしてください。

##scoopのインストール##

次に「scoop」をインストールします。

scoopとはＭａｃで言うHomebrewみたいなものです。

WindowsのPower shellを「管理者として実行」し、下記のコマンドを入力

```
> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
iwr -useb get.scoop.sh | iex
```

##gitのインストール##

既にgitコマンドを打てている人はこちらはスルーしてください。

```
> scoop install git
```

##npmのインストール##

こちらも既にnpmコマンドを打てている方はスルーしてください。

```
> scoopi install npm
```

##extrasの追加##

```
> scoop bucket add extras
```

##デバッグ用のパッケージインストール##

ここからは一気に行きます

```
> scoop install ios-webkit-debug-proxy
```

```
> scoop install nodejs
```

```
> npm install remotedebug-ios-webkit-adapter -g
```

これでデバッグを行う準備が整いました。

#Safariのデバッグ#

ここらは、iPhoneとWindowsをケーブルで繋いだまま行ってください。

Windowsに接続している状態でSafariでデバッグをしたいページを開いてください。

Power shellで以下のコマンドを実行

```
> remotedebug_ios_webkit_adapter --port=9221
```

[chrome://inspect/#devices](chrome://inspect/#devices)にアクセス

Configureをクリックし、Target discovery settingsにlocalhost:9221を追加

すると、Remote TargetにSafariで開いたページのURLが表示されます。

下の「inspect」をクリック

そしたら、いつもの通りに開発者ツールでデバッグできます。

いかがだったでしょうか？？？

意外とすんなりとデバッグできることに驚きました。

また、WindowsにもHomebrewみたいな機能があるとは驚き。

みんなでChrome使えば平和なのにな～

以上、「iPhoenのSafariのエラーでしょ？？それ「remotedebug_ios_webkit_adapter」で解決できるよ」でした！

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

あと、最近「ココナラ」で環境構築のお手伝いをするサービスを始めました。

気になる方はぜひ一度ご相談ください！

Thank you for reading

#参考記事#

[WindowsでiOSのSafariで開いたページをデバッグする](https://webkatu.com/202005091640-ios-safari-debug-on-windows/)
仮想マシン上のSeleniumをssh経由で駆動するTIPS

#　Seleniumで色々試すけど、、
Seleniumで少々試行錯誤しながら作り込みをする必要があり。
ポリシーで開発系は手元のPCには展開せず、一段仮想マシンを作ってその上に一通り展開する方式を取っているので、SeleniumについてもXubutu on 仮想マシンで動作させます。
ただ、動作させるためのコードも仮想マシンで書こうとすると微妙な画面サイズやらマウスが捕まったりとかキーバインドの変更とかが色々とめんどくさい。
PCのOSから仮想マシンにSSHして、そこでコードを書きつつ、かつ仮想マシン上でブラウザを立ち上げてSeleniumで操作したい。
そういうときのTIPSの話。

# DISPLAY(環境変数)の確認
SSHで仮想マシンにログインした状態で、Selenumを呼び出すコードを書いて実行、、してもエラーで止まります。
これはプログラムがブラウザを起動しようとした際、どの画面（Display）に描画していいかわからないからなわけですね。

仮想マシンのWindowをPC上で開いていて、その中でブラウザがガリガリSelenium配下で動いてほしい。
なので、仮想マシンのWindowに該当するDisplay情報を調べます。

```
$ who
user tty7 2021-03-09 00:00 (:0)
user pts/0 2021-03-09 00:00 (10.0.0.1)
```

現在OS(仮想マシン)にログインしているユーザと、ログイン経路を表示するコマンドですね。
１行目が、Window上で画面表示してる仮想マシンへのログイン情報。
２行目が、手元のPCからSSH経由でログインしてる情報。

１行目の":0"が、今回使いたいDisplay情報

# DISPLAYの設定とipythonの起動
上記で調べたDisplyを有効にしつつipythonを起動したい場合。

```
$ env DISPLAY=":0" ipython
```

これでOK。
この方法でipythonを起動して、その上でSeleniumを呼び出せば、仮想マシン用に開いたWindows上でブラウザがグイグイ動きます。

まぁ、そんだけ。
【Vue.js】Vuex導入

# Vuex とは何か？
データ管理専門のVueインスタンス
状態管理センターとも呼ばれる
どこからでも値（state）を参照できるという意味でセンター

# インストール

```
$ npm install vuex
```

# Vuex 入門
## 基本設定

src/store/index.jsを作成
Storeの作成

```index.js
"use strict"

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: { // ≒ data
      message: 'hello world',
      count: 0,
    },
    mutations: { // ≒ methods
      increment (state) {
        state.count++
      }
    },
    // getters: { ... },// ≒ 算出プロパティ
    // actions: { ... } // ≒ mutationsの実行を非同期に行う場所
  });
  
export default store
```
main.jsでsrc/store/index.jsを読み込む

```main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router' //index.jsのexport default routerから受け取る
import store from "./store";

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

```
# Storeのプロパティ
jsファイル側にプロパティを設定して、コンポーネント側で使う
### state・mutations
各コンポーネント側からmutationsに設定されたメソッドを実行することを、「commitする」という

```index.js
const store = new Vuex.Store({
    state: { //状態
      message: 'hello world',
      count: 0, //コンポーネント側からmutationsがcommitされると１増える
    },
    mutations: {
      increment (state) {
        state.count++
```

```~.vue
methods: {
  this.$store.commit('increment'); //mutationsで設定したメソッドを実行
}
```

## getters
配列の数を取得

```js
const store = new Vuex.Store({
    state: {
      message: 'hello world',
      count: 0,
      cartItems: ['肉', '魚', 'りんご', 'みかん']
    },
    mutations: { //同期的なコミットはコンポーネント側からされる
      increment (state, payload) {
        state.count += payload;
      }
    },
    getters: {
      cartItemsCount(state) {
        return state.cartItems.length;
      }
    },
```

```~.vue
computed: {
    cartItemsCount(){
        return this.$store.getters.cartItemsCount;
    }
}
```

## actions
mutationsを非同期でコミットする（サーバー通信等により値を変更）

```js

const store = new Vuex.Store({
    state: {
      message: 'hello world',
      count: 0,  //コンポーネント側からmutationsがcommitされると１増える
      cartItems: ['肉', '魚', 'りんご', 'みかん']
    },
    mutations: { //同期的なコミットはコンポーネント側からされる
      increment (state, payload) {
        state.count += payload;
      }
    },
    getters: {
      cartItemsCount(state) {
        return state.cartItems.length;
      }
    },
    actions: { //mutationsを非同期でコミットする（サーバー通信等により値を変更）
      increment (context, payload) {
        setTimeout(() => {
          context.commit('increment', payload);
        }, 1000)
      }
    }
  });
```

```~.vue
<script>
export default {
    // methods: { //mutationsを同期的にコミットする
    //     increment(){
    //         this.$store.commit('increment', 10);
    //     }
    // },
    methods: {
        increment(){
            this.$store.dispatch('increment', 10);
        }
    },
    computed: {
        cartItemsCount(){
            return this.$store.getters.cartItemsCount;
        }
    }
}
</script>
```

# Vuexヘルパー

```
mapState
mapMutations
mapGetters
mapActuons
```

# 参考
https://vuex.vuejs.org/ja/guide/
Notion使って、日々の支出を記録

#はじめに
Notionの使い方にも慣れてきたので、私の使い方を一つ紹介します。

##毎月の記録のつけ方

###テンプレートボタンを利用して、月のページを生成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/80b66d26-affb-54ed-250b-580e9214e6f6.png)

生成される一つのページには、以下のコンテンツがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/5beea4db-30aa-8420-ff3b-3752b45411ac.png)

中でも、Daily shoppingについて少し紹介します。

###日々の支出記録

毎月のページとは別で、家計簿の元となるページを一つ作成しています。
毎月のページには、そこから`create linked database`として表示させています。

データベースの内容かスマホからも入力しやすいように簡単にしています。
以下、参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/4e8ea5c6-42d2-ea03-c909-2fdc63be402c.png)

`create linked database`にしておくことで、月のページから入力することができます。
`Category`をselectにしておくと、入力が手軽にできます。
AWS_Cloudformationで環境構築してみた①

「CloudFormationは習うより慣れよ」ということで、環境構築にチャレンジ。
構成はシンプルに以下のようなものを作りたい。
![CloudFormation構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/d5d4fa97-4ed5-1752-2ee7-5f3f823c7af9.png)
CloudFormationのテンプレートは以下の3つに分けて作る。
①Networkレイヤ・・・VPC/Subnet/ルートテーブル/InternetGatewayなど
②Securityレイヤ・・・SecurityGroup、IAMなど
③Applicationレイヤ・・・EC2、RDSなど
***
今回は土台となるNetworkレイヤ(VPC/Subnet/ルートテーブル/InternetGateway)から作成する。
マネージメントコンソールから**[CloudFormation]**を選択し、**[スタックの作成]**をクリックする。
**[テンプレートファイルのアップロード]**を選んで、ymlをアップロードする。
![1.テンプレートの指定.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/39e2d1a9-0f8c-bcc5-f64f-9f2bc690610a.png)


アップロードするymlは以下。
なお、!Ref関数は同じyml内でしか参照できない点が注意。

```
AWSTemplateFormatVersion: 2010-09-09
Description: Create Network
Resources: 
#VPC作成
 VPC2:
   Type: AWS::EC2::VPC
   Properties:
     CidrBlock: 172.17.0.0/20
     EnableDnsSupport: true
     EnableDnsHostnames: true
     InstanceTenancy: "default"
     Tags:
       - Key: Name
         Value: VPC_fromCF

#インターネットゲートウェイ作成
 InternetGW2:
   Type: AWS::EC2::InternetGateway
   Properties:
     Tags:
       - Key: Name
         Value: IGW_fromCF

#インターネットゲートウェイをVPCにアタッチ        
 IGWAttachment:
   Type: AWS::EC2::VPCGatewayAttachment
   Properties:
     VpcId: !Ref VPC2
     InternetGatewayId: !Ref InternetGW2

#パブリックサブネットを定義
 PubSub:
  Type: AWS::EC2::Subnet
  Properties:
   VpcId: !Ref VPC2
   CidrBlock: 172.17.1.0/24
   AvailabilityZone: ap-northeast-1a
   Tags:
    - Key: Name
      Value: PublicSubnet_fromCF

#ルートテーブルを定義
 PubSubRoute:
  Type: AWS::EC2::RouteTable
  Properties :
   VpcId: !Ref VPC2
   Tags: 
     - Key: Name
       Value: RouteTablePublicFromCF 

#ルートテーブルとサブネットを関連付け
 PubSubRouteTableAssociation:
  Type: AWS::EC2::SubnetRouteTableAssociation
  Properties:
    RouteTableId: !Ref PubSubRoute
    SubnetId: !Ref PubSub

#ルートテーブル(IGW向け)
 PubSubToIGW:
  Type: AWS::EC2::Route
  Properties: 
   RouteTableId: !Ref PubSubRoute
   DestinationCidrBlock: 0.0.0.0/0
   GatewayId: !Ref InternetGW2
```

スタックの作成画面に出ていた**[デザイナーで表示]**という補助機能があるのだが、それがまじで神機能で
アップロードしたテンプレートがどんな構成になるかを絵で描いてくれる。
これでイメージと違うかもチェックできるし、構文が違うのも発見できる。
![1.5デザイナーの表示.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/c7196689-7ff9-a896-1ca7-4e850d8a97d9.png)

次にスタック名を決めて、あとのオプションは変更せずに次へと進んでスタックを作成する。
スタックとはCloudFormationで作成される塊みたいなもん。
![2.スタックの詳細.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/50462b4e-5da9-9187-a377-ab739af448ce.png)
作成後にイベントタブで更新連打をすれば、作成される過程が見れる。
とりあえず土台の作成は成功した。
![3.イベントログ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/d8cdc6ec-3e12-8ecf-d906-b9df3fa7196b.png)
次回は、セキュリティグループとEC2の作成をCloudFormationでやってみたいと思う。
Import関数やOutputパラメータが必要になる想定だ。

**つづく**
https://qiita.com/shinichi_yoshioka/items/b027f71a9998a87c46b8

***
この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com
ついこの間までbundle installできていたのに、ある日突然 gem ffi でエラーがでるようになったときにすること(@MacOS)

## はじめに

忘れてしまうので備忘録と解決策の共有になります。主にMac OSの方を想定してます。

## ざっくり診断

* OSの更新やXcodeのアップデートによってXcode(というよりコマンドラインツール？)がインストールできてないと発生すると思われる。
* ffiのバージョンによって発生すると思われる。

## 対応方法

### ・ Xcodeがインストールされてないとき

Xcodeをインストールする。

```
# インストール
# すでにインストールされている場合は、 xcode-select: error: command line tools are already installed, use "Software Update" to install updates が出力される。

xcode-select --install
```

**メモ**
このパターンに該当する場合は、エラーメッセージに`You have to install development tools first`みたいなメッセージが出てたと記憶。
ちなみに、利用規約に同意していない場合にも発生するので注意。

参考：
[【解決方法】Macで gem ffi の インストール (アップデート) に 失敗する](https://qiita.com/NaokiIshimura/items/f24091d31d4788295b12)

### ・ ffiのバージョンを変えてもいいとき(バージョン更新してもいいとき)

ffiのバージョンを更新する(一番手取り早い気がする)。

```
# ffiのバージョン更新
bundle update ffi
```

**メモ**
参考元の記事だとダウングレード〜と書かれているが最新のものにしても直ったのである特定のバージョンで発生すると思われる。

参考：
[ffi (1.9.21) instalation fails in linux](https://github.com/ffi/ffi/issues/611#issuecomment-364621532)

### ・ ffiのバージョンを変えたくないとき

オプションをつけて対応する。

```
# bundleのcondigに次のフラグをセット
bundle config --local build.ffi "--with-cflags=-Wno-implicit-function-declaration"

bundle install
```

**メモ**
参考元の記事を読むに、MacOSでC言語などのコードを暗黙的にbuildしようとするとエラーを出す、というのがデフォルト設定らしい。
このオプションをつけることで明示的になるからエラーが出なくなる(と思われる)。

参考：
[Native extension won’t compile on macOS 10.16/11.0 Big Sur beta](https://github.com/tmm1/rbtrace/issues/81)
ファイルマージのJava参考テンプレソース

指定のディレクトリ配下にあるファイルを取得し、
内容の単項目チェックを行って
ひとつのファイルにマージするだけのJavaです。

```java:sample.java

package practice;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/*
 * ファイルのマージを行う
 */
public class MergePractice {

	public static void main(String[] args) {

		long startTime = System.currentTimeMillis();

		File directory = new File("入力ファイルのディレクトリ");
                // 入力ファイル一覧取得
		File[] filesArray = directory.listFiles();

		List<File> filesList = new ArrayList<File>();

		if(filesArray == null) return;

		// ファイルサイズ0バイト以外のものを処理対象にする
		for(File file:filesArray) {
			if(file.isFile() && file.length() != 0L) {
				filesList.add(file);
			}
		}

		// マージファイル
		File mergeFile = new File("出力ファイル");

		Path path = Paths.get(mergeFile.getAbsolutePath());

		// マージファイルが既にある場合は削除
		if(Files.exists(path)){
			try {
				Files.delete(path);
			}catch(IOException ex){
				ex.printStackTrace();
			}
		}

		// 読込みと書込み
		for(File readfile :filesList) {
			System.out.println(readfile.getName());
			try(BufferedReader br = new BufferedReader(new FileReader(readfile))){
				// trueを指定することで追記モードにする
				try(BufferedWriter bw = new BufferedWriter(new FileWriter(mergeFile,true))) {
					String line;
					while((line = br.readLine()) != null) {
						if(checkLine(line)) {
							bw.write(line);
							bw.newLine();
						}else {
							System.out.println("エラー行がありました。:" + line);
							bw.close();
							return;
						}
					}
					bw.flush();
				}catch(IOException ex) {
					ex.printStackTrace();
				}
			}catch(IOException ex) {
				ex.printStackTrace();
			}
		}

        long endTime = System.currentTimeMillis();
        System.out.println("処理時間：" + (endTime - startTime) + " ms");

	}

        /*
         * ファイル内容の単項目チェックを行う
         */
	private static boolean checkLine(String line) {

		String[] strArray = line.split(",");

                // 以下は一例
		if(strArray.length != 2) {
			return false;
		}

		if(strArray[1].length() != 3) {
			return false;
		}

		return true;
	}
}

```