OmniAICreator/Qiita-1.07M huggingface dataset:
AndroidのボタンUIを角丸にしたい

画面デザイン資料をもらった時、ボタンUIが角丸で枠線が付いていた為、次のような対応を行った。

##### リソースのlayout
まずはlayoutファイルにButtonを配置。

```xml
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:textColor="#ffffffff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
```

##### リソースのdrawable
つぎにshapeを使ったdrawableファイルを作成。

```xml:button_style.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dip" />
    <solid android:color="#ff262626" />
    <stroke
        android:width="1dp"
        android:color="#ffffffff" />
</shape>
```

##### 作成したdrawableをlayoutに適用
Buttonのbackground属性に作成したdrawableを設定する。

```xml
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:textColor="#ffffffff"
        android:background="@drawable/button_style"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
```

##### イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/744890/a892e855-f775-8e37-bd08-c8d769c8cbea.png)
インクリメントとデクリメントについて

#インクリメントデクリメントとは?#

文字列"a"に対して　「a=a+1」
文字列"b"に対して　「b=b+1」

という記述を**++a**とか**b++**という風に短縮できる書き方と覚えましょう。

++aのように先に記号を記述するやり方を前置インクリメントといい

以下のような計算をします。


**① b=++a**

この場合だと先にaに1を加えてbに代入します。

**②b=a++**

この場合だとbにaを代入した後にaに1を加えます

なので、先に置くか後に置くかでそのあとのa,bの値が変動してしまうのです。

#文字列の連結#

文字列の連結をする際、型に注意して連結していかなければなりません、

例①　String,int型の連結

"FFA+J"+1+12

の場合""で囲まれている部分はString型、1,12がint型の確認

計算は左から行われていくためまず"FFA+J+1"+12

最後に"FFA+J+112"となります。

ご参考までに。
【GASメモ】自分のカレンダーの予定を取得する

記事が古いものばかりだったのと、すぐ思い出せるために。

```index.gs
function getSchedule() {
  const schedule = CalendarApp.getCalendarById('xxxxx@gmail.com')//各自メールアドレスを記入
  const startDate = new Date()
  //検索範囲を2週間にする
  const endDate = new Date(startDate.getTime() + 1209600000)
  var schedules = schedule.getEvents(startDate, endDate)
  for(const event of schedules){
    //イベントのタイトルを取得してみる
    console.log(event.getTitle())
  }
}
```

endDateに`startDate + 1209600000`と記述したのは、startDateよりタイムスタンプ下記計算式で求めてあります。

```
3600000(1時間)*24(時間)*14(日) = 1209600000
```
VBA 二次元配列の一次元（行数）を増減させる関数

VBAの二次元配列で、一次元目を変更させる関数を作りました。


    Function chgVarRows(vBuf As Variant, Optional cnt As Long = 1) As Variant
        
        vBuf = WorksheetFunction.Transpose(vBuf)
        ReDim Preserve vBuf(1 To UBound(vBuf, 1), 1 To UBound(vBuf, 2) + cnt)
        chgVarRows = WorksheetFunction.Transpose(vBuf)
        
    End Function
Eclipseでパッケージ構成を変更する

Eclipseでパッケージ構成を変更する方法について紹介していきます。


#「名前変更」を選択

変更したいパッケージ構成が「com.example.demo」だとしたら、「demo」を選択し、
「リファクタリング」>「名前変更」をクリックします。


![スクリーンショット 2021-04-10 13.33.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/c244a4ea-76d9-585d-71b8-b524cbeb9e45.png)


#パッケージ名の変更
下記の3点にチェックを入れ、「プレビュー」をクリックします。

- 「参照の更新」：変更対象のパッケージ構成を使った参照を新しいパッケージ構成に変更します。
- 「サブパッケージの名前変更」：該当のパッケージ以下のサブパッケージを変更します。
- 「コメント及びストリング内のテキスト出現箇所の更新」:Javadocのタグ、コメント内に登場する変更対象のパッケージ構成を変更します。


今回変更するパッケージ配下には「非Javaテキスト」は無いため、
「非Javaテキスト・ファイル内の完全修飾名の更新」のチェックは外しています。

![スクリーンショット 2021-04-10 13.37.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/24f4b9e0-8d1d-5ee8-7092-9d45a47f0b80.png)

#変更の継続

「継続」をクリック。
変更対処のパッケージの配下にmainクラスが含まれているとこの注意文がでてきます。

![スクリーンショット 2021-04-10 13.52.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/7d3ec360-c112-7399-e2b0-76b7bbfbd975.png)


#変更の実行
「OK」をクリック。　変更が実行されます。

![スクリーンショット 2021-04-10 13.52.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/cc63059d-f0ff-f5ad-41d2-65e016f4a27b.png)


これでパッケージ構成が変更されました。
アプリケーションを実行し動作確認を行うといいでしょう。


#追記 テストケースの「パッケージ構成」の変更

実行クラスのパッケージ構成の変更後、テストケースが実行できない場合があります。
その時は、同様の手順で、テストケースが格納されているパッケージも実行クラスと同じパッケージ構成に変更しましょう。


#「名前変更」を選択

変更したいパッケージ構成が「com.example.demo」だとしたら、「demo」を選択し、
「リファクタリング」>「名前変更」をクリックします。

![スクリーンショット 2021-04-10 14.01.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/1371782d-28a2-057b-1adf-61f660bf4f71.png)

#パッケージ名の変更
下記の3点にチェックを入れ、「プレビュー」をクリックします。

- 「参照の更新」
- 「サブパッケージの名前変更」
- 「コメント及びストリング内のテキスト出現箇所の更新」

![スクリーンショット 2021-04-10 13.37.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/04615d0d-d7e0-6ff5-6fcf-2ad8ee1fe53d.png)

#変更の継続
「継続」をクリック

変更した実行クラスのパッケージ構成と同名に変更しようとしているので、このような注意文が表示されます。


![スクリーンショット 2021-04-10 14.02.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/d533d3e8-766f-4a2b-3ce8-ecca7b2507cd.png)

#変更の実行
「OK」をクリック。　変更が実行されます。

![スクリーンショット 2021-04-10 14.02.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/2ad5e85a-e1b2-10f7-7094-a7db7dbcfb59.png)


この段階で、エラーが発生する場合があります。
今回変更する「com.example.demo」の1階層上のフォルダを右クリック。
「実行」>「実行の構成」でテストケースのパッケージ構成などが現在使用しているものと一致するか、
一致していない場合は、「テスト・ケース:」などを修正し、適用すると無事パッケージ構成の変更が実行できました。

*筆者の環境では、パッケージ構成の変更をする前に、テストケース名、テストメソッド名を変更し、実行の構成まで変更していなかったのが原因でエラーが発生しました。


テストケースを実行して、正常に実行されたら完了です。
PostgreSQLで列がないと言われたときの対処法

# Postgreで列がないと言われる
今までMySQLを使用しており、Postgreを触り始めて2日目のことです。
列がないとのエラーに悩まされます。
いや…あるんやけど…(T T)

![スクリーンショット 2021-04-10 142037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1044070/e2de210b-2656-c28d-656d-a6f692350a57.png)

![スクリーンショット 2021-04-10 142120.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1044070/1a513c29-43fc-93b7-a12a-f67d9e853b65.png)
※テーブルの中身は無視してくださいww

# 調べた事
エラーメッセージ的にidがダメっぽい。
MySQLでは`AUTO_INCREMENT`を使っていましたが、Postgreで初めて`serial型`を使用しました。
これが原因なのか？と思い自動連番の指定がおかしいかもと調べる。


#原因
エラーメッセージの通り、***「movieidはないけど、movieIDを参照したいっぽいよ」***ということでした。
Postgreは大文字小文字を区別しているので、そんな列ないよっということでした。

そして、movieIDで判断してほしいなら、””を付ければOK！

![スクリーンショット 2021-04-10 143240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1044070/22d27936-1fca-a574-fca2-1ae3635f53b0.png)

解決！

#参考
この記事を読んだら一発で解決でした笑
ありがとうございます。
https://buralog.jp/postgresql-relation-does-not-exist-error/
REALSENSE のUnity サンプルプログラム起動

## はじめに
intel REALSENSE D455を買ったので、サンプルプログラムを動かしてみる
本家のReadmeを読めば書いてあるが、自分への備忘録として

本家のReadme

https://github.com/IntelRealSense/librealsense/tree/master/wrappers/unity


## 動作確認環境
Windows10 64bit
Unity 2020.3.2f1

## 設定手順

### CMakeのインストール

ビルドするために、CMakeが必要なので、インストール

導入方法

https://qiita.com/East_san/items/aff4f7907aedabe6da47

### SDKのインストール

使用しているPCにあったSDKをインストールする

https://github.com/IntelRealSense/librealsense/releases

2021/4/10に 2.44.0.3056 で確認した

### librealsenseのライブラリ取得


https://github.com/IntelRealSense/librealsense

ここからクローンしてくる


### ビルド

クローンした、librealsense配下でコマンドプロンプトで下記コマンドを実行

```
mkdir build
cd build
cmake .. -DBUILD_CSHARP_BINDINGS=ON -DBUILD_UNITY_BINDINGS=ON -DBUILD_SHARED_LIBS=ON \
-DDOTNET_VERSION_LIBRARY=3.5 -DCMAKE_GENERATOR_PLATFORM=x64 \
-DUNITY_PATH=<path_to_unityeditor>/Unity.exe
```

##### ビルド時にkernel32.libがないエラーが発生したとき

下記を参考にkernel32.lib をインストール
https://blog.janjan.net/2020/10/05/build-error-can-not-open-kernel32-lib/


### ライブラリのコピー

Pluginsフォルダーを作成して、そこにlibファイルをコピーする

コピー先
```librealsense\build\wrappers\unity\Assets\RealSenseSDK2.0\Plugins
```

コピー元
```C:\Program Files (x86)\Intel RealSense SDK 2.0\bin\x64
```

コピーするファイル
Intel.Realsense.dll
realsense2.dll

### サンプルプログラムの起動

下記にあるサンプルプログラムを起動する
``` librealsense\build\wrappers\unity\Assets\RealSenseSDK2.0\Scenes\StartHere.unity ```

ちゃんと、build配下のサンプルプログラムを実行すること
(2021/4/10 時点だと、これでうまく動作しました)


## めちゃくちゃ参考になったサイト

https://www.intel.co.jp/content/www/jp/ja/support/articles/000027039/emerging-technologies/intel-realsense-technology.html

https://www.autumn-color.com/archives/1837
Base64 変換

Base64 変換についてまとめてみました。

Python3 の例

```py:encode01.py
#! /usr/bin/python
#
import base64
#
data_in = 'こんにちは'
bytes_in = data_in.encode()
#
encoded = base64.b64encode(bytes_in)
print(encoded)
```

```py:decode01.py
#! /usr/bin/python
#
import base64
#
data = b'44GT44KT44Gr44Gh44Gv'
decoded = base64.b64decode(data)
str_out = decoded.decode()
print(str_out)
#
```

Node.js の例

```js:encode01.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	encode01.js
//
//					Apr/10/2021
//
// ---------------------------------------------------------------
'use strict'

// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const data_in = 'こんにちは'
const buffer = new Buffer.from(data_in)
const string = buffer.toString('base64')
console.log(string)

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

```js:decode01.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	decode01.js
//
//					Apr/10/2021
//
// ---------------------------------------------------------------
'use strict'

// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const data_in = '44GT44KT44Gr44Gh44Gv'

const string = Buffer.from(data_in,'base64')
console.log(string.toString())

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

Go の例

```go:encode01.go
package main

import (
	b64 "encoding/base64"
	"fmt"
	"os"
)

func main() {
	fmt.Fprintf (os.Stderr,"*** 開始 ***\n")
	data := "こんにちは"

	sEnc := b64.StdEncoding.EncodeToString([]byte(data))
	fmt.Println(sEnc)
	fmt.Fprintf (os.Stderr,"*** 終了 ***\n")
}
```

```go:decode01.go
package main

import (
	b64 "encoding/base64"
	"fmt"
	"os"
)

func main() {
	fmt.Fprintf (os.Stderr,"*** 開始 ***\n")
	data_in := "44GT44KT44Gr44Gh44Gv"
	uDec, _ := b64.URLEncoding.DecodeString(data_in)
	fmt.Println(string(uDec))
	fmt.Fprintf (os.Stderr,"*** 終了 ***\n")
}
```

コマンドでの変換

エンコード

>入力データ

>```text:a01.txt
こんにちは
```

>実行結果

>```text
$ base64 a01.txt
44GT44KT44Gr44Gh44Gv
```

デコード

>入力データ

>```text:b01.txt
44GT44KT44Gr44Gh44Gv
```

>実行結果

>```text
$ base64 -d b01.txt
こんにちは
```
【アジャイル開発】スクラムとは？スクラムチームの役割は？

## はじめに
業務でアジャイル開発を行っている。アジャイルとは、特にこことでは説明しないが、興味のある人はググって欲しい。アジャイル開発の手法の中の1つ、```スクラム```に関して、この記事では簡単にまとめていきたい。

## スクラムとは
スクラムとは、アジャイル開発の1つの手法だ。
スクラムのルールは[スクラムガイド](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)で定義されている。このスクラムガイドは、１〜２年に定義されているらしい。スクラムには``５つのイベント``と``3つのロール``と``3つの作成物``がセットで構成されている。ただ、これらはあくまで基本的なルールに過ぎないので、スクラムチームの性質によって自分たちでやり方を変えていく必要があることを忘れてはいけない。コードの書き方や、テストのやり方などはチームの状況を踏まえた取り組む必要がある。スクラムとは、フレームワークと表現されることもある。![feedback-2990424_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628093/70d73c7c-a5a7-bd5a-8a28-2b222ffc94e5.jpeg)

## 3つのロール(役割)
上記でも述べたように、スクラムには3つのロールが存在する。
<dl>
  <dt>１.プロダクトオーナー</dt>
  <dd> POと表現されることがおおい。プロダクトオーナーは１プロジェクトにつき、１人存在する。開発チームを活用して、そのプロダクトが生み出す価値を最大限に発揮するにはどうすれべきかを常に考え続けなければならない。</dd>
  <dt>２.開発チーム</dt>
  <dd>開発チームが必要。スクラムでは、開発チームの人数は多くても10人以内におさめたい。3人から10人が理想的と言われている。開発チームはプロダクトを作るために必要な作業全てができなければならない。設計、コードを書くこと、サーバー構築、テスト。ドキュメントを書くなど、すべての能力は必要だ。</dd>
  <dt>３.スクラムマスター</dt>
  <dd>スクラムというフレームワークを円滑に回して、プロダクトをうまく作れるようにプロダクトオーナーや開発チームを支えるのがスクラムマスターの役目。スクラムマスターは、スクラムを行う上でのルールや作成物、進め方などをPOや開発チームに理解をさせること、外部の人間からの妨害や割り込みからPOや開発チームを守ることが大きな役目となる。自分のイメージだと、なんでも屋さんのイメージがある。</dd>
</dl>
![team-4423339_640.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628093/e7c79dcf-98a2-843b-4392-388020eebc53.png)



## いまの自分の役割
自分は今プロジェクトでスクラムマスターという役割にいる。スクラムマスターはこのアジャイル開発のスクラムという手法でプロジェクトを成功させるために、ありとあらゆることを行わないといけない。とてもやりがいのあるポジションで、最高の楽しい。その分、プレッシャーを感じることもある。

### スクラムマスターとして重要なこと
POも開発チームもプロジェクトが進行していくと、なにが本当に最優先事項なのかを見失いがち。この最優先事項を常に気にすることがスクラムマスターの大きな役割だと感じている。この最優先事項に着手し、解決するためには開発チームが仕事を進めるうえで妨げになっているものを排除する必要がある。それは、技術的なことかもしれないし、スケジュールの問題かもしれない。もしかすると、外部からのなにかが関係しているのかもしれない。それにいち早く気がつき、解決をしていくのがスクラムマスターだ。
Freenomでドメイン取得しようとして利用不可になる場合の対応

## 困ったこと
ドメイン名に何を入力しても利用不可になるので、ドメインを取得できない。
![スクリーンショット 2021-04-10 14.18.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1301545/cb7e9aec-e8cb-b762-05f4-c1e7382a5e59.png)

## 対応
 トップレベルドメイン（「.tk」「.ml」など）まで指定すると利用可能となる。
![スクリーンショット 2021-04-10 14.19.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1301545/28183c82-ddc8-fcda-ae77-fd0d2fda99cc.png)
勿論、既に使われているドメインは利用不可である。

[Freenom](https://www.freenom.com/ja/index.html)
Qiitaの下書き記事をスマホから投稿する手順書

#前提
Qiitaにおいて、2021年4月現在、**PC**から下書き保存した記事を、スマホから投稿しようと思うと、スマホの画面上では投稿ボタンの「Qiitaに投稿」は表示されません。

#本記事の概要
Qiitaで、PCで下書き保存した記事を、スマホから投稿する方法について共有します。

#実行手順
1. PCで記事を下書き保存する
2. スマホから、1のページにいく
3. スマホから、新規でタブを開き"https://qiita.com/drafts/new" にアクセスする
4. スマホから、１の内容をコピーし、3に貼り付ける
5. スマホから、投稿ボタンを押す

##手順3を行うと、スマホ画面に「Qiitaに投稿」が出現
PCで下書き保存した記事を、スマホから閲覧してもスマホ画面に「Qiitaに投稿」は表示されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/f3a84ebb-3566-d1b7-36af-e21883240a4f.png)


以上です。
自分のサイトに入力された情報をLINEに通知する方法



自分のサイトに入力フォームを設置し，ユーザーによって入力された値を使ってサーバーで何かしらの計算を行えるようにしたとき，ユーザーが使ったタイミングで通知が欲しい時があります．

今回は，WordPressで作られたサイトに入力された値を使ってPythonで計算したときにLINEに通知を入れる方法を書きます．

#環境
サイト：WordPress
サーバー：mixhost
サーバーから通知：Python，LINE Notifyを使用

システム構成のイメージはこんな感じです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1298289/211700fe-2798-604a-292c-d83a9a5c7227.png)


#WordPressに入力フォームを設置して計算ツールを作る

WordPress上に入力フォームを設置
→サーバーでPython計算
→サイトに計算結果を表示
までの流れは，以下の記事を参考にしました．

ブログ（WordPress）のフォームの入力値を使用してPythonで計算しブログにグラフを表示

https://atsblog.org/wordpresspython_matome/

同じ環境なら，同じようにできると思います．

#計算が行われたら通知をLINEに送る

基本的には，LINE NotifyというサービスをPythonで使って通知を送るだけです．

#トークンを取得（LINE Notify）
「LINE Notify Python」などで検索すればたくさんやり方が出てきます．
例：https://qiita.com/ken_yoshi/items/7879b3117d298a143101

（というか，この例のリンク記事だけで完結できるかもしれません）

#通知を送るソースコードをPythonに書く

以下のコードをサーバーに用意すればOKです．

**line_notify_bot.py** (実行するPythonファイルと同じディレクトリに置く)

```python
import requests

class LINENotifyBot:
    API_URL = 'https://notify-api.line.me/api/notify'
    def __init__(self, access_token):
        self.__headers = {'Authorization': 'Bearer ' + access_token}

    def send(
            self, message,
            image=None, sticker_package_id=None, sticker_id=None,
            ):
        payload = {
            'message': message,
            'stickerPackageId': sticker_package_id,
            'stickerId': sticker_id,
            }
        files = {}
        if image != None:
            files = {'imageFile': open(image, 'rb')}
        r = requests.post(
            LINENotifyBot.API_URL,
            headers=self.__headers,
            data=payload,
            files=files,
            )
```

※requestsはpipでインストールしておいてください．

**実行するPythonファイル**

```python
#何かしらの計算がここに書かれている

#以下，LINE Notifyによる通知
from line_notify_bot import LINENotifyBot
bot = LINENotifyBot(access_token='取得したトークン')

bot.send(
    message='サイト上でツールが使用されました',
    #image='test.png',  # png or jpg
    sticker_package_id=11537,
    sticker_id=52002759,
    )
```

「取得したトークン」のところに先ほど取得したトークンをコピペしてください．

これで，サイト上で入力された値を使用してに計算が行われたとき，LINEに「サイト上でツールが使用されました」という通知がきます．

ちなみに，sticker_package_id，sticker_idのところは通知のときにスタンプを送ります．どのスタンプにするかは以下を参照．
https://developers.line.biz/en/docs/messaging-api/sticker-list/

**messageに値を代入すればサイトに入力された値や計算結果をLINEに送ることができます．**
また，画像を送ったりもできるようです．色々工夫すると面白いと思います．

#結果
自分のサイト上のフォームに値を入力すると，こんな感じで通知が来ました．

![20210410_135717.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1298289/8b5f7395-5873-63de-7012-0aac019862f3.jpeg)

ちなみにですが，私が実行したサイト上のツールは以下です．米国株ポートフォリオを分析するために作りました．

https://optrip.xyz/?page_id=2
InvocableMethodについて

Process Builderはどうも好きになれないので、わざわざProcess Builderで使うためにApexクラスでInvocableMethodを使おうとは思っていませんでした（ああ、今もあんまり思ってないかも）

しかし、何であるんだろうって考えると不思議で調べてみました。


トリガーは優れており、Salesforceのレコードに発生するほとんどすべてのことに反応することができます。

ただし、トリガーについてそれほど優れていないことがいくつかあります。主な2つは次のとおりです。

1.トリガーが実行される順序を制御することはできません。

2.トリガーを無効にするには、変更セットを作成し、テストを更新して展開する必要があります。

これらの両方は、トリガーを使用する代わりに、Process Builderと@InvocableMethodアノテーションの機能を活用して、呼び出し可能なアクションを作成することで克服できます。

確かに、実行順序が担保されないので、複雑なロジックだと悩みます。確かに消すときも面倒だ。

このために、あるんだ.... ちょっと納得。

じゃあ、全部　Process Builderと@InvocableMethodでいいかというとそうでもないみたい。


Process Builderを使用して達成できないビジネスユースケースがいくつかあります。例えば

1.アウトバウンドメッセージをサポートしていません
2.複数のレコードの作成をサポートしていません
3.レコードを削除できません


一長一短があるなぁ。でもやっぱりApexトリガーに軍配を上げるな。



https://www.desynit.com/dev-zone/salesforce-development/replacing-apex-triggers-processes-invocable-actions/

https://www.forcetalks.com/salesforce-topic/what-is-the-use-of-invocablemethod-in-salesforce/
知っていると役に立つ！Web系エンジニア向けサービス 11選


春なので、新人エンジニアに向けて役に立ちそうなWebサービスを紹介します。

# ⭐️ Webサービス編

## Quarkly(デザインツール)

`Quarkly`はWeb開発者とWebデザイナーの両方のために作成された**無料**のツールです。GUI上で直感的にデザインを作成できるため、デザインが苦手な方でも簡単に使うことができます。さらに作成したデザインは[React](https://reactjs.org/)に基づいた形で[Netlify](https://www.netlify.com/)に公開ができるようになっています。

https://quarkly.io/

## Undesign(デザインリソース)

`Undesign`はデザインリソースを探すとき、カテゴリ別にまとめられているため、Google検索で時間をかけて探す手間を省略できます。

https://undesign.learn.uno/

## Miro(ホワイトボード)

リモートワークが浸透してきた今の世の中でホワイトボードのサービスは必須でないでしょうか。`Miro`はぬるぬる描画ができるので描いていて気持ちいいです。

https://miro.com/

## Draw.io(作図ツール)

`Draw.io`はシステム構成図やフローチャート、シーケンス図などドキュメント作成が捗るツールです。

https://www.draw.io/

## Codesandbox(統合開発環境)

`Codesandbox`はWebブラウザ上の統合開発環境(IDE)です。私はCodesandbox上でがっつりとした開発はしたことないですが、サクッとコードを書いてみて、共有したいときに使ったりします。

https://codesandbox.io/

似たサービスに`Glitch`があります。

https://glitch.com/

ライトにコードを記述するなら`Codepen`もおすすめです。

https://codepen.io/

## Devdocs(ハンドブック)

`Devdocs`は、さまざまWebテクノロジーのハンドブックです。数が多いのでほとんどの技術を網羅しているのではないでしょうか。

https://devdocs.io/

似たサービスに`Devhints`があります。

- Devhints

https://devhints.io/

## Codic(ネーミング辞書)

変数名や関数名を考えるのが苦手な人は多いですよね。そんな人に`Codic`がおすすめです。

https://codic.jp/

## Can i use

Webテクノロジーの互換性を表示してくれるサービスです。

https://caniuse.com/

## Webcode.tools(Webコードジェネレーター)

簡単なHTML/CSSのコードをプレビューを見ながら生成できます。近年はスクラッチで開発することも少ないですが、ちょっとした開発のおともに。

https://webcode.tools/

## Placehold.jp(ダミー画像)

ダミー画像を作成してくれるサービスです。

https://placehold.jp/

## Slidesgo(Googleスライドのテンプレート集)

春は自己紹介をする機会も多いですよね。そんなときはこちらから Cool はテンプレートを見つけてみてください。

https://slidesgo.com/

# さいごに

本当はクライアントアプリ編も同時に記事にするつもりでしたが、Webサービスを書いているだけでまぁまぁな量になってきたため、次回、クライアントアプリ編を記事にします。
[SwiftUI] $hoge.fugaは$(hoge.fuga)ではない

細かいことですが、SwiftUIなどで時折書く`$hoge.fuga`という式は`$(hoge.fuga)`ではないのだ、という話をします。

# 例
まずは記述例を挙げます。

```Swift
struct Hoge {
    var fuga: String = ""
}

struct MyContentView: View {
    @State private var hoge = Hoge()

    var body: some View {
        TextField("入力してね", text: $hoge.fuga)
            .textFieldStyle(RoundedBorderTextFieldStyle())
    }
}
```
非常にシンプルです。

では、次のように書いてみましょう。エラーが出ます。

```Swift
//Error: '$' is not an identifier; use backticks to escape it
TextField("入力してね", text: $(hoge.fuga)) 
```
それからこれもダメです。

```Swift
//Error: Referencing subscript 'subscript(dynamicMember:)' requires wrapper 'Binding<Hoge>'
//Error: Value of type 'Hoge' has no dynamic member '$fuga' using key path from root type 'Hoge'
TextField("入力してね", text: hoge.$fuga)
```

これでひとまず`$hoge.fuga`が`$(hoge.fuga)`でないことはおわかりいただけたと思います。しかしでは`$hoge.fuga`とはなんなのでしょう。

# 正体
そもそも`$`を用いたアクセスは`propertyWrapper`の機能によるものです。`State<T>`の`projectedValue`は`Binding<T>`となっています。ですから`$hoge`とは`Binding<Hoge>`の値です。

しかし、そうすると`Binding<Hoge>`にプロパティ`fuga`が存在するのが不思議に思えるはずです。これを実現しているのが`dynamicMemberLookup`です。Swift5.1以降で`KeyPath`を使ったLookupができるようになったため、おそらく`Binding`が次のように定義されています。

```Swift
@dynamicMemberLookup
struct Binding<T> {
    subscript<U>(dynamicMember keyPath: WritableKeyPath<T, U>) -> Binding<U> {
        //処理
    }
}
```

これだけでは少しわかりにくいので、もっと単純なサンプルを見てみましょう。

```Swift
@dynamicMemberLookup
private struct Wrapper<T> {
    init(wrappedValue: T) {
        self.wrappedValue = wrappedValue
    }

    private var wrappedValue: T

    subscript<U>(dynamicMember keyPath: WritableKeyPath<T, U>) -> Wrapper<U> {
        get {
            return Wrapper<U>(wrappedValue: wrappedValue[keyPath: keyPath])
        }
    }
}
```
こうすると、`value`は`Wrapper`型の値であるにもかかわらず、`String`が持っていたはずのプロパティにアクセスできるようになっています。もちろん定義した通り`Wrapped<Int>`の値です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638786/9fe10c42-a4a8-64e3-ae84-ac93220be763.png" width="500px">

以上で`$hoge.fuga`の正体は説明がつきます。`$hoge`が`State`という`propertyWrapper`の`projectedValue`であり、その値は`Binding<Hoge>`型です。`Binding<Hoge>`型は`dynamicMemberLookup`をサポートしており、これを通して`hoge`のプロパティである`fuga`を`Binding<String>`に変換して返すのです。

# 補足
以上だけだとひょっとすると`$hoge[0]`のような記法が可能なことが奇妙に思えるかもしれません。実際以下は全く正しく動きます。

```Swift
struct MyContentView: View {
    @State private var hoge = ["A", "B", "C"]

    var body: some View {
        TextField("入力してね", text: $hoge[0])
            .textFieldStyle(RoundedBorderTextFieldStyle())
    }
}
```
実はこれも`dynamicMemberLookup`で実現されています。びっくりするほど気持ち悪いですが、`subscript`への`KeyPath`というものが存在するおかげです。

```Swift
let keyPath: WritableKeyPath<[Int], Int> = \.[0]
```
以上でだいたい網羅できたのではないかと思います。
# 参考
https://developer.apple.com/documentation/swiftui/binding/subscript(dynamicmember:)
【Python】【nltk】バーティカルバーを用いたFreqDistのマージは、組み込み演算子とは挙動が異なる件について

#### 前置き
[Natural Language Processing with Pythonの1章](http://www.nltk.org/book/ch01.html)を見ていると、以下のような機能説明が。

```python:
# Functions Defined for NLTK's Frequency Distributions
fdist1 |= fdist2  # update fdist1 with counts from fdist2
```

fdist1とfdist2はFreqDistクラスのインスタンスです。FreqDistクラスは単語の頻度分布、つまりFrequency Distributionを取り扱うための色々便利な機能が揃っています。

一方でこの記号"|="、これはPython3.9で登場したマージ演算子による累積代入と同じ書き方です。この書き方だと、存在しないキーについては単純な追加。キーが重複しているときは、fdist1側の要素をfdist2側の要素が一律に上書きするようになっています。(参考: [Pythonで辞書に要素を追加、辞書同士を連結（結合）](https://note.nkmk.me/python-dict-add-update/)

```python:
sample_dict1 = {"k1": 1000, "k2": 2000, "k5": 5}
sample_dict2 = {"k2": 200, "k3": 300, "k4": 400}

sample_dict1 |= sample_dict2
print(sample_dict1)
```

```:出力
{'k1': 1000, 'k2': 200, 'k5': 5, 'k3': 300, 'k4': 400}
```

私はこの記号を見て、「あぁFreqDistもマージ演算の累積代入が可能なんだな」と確かめもせずに思っていましたが、実際は全く同じというわけではありませんでした。

### FreqDistの挙動
結論から言いますと、「キーが存在しない場合は単純な追加」という点は同じですが、キーが重複していた場合は必ずしも上書きされるわけではなく、「**要素数が多い方が優先される**」というのが正しい理解になります。

ここではサンプルプログラムとして、上の書籍のChapter1: Language Processing and PythonのSection3.4: Counting Other Thingsで使われていた単語の長さを確認するプログラムを少しいじって利用します。サンプルの文字列を空白ごとに分割し、文字数をカウントしてから辞書に割り当てる、といった流れですね。

```python:
from nltk.tokenize import word_tokenize
from nltk.probability import FreqDist


sample_text1 = "a a a aa aaa aaaa"
fdist1 = FreqDist()
for word in word_tokenize(sample_text1):
    fdist1["length" + str(len(word.lower()))] += 1

print(fdist1.tabulate())

sample_text2 = "a aa aa aaaa aaaa aaaaa"
fdist2 = FreqDist()
for word in word_tokenize(sample_text2):
    fdist2["length" + str(len(word.lower()))] += 1

print(fdist2.tabulate())

print("------------after------------------")
fdist1 |= fdist2
print(fdist1.tabulate())
print(fdist2.tabulate())
```

こちらの出力は以下のようになります。

```:出力
length1 length2 length3 length4 
      3       1       1       1 
None
length2 length4 length1 length5 
      2       2       1       1 
None
------------after------------------
length1 length2 length4 length3 length5 
      3       2       2       1       1 
None
length2 length4 length1 length5 
      2       2       1       1 
None
```

まずはlength5に注目しましょう。
1つ目のサンプルにはlength5,つまり"aaaaa"が存在していません。よって、afterの方では単純にlength5: 1の組み合わせで追加されています。

次はlength2に注目しましょう。
1つ目のサンプルにはlength2,つまりaaが1個存在しています。テキストの"aa"由来ですね。しかし2つ目のテキストにも"aa aa"、つまりlength2: 2の組み合わせがあったので、そちらでlength2が上書きされています。

とまぁここまでは従来のマージ演算と同じだと言っても問題はありません。length2に対する上書きは単純に右側にあったが故、と考えても成立するからです。

問題はlength1、こちらに注目してください。
1つ目のサンプルではlength1: 3となっています。テキストに"a a a"が含まれているからですね。一方で2つ目のサンプルの方でもlength1: 1があります。テキストに"a"がありますので。
しかし、結果を見てみると、length1: 3はそのままで**上書きされていません**。これが一律上書きをする組み込み演算子による辞書マージとの違いです。値が大きいためそちらが優先された、と考えると一応挙動に説明はつきます。

### まとめ
ここまでで"|="の挙動をまとめると、

1.)左側にキーが無い時は右側からそのまま追加
2.)キーが重複している場合は要素数が多いほうが優先される。つまり、左側のほうが大きかった場合は上書きが起きない。

ということなると思います。FreqDistクラスが辞書と同じ挙動をしている、という考え方がそもそもの間違いの原因である気もします。どちらかというと集合で使われる和集合の演算の方が近いような……でもFreqDistの和集合というのにもどうにも違和感が……的確な説明が出来る方がいたら、ぜひ教えてもらいたいところです。

いずれにせよ、変なハマり方をする前に気づけてよかったです。集合知に感謝。
No template for interactive requestの対処事例（ルーティングの基本大事）


基本がわかっていないことが発覚することなので書きます。
MVCを理解しておりませんでした。

■エラー内容
--
![20210410-124131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/14263523-b6a4-749d-8f0f-abc04834b7fc.png)


テンプレートなしというエラーでした。

`それまでに行ってきたこと`
・[gem]devise導入
　　　　　　/bundle install/rails g devise install/rails g devise users/
　　　　　　/terminalでrails server実行/rails g devise views/
　　　　　　/rails db:migrate実行
・application.controller.rb
　　　　　　/before_action :configure_permitted_parameters...記述
　　　　　　/devise_parameter_sanitizerメソッド記述
・ログインview画面作成
　　　　　　/devises/registrationsフォルダにて⇨登録成功
・indexファイル作成
　　　　　　/itemsフォルダ
・item_contorller作成


さてindexファイルもできたことだしサイトを表示させてみようと
terminalでルーティングを行いました

![20210410-130217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/49315b59-20dc-d52e-468c-0a4b1369a21d.png)


すると「users#index」とありました。
さっき設定したのはitemsフォルダのなか？？？

ここで気づいていればよかったのですが、
基本：自分が設定したものをルーティングは表示してれくれているだけなんです。
--

```ruby:config/root.rb
Rails.application.routes.draw do
  devise_for :users
  root "items#index"
  resources :users  
end
```

resouses :usersと自分が書いたので
users#index
users#create
users#new
users#edit
users#show
users#update
users#destroy
の７つができていただけなんです。

```ruby:config/root.rb
Rails.application.routes.draw do
  devise_for :users
  root "items#index"
end
```


にするとエラーもでずlocalhost3000がきちんと表示されました。

※ちなみに以下のルートは
![20210410-130943.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/39188b21-e882-870c-8d7c-fbbb1491991d.png)


```ruby:config/root.rb
Rails.application.routes.draw do
  devise_for :users
#  root "items#index"
#  resources :users  
end
```

deviseインストール時に自動追記された「devise_for :users」によるルーティングです。
参考までに
組み込みエンジニアのための壊さない基板取り扱い方

## はじめに

春からエンジニアとして働き始める人も多いことでしょう。特に、組み込み分野は基板やデバイスに触れる機会が多くあります。ちょっとした基板からFPGAが複数のるような高価なものまで色々ありますが、どんなものでも壊すとちょっと落ち込みます。そこで、基板を壊さないように気をつけることをまとめました。

## 基板を持つとき

### 部品が実装してある面を持たない

部品が実装してある面に触れると静電気で部品を壊すおそれがあります。端面など、部品に触れないように持ちましょう。

### 手渡ししない

渡す方、渡される方のいずれかが帯電していると、静電気で破壊につながるおそれがあります。机において渡すようにしましょう。

### 落とさない、ぶつけない

衝撃を与えると部品がとれたり、半田にクラックが入ったりすることがあります。一見、異常がないように見えても進行性のあるヒビが入っていることもあります。また、基板がなにかに触れたとき、静電気が発生して破壊に至る恐れもあります。

## 基板を置くとき

### 導電性の机に直置きしない

基板が帯電していた場合、抵抗の低い机との間で静電気が発生するおそれがあります。また、そのまま電源をいれると部品間でショートして破壊につながるおそれがあります。脚付きでない場合、静電マットの上に置くようにしましょう。

### 力をかけない・曲げない

立て掛けたり上から押したりすると基板が変形し、半田クラックが発生するおそれがあります。安定した場所で他のものに当たらないように置きましょう。

### 上にものを乗せない

部品にダメージを与えたり、部品同士がものを介してショートするおそれがあります。

## 電源投入時

### PW(+)とGND(-)を間違えない

壊れます。電池、電源の挿し口、コネクタの挿し口など、向きやリード線の色をよく見て正しく接続しましょう。

### PW(+)とGND(-)をショートさせない

基板から出るリード線をクリップで挟んで電源を供給する場合など、クリップ同士やクリップと基板が接触してショートすることがあります。挟んでいる部分を被覆したり、袋やテープで包んだりしてショートさせないようにしましょう。

### 定格外の電圧をかけない

壊れます。安定化電源で電圧を調整するときも、つまみを早く回すと急激に電圧が変化するので気をつけましょう。念の為、電源の出力の電圧をテスタで測ってから接続すると良いでしょう。

## 動作中

### ケーブルやフレキを抜き挿ししない

挿抜時にピン同士がショートしたり、過電圧が発生したりして破壊につながります。電源を切ってから挿抜しましょう。

### 部品に触らない

電源を切っているときも同様ですが、動作中も部品に触らないようにしましょう。静電気以外にも電圧変動など破壊につながる現象が発生する恐れがあります。

## その他

### テープを勢いよく剥がさない

部品やリード線を固定するためにテープを貼ることがあります。このテープを貼ったり剥がしたりするとき、静電気が発生します。勢いよく剥がすと数kV～数十kVもの静電気が発生し部品を破壊します。どうしても剥がす場合はゆっくり慎重に剥がしましょう。

## さいごに

以上よりわかるとおり、電子部品が壊れる要因として多いものは

- 静電気
- ショート（過電流）
- 変形・衝撃

です。これらに気をつけて快適なエンジニアライフをお過ごしください。
Laravel MIMEのimage/jpegの配列が変化しているので注意する

# 目的

- Laravelの内部ファイルの仕様が一部変更になっていたので注意喚起のための自分メモとして残す

# 詳細

- `アプリ名ディレクトリ/vendor/symfony/mime/MimeTypes.php`の`'image/jpeg' => ['jpeg', 'jpg', 'jpe'],`が`'image/jpeg' => ['jpg', 'jpeg', 'jpe'],`に変更になった。
- コミットへのリンク
    - [https://github.com/symfony/symfony/pull/38407/files](https://github.com/symfony/symfony/pull/38407/files)
emptyの表記方法

どこで調べたかは忘れたけど
empty?にはこういう表記方法もあるようだ

```ruby
<% if @items.empty?.! %>
      <% @items.each do |item| %>
      <li class='list'>
        <%= link_to item_path(item.id) do %>
        <div class='item-img-content'>
          <%= image_tag item.image, class: "item-img" %>
```
emptyは文字列が空の時、真を返すが
emptyの後ろに.!をつけると反対の意味になるようだ
【学習メモ】AWSで使えるリンクローカルアドレス

メモ。

|アドレス|用途|リファレンス|
|:--:|:--:|:--:|
|169.254.169.123|時刻取得|[Linuxインスタンスの時刻の設定](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/set-time.html)|
|169.254.169.253|名前解決|[VPC での DNS の使用](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-dns.html)|
|169.254.169.254|メタデータの取得|[インスタンスメタデータの取得](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html)|
【Rails】fail to bundle install puma 4.3.5 ~~ でbundle installが落ちた話

`bundle install`でpumaのインストールに失敗して若干ハマったのでメモ

### 経緯と結果
`bundle install` 時に以下のエラーが発生

```
fail to bundle install puma 4.3.5 or gem puma with ruby-2.6.6 on macos-10.15.6 [duplicate]
```


↓のコマンドを実行後にbundle installしたらうまくいきました

```
$ bundle config build.puma --with-cflags="-Wno-error=implicit-function-declaration"
```

原因とか良く分からんから少しもやもや・・😇

詳しい人いたら教えてください〜


### 参考記事

https://stackoverflow.com/questions/63187613/fail-to-bundle-install-puma-4-3-5-or-gem-puma-with-ruby-2-6-6-on-macos-10-15-6/63201544#63201544
連想配列のkeyに意味を持たせないで

# 問題となるコード
一つの商品棚に対して一種類の商品を乗せるという要件を考えます。

そして、以下のようなテストデータを考えます。

```php
$products = [
  1 => ['name' => 'pen',   'price' => 10],
  2 => ['name' => 'note',  'price' => 100],
  3 => ['name' => 'apple', 'price' => 300],
];
```

これを用いてfactoryでDBにテストデータを挿入します。

```php
foreach ($products as $key => $product)
{
  factory(Shelf::class, $key)
  ->create()
  ->each(function (Shelf $shelf) use ($product))
  {
    $shelf->update([
      'product_name' => $product['name'],
      'product_price' => $product['price']
    ])
  }
}
```

これは、テストデータの$productsの要素それぞれに対して、その連想配列のkeyの数だけ商品棚テーブルにレコードを挿入しています。
つまり、商品棚テーブルは以下のような状態になります。

| id | product_name | product_price |
| --- | --- | --- |
| 1 | 'pen' | 10 |
| 2 | 'note' | 100 |
| 3 | 'note' | 100 |
| 4 | 'apple' | 300 |
| 5 | 'apple' | 300 |
| 6 | 'apple' | 300 |

# 何が問題か
上記のようなコードを見た際、`$products`という連想配列のそれぞれの要素に対し、keyの数だけテストデータが挿入されるというのが直感的に分かりにくいと思いました。

なぜそうなるかと言うと、連想配列のkeyが何らかの値として意味を持つという認識が私にはなかったからです。

# どうすれば良いか
連想配列のkeyに値を持たせるのではなく、「その要素のレコードをいくつ作るか」を示す属性をきちんと持たせるべきだと思います。

具体的には、以下のような形です。

```php
$products = [
  ['name' => 'pen',   'price' => 10, 'amount' => 1],
  ['name' => 'note',  'price' => 100, 'amount' => 2],
  ['name' => 'apple', 'price' => 300, 'amount' => 3],
];
```

# まとめ
「短い」よりも「分かりやすい」方が大事だとしみじみ思いました。
PrivateなEC2でyumコマンド使いたいけど「Resolving timed out after 5000 milliseconds」が出た時の対応

EC2でyum updateしようとしたら以下のエラーが発生した。
前提として
・EC2はPrivate Subnetに配置してある
・VPCエンドポイントは設定済み
である。

```
[ec2-user@ip-10-0-77-0 ~]$ sudo yum update
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
Could not retrieve mirrorlist http://amazonlinux.ap-northeast-1.amazonaws.com/2/core/latest/x86_64/mirror.list error was
12: Timeout on http://amazonlinux.ap-northeast-1.amazonaws.com/2/core/latest/x86_64/mirror.list: (28, 'Resolving timed out after 5000 milliseconds')


 One of the configured repositories failed (不明),
 and yum doesn't have enough cached data to continue. At this point the only
 safe thing yum can do is fail. There are a few ways to work "fix" this:

     1. Contact the upstream for the repository and get them to fix the problem.

     2. Reconfigure the baseurl/etc. for the repository, to point to a working
        upstream. This is most often useful if you are using a newer
        distribution release than is supported by the repository (and the
        packages for the previous distribution release still work).

     3. Run the command with the repository temporarily disabled
            yum --disablerepo=<repoid> ...

     4. Disable the repository permanently, so yum won't use it by default. Yum
        will then just ignore the repository until you permanently enable it
        again or use --enablerepo for temporary usage:

            yum-config-manager --disable <repoid>
        or
            subscription-manager repos --disable=<repoid>

     5. Configure the failing repository to be skipped, if it is unavailable.
        Note that yum will try to contact the repo. when it runs most commands,
        so will have to try and fail each time (and thus. yum will be be much
        slower). If it is a very temporary problem though, this is often a nice
        compromise:

            yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

Cannot find a valid baseurl for repo: amzn2-core/2/x86_64
```

`Resolving timed out after 5000 milliseconds` でggったら公式リファレンスが引っかかった。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-troubleshoot-yum-errors-al1-al2/

けど内容が正直よく分からない・・・（YourDNSって何？どう正しければ良いの？何を直せばいいの？）
>「Resolving timed out after 5000 milliseconds」
>次のコマンドを実行して、/etc/resolv.conf ファイルに DNS サーバーの正しい IP があることを確認します。
>cat /etc/resolv.conf
>nameserver YourDNSIP

取り急ぎの対応だとは思うが、とりあえずこの `/etc/resolv.conf` の設定を変えることで自分の場合がyum使えるようになりました。
以下手順です。

①sudo権限で/etc/resolv.confを編集する

```
$ sudo vi /etc/resolv.conf
```

②nameserver {IPアドレス}の部分を上書きする。（上書きしたら!wqで保存。）

```
（変更前）
nameserver {IPアドレス}

（変更後）
nameserver 8.8.8.8
nameserver 8.8.4.4
```

これで出来ない場合は上に貼った公式リファレンスを上から眺めていくと良いかもです。
プログラミング超入門(Final)〜GO言語〜

#構造体
構造体とは、自分で考えて属性を定義できるデータ型のことをいいます。`struct`というデータ型を用いり、`type 構造体名 struct`で定義します。構造体名は小文字で始めてもいいのですが、大きなプロジェクトのプログラムでは基本頭文字を大文字にしているので、ここでは大文字で記述しました。構造体の中では属性を指定でき、GOでは属性を`フィールド`と呼びます。下記コードでは、`length(全長)`,`group(種類)`,`name(名前)`が各フィールド名になります。構造体の定義はフィールド名とデータ型を示すもので、データはフィールドに値を与えて作成します。名前を「アジ」にし、種目に「スズキ目」、全長が「２０ｃｍ」の魚のデータを作成して`変数sea`（海の魚なので）に代入してあります。このように決められた構造に従って組み立てたデータを**インスタンス**と呼びます。`構造体FIshのインスタンスsea`でまとめるとわかりやすいでしょう。フィールドに値を与えてインスタンスを作成したわけですが、`Fishインスタンスsea,river,lake`を作成して要素とする配列のスライス`fishs`を定義し、その`fishs`の要素`fishs[i]`の後に`構造体Fish`のフィールド名`fishs[i].group`, `fishs[i].name`を書くとフィールドの値が取り出せます。

```go
package main

import "fmt"

type Fish struct {
	name string
	group string
	length int
}

func main() {
	sea := Fish{"アジ", "スズキ目", 20}
	river := Fish{"アユ", "キュウリウオ目", 15}
	lake := Fish{"フナ", "コイ目", 40}

	fishs := []Fish{sea, river, lake}

	for i := 0; i < len(fishs); i++ {
		fmt.Printf("%sの%sになります\n", fishs[i].group, fishs[i].name)
	} 
}
```
##ビルドして実行

```
スズキ目のアジになります
キュウリウオ目のアユになります
コイ目のフナになります
```
#構造体のインスタンスを引数にとる関数
構造体のインスタンスを関数の引数にしてみます。**bigger関数**を定義し`Fish`のインスタンスを２つ引数にとり、その`length`フィールドの値を比較してみます。両者の差が`±５`以内であれば、同じ大きさとみなします。**main関数**の中にある**for文**を**bigger関数**を使った記述に変更し、スライス`fishs`が見ている配列のある要素を**bigger関数**の引数に与えます。配列の最後の要素は次の要素(next)として配列の最初の要素をあてます。

```go
package main

import "fmt"

type Fish struct {
	name   string
	group  string
	length int
}

func bigger(f1 Fish, f2 Fish) string {
	fiff := f1.length - f2.length
	switch {
	case fiff > 5:
		return "より大きい"
	case fiff < -5:
		return "より小さい"
	default:
		return "と同じ大きさ"
	}
}

func main() {
	sea := Fish{"アジ", "スズキ目", 20}
	river := Fish{"アユ", "キュウリウオ目", 15}
	lake := Fish{"フナ", "コイ目", 40}

	fishs := []Fish{sea, river, lake}

	for i := 0; i < len(fishs); i++ {
		next := i + 1
		if next >= len(fishs) {
			next = 0
		}
		fmt.Printf("%sは%s%sです\n", fishs[i].name, fishs[next].name, bigger(fishs[i], fishs[next]))
	}
}
```
##ビルドして実行

```
アジはアユと同じ大きさです
アユはフナより小さいです
フナはアジより大きいです
```
#構造体のインスタンスを戻り値とする関数
上記、**bigger関数**では２つの要素を比較しましたが、今度は一番大きな要素を戻す**biggest関数**に書き換えてプログラムを構成していきます。**biggest関数**は、引数に`Fish`のインスタンスの配列のスライスを取り、フィールド`length`の値が最大の要素を戻します。戻り値の型は`Fish`インスタンスになります。**main関数**の中では、`biggest`の引数に`fishs`を渡し、戻り値の`Fish`インスタンスを受け取ってフィールド`name`の値を取り出しています。

```go
package main

import "fmt"

type Fish struct {
	name   string
	group  string
	length int
}

func biggest(fishs []Fish) Fish {
	biggest := fishs[0]

	for i := 1; i < len(fishs); i++ {
		if fishs[i].length > biggest.length {
			biggest = fishs[i]
		}
	}
	return biggest
}

func main() {
	sea := Fish{"アジ", "スズキ目", 20}
	river := Fish{"アユ", "キュウリウオ目", 15}
	lake := Fish{"フナ", "コイ目", 40}

	fishs := []Fish{sea, river, lake}

	fmt.Printf("%sが最大です\n", biggest(fishs).name)
}
```
##再度ビルドして実行

```
フナが最大です
```
[←前回の記事](https://qiita.com/ume-bar/items/844d699b5f1bd2f9448f)

###※皆様、本記事を最後までお読み頂きありがとうございました。私は、GO言語を学ぶにあたってある一冊の本にとても支えられ、ここまで覚えることが出来ました。プログラミングを早く上達させるには、読むだけではなく実際にコードを書き出して、どんどん覚えたことをアウトプット(出力)して行けば、より早く上達できると身をもって感じました。この後に続く実践・応用編は、実際に参考にさせて頂いた[著書](https://gihyo.jp/book/2020/978-4-297-11617-0)をご覧になって学習して頂きたいと思います。本来であれば、もっと技術的な記事を配信していかなければならない`Qiita`を今回こういう形で利用させて頂きましたが、この記事をご覧になられた初学者の方々への励みになれば幸いです。
macOS Big Sur で eventmachine がインストールできないときの対処法

# 結果だけ知りたい
```shell:Shell
sudo xcode-select --switch /Applications/Xcode.app
sudo xcodebuild -license accept
gem install eventmachine
```


# 環境
* macOS Big Sur 11.2.3
* Xcode 12.4
* Ruby 2.7.1
* RubyGems 3.1.2
* Bundler 2.1.4
* eventmachine 1.2.7

システムのバージョン詳細: [Brewfile.lock.json](https://github.com/noraworld/dotfiles/blob/6f63a6e8266c21a0ea7557d111d80c1c7eaf222d/core/Brewfile.lock.json)


# `--with-cppflags` ではダメだった
macOS に eventmachine をインストールしようとしたら失敗した。

ネットで記事を調べると、以下の解決法しか出てこないが、これだとインストールできなかった。

```shell:Shell
gem install eventmachine -- --with-cppflags=-I/usr/local/opt/openssl/include
```

https://stackoverflow.com/questions/30818391/gem-eventmachine-fatal-error-openssl-ssl-h-file-not-found


# ログを見る
真面目にログを見てみる。

```log:/Users/noraworld/.anyenv/envs/rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/extensions/x86_64-darwin-19/2.7.0/eventmachine-1.2.7/mkmf.log
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main(int argc, char **argv)
4: {
5:   return !!argv[argc];
6: }
/* end */

"pkg-config --exists openssl"
package configuration for openssl is not found
```

## package configuration for openssl is not found
`package configuration for openssl is not found` が気になる。

でも、OpenSSL はちゃんと最新版がインストールされているし、`--with-ssl-include` とか `--with-cppflags` とか `--with-openssl-config` とか、OpenSSL に関連しそうなオプションをいろいろ付けてみたけどダメだった。

`package configuration for openssl is not found` って出てくるけど、どうやら OpenSSL の問題だけではなさそう。

## xcrun: error: invalid active developer path
次に気になるのは `xcrun: error: invalid active developer path` だ。

`CommandLineTools` のパスがなんかおかしいと言われている。

ここで、ふと、自分が以前に書いた記事を思い出した。

https://ja.developers.noraworld.blog/brew-install-and-update-failure-on-macos-mojave

すると、過去にも全く同じ警告が出ていることがわかった。


# `brew doctor`
そこで、`brew doctor` を試してみた。

```shell:Shell
brew doctor
```

```
Warning: Your Xcode is configured with an invalid path.
You should change it to the correct path:
  sudo xcode-select --switch /Applications/Xcode.app
```

どうやらこれを実行すれば良さそう。

```shell:Shell
sudo xcode-select --switch /Applications/Xcode.app
```

その後、もう一度 `brew doctor` を実行すると、以下のエラーが出た。

```shell:Shell
brew doctor
```

```
Error: You have not agreed to the Xcode license. Please resolve this by running:
  sudo xcodebuild -license accept
```

ライセンスに同意していないので同意してくれということらしいので、同意する。

```shell:Shell
sudo xcodebuild -license accept
```

そして、さらにもう一度 `brew doctor` を実行すると、警告が消えた。


# インストール完了
ここで、最初に戻り、eventmachine をインストールしようとしたら、インストールできた。

```
gem install eventmachine
```

結局、オプション (`--with-ssl-include` とか `--with-cppflags` とか `--with-openssl-config` とか) は要らなかった。


# 結論
困ったときは、`brew doctor`。
Qiitaへの初めての記事投稿してみた

# はじめに
初めまして、@takashi_sakamotoです。
少しプログラミングかじって、現在はPMをしています。
外部への情報発信とプログラミングの基礎を学びなおそうと思い、初めてQiitaに記事投稿していこうと思います。（目標は低めに月１投稿です！）

##初めての記事投稿
試しに「投稿する」ボタンを押して、「記事投稿」を選択しました。
。。。Markdown。
おっと、いきなりそう来ましたか（笑

最近は共同編集しするドキュメントの構成管理のしやすさからMarkdownを触り始めたばかりでした。
記事もそちらで書きなさいと。。。

安心してください、コピれますよ！
ということでQiitaのヘルプから、他の記事をMarkdownで見る方法([Qiitaの投稿をMarkdown表示にする方法](https://help.qiita.com/ja/articles/qiita-show-raw-body))を確認（笑
同じ初心者っぽい記事をMarkdown表示してコピペです！

##まとめ
* 失敗してもいいから始めてみよう
* 他の人の記事をコピペして、Markdownのヘルプ見ながら編集してみる
* いざ、投稿！



###関連記事
* [【マークダウン記法とは？】マークダウンの書き方を網羅的に解説](https://backlog.com/ja/blog/how-to-write-markdown/)
* [Qiitaの投稿をMarkdown表示にする方法](https://help.qiita.com/ja/articles/qiita-show-raw-body)
* [Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
専門職大学院大学での学びの整理・プロジェクト管理

## プロジェクト管理の概要
|項目 |第4限の記載内容 |第5限の記載内容 |
|---|---|---|
|今回のポイント  |・大変なプロジェクトを経験することで自身の成長につながる。  |メンバーの好悪や好みを予め頭の中に描きチームとしての偏りがないように意識をあげていく。 |
|自らの業務や活動に活用できるポイント |・チーム力をあげていくためには、チームメンバーの特徴を理解する。| お互いの異質性を受け止めて、それを活かす施策を考える。相手の特性を観察して、それに合わせた話し方をする。 |

## 進捗管理
|項目 |第4限の記載内容 |第5限の記載内容 |
|---|---|---|
|今回のポイント  |・PDMを作らないとどこに注力しないといけないのかの全体像およびクリティカルパスが見えない。遅れの予兆を見逃さない。進捗率はあてにしない（永遠の進捗率95％）  |・プロジェクト内でEVMの傾向は急には変わらないので傾向を読み取ることはできる。EVMで可視化することでプロジェクトの進捗を上層部に分かりやすく報告できる。
|自らの業務や活動に活用できるポイント |・状況により変化するので注意する。スケジュールが遅れたときの代替案を用意しておく。所要時間も実施する人によってズレる可能性があるので見積りも大事になる。複数の作業が交わるポイントでは予備を設ける。| ・コストとスケジュールを関連させてコントロールする。傾向が見えたら是正処置して変更管理する。余裕あり過ぎなどを修正する。傾向から予測値を出して報告する。見積ノウハウを個人・組織でためて活用する。 |

## リスク分析
|項目 |第4限の記載内容 |第5限の記載内容 |
|---|---|---|
|今回のポイント  |リスク分析は状況により変化するが見直しは、見直しは省かれがちである。  |原因・対応策は複数の知識エリアに跨る。 |
|  |リスクコントロール軽視されがちである。  |  |
| |想定できるものは想定しておく。  |  |
|自らの業務や活動に活用できるポイント |状況により変化したリスクは早く見直す。 |  |
| |リスク軽減策で実行できるものはなるべく早く実行する。 |コミュニケーションの対応策・改善策は、人やチームによるので答えは一つではないが人に応じて複数実行していく。|
| |リスク管理は評価されない傾向にあるが粛々と実行する。| 同じことでも大事なことは何度でも言う。|
同じことでも大事なことは何度でも言う場合は、相手に嫌がられないようにうまくやる。

## ステークホルダー
|項目 |第4限の記載内容 |第5限の記載内容 |
|---|---|---|
|今回のポイント  |ステークホルダーの洗い出し、管理・整理。PMBOKの全体像、プロジェクトの前提（経営層の承認）。  |プロジェクトの失敗から学ぶ（事例式）、プロジェクトレベルでプロジェクトを見る。QCD＋CS＋ESが大事。|
|自らの業務や活動に活用できるポイント |ステークホルダーを表にして非属人的な管理ができる。表にしてステークホルダーのマネジメントを意識して実践する。| 組織として失敗を学びで改善させ続ける。過去の教訓を生かす。 |

## 品質管理
|項目 |第4限の記載内容 |第5限の記載内容 |
|---|---|---|
|今回のポイント  |設計上はOKでも本番環境でNGのこともある。品質基準があっても活用されないことがある。QC7つ道具、5Why Question（なぜなぜ分析）なぜなぜ分析の真因が「人」に帰着してはいけない。  |人の余剰や不足を防ぐのが大事。コミュニケーションパスの増加は「標準化」で対応する。山積み山崩しが大事（資源標準化）、チーム育成（人間関係・行動規範）タックマンモデルでは各段階がある。「動乱期」にはちゃんと議論することが大事。|
|自らの業務や活動に活用できるポイント |「なぜなぜ分析」で問題の真因に迫りプロジェクトの反省をしていきます。「なぜなぜ分析」は、教訓の収集やPDCAの回転にも応用できると良いと思います。失敗事例の共有は大事。| 「動乱期」にちゃんとお互いに違いがあることを認識しあい、ちゃんと議論して次に進むことが大事。（次は安定期）「正しい対立」は良いことで意見の対立は歓迎する。フィードバックは本人に直接かつ具体的に言う。 |
品質は過剰品質も問題で、そもそも顧客が望んでもいないような高レベルなことをしても意味がなく、顧客と合意しておくのが望ましい。

 [タックマンモデルとは](https://toyokeizai.net/articles/-/117979?page=2 "タックマンモデルとは")
ransackについて

ransackについて、qiitaにはない便利な記事

ransack公式:
https://github.com/activerecord-hackery/ransack

ransacker公式:
https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers

Ransackで簡単に検索フォームを作る73のレシピ:
http://nekorails.hatenablog.com/entry/2017/05/31/173925

Ransackで親テーブルや子テーブルのカラムで複数検索する方法:
https://hi-algorithm.com/ransack-multiple-search/
GCPコンソールの認証情報でAPIキーの利用を制限する方法（Browser key）

以下の記事の「GCPコンソール内の認証情報でAPIキーの利用を制限」の設定方法です。

https://zenn.dev/okada3/articles/3b308612b70c26#2021%2F03%2F14%E8%BF%BD%E8%A8%98

Browser keyのHTTP リファラーに制限をかけることで、FirebaseのKeyが知られても他の人が使えないようにします。

# GCPコンソールで設定

https://console.developers.google.com/apis/credentials を開きます。
以下の矢印のところが、対象のアプリになっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11545/14c295a0-efe3-e233-3c71-706406797bf4.png)

APIキーのBrowser keyをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11545/8c5c25bc-c9f5-93ed-0391-83b2eaf7ae25.png)

以下の2箇所を設定して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11545/897dcad4-7460-bcce-1cc0-d4bafac60014.png)
① HTTP リファラー（ウェブサイト）を選択
② 許可するサイトを設定

## 注意
②ではlocalhostは設定しないようにします。
localhostがあると、せっかく制限をかけても、誰でもローカルから呼び出せてしまいます。
そのため、ここでは公開用のURLのみ設定します。

# 動作確認

設定完了後に、localhostから呼び出せなくなっていたら成功です。

```
Uncaught Error in snapshot listener: FirebaseError: Missing or insufficient permissions.
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11545/2697cfc3-1573-b1fe-63f4-566c86d2d62b.png)

設定したドメインでは、問題なくアプリケーションが動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11545/aa2d7697-bed1-44a1-57b1-48430f2a5b69.png)

# ローカルで開発しにくい
この設定をしてしまうと、localhostで動かず開発しにくいです。
そのため、私はlocal開発時は別のFirestoreを使うようにしました。

https://qiita.com/okada3333/items/43bf58e188a31fde86bd
hover時に線が入ってしまうエラーを修正する

○ローカルでは出なかった挙動がデブロイすることによって起こっているので
　その対策を備忘録として残しておきます。

マウスhover前
![スクリーンショット 2021-04-10 8.52.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/96ea73b3-bb8e-82de-b25d-4159aff6d01e.png)
マウスhover後
![スクリーンショット 2021-04-10 8.52.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/a22b148f-9cf2-40ed-d774-eba4ed552c60.png)

ホバー時に、謎の線が出てします。
対策：cssを適用する

```index.html
<%= link_to  new_nursing_home_registration_path,id:"btnline" do %>
<button class="style-topoffices-newmenbtn style-boder-smallradius">事業所新規登録</button>
<% end %>
```


```style.css
#btnline:hover{
text-decoration: none;
}
```


ホバー時
![スクリーンショット 2021-04-10 8.52.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/96ea73b3-bb8e-82de-b25d-4159aff6d01e.png)


これで解決しました。
バッチファイルでファイルをダウンロードする（プロキシ・失敗考慮）

Y子です。
今日は、ファイルをダウンロードしてみます。HTTPリクエストってやつです。

# 概要・用途・注意
決まったURLのファイルをダウンロードするバッチファイルです。
```http://example.jp/daily_data.csv``` を、 ```savefile.csv``` という名前で保存してみます。
たとえば、 __「毎日更新されるファイルをダウンロードして上書きし、業務に使う」__ なんて場合を想定しています。
「```curl```」というコマンドを使いますが、これはWindows 10のRS3（2018年）から標準で付属しているようです。（[参考](https://ascii.jp/elem/000/004/021/4021036/ "Windows 10で標準で用意されるようになったcurlを使ってみる")）

https://ascii.jp/elem/000/004/021/4021036/

# コード
### (1) シンプルな例
単純に、ダウンロードして保存します。

```bat:download_file_simple.bat
@echo off

rem ダウンロードしたいファイルのURL
set str_url="http://example.jp/daily_data.csv"

rem 保存するファイル名
set str_savefile=savefile.csv

rem ダウンロード実行
curl %str_url% > %str_savefile%

pause
```

### (2) プロキシを考慮した例
社内ネットワークなど、認証が必要なプロキシがある場合はこちら。

```bat:download_file_proxy.bat
@echo off

rem ダウンロードしたいファイルのURL
set str_url="http://example.jp/daily_data.csv"

rem 保存するファイル名
set str_savefile=savefile.csv

rem プロキシのユーザ名、パスワード、サーバ名、ポート番号
set pid=username
set ppw=password
set psv=proxy.example.jp
set ppt=8080

rem ダウンロード実行(プロキシ考慮)
curl %str_url% -x http://%pid%:%ppw%@%psv%:%ppt% > %str_savefile%

pause
```

### (3) ダウンロード成否を判定する例
ダウンロードに失敗する可能性がある場合を考慮します。
失敗データ（空ファイル）を、既存のファイルに上書きしてしまうと悲しいですので…。

ダウンロードしたものをいったん一時ファイルとして保存し、空でなければ採用する、という2段構えにしました。

```bat:download_file_cmp.bat
@echo off

rem ダウンロードしたいファイルのURL
set str_url="http://example.jp/daily_data.csv"

rem 一時保存するファイル名
set str_tmpfile=tmpfile.csv

rem 保存するファイル名
set str_savefile=savefile.csv

rem ダウンロード実行(一時保存)
curl %str_url% > %str_tmpfile%

rem 一時保存ファイルのサイズを取得するおまじない
for %%i in (%str_tmpfile%) do set size=%%~zi

rem ダウンロード失敗の場合(空ファイルの場合)
if %size%==0 (
  rem 一時保存ファイルを削除
  del %str_tmpfile%
  echo ×失敗×

rem ダウンロード成功の場合
) else (
  rem 古い保存ファイルがあったら消す
  if exist %str_savefile% (
    del %str_savefile%
  )
  rem 一時保存ファイルを保存ファイルにリネーム
  ren %str_tmpfile% %str_savefile%
  echo ○成功○
)

pause
```

```:実行結果
> download_file_cmp.bat
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 12425  100 12425    0     0  12425      0  0:00:01 --:--:--  0:00:01 39696
○成功○
続行するには何かキーを押してください . . .
```

# おわりに
毎日ブラウザから保存していたファイルが、バッチファイルを叩くだけで保存できてしまうのは便利です。
自分が作ったツールで業務改善できると、ちょっと嬉しくなります。

ではまた！
Webpacker::Manifest::MissingEntryError in Home#topの対処

railsで新規appwを作製し、サーバーを立ち上げアクセスしたところエラーが出てしまったので対処しました

やったこと
1.node.jsの削除
2.node.js安定版のインストール
3. $rails webpacker:install
4. $rails webpacker:compile

以上でできたのでお試しあれ。
Java初心者におすすめの本を一つ

#はじめに
今年度からJava関係の仕事をする予定であることから、ずっとしていなかったJavaの勉強を本格的に始めました。これまでPython、JavaScript、phpのような比較的取り組みやすいと言われる言語は学んでいたのですが、いよいよJavaを学習する時がきました。Javaといえば、大学１年生の頃（もう８年前か...)に実は少しかじったのですが、とっかかりのpublic static void main(String[] args)のところでウワーってなって勉強をやめた記憶があります。（あと当時の私のノートパソコンでは統合開発環境の動作が重すぎていやになった記憶もある...）
#で、おすすめのJavaの本て結局何なの？
そんなこんなで、どう勉強しようかと悩んでいたのですが、本屋さんにいったらなんと以前にはなかったなんか分かりやすそうな本があるじゃないですか？！

そう...それは**「スッキリわかるJava入門」**です。いかにも分かりやすそうな表紙をしていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445199/e0cb0de7-88bf-616b-04de-4d28732318f7.png)
www.amazon.co.jp/dp/4295007803
まあ、ここに来て私が言わなくても、どこで調べても一番に上がってくるので知ってますよね...

入門編と実践編、サーブレット・JSP編の３冊に分かれています。まあ、Java言語自体を学ぶのであればサーブレット・JSP編はいらないと思います。

#で、なんでおすすめなの？根拠を言ってください
まあ、私が勉強していて分かりやすかったから...なんですが、お勧めできる点を紹介しておきます。

* 図やイラストが多く視覚的に非常に分かりやすい
* 機能の概念の説明にとどまらず、なぜその機能があるのかや開発を意識した説明が随所にちりばめられている
- オブジェクト指向の説明が初学者向けに非常に工夫されている
 - オブジェクト指向初学者にも学習のフローチャートが提示されており、ドツボにはまらないような工夫がある
 - オブジェクト指向の概念が分かりやすい例に落とし込まれ説明されている
 - なぜ、オブジェクト指向を使うのか、なぜ抽象クラスやインターフェースの概念が用意されているのかが説明されている
* 実践編では言語仕様の説明のみにとどまらず、実際の開発現場で必要となる周辺知識まで解説されている

#まとめ
以上、「スッキリわかるJava入門」のお勧めできる点をいくつか書きましたが、やっぱり一番ためになったなと思うのが、なぜその機能があるのかにしっかりと触れている点です。実際に開発者目線から解説してくれているので、分かりやすい上に非常にためになる書き方がされているなと感じます。今後、Javaを勉強しようというかたに胸を張っておすすめします！