プロジェクト管理を整える月曜日

9:00

おはようございます。

publish:WRM:セルフマネジメントとそのためのツールについて|倉下忠憲|note

あとで読む:

fragment:プロジェクト管理について:

昨日は一日プロジェクト管理について考えていたので、それについてまとめます。

まず、複数のプロジェクトにコミットするようになったので、それを管理したいという希望がありました。そのために何かしようと思っていたのがスタート。

最初はいろいろなUIを考えました。プロジェクトを一つのタブとして表示してそれを横に並べるとか、作業ログとプロジェクトリストを並べてその「diff」を把握しやすいようにする、などといったことです。

で、もろもろ「良さそうなもの」はイメージできるのですが、どうも「じゃあ、実装するか」というレベルには至りませんでした。

で、ちょこっと思いつきで作った以下のUI。

Image from Gyazo

これが存外に良い感触でした。それでわかったのは、自分は「プロジェクト管理」を求めていたわけではない、ということ。その時点で持っているプロジェクトを一覧し、それを並行的に管理したい、というわけではなかったのです。

では何だったのかと言えば、「そういえば、あれ最近やっていないな」みたいなことを、“思える"ようにしたかった、というのが近しいでしょう。毎日適切に進捗を進めることをサポートするのではなく、気のままにプロジェクトに着手し、しかしながら、たまに「しばらく手を付けていないこと」がわかるようにすること。それくらいの「管理」で十分なのです(なぜなら、重要なことは原稿の執筆のように毎日やっているから)。

ガントチャートのようなものは使えません。一日でどの作業がどのくらい進むかがわからないからです。ガントチャートが使えるならば、複数のプロジェクトを並べて、作業を割り振っていけばうまく管理できるでしょう。しかし、その方法は使えないわけです。

で、どうするか。

基本的には、「自分がその日にやろうと思ったことをやる」であり、その「やろうと思う」をいかにサポートするのかが鍵です。

で、TextboxではBoard.mdというファイルを作って、コミットしているものを並べているのですが、要素を縦に並べているので、最初のいくつかの部分しか目に入りません。それだと、しばらくコミットしていないものは目に入らず、そのまま忘却されてしまう(あるいはなかなか手が付けられないまま時間が流れてしまう)という状況が起こります。これを変えたかった。

そこで、「要素を横に並べる」ということを考えていたのですが、HTMLで横に並べるとなると、flex-boxなどを使うことになるのですが、そうなるとすべての要素が「対等」になります。粒度が揃うのです。そこに違和感を感じていたのでしょう。「何か違う」と。

先ほど表示した例は、その粒度が散らばっています。求めていたのはこうした表示(UI)でした。

右横の窓(ワイプ窓と呼ぶことにする)は、付加情報として添えられています。そこに何かしらの「足跡」を残しておけば、たぶんそれで十分です。その足跡の方は、情報が追加されたり、変更されたりしても構いません。たとえば、作業したしたものが下にいく、といった対応もできますし、最終実行日の日付が記述されて、それが変更されていくのでもよいでしょう。

なんであれ、主幹として「自分がやろうとしていること」がメインページに表示され、それを補佐する情報がワイプ窓に表示される、という形で私が求めている情報構成はできあがりそうです。

でもって、たとえばこのワイプ窓に表示させる情報を変更できても面白いでしょう。「Honkureで書きたいこと」「買った本」などが表示できる、ということです。でもって、それはTextbox内に保存している情報でもあります。

Textboxでそれらを一画面として表示させることもできるし、何かを表示しているときにワイプ窓にそれを表示させることもできる。それができればプロジェクト管理以外でも何か使い道が出てくるのではないでしょうか。

fragment:Board.mdについての検討:

現状Board.mdには以下の要素がある。

このうち、「連載リスト」と「進めたい原稿」以外は機能している。逆に言えば、「連載リスト」と「進めたい原稿」はほとんど活躍していない。でもって、その活躍していない感じが上のようなプロジェクト管理欲求を発生させたのだろう。

で、上記の要素は基本的にはTextboxで単一ファイルとして生成することもできる。それをやらないのは、第一に情報の量があまりに小さいことであり、第二に単体で表示させることがほとんどないからだ。

が、ワイプ窓方式が使えるなら、それぞれお単一ファイルで保存しつつ、表示はこのBoardで一覧、ということもできる。ただしその場合は、Boardから直接内容が編集できず、それぞれのファイルを呼び出す必要がある。その点だけがネック。

その情報がログ的なもの(最近触ったプロジェクト、買った本のリスト)などであれば、自分で書き換えることなくスクリプト任せで十分である。言い換えれば、生成されたデータが後から変更されることはほぼない(追記されるだけ)。よって、Boardから編修できなくえも問題はない。

それ以外のファイルについては、若干その点が問題ではある。

しかしながらワイプ窓方式は検討に値するように思う。

* * *

話を少しもどす。

「懸案事項」の項目には、「おーぷん・かーそる用に「GTDよサラバ」(仮)を書く」や「かーそる第五号用に「生活における知」について書く」が書かれている。ようするに「進めたい原稿」の項目がそのままこちらも来ている。単にその情報が箇条書きではなく、カラーリングされた表組みで表示されているに過ぎない。

まず、ここを改める。

* * *

「懸案事項」の項目を消した。

「連載リスト」はどうか。現状はワイプ窓にほぼ同じものが表示されている。しかし、「連載一覧」が横に並んでいるUIの感覚は悪くはない。

* * *

たとえば、ワイプ窓の中身がスライドできて、上記の連載リストが次々に表示されるようにできたら嬉しいだろうか。

* * *

「連載リスト」一覧は、リストではあるが、むしろテンポラリーリストであろう。「連載」という性質を持つプロジェクトの検索結果を表示している、という感じ。やることリストとは少し違う。だから、連載一覧をBaord上で編集する必要はない。だとしたら、他のファイルに置いておいても構わない?

たぶん構わない。今までは、他のファイルの情報を引っ張ってこれないので一緒に記述していたが、そもそもが別枠の情報である。そこで一旦「連載リスト」も消してみる。

* * *

かなりすっきりした。一画面で全項目のヘッダーまではきちんと収まっている。「気になっていること」の最初の二行までが表示されている。つまり「目に入る」。これで十分。むしろ「気になっていること」は最初の二行くらいが目に入るのでちょうどいい。

* * *

Image from Gyazo

ワイプ窓のCSSを少し変更。

とりあえず、もう現状この状態で十分である。考えているのはワイプ窓の中身を外部ファイルから読み込むというものだが、そもそも十行くらいのテキストだし、ここ以外で使う想定も現時点ではないので、直接書いておいても、今は問題ない。

たとえば、この窓の上にタブを並べておき、「プロジェクトリスト」「連載リスト」「日課リスト」と分けてみてもいいだろう。そのようにして外部ファイルを読み込めれば面白いが。

でもまあ、このくらいの分量であれば、わざわざ分ける必要はないか。分けることで、タブをクリックせず、中身が目に入らない可能性がある。

「レシート・メモ処理」の項目が若干浮いている感じがして、それを切り分けたいのだろう。MainとSubにわけてもいいが。デイリーミッション?

* * *

Image from Gyazo

一応表示だけタブを付けてみた。

若干鬱陶しい気はする。リストの整理自体は区分けした方が進むだろうが、そうやって小綺麗で小さなリストを作ると、ついつい項目を増やしたくなるのではないか。こういうコミットメントに関するリストは、そういう肥大化はよろしくないのではないか。

まあ、使わなかったから後から消せばいいか。今は(どうせ表示の切り替えはできないので)、このまま表示しておくことにしよう。

プロジェクト管理についての検討は、とりあえずここまでとする。

10:00

Textbox:

上記はそれでいいとして、思考実験で実装した「Textboxのワイプ窓」機能について考えたい。

あるページの中身に、別のページの中身を使えるようにすること。

現状は、Textboxの本体ページ(index.html)に、javascriptで「mdファイルの中身を読み込む」という機能を設けている。この機能は、書き込む先のDivが決定されている。

よって、ページ内部で別ページの中身を表示させるには、上ととは違う関数を書く必要がある。

というところで気がついた。そうか、こういうときにオブジェクト指向の継承なりなんなりをつかえばいいのか、と。

たとえば、xという関数オブジェクトがあり、それが内部変数として書き込み先のdivの情報を持っている。で、読み込むファイルを与えれば、その内部変数を参照して読み込みを実行する。そういう流れ。で、xの関数オブジェクトを生成するときに、初期値として書き込み先を与える。

こうなると、x型の関数オブジェクトAでは、Textboxのmainboxにページの読み込み&表示を行い、x型の関数オブジェクトBでは、ページのワイプ窓に表示を行う、ということができる。書き込み処理を変えたければ、おおもとのxという関数オブジェクトの処理を書き換えばいいだけ。

これがたぶん、「オブジェクト指向っぽい」コードの組み立て方なのだと思う。

実際にうまく書けるかはわからないが、そういう理路を取れば、それぞれのページが独自に「ページを読み込む関数」を使えることになる(今までは、自分が読み込まれているそのdivの中身を書き換えることしかできなかった(つまりリンク))。

* * *

と、ロジックはわかったが、実際にコードが書けるかは別問題である。

初心者のためのオブジェクト指向 JavaScript - ウェブ開発を学ぶ | MDN

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
function Person(first, last, age, gender, interests) {
  this.name = {
     first : first,
     last : last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
  this.bio = function() {
    alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
  };
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name.first + '.');
  };
}
1
let person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

上記をそのままトレースすれば、function pagedraw(target){}を定義し、メインとなるindex.htmlでは、new pagedraw(mainboard)みたいなものを作り、読み込みはpagedraw.pagedraw()みたいに実行する(ネーミングが最悪なことになっているな)。

で、それぞれのページでも、読み込み処理を行いたいならば、new pagedraw(ワイプ窓)とかnew pagedraw(付箋)などの書き込み先の情報と読み込み機能を持った関数オブジェクトを作ればいい、ということか。

名前はどうなるか。pagedrawオブジェクトでいいか。

* * *

できました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function loadedFile(target){
  this.target = target;
  this.drawPage = function(file) {
    var result1 = document.getElementById(this.target);
    var xhr = new XMLHttpRequest();
    xhr.open('GET',file, false);
    xhr.setRequestHeader('Pragma', 'no-cache');
    xhr.setRequestHeader('Cache-Control', 'no-cache');
    xhr.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT');
    xhr.onreadystatechange = function(){
        // 本番用
        if (xhr.readyState === 4) {
          if (xhr.status === 200){
            result1.innerHTML = replacLinkBtn(marked(xhr.responseText));
            setOnClickEvent()
            }else{
            result1.innerHTML =  "<p>" + file +  "はまだ存在しません。</p>" + "<a onclick='appendtext(\"list/ページ呼出.md\",\"[[" + file.slice(5, -3) + "]]\"); setalert(nowPage);mainPage.drawPage(\"ページ呼出\");'  class=\"btn btn-primary\">ファイルを作成する</a>";
            }
          }};
    xhr.send(null);

    readScript();
  };
}

これで、new loadedFile すればそれぞれのページが好きな要素に他のファイルの内容を読み込ませることができます。これで「再帰性」の強度がさらに高まりました。

* * *

たとえば、買った本のリストと、未消化のtodoのリストをそれぞれ別ファイルで作っておき、それとは別にそれらを統合して表示するファイルを作る、ということができるようになります。だいぶ無敵感が出てきましたね。

12:00

Textbox:

スクリプトの実行周りで問題発生。

あるページを呼び出したときに、別のページの内容を初期状態で表示させる場合は、初回のロード時に読み込み処理を行うことになる。

で、その「ページを読み込んで、表示させる」という一連の動作の最後に「スクリプトが含まれていたら実行する」がある。で、そのスクリプトが「今のファイルのスクリプトなのか、読み込み先のスクリプトなのか」を区分けしていないので、そのページのスクリプトである「最初にページを読み込んで、スクリプトを実行する」が永遠に繰り返されてしまう。

ふむ。

* * *

現状は、ページの描写が終わったらとに、readScript()を実行している。それが描写の関数の一部になっている。

で、そのreadScript()は、今表示されているページにscriptタグを追加する、というもの。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//スクリプトの読み込み
  function readScript(){
    var addScript = document.getElementById("init");
    if (addScript){
      if (document.getElementById("temp")){
        document.getElementById("temp").remove();
      }
      var loadscript = document.createElement('script');
      loadscript.id = "temp"
      loadscript.innerHTML = addScript.innerHTML
      document.body.appendChild(loadscript);
    }
  }

読み込んだファイルには、scriptタグにinitというIDが付けてあるので、その情報を読み取り、それを新しく作るscriptタグの中身とする。その後、追加する。

ページ内で別のページを呼んだときも、これが動く。でもって、今表示されているページもinitというidが付いたScriptタグがあり、それが実行される。そのスクリプトに「別のページを呼ぶ」が含まれていると、永遠とそれが繰り返される、という再帰的な循環。

まず思いつく解決は、ページ内で呼ぶページの場合は、このreadScript()を実行しない、というもの。ページ内呼び出しではスクリプトを禁止する、ということ。これであれば、循環は止められる(実装方法はわからない)。ただし、いくつかのページを呼んでいるページたちをさらに呼び出して、「総合総合ページ」みたいなものは作れないことになる(それは別に構わないが)。

別の方法はないか。実行するスクリプトを何かしらで限定する方法。

重複を確認する?

ファイルを読み込んだらフラグを立て、それが経っている間は同じ読み込みをしない、というような。

いや、待てよ。たとえば、「このページを再読み込みする」(ブラウザのリロードではなくTextboxの機能で)を行うときは、どうなるか。その場合でも、期待する状態になるか。

* * *

整理する。

readScript()は「ページを読み込む」処理を内側に持つので、readScript()で実行されるスクリプトの中に「ページを読み込む」が含まれていると無限に続いてしまう。これをどう解決するか。

今表示されているページと読み込むページが一緒ならば中止する、という場合、単純に再読み込みしたい場合にうまくいかない。

* * *

やっぱり、サブで呼びだすときはScritpを使わない、というのが良さそうではある。

* * *

今のところ、readScript()は loadedFileの関数オブジェクトの中でしか使用されていない。

であれば、どうなるか。

今のところ、readScript()は、表示されているページ全体を対象としている。これを限定すればいいのではないか。読み込んだファイル部分だけからスクリプトを探す、というように。

読み込みは、こうなっている。

result1.innerHTML = replacLinkBtn(marked(xhr.responseText));

で、このinnterHTMLにはscriptタグも含まれているのだが、そのままでは実行されないのでScriptタグを追加する、という動作を加えている。

読み込んだ、そのファイルのscirptだけを追加するならば、今表示しているページのscriptは関係なくなる。

readScript()の引き数にresult1.innerHTMLを与える?

* * *

できました。

これまでは、idがinitである要素を探していましたが、以下のように書き換え。

var addScript = document.querySelector("#” + targetarea + " > script”)

targetareaは、その関数オブジェクトの実体が持っている描写する対象のエリア名です。

これでScriptタグにinitというidを割り当てる必要もなくなりました。ただし、同一document内に複数のScriptが追加されるので、名前の衝突などには注意が必要ですね。

* * *

さらにです。ページを描写した後に、これまではすべてのボタン属性を持つ要素にリンク処理を施していましたが、先ほどの考えを用いれば「ページを読み込んだ、その対象領域内」に限定することができます。やってみましょう。

こういう感じで良さそうです。

const btnObj = document.querySelectorAll(targetarea + " .linkbtn”);

これまではページを読み込むたびに、全要素にリンク化処理が行われていましたが、移行は読み込んだファイルの内部だけにその処理が行われます。Good。

14:00

Textbox:

以前、Textboxに情報を「送る」ということについて考えていたが、Boardに設置したワイプ窓がその役割をはたすのではないか。

自分に送りたい情報があれば、それをどこかのファイルに保存しておく。で、そうした情報をBoardのワイプ窓に表示させる。そうすれば、「自分で見に行く」必要はなくなる。Boardを見たときに自然に目に入る。一方で、Boardをどうにかする必要はない。

たとえば今はタブでワイプ窓の内容を切り替えることを考えているが、一定時間で切り替わってもいい。何かしらテキストファイルの状況を見て、優先的にそれを表示させる、ということもできたら面白い。

表示させたいものを事前にいくつか選んでおき、ランダムにそれを表示させていくスライドショー(スクリーンセーバーのようなもの)にしてもいい。夢は広がる。

18:00

TH:

では、原稿を進めましょう。

* * *

少し手直しして、3700字くらい。もうちょっと書いて4000字くらいを一つの目標にしたいところ。

19:00

『Re:vision』:

003の手直しを進めます。

* * *

003の80行目まで直しました(全体はだいたい400行)。話題の展開が若干「はやい」ですね。もうちょっとペースを落としたほうがいいかもしれません。

20:00

prebooks:

取り合えず、テキストファイルだけ作っておきます。newsletterで書いた原稿をコピペしてprebooksのフォルダに。

* * *

その他こまごまとしていたフォルダの中身を、prebooksかTextboxのどちらかに移動。最終的にはprebooksもTextboxに配置されるのではないか。

とりあえず、prebooksに移動したファイルの整理も必要ですね。

duolingo:

21:00

本日の振り返り:

今日は、だいたいコードを書いていました。既存のコードをリファクタリングすることで、新しい機能をスマートに追加できたと思います。頻繁に使うかどうかはわかりませんが。

メモの処理も道筋がつき、プロジェクトの管理も見通しができました。企画になる前のアイデアノートの扱いもだんだん固まりつつあります。よいことです。

そういうのを一通り固めてしまって、あとは執筆作業に邁進したいところです。

というわけで本日はそろそろ閉店がらがらです。

お疲れさまでした。仕事終わりの妻を迎えに行ってきます。