Rhysのメモ帳

身につけた知識をただ垂れ流す場所です

レビュー: ぷしゅ よなよなエールがお世話になります

久々の投稿。

今回は勉強の話ではなく、タイトル通りレビューを書きたいと思います!

本の紹介

今回紹介したいのはこの本です。

ぷしゅ よなよなエールがお世話になります

ぷしゅ よなよなエールがお世話になります

よなよなエール」「水曜日のネコ」などを販売・製造しているヤッホーブルーイングの社長が書いた本で、エールビールを日本に普及させるために試行錯誤した話をまとめたビジネス書です。

感想

ビジネス書って聞くと大層なものをイメージするかもしれませんが、この本は他のビジネス書とは違ってすごく読みやすく「てんちょ」の経験が語られています。(「てんちょ」というのは著者井出さんのニックネームです)

もはやビジネス書というよりかは、ノンフィクションの小説、と言った方が伝わりやすいかもしれません 笑

さすがに小説ほど細かくストーリーがあるわけでもなく伏線が散りばめられているわけでもないですが、とにかく「てんちょ」の心が直接伝わってくるような、そんな文体です。

僕自身そこそこ本は読むのですが、ここまで惹きこまれた本は久しぶりでした。1


詳細は語りませんが、この本の中では「てんちょ」が経験から得た教訓をそれぞれの章でテーマに設定しながら、誰にでも伝わるような文章で読者にも大きな説得力を持って伝えてくれます。

例えば「スキルは挑戦しながら身につければいい」「ファンは100人に1人でいい」など、社会に出ていない自分2でさえ生きていく上での教訓となるような。

といっても堅苦しいものではなく、「てんちょ」のストーリーがあるからこそ柔軟に解釈ができて自らの体験に落とし込めやすい、そんな文章です。

読まなければ分からないと思いますし、簡単に読み切れるとも思いますので、是非みなさん読んでみてください!


  1. 「出会い系サイトで70人と実際に会ってその人に合いそうな本をすすめまくった1年間のこと」という本も非常におすすめです。

  2. まだ大学生です。社会に出たいような出たくないような…

配列のポインタについて

int a[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = a;

前提

・aは要素数10の int型配列で、初めから10個 int型を入れるスペースを用意
・pは配列のポインタで、「int型を指すもの」である宣言しかしていない。今回は int型配列のアドレスを代入


printf("a[0]: %d\n",a[0]);     // a[0]: 1
printf("p[0]: %d\n",p[0]);     // p[0]: 1
printf("a: %d\n", *a);         // *a: 1
printf("*p: %d\n",*p);         // *p: 1
printf("&a[0]: %p\n", &a[0]);  // &a: 0x7ffee04b4b40
printf("&p[0]: %p\n", &p[0]);  // &a: 0x7ffee04b4b40
printf("a: %p\n",a);           // a: 0x7ffee04b4b40
printf("&a: %p\n",&a);         // &a: 0x7ffee04b4b40
printf("p: %p\n", p);          // p: 0x7ffee04b4b40
printf("&p: %p\n",&p);         // &p: 0x7ffee04b4b20 (これだけ違う)

a[0] = 10;
printf("a[0]: %d\n",a[0]);  // a[0]: 10
printf("p[0]: %d\n",p[0]);  // p[0]: 10
printf("*p: %d\n",*p);      // *p: 10

p[0] = 100;
printf("a[0]: %d\n",a[0]);  // a[0]: 100
printf("p[0]: %d\n",p[0]);  // p[0]: 100
printf("*p: %d\n",*p);      // *p: 100

わかること

  • *p つまり「ポインタ p が指すもの」は配列の頭の要素 ( この場合だと 1 )
  • 配列のポインタは変数として配列と同様の形 ( この場合だとp[0] ) で入力できる ( *p = p[0] )
  • (ポインタでない)配列についてもポインタと同様の表記で値を返せる、つまり配列名はその配列のアドレスを表す ( a[0] = *a ) ( aはアドレス )
  • p はポインタだから a[0]が変われば p ( しつこいが「ポインタ p が指すもの」) も変わる。逆も然り ( a[0] = p[0] = a = *p )
  • 「ポインタが指すもの」が 配列なだけであって、そのポインタのアドレスと配列のアドレスは異なる ( &a != &p )

html, css, js 初心者がいきなり D3.js に手を出した話

おはようございます。

今日はタイトルの通り D3.js という、情報の可視化に適したライブラリを使う話をしたいと思います!

ただ今回も Chromium を手探ると同じように「javascript ? 聞いたことある」状態からスタートなのでとても苦労ですね...笑1

D3.js とは

D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.

以上は公式サイトからの引用です。

端的にいうと、データセットの様々な可視化の為にもの凄い役に立つ js のライブラリってことですね。

以下どんな可視化があるか例をあげますと、

f:id:RHys:20181103075039p:plain

こうやってノードごとの関係を可視化したり、

f:id:RHys:20181103075137p:plain

こうやって地図を色分けしたり、

f:id:RHys:20181103075214p:plain

こうやって頻出ワードを抽出したりすることができます。

すごいですよね。こちらから色々なデモが見られるのでよかったらどうぞ。


それでは次回以降 少しずつ D3.js のお話をしていきますね!


参考

D3.jsの概要と使い所について - Qiita


  1. 察しの良い方ならわかる通り、これも後期実習の一環 情報可視化とデータ解析です

git のキソのキソ 2

おはようございます。今日は寝坊してしまいました...

早起きを習慣化していきたいのですが、前日の夜にこなすタスクがしっかりあるとなかなか難しいですね。

(あと朝起きた時、尋常じゃないほど鬱なのどうにかしたい)

では、前回に引き続き git についてお話ししていきたいと思います!

リポジトリ

前回、git のホスティングサービスを利用してオンライン上に他の人と共有できるディレクトリを作成できることをお話ししたと思います。

この「他の人と共有できるディレクトリ」という表現は、実は間違っているんですよね 笑

どういうことか説明していきたいと思います。

ディレクトリとリポジトリ

そもそも git というのは、少し難しい表現にはなってしまいますが一言でいうと、「分散型バージョン管理システム」です。

どういうことかというと、サーバに Git というアクセスできるデータベースが一つある、というわけではなくて、サーバにも各々のPCにもデータベースが存在している、ということです。

ここでいうデータベースとは、ソースコードなど全てのデータのバージョンを管理・保持しているものを指します。1

データベースが貯蓄されているのが文字通り「リポジトリ」であり、当然のことながら「ディレクトリ」とは全く別物です。
( 筆者はこのことの理解をせずに git を使おうとしてはうまく行かず失敗ばかりしてました )

ここで、サーバにある Git というデータベースのことを「リモートリポジトリ」、各々のPCにある Git というデータベースを「ローカルリポジトリ」と呼びます。

実際の動き

ではどのようにデータがリポジトリに記録されていくのか、仕組みを簡単に説明します。実際に使うコマンドも記載しておきますね。

例えばあるプロジェクトに参加することになり、そのバージョンが git で管理されていたとします。

まずはそのリモートのリポジトリを自分のPCにコピーしてローカルリポジトリを作成します。
コマンド: git clone (リモートリポジトリのurl)

そこには今までにあった変更が全て記載されているので、もちろん自分のPCには今のディレクトリに、そのプロジェクトで作成されたデータと隠しディレクトリとして .git ファイルが存在します。

そのデータに自分が変更を加えたなら、ローカルリポジトリに変更した内容を書き加えます。
コマンド: git add (変更したファイル) 2

さらにリモートリポジトリにその変更を書き加える前に、その変更についてのコメントを書き加えます。
コマンド: git commit -m "こんな変更をしました"

ここまでしたらリモートに push したいところですが、筆者はその前にコンフリクトを起こさない為にも、先にリモートリポジトリの変更をローカルリポジトリに書き加えます。
コマンド: git pull origin master

これが全て確認できてから、リモートに push します。
コマンド: git push -u origin master

まとめ

これが git のキソのキソだと思います。これさえ分かっておけば、とりあえずは困らないかと。

正直これより先の git の基礎の内容は自分もまだ勉強中なので、理解し次第 git シリーズとしてまとめていきたいですね!

参考

まずはGitの仕組みを理解することから - Qiita


  1. もっとわかりやすくいうと、ソースコードが書き換えられたとき「それが変更されたこと」の記録もデータベースの一部です。

  2. git add .で全てのファイルを add できます。

git のキソのキソ 1

おはようございます!

身につけるためにも文章力を磨くためにもタイプ速度あげるためにも、少しでも学んだことがあれば記事を書いていこうと思いました。

Qiitaではないので何番煎じになろうとも自分のアウトプットのために書いていくのでご了承ください 笑

git

タイトルにもある通り、今日は git の使い方についてお話ししたいと思います。

とはいっても自分もこの前初めて触ったばっかりなのであまり詳しくはないのですが、理解したことだけつらつらと述べていきます。

git とは

git というのはご存知の方も多いと思いますが、あるプロジェクトのバージョン管理をしたいときに主に用いられる、オンライン上のディレクトリのようなものです。

どういうことかというと、
・自分の作成したデータをオンライン上のディレクトリにあげる
 ↓
・同じチームの人がそのディレクトリからそのデータを自分のPCまで引っ張ってくる
 ↓
・またその人が作成したデータをオンライン上のディレクトリにあげる
 ↓
・・・
このように、他の人とディレクトリを共有しながらプロジェクトを進めていける素晴らしい機能です!

git のサーバー

git はオンライン上でデータのやり取りをするので、そのためには専用のサーバが必要になります。

ただサーバーを立てるのって管理とか面倒ですよね。

ということで存在するのが git のホスティングサイトです。有名なやつですと、例えば GitHub とかですね。

こうしたホスティングサイトのサービスを利用することで、容易にプロジェクトを立ち上げられサーバの管理もしなくてすみます。

ただしサービスごとに利点・欠点は存在するらしいので気をつけましょう!
(正直、git 初学者には長所短所なんてわからないのです)


今日はここまでにします。この程度の執筆に30分かかるので、根気よくコツコツやっていきたいと思います。笑

参考

Git - Git のホスティング

atom-beautify のショートカットキーが使えない

自分は基本エディタにAtomを使用しているのですが、自力でインデントとか綺麗にするの超めんどくさい...

ということで atom-beautify を入れてみることにしました。

atom-beautify のinstall

普通に Atom エディタの設定から Install を選択。" atom-beautify " で検索すれば出てきます。

ショートカットキーの設定

毎回 Packages->Atom Beautify->Beautify から実行するのも面倒なのでショートカットキーを調べてみたら、Macでも「Control + alt (option) + b」で実行可能とのこと。
いざやってみると

" Could Not Find ' Uncrustify ' . The Program May Not Be Installed. "

と言われてしまいました。

なので、

brew install uncrustify

Uncrustify をインストールしましたが、ここから何をすればいいのかなかなか分かりませんでした。

(ちなむと Mac の場合、Finder で不可視ファイルを表示するのは「Command + Shift + . 」で出来ます。)

install した uncrustify をどこのディレクトリに置けばいいのか問題

はじめは/usr/local/Celler/uncrustify というディレクトリができていたので、これを/Users/(username)/.atom/packagesとかに移動させては「違うなぁ」ということを繰り返してました。
調べたら Windows の場合にのみ、展開して得た uncrustify.exe を packages 下に置かなければならないだけで Mac だと何も触らなくていいみたいですね。この原理はちょっとまだ分かっていないのでそのうちちゃんと調べたいです。

uncrustify の config 設定問題

どうやら Uncrustify はインストールするだけじゃなく、詳細なconfigを書いた uncrustify.cfg を用意して、Atom の Settings -> Packages -> Atom Beautify からそれぞれの言語に対して絶対パスを通す必要があるそうです。(自分は絶対パスの記入でタイポしていて無駄に悩んでいました笑)

自分の場合は/Users/(username)/下に/.uncrustify/uncrustify.cfgを作成しました。

config の内容は以下の記事を参考にさせていただきました。

qiita.com

ただ Uncrustify もアップデートされているようで、Uncrustifydefault config をみてみると、上記のサイトに掲載されている設定に一部誤りが含まれていたので、以下に自分の変更点をまとめておきます。

・align_number_left を align_number_right に変更
・L.314, L.338, L.597のコメントアウトに対して日本語であるせいかエラーが吐かれているので適当に改行
・L.485 D言語のテンプレート sp_before_template_paren が { number } になっていたので { ignore, add, remove, force } に変更 (自分は ignore を選びました)
・ mod_full_brace_if_chain = false の下に mod_full_brace_if_chain_only = false を挿入
・sp_func_call_user_paren = remove の下に sp_func_call_user_inside_fparen = ignore, sp_func_call_user_paren_paren = ignore の挿入

下二つは必要なかったかもしれませんが、default config にあってこちらになかったのを発見してしまったので一応追加しておきました。

まとめ

以上で atom-beautify とそのショートカットキーの導入が完了しました。
情弱すぎてこの実装にさえ一時間ほどかかってしまったのでちょっと悲しいです...笑
しかし、これからは快適な Atom 生活でどんどん強くなっていきたいですね!

自分のように困っている方の助けになれば幸いです。

参考

Macのショートカットキー - 不可視ファイルの表示/非表示を切り替える - PC設定のカルマ 
atomにatom-beautifyを入れた時にハマったこと | one more step
意識の高さからかコードフォーマッター設定を公開
PATHを通すために環境変数の設定を理解する (Mac OS X)
Atomエディタでatom-beautifyを使ってPHPのソースコードを整形する(追記あり) - そうだ車輪と名づけよう 7th
http://uncrustify.sourceforge.net/default.cfg

Chromiumを手探る 3

この記事は前回からの連載(?)です。よろしければそちらから。

タブがシークレットモードで開かなかった原因

前回設定した関数 NewEmptyTab() の中で

void NewEmptyTab(Browser* browser, Profile* profile){
  // incognitoとbrowser->profile()を一致させる?
  bool incognito = profile->IsOffTheRecord();
  PrefService* prefs = profile->GetPrefs();
  if (incognito) {
    if (IncognitoModePrefs::GetAvailability(prefs) ==
          IncognitoModePrefs::DISABLED) {
      incognito = false;
    }
  } else if (profile->IsGuestSession() ||
             (browser_defaults::kAlwaysOpenIncognitoWindow &&
              IncognitoModePrefs::ShouldLaunchIncognito(
                  *base::CommandLine::ForCurrentProcess(), prefs))) {
    incognito = true;
  }

つまり、おそらく
NewIncognitoTab() が呼ばれる
 ↓
profile->IsOffTheRecord() なので incognito = true になる
 ↓
IncognitoModePrefs::GetAvailability(prefs) == IncognitoModePrefs::DISABLED なので incognito = false になってしまう
 ↓
普通のタブが開く
という挙動になってしまったのが原因だと考えました。

てかわざわざこんなことしなくても SetProfile() って関数作って NewTab() と NewIncognitoTab() の中で profile をセットすればいいだけじゃね?と思ってしまいました。実はこれは相方のアイデアなのですが、潔く丸パクリすることにしました。決断力。

改装

NewTab() と NewIncognitoTab() は以下のようにコードを変えました。(大事だと思ったので丸々載せますが基本元のNewTab()と構成は一緒です)

void NewTab(Browser* browser) {
  base::RecordAction(UserMetricsAction("NewTab"));
  // TODO(asvitkine): This is invoked programmatically from several places.
  // Audit the code and change it so that the histogram only gets collected for
  // user-initiated commands.
  UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
                            TabStripModel::NEW_TAB_ENUM_COUNT);
    
  browser->SetProfile(browser->profile()->GetOriginalProfile());

  if (browser->is_type_tabbed()) {
    AddTabAt(browser, GURL(), -1, true);
    browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  } else {
    ScopedTabbedBrowserDisplayer displayer(browser->profile());
    Browser* b = displayer.browser();
    AddTabAt(b, GURL(), -1, true);
    b->window()->Show();
    // The call to AddBlankTabAt above did not set the focus to the tab as its
    // window was not active, so we have to do it explicitly.
    // See http://crbug.com/6380.
    b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  }
}
    
void NewIncognitoTab(Browser* browser) {
    base::RecordAction(UserMetricsAction("NewTab"));
    // TODO(asvitkine): This is invoked programmatically from several places.
    // Audit the code and change it so that the histogram only gets collected for
    // user-initiated commands.
    UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
                                TabStripModel::NEW_TAB_ENUM_COUNT);
    
    browser->SetProfile(browser->profile()->GetOffTheRecordProfile());
    
    if (browser->is_type_tabbed()) {
        AddTabAt(browser, GURL(), -1, true);
        browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
    } else {
        ScopedTabbedBrowserDisplayer displayer(browser->profile());
        Browser* b = displayer.browser();
        AddTabAt(b, GURL(), -1, true);
        b->window()->Show();
        // The call to AddBlankTabAt above did not set the focus to the tab as its
        // window was not active, so we have to do it explicitly.
        // See http://crbug.com/6380.
        b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
    }
}

そして browser.h には

class Browser : public TabStripModelObserver,
                  ・・・
{
  public : 
  ・・・
   // Accessors ////////////////////////////////////////////////////////////////
  ・・・
  void SetProfile(Profile* profile) { profile_ = profile; }
  ・・・
}

さらに、タブによってprofileを変えるために browser.h 内の Profile* const profile_; から const を削除して Profile* profile_; にしました。

また、よくよくみていくと tab_activity_watcher.cc にて

namespace resource_coordinator {
class TabActivityWatcher::WebContentsData
    : public content::WebContentsObserver,
      public content::WebContentsUserData<WebContentsData>,
      public content::RenderWidgetHost::InputEventObserver {
  ・・・
  private :
    explicit WebContentsData(content::WebContents* web_contents)
      : WebContentsObserver(web_contents) {
    DCHECK(!web_contents->GetBrowserContext()->IsOffTheRecord());
    tab_metrics_.web_contents = web_contents;
    web_contents->GetRenderViewHost()->GetWidget()->AddInputEventObserver(this);
    ・・・
  }
  ・・・
}
}

と DCHECK で OffTheRecord() のチェックが入ってしまっているので、この一行を削除しました。

結果

f:id:RHys:20181022181753p:plainf:id:RHys:20181022181759p:plain

画像ではわかりにくいですが無事実装できました!!

やっぱりひとまずとはいえ完成すると嬉しいですね!w

課題

f:id:RHys:20181022182029p:plain

実は先ほどの画像の状態で、もう一度元のタブに戻った時の画像がこちらなのですが、なんか変ですよね...?

おそらくこのタブを開いた時は browser->profile() が GetOriginalProfile() だったのに、新しいシークレットタブを開いたせいで profile が GetOffTheRecordProfile() になってしまっているせいで、なんらかのコンフリクトが生じてしまっています。

この画像のタブで検索をしてみても新しいタブが開かれてしまうんですよね...

選択するタブを切り替える時の動作を追うことができればそこでまた profile を変更するようにすれば良いと思うのですが、残念ながら講義時間中ではそこまで追いきれませんでした。1

後は見てお気づきかとは思いますが GUI やショートカットキーの割り当てですね。画像ではショートカットキーが割り当てられているような雰囲気を醸していますがこれはハリボテで押しても何も反応しませんw

相方は Linux で行なっていたのでキーの割り当てが比較的簡単にできていそうでしたが、macOS は何か特殊らしくよくわからなかったですね。時間を見つけてまた取り組みたいところです。

感想

さて、初めてこんな複雑なプログラムに触れて見ましたが、意外とたのしかったです。なんというか、これを趣味にするのもわかる気がする。。。

自分はプログラミング完全初心者2で、特に c++java なんかは見たこともほとんどないレベルだったのですが、まあやっていくうちになんとなく読めてなんとなーく書けるようになっていきました。

なので初心者の方々も気軽に触ってみてはいかがでしょうか。


次回以降の演習で chromium を手探る方は無理ない程度に無理して頑張ってください!


  1. はじめにも記載しましたが大学の実習の一環として取り組んでいます。詳細はこちら

  2. 実は去年の必修のプログラミングの単位も落としています。ほんとうにつらい