OmniAICreator/Qiita-1.07M huggingface dataset:
ERROR in src/app/app.module.ts(80,49): error TS2339: Property 'firebase' does not exist on type '{ production: boolean; }'.

【備忘録】

<br>

Angular7を以下のコマンドでプロダクションビルドして出たエラー

```cmd
C:\projects\projectA>ng build --prod --output-path=dist
```

<br>


エラー内容：

```cmd
ERROR in src/app/app.module.ts(80,49): error TS2339: Property 'firebase' does not exist on type '{ production: boolean; }'.
```

<br>



### 対処法



とても簡単で、`ng build --prod` コマンドではangular-cliは**environment.prod.tsファイル**を使用する。
**environment.ts**ではなくて。

なので**environment.prod.ts**ファイルにも**environment.ts**と同じようにfirebaseで使う環境変数を入力してあげればよい。

###### environment.prod.ts

```typescript
export const environment = {
  production: true,
    // Initialize Firebase
    firebase : {
      apiKey: "<＊＊＊＊>",
      authDomain: "<＊＊＊＊>.firebaseapp.com",
      databaseURL: "https://<＊＊＊＊>.firebaseio.com",
      projectId: "<＊＊＊＊>",
      storageBucket: "<＊＊＊＊>.appspot.com",
      messagingSenderId: "<＊＊＊＊>"
    }
};
```







以上
Docker でコンテナの外から MySQL に接続してファイルの SQL を実行するコマンド

DB のコンテナがすでに起動している時にやりたかったこと。自分用のメモとして書き残しておく。
今回は実行結果もログに出力します。

```
docker exec -i [DBコンテナ名] mysql -u [ユーザ名] -p[パスワード] [DB名] -vvv < ファイル名.sql > [ログファイル名].log
```

`-p`とパスワードの間には半角スペースを入れない。そうすることでパスワード入力を省ける(セキュリティ的にはあまりよくない😇)。

`-vvv`は MySQL のオプション。出力結果を冗長表示(詳細に表示)する。 
※`-v` `-vv` `-vvv`で冗長度合いが変わるらしい。

普段 `docker exec` でコンテナに入るときは `-it`をオプションで入力しているけれど、今回はターミナルを開かずワンライナーでSQLを実行したいので、 `-i` だけオプションに指定すればよい。

##### 参考
[docker exec -itって実際は何をしてるの？【90日目】 - エンジニアのひよこ_level10](https://www.nyamucoro.com/entry/2018/01/11/224932)
ライブラリを使わずgasだけで作るオウム返しするslack botの作り方

[Outgoing Webhooks](https://api.slack.com/custom-integrations/outgoing-webhooks)はお勧めしませんとslackさんがおっしゃるので、ひとまずオウム返しするbotを作りましたので共有します。

下記のコードは、特定のチャンネルでのbotへのメンションに対してオウム返しするものになります。
下記のコード中のチャンネルID、ボットユーザIDはご自身の環境でログを仕込んで調べていただいて書き換えてもらえればと思います。

## 作り方

- スプレッドシートから```ツール>スクリプトエディタ```を選択してエディタを開いて下記のコードをコピペ

```js
function doPost(e) {
  var postData = JSON.parse(e.postData.getDataAsString());
  
  // Event Subscriptionsに必要な部分
  if(postData.type == 'url_verification') {
    return ContentService.createTextOutput(postData.challenge);
  } else if　(
      postData.event.channel == 'チャンネルID' // 指定のチャンネルだけを観測する
      && postData.authed_users[0] != 'ボットユーザID' // botが発言者の場合には反応しない
      && postData.event.text.indexOf('ボットユーザID') != -1 // botが呼ばれた時だけ反応する
      ) {
    return reply(postData);
  }

  return 0;
}

function reply(postData){
  // Incoming WebhooksのURL
  var slackUrl = 'Incoming WebhooksのURL';
  // botへのメンションを全て消す
  var text = postData.event.text.replace(/<@ボットユーザID>/g, '').trim();
  // おうむ返しするテキストを用意する
  var messageData = {
    'text': '<@' + postData.event.user + '> '　+ text
  };
  
  var options = {
    'method'  : 'POST',
    'headers' : {'Content-type': 'application/json'},
    'payload' : JSON.stringify(messageData)
  };
  
  return UrlFetchApp.fetch(slackUrl, options); 
}
```

- ```公開>ウェブアプリケーションとして導入```を選択すると下記の画像のようなのがでてくる
- プロジェクトバージョンをnewにして、自分が実行者でアクセスは匿名でもできるように選択して更新をクリックする
  - 今後コードを修正するたびにnewにして更新した方がよいと思います（何でかは良く理解していない）
- 更新して出てきたURLはslack apiで使うのでコピーしておく


<img width="464" alt="スクリーンショット 2019-04-10 14.12.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/120339/6b4cae4f-a902-99ec-41d3-9b8903958248.png">


### slack botの設定

- https://api.slack.com/ にアクセスしてbotを流れるように作成
- Event SubscriptionsのRequest URLに先ほどスプレッドシートでコピーしたURLをペースト（おそらく緑のチェックマークがつくはず）

<img width="964" alt="スクリーンショット 2019-04-10 14.05.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/120339/2babaeed-c6e0-f0f3-31d1-2eb74aba92cb.png">

- Subscribe to Workspace EventsとSubscribe to Bot Eventsの設定は下記の画像のように設定する


<img width="964" alt="スクリーンショット 2019-04-10 14.05.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/120339/c1ac9f6b-cab3-fa44-2903-00dbd9e63db2.png">

（私はこれでできた）


### ログに関しての参考資料
- https://qiita.com/howdy39/items/398f4969639a558c8487
Djangoの使い方～デザイン編①～

##はじめに
[Djangoの使い方～デプロイ編②～](https://qiita.com/connecrew-sugiyama/items/5080052e564334672bd6)の続きです。
今回はデプロイで表示できたサイトの見た目を変えていきます

##URLを作ろう
mysite/urls.py ファイルを下記に下記に書き換えて下さい。

```mysite/urls.py
from django.urls import path, includefrom django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
]
```
これでDjangoは'http://127.0.0.1:8000/' に来たリクエストを blog.urls へリダイレクトするようになります。

##blogのURL
blog ディレクトリの下に、新しく urls.py という空のファイルを作って、コードエディタで開いて下さい。そして最初の2行を以下のように書きます。

```blog/urls.py
from django.urls import path
from . import views
```
これはDjangoの path メソッドと、blog アプリの全ての ビューをインポートするという意味です。


その後、最初のURLパターンを追加します。


```blog/urls.py
urlpatterns = [
    path('', views.post_list, name='post_list'),
]
```
これは 'http://127.0.0.1:8000/' というアドレスにアクセスしてきたら views.post_list が正しい行き先だということをDjangoに伝えています。

##ビューの作成
blog/views.py をコードエディタで開いて次のように記入して下さい。

```blog/views.py
from django.shortcuts import render

def post_list(request):
return render(request, 'blog/post_list.html', {})
```
##テンプレートの作成
blogディレクトリの中にtemplatesという名前のディレクトリを作成してください。 次に、自分のtemplatesディレクトリの中にblogという名前のディレクトリを作ります。
blog
└───templates
    └───blog
blog/templates/blogディレクトリの中に、post_list.htmlファイルを作成します。
post_list.htmlファイルをコードエディタで開いて、次の内容を加えます。

```post_list.html
<html>
    <head>
        <title>Django Girls blog</title>
    </head>
    <body>
        <div>
            <h1><a href="/">Django Girls Blog</a></h1>
        </div>


        <div>
            <p>published: 14.06.2014, 12:14</p>
            <h2><a href="">My first post</a></h2>
            <p>Aenean eu leo quam. こんにちは！ よろしくお願いします！ </p>
        </div>


        <div>
            <p>公開日: 2014/06/14, 12:14</p>
            <h2><a href="">2番目の投稿</a></h2>
            <p> こんにちは！ よろしくお願いします！ </p>
        </div>
    </body></html>
```
[ここ](http://127.0.0.1:8000/)を開いて確認してみましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/376013/d9e5975e-349e-1bda-95e2-dcafaaca35ba.png)
このように表示されるはずです。

##デプロイしよう
djangogirls ディレクトリにいることを確認

```ruby:command-line
$ git status
```

コミット

```ruby:command-line
$ git add --all .
```

コミットメッセージをつける

```ruby:command-line
$ git commit -m "Changed the HTML for the site."
```

GitHubに変更部分をプッシュ

```ruby:command-line
$ git push
```
[PythonAnywhereコンソールページ](https://www.pythonanywhere.com/login/?next=/consoles/)を開き、Bashコンソールに移動してください。
ユーザー名を自分にして下記を実行

```ruby:command-line
$ cd ~/<your-pythonanywhere-username>.pythonanywhere.com
$ git pull
[...]
```

Webページで自分のアプリを**Reload**するとWeb上で動くようになります！

##おわりに
次はHTMLでデザインを変えていきます！
CirclrCIのキャッシュのkeyに環境変数を使う

CircleCIでrebuildするとき、キャッシュなしで実行する「rebuild without cache」機能があるんですが、workflowを使った場合その機能が使えません（ボタンが表示されません）。

cacheのkeyに環境変数を使うことで似たような機能を実現します。

## 対応

CircleCIで、Settings > Environment Variables で環境変数（今回は`CACHE_KEY`）を設定して、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/611/a5855096-645c-8deb-a071-d16cd2879345.png)


こんな感じでkeyに利用します。

```yml:.circleci/config.yml
- restore_cache:
    keys:
      - gem-cache-{{ .Environment.CACHE_KEY }}-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
      - gem-cache-{{ .Environment.CACHE_KEY }}-{{ arch }}-{{ .Branch }}
      - gem-cache-{{ .Environment.CACHE_KEY }}
```

環境変数を別の値に書き換えてrebuildすればkeyが異なるのでキャッシュなしで実行できます。

以上です :hugging: 

## 参考
- [Caching Dependencies \- CircleCI](https://circleci.com/docs/2.0/caching/#using-keys-and-templates)
Uplift Modeling用Pythonパッケージ「CausalLift」を作りました。

機械学習モデルで反応する顧客を予測して広告、勧誘等のキャンペーンを実施したいという要望はよくありますが、単純に予測モデルを作るだけだと、キャンペーン無しでも反応していたはずの顧客へも実施することになり、ムダが発生します。

効率的にキャンペーン対象顧客を選ぶのに使えるUplift Modeling用Python/ Rパッケージは既にありますが、Qini等の専門的な評価指標は関係者に説明しづらいという問題がありました。

そこで、ビジネスの実務で使えるように設計したUplift Modeling用Pythonパッケージを作りました。

https://github.com/Minyus/causallift


pipでインストール可能です。

pip install causallift

A/B Testではないデータ(観察データ)でも使えます。



できること：

1. 傾向スコアを計算(A/B Testでないデータの場合)
2. IPW(傾向スコアの逆数で重み付け)で補正した2つのXGBoostモデルからUpliftスコア(CATE, ITE)を計算
3. Upliftスコアに従ってキャンペーンを実施すればConversion Rate(購入率等)が何倍になるかを計算


シミュレーション観察データかLalondeデータを使ったサンプルコードをColab上で試せます。
https://colab.research.google.com/github/Minyus/causallift/blob/master/examples/CausalLift_example.ipynb



[為になった資料： 因果推論]

「原因と結果」の経済学(https://www.amazon.co.jp/dp/B06X6GJYWF/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1) 


データ分析の不思議、シンプソンのパラドックスを統計的因果推論から考える
https://www.krsk-phs.com/entry/simpsonparadox



[為になった資料： 因果推論、傾向スコア、IPW]

岩波データサイエンス Vol.3 (https://www.amazon.co.jp/dp/B0764942HW/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

統計的因果推論(2): 傾向スコア(Propensity Score)の初歩をRで実践してみる
https://tjo.hatenablog.com/entry/2016/10/05/190000



[為になった資料： Uplift Modeling]

『仕事ではじめる機械学習』(https://www.amazon.co.jp/%E4%BB%95%E4%BA%8B%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E6%9C%89%E8%B3%80-%E5%BA%B7%E9%A1%95/dp/4873118255) 第9章 


Uplift Modeling用のパッケージtools4upliftを使ってみた
http://kamonohashiperry.com/archives/2197 




[為になった資料：観察データでのUplift Modeling]

傾向スコアを用いて観察データからUpliftをモデリングする
https://qiita.com/usaito/items/f713d93732db82696a76

EconMLパッケージの紹介 (meta-learners編)
https://usaito.hatenablog.com/entry/2019/04/07/205756
Sass(Node-sass)の環境構築を行ってみる

<h2>1. Sass概要</h2>

SassはCSSプリプロセッサで
Sass記法とScss記法（Sassy CSS）があります。
現在の主流はScssです。

CSSからScssへ移行した際のメリットは
 1.  記述の簡略化（入れ子構造）
 2.  専用のコメント（CSSなのに1行コメント等）
 3.  変数を使用して、同じ値を使い回せる
 4.  extendを使用して、セレクタを使いまわせる
 5.  mixinを使用して、スタイルをまとめ使いまわせる
 6.  Partialを使い、複数のSassを1つのCSSにまとめることができる
 7.  条件分岐や繰り返し処理がCSSなのに可能に
 8.  CSSへコンパイルする際は圧縮できる
 9.  様々なフレームワークの基礎となっている

ということで、Sassを導入してみました。

<h2>2.2つのSassについて</h2>


Sassには、大きく分けて
　・node-sass(LibSass)
　・Ruby Sass　　
があります。

Ruby Sassは、Rubyで開発されたSassですが
node-sassは、C/C++で開発されたSassです。

そのため、node-sassは
Node.js以外（PHP,Phython,Scala）でも使用可能です。
一番大きなメリットはRuby sassよりも圧倒的に早いことです。

というわけで今回は
mac環境でnode-sassの環境構築をしていきます。



<h2>3.Node.jsのインストール</h2>

まずは、Node.jsをダウンロードしていきましょう。

https://nodejs.org/ja/
特に理由がなければ、左側の推奨版で構いません。

解凍次第、
ターミナル（黒い画面）にいき、

```
node -v
```
と打つことで
node.jsのバージョンを確認することができます。
（これでちゃんとインストールできたかを確認することができます。）


<h2>4.gulpのインストール</h2>

このgulpは、タスクランナーソフトで、
様々な処理を自動化する役割です。

Sassを使用する場合、最終的にはCSSにコンパイルする必要があるため
タスクランナーを使い自動化させています。

<h3>4-1.gulp-cilのインストール</h3>


gulpのインストールには
Node.jsのパッケージ管理マネージャであるnpmを使用していきます。

```
nmp install --global gulp-cil
```

これで、グローバルにインストールできましたので、
インストールしたマシンのどのディレクトリでも
gulpコマンドを使用することができるようになりました。


```
gulp -v
```

を使用して、インストールできているか
確認しておきましょう。

※---------------------------------------------------
自分の場合は最初に
「permission denied」というエラー（要は権限不足）が出たので

```
chmod ７７７ 5_sass_test.txt
```

として回避しました。
[permission deniedで悩まされたので勉強してみた](https://qiita.com/takuyanin/items/18590600d077df707923)
※---------------------------------------------------

<h3>4-2. package.jsonの作成</h3>

これで、package.jsonが作成されます。

```
npm init -y;
```

<h3>4-3. gulpのインストール</h3>

次にgulpとgulp-sassをインストールしていきます。

```
npm install --save-dev gulp
```

実行し、成功するとこのように
「package.json」が作成されます。

![スクリーンショット 2019-04-10 13.24.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352124/3d51994d-869e-594c-319c-c6e561c3d777.png)


<h3>4-4. gulp-sassのインストール</h3>

これだけでは自動更新されないため
gulp-sassも追加

```
npm install --save-dev gulp-sass
```

<h3>4-5. gulpfile.jsの作成</h3>

ここまでで自動化を行う下地ができたので、
次にjavascriptファイルに、自動化の内容を書き込んでいきます。

が、基本的にはコピペで大丈夫です。

gulupfile.jsは下記サイトからもってきましょう
https://www.npmjs.com/package/gulp-sass

色々なバージョンがありますが、
一番基本的なこいつ（下記）をgulpfile.jsとして手動で作成

```js:gulpfile.js

'use strict';
 
var gulp = require('gulp');
var sass = require('gulp-sass');
 
sass.compiler = require('node-sass');
 
gulp.task('sass', function () {
  return gulp.src('./sass/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('./css'));
});
 
gulp.task('sass:watch', function () {
  gulp.watch('./sass/**/*.scss', ['sass']);
});
```

これで終了です。
お疲れ様でした。


<h2>同じ環境を構築したい場合</h2>

もし同じ環境を構築したい場合は,

<h3>4-1.gulp-cilのインストール</h3>


```
nmp install --global gulp-cil
```
の後に、今回作成したpackage.jsonがある状態で

```
npm install
```

と行うだけで、全てのパッケージがインストールされます。

同じ環境を作成するにはpackage.jsonが重要ということですね。
Selenium WebDriver (Chrome) でテストするにあたり役に立ったTips

Node.jsのSelenium-webdriverでE2Eテスト書くためのTips。はじめから知っていればどれだけ捗ったか。

# Seleniumの公式ドキュメントはここ

探してもなかなか見つからなかった。
ここ。
https://seleniumhq.github.io/selenium/docs/api/javascript/index.html
公式ドキュメントを見るのが1番なので、Qiitaで知った気になっている人はこのリンク先だけ見ておけ。

# ChromeのデベロッパーツールにXpathを作ってもらう

階層が深いDOMElementだったり、SPAでいろいろなコンポーネントを使ってサイトを作っていると、なかなかXPathを思ったとおりに指定するのが難しい。
そんな時は思考停止してChromeのデベロッパーツールを使ってXpathを取得しよう。

とはいえ `@class` `@id` で指定するほうが記述が簡潔になる場合が多い。
Chromeに頼りすぎるな。自分の頭で考えろ。


<img width="979" alt="スクリーンショット 2019-04-10 13.44.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/159511/39363497-66d5-d218-1477-0423934b6d80.png">


# ChromeのデベロッパーツールでXpathを指定して要素を取得しよう

既存のテストを読んだところで指定されているXpathがどの要素を指定しているかわからない。そんな時はChromeデベロッパーツールを使えば要素を取得できる。

`$x('xpath')` にXpathを渡してやれば要素を確認することができる。

<img width="980" alt="スクリーンショット 2019-04-10 13.49.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/159511/9aa24b5a-23ab-f9c0-db02-52856bdea29d.png">

# WebElement#clear() 動いてなくね？

MaterialUIのコンポーネントだからなのかinput要素に`sendKeys()`でテキストを送ることはできても、`clear()` で削除することができない。なんなんこれ。

代替手段としての `BACK_SPACE` キーを送信してテキストを削除する。

```javascript
// e.g. sending back space.
import webdriver, { until, By, Key } from 'selenium-webdriver'

export const timeout = 15000
const drive = new webdriver.Builder()
  .forBrowser('chrome')
  .build()


driver
  .findElement(By.xpath('//*[contains(@id,"name_input")]'))
  .then(element => {
    element.sendKeys.apply(element, [Key.chord(Key.CONTROL, "e"), ...(new Array(30).fill(Key.BACK_SPACE))])
    element.sendKeys('new name')
  })

```

この例では、まず `Ctrl+e` を送信してカーソル位置を文字列の最後に移動させてから `BACK_SPACE` を送信している。また、送信数も30回にしているが、このあたりは環境によって調整が必要。

詳しくは[ドキュメント](https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_Key.html)を見ろ。
Cognos Analyticsで、マスター詳細を利用したレポート例① -リストにグラフを埋め込む-

#はじめに
Cognosのレポート開発をしていて、デフォルトの機能で便利なものがあるのにいまいち活用されていないと思うものがいくつかあるので紹介できれば、という投稿です。
その一つが「マスター詳細の関係」です。

この記事では下記のようにリストの中にグラフを埋め込み、マスター詳細を利用して各行の製品の数量に絞った折れ線グラフを表示しています。

#完成形
![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/0129a7d7-6849-b815-adf9-7c4825e9b1bd.jpeg)


#手順

## 1. メインリストの作成
まず最初にメインとなるリストを作成します。ここはいつものCognosのサンプルを使用しています。

![002.jpg](https://qiita-image-store.s3.amazonaws.com/0/146283/51298544-4b95-5f20-ecea-7cd1f9eda666.jpeg)


## 2. リストにグラフを追加する
ツールボックスから「視覚化」を選択し、リストの「製品」列と「数量」列の間にドラッグ&ドロップします。
![003.jpg](https://qiita-image-store.s3.amazonaws.com/0/146283/29d21c9f-e71f-3e29-77e8-884102b93c4e.jpeg)

## 3. 使用するグラフの選択
視覚化ギャラリーで、右上のプルダウンボックスを「グラフ」に変更し「クラスター折れ線」をグラフを選択します。
![004.jpg](https://qiita-image-store.s3.amazonaws.com/0/146283/eb95f2d0-1877-bd96-7932-343137992c05.jpeg)



## 4. グラフに項目を配置する
グラフで使用する項目を追加します。
Y軸に数量、主軸に製品、X軸に月キーを配置しています。
グラフが使用するクエリーは新しく定義し、リストが使用するクエリーとはわけてください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/146283/f54920b1-f68c-7697-3704-5cf463a68ba7.png)


## 5. マスター詳細を定義
グラフを選択し、プロパティから「マスター/詳細の関係」をクリックします。
「リンクを新規作成」をクリックして表示されるリンクの線をクエリー1の「製品」とクエリー2の「製品」が紐づくように定義します。
![006.jpg](https://qiita-image-store.s3.amazonaws.com/0/146283/9f0e1f01-2eb6-e8a7-76e8-b8ac07292544.jpeg)

## 6. レポートを実行してみる
マスター詳細の定義は実はこれだけなので、必要最低限の設定は以上になります。
後は、レポートを実行して結果を確認してみてください。

## グラフのパロパティ設定
最初に紹介した完成形のリストでは、グラフのプロパティ設定を追加でいくつか変更しています。
ここはレポートの要件・見栄えに合わせて適宜、変更・設定してください。

- 高さを100pxに設定
- 凡例の表示を非表示に設定
- 軸のタイトルを非表示に設定
- X軸に配置している月キーに昇順のソートを設定

## 親階層でのリンク
製品のみで一意に紐付けられないデータの持ち方をしている場合は、グラフ用のクエリー2に製品ライン、製品タイプといった親階層のデータアイテムを追加し、リンクを定義してあげてください。
![007.jpg](https://qiita-image-store.s3.amazonaws.com/0/146283/1fe608c2-a074-83af-b518-c0bd2b34f193.jpeg)



#さいごに
マスター詳細を利用したレポートのチューニングに関してこちらで紹介されているので合わせてご覧ください。
[Cognos Analytics でのマスター詳細を使用したレポートのチューニング](https://qiita.com/shinyama/items/e45ee948139bbf675122)


#自己学習記事一覧
**Cognos Analytics をエンドユーザーの方に自己学習して頂くためのサイト**
https://qiita.com/shinyama/items/95885c7246dc413b6448
vimの改行を含まない行選択

自分向けの備忘録に書いときます。他にいいやり方があれば教えてくれると嬉しいです。

1.　選択する行に移動
2.　`０`で行頭に移動
3.　`w`で文字の行頭に移動
4.　`v`でヴィジュアルモード
5.　`shift+$`で行末まで選択
6.　`h`で改行の一文字を選択から除く
7.　あとは実行したいコマンドを実行
Houdini Apprenticeが起動出来ない問題の解決方法2019/4（ライセンスでエラーが出る）

#Production Build 17.5.173  •  Windows 

Houdini Apprenticeがライセンスインストール部分でエラーを吐いて起動が出来ませんでしたので、解決方法を書いておきます。
<img width="631" alt="コメント 2019-04-10 131908.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328760/d9f57c6e-cce5-a549-1c5a-b2ed9ba44a67.png">
起動したらこんな感じのエラーが出る人用です。
あと、License Administratorの、File -- Install Licenses　がグレーアウトしてる人用です。
あと、Install Licensesでログインしてもこんな感じでエラる人用です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/328760/ffe7ccaa-99b7-3972-8b88-17cca90bfd45.png)

~~まとめて言え~~


#対策
Houdiniの公式サイトからインストーラーをダウンロードしてきます。（[公式サイト](https://www.sidefx.com/download/)）
普通にインストール手順を踏んでいきます。
__無料版はここでApprenticeに切り替えましょう。__

![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328760/79a861ac-ce87-5d5b-4136-84a0afcc4295.png)

そのままインストールを勧めていきます。

このウィンドウが出てきたら、Server Informationをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328760/30b10d95-98d7-147e-8b32-68b96860aea7.png)

__・License server host__
__・License server code__
をメモっておきましょう。

そしたら、公式サイトに飛びアカウントメニューからServiceをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328760/f493515e-d094-f025-1f8e-0c109f35e22d.png)

左上のメニュー__License Manager__にある__Non-commercial Licenses__をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/328760/9f7455bf-f0db-fce1-bcba-76810a6167a7.png)

__sever name__と__sever code__に先程メモした__License server host__と__License server code__をそれぞれ入力します。　そのままGenerate Licenseをクリック。

クリックすると、Licenseが3行表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/328760/dcafcc03-8468-2ba0-a5d5-50b50e4d293d.png)

次は、またHoudiniに戻ります。
FileからManually Enter Keys...をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/328760/a7d77a48-d7da-8f27-960c-0cd959fea58d.png)

keyに先程生成したLicenseを1行ずつコピペしていきます。
5行ありますが、下の2行は空白でOKです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/328760/3b56c941-9dac-f919-a05f-b9a133d9c51f.png)

Acceptし、Successfullyが3つ表示され、すべて項目にチェックマークがついてれば完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/328760/98ddabf2-d955-1829-827a-bda8e98bf953.png)

あとはウィンドウを閉じてFinishすれば終わります。
これでHoudini Apprenticeが起動できるようになります。

#注意
インストール中に立ち上がったLicense Administratorではなく、インストール後に起動したものでは、Manually Enter Keys...等がグレーアウトしており、入力できないと思います。
面倒ですが、インストールからやり直さないと駄目なようです。

#おわりに
大学の講義で使うため、インストールをしようとしたら起動しない問題が起きたため書きました。　周りでも同じような問題が起こっているため、Qiitaにまとめた次第です。
php-master-changes 2019-04-09

今日は JIT のバグ修正、HAVE_STRERROR の条件コンパイル削除、ZEND_VM_KIND_SWITCH の場合に誤ったコードを吐いていた問題の修正、ビルドシステムの不要コード削除、変数代入処理のリファクタリング、FFI のテストこけの修正があった！

# 2019-04-09
## laruence:  Fixed bug [#77857](https://bugs.php.net/bug.php?id=77857) (Wrong result if executed with JIT)
- https://github.com/php/php-src/commit/c9fefb31fd06ed2b07345d1c1e9d00dd492399f2
- ext/opcache/jit で、JIT 有効時に計算結果がおかしくなる場合がある問題の修正
- 報告入れてるの [y-uti さん](https://twitter.com/y__uti/status/1115235058988736512)だ
- 乗算命令で型情報からレジスタ割当を行うかの判定コードと、ZVAL_COPY_VALUE の dynasm のマクロで宛先がメモリな場合の型判定コードをいじってるくさい？
- なお後者については後で Dmitry 御大が若干修正入れてる

## laruence: Fixed missed NEWS while merging
- https://github.com/php/php-src/commit/2f03c0aa72230eb787d20d77bf9f4f367bb3e081
- ↑の修正で間違って消しちゃってた NEWS エントリを復活

## petk: Remove HAVE_STRERROR
- https://github.com/php/php-src/commit/e6a6017f78878609b2885451b6046717f478c027
- [7.4~]
- HAVE_STRERROR の条件コンパイルを削除
- C89 で標準化されているので

## dstogov: Repare SWITCH VM
- https://github.com/php/php-src/commit/7b8212f4d119b1f055238b183092249a022a7841
- [7.2~]
- zend_vm_gen.php で、ZEND_VM_KIND_SWITCH の場合に誤ったコードを吐いていた問題の修正

## petk: Remove duplicated substitude for Makefile
- https://github.com/php/php-src/commit/8021d52fb6b36753ba1456acdae367c150a92e96
- [7.4~]
- ビルドシステムで、 configure.ac から PHP_SUBST(PHP_EXECUTABLE) を削除
- CLI の config.m4 で重複して入っていたので

## dstogov: Compare only "significant" bits
- https://github.com/php/php-src/commit/9c14cfdc78d3599537ef16ae116053c9c2b1448d
- ext/opcache/jit で、ZVAL_COPY_VALUE と ZVAL_COPY_VALUE_2 の dynasm のマクロで、コピー元/コピー先の型推論情報を比較するところで MAY_BE_ANY|MAY_BE_UNDEF の箇所の違いだけを見るようにしている

## dstogov: Micro-optimization
- https://github.com/php/php-src/commit/5fdee9394f5481459316c0e46a9ad8e25cab6134
- [7.4~]
- 参照代入処理のリファクタリング

## dstogov: Eliminated check for assignment to itself
- https://github.com/php/php-src/commit/ec5d4c79d28fa9e12a213e24b491c5e21673e5d7
- [7.4~]
- 自分自身への代入を特別扱いでチェックしてコピーを行わないようにしていたチェックコードの削除

## dstogov: Fixed ext/ffi/tests/044.phpt failure on 32-bit Linux
- https://github.com/php/php-src/commit/a5e86d82643e1fc718c356f9a6dc4a2daa31e7be
- [7.4~]
- ext/ffi で、32 ビット Linux でこけるテストがあったのを修正
rbenv の global バージョンが変わらなくて困ったこと 《global と local》

`ruby`のバージョン変更が効かない！！って困ったけど特に問題も見つからなくて
色々調べたら`rbenv`のことにちょっと詳しくなったっていうお話です。

予め断りますが、高度なお話は期待しないでください。

さて早速ターミナル操作ですよ、と・・・

```
❯ rbenv global 2.3.1

❯ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]
```
おんやぁ・・・？？？

```
❯ rbenv versions                           
  system
  2.3.1
* 2.5.1 (set by /hogehoge/.ruby-version)
```

あんれぇ・・・？？？

ということになったわけです。
困りました。

```
❯ which ruby                                                                       
/Users/username/.rbenv/shims/ruby
❯ cat ~/.zshrc 
# (bashなら ~/.bash_profile など)
中略
eval "$(rbenv init -)"
中略
```

`ruby`の読み込みパスが上記の通りなら
間違いなく`rbenv`が今使っている`ruby`を管理をしている。
一応、シェルのプロファイルの中を読んでみると
`rbenv`のパスが通っているはずなので
シェルはきちんと`rbenv`を読み込んで実行できている。
（というかターミナルで`rbenv`コマンド通ってるしね・・・。）
とりあえず大枠で`rbenv`はエラーなく正常動作しているはず・・・。
なのになぜ！？


さてこれはどういうことか。

#結論をいうと何も異常がない可能性があります。

以下を試してみてください。

```
❯ cd ~
❯ rbenv versions                                                                   
  system
* 2.3.1 (set by /Users/username/.rbenv/version)
  2.5.1
```

↑の状態は`rbenv`で`local`環境に設定された`ruby`バージョンを読んでいます。
つまりきちんとコマンド通り`global`バージョンの設定変更はできています。

**そう、初めからちゃんとバージョン切り替えできていたんです**

**・・・・`global`のね！**


##どういうことか説明しますと
そもそも`rbenv`は`ruby`のバージョン管理を目的としたソフトです。
（たぶんrb=rubyの environment=環境 の管理みたいなネーミング？）
通常に`ruby`をインストールすると
そのPCでは常時同じバージョンの`ruby`しか使えません。
しかし、`rbenv`を使い、`rbenv`フォルダ以下に
複数の`ruby`をインストール＝管理することで
プロジェクトごとに異なるバージョンの`ruby`を使い分けることができるというものです。


`global`というのは、そのPCがデフォルトで使うバージョンを設定することです。
で、`local`ってのがPCの中の一部、
例えば特定のプロジェクトファイル以下で使うバージョンを指定することです。
この`local`でのバージョン指定をしているのが`.ruby-version`というファイルです。
このファイルがあるフォルダ以下には
`.ruby-version`ファイルに記載されたバージョンの`ruby`が動きます。


さてここで先程までのターミナルのログを再確認みましょう
ローカルバージョンのログとグローバルバージョンのログをよく比較してみてください。

```
❯ rbenv versions  
* 2.5.1 (set by /hogehoge/.ruby-version)
* 2.3.1 (set by /Users/username/.rbenv/version)
```

お分かりでしょうか。

**set by以下が違いますね？**

これは`rbenv`がバージョンを参照している管理ファイルの所在です。
上のローカルバージョンでは各フォルダの`.ruby-version`
そしてグローバルバージョンでは`/Users/username/.rbenv/version`です。

わかってる方は記事の最初の方で即ツッコミ入れてたわけですね、、、
m9(^Д^)ﾌﾟｷﾞｬｰプスプス何やってんのこいつwww
とか言われてたわけです・・・orz



さてではこの２つのファイルの中身はというと・・・

```
❯ cat /hogehoge/.ruby-version
2.5.1
❯ cat /Users/username/.rbenv/version                                               
2.3.1
```
ものっすごいシンプル！！
たったこれだけの記載でバージョン管理がされてるんですね。
（他にもこのファイルを読み込む別のinitファイルあるかもしれませんけど）

謎は全て解けた！
謎も何も・・・`rbenv`のこと何もわかってなかったっていう恥ずかしい話でした。

---
そういえば金田一少年は近年37才サラリーマンになって
相変わらず事件に巻き込まれる生活してるみたいです。

##参考記事
今回こちらの記事を参考にさせていただきました。
https://qiita.com/eijish/items/ae16c2c3e4564ab5a6c5


##次回予告
というか実は前回（プライベート記事で）
`localhost`がiphoneから見られねぇ困った！の記事にすると予告してたのですが
そちらもこれから（個人的には割と必要性が高いと感じるので）環境テストしていく予定です。
ある程度まとまった検証ができ次第記事にしてみようと思います。
オレの技術書典６のサークルチェックリストをさらす


技術書典６ | サークルチェックリスト(2019/04/10時点)

* コンテナー関係多し

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/e2609892-c55a-33b1-63ba-56c5ba8981a1.png)

技術書典６ \| サークルチェックリスト

**う44アルハンブラの畔**
*バルゴ*
*ソフトウェア全般*

**う46カエルと空**
*toshi0607*
*ソフトウェア全般*

**う47おとうふ工房**
*あおい*
*ソフトウェア全般*

**う48メンチコロッケカレー**
*山P、buchy*
*ソフトウェア全般*

**う50Japan Container Days**
*jacopen*
*ソフトウェア全般*

**う51すべてがM(icro)になる**
*ota42y*
*ソフトウェア全般*

**う60Develup**
*\@Clorets8lack*
*ソフトウェア全般*

**お04docker-machine**
*\@enakai00/\@_dr_asa*
*科学技術*

**お37POStudy ～アジャイル・プロダクトマネジメント研究会～**
*fullvirtue*
*ソフトウェア全般*

**か08tomo-makes**
*tomo-makes*
*ソフトウェア全般*

**か53みさきとミギー**
*youchan*
*ソフトウェア全般*

**け33まいにちがきんようび。**
*しゅーくりーむ*
*ソフトウェア全般*

**こ15EREX工房**
*夜道*
*ソフトウェア全般*

**こ38めがねをかけるんだ**
*Keiji ARIYAMA*
*ソフトウェア全般*

**こ39Rosenblock Chainers**
*cafeunder*
*科学技術*

**こ40データリファインメント**
*カレーちゃん*
*科学技術*
GitHub EnterpriseとSlackを連携させる

# GitHub EnterpriseとSlackを連携させる

## Slackアプリインストール
通常のGitHubのSlackアプリは、Enterprise版には対応していないとのこと。
https://slack.com/apps/A8GBNUWU8-github
>Using an older version of GitHub and Slack? Installing the new integration will allow you to migrate subscriptions from legacy versions. GitHub Enterprise and Slack Enterprise Grid are not yet supported.

GitHub Notifications (Legacy)をSlackにインストールする
https://slack.com/apps/A0F7YS2SX-github
![QS_20190401-165007.png](https://qiita-image-store.s3.amazonaws.com/0/281587/2d204b13-f79a-46ad-5fc8-835c529b5a43.png)

## Slackと連携させる
1．SlackのAppsの管理サイトにアクセスする

```
https://XXXXXX.slack.com/apps/manage
```
※XXXXXXは任意のワークスペース名

2. GitHub Notifications (Legacy)を選択
![QS_20190403-094741.png](https://qiita-image-store.s3.amazonaws.com/0/281587/f78f288b-50e9-427b-b15c-7a7f0cf9bf4f.png)


3. 設定を編集を選択
![QS_20190402-164419.png](https://qiita-image-store.s3.amazonaws.com/0/281587/155a2580-79ca-14e8-7784-295e8868241b.png)

4. Webhook URL をコピーする
![QS_20190402-164010.png](https://qiita-image-store.s3.amazonaws.com/0/281587/ac3401be-4736-120c-3eca-fe783dcff77e.png)

5. GitHub Enterpriseにアクセスし、設定したいリポジトリの「Settings >> Hooks >> Addwebhook」を選択
![QS_20190402-164605.png](https://qiita-image-store.s3.amazonaws.com/0/281587/9655e56b-7d81-210a-cd10-206f6219b342.png)

6. Payload URL に手順4.でコピーしたWebhook URLを貼り付け。

7. Content typeを`application/json`を選択し、`Add webhook`を押下する
![QS_20190403-093903.png](https://qiita-image-store.s3.amazonaws.com/0/281587/a6af3138-8c77-7fcc-42b1-dd24cdcfef04.png)
Unityエディタからadbコマンドを実行する

## はじめに
PCからAndroidデバイスを操作する時にadbコマンドをよく使うのですが、
adbコマンドを使うためだけにコマンドプロンプトやPowerShellを立ち上げるのはちょっとめんどくさい。

そこで、エディタ拡張を利用して 
**Unityエディタ上からadbコマンドを実行** できるようにしてみました。

## 環境
Windows 10
Unity2018.2.12f1

## adb.exeのパスを確認する
C#からadbコマンドを実行するためには **adb.exe** のパスが必要になります。

PATHにadb.exeを通している場合、コマンドプロンプト上で以下のコマンドを実行するとadb.exeの場所が確認できます。

```
where adb.exe
```

<br>
自分の環境では以下のパスが表示されました。

```
C:\NVPACK\android-sdk-windows\platform-tools\adb.exe
```

## C#からadbコマンドを実行する方法
C#から以下のメソッドを呼ぶとadbコマンドが実行できます。

```
System.Diagnostics.Process.Start(adb.exeのパス,コマンド)
```


たとえば、```adb reboot``` を実行したいときはC#で以下のメソッドを呼びます。


```csharp
System.Diagnostics.Process.Start(@"C:\NVPACK\android-sdk-windows\platform-tools\adb.exe", "reboot");
```

## Unityのメニューからadbコマンドを実行
Unityエディタ拡張を利用して、メニューからadbコマンドを呼び出せるようにしてみます。

```csharp:EditorAdbCommand.cs
using UnityEditor;
using System.Diagnostics;

public class EditorAdbCommand
{
    [MenuItem("ADB/Reboot")]
    static void AndroidReboot()
    {
        Process.Start(@"C:\NVPACK\android-sdk-windows\platform-tools\adb.exe", "reboot");
    }
}
```

<br>
メニューの ADB/Rebootを選択すると ```adb reboot``` が実行され、Android端末に再起動がかかるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/e37ae3dd-9ac8-594f-be53-7ab44582347e.png)
Docker入門記事まとめ（個人用メモ）

###### 目的：基本的なDocker利用方法がわかるようになること

# 入門
- [いまさらDockerに入門したので分かりやすくまとめます](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1)

# インストール
- [Windows10 Home（Toolbox利用）](https://qiita.com/KIYS/items/8ac37f6757a6b7f84569)
    - Windows ＝＞（OracleVM）＝＞Linux＝＞Docker
- [Windows10 Pro（Docker for Windows利用）](https://qiita.com/ksh-fthr/items/6b1242c010fac7395a45)
- [Mac（Docker for Mac利用）](https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81)

# コマンド（レガシー含む）
- https://qiita.com/zembutsu/items/6e1ad18f0d548ce6c266

# Dockerfile作成
- [超入門](https://qiita.com/nl0_blu/items/1de829288db2670276e8)
- [効率的に安全な Dockerfile を作るには](https://qiita.com/pottava/items/452bf80e334bc1fee69a)

# Docker Compose
- [docker-compose コマンドまとめ](https://qiita.com/wasanx25/items/d47caf37b79e855af95f)

# MySQL連携
- [MySQLデータ初期化](https://qiita.com/moaikids/items/f7c0db2c98425094ef10#initdatacsv)
- [docker-compose でMySQL環境簡単構築](https://qiita.com/A-Kira/items/f401aea261693c395966)

# Docker Hub
- [公式サイト](https://hub.docker.com/)
#jq コマンドで #JSON 配列の個数を調べる例

# flat array

```
$ echo '["a","b","c","d","e"]' | jq '. | length'
5
```

# nested array

```
$ echo '[["a","b","c","d"],["e"]]' | jq '. | length'
2
$ echo '[["a","b","c","d"],["e"]]' | jq '.[] | length'
4
1
```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1157








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
初心者のための再帰関数

　初心者にとって再帰関数はわかりにくいものです。
　入門書などの「再帰関数」を見ると、フィボナッチ数などが例に挙がっていますが、そもそも「フィボナッチ数って何?」と、謎が深まるばかり。

　そこで、もう少し判りやすいところで再帰関数を使ってみます。ここでは、「数字1234567を、文字列1,234,567にする」という処理を行います。

####どんな処理を行うのか文章にしてみる
1. 与えられた数字から下位3桁(1000で割った余り)を切り出す。 1234567 → "567"
2. まだ上の桁があるので、先ほど切り出した文字列の頭にカンマ(,)をつける。　"567" → ",567"
3. 3桁より上の桁(1000で割った値)から、再び下位3桁を切り出す。　1234 → "234"
4. まだ上の桁があるので、切り出した文字列の頭にカンマ(,)をつける。　"234" → ",234"
5. 2.で作った文字列とつなげる　",234,567"
6. 6桁より上の桁(さらに1000で割った値)があるので、再び3桁を切り出す。　1 → "1"
7. もう上の桁がないので、5.で作った文字とつなげて終了　"1,234,567"

　この流れを見ると、元の数字が何桁になっても、
1. 下3桁切り出す
2. カンマをつける
3. すでに作った文字列とつなげる
　を繰り返すことで、所望する文字列が得られそうです。

####プログラムにしてみる

```Swift
func commaNumber(number: Int, low: String = "") -> String {
    if number < 1000 {
        return String(number) + low  // (1)
    }
    let last3Keta = number % 1000 // (2)
    let last3KetaString = ("000" + String(last3Keta)).suffix(3) // (3)
    let newlow = "," + last3KetaString + low // (4)
    return commaNumber(number: number / 1000, low: newlow) // (5)
}

commaNumber(number: 1234567) // 1,234,567
```

(1)　numberが1000未満であれば、numberを文字列にして、下位文字列とつなげた文字列を返す(再帰処理の終了)。
(2)　numberを1000で割ることで、下位3桁を切り出す。
(3)　下位3桁を文字列にする。このとき、numberが100未満だと3桁にならないので、頭に"000"を付け、下位3桁分だけ取り出している。
(4)　先頭にカンマをつけ、末尾に下位文字列をつなげる。
(5)　numberを1000で割った値と(4)で作った文字列を、commaNumberに渡す(再帰処理)。

　という処理になります。

　この処理は単純な繰り返しなのでforループでも実現可能ですが、再帰処理の入門には良いのではないでしょうか。

　なおこの処理は、公開アプリなどでは使わない方が良いです(多言語化をサポートしたライブラリを使うべき)。
Laravel DBのint型のカラムがstring型で取得される

ここ2、3日ハマっていた「DBのint型のカラムがstring型で取得される」現象の原因がわかりました。
### 現象
int型のカラムの取得がstringになってしまう。
### 原因
- SQLServer固有の問題
- pdo_sqlsrvだけ、intのカラムのデータをstring にキャストしてしまうようでした。
https://github.com/laravel/framework/issues/11780

### 解決方法
config/database.php のsqlsrvの記述に、`options`を追加。

```
'sqlsrv' => [
            'driver' => 'sqlsrv',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '1433'),
            'database' => env('DB_DATABASE', ''),
            'username' => env('DB_USERNAME', ''),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'options' => array(
                PDO::ATTR_STRINGIFY_FETCHES => false,
                PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true
            )
        ],
```
Android MVVMについて

## はじめに
AndroidをMVVMで実装するようになり、そもそもMVVMてなんだと思い調べました。
自分の理解と考えをAndroidの落とし込んで記事にします。 ← そんなに大層なものではないw

## MVC
※MVCは使う場面やフレームワークによってニュアンスが異なっています。

一般的に言われるMVCは何かを[Wikipedia](https://ja.wikipedia.org/wiki/Model_View_Controller)で調べてみる、そして自分なりに言い換えると

```
▪️View
モデルのデータを取り出してユーザが見るのに適した形で表示する要素で、UIへの出力を担当する。

▪️Controller
ユーザからの入力（通常イベントとして通知される）をモデルに伝える要素で、UIからの入力を担当する。
モデルに変更を引き起こす場合もあるが、直接に描画を行ったり、モデルの内部データを直接操作したりはしない。

▪️Model
そのアプリケーションが扱う領域のデータと手続きを表現する要素。
また、データの変更をビューに通知するのもモデルの責任である。
```

▪️図で表した場合
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177058/ac9faeb2-4d2e-fcb0-1055-e0c73c165529.png" width="400"/>
▪️Androidで表した場合
<img width="600" alt="スクリーンショット 2019-04-10 12.09.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177058/a83b0ad9-367c-3ab1-7b90-e8100fc24ae6.png">

### 問題点
ViewがActivity・Fragment　→　状態に関する情報を保存する必要がある
ControllerもActivity・Fragmentにある　→　Viewと混在している
ViewとControllerの役割が肥大する

## MVVM
また[Wikipedia](https://ja.wikipedia.org/wiki/Model_View_ViewModel)を読んでみる、そして自分なりに言い換えると

```
▪️View
アプリケーションの扱うデータをユーザーが見るのに適した形で表示し、ユーザーからの入力を受け取る要素。
ViewModelからパラメータ変更の通知を受け取り、パラメータの参照をする。
Viewそのものに複雑なロジックと状態を持たないのがMVVMのViewの特徴。

▪️ViewModel
ViewとModelの間の情報の伝達と、Viewのための状態保持のみを役割とする要素。
Viewを描画するための状態の保持する。
Viewから受け取った入力を適切な形に変換してModelに伝達する。

▪️Model
そのアプリケーションが扱う領域のデータと手続きを表現する要素。(APIとか)
アプリケーションのドメインを担う。
ViewModelにデータ取得を通知する。
```

▪️図で表した場合
<img width="236" alt="スクリーンショット 2019-04-11 0.45.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/177058/6eba5905-15dc-cb82-d101-80fa64632890.png">
▪️Androidで表した場合
<img width="600" alt="スクリーンショット 2019-04-10 13.02.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177058/d20ce24a-a39c-3c19-06e1-e381f967e2ed.png">

### 

### メリット
各レイヤーは自身の役割のみに集中できる(他のクラスの挙動を意識する必要がない)。
ビジネスロジックの実行と画面のオペレーティングを混同することがなくなる。

## 最後に
MVVMにはよくデータバインディングという言葉が使われますが、上記で記載した役割をViewModelが果たし、「関心の分離・依存関係の切り離し」ができていれば、MVVMであると思っています。
データバインディングは、あくまでも手段だということです。

## 参考にしたサイト
https://ja.wikipedia.org/wiki/Model_View_Controller
https://ja.wikipedia.org/wiki/Model_View_ViewModel
https://qiita.com/yuutetu/items/ea175b73e1dbbfd355db#view
https://qiita.com/homyu/items/046c9a43b15b9e376198

## 他の記事
https://qiita.com/zakimiiiii/items/2d0de51bc37f8e3789e0
ABC - 103- A&B&C

#AtCoder ABC 103 A&B&C
[AtCoder - 103](https://atcoder.jp/contests/abc103)

#A問題

 - 配列に格納してソート
 - ソートした順に作業

```java
	private void solveA() {
		Scanner scanner = null;

		try {
			scanner = new Scanner(System.in);
			int[] wk = new int[3];

			for (int i = 0; i < wk.length; i++) {
				wk[i] = scanner.nextInt();
			}

			Arrays.sort(wk);
			int res = Math.abs(wk[0] - wk[1]) + Math.abs(wk[1] - wk[2]);

			System.out.println(res);

		} finally {
			if (scanner != null) {
				scanner.close();
			}
		}
	}
```

#B問題

 - kyotoという文字列の最後の文字を最初に持っていって循環させる
    - kyoto
        - okyot
            - tokyo
                - .....

 - 一文字ずつ判定しても何とかなるけど、、、
    - 文字列Tは文字列Sの長さを超えることはないので、　`kyoto+kyoto=kyotokyoto`　としてしまって `kyotokyoto` のなかに文字列Tが含まれるのかを判定するのが早い

```java
	private void solveB() {
		Scanner scanner = null;
		String s;
		String t;

		try {
			scanner = new Scanner(System.in);
			s = scanner.next();
			t = scanner.next();

			s = s + s;

			System.out.println(s.contains(t) ? "Yes" : "No");

		} finally {
			if (scanner != null) {
				scanner.close();
			}
		}
	}
```

#C問題

$f(m) \; =\; (m \; mod \; a_1) \; + \; (m \; mod \; a_2) \; +...+ \; (m \; mod \; a_N)$

 - $f(m)$ を最大化したい
    - 細かく見ると
        - $(m \; mod \; a_i) $ の最小は $(m \; mod \; a_i) =0$
        - $(m \; mod \; a_i) $ の最大は $(m \; mod \; a_i) =a_i-1$  <-  $a_i$の余りなので
    - $f(m)$ を最大化するには、 $(m \; mod \; a_i) $ が最大化できればよい

 - $m = a_1 × a_2 × · · · × a_N$ とすると、各 i について $(m \; mod \; a_i = 0)$ なので、$((m − 1) \; mod \; a_i = a_i − 1)$
    - $(N*A \; mod \; A)$ は $N$ によらず $0$ ...
 - $f(m − 1) = (a_1 − 1) + (a_2 − 1) + ...... + (a_n − 1)$ となり、各項が最大値を取っている

```java

	private void solveC() {
		Scanner scanner = null;
		int numN = 0;

		try {
			scanner = new Scanner(System.in);
			numN = scanner.nextInt();
			int[] wk = new int[numN];

			int res = 0;
			for (int i = 0; i < wk.length; i++) {
				wk[i] = scanner.nextInt();
				res += wk[i] - 1;
			}

			System.out.println(res);

		} finally {
			if (scanner != null) {
				scanner.close();
			}
		}
	}

```
Unityでシーン一覧をFavoritesに登録しておくと楽

毎回シーン探すの面倒で、これがあるとらくだなぁと思ったのでメモ

![favorite_480.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15000/77bd3ef6-d5b6-f60a-1c91-873bd56fc761.gif)


1. 検索窓に `t:Scene` と記述.
2. スタートボタンを押す
3. 名前を登録
curl -F (--form) で @ から始まる文字列を POST する方法

## @ が先頭にあるとファイルとして認識されてしまう...
curl で `-F` オプションを使うと、curl がよしなに MIME type を `multipart/form-data` に設定してくれて、key=value 形式で POST することができます。
...が、`@ (アットマーク)` から始まる文字列は必ずファイルとして認識されてしまいます... orz

```
$ curl -F key=@val http://atsign.stringde.post.shitai.co.jp
curl: (26) couldn't open file "val"

$ curl -F "key=@val" http://atsign.stringde.post.shitai.co.jp
curl: (26) couldn't open file "val"

$ curl -F 'key=@val' http://atsign.stringde.post.shitai.co.jp
curl: (26) couldn't open file "val"
```

上の例は抽象的にしましたが、こういう風に例えば単価情報を送りたい。というケースもあるかもしれません。(@ が単価を表すとかの [まとめはこちら。](https://qiita.com/att55/items/cb3965f4967b360bf438))

```shell
$ curl -F "unit_price=@100" http://atsign.stringde.post.shitai.co.jp
```

## --form-string オプションを使えばできる
curl `-d` オプションで、`application/x-www-form-urlencoded` 形式で POST するしかないかな〜と思っていましたが、`--form-string` なるオプションを curl は用意してくれていました。

```text
To send a field value literally without interpreting a leading '@'
or '<', or an embedded ';type=', use --form-string instead of
-F. This is recommended when the value is obtained from a user or
some other unpredictable source. Under these circumstances, using
-F instead of --form-string would allow a user to trick curl into
uploading a file.
```

https://curl.haxx.se/docs/manual.html

これで解決。

```shell
$ curl --form-string "unit_price=@100" http://atsign.stringde.post.shitai.co.jp
```
[備忘録]サーバーとSSH通信できるようにする

# サーバーとSSH通信できるようにする
公開鍵を作って、サーバーの設定ファイルに追記したらOK

1. 公開鍵を作る

```
ssh-keygen -t ed25519 -N "" -C "makimatsun" -f ~/.ssh/makimatsun
```

2. サーバーに接続する設定を追加

```
code ~/.ssh/config
```
で開いたConfigファイルに

```
Host makimatsun
    HostName pdb.maki-matsun.biz
    Port 3771
    User ubuntu
    IdentityFile ~/.ssh/makimatsun
```
を追記する

3. 公開鍵は

```
cat ~/.ssh/windsscore.pub 
```
で取得できる

```
ssh-ed25519 AAAA~~~~~~~~~~~~~~~~VE8k/Gsgs makimatsun
```
みたいな感じ
サーバーのファイルに追記

4. サーバーに接続するコマンドは

```
ssh makimatsun
```
ubuntuで繋がる

```
ls -la .ssh
```
で一覧がとれるからcatコマンドで確認可能
(mac)SourceTreeでremote: Invalid username or passwordが表示

soucetreeを使ってpush使用としたところpasswordを求められた。嫌な予感がしたが、passwordを入力。案の定、間違えてしまい。remote: Invalid username or passwordが連呼された。
理由は間違ったアカウント情報だからだめーということだがハマりにはハマったのでメモとして残す。
#アカウントの設定
アカウントの設定がなかったので改めて設定しようとした。
soucetreeが有効になっている状態でメニューバー > soucetree > 環境設定　> アカウント
bitbucketのアカウントでsoucetreeを使用しているので　bitbucketを選択。
しかし、うまく認証画面にいかない。うそだろと、12回試したとこで諦めた。

#高度な設定に登録されているホスト名を削除
高度な設定に登録されているホスト名を削除を削除して、リモートにアクセスするといけるとあったので
とりあえず削除して　soucetreeが有効になっている状態でメニューバー > soucetree > 環境設定　> 高度な設定
2つホストに登録があり、2つとも削除してリモートにアクセス。
remote: Invalid username or passwordが連呼され、諦めた

#KeyChainAccess
KeyChainAccessにsoucetreeに設定したpasswordがあるとの記事を取得！！！

https://qiita.com/okamotoke/items/141ecf280c84f93c8d4e 
@okamotokeさんありがとうございます。

KeyChainAccessを開きみると、、色々これまでみたサイトのベーシックが保存されていた。どれだろうと確認している
soucetreeにアクセスするbitbucketのhostが記載された項目発見。
これを一回削除して、リモートへアクセスするとpasswordの要求があり、再度設定。
これでなんとかpush完了。




soucetreeでpasswordが出たら鬼門
Swiftのasってなんだ？

## `as` とは？
型を変換することを意味します。

###詳しく
例えば生き物を示すクラス`Creature`と
これを継承した`Person`があるとします。

```swift
class Creature { ... }
class Person: Creature { ... }
```

`Person`クラスをインスタンス化すると`Person`型のインスタンスが出来上がります。

```swift
let person = Person() //personはPerson型
```

この`person`を`Creature`型の変数に入れてみます。

```swift
let creature: Creature = person
```
すると変数`creature`は`Person`型から`Creature`型として認識されてしまい
`Person`型として扱えなくなってしまいます。

***もう一度`Person`型として扱いたい！***

そんな時に使うのが`as`です。

`as`を使って`Creature`型から`Person`型へダウンキャストします。

```swift
let personA = creature as! Person
```
これで`personA`は`Person`型として再度扱えるようになりました。
でも、ん？ よく見ると`as!`の`!`ってなんだ？

## as、as!、as?の違い
いづれにおいても`as`は型を変換することは間違い無いですが
**必ず変換に成功するか？**
この条件によってどれを使うかが変わってきます。

###必ず成功する場合
`Person`型は`Creature`型を継承しているため必ず型の変換に成功します。

```swift
let creature = Person() as Creature //asでOK!
```

###必ず成功するとは限らない場合
`Creature`型のインスタンスは必ず`Person`型であるとは限りません

```swift
//as!かas?でないとだめ！
let person = Creature() as? Person //もし変換に失敗したらnilが返る
let person = Creature() as! Person //もし変換に失敗したらアプリがクラッシュ
```
MacのMAMP上でWordPressを立ち上げる


## 背景

WordPressを使って自分のテーマをカスタマイズする勉強をしている. 最初, プライベート用のMacでサーバーを立ち上げていたが, 研究室のPCでも編集がしたくなった. そこで, 実際にWordPressを動かす環境を整えた.

## 方法

### MAMPをインストールする

```sh
brew cask install mamp
```

もうBrewfileにいれてしまう.

### WordPressをダウンロードして, MAMPに入れる.

[https://ja.wordpress.org/download/](https://ja.wordpress.org/download/)からダウンロードする. 自分は[作りかけのもの](https://github.com/adshidtadka/wordpress)があったため, それを利用.

ダウンロードしたものをフォルダごと`/Applications/MAMP/htdocs`に入れる.


### データベースを設定する

まず, MAMPを起動してポートの設定をして起動する.

![port.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253063/ad130d40-cb44-a949-cde1-29297f6c4811.png)

次に, 以下の画面にてデータベースを作る.

![database.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253063/4a57f4ac-4b67-11e6-090f-47dc887e6159.png)

### いろいろ設定する

最後に, [http://localhost/wp](http://localhost/wordpress)にアクセスするとサイトのいろんな設定ができる.

## 感想

割と一瞬でできた.
vagrant, ubuntu, TensorBoardメモ

この辺のキーワードでTensorBoardが使えないときの備忘録として書いておきます。


##いつも引っかかる状況

vagrant + ubuntuでtensorflow(cpu)で学習を実施
↓
TensorBoardでグラフ見てみたろ！！！ｸﾛｰﾑﾋﾗｷｰ
↓
"TensorBoard 0.4.0 at http://vagrant-ubuntu-trusty:6006 (Press CTRL+C to quit)"？　とりあえずそのままURLコピペしたろ！！
↓
ﾌｧｯ！？ページが表示されんやんけ！！


ここまでが最初の私でした



###①VagrantFileをみてみる

```
config.vm.network "private_network", ip: "192.168.33.10"
```

URLは
"http://vagrant-ubuntu-trusty:6006"
じゃなくて
http://192.168.33.10:6006
でしたね


###②tensorboardコマンドをみてみる
いろんなサイトや質問版に書いてありますが
tensorboard --logdir=(ログファイルのディレクトリまでの「フルパス」)
でうまくいきました

以上です
condaでよく使うコマンド

###仮想環境の作成

```
conda create -n <envName> <modules...>

# 例 py37 という名前でPython 3.7 + PyTorch 1.0 (cpu)の環境を作る
conda create -n py37 python=3.7 pytorch torchvision -c pytorch
```
###仮想環境の複製
```
conda create -n <newEnvName> --clone <oldEnvName>
```
###仮想環境の一覧を表示
```
conda info -e
```
###仮想環境に入る
```
conda activate <envName>
```
###モジュールをインストール
```
conda install <modules...>

# スペース区切りで複数同時に指定可、-y を付けるとyes/noを聞かれない
# 例 minicondaの場合に、jupyter notebookを使えるようにする
conda install jupyter -y
```
###モジュールの一覧を表示
```
conda list
```
###モジュールをすべてアップデートする
```
conda update --all
```
jQueryでドロップダウンメニューを作成する

# 課題
`hover`を使ったドロップダウンメニューの作り方をアレンジして、`on`を使って書き直してみる。

# 仕様
親メニューをクリックすると子メニューが出現し、さらに親メニューをダブルクリックすると子メニューが閉じる。

# メモ

-  `on()`メソッドは、複数のイベント定義ができる。  
`$('要素').on({ イベント1, イベント2});`  
例えば、

```js
$('#button').on({
  'mouseenter': function(){
      alert("マウスオーバーされた");
  },
  'mouseleave': function(){
      alert("マウスアウトした");
  }
});
```
- イベント1とイベント2両方のキーにイベントタイプ`click`を指定すると動かなくなる。（当たり前…）

# ファイル構成
## HTML
```html
<body>
        <div id="main">
            <ul class="menu">
                <li>menu 1</li>
                <li>menu 2
                    <ul class="sub">
                        <li><a href="#">menu 2-1</a></li>
                        <li><a href="#">menu 2-2</a></li>
                    </ul>
                </li>
                <li>menu 3
                    <ul class="sub">
                        <li><a href="#">menu 3-1</a></li>
                        <li><a href="#">menu 3-2</a></li>
                    </ul>
                </li>
                <li>menu 4
                    <ul class="sub">
                        <li><a href="#">menu 4-1</a></li>
                        <li><a href="#">menu 4-2</a></li>
                        <li><a href="#">menu 4-3</a></li>
                    </ul>
                </li>
            </ul>
        </div>

        <script src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>
        <script src="app.js"></script>

    </body>
```
## CSS
```css
#main{
    margin: 100px auto;
}
ul{
    list-style-type: none;
    margin: 0;
    padding: 0;
    color: #fff;
}
ul.menu li{
    float: left;
    position: relative;
    margin: 0 0 0 1px;
    padding: 5px;
    width: 200px;
    background: #555555;
    display: block;
}
ul.sub{
    display: none;
    position: absolute;
    margin-left: -6px;
    padding: 0;
}
ul.sub li a{
    padding: 5px 10px;
    margin-left: -5px;
    margin-right: -5px;
    margin-bottom: -5px;
    display: block;
    color: #fff;
}
ul.sub li a:hover{
    background: #ff9900;
    text-decoration: none;
}
```
## jQuery
```js
// 
// $(function(){
//     $("ul.menu li").hover(function(){
//         $("ul.sub:not(:animated)",this).slideDown();
//     }, function(){
//         $("ul.sub",this).slideUp();
//     });
// });

$(function(){
    $("ul.menu li").on({
        'click': function(){
            $("ul.sub:not(:animated)",this).slideDown();
        },
        'dblclick': function(){
            $("ul.sub:not(:animated)",this).slideUp();
        }
    });
});
```
# 参考
> [jQueryでドロップダウンメニューを作成する方法](https://www.terakoya.work/jquery-drop-down-menu-build/)
> [jQuery on() イベントの種類](https://qiita.com/temori1919/items/bcbfc4a93301ef902d1d)
> [jQueryでクリックイベントで処理を実行する：on(), click()](https://uxmilk.jp/10065)
> [ウェブカツ](https://webukatu.com/?afid=p5lxu1kvh03rayd2ctjsw4e9bgzq8nom)
herokuでrails consoleを使う

1. heroku にログインし、ダッシュボードをへアクセス
2. アプリを選択
3. 画面右上のMOREをクリック
4. メニュー内のRun consoleをクリック

![スクリーンショット 2019-04-10 10.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/54f35852-ecc9-bd38-b96f-626713a5c5ce.png)

5.画面下に表示されるフォームにconsoleと入力し Run ボタンをクリック
![スクリーンショット 2019-04-10 10.37.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/b603c09c-f436-4682-006a-dc7f3c3529d0.png)

6.rails consoleが起動するので後は使うだけ

![スクリーンショット 2019-04-10 10.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/9cae2dc7-3a76-6a41-fa01-90e4e5e431f8.png)
[Dev. Op.] Azure Pipelinesでビルド・テスト・リリースなどの管理

AzureのPipelinesを使ってCI (Continues Integration) を管理しみます。ASP.Net Core + Azureで開発している方々用のまとめです。

# CIとは

CI=Continuous Integration。日本語では継続的インテグレーション。レポジトリーに対して都度（トリガーを設定）自動化されたビルド・テスト・リリースなどのワークフロー実行することです。

# Azure Pipelinesとは

Azure PipelinesはCIをAzure上でよろしくやってくれるサービスになり、Azure DevOpsサービスの1メニューです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/85904604-fe5a-d307-b56b-326a097ad0fa.png)


https://azure.microsoft.com/ja-jp/services/devops/pipelines/ こちらを参照

# ワークフローを自動化
色々なワークフローを自動化することができるのですが、今日はいくつかいつも使っているフローに関してまとめます。

## 1. マスターにプルリクエストしたら自動でビルド

Buildを選択して、右上のNewをクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/20fbd5cb-7fd0-8b74-5b04-0ad928540717.png)

今回はAzure Repos Gitを使用。　

### YAML
YAML (Ain’t Markup Language) = 構造化されたデータを表現するためのフォーマットです。設定ファイルなどの用途でよく使われ、今回のビルド設定もYAMLを使います。

次はRepoを選択します。このプロジェクトには1個しかないので、Corporate Siteを選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/aad142b8-d994-63e6-2366-2e42e40f111c.png)

ベーシックなYAMLファイルが生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/df535baf-fcb2-5cf9-65bb-d786fa27fa76.png)

詳細はこちらを参照　https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/dotnet-core?view=azure-devops

これで一旦Azure DevOp上でASP.Net Coreアプリケーションのビルドを行うことができます。

## 2. ビルドされたアプリケーションをWeb Appsにリリースする。

リリースする先であるAzure Web Appsを事前に立ち上げておきます。
Azure Web Appsはこちらを参照。　https://azure.microsoft.com/ja-jp/services/app-service/web/

リリースタブから、Newをクリックします。今回はAzure App Service deploymentを選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/b6c999d5-3e63-4bef-b970-13661d90cd41.png)

Artifactとステージが作成されます。 Artifactはパッケージになります、ここで指定したパッケージはビルドされた　"_Corporate Site"になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/952a87f8-1292-a1f5-40a2-03402a70b667.png)

常に最新のビルドバージョンをリリースするように指定しています。この設定はテストではOKなのですが、常に自動的に最新バージョンが自動でリリースされてしまうのはよくないかもしれません。なので、バージョンを選択することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/7a77316f-0ea7-0cd3-4542-3f25b73fcc49.png)

Artifactsの右上にある雷アイコンをクリックするとトリガーを選択することができます。今回はビルドされたものを自動的にリリースしたいので、 Continuous deployment triggerをEnableにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/b658e603-65e3-3271-65ec-c24df3bed28b.png)

トリガーはこれでセットできました。次はステージ内にあるアクションタスクを指定します。　Deploy Azure App Serviceの詳細を設定していきます。　同じAD内で権限があれば、Subscription, App type, App service nameをここで指定することができます。事前に立ち上げておいたWeb Appsを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/214f8097-d188-54de-6e01-0b44ef836b80.png)

ここで、マスターブランチを更新して、ビルド→リリースというワークフローが自動的に動くかテストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/b035beeb-87af-f289-b192-c2439469c8e8.png)

全部グリーンライトで行けました。

# 次

次にさらに細かい設定見ていきます。
型システムが機能しない場合とは？　例として Entity Framework について考えてみる

# 型システムの利点
型の利点とは、バグを入り込ませないためのものだといえるでしょう。つまり、制約をつけて保持できる状態や機能を絞るということです。だからこそ、単一責務など、そういう設計になり保守性も上がるということが期待されるわけです。

# null 参照の問題も関連
null とは参照先がないことです。参照元の型はあるでしょうが、参照先自体がないので実体がなく型がない、これが問題となります。正しく参照されている場合とそうでない場合がそれぞれ生まれる、それは極端に言えば、型を２つ持っているような状態です。だから、null チェックが必要になったりする。じゃ、いっそのこと null 自体をなくしてしまおう、という方向に進むわけです。

# 型システムがうまく働かない場合とは？
[以前にも書いた EF についての問題点](https://qiita.com/Ogacha/items/01e9cf46be28d2128f9e) に引き続いて、Entity Framework の問題点をまた書いてしまいますが、EF Core においては顕著です。リレーションシップによって別オブジェクトとの関連を持たせることが EF としての醍醐味なのですが、EF Core では、元祖初代 EF v1 のように遅延読み込みをしなくなりました。つまり、最初にデータベースから取得するときに Include メソッドによって、他テーブルから情報を取るかどうかを決めてしまうのです。ということは？　エンティティー モデル自体には参照があるのに、Include つけて呼ばれないと、ずっと null だということです。そうなのです。Include をつけるか否かで別の型のようになってしまうのです。同じ型なのに。もはや実質同じ型であるとは言えないような扱いになります。

# もちろん EF でなくても起こりうる
EF は一つの例として挙げましたが、型というのは安全性が担保されてこそ活かされるものです。設計の仕方によってそれは安全にも危険にもなります。大抵の言語は型を自作するようにできていると思います。結局、そこで大切なのは私たちが造り上げていく設計なのです。 だから、後々のためにも、どうすれば安全になるかを考えて開発したいものです。