openSuSEネットワークインストール(11.3から12.2へ)

新年明けましておめでとうございます。
今年は抱負をパッと言えるくらいのアドリブの強さを身につけていきたいpneuです。


さて、openSuSEのサポートが15日で切れるようなのでアップグレードをしました。
# といってもlinuxに触れるのは久しいのですが。


今回はブランクのDVDが無かったということもありネットワークインストールを行いました。
これまでDVDインストールをしたことがある人であれば、下記のドキュメントが全てです。

http://en.opensuse.org/SDB:Network_installation#Media_free_network_installation


作業自体はとても簡単ですが、時間とディスク容量には気をつけましょう。
4.7GB DVD版を使用する場合に比べて3倍近く掛かりました。
また、ディスク容量が足りない場合にはインストールに失敗して中途半端なシステムが残ると思います。


それでは、よいお年を。


(以降は、インストールの中で気になったことのメモ)

続きを読む

窓使いの憂鬱で&ShellExecuteが遅い

&Sync &ShellExecute("open", "%SystemRoot%/explorer.exe", "/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", , ShowNormal)

&Sync &ShellExecute("open", "C:/WINDOWS/explorer.exe", "/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", , ShowNormal)

&Sync &ShellExecute("open", "C:\\WINDOWS\\explorer.exe", "/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", , ShowNormal)

この3つの表記で最後のが一番早かった。何故。

仕事場にlinuxシェル環境が無いので作りました

https://github.com/pneu/copytask


ファイルをコピーするだけのスクリプトです。
config/sample*.vimを参考にコピーしたいファイルを追加して、run.batを叩けばうまくいくと思います。
windowsのタスク機能?とか使えば、必要なときにほしいファイルをコピーしてこれるでしょう。

経緯

朝イチで共有PCからファイルをコピーして仕事を進めてますが、
いくつものPCにアクセスして特定のファイルをコピーするのが面倒なので作りました。
# 2分掛かってたのが10秒で済むようになったよ!
bash環境があればスクリプト書いちゃうんですが、
現状、手元にあるのがvimとcmd.exe、ってな感じの貧弱環境で仕事中ですのでこんな感じになりました。


ネット見れればdosbatchの文法調べて・・・ってなことも可能だったんだろうけど。
vimはhelp付いてて助かる。

c++の関数テンプレートと参照

関数テンプレートでは、型がバインドされるようなので、
こんな書き方ができるみたいです。

template <size_t N>
unsigned int foo(const char (&str)[N])
{
	return N;
}

int main(void) {
	std::cout << foo("foo") << std::endl;
	return 0;
}

これはstrを参照で渡しているからできることですね。
# 型がconst char [4]になります
Cじゃ配列数は渡せないんじゃないかなあ・・・


これの元になったコードを見たときに、
Nがどこから来ているのか分からなかったので、びっくりしました。


というわけで、脈絡もなく階乗のコード置いておきますね。

template <size_t N>
unsigned int foo(const char (&str)[N]) {
	return N * foo(reinterpret_cast<const char (&)[N-1]>(str));
}

template <>
unsigned int foo(const char (&str)[1]) {
	return 1;
}

int main(void) {
	std::cout << foo("foo") << std::endl;
	return 0;
}

実装によるのかもしれませんが、
参照とポインタって出力されるコードが同じなのですね。

void foo(const char *str) {
	str[0] + 'a';
}

int main(void) {
	foo("foo");
	return 0;
}
void foo(const char (&str)[4]) {
	str[0] + 'a';
}

int main(void) {
	foo("foo");
	return 0;
}

って感じでgccで試してみましたが、関数シンボルとファイル名しか違いがありませんでした。
アセンブラについてあまり知識はないので割愛

オブジェクト指向のこころ・10章・練習問題

基礎

  • 切り出すという言葉と抽象的側面という言葉を定義してください
    • 切り出す(decouple)という言葉は、ものごとが互いに独立して振る舞えるようにする、または少なくとも、それらの関係を明確に述べることを意味している
    • 抽象的側面(abstraction)という言葉は、具体例から一歩引いた、さまざまな物事における概念的な特徴を指している
  • Bridgeパターンのコンテキストにおける実装という言葉を定義してください
    • 抽象クラスとその派生物が自らを実装するために必要とするものを指している(抽象クラスの派生物、すなわち具象クラスを実装と呼ぶ場合もありますが、ここで意味する実装とは別のものです)
    • (著者より)抽象的側面の実現方法を指している、わけではない
  • シーケンス図の基本要素(basic element)とは何でしょうか?
    • (わからん;「基本要素」が指す意味がわからないので、答えられない)
    • 英訳より:
      • 図の最上部にある箱は、注目すべきオブジェクトを表しています。
      • オブジェクトには名前が付けられていることがあります(付けられていないこともあります)。その形式はobjectname:classnameとなります。
      • 縦の点線はswim laneと呼ばれるもので、各オブジェクトの時間を表しています。
      • 水平や縦に引かれた矢印は、オブジェクト間のメッセージのやり取りを表しています。その意味を表すラベルが、個々の矢印に付いています。
      • ノートは、オブションです。
  • パターンの使用方法に関するAlexanderの観点とは何でしょうか?彼は、まず最初に解決策から考察することを提唱しているのでしょうか?
    • 解決策を考察するのは、二の次である。それは以下のAlexanderの言による。「各パターンとは、我々の環境で何度も繰り返される問題を描写し、その後、問題を解決する上での革新を描写することで。。。」
    • まず考察すべきは解決策ではなく、パターンのコンテキスト、つまり解決しようとしている問題に着目することである。
    • これはパターンが提供する解決策を重視してしまうと、問題そのものを理解することなしに、問題領域の中からパターンが適用できそうな部分を探し出すというアプローチを取ってしまいがちであり、結局何をするかは見当がつくものの、いつそれを使うのか、と何故それを使うのかといったことが分からないままになってしまうから。
  • 共通性分析では何を洗い出そうとするのでしょうか?可変性分析では何を洗い出そうとするのでしょうか?
    • (8章より)共通性分析では、時が経っても変化しにくい構造を見つけるものであり、可変性分析は変化しやすい構造を洗い出すものです。
    • 言い換えれば、問題領域中の特定部分に流動的要素がある場合、共通性分析によってそれらをまとめる概念を定義することができる。こういった概念は、抽象クラスによって表現できます。
    • そして、可変性分析によって洗い出された流動的要素は、具象クラス(つまりその抽象クラスから派生したクラス)によって実装されます。
  • Bridgeパターンが解決する問題とは、基本的にどういったものでしょうか?
    • Bridgeパターンは、ある抽象的側面とさまざまな実装が共存している場合に利用することができます。このパターンにより、実装と抽象的側面を、お互いの存在を気にかけることなく別々に変更できるようになるのです。
    • 抽象的側面の増加(要求追加、要求変更)によって、その実装を担うためのクラス数の爆発が生じるケース
  • 「1つの場所には1つの規則」という戦略を定義してください
    • 何かを行うための規則がある場合、それを1度だけ実装するように心がけること
      • 例えば、共通で呼ばれる規則(メソッド)をインタフェース側で呼ぶことで、1度だけ実装されることになる。(派生クラス側で実装しない;実装するとしたら、可変性のみを派生側に押し込めるように設計すること)
    • 通常はこれを実践することで、小さなメソッドを保持したコードが大量にできることになるため、若干の追加コストが発生しますが、重複を避けることができるとともに、将来的に発生するさまざまな問題の芽を摘むことができるのです。重複によって、同じものを入力するという無駄な作業が発生するだけでなく、将来の変更時に修正部分を漏らしてしまうという問題も引き起こされるのです。
  • Bridgeパターンの因果関係とは何でしょうか?
    • オブジェクトが使用している実装を、そのオブジェクトから切り離すことによって、拡張性を高める。クライアントオブジェクトは、実装に関するあれこれを気にする必要がなくなる。

応用

  • GoFはBridgeパターンの目的を、「実装から抽象的側面を切り出して、それらを独立して変更できるようにする」ことであると述べています。
  1. この意味を解説してください
    • 抽象的側面(abstraction)がその実装から独立している、ということ
  2. 例を挙げてください
    • Shapeクラス(=抽象的側面)は自分が知っているオブジェクトに対して責任を持っており、Drawingクラス(=抽象的側面の実装)は描画ルーチンの実装(;この「実装」は前の『実装』と意味が異なる)に対して責任をもっている。個々の形状はどのように描画されるかについて知っている必要はない。
  • 結合度が高くなると、何故クラス数の爆発が生じるのでしょうか?
    • 結合度が高いと、抽象的側面の追加によって、実装の追加をその分行わなければならないため。

結合度が高いと、抽象的側面の追加によって増えたクラスや変数に対する実装の責任を、それぞれのクラスや変数がもつことになるため。

あなたの意見

  • 「オブジェクトの振る舞いではなく、責務に着目してください。」こういった文章によって、継承の使用方法に対するあなたの考え方に、何らかの変化があったでしょうか?
    • 責務に着目することは、責任を果たすべきオブジェクトの存在を示唆する。この事でクラス分割(分割という言い方がこの書籍的によいかは分からないが。)がよく見えてくる。。。のでは?
    • 振る舞いに着目するというこアプローチとは、機能分割と同じであると思う。つまりある処理を細かいモジュールに分割できれば、それは誰が使っても良いのであり、クラス分割が進まない。
  • GoFがこのパターンを「Bridge」(橋)と呼んだのは何故だと思いますか?行っていることを考えた場合、これは適切な名前でしょうか?その答えと理由を述べてください。
    • 抽象的側面と、実装をつなぐ「橋」があるため。(図10.13のUMLにある集約のラインを「橋」に見立てているのでは?)