Neunomizuの日記

俺だけが俺だけじゃない

# Sunk CostとしてのAtCoder(緑色で引退)

tags: 情報

要約

  • AtCoderはデータ構造とアルゴリズムを勉強するのに効率が良いと思って始めた
  • 効率よく勉強するのが目的なら他によい手段が見つかった
  • AtCoderは良いサービス
  • LeetCodeの方が自分には向いてそう

始めた理由

始めたのはデータ構造とアルゴリズムに詳しくなりたかったからです

加えて, 周りのやっている人が強い人だったからというのもあります

(自分への)実際の効用

AtCoderを始めた時は本当にプログラミングが出来なかったのですが, 始めてコードを書く量が増えたので前よりはできるようになりました. 当たり前ですね

加えてデータ構造とアルゴリズムにも詳しくなりました. 試験勉強で「あ, これAtCoderで見た!」となったこともあります

やめた理由

  • AtCoderのレートで疲れた
  • データ構造とアルゴリズムを勉強するなら他のサービスの方が良いと思った
  • これをやっている時間を他のことに使いたい
  • 新ABCからレートが上がらないのでつまらない(笑)
  • 数学(パズル?)みたいな問題が出てイライラするから(笑)

英語試験と似ている?

AtCoderというのは英語の資格試験と似ている点が結構あって

  • レート(スコア)が高いとプログラミング(英語)そのものができると思われやすい
  • レート(スコア)が目的化してしまう
  • 試験に出せるものはできるようになるがそれ以外は試験勉強ではできるようにならない

最後は語弊がありそうなので付け加えると, AtCoderの問題を解くとAtCoderの問題は解けるようになるけどWebアプリケーションが作れるようにはならないというだけで別に役に立たないということが言いたいわけではないです

逆に異なるのは

  • 英語が母国語の人は資格試験のスコアがすごいことになる
  • 無為にプログラミングをしているだけでは少し対策した程度ですごいスコアは出ない

僕はこの無駄にレートに拘るというものをしていたのですが, レートが上げて何がしたいのかと冷静に考えると特にないのでやめることにしました

TOEICの点数にめちゃくちゃこだわっている人もいますがそんな感じでしたね. 大してやっていないけど気にして脳のリソースが奪われるやつ

やめるけど

緑色の自分が言うのもなんですが役には立つと思います. やっていなかったら出来なかったであろう処理もあります

しかし, レート(水色になってやめたかった気もする)とかかけた時間を考えるとやめるのもなぁと思いながらダラダラやっていたのですがそうやってもっと大事なことをやらない方がもったいないのでやめるだけです

今はLeetCodeをぼちぼちやっています. それは僕がそっちの方が自分にとって効率的だと思っただけです. AtCoderは素晴らしいサービスだと思います(ついでにAtCoder Jobsも使うつもりなので頭上がらないです^^)

個人的には海外の面接で使われる問題をそのままパクっていて学習的なサイトであるLeetCodeの方がいいと思いました

LeetCodeの宣伝

LeetCodeの宣伝をします(冗談です)

このサイトは主にアメリカ企業のコーディングテストを突破するために作られていて, 体系的にデータ構造とアルゴリズムを学ぶことが可能です

僕がLeetCodeで気に入った点は以下の通りです

  • AtCoder的な数学ぽい問題は(少なくとも僕とその周辺の意見では)少ないです
  • 体系的にデータ構造とアルゴリズムが学べる
    • Learnというのデータ構造やアルゴリズムに関する問題が体系的にまとまったページがあります(下の通り)
    • 問題にもタグが付いているので自分の関心があるものを重点的に学ぶことができます
    • AtCoderではそういうサービスはないのでこれが大きいです

  • 問題もこのように問題ごとに難易度も書かれていて使いやすいです
    • AtCoderにはこういう自前のサービスがなくUIも見やすいです
  • 実際にコーディングテストに出題された問題が大半なので就職の役に立つ(らしいです)
  • 課金するとコーディングテストの役に立つコンテンツが使えるようになる
    • 質が高いものならお金を払ってもいいと思っています
    • 解説がわかりやすいです. 一部有料ですがこのわかりやすさなら納得です
  • discussionというユーザーが解法を共有する空間がある
    • 公式の解説が分からなくてもなんとかなります
  • 時間計算量だけでなく空間計算量の改善も重要である
    • AtCoderでは時間計算量だけが問われることが多いですが, 空間計算量も考慮するようになりました
  • 解説の動画がYoutubeにたくさんある
    • B2Bがわかり易すぎる(ちなみにYoutubeにはKruscal先生も登場します)
    • AtCoderの解説放送とは違い編集もされていて, 言語が強いと量と質も違うのだなあと思いました(丸)

他にもあると思いますがぱっと思いついたのがこれですね. ただ, 複合的な問題は出てこないですし, アルゴリズムの実装がメインです. 結構毛色が違いますねやはり

コンテストも一応開催していますが, 自分は出ていません. まだ問題解き始めた段階ですしね

手段と目的

プログラミングは手段に過ぎないと考えている人とそれ自体が目的の人がいると思います. 僕にとってはどちらでもあり目的となるプログラミングはAtCoderでのプログラミングではなく, 手段としてもAtCoder社の提供するもの以外にもっと良いと思うものがあったというだけです

某氏曰く「水色ならば人間だ」だそうですが, こういうレートが正義みたいな意見が強いのも苦手だったのでちょうどいい機会でした

(このブログを読んだchokudai氏とそのファンネルにあれこれ言われそうだ...)

# プログラミングで詰まっている所

tags: 情報

satoru-takeuchi.hatenablog.com

mizchi.hatenablog.com

流行りなのかな?ということで考えてみます

プログラミング歴

こんなのでも情報系の学部に所属しています

理解した気になっていた所

ポインタとかアドレスとか配列とか

コンピュータのメモリ上に変数などが置かれると分かるまではよく分かっていなかった

文法的に*&が付くものだと思っているだけで本質的に配列が何なのかなどを理解していなかった

理解した気になっている所

型推論

型推論と動的型付けの違いがよく分かっていないと思う

ふわふわとした「型推論」について話しているだけ

GC

「RustはGCがない言語です. 素晴らしいです」

うん. GCはコストのかかる処理だからない方が良いかも知れない. でもなんで他の言語はそんなにコストがかかるのにGCがあるのだろう. 書きやすいから?

そもそもGCがのコストって実装もしたことがないからなぁ...分かりたいと思っている

関数型プログラミング

OCamlLispも書いたことはあるけど, それで関数型プログラミングを理解したことにはならないと思う

本質みたいなのはまだよく分かっていない

これがわかりやすかったけど, 結局大規模なソフトウェアを書かないと本当の良さは分からなそう

ラムダ計算

無名関数は使っていて便利だとは思うけど, それがどう数学的に有用なのかは分かっていない

OOP

オブジェクト指向がメモリをどう使っているか, 抽象化をしているかはわかった気になっているだけで, 結局コードを書かないと分かった気になったままだと感じている

Web

Web系の会社でインターンしたのに未だによく分かっていません

ソフトウェア

ソフトウェアを作るってなんなのだろうか

そもそもソフトウェアが何なのかよく分かっていない

今の自分にアドバイス

コードを書く

コードを書かないと理解は出来ない

自分ではアルゴリズムを理解した気になっても, 本当にそれが理解できたかはコードに落とせるかで判断した方が良いという話

後, 書けるコードばかりを書いていっても書けるコードは増えないので, ある程度書けるようになったら他人のコードを読むことを覚えたほうが良いと思う

理屈も勉強した方が結局早い

理屈とはハードウェアの話から実際にどうソフトウェアで実装されているかまで

コンピュータ・アーキテクチャとOSまで理解できたらC言語とか別にいらない気がするし, 他もおそらくそう

でも理屈を勉強するのと一緒にコードを書くのが一番なのでそれをやるべき

分かっていないのが分かってきてからが本番かも知れない

最初は分かったと思い込んでしまうものだけど, それが徐々に分かってないに変わる時が来てからが本番なのかも

分かったつもりで色々話してしまうのが初心者ならば(周りを見ていてもそうだけど), 分かったつもりでいることを分かったことにできるのが中級者な気がする

上級者は人に分からせるのかな. 例えばC言語を作ったりして.

まとめ

プログラミングを2年近くやっていてもこのザマなのだけど, 未来の自分がどうにかしてくれるはずだと思って生きています

C言語における*charとchar[]の違い

tags: 情報

pointer & array

C言語では変数を宣言する際にchar*と使うものとchar[]があります

「これにはなんの違いがあるの?」という人もいそうです.かくいう自分もそうでした

ということで図示すればわかりやすいだろうということで図示したのがこちら

char*はあるarrayを指すポインタ,つまりなんらかの定数が入っています

一方,char[]はarrayそのものです

multi dimentional array

これが多次元になるとどうなるんでしょうか?

以下のようになります

char *names[]はある配列を指す複数のポインタが中に入ったarrayです

char nemes[][10]は長さ10の配列をsubarrayとして持つarrayです

まとめ

単にhttps://www.draw.io/が試したかっただけです

Rust以外無意味

tags: 情報

この記事はeeic (東京大学工学部電気電子・電子情報工学科) Advent Calendar 2019の11日目の記事として書かれました

Rustとは

公式HPによれば

  • Performance
  • Reliability
  • Productivity

という長所がある言語なようです

下のように

Rust以外は無意味なのです

C++でバリバリにコードを書いたことがないとそのありがたみがわからないよ的な文章も読みました

しかし,そう言われても実際にどういうものかわからないとこれが真実かイキリかどうか見分けがつきません

ということで実際にドキュメントを読んで短いコードを書いてみることにしました

どのドキュメントを読んだのか

公式のレポジトリにあるものを読みました

の3種類があります

Nightly(毎日更新)->Beta(6週間でNightlyから昇格)->Stable(6週間でBetaから昇格)という風になっているようです

私はStableを読みました

日本語版は2018年Editionに対応していないのでまだ読まないほうが良いと思ったので英語の方を読みました

読んだ感想

  • 競プロをするだけなら1~9章と10,12,13,18章を読んで後は他人のコードを見ながらコードを書けばなんとかなりそうな気がします
  • コンパイラがめちゃくちゃ賢い色々なパラダイムを含む言語だと思いました
  • CやC++を書いたことがない人(メモリに対する知識がない人)がいきなりRustを書くのは大変な気がします
    • Rustでコードを書こうとするとownership,borrowing,lifetimesを常に意識する必要がります
    • これらを理解するのにメモリに関して具体的にイメージできる必要があるように思えます
      • そして,そういう勉強をした人はCやC++を学んだ経験があるはずなので初心者がやることがそもそもなさそうに感じます
      • 初心者がやるとコンパイラが優しすぎて,挫折してしまいそうです
    • という理由で文系学部などから来たWeb系に来た人がいきなりこれを書くのも大変そうだなという感想を持ちました
  • バグの温床になりそうな部分を片っ端から潰している言語で使えるようになったら楽しそうです
  • Rustで書いている人が強いという話は本当っぽいなぁと思いました(ただなんちゃってみたいな人は除く)

読んでとりあえずコードを書く

Rustという言語の強みはコンパイラと言いました.これは本当でコンパイラが少しでもバグの原因になりそう!というコードを見つけたら教えてくれます

ということで適当に書いてみます

フィボナッチ数

プログラミング言語の勉強をする時,最初は再帰関数の練習としてフィボナッチ数を書きますよね(?)

ということで次のような感じで0~10のフィボナッチ数は書けます

fn main() {
    println!("!Fibonacci!");
    for i in 0..11 {
        println!("{}th Fibonacci number is {}", i, fibonacci(i));
    }
}

fn fibonacci(n: u32) -> u32 {
    if n == 0 || n == 1 {
        1
    } else {
        fibonacci(n - 1) + fibonacci(n - 2)
    }
}

実行するとこんな感じに出力されます

!Fibonacci!
0th Fibonacci number is 1
1th Fibonacci number is 1
2th Fibonacci number is 2
3th Fibonacci number is 3
4th Fibonacci number is 5
5th Fibonacci number is 8
6th Fibonacci number is 13
7th Fibonacci number is 21
8th Fibonacci number is 34
9th Fibonacci number is 55
10th Fibonacci number is 89

このコードを見ると

「あれ?そんなに難しくじゃん」

と思うかも知れません.しかし,後ほんの少し複雑なコードを書くと困ったことになります

Hashmapを使った問題

LeetCodeで一番解かれている問題を使います

めちゃくちゃ簡単なこの問題ですが,Rustで書くと落とし穴が何個か有ります

問題の概要はある整数列が与えられその値から2つの異なる値を足し合わせてtargetという目的の数になること

解答は

  • map<target - num0, num1>というHashMapを作り,この値があればそれを出力し,なければ新しくkeyとvalueを新しく格納する

というものです

下のように書きました

use std::collections::HashMap;
impl Solution {
    pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {        
        let mut map: HashMap<i32, i32> = HashMap::new();
        let mut res: Vec<i32> = Vec::new();
        
        for (i, num) in nums.iter().enumerate() {
            if (map.contains_key(&(target - num))) {
                res.push(map[&(target - num)]);
                res.push(i as i32);
                return res;
            }
            map.insert(*num, i as i32);
        }
        return res;
    }
}

この短いコードの相田に以下のような点に注意する必要が有ります

  • map.contains_key(&(target - num))に関して
    • ここではHashMapの仕様上&を付けてborrowする必要がある(他はダメ)
  • map.insert(*num, i as i32)に関して
    • numnums.iter().enumerate()から取り出しており,borrowされており,*を付けてdereferenceをしないとinsertできないため(これはHashMapinsertする際にownershipが移ることから)
    • i as i32iのままだとusize(符号なし)というデータ型なので出力形式とマッチしないから

このように実行時のバグをなくすためにコンパイル時に指摘しまくります

自分もあまり理解しておらず理解が浅いうちはコンパイラにお世話になりっぱなしだと思います

結論

Rust以外無意味ではなくてRust(が書けないエンジニアはコンピュータを分かったつもりで書いているので)無意味ということなのかなと思いました

C++やCをわかっていない人が書いても確かに恩恵が分かりにくそうだと感じました.というのも一度メモリに触れておかないとコンパイラに頼りっぱなしでごちゃごちゃやって理解した気になってしまいそうだと感じたからです

基本大事ダネ☆

次回

C言語以外無意味

続く...

Firefoxのブックマーク機能を変えた

tags: 情報

大規模ソフトウェアを手探るという授業の一環でやっています

Firefoxのビルドに関して

前回の記事を読んで下さい

propyon.hateblo.jp

現在のブックマーク機能

現在のFirefoxのブックマーク機能では常にデフォルトの保存先フォルダ(Other Bookmarks)に保存することが決まっています

これを,最後にブックマークを保存したフォルダに随時変更するようにしたいと思いました

変更されたブックマーク機能

ということで,ブラウザが開いている間にブックマークしたページの最新の保存先にデフォルトのフォルダが更新されるように変更を加えました

加えて,その機能をToggleできるようにしました

デフォルトの保存先を変更するためのソースコード

結局ソースコードを見るのが一番わかるはずです

デフォルトの保存先フォルダを変更するために修正を加える必要があるのはbrowser/base/content/browser-placesにあるparentGuidです

この変数が保存先フォルダを指しています

最初の実装では別にLAST_USED_PARENT_IDというグローバル変数を作り,これで最後に保存したフォルダを記憶し,これをparentGuidに代入するようにしました

diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 809e6b642f..9e567ad831 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -5,6 +5,8 @@
 // This file is loaded into the browser window scope.
 /* eslint-env mozilla/browser-window */ 
+var LAST_USED_PARENT_ID = undefined;

 XPCOMUtils.defineLazyScriptGetter(
   this,
   ["PlacesToolbar", "PlacesMenu", "PlacesPanelview", "PlacesPanelMenuView"],
@@ -70,6 +72,7 @@ var StarUI = {
         clearTimeout(this._autoCloseTimer);
         if (aEvent.originalTarget == this.panel) {
           let selectedFolderGuid = gEditItemOverlay.selectedFolderGuid;
+          LAST_USED_PARENT_ID = selectedFolderGuid;
           gEditItemOverlay.uninitPanel(true);
 
           this._anchorElement.removeAttribute("open");
@@ -444,7 +447,12 @@ var PlacesCommandHook = {
     let isNewBookmark = !info;
     let showEditUI = !isNewBookmark || StarUI.showForNewBookmarks;
     if (isNewBookmark) {
-      let parentGuid = PlacesUtils.bookmarks.unfiledGuid;
+      let parentGuid;
+      if (LAST_USED_PARENT_ID !== undefined) {
+        parentGuid = LAST_USED_PARENT_ID;
+      } else {
+        parentGuid = PlacesUtils.bookmarks.unfiledGuid;
+      }
       info = { url, parentGuid };
       // Bug 1148838 - Make this code work for full page plugins.
       let charset = null;

しかし,これは安全なコードではないのでグローバル変数をなくすために以下のように書き直しました

diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 809e6b642f..994d573568 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -28,6 +28,7 @@ var StarUI = {
   // in browser/components/pocket/content/panels/js/saved.js.
   _autoCloseTimeout: 3500,
   _removeBookmarksOnPopupHidden: false,
+  _lastUsedParentId : undefined,
 
   _element(aID) {
     return document.getElementById(aID);
@@ -70,6 +71,7 @@ var StarUI = {
         clearTimeout(this._autoCloseTimer);
         if (aEvent.originalTarget == this.panel) {
           let selectedFolderGuid = gEditItemOverlay.selectedFolderGuid;
+          this._lastUsedParentId = selectedFolderGuid;
           gEditItemOverlay.uninitPanel(true);
 
           this._anchorElement.removeAttribute("open");
@@ -443,8 +445,14 @@ var PlacesCommandHook = {
     let info = await PlacesUtils.bookmarks.fetch({ url });
     let isNewBookmark = !info;
     let showEditUI = !isNewBookmark || StarUI.showForNewBookmarks;
+    let lastUsedParentId = StarUI._lastUsedParentId;
     if (isNewBookmark) {
-      let parentGuid = PlacesUtils.bookmarks.unfiledGuid;
+      let parentGuid;
+      if (lastUsedParentId !== undefined) {
+        parentGuid = lastUsedParentId;
+      } else {
+        parentGuid = PlacesUtils.bookmarks.unfiledGuid;
+      }
       info = { url, parentGuid };
       // Bug 1148838 - Make this code work for full page plugins.
       let charset = null;

ついでにJSのお作法を知らなかったのでそこも直しました

Javascriptでのnullは何もない値とこちらから決めた値です.しかし上ではundefinedが使われています

つまりundefinedは意図的に定める値ではないのにここでは定められています.それをnullに変更

diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 994d573568..ae8041e65e 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -28,7 +28,7 @@ var StarUI = {
   // in browser/components/pocket/content/panels/js/saved.js.
   _autoCloseTimeout: 3500,
   _removeBookmarksOnPopupHidden: false,
-  _lastUsedParentId : undefined,
+  _lastUsedParentId: null,
 
   _element(aID) {
     return document.getElementById(aID);
@@ -448,7 +448,7 @@ var PlacesCommandHook = {
     let lastUsedParentId = StarUI._lastUsedParentId;
     if (isNewBookmark) {
       let parentGuid;
-      if (lastUsedParentId !== undefined) {
+      if (lastUsedParentId !== null) {
         parentGuid = lastUsedParentId;
       } else {
         parentGuid = PlacesUtils.bookmarks.unfiledGuid;
diff --git a/done.txt b/done.txt
new file mode 100644
index 0000000000..cfa2b8818c
--- /dev/null
+++ b/done.txt
@@ -0,0 +1,38 @@

これで完成です.本当に少ししかいじっていないし,僕は大規模ソフトウェアの表面をなぞっているだけだ...と若干鬱です

Toggleするためのソースコード

上の機能を使用したくない人もいると思います.ということで切り替えができるようにしました

既存のFirefoxにはブックマークをした時に,ブックマーク先をどうするか選ぶためのエディタ(下の画像の通り)が開くかどうかをToggleできます.これをパクって利用してやろうということになりました

ブックマークエディタ

"Show editor when saving"がデフォルトの部分

"Use default folder"が今回追加した部分

実際にコードを変更したのは次の4箇所です

firefox.js

ここではtoggleするために必要な変数を設定しています.デフォルトだとtrueにしてあります(つまり,最後の保存先フォルダを記憶しない設定にしてあります)

diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 2bbfc67da2..7606fad678 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1009,6 +1009,9 @@ pref("browser.privatebrowsing.autostart", false);
 // Whether the bookmark panel should be shown when bookmarking a page.
 pref("browser.bookmarks.editDialog.showForNewBookmarks", true);
 
+// Whether the default bookmark foulder should be shown when bookmarking a page
+pref("browser.bookmarks.editDialog.toggleDefaultFolder", true);
+
 // Don't try to alter this pref, it'll be reset the next time you use the
 // bookmarking dialog
 pref("browser.bookmarks.editDialog.firstEditField", "namePicker");

browser-places.js

ここでは実際にブラウザ上でブックマークをした際にtoggleに必要な変数が変更がされるようにしています

何が起こっているのかはおそらく多少プログラミングをしたことがある人にはわかるでしょ.ただ,わからないという人もいると思うので説明しておきます

下から説明します

  • if構文から説明します.ここではtoggleボタンで最後の保存先をフォルダを使うかどうか決めています
  • 次のonToggleDefaultFolderCheckboxではチェックボックスがチェックされているかに応じてブックマークの設定を決める値にブール値を設定しています
  • 次のthis._elementの部分ではjavascriptの文法がよくわからないのですが,thisの中にthis.toggleDefaultFolderの値を代入しています
  • getの部分はthis.toggleDefaultFolderで呼び出された際にbrowser.bookmarks.editDialog.toggleDefaultFolderのブール値を返します

この部分はブックマークエディタでチェックを入れたり,消した際に呼び出される関数郡が書かれています

diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index ae8041e65e..aa8bc2f7b0 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -40,6 +40,12 @@ var StarUI = {
     );
   },
 
+  get toggleDefaultFolder() {
+    return Services.prefs.getBoolPref(
+      "browser.bookmarks.editDialog.toggleDefaultFolder"
+    )
+  },
+
   // Edit-bookmark panel
   get panel() {
     delete this.panel;
@@ -221,6 +227,10 @@ var StarUI = {
       "editBookmarkPanel_showForNewBookmarks"
     ).checked = this.showForNewBookmarks;
 
+    this._element(
+      "editBookmarkPanel_toggleDefaultFolder"
+    ).checked = this.toggleDefaultFolder;
+
     this._itemGuids = [];
     await PlacesUtils.bookmarks.fetch({ url: aUrl }, bookmark =>
       this._itemGuids.push(bookmark.guid)
@@ -400,6 +410,13 @@ var StarUI = {
     );
   },
 
+  onToggleDefaultFolderCheckboxCommand() {
+    Services.prefs.setBoolPref(
+      "browser.bookmarks.editDialog.toggleDefaultFolder",
+      this._element("editBookmarkPanel_toggleDefaultFolder").checked
+    );
+  },
+
   showConfirmation() {
     let animationTriggered = LibraryUI.triggerLibraryAnimation("bookmark");
 
@@ -448,10 +465,10 @@ var PlacesCommandHook = {
     let lastUsedParentId = StarUI._lastUsedParentId;
     if (isNewBookmark) {
       let parentGuid;
-      if (lastUsedParentId !== null) {
-        parentGuid = lastUsedParentId;
-      } else {
+      if (StarUI.toggleDefaultFolder || lastUsedParentId === null) {
         parentGuid = PlacesUtils.bookmarks.unfiledGuid;
+      } else {
+        parentGuid = lastUsedParentId;
       }
       info = { url, parentGuid };
       // Bug 1148838 - Make this code work for full page plugins.   

browser.xhtml

ここではブックマークエディタの表示を決めています.checkboxという部分からチェックボックスを作っていることがわかると思います

特に重要なのはoncommandという部分で,ここでチェックされた際に呼び出される関数を決めています

diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index e53c9f7f4b..69daa32920 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -290,6 +290,13 @@
                   accesskey="&editBookmark.showForNewBookmarks.accesskey;"
                   oncommand="StarUI.onShowForNewBookmarksCheckboxCommand();"/>
       </vbox>
+      <vbox id="editBookmarkPanelBottomContent"
+            flex="1">
+        <checkbox id="editBookmarkPanel_toggleDefaultFolder"
+                  label="&editBookmark.toggleDefaultFolder.label;"
+                  accesskey="&editBookmark.toggleDefaultFolder.accesskey;"
+                  oncommand="StarUI.onToggleDefaultFolderCheckboxCommand();"/>
+      </vbox>
       <hbox id="editBookmarkPanelBottomButtons"
             class="panel-footer"
             style="min-width: &editBookmark.panel.width;;">

browser.dtd

ここはブックマークエディタで表示される文言を設定しています.上で定めたlabelaccesskeyと対応しているとわかると思います

チェックボックスにチェックを加えるとデフォルトのフォルダを使うようにしているので"Use default folder"という文言にしています

diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd
index 0407ec8a0b..1cac2da49b 100644
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -627,6 +627,8 @@ you can use these alternative items. Otherwise, their values should be empty.  -
 <!ENTITY editBookmark.done.label                     "Done">
 <!ENTITY editBookmark.showForNewBookmarks.label       "Show editor when saving">
 <!ENTITY editBookmark.showForNewBookmarks.accesskey   "S">
+<!ENTITY editBookmark.toggleDefaultFolder.label       "Use default folder">
+<!ENTITY editBookmark.toggleDefaultFolder.accesskey   "S">
 
 <!ENTITY identity.connectionSecure3 "Connection secure">
 <!ENTITY identity.connectionNotSecure2 "Connection not secure">

開発に関して

Searchfox, Bugzillaというツールが有効でした

SearchfoxはFirefox用のGoogle検索みたいなもので,変数名などを検索したら色々と出てきます

BugzillaはMozilla(Firefoxを開発しているところ)のIssueが転がっている場所です.関連したIssueを見て勉強に成りました(ソースコードが変わっていてあまり使えなかった)

より使えたのはDeveloper toolsです

このページがわかりやすいです

これらを見ながら機能を推測して,変えて,その結果を眺めるというのを繰り返して開発をしていました

スライド

授業の一環でやったのでスライドにしてあります.以下の通りです

気になったらご覧ください

感想

前回のインターン

大規模ソフトウェアをいじった経験はインターン以来でした(夏にWeb系の企業にインターンに行った)

この時はRuby on Railsをいじっていました

で,そのときに感じたのは,大規模ソフトウェアの開発って変えたい機能に関連する部分をちょこちょこ変えるだけでつまらなくないですか???ということです

そこではタスクが振られて,それをこなすという風に開発をしていたのですが,毎回異なる機能について実装をしていたので新しいことをやれるという反面,毎回同じことを覚える必要があり,「あまりおもしろくない...」と思っていました

今回の実験

しかし,今回はもう少し長い時間同じソフトウェアを触れていたのでまた違った感想を持ちました

開発に関する速度はそのソフトウェアに関する知識を真数とした対数グラフみたいになっていて,だんだん知識が深まると開発も早くなり楽しくなるよねということです

大規模ソフトウェアと言っても挙動を理解するだけならある程度読めばなんとか理解できます

ということで「大規模ソフトウェアも楽しいよ」というのが今回の感想

それと早く「慣れる」速度を高めたいなということです.慣れるのが早ければ早くなるほど多分もっとソフトウェアの開発も楽しめるはずです

最後に

相方と先生,TAの方に感謝

大規模ソフトウェアをいじるといっても大したことはないと思えるように成りました

眺めているだけでも楽しいのでコミットまでできるように頑張りたい