新・日々録 by TRASH BOX@Eel このページをアンテナに追加 RSSフィード

2018-04-15

エンジニアにとって「コミュニケーション能力」とは何を意味するのか?

世の企業も求むる「コミュニケーション能力を持つ社員」といふものを、エンヂニアリングの現場でも求めてみむとてするなり。

コミュニケーション能力」という言葉は実に曖昧で、10人いれば5〜6パターンぐらいは異なる解釈が出てきそうな代物だ。この文章では、ソフト屋さんを含む「エンジニアリングの現場にいる技術者」に求められるコミュニケーション能力の実体について、基本的なところを述べてみたい。

(ただし私はプログラマなので、ソフト屋寄りの見解となる)

コミュニケーション能力を「社会生活を営む人間の間で知覚・感情・思考を伝達するための能力」であると仮定した上で、掘り下げてみよう。

コミュニケーション能力を獲得するための第一歩は、経験の言語化だ。一般に、人間はことばという共通のフレームを用いて情報を伝達する。経験を言語化できなければ、経験を相手に伝えることができないし、また相手の言葉を理解する(ことばを経験にマッピングする)こともできない。

一般的に、経験の言語化は幼少期に家族などの特定の親しい人との会話によって形成され始めるらしい。ただ、発達障害(とくに自閉症)の場合、会話によってこの辺の能力を形成していくのが難しい傾向にあるようだ(ではどうすればよいか、という点については色々と研究されている模様)。

経験を言語化できていると仮定すると、次の論点は、発達心理学でいう一時的ことばと二次的ことばだろう。

一時的ことばは、同じコンテキストを持つ親しい相手と1対1でコミュニケーションする際に用いることばだ。経験の言語化が、幼少期に家族などの特定の親しい人との会話によって培われるために、一時的ことばは「お互いについての知識・経験を共有している」という前提のものとなる。だから、不完全な表現であっても相手は共有する知識・経験から補完して理解することができる。

二次的ことばは、未知の人も含む不特定多数の人とコミュニケーションする際に用いることばだ。この場合、「お互いについての知識・経験を共有している」という前提は成立しない。そのため、情報を発信する側は、発信する情報を理解するために必要な情報を全て言語化し、整理した上で、表現する必要がある。同時に、情報を受信する側は、内容を理解するために必要な情報を全てことばの文脈から抽出し、個々の情報の関連付けを行うことで、理解する必要がある。

二次的ことばは、スピーチのように不特定多数にたいして語る場面だけでなく、チームミーティングでの進捗報告や、業務手順書の作成のように、「ある程度共通するバックグラウンドを持つが、『家族などの特定の親しい人』ほどはお互いについての知識・経験を共有していない、特定少数の人々」との情報伝達でも用いられる。お互いに共有している知識・経験が限られているため、情報を発信する際には、相手が内容を正しく理解するに足るだけの情報を提供しなくてはならない。

社会人に求められるコミュニケーション能力は、「二次的ことばによる情報の伝達がスムーズに行える」ということである。つまり、自分が伝えたい内容について相手側の知識・経験が乏しい場合でも正しい情報を伝達できることであり、その逆に相手が発信する場合にも会話・文章ということばだけから正しい情報を理解できることである。

要するに「話が面白い」とか「会話が弾む」などの面で評価が高い人であっても、それが「一時的ことばによる身内間での情報伝達」に留まるのならば、それは「社会人に求められるコミュニケーション能力」を兼ね備えていることを意味しない。

さて、二次的ことばによるコミュニケーションでは、情報を全てことば(相手の話した内容や、文章に書かれている内容)だけから理解していく必要がある。これを実現するには、ことばに含まれる単語を正確に理解し、単語を連結している文法を正確に理解する必要がある。また自分自身が発信側となる場合には、単語を正確に用いつつ、単語を連結する文法を正確に用いなくてはならない。

社会人(というか職場)でのコミュニケーションで用いられる単語には、日常でも用いられる単語だけではなく、その環境に応じた専門用語・業界用語の類も含まれる。エンジニアコミュニケーションにおいては専門用語が多用される傾向にあるので、各専門用語の意味を正確に理解して用いる必要がある。

なぜ専門用語が多用されるのか? お互いに「相手はその専門用語を知らない」という前提でコミュニケーションしようとすると、内容が冗長になりすぎて、全てを伝えるのに時間がかかりすぎてしまうからだ。だから、専門用語として厳密に意味を定義した上で、双方とも定義された意味を理解しているという前提で情報伝達を行うのである。

例えるなら……バリカタを知らない人にバリカタという言葉を使わずに「あのラーメン屋のバリカタは柔らかすぎでバリカタじゃない」ということを伝えようとするようなものである。バリカタのラーメンを食べたことがない人は、バリカタを「通常よりもかなり硬い麺」に置き換えて説明されたとしても、そもそもバリカタの硬さを理解していないので、「あのラーメン屋のバリカタという名の『バリカタよりも柔らかい麺』」がどの程度の硬さなのか類推できない。だから、単に「通常よりもかなり硬い麺」に置き換えるのでは駄目で、相手が食感を覚えている食べ物のうち、「バリカタに近い硬さのもの」と「あのラーメン屋のバリカタという名の『バリカタよりも柔らかい麺』に近い硬さのもの」を探り出して提示しなくてはならない。しかし身をもってバリカタを知っている人同士ならば、バリカタで十分通じるものだ。だから時には「話をする前に、今から『本当にバリカタのラーメン』と『バリカタという名のバリカタよりも柔らかい麺のラーメン』を食べ比べに行こうぜ!」という方法も有効だ。ことばで説明するよりは早く済むだろう。でも食べ比べの時間は余分にかかるから、結局は、バリカタを知っている人同士の方が情報伝達が早く済むことになる。

エンジニアが用いる専門用語は、その職場・チームといった環境に特異のものだけでなく、他の環境のエンジニアを含むもう少し広い範囲(例えば業界)にて共通言語として用いられる専門用語もある。例えばソフトウェアエンジニアの場合、基本情報技術者試験に出てくるような用語は、専門用語の中でも広い範囲で用いられるものだ(スレッドという単語が通じるソフト屋さんは少なくないはず)。そういった公知の専門用語をどれくらい正しく理解して使用できているか――という点もエンジニアコミュニケーション能力に含まれてくる。

ただし専門用語知識の有無は人によって異なるので、情報を発信する側は、文脈によって専門用語を用いるか否かを切り替える必要がある。例えば、新入社員と会話する時と同期の社員と会話する時では、前者よりも後者の方が専門用語の割合が多いはずだ。

また、エンジニアコミュニケーションでは、抽象度の高い事象や、大きくて一度に理解できない事象を取り扱うことが多い。そのため、同じ情報を後から何度でも参照できるように、会話だけでなく「文章を用いた二次的ことばによるコミュニケーション」が多用される傾向にある。文章によるコミュニケーションでは、会話でのコミュニケーションでは可能な「その場のニュアンスで不完全な表現を補完する」ということが不可能なので、単語の内容や、単語を連結する文法を、会話の場合よりも正確に用いなくてはならない。

その上で、文章だけでは抽象度の高い事象を正確に伝達できない可能性があるため、時には適切な図表を用いる必要もある。事象によっては数式で表現することもあるだろう。ソフト屋の場合は、時にソースコードという人工言語にて他のエンジニアコミュニケーションを図ることもある。

つまるところ、文章と図表を用いて情報を正確に発信できること、文章と図表から情報を正確に読み取ることができること、この2点である。この辺りは、大学教育でのレポートや論文の作成にて発信側を、レポート・論文作成の際の文献調査にて読み取り側を研鑽するように思う(で、その前提となる「普通の文章の読み書き能力」は義務教育で学ぶ……と書いてしまって大丈夫だろうか?)。

まとめると、エンジニアに求められる「コミュニケーション能力」とは、以下を兼ね備えていることである。

  1. 二次的ことばによる情報の正確な伝達をスムーズに行うことができる。
  2. 文章と図表による情報の正確な伝達をスムーズに行うことができる。
  3. 専門用語を正しく理解して使用することができる。

基本的に、エンジニア同士のコミュニケーションでは「正確な情報をスムーズに」という点が重視される。エンジニアが取り扱う事象の大半は、抽象度の高いものや、大きくて一度に理解できないものなどの、複雑な事象だ。複雑なものを取り扱うには正確な情報が必要であるし、複雑なものを取り扱うことに集中するためにも余分なコスト(「情報が不正確かもしれないので再検証する」という時間的ムダなど)を払いたくないものだ。

特に、簡単な事象が過去に解決されてきた積み重ねの結果、エンジニアリングの現場にて取り扱う事象が高度化している昨今では、複雑な事象にチームで取り組むことが多い。『人月の神話【新装版】』のブルックスの法則にて言及されているように、チーム内で相互コミュニケーションが求められる場合、コミュニケーションの労力は人数nの時「n(n - 1) / 2」に比例する。このような本質的問題を抱える状況において、「情報が不正確である」とか「情報は正確だが、読み解くのに苦労する」などの偶有的問題まで発生したら、進むものも進まない。それゆえに、エンジニアは「正確な情報をスムーズに」という点を重視する傾向にある。

だから、世間一般で言われるコミュ障(雑談が苦手・苦痛なタイプ)でも、業務上必要な情報を正確かつスムーズに伝えられるのなら、大抵は問題ない。もっとも、コミュ障ゆえに対人関係の構築に不慣れな場合、業務上必要な情報を伝達する際に相手が把握している情報量をうまく推測できないために、「どこまで情報を付与すれば相手が理解できるか/どこまで省略しても相手が理解できるか」を見誤ることはある*1

まあ、最初から上記3項目を全て高いレベルで身に着けている新卒社員は少ないだろうから新人教育やOJTで最低限鍛えるぞ――というのがジャパニーズ・トラディショナルカンパニーの伝統行事なのだが、しかし会社にも「許容できる教育コスト」に上限がある。だから、新卒採用にて「コミュニケーション能力のある人=上記(1)と(2)がある程度の水準に達している人」を求めるのだ、その辺の能力を正しく計測できて採用できているか否かは別として*2

*1:難しいよね。

*2:多分できていない。

2018-04-01

実はオブジェクト指向ってしっくりこないんです?

――いや、自己分析するに、「オブジェクト指向」ではなく「特定のオブジェクト指向プログラミング言語」がしっくりこないことがあるんだな、これが。

具体的には、触ったことのある言語ではJavaC#だ。この2つの「しっくりこなさ」具合からすれば、C++の方がマシだ(もっとも、C++は別の部分で好きになれない面があるのだが*1)。

C#は経験が浅すぎるので、Javaについて。Javaは、ここ数年の間にちょっとしたコンソールアプリの実装とAndroidアプリの開発で使用した。興味深いことに、コンソールアプリを書いた際は「しっくりこなさ」全開だったのだが、Androidアプリを書いた時にはその手の違和感はなかった。

この違いは何だろうと考えて、ふと気づいた。おそらく私は、クラスの定義を強要されることに違和感を感じる体質なのだ。

私のプログラマとしての土台(第一プログラミング言語)はC言語だ。C言語にはクラスはない。次に使うことが多いC++は、クラスを定義するも定義しないも活殺自在な言語だ。JavaScript/JScriptVBScriptも、クラスを定義する/しないは比較的自由だ。小ツール実装で時々使うRubyPythonは、ちょっとしたスクリプトであれば構文の見た目として「クラス定義なんて知らないよっメソッド定義だけだよ!」風に記述できる。

これらの言語のうち、C言語C++アプリケーションメインエントリは関数だ。JavaScript/JScriptVBScriptRubyPythonでは、必須構文としてのアプリケーションメインエントリ的なものはない*2

つまり、C言語を除けば、コードの見た目として「必要になったらクラスを定義するが、必要なければ使わない(関数メソッドを単独で定義して用いる)」というスタイルで記述することが可能な言語に慣れている(そしてC言語にはそもそもクラスが存在しない)。

しかしJavaC#は、例えばC++にてmain関数と2つのサブ関数で記述できるような小ツールであっても、クラスを定義した上でmainメソッドを記述しなくてはならない。この時点で、何というか「この程度のことでクラスを持ち出すなんて……」と思ってしまうのだ。

その一方で、Androidアプリのような複雑な*3ソフトウェア、特にGUIアプリケーションというオブジェクト指向プログラミング的アプローチに向いているソフトウェアでは、クラスを用いる意味もメリットもあるので、違和感を感じることがない。とはいえ、時としてクラスに属しないメソッドを書きたくなることはある。C++ならば名前空間に直接属する関数として、Objective-CならC言語流のファイルによるモジュール分割を用いたデータ結合の関数として定義するだろう、ちょっとした汎用のユーティリティ・メソッドだ。

別の視点から考察すると、どうも私は「構造体(=レコード型)」の影響を強く受けていて、「何らかの関連がある複数のデータ+それらを操作する専用のルーチン=オブジェクト」という意識が強い。C言語で構造体を使用してややオブジェクト指向プログラミングっぽいアプローチをすることもあるが、その場合、「何らかの関連がある複数のデータ」を一まとめにする必要があるならば構造体にまとめるが、必要なければまとめない。

つまり、心理的に「クラス≒抽象データ型≒レコード(複数のフィールド)と操作用ルーチン」という意識がある。抽象データ型として扱うのが妥当ならばクラスにするが、それ以外の用途――例えばJavaJavaScriptのMathクラスのような使い方――でのクラスの採用に消極的というか、クラス以外の代替機能を使おうとする個人的傾向がある。

仮にMathクラスのようなものをC++で再実装するならば*4、個人的にはクラスではなく名前空間を使用して、関数や定数をひとまとめにするだろう。

このようなアプローチは、例えばC++で採用するには問題ない。しかし、慣れ故にJavaC#でも採用しようとしてしまい、メソッドをクラス内でしか定義できないことに気づき、ついついもやもやしたものを感じてしまう。

現実には、プログラミング言語には「言語仕様」という制約がある訳で、その制約の元では、例えば「『C++名前空間』のような機能がないので、代わりにクラスを使う」などのアプローチは合法的だろう。だから、もやもやしたものを感じてしまう必要など全くないのだが……。

結局のところ、慣れの問題なのだ。クラスのない世界での生活が長く、また必要に応じてクラスを定義するか否かを切り替えられる言語に慣れてしまっていて、クラスが必須な言語には慣れていないので、違和感を感じるのだろう。

蛇足:クラスが必須な言語に違和感を感じる一方で、CやC++のような関数が必須な言語(ステートメント関数の中にしか記述できない言語)には違和感を感じないあたり、どう考えても慣れの問題以外の何者でもない。

*1:好きにはなれないが、better Cとして使い方をわきまえている分には便利な言語だと思う。

*2:もしかしたら、私が知らないだけで、アプリケーションメインエントリ的なものがあるかもしれない。しかし、そうだとしても、必須ではない(何らかの構文として記述する必要がない)だろうから、その言語のユーザからすれば「無いも同然」だ。

*3:テキストフィルタよりもGUIアプリの方が複雑だ、という意味での「複雑な」である。

*4:標準ライブラリに用意されている、C言語由来のcmathの数学関数は無視するものとする。

2018-03-18

仕様書・設計書の必要論と不要論の不毛な議論を避けるためのヒント

仕様書や設計書の「要る/要らない」で議論になることがあるが、往々にして不毛なのでここに記しておく。

実のところ「仕様書や設計書は必要だ」という意見も「仕様書や設計書なんて不要だ」という意見も、根本的には同じ問題を出発点としている。

それは「必要な仕様書・設計書を、必要なときに、必要なだけ」というジャスト・イン・タイムの原則から外れている、ということだ。

仕様書や設計書は必要だ」という人は、「必要なドキュメントが存在しない」「必要なときに手に入らない」「内容が不足している」という経験をした人であることが多い。

仕様書や設計書なんて不要だ」という人は、「不要なドキュメントを作らされた」「まだ必要ではないのに作らされた/不要になった後に作らされた」「必要量を超えて作らされた/不要な内容まで書かされた」という経験をした人であることが多い。

結局はどちらも「必要な仕様書・設計書を、必要なときに、必要なだけ」が成立していないのだ。

問題の根っ子は同じなのに、適正レベルからの逸脱の方向の違いというコンテキストの差異にしか目を向けていないために、必要論不要論に分かれてしまうのだ。不毛だと言わざるを得ない。

2018-03-03

そろそろ「美しいコード」って言うの止めようぜ

――と題名の通りの感想を抱いたのだが、「美しいコード」の代替となる上手い言い方が思い浮かばないのである。

いや、記事の内容に異論はないというか、私自身は汚いコードに拒否反応を示す人であるし、未だに「もっと良いコードを書きたいなあ」という欲を持っている。

なんだけど、こう、何というか、「美しいコード」の「美しい」という言葉ゆえに誤解されてしまっている側面があるように思うのだ。

どうも「美しさなんか関係ないだろ!」と否定する人は、「美しい」という言葉ゆえに脊髄反射的に「気難しい職人のこだわり」みたいな解釈をしているように感じられる。どことなく「常のものではない」という意識がある。だから「(常の側にいる私たちには)関係ない」と切り捨ててしまう。

でも実のところ、「美しいコード」の初級〜中級というのは、製造現場に例えると「4S5Sが定着している状態」だと思うのだ。目的は「安全性・効率化・品質向上」で、手段の1つが「4Sないし5S」。これがプログラミングでは、目的は「RASIS」であり、手段の1つが「美しいコード」、という感じだろうか。

「3M(ムダ・ムラ・ムリ)を解消する手段の1つとしての4S/5S」からのアナロジーとして「システム開発の3Mを解消する手段の1つとしての『美しいコード』」と捉えると、「美しいコード」は割と基礎レベル寄りの手法であるし、日常的に定着していないとマズい代物だということになる。

つまり「美しいコード」は常のものだ。それどころか4Sや5Sのような土台・基礎であり、出来てないと「え、そんなこともできないの?」と言われて恥をかくレベルのモノだ。

だから「『美しいコード』って、実は製造現場でいう4Sや5Sなんですよ。基礎中の基礎ですよ」と明確化すると同時に、今後似たような誤解が起こらないように、対外的には「美しいコード」という言葉を封印して、別の言い方をすべきだと思う。

問題は「美しいコード」に代わるパワーワードが思い浮かばないことだ。「良いコード」だとインパクトに欠けるしなあ。

2018-02-10

2〜3世代前のOS X/macOSの実行環境を整えるためのメモ

最新版を含む過去4世代OS X/macOSをbootできる環境を整えているのだが、環境構築の過程で得られた知見を残しておく。

なお、このメモはOS X Mavericks(10.9)以降を前提としている。執筆時点での最新のOSmacOS High Sierra(10.13)である。

どこまで古いOSインストールできるか?

Windowsの場合、例えばWindows 10プリインストールPCであっても、Windows 7に対応したデバイスドライバが公開されているなら、Windows 7でも問題なく動作する可能性が高い。しかしMacはそうではない。

現在のMacハードウェアOS双方を含めてクローズドなシステムだ。そのため、Mac本体の各デバイス用のドライバを独自に入手する術がない。OS付属のデバイスドライバを使用するしかないのである。

そのため論理的には、あるMacの機種に、その機種にプリインストールされていたものよりも古いOSを入れようとした場合、必要なデバイスドライバが古いOSに含まれていないために正常に動作しない、という可能性がある。

(もしかしたら、OSインストーラ側にてガードがかけられていて、古いOSインストールできないようになっているかもしれないが、試していないので不明である)

少なくとも、当該機種の発表時に搭載されていたOS以降のものを入れるべきだろう。例えば、購入時にOS X El Capitan(10.11)がインストールされていたMacには、El Capitan以降のOSのみ入れるべきだ。間違ってもMavericksを入れようとするべきではない。もしMavericksの動作環境を構築したいなら、古いMacを入手してインストールするか、ParallelsVMwareなどの仮想環境にゲストOSとしてインストールするべきだろう。

古いOSインストール

用途次第ではあるが、過去数世代のOSを入れるとなると、各バージョンごとにそこそこのディスクスペースが必要となる。なので内蔵ディスクではなく外付けHDDなどに入れるべきだろう。*1

古いOSインストーラの入手方法

El Capitan以前のOSインストーラは、過去にApp Storeからダウンロードしたことがあるのなら、App Storeの「購入済み」タブから再ダウンロードできる。

過去にダウンロードしたことがないために「購入済み」タブから再ダウンロードできない場合は、OS X El Capitan をダウンロードする方法 - Apple サポートに書かれているように、このリンク経由でApp StoreOS X El Capitanのページを開いて、そこからダウンロードすることができる。MavericksOS X Yosemite(10.10)のページは既に存在しないようなので、過去にダウンロードしたことがない場合、通常の手段で入手することはできなさそうだ。

macOS Sierra(10.12)以降は、App Storeからダウンロードしても、「購入済み」タブに表示されなくなった。

Sierraインストーラを入手したい場合は、macOS Sierra をダウンロードする方法 - Apple サポートに書かれているように、このリンク経由でApp StoremacOS Sierraのページを開いて、そこからダウンロードすること。

High Sierraこのリンク経由でダウンロードできるが、El CapitanないしSierra上のApp Storeからダウンロードしないと、全コンポーネントが含まれた状態のインストーラを入手できないようだ。

なお上記のいずれか場合も、過去にダウンロードしたインストーラがディスク上に残っていると、再ダウンロードができない可能性がある。この場合は、ディスク上のインストーラを削除してから再ダウンロードを試みること。

特にありがちなのは、例えばSierraの公開直後に10.12のインストーラダウンロードしていて、1年後のHigh Sierra公開前後にSierraの最終版である10.12.6のインストーラダウンロードしようとして、10.12のインストーラが残っていたために再ダウンロードできない――というパターンである。注意すること。

インストールメディアの作成

ダウンロードしたインストーラmacOS上でアプリケーションとして実行可能だが、インストーラに付属するcreateinstallmediaを使用してインストールメディアを作成することも可能だ。対象メディアUSBメモリや外付けHDDだ。

作成方法についてはmacOS の起動可能なインストーラを作成する方法 - Apple サポートを参照のこと。

(前述のサポート情報にも書かれているが)High Sierraインストーラは、El CapitanないしSierra上のApp Storeからダウンロードしないと、全コンポーネントが含まれた状態のものが入手できず、結果としてインストールメディアを作成できないので、注意すること。

*1Windowsユーザ向け補足:Windows PCでは、外付けディスクにWindowsを入れることは不自然というか、Microsoftのポリシーの関係で普通にはできない所業なのだが、一方でMacでは割と普通なことである。