NGW開発BLOG
← 記事一覧へ
·#006

「係長」という役職名は、思ったより難しい

決裁欄の役職名は「所属名+長」で組み立てられそうに見える。だが制度の現実は例外だらけだ。例外を消さず、一箇所に閉じ込めて名前を付けるという設計判断を綴る。

問題設定:「所属名+長」で終わるはずだった

決裁文書には、承認欄に決裁者の役職名を刷る。課長なら「◯◯課長」、係長なら「◯◯係長」。所属名の末尾に「長」を付ければよい——最初はそう見えた。実際、大半のケースはそれで正しく出る。

ところが動かしてみると、ぽつぽつと違う名前が要る場所が現れる。組織の実態を聞き込むほど、単純な文字列連結では届かない例外が積み上がっていった。役職名は、思ったより難しかった。

なぜ例外が生まれるのか:制度がそうなっている

典型が「課の直属の係」だ。ふつう係は課の下の課の中の一組織で、係長の役職名は係の名前から作る。だが、課に係が置かれていない、あるいは係が課へ直属している構成では、係名だけでは決裁欄に何の係長か伝わらない。この場合は課名を冠して「◯◯課◯◯係長」のように表記する必要がある。「所属名+長」という素朴な規則が、組織階層の形によって崩れる。

さらに厄介なのは、呼び方そのものが団体ごとに違うことだ。ある団体では課名を冠さず常に「係長」で固定、別の団体では必ず課名を冠する。どちらが正しいという話ではなく、その団体の慣行がそうなっている。加えて、一般職・特別職・会計年度任用職員・委員や議員では、そもそも役職名の出し方の規則が別立てだ。特別職に「所属名+長」は当てはまらないし、委員は職名の体系自体が違う。

ここで踏みとどまりたいのは、これらを「データ設計の不足」と見なさないことだ。フラグが足りない、マスタが正規化できていない——そう疑いたくなる。だが実際は、現実の制度がそう複雑にできている。制度を写すシステムでは、例外の多くは設計ミスではなく、写し取るべき仕様そのものである。

例外を消さず、一箇所に閉じ込める

例外を相手にするとき、やってはいけないのは各所へのベタ書きだ。決裁欄を刷る帳票はひとつではない。一覧、詳細、PDF、履歴——役職名を組み立てる場所が散らばっている。そこに「課直属なら課名を冠する」「この団体は係長固定」という分岐を都度書けば、いずれ条件が食い違い、同じ文書でも経路によって違う役職名が出る。制度の例外は、書く場所が増えるほど破綻確率が上がる。

採った方針は逆で、係長の役職名を決めるロジックを唯一の関数に閉じ込めた。「課直属か」「団体特例か」の判定は、その関数の中にだけ置く。呼び出す側は係長かどうかと必要な情報を渡すだけで、規則を知らない。

// 呼び出し側は規則を持たない
name = resolveSectionChiefTitle(division, org, tenantRule)

// 規則はこの関数の中にだけ在る
function resolveSectionChiefTitle(division, org, rule) {
  if (rule.alwaysFixed)        return "係長"
  if (org.isDirectUnderKa)     return division.kaName + division.name + "長"
  return division.name + "長"
}

こうすると、新しい団体の特例が来ても直す場所は一箇所で済む。例外の数は減らないが、例外が散らばらない。関数に名前が付いていること自体が効く。resolveSectionChiefTitle という名前は「係長の名前決めには例外がある」という知識を、コード上にひとつの居場所として定着させる。次に触る人は、まずそこを読めばよい。

AIとの協働作業での学び:例外を局所化して名前を付ける

制度を相手にするシステムでは、例外を消そうとしないことが肝心だ。例外は現実の写しであり、消せば制度からずれる。やるべきは、例外を一箇所に集め、名前を付けて他から切り離すこと——この「例外の局所化」が、そのまま保守性を左右する。

そしてこの手の細部は、ドメインを知る作り手でなければ拾えない。「課直属の係だけ課名を冠する」は仕様書に一行あるかないかで、現場の組織図を知らなければ見落とす。制度の襞に気づけることは、制度を写すシステムを作る側の、地味だが決定的な強みだと思う。