2022年2月15日火曜日

ActionCableを用いたチャットアプリの作成

事前準備

今回,下記の手順で動作を検証したバージョンは,Ruby,Railsともに次のとおりである.

$ ruby --version

ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [arm64-darwin20]

$ bin/rails --version

Rails 7.0.2.2

$ 

Railsの雛形を次の手順で用意する.

$ mkdir chatroom

$ cd chatroom

$ rbenv local 3.0.2

$ bundle init

Writing new Gemfile to /private/tmp/chatroom/Gemfile

$ vi Gemfile

Gemfileの # gem 'rails' の行,「# 」を削除してコメントアウトを外す.

$ bundle config set path vendor/bundle

$ bundle install

Fetching gem metadata from https://rubygems.org/...........

Resolving dependencies...

Fetching rake 13.0.6

Installing rake 13.0.6

Fetching minitest 5.15.0

(中略)

Fetching rails 7.0.2.2

Installing rails 7.0.2.2

Bundle complete! 1 Gemfile dependency, 47 gems now installed.

Bundled gems are installed into `./vendor/bundle`

$ bundle exec rails new . -f

       exist  

      create  README.md

      create  Rakefile

   identical  .ruby-version

      create  config.ru

      create  .gitignore

      create  .gitattributes

       force  Gemfile

         run  git init from "."

(中略)

Import Stimulus controllers

      append  app/javascript/application.js

Pin Stimulus

      append  config/importmap.rb

$ 

以上で準備はOK.

チャットルームへの第1歩

roomsコントローラを作る.とりあえず,今回は一つのルームで一つのページしか表示しないSingle Page Application (SPA)なので,showメソッドだけ作ればよい.

$ bin/rails g controller rooms show

      create  app/controllers/rooms_controller.rb

       route  get 'rooms/show'

      invoke  erb

      create    app/views/rooms

      create    app/views/rooms/show.html.erb

      invoke  test_unit

      create    test/controllers/rooms_controller_test.rb

      invoke  helper

      create    app/helpers/rooms_helper.rb

      invoke    test_unit

$ 

config/routes.rb を次のように修正する.localhost:3000/ にアクセスすると,Roomsのshowメソッドにルーティングされるように記述する.

Rails.application.routes.draw do

  root to: 'rooms#show'

end

データベースを作る.

$ bin/rails db:create

Created database 'db/development.sqlite3'

Created database 'db/test.sqlite3'

$ 

今回はテストなので,デフォルトのSQLite3をそのまま使う.

確認

サーバを起動する.

$ bin/rails server

=> Booting Puma

=> Rails 7.0.2.2 application starting in development 

=> Run `bin/rails server --help` for more startup options

Puma starting in single mode...

* Puma version: 5.6.2 (ruby 3.0.2-p107) ("Birdie's Version")

*  Min threads: 5

*  Max threads: 5

*  Environment: development

*          PID: 32482

* Listening on http://127.0.0.1:3000

* Listening on http://[::1]:3000

Use Ctrl-C to stop

ブラウザを立ち上げて,localhost:3000 にアクセスする.

この画面が出ればOK.

メッセージのモデルを作成

メッセージのモデルを作る.文字列(text)型のbodyカラムを一つだけ持つ,たいへんシンプルなモデルである.

$ bin/rails g model message body:text

      invoke  active_record

      create    db/migrate/20220215115613_create_messages.rb

      create    app/models/message.rb

      invoke    test_unit

      create      test/models/message_test.rb

      create      test/fixtures/messages.yml

$ bin/rails db:migrate

== 20220215115613 CreateMessages: migrating ===================================

-- create_table(:messages)

   -> 0.0006s

== 20220215115613 CreateMessages: migrated (0.0007s) ==========================


$ 

モデルを作成したあとは,マイグレーションを忘れずに.

チャットルームのビューとコントローラを作成

次はルームのビューとコントローラを作成する.既に先のコマンドで雛形が作成されている.

app/controllers/rooms_controllers.rb を次のように修正する.Mssageモデルから,全てを取ってきて(Message.all())@messageに入れている.

class RoomsController < ApplicationController

  def show

    @messages = Message.all()

  end

end

部分レンダリングを使うので,app/views/messages ディレクトリを作成する.部分レンダリングとは,ページの一部分だけをレンダリングするものである.今回は多くのメッセージを順番に表示するので,そのメッセージの表示部分だけを部分テンプレートとして用意しておく.

$ mkdir app/views/messages

そのディレクトリに app/views/messages/_message.html.erb を次の内容で作成する.これが部分テンプレートとなる.メッセージのボディ(内容)だけを表示する.

<div class="message">

  <p><%= message.body %></p>

</div>

Roomsのビューも作る.app/views/rooms/show.html.erb を次の内容で作成する.

<h1>Chatroom</h1>

<div id ='messages'>

  <%= render @messages %>

</div>

render @messages というコマンドで,@messages に含まれるメッセージを,部分レンダリングとして用意したものとしてまとめてレンダリングしてくれる.

テストデータの投入

Railsコンソールから,テストデータを投入する.

$ bin/rails c

Loading development environment (Rails 7.0.2.2)

irb(main):001:0> Message.create! body: '庭には二羽鶏がいる'

   (0.7ms)  SELECT sqlite_version(*)

  TRANSACTION (0.0ms)  begin transaction                      

  Message Create (0.6ms)  INSERT INTO "messages" ("body", "created_at", "updated_at") VALUES (?, ?, ?)  [["body", "庭には二羽鶏がいる"], ["created_at", "2022-02-15 12:25:23.071306"], ["updated_at", "2022-02-15 12:25:23.071306"]]

  TRANSACTION (0.5ms)  commit transaction                     

=> 

#<Message:0x0000000123e157e8

 id: 1,

 body: "庭には二羽鶏がいる",

 created_at: Tue, 15 Feb 2022 12:25:23.071306000 UTC +00:00,

 updated_at: Tue, 15 Feb 2022 12:25:23.071306000 UTC +00:00>

irb(main):002:0> 

$ 

とりあえずは一つ用意しておけばよいだろう(複数,用意すれば,部分レンダリングがきちんと対応していることも確認できる).

確認

サーバを起動する.

$ bin/rails s

ブラウザを立ち上げて,localhost:3000 にアクセスする.

コンソールから入力したデータが表示されればOK.

フォームの作成

フォームを用意する.app/views/rooms/show.html.erb を次のように修正する.

<h1>Chatroom</h1>

<div id ='messages'>

  <%= render @messages %>

</div>

<form>

  <label>Leave your message:</label><br>

  <input type="text" data-behavior="room_speaker">

</form>

Railsのフォーム作成用ヘルパーメソッドも使えるが,今回は割愛.

確認

サーバを起動する.

$ bin/rails s

ブラウザを立ち上げて,localhost:3000 にアクセスする.

フォームが表示されればOK.

ルーム・チャネルの作成

Roomに対するチャネルを次のコマンドで作成する.

$ bin/rails g channel room speak

      invoke  test_unit

      create    test/channels/room_channel_test.rb

   identical  app/channels/application_cable/channel.rb

   identical  app/channels/application_cable/connection.rb

      create  app/channels/room_channel.rb

      create  app/javascript/channels/index.js

      create  app/javascript/channels/consumer.js

      append  app/javascript/application.js

      append  config/importmap.rb

      create  app/javascript/channels/room_channel.js

        gsub  app/javascript/channels/room_channel.js

      append  app/javascript/channels/index.js

$ 

app/channels/room_channel.rb が今回使用するチャネルの主要部分である.

サーバ側の処理

app/channels/room_channel.rb を次のように編集する.

class RoomChannel < ApplicationCable::Channel

  def subscribed

    stream_from 'room_channel'

  end


  def unsubscribed

    # Any cleanup needed when channel is unsubscribed

  end


  def speak(data)

    ActionCable.server.broadcast('room_channel',

                                 { message: data['message'] })

  end

end

subscribedメソッドで’room_channel' からデータを取得すること,speakメソッドで各クライアントにbroadcastすることを,それぞれ記述する.

クライアント側の処理

app/javascript/channels/room_channel.js を次のように編集する.

import consumer from "channels/consumer"


const appRoom = consumer.subscriptions.create("RoomChannel", {

  connected() {

    // Called when the subscription is ready for use on the server

  },

  disconnected() {

    // Called when the subscription has been terminated by the server

  },

  received(data) {

    // Called when there's incoming data on the websocket for this channel

    return alert(data['message']);

  },

  speak: function(message) {

    return this.perform('speak', {message: message});

  }

});


window.addEventListener('keypress', function(e) {

  if (e.keyCode === 13) {

    appRoom.speak(e.target.value);

    e.target.value = '';

    e.preventDefault();

  }

})

この処理で,フォームからサーバに送られたデータがブロードキャストされて,各クライアントのreceived()が受け取り,それぞれでアラートが表示されるようになる.

サーバを起動し,ブラウザのウィンドウを複数立ち上げて,どこか一つからメッセージを投げると,全てのウィンドウでアラートが出ることを確認せよ.

あとは,受け取ったクライアント側で,アラートを出すのではなく,Chatのメッセージを表示するように画面を書き換えれば,リアルタイムチャットアプリの完成である.

データベースに記録するように修正

app/channels/room_channel.rb のspeak(data) を修正.

class RoomChannel < ApplicationCable::Channel

  def subscribed

    stream_from 'room_channel'

  end


  def unsubscribed

    # Any cleanup needed when channel is unsubscribed

  end


  def speak(data)

    Message.create! body: data['message']

  end

end

データベースに記録するように変更した.チャネルのspeak処理を消してしまったので,データベースにデータをコミットした後に非同期で動作する処理を追加し,そこでspeak処理を行うように修正する.

speak(data) で Message.create! した直後に,そのまま broadcast() してもよいが,クライアント数が多くなったときにそれらへのブロードキャスト対応を別途切り分けて実施することでシステムを安定して動作させることを狙っている.

app/models/message.rb を次のように修正する.

class Message < ApplicationRecord

  after_create_commit { MessageBroadcastJob.perform_later self }

end

commitの後で(after_create_commit),次に作るジョブMessageBroadcastJob を実施する(perform_later)という記述である.

ジョブの作成

次の手順でジョブを作成する.

$ bin/rails g job MessageBroadcast

      invoke  test_unit

      create    test/jobs/message_broadcast_job_test.rb

      create  app/jobs/message_broadcast_job.rb

$ 

app/jobs/message_broadcast_job.rb を次のように修正する.

class MessageBroadcastJob < ApplicationJob

  queue_as :default


  def perform(message)

    ActionCable.server.broadcast('room_channel',

      { message: ApplicationController.renderer

                   .render(partial: 'messages/message',

                           locals: { message: message }) })

  end

end

ApplicationController.renderer.render() で,message がよしなにレンダリングされたものが,全てのクライアントにbroadcastされる.

クライアント側の修正

サーバから各クライアントに broadcast されたメッセージを,クライアント側のブラウザに表示されているHTMLに反映させるように,JavaScriptによるクライアント側の処理を修正する.

app/javascript/channels/room_channel.js を,次のように変更する.

変更するのは received(data) の部分.

import consumer from "channels/consumer"


const appRoom = consumer.subscriptions.create("RoomChannel", {

  connected() {

    // Called when the subscription is ready for use on the server

  },


  disconnected() {

    // Called when the subscription has been terminated by the server

  },


  received(data) {

    const messages = document.getElementById('messages');

    messages.insertAdjacentHTML('beforeend', data['message']);

  },


  speak: function(message) {

    return this.perform('speak', {message: message});

  }

});

window.addEventListener('keypress', function(e) {

  if (e.keyCode === 13) {

    appRoom.speak(e.target.value);

    e.target.value = '';

    e.preventDefault();

  }

})

以上で完成である.サーバを起動し,複数のブラウザを用意して,それぞれのブラウザからメッセージを入れて同期することを確認せよ.

完成

完成すると,こんな感じで動くよ.

本記事は「【Rails6.0】ActionCableを使用したライブチャットアプリを実装する手順を解説」というブログを参考にした(ただし記事のとおりやっても,Railsの最新版だとうまくいかなかったので,注意.若干の修正を加えている).そちらにも丁寧な解説が示されているので,参考にされたい.

2022年2月11日金曜日

連絡不行き届きに注意

ツールを過信すべからず(とくにそれがソフトウェアの場合には!)というお話をしたい.

先日,某所からオンラインでインタビューをさせてほしいという連絡を受け,快諾した.で,ZoomのURLを送ったから,というメッセージがメールで届き,別途,Zoomから自動で発信されたと思しきメッセージも受け取った.

ところが,URL送ったから,というメールには時間が書いていない.時間は何時?という返信を送ったあと,学生が研究室にやってきてその対応をしていたり,別の作業にかまけていたら,すっかりその件を失念してしまった.夕方に再びメールをチェックしたところ,

I had shared today’s invite with you for 4:30pm-5:15 pm Japan time.

というメールの後に,16:30過ぎのタイプスタンプで次のような恨み節が届いていた.

I dialed at 4:30pm

時間の調整なんて当日じゃなくてもっと前にやってくれよ!と思ったものの,その後のメールのやりとりで,翌日に再調整することとなった.

ところが,翌日のやりとりで,新たなZoom URLと,次のようなメッセージが届いたのである.

I will just share a revised invite for our discussion tomorrow.

ところが,ここにも,時間の情報が書かれていない.業を煮やした私は,時間は?!時間を教えろよ!と再度督促したわけだ.すると,

I had shared the invite with you...

とのメッセージが.まあ,このメッセージに日時が書かれていて,結局はオンラインインタビューを受けることができたのだが,何この山羊さんゆうびんみたいなやりとり?

結論を言うと,Zoomから発信されていたメッセージに時間が書かれていたのである.しかし私はそれを読むことができなかった.次の図は当該のメールである.▶︎をクリックすると,情報がびろーんと出てきて,そこに時間が書かれていた.

これ,気付かなかった私が悪いのか?そんなところクリックできて,そこに隠されているなんて,誰が分かろうというものだろうか?

2022年2月10日木曜日

2月上旬の話題まとめ

2月1日

鬼滅の刃

日曜日の夜遅くに鬼滅の刃アニメが放映されるため,月曜日に鬼滅の刃クラスタが発生するというパターンが常態化しました.このような毎週のパターンは,もう,そういうもんだと認めるしかないですかね.週末の競馬もしかり.

APEX

Apex Legends というオンラインゲームの話題です.それ以上はよくわかりません.形態素解析器の問題で,APEXがAPとEXに分かれてしまっている点はご愛嬌というところでしょうか.

F15戦闘機

さて,こちらはニュース的な話題です.小松基地を発進したF15戦闘機が日本海上空でレーダーから消えたという報道が話題になりました.その後の報道によると,機体の一部が見つかったとか.爆発してしまったのでしょうか.搭乗員は脱出できたのでしょうか.

2月2日

サウジアラビア戦

日本 - サウジアラビア戦は2 - 0で日本が勝ちました.その時間,都内某所で飲みながら某先生とちょっとした打合せをしていたんですが,サッカーに何の興味もない二人は「サッカー中継がうるさいなあ」とぼやいていたとかいなかったとか.

キンプリCM

こちらも全く興味がない話題ですがジャニーズは強い.King & Prince の平野紫耀がジュレームiPというシャンプー?のCMに起用されて,というニュースです.

石原慎太郎

石原慎太郎が亡くなりました.享年89歳.ご冥福をお祈り申し上げます.偲ぶ動画がTVで流れていたけれど,「死んだら弟(石原裕次郎)の記念碑の隣に碑を立ててほしい」とかいっていて,そのメンタリティが理解できない.死んでしまったらそれを知ることはできないのに……

2月3日

APEX

Apex Legends,オンラインゲームですね.新シリーズが始まるにあたり,武器の調整が入ったというニュースが話題です.オンラインゲームに全く興味がない私にとっては「ふーん」というものですが,好きな人には気になる話題なんでしょうね.

東京2万人

新型コロナウィルスの感染状況,第六波と言われているそれ,とうとう東京の感染者が2万人を超えたということで大きな話題になりました.医療機関がたいへんなことになっているのは困ったことです.しかし私の周りにはほとんど関係者がいないので,どこの世界の話なんだろうとも.まあ,油断は禁物です.気をつけましょう.

川崎記念

以前,東京大賞典?だかでTCKが取り上げられたことがありましたが,今度は川崎競馬場です.Twitterの競馬チーム,JRAのみならず,地方競馬にも大参加です.そのうちボートや自転車,オートまで拡がっていくのかな?

2月4日

恵方巻

昨日は節分でした.作られた恵方巻のブームは本当にあほくさいと思う一方で,まあ,美味しいならいいかという気分もある.しかし売らんかなの恵方巻ゴリ押しは勘弁で,コンビニバイトのノルマ強要や大量廃棄には胸を痛めざるを得ない.そんな私は結局,今年も食べませんでした.低みの見物です.

乃木坂46ANN

乃木坂46のオールナイトニッポンも根強い人気がありますね.たまに話題が出てきます.パーソナリティが交代するというので先週,今週はちょいちょい話題になっているんでしょうね.妄想結婚式だのクルトガだの,番組内で話題になったキーワードがトレンドとして上がってきています.

刀剣乱舞無双

刀剣乱舞のゲーム,任天堂Switch向けの体験版が配信開始というニュースです.毎回ツッコミますけれど,私は刀剣乱舞より工具維新派です.

2月5日

ラルク芸人

TV番組のアメトーーク,ラルク大好き芸人というテーマで放映があったようで,その話題が大きなクラスタを作りました.アメトーーク,特番のときにたまに観ます.面白い番組ですよね.

謎の車

そして面白いといえば注目のニュースがこれ.自分の敷地に無断駐車された地主が警察に行ったら民事不介入で地裁に行けとたらい回しされ,地裁からは(法律がそうなっているせいか?)その車を持ち主の了解なしに動かしてはならぬと指示を受けてブチ切れた地主氏,じゃあお前らどうすんだ?と地裁の玄関前に抗議の意味を込めて無断駐車したという話.とんちが効いていて面白い.

原神

ゲームです.石田彰という声優が新しいキャラクターの声をあてるという発表を受けてちょっとした話題クラスタができました.ゲームの話題はようわからんのでこれ以上は言及しません.ごめんなさい.

2月6日

競馬

昨日は土曜日です.東京・中京・小倉の競馬クラスタが大きな一つのクラスタにまとめられてしまっています.それにしても競馬の侵食具合がすごない?

インタビューの途中

北京オリンピックの話題,ですが……銅メダル確定の堀島選手,インタビューの途中でいきなりCMをぶっ込むという大胆な行動に出たテレ東が炎上したようです.あれあれまあ.しかし,そんな話題しか見かけない北京オリンピックってどうなの?

三四郎ANN0

TVだけでなくラジオもたまに話題になりますね.それもオールナイトニッポン,深夜放送とTwitterは親和性が高いのでしょうか.お笑い芸人,三四郎のコンビが送る番組が話題になっていました.三四郎,独特の喋り口の小宮とちょっととぼけた相田のコンビ,私は好きですよ.

2月7日

競馬

競馬の大きなクラスタができています.日曜日ですからね.東京で東京新聞杯,中京できさらぎ賞というレースがあったようです.「通常どおり開催」というトレンドが気になりますが,何があったのでしょうか.

ニチアサ

そしてニチアサです.横にビヨーンと飛び出してしまっているクラスタは,プリキュアですね.新シリーズが始まって,けっこうぶっ飛んだ内容だったようです.オネエキャラというキーワードが気になります.

北京オリンピック

北京で行われている冬季オリンピックも,ようやく,少し話題になるようになってきました.TVでもちらほら報道されているようですからね.

2月8日

鬼滅の刃

日曜日夜の話題を受けて月曜は鬼滅の話題クラスタが出現する,というパターンが恒例になってきました.だんだんクラスタの大きさも大きくなってきているような気がします.同じテーマでクラスタの大きさを追っかけていくと,シリーズの盛り上がり状況がわかるかな?

フィギュアスケート

オリンピックの話題も,だいぶ,盛り上がるようになってきました.今日はいよいよゆづの登場ですな.ほぼジャニーズと同じような扱いにされているんじゃないかというような気もするけど.

ジャンプ

そして,スキージャンプ男女混合競技のスキャンダラスな事件です.高梨沙羅が失格しただけでなく,各国,どんどん失格して,ノルウェーなんて2人も失格?これ,競技としてどうなのよ?という感想でしかない.

2月9日

フィギュアスケート

ショートプログラムで羽生結弦が失速し,18歳の新星が第2位だそうです.スポーツ界も世代交代なんですかね.習近平のお膝元なので,プーさんは分が悪い……というのは穿った見方すぎますか.

ジャンプ

スキージャンプの件,各国の選手が相次いで失格し,怒りの声がSNSに溢れています.しかし,次々と選手が失格するって競技としてどうなのよ?とは思うけれど,怒るってのはわからんなあ.あんたが怒ったところで何が変わるわけでなし,そんなこと言い出したら,オリンピックの結果と私の人生,全く交わらないからねえ.そもそも興味ないし(とか言っちゃう)

ドライブマイカー

「ドライブ・マイ・カー」という日本映画が,アカデミー賞のオスカー作品賞に邦画作品としては初めてノミネートされたんだそうです.受賞するといいですね.幸運を祈ります.

2月10日

ゼンカイジャー

これはニチアサですね?仮面ライダー?戦闘ヒーローシリーズ?どっちでしょう.プリキュアでないことはわかります.そして平日の真っ只中になぜこれが話題になったのか.今日は小粒な話題が多かったとはいえ……不思議です.

ハーフパイプ

こちらはオリンピックの話題.ハーフパイプ,予選が終わったのでしょうか.今日,学生と話をしていて,スノーボードはやらないんですか?と質問された.私ら学生のころはスキーしかなかったからねえと回答.ああ,社会はうつろいゆくものですなあ.

ウォークマン

そしてウォークマンですよ.ソニーのウォークマン,新型が発表になりちょっとした話題です.ウォークマンといえばソニーの代名詞.小型のカセットテープレコーダーでしたが,いまやシリコンオーディオプレイヤーですね.時代は変わりました.

2022年2月9日水曜日

Webアプリ構築特別補講・書き起こし

はい,それじゃあですね,国際情報演習の補講ですね.補講.というかですね,皆さんがWebアプリケーションを作れるようになろうというビデオの作成を今からします.資料はすでにもう公開してありますが,ちょっとその資料を見ながらやっていこうと思います.Webアプリ構築特別補講(1)から補講(4)まで用意してあります.ちょっと長くなるかもしれませんがじっくり勉強しましょう.

さて,そもそもの疑問点ですね.ブログラムの書き方を覚えただけではアプリやシステムを作れるようにはならない,という疑問ですね.それはなぜかということですが,どんなプログラムの書き方,まあ,ここで,プログラムの書き方というのは1年生のときにプログラミング基礎で,プログラミングとは何かというのを習いますよね.それだけではシステムを作れるようにならない.あるいは,アプリケーションを作ることができないと.

で,それはプログラムを書く,書けるようになるだけではなくてですね,色々と身につけなければならない知識というものが,やはり,あるいうわけです.で,そういったことを全部覚えないといけません.そういうことをすべて覚えるとですね,まぁそれなりのプログラム,ないし,アプリケーションやシステムを作れるようになると.

で,どうしたら作れるようになるかというのは,その総合的に色々勉強していただきたいということですが,今回はですね,そのなかでも,インターフェースというものに着目して,それを段階的に習得する道筋というものを考えてみたい,ということですね.なぜインターフェースなのか,それは私の専門がユーザーインタフェースだからです.

えっと,まあ,もう一度,整理しますね.プログラミング基礎でプログラミングを学んでも,アプリケーションやシステムを作れるようにはならない.それはなぜですか?ということです.いつも私が皆さんに提示している情報システムのモデルというところから考えてみたいと.

で,いつものですね,情報システムのモデルの,この簡単な図ですね.これを皆さんに示すときは,入力があって何かデータが入力されて,コンピューターの情報システムにデータが入力されますよ,と.その入力された情報を受け取ってコンピュータの中身は処理をします.さらにその処理をした結果が主力されて,大体一回で入力→処理→出力が終わるわけではなくて,それを見て人的機構,まあ人間側ですね,人間がフィードバックプロセスを経て,次の情報を入力して,まーこのサイクルを回していって,一連のセッションが行われるんだという説明を,もう私の講義やら何やら聴いてる人はですね,毎度おなじみのいつも話かというふうに思っていただければいいと思うんですが.

ここではちょっとカッコつけて,インプット,プロセス,アウトプット,フィードバックというふうに絵を描いてあります.これには意味があってですね,プログラミング基礎でやるところは,ちょっとこの,英語で書いているのは,まあ一連のですね,この今日お話しする中身は,海外で発表しようかなと思っているので,まあ英語で書いてあります.けれどもBasic Programming Course focuses on the knowledge only in this courseというふうに書いてありますね.つまり,プログラム基礎でやっているところっていうのは,この中身の部分ですね.どうやってデータを処理するのかと,ここの部分をこの部分に,こう,焦点を当ててやってるわけだと.

じゃあどうやってデータをインプットするのか?あるいはどうやってアウトプットしていくのか?フィードバックループをどうやって回すのかと.人間系まで詰めたところというのは,一切,ちょっとだけありますけどね.printf()とかね,あるいはscanf()に問題があるよ,とか.まあ,そんな話をちょっとするぐらいで,中心レイヤーのところが,この中身にフォーカスしてやっているからです.

ところが全体として,アプリを作らないといけない,あるいは,情報システムを作らなきゃいけないっていうのは,このインプットからアウトプット,さらにはフィードバック,このようなループをどうやって回していくのかというようなところまで考えないといけないので,プログラミング基礎を習っただけでは,アプリや情報システムを作ることができない,ということになるわけです.

で,まあ今の話がこのデータ入出力や各インターフェイスっていうところで,赤字で書いてありますが,プログラムの書き方の基本的なところは,プログラミング基礎で学びます.さらに他 に,じゃあシステム開発に必要な知識って何だろう?っていうのを考えてみると,もう,いっぱいあるわけですね.

他に身につけなければならないことは,適切かつ効率的なロジックの構築の仕方,あるいは,これはプログラム基礎でもちょっと触れますが,私のクラスでは触れてますけれども,計算誤差をいかに伝播させていかないかというような計算精度の話とか,文字コードの話とか,そういうコード体系をだいたいなんでいくかという話も,知っておく必要があります.

さらにはこのウェブアプリの講座の中ではちょっと触れますけれども,データの永続化,データベースを利用してため込んだデータをどうやって記録していくんだというような,その辺の知識も必要になってきます.

さらにはですね,実際のアプリケーションを作るときは,エラー処理や例外処理,あるいは情報セキュリティの対応ですね.ここ,すごく重要です.なぜならば,人間って,人間系っていうのは,もうエラーの塊なんですね.人間ってのは,まぁ一般ユーザーってのは何をするかようわからない.いかにそこをですねモデル化するか,ということがすごく重要になってくるわけですが,まぁ,今回はですね,このエラー処理や例外処理の話はスコープの外で,あまり触れませんけれども,ここも非常に重要です.

さらにはですね,一連のプロセスをどうやって回していくかです.どうやってやっていくか,開発の仕方ですね.そういった辺りはソフトウェア工学を,あるいは,その他,プロジェクトをどうマネジメントしていくのか,ああこれはプロジェクトマネジメントですね.

さらに,iTLですので,ここでは書いていませんが,リーガルイシューですね.つまり作ったアプリケーションが法的に問題ないのか?社会にサービスを提供しているときに法律とコンフリクトはないかどうか,整合性をどうやって取っていくのかという話.あるいは,最近ですとソフトウェア・エシックスというのかなあ,倫理的な問題ですね.パーソナルデータをどうやって取り扱うのかとか,そういった話も,ちゃんと考えないといけないよと.

まぁそこを考えるのがですね,大変.まあ,もうiTLを卒業ですね,という話になっちゃうので ,まあ,いろいろ考えないといけないということを,まずはここでは意識をしてください,ということです.

さて,で,さっきも申し上げたように,いま私の専門がユーザインターフェース的なことであるということもあるので,今回の,この,まずWebアプリを作りましょう,のためのですね,第1回ということで,インターフェイスの構築に関する基礎知識の習得ということを,考えていきます.

で,インターフェースというのは,先ほどの情報システムのモデルの中でですね,情報システムの中心部分,この黄色?オレンジ色の部分は機械的機構,コンピュータ,あるいは情報システムそのもの,ですけれども,そこに対して情報を入力する,あるいは,そこから情報が出力されるというところで,周りはこれ人間が関与しているわけです.人間というかユーザーですかね.

まあユーザーだけとは限らないかもしれない,いろんなケースがありますが,他のシステムと組み合わせて使うなんてときは,外側が他のシステムだったりすることもあります.いずれにしても,その中心,いま考えているこの黄色の部分ですね.黄色の部分のモジュールと,それ以外のユーザーないしは他のシステムとの接点部分は,これ,インターフェースというふうにいいます.

さて,このインターフェースをですね,どうやって開発していくのか?ということですが,ここではですね,レベル0からレベル4まで,段階的に考えていきましょう,ということを想定してみました.

レベル0はfunction.レベル1が,コマンドラインインターフェース(CLI).レベル2はチャットボット,レベル3が,グラフィカルユーザーインターフェース(GUI)ですね.そしてレベル4,いきなりレベル4がWebアプリケーションになりますが,まぁレベル0からレベル4になるに従って,難しくなっていくというイメージですね.

じゃあ最初のレベル0,ファンクション,これなんだ?これも簡単ですねえ.関数ですね.関数で,数学では,y = f(x)なんていう書き方をしますけれども,これ,プログラミングもですね関数型プログラミングなんていうのはこの書き方でプログラムを書いていきます.手続き型でもですね,

Pythonで表現するとfunction定義っていうのは,function definitionは,defというキーワードで始まって,名前があって,inputたる引数があって,関数の中身でですね.まぁ,ここでは,スクエア,2乗ですね.引数で与えるインプットを二乗して,変数に入れて,で,そこの処理がプロセスに相当すると.そしてリターンはアウトプット.

これ非常にシンプルですね.インプットとプロセスとアウトプットが,それぞれ関数の引数,それからその中身,そして返り値というふうに対応する,これもう,これ以上簡単にならないというか.ここはですね,そのプログラミング基礎で皆さんが習うと関数の使い方とか,定義ですか.まあ,皆さんが習ったプログラム言語はCでありますが,ほぼ同じですね.Cでも関数定義があって.関数や変数に型があるかないかぐらいの違いなので.そんなに難しく考えることはないでしょう.

でこれが一番プリミティブなインプット→プロセス→アウトプットのモデルというふうに考えてください.

さて,今度はですね,レベル1ですね.CLI,コマンドラインインターフェースを考えます.

そうするとですね,コマンドラインインターフェースで,このレベルはプログラミング基礎でもですね.scanf()とかprintf()というようなものを使って,コマンドから何か,コマンドラインで情報を入力してそして,まあ標準入力と標準出力ですね,標準入力からデータを受け取って標準出力に書き出すということをやったはずです.

で,この例でいうとですね,まず先ほど定義したsquare()という2乗の関数がありますね.そしてそのスクエアを利用してさらにcli()という関数を定義しています.cli()関数はインプット「x =」とプロンプトを出して.

まず,インプットという関数,組み込み関数ですね.input()というPythonの組み込み関数を用いて,コマンドから情報を入力していると.そうすると入力されたものはまあこれ文字列で,オブジェクトなので,intに変換をしていてxには整数値として入ります.そして,その整数値を使ってですね,この場合y = square(x)というところが,まあ,プロセス処理そのものになるわけですね.で,アウトプットとしては,yの値ということで.

たとえば,こうした事例が出ていますが,5を入れると25.5かける5で25.9x9は81,16だったら256というふうに.これ2乗した値が出てきますね,というようなものになっています.ここでですね,黄色は定義,緑色は利用という状況を示しているということで,インプット,プロセス,アウトプットのそれぞれプログラムで,cliの中で定義がなされているというのはまあ見たとおりですね.さらに,コマンドラインで例えば16っていうインプットを入れるとには256ってことが出てくるというような利用状況を,この緑で示しています.

面白いのはこの定義する中でですね,実はy = square(x)というところで,上の定義を利用しているんですね.つまりこのcli関数の中で,さらにですね,関数を利用しているので,これ関数の入れ構造みたいになっていて,でxをインプットとして与えて,yにアウトプットが出てくる,これは上のsquare(x)の定義を利用しています.

そんな,チャイム鳴ってしまいました.えっと,ちょっとお構いなしにやっていきますね.

で,これはですねえ,コマンドラインで入力して,リード・エバル・プリントで,それをひたすら繰り返していくということでレップ・ループって通常いわれます.

リード,これはインプットに対応するもの,そしてエバリュエーション,エバるといいます,それプロセスね.そしてアウトプットとしてはプリントで,それを回していくので,まあまあ元のところにもどっていくよ,ということで,フィードバックの部分をループとして表現する所で,レップ・ループというふうに言うこともあります.まあ覚えておきましょう.

さて,次はレベル2ですね.レベル2は,これ,LINE botというものを考えます.with google  app scriptですね.で,これはもう細かな話はしていきませんが,LINEのデベロッパー登録をすると,このようなプログラムを作れる.まあLINEのプラットフォームを利用することができます.

たとえばですね,ここでですね,まぁJun botとか変なLINEボットがいますが,まぁ私の似顔絵のアイコンのLINEボットが入って,右側の緑の部分が,これ入力の部分ですね.「Hello Jun Bot」とかっていうと,Jun botはですね「You mentioned "hello Jun Bot," ok thank you」というふうに,まあ鸚鵡返しにレスポンスを返すわけです.そうするとですね,ま例えば「Hy, Jun Bot. Could you tell me what you are talking about?」というとJun bot ですね「You mentioned "Hy, Jun Bot. Could you tell me what you are talking about?," ok thank you」 というように,まあ,まったく鸚鵡返しに返してくるだけです.

オーケーサンキュー,ですねえ.でまぁこれ,たんにですね,メッセージをそのまま返すだけ っていう非常にシンプルな実装になっているので,こんな単純なものですけれども,まあこんなプログラムを作ってですね,そしてLINE Messaging apiを使って,アプリを登録すると,まぁこんなことが実現されます.これが今のチャットボットの簡単なプログラムです.

ここではですね,まあ説明は部分的にしかしませんが,doPost()っていう関数の中で,json.events[0].message.textっていう,この書き方でインプットされた中身をmessageに取り入れることが実はできるんですね.そして,ここに入ってきた入力に対して「You mentioned ... blah-blah-blah」みたいな感じで,そのままアウトプットを返していると.でそれをですね最後に ContentService.createTextOutput(...)っていうような,こんな書き方をして,ここでsetMimeType(...)っていうふうにやると,処理したものをLINEのプラットフォームに返してあげることができると.

まあ,それだけなんですね.つまり我々が,じゃあ何をやらなければいけないのか?というと,このプロセスの中ですね.ここは,もう単純に鸚鵡返ししてるだけなので,You mentioned ... っていう文字列にメッセージそのものをくっつけて,で改行を2つくっつけて ok thank youというのをくっつけて,返しているだけなので,これ鸚鵡返しになってるんだけど,まぁここでね,メッセージの中身に従って,AI使うとかね,いろんなやり方で重要な情報を,アウトプットしてあげる.

例えば,メッセージ,例えばxで,x掛けるx,スクエアを計算するとして「you entered five and I return twenty-five as square of five」とかね.まあまあどうでもいいんですけど,そういうようなプログラムを作ってあげると.

で,ここで重要なのはインプットとアウトプットが抽象化されているので,これもう,プロセスに注力するだけでいいということで,インプットとアウトプットのところを我々はプログラマーはあんまり考慮する必要がないということです.えとですね,まぁ,今の話ですね,in-msgが,json.event[0]なんとかっていうところが入ってきてfunc()でリターンメッセージをつくって,それを'message': ['text' : out_msg]というところに放り込んで返してあげればいいということで.

こうやって抽象化するとですねぇ,ここで実際,処理っていうのはこのfunc(in-msg)この部分ですね.この部分を考えればいいだけなんですね.ということで,実はこれレベルが2となっていますが,今まで見てきたレベル1あるいはレベル0とそれほど大差ないわけですね,

で,問題はですね 使うようにするまでの設定の部分ですね,つまりこのラインデベロッパー登録をしてメッセージapiを使って云々という話とか,googleアップスクリプトでどうやってやりますかーみたいな所ですね,ここの条件が,準備するのはちょっと大変だと.で,それさえできてしまえばですね,あとは定型なので,もうここをごちゃごちゃっと書いていくだけでいい.で,そうするとここで図にして見せているような,インプット,アウトプットのインターフェースはこれLINEが提供してくれるので,コマンドラインで与えるとか,あるいはプログラミングの関数自体に引数で渡して返り値が戻ってくるっていうのとインターフェイスとしては大差ないわけですね.

なので,これ少し難しいように見えるけれども,レベル2になる,ということです.

さあどんどん行きましょう.レベル3ですね.レベル3は,これは去年,2021年の3年生のゼミのときに少し,1回使っていろいろやったというような記憶がありますけれども,これGUIのアプリケーションです.

で,プラットフォームはHTMLとJavaScriptとCSSを使って,シングルページアプリケーションとして作ったもののはずで,これどんなアプリだったかっていうと,ムービーをドラッグ&ドロップで並べ替えることができて,で順番に並べ替えてプレイボタンを押すと,その順番の通りこのムービーが流れますよ,みたいな,そんな単純なアプリだったと思います.

これはですね,ある,ちょっとしたリクエストがあって作ったものですけれども,この辺の GUI,ユーザーのインプット,ここでユーザーのインプットは何かっていうと,ちょっと考えてみてください.

このときにユーザーのインプットって何になりますか?なにになるでしょうかわかりますか?ここでドラッグ&ドロップで,それぞれムービー1からムービー4まで順番を入れ替える,これ一つのインプットになりますね,それから,プレイボタンを押す,これもインプットになりますね.じゃあ,アウトプットは何でしょうか?アウトプットはドラッグ&ドロップに従って順番が変わるよってのは,これ一つのアウトプットだけれども,プレイボタン押したらその通りに順番でビデオが流れると,これも,アウトプットになるわけですね.

で,そういうようなものを実現するために,どんな知識が必要かというと,これモダンなGUIプログラム必に要な知識としては,基本的なところはWINPというアイディアですね,考え方.ウィンドウ・アイコン・メニュー・ポインタ,そういったものでグラフィカルインターフェースは作られているということ.

それからウィジェットという考え方ですね.ディスプレイ・コンポーネンツ,ウィジェットっていうのは,例えば,この一つ一つのサムネイルが,このオーダーっていうカラムに含まれていて,さらにそれが一つのウィンドウの中に入っている.リザルトというカラム,ちょっと大きいですけれども,その大きなカラムの中に,このムービーのペインが入っていて,さらにプレイボタンが入っている,こういうですね,実はそれぞれ一つ一つが部品になっているということ.

それからそういった部品っていうのは必ずですね,階層構造を持っていて,入れ子になっているんだというような概念ですね.そういったものをこれディスプレイ・コンポーネンツあるいはウィジェットというふうに言いますが,そういったものの考え方.

それからですねページトランジション,この例ではページというものがないので,一つのページの中に収まっている,つまりシングルページアプリケーション,というものですけれども.通常はですね,まあ例えば何かどうかな,ボタンを押すとスクリーン全体が変わるとか,そういうようなページ遷移,ページトランジションというものが発生します.

さらに重要なのは,イベントドリブンプログラミングという概念で,イベント駆動型プログラミング.ユーザーが操作するとですね,さまざまなイベントが発生します.さまざまなイベントって何かというと,ドラッグ&ドロップして配置を入れ替えましたっていうようなイベントとか,えっとこの例ではないけれども,スクロールバーなんかがついていてスクロールバーをぐりぐりやると上に行ったり下に行ったりしますとかね.あるいはこのプレイボタンを押した,プレイボタンを押すとここでプレイボタンが押されたというイベントが発生すると.

で,イベンドドリブンプログラミングっていうのは,そういったですね,イベントが行われたら,イベントが生じたらですね,それぞれのイベントに対してどういう反応をするのかっていうことをプログラミングしていくんだと.ドラッグ&ドロップでこのサムネイルを入れ替えたら,その時はonDragReleaseEndっていうようなイベントが発生,まあドラッグがこう行われてマウスボタンが離されたときですね,その瞬間にドラグ&ドロップの後の処理をどういう風にするのかということを記述するとか.

あるいはこれclickListenerFunction = function() {...}となってますけども,なんとかイベントが発生したら,どのファンクションを実施するよっていうようなルールで結びつけるような,addEventListenerというメソッドを使ったりとクリックリスナーにこういうfunctionを設定したりというようなことをやりますけれども,そうすると,この例えばこのプレイボタンからクリックイベントが発生したらこのファンクションなんとかね,とか,このファンクションを実行してくださいとか,まあそういうような書き方をするわけです.今日はですね,このGUIのこのアプリについては説明はしませんが,これは解説した記事を書いているのでぜひそっちも参考にしてください.

えっとですね,そしてGUIプログラミングっていうのは,レベル3なので若干ややこしいと.で,なぜややこしいかというと,これ,見てわかるとおりですね,グラフィックインターフェイスの中で,どこからどこまでがインプットで,どこからどこまでがアウトプットっていうのが,これ判然としないわけですね.つまり画面上で情報を入力して,画面上で情報が出てくるということで,インプットとアウトプットがこれ判然一体になっている.このへんが若干わかりにくい.

それからGUIはやっぱりあのCLIほど簡単じゃなくて,まあこの環境を整備するところがやや面倒で,ウィジェットを用意するとか,そういった準備の行動っていうものが必要になってきます.さらにプログラミング方法がGUIの環境によってだいぶ違います.この例はHTMLと JavaScript,CSS,つまりWebアプリのフロント側のパーツですね,それで全部実現できていますが,これがiOSのネイティブアプリを作りますとかね,まあ,あのMacでもWindowsでもいいんですけど,そういうネイティブアプリを作りますとなると,それ専用のプログラミング環境でwidgetライブラリーなんかを使ってやるとかね,そういうようなところも設定がやや面倒くさかったりします.

一方でですね,えっとオブジェクト指向の考え方と非常に相性がいいんですね.つまりこの辺の部品一つ一つがオブジェクトなので,さらにですね階層構造を持っているってことで,これhas-a構造をそのまま埋め込むことができるんですね.

さらにですね,それぞれの部品は大きな基本的な部品のサブクラスであるというような考え方にも非常に親和性が高くてですね,has-aも目で見えるわ,is-a構造も目で見えるわっていうことで,オブジェクト指向の考え方を,このGUIのプログラミングで習うというのは,非常に自然です.なのでオブジェクト指向よくわからないなあという人はGUIプログラミングにチャレンジしてみると「ああなるほどそういうことかぁ」っていうふうにね,わかるかと思います.

あとはまあ,この繰り返しなりますけど,イベントドリブンの概念ですね.これがあの通常のですね,というかプログラミング基礎でやったような,いわゆる構造化プログラミングですね,連結・分岐・反復・呼出し,コンカティネーション・セレクション・イテレーション・インヴォケーション,ね.その4つの組み合わせでプログラムが記述されるというような,構造化プログラミングに慣れているとですね,いきなりこうイベントがポッと発生したとき,そこにすぐ対応するメソッドが呼ばれるというような,イベントドリブンの考え方はちょっと発想の転換がやっぱり必要ですね.

構造化プログラミングは基本的には上から順番にやってきますから,まあ連結の考え方で上から順番に実行されるというのは基本的になってきますので.ただ,インヴォケーションのね,呼出しとイベント駆動の関数呼び出しはほぼ同じなので,まあちゃんととわかればね,そんなに大した違いはないわけですけれども.そこの発想の転換が必要になるというところが,少し難しいかなというふうに思います.

この後のWebアプリも,基本的にはリクエスト・レスポンス型の,クライアントからのリクエストに応じて何がしかのサービスを行って,レスポンスとして返すというようなパターンを基本としますので,Webアプリも基本的にはイベントドリブンだというふうに考えて構わないと思います.

はい,そして最後のですね,レベル4がこれ,Webアプリケーションです.

一般的なアプリケーションっていうのは,みなさん手元のスマートフォンだったりパソコンなりですね,そういった手元のデバイスで動きます.そこにあるCPUでデータ処理がなされると.ところがですねWebアプリのこれ,基本的にはネットワークが繋がってないといけません.ネットワークでつながっていて,中心的な処理は,向こうのね,ネットワークの向こう側のサーバー上で動作すると.

で,さらにWebアプリというのは,ユーザーインターフェイスとして手前のWebブラウザを使っているので,まぁだいたいですね,最近はどのデバイスでもブラウザは標準で入っていますから,インストールする必要はありません.アプリケーションをインストールしている必要はないと.さらにアプリケーションも,サーバー側で勝手にアップデートしちゃうので,サーバー, サービス提供がですね,非常に具合がいい.

皆さんもね,TwitterとかFacebookとか,ああいうSNS,毎日のように使ってるかもしれません.Facebookは,まあおっさんのメディアだから,あんまり皆さん使ってないかなあ.まあInstagramとかね,あのそういったものを使っていると思いますけれども,ある日アクセスしたら,なんかインターフェイスがちょっと変わったとか,たとえば,なんだっけTwitterのボタンの色がね,白から黒に変わってたとか,なんかいろんなことがあって,そのためにおおーっとかなんかどよめきが起こってたみたいですけど,そういったように勝手にサーバー側で変えちゃえるので,サービス提供側にとっては非常に都合がいいわけですね.

さらにまあ,クライアント環境もですね,モバイルデバイス,スマートフォンからタブレットから,パソコンからなんだかんだ,まあいろんなものに対応可能というような工夫も最近ではなされていますよ,ということですね.

はい,今の違いの話です.一般のアプリケーションは手元で動作します.処理の主体とユーザーインターフェイスの提供が同じデバイスで行われます.それに対してWebアプリケーションは,サーバー側で動作するのでユーザーインターフェースは手元のデバイスが提供します.そして インプットがネットワーク越しに飛んでいって,処理の主体でプロセスが行われて,アウトプットしてレスポンスが返ってくる,そういう動作をするという違いがありますね.

はい,で,まぁ基本的にはですね,こういう処理のシステムのことを,CSシステム,クライアント・サーバーシステムというふうに言います.クライアントサーバシステムね.で,クライアントっていうのはユーザーが処理をするユーザインタフェースに対応していて,そしてサーバー側で実際のデータ処理や計算を行います.

で,さっきの話ですね.えっと順番とては,1番,リクエストが送信される,と.で2番が実際のデータ処理や計算が行われて,3番としてレスポンスとして返答が返って来て,それをクライアント側で描画してアウトプットとして人間に提示するということですね.

まぁ,クライアントの部分ね,Webブラウザの部分も,これのインプットアウトプットも渾然一体としてるってのはGUIと同じ問題を抱えていますけれども,まぁその辺はちょっと目を瞑ってもらうとすると,わりときれいに,リクエストがインプットに対応,そして実際の処理がプロセスに対応,そしてレスポンスが返ってくるというところ,アウトプットに対応しているということで,情報システムのモデルとの整合性もそれなりに取れているということがわかると思います.

問題はですね,これ次にあったかなあー,えっとですね,Webアプリ,シンプルなWebアプリの話があって,ちょっと待ってくださいね,処理は,資料がないな,じゃあ口頭で補足します.問題はですね,基本的には「行って来い」で1回で終わってしまうという問題を抱えているというのは頭に入れておいて下さい.つまり,リクエスト・レスポンス型の通信,リクエストがあって,実際のデータ処理や計算が行われてレスポンスが返ってくる,以上終わり!ですね.

つまり,情報システムもモデルで言うところのこと,ダーっと戻るとですね,ダーッと戻ってここですね,リクエストが送られて,プロセスが行われて,レスポンスとしてアウトプットは返ってくると,で,ここでおしまいです.この後のフィードバックで,次にインプットに戻していくところ,ここが,実はですねえ,単純なクライアントサーバモデルには欠如していると.フィードバックループで回す,4番がないわけですね.

で,そうするとWebアプリとしては,でも,困っちゃうわけですね.つまり情報システムのモデルってのは,そのフィードバックループを回して次のリクエストを送る,そして次の処理を行って,どんどんこの処理の精度を上げていって最終的にソリューションに至るというですね,そこが重要になってくるので,このフィードバックをどうやって回していくのか,次のセッションにどうやってつなげていくのか,っていうところは,実はWebアプリの課題の一つではあります.

色々それに対していろんな解決策が提示されているので,そこはまぁおいおい見ていくとして,まあそういうですね,根本的な課題を抱えているということは頭の中に入れておいてください.

さて,これはですね,Flaskを使った非常に一番シンプルなWebアプリですね.実際のFlaskを使ってやっていくというような話は,2番,3番,4番でWebアプリを作っていきましょうねというところに話が続いていきますので,まあこれは,そのアプリケーションの内容のね,どういうプログラムがどういう意味を持ってるのかっていうようなあたりはまたおいおい見ていくとして.

インプットとしてこのhello?name=Junっていうのが,これ,inputになります.でそして,それを処理して,ハローなんとかっていうメッセージを作りますよ,それがプロセスですね.でリターンして戻していくと,これがアウトプットの定義になっていて,実際の利用はこのURLのところアドレスバーに「hello?name=ホゲホゲ」っていうようなものを入力して,サーバに送る,まあこれ,ローカルで動いていますのでネットワークがなくてもローカルで処理がされますけど.127.0.0.1っていう,ローカルホスト,自分自身です,ローカル側のサーバーで処理をされて,でHello, Junていうアウトプット,メッセージが出てきて,それが表示されるっていうのは非常にシンプルですね.

ここがですね,まぁWebアプリの課題を先にお話をしておくと,インプットをどうやって渡していくのかというのがまあやや複雑です.今みたいなアドレスバーに,そのまま書いてしまうっていうのはいかにも乱暴で,実際のアプリだとそんなふうな処理を一般ユーザーに求めるのは ちょっと酷ですね.なのでここはですね,HTTPのプロトコルをきちんと理解して,GETとは何ぞやとかPOSTとは何ぞやみたいなところ,若干,まあ精通する必要ないと思いますけれども,そういうようなプロトコルでクライアントとサーバーがお話をしているのかというあたりは知っている必要があります.

でここの渡し方もですね,パスパラメーターとか,クエリパラメーターとか,リクエストパラメータとか,いくつか種類があるので,そういったものを学んでいく必要があるでしょう.

それからですね,ルーティングという概念,これ基本的にWebアプリでは基本的な概念で,ここも学んでおく必要があるでしょう.さらにはですねWebアプリは,これネットで公開して入力を受け付けますので,これ確実にですね,セキュリティ,情報セキュリティのイロハを知っている必要があります.さもないとですね,ネットを介して悪意ある第三者にアクセスされてシステムを壊されてしまう可能性があります.なのでここも基本的なところを学んでおく必要があります.

困ったことにですねアウトプットのアプローチもやや複雑です.それはなぜかというとアウトプットとしてHTMLの画面を返してあげないといけないんだけれども,そこの画面生成にはCSS のデザインがどうだとかですね,テンプレートを用意してどうやって使っていくのかとか,そういうような知識が必要になってきます.

で,そうするとですね,やっぱりその,レベル3のGUIのプログラミングも1回体験しておくというのは非常に重要で,それを応用することができますので,若干,まあ順番に本当はやっていくといいと思いますけど,今回はねWebアプリを作ってみましょうということで,レベル3をすっ飛ばしてやっていますが,まあそんな感じで学んでいくといいと思います.

あと,ああ,これさっきの話ですね.HTTPの根本的な課題とその対応が複雑である,つまり, HTTPの根本的な課題っていうのは,まあHTTPの根本的な課題というよりは,クライアントサーバモデルの根本的な課題ですけども,こういう形の通信モデルであるということで,そのために,セッション管理などの仕組みが後付で作られていると.じゃあどういうふうに作られているのかというと,まあcookieを使うとか,AJAXを使うとか,まぁ,いろいろなやり方があります.

で,そういうのはですね,個々の技術を一つ一つ覚えてくのでもいいんですけども,実際にはですね,そういうのがドーンとねえっと一通りセットされているようなフレームワークと呼ばれるものを使っていきます.まあ,さっきのFlaskなんかもね,実はシンプルな,マイクロフレームワークっていうのかな,軽量フレームワークというかな,簡単にそのWebアプリを作れるフレームワークとして提供されていますが,そういったものを使っていくんだ,ということを覚えておいてください.

はい後はですね,ちょっと追加の話ですね.アプリケーションの構成のモデルとしてMVCモデルってのがあって,これは多くのWebアプリフレームワークで使われているので,これもですね,きちんと理解しておくとよいでしょう.

MVCモデルっていうのは,アプリケーションをモデル・ビュー・コントローラという3つのパーツに分けて考えるときれいにできますよっていう考え方ですね.もうこれだいぶ古いです.半世紀前ですね.1970年代にゼロックスのPARCね,ゼロックスのパロアルト研究所,パロアルト・リサーチセンターで,Dynabookって,ダイナブックてね,東芝のパソコンでも Dynabookってありましたけど,それより前にアラン・ケイっていう,パーソナルコンピュータの父とか何かいわれることもありますが,彼がですね開発したSmalltalkと呼ばれるシステムでまず実装されて提唱されたモデルですね.まあそういったものもちょっと理解しているとよいでしょう.

MVCモデルそのものについては,ここでは時間もないのでちょっとばします,はい,えーまぁ飛ばしますと言いつつちょっとだけね.MVCモデルを使うと何が嬉しいのかという話で,データモデル設計と,ビュー設計と,コントローラー設定っての分けましょう,と.

どうやって分けるかっていうことですが,データのモデルは,これシステムの根幹をなすのでデータのモデルの設計,具体的にはデータベースのテーブルをどういうふうにするかですね.そういったところっていうのは,そんなにですね,こう未来永劫あんまり変わらないんですね.まぁちょっとずつレコードを足していきましょうとか,カラムを足していきましょうとか,これはもう要らないのでカラムを削りましょうとかね.まぁそのぐらいの変更があるぐらいで,きっちりこう定義して,きっちり定義してしまえば,割とこう,長持ちを持ちするんですね.なのでえっとデータモデル設計を,まずしっかりしましょうと.

で,じゃあそれをどうやって見せていくのか,そこがビューの設計ですね.ユーザインターフェースの画面とかはこれ得意な人に任せちゃえばいいでしょ.デザインが得意な人に,じゃあそこを任せます.

コントローラーの設計っていうのは,まあこれはですね,そんなに変更を加える必要はないんですね.多くのアプリで,クライアントからのリクエストを受け付けて,ロジックのところに回して,でロジックの処理の結果を受け取って,HTTPとしてレスポンスとして返す,この手順ですね.ここはもうどんなWebアプリでも一緒なので,その手順自体はそんなに変更する必要がないと.ただ,細かなところでちょっとずつ変えていかないといけない.どのデータにアクセスしないとだめだなみたいなところは少し変えないといけないんでそこだけいじればいいですよというのが,まあ,コントローラー設計の部分ですね.

はい,ということで,最後に,まずカッコ1を,これで終わりにしますが,最後に気をつけないといけないところはですね,ええ,ここですね.Practical Programming must take error handling into account!ということで,ここの部分ですね.エラーが起きたときにどうするの?エラーログ見ましょう.

実はアウトプット,standard out の他に standard error,標準エラー出力ですね,そこに,いろんな情報を出してですね,エラーが起こったとき,不測の事態が起こったときに,どういうふうに対応するんだ?これフィードバックもちゃんと回して,もう1回,正しいデータを入れさせるとかね,まあ,そういうところをしっかり考えないといけません.ただし今回はそれはちょっと考えてないので,ここは一つの課題として残されているということは気ををつけましょう.

はい,えー,ということで,まず1回目を終えますが,インターフェイスに着目して,システムにおけるその重要性を段階的に理解する道筋というものを,ちょっと考えてみました.で,レベル0ね,関数定義の部分のシンプルなテイからスタートして,実際にはWebアプリとして具体的かつ現実的なアプリケーションってのはどうあるべきかというところまできました.

で,今回ですね,非常にざっくりと,もうこれ何分,話をしているかな?今,えっとですね,何分になるのかな?ちょっとわかんないけど,もう30分以上,話をしてますかねえ,だいぶ長くなりましたけれど.まず今回ね,具体的なプログラミングの実装については,まぁ最初のね,スクエアとか何か考えましたけれども,後のほうはもう全部,具体的なコードみたいな話はしなかったので,それぞれの段階,レベル1,レベル2,レベル3,レベル4の段階で,より皆さんの興味を引くような,面白いものの事例を提示できると,これ教育的な効果があるのかなというふうに考えています.

はい,その辺はみなさん,また一緒に考えていきましょう.はい,それではですねえ,特別講習第1回目を終わります.

2022年2月4日金曜日

学内便(かんじへんかん)の謎

このタイトル,正しくは「漢字変換の謎」なのだ.「かんじへんかんのなぞ」で変換したら「学内便の謎」になってしまった.そう,Macの学内便,じゃない,Macの漢字変換が妙なんである.

まずは次のスクリーンショットをご覧いただきたい.

おかしいな?と思い始めたのは去年の暮れあたり.次はこれ.

この「ますくはんがー」はこの後,何度も出てくるので記憶に留めておいていただきたい.

こんなものもあった.どうも「アルファベット1文字」がヤバいようである.

「ますくはんがー」は容赦なく出てくる.

こんなのも.

Appleよ.データサイエンスが泣くぞ?

それで極め付きはこれである.もう……何もいうまい.

2022年2月2日水曜日

反転授業,予習の実際

オンライン対応の副産物として反転授業をやりやすくなったということについては,以前,何回か紹介したし,拙書「オンライン化する大学」でも論じた.実際に学生がどのような予習活動をしているのか,LMSのアクセスログを仔細に調べてみたら,興味深い事実が見えてきた.

反転授業として実施し,アクセスログを調査した科目は「プログラミング基礎」,1年生の必修科目で,受講学生は20名である.初回は事前学習させる術がないため,初回のオリエンテーションと最終回の力試しテストを除き,第2回から第13回までを反転授業の対象とした.

教室で,その回の授業が終わった直後に次回の講義資料と講義動画を公開する.学生は次回までにその資料をダウンロードし講義動画を視聴する.教室ではそれに基づいて少し高度な内容を補足するという手順で,反転授業を実施した.なお,1回の講義コンテンツは5〜7ページほどに分割されており,それぞれアクセスの記録が残る.基本的に,各ページに一つの動画が埋め込まれており,簡単な説明が動画に付随という作りになっている.

manabaの資料へのアクセスログは,最終アクセス時刻が記録される.したがって,復習のために再度ページへアクセスすると,アクセス時刻が更新されてしまう.正確な予習時間を計算するために,manabaからアクセスログの全てを取得し,各資料にアクセスした初回のタイムスタンプを取得した.

予習状況を確認するためには,予習が終了した時刻を測定する必要がある.しかし,終了したことはLMSのアクセス状況から察知することはできない.したがって,各回に出した課題の他に,プレ課題と題するレポート課題を各回,学生に提出されることにした.プレ課題では,動画を見終わって質問やコメントがあればそれを提出せよとし,とくにない場合は「動画を見ました」だけでよい,とした.

このグラフは,プレ課題提出のタイムスタンプから初回アクセスのタイムスタンプを引いた結果のヒストグラムである.横軸の単位は「日」,縦軸は件数である.

グラフから,次の事象が読み解かれるだろう.

  • 多くの学生が,1日(12時間以内)で予習を片付けている.6〜7日のところにあるピークを無視すれば,予習期間の長さは指数分布に従っているようにみえる.これは待ち行列理論おけるイベント発生期間の分布が指数分布に従うこととも合致する.
  • 5.5〜7.0のところに小さなピークがある.これは,とりあえず予習コンテンツが公開された時点でアクセスした後に放置し,次回の授業直前になって思い出したように報告する,あるいは,実際には予習を終えていたにもかかわらず,報告を忘れていて慌てて報告した状況も少なからぬ割合で発生したことによるものと推定される.
  • 期間がマイナスになっているケースがいくつか発生した.本来はあり得ない状況である.「動画見ました」の報告よりも初回アクセス記録が後になっているケースで,学生による虚偽の報告によるものかどうかは現在調査中である.

なお,この期間イコール予習時間,ではないことには注意しておきたい.あくまで,初回アクセスから予習終了までの時間を計測したものにすぎないため,実際の予習時間は,より短いものとなっているはずである.

追記:予習期間がマイナスになっているケースは,調査の結果,学生による虚偽の報告が原因であるということが判明した.本人が正直に告げてきたので「嘘はいかん」と説諭して本件は終了.