write ahead log

ロールフォワード用

Ubuntu(17.10)上で手っ取り早くRuby + Apache2でCGIを使う

CGIなんて久しく使っていなかったのでメモっておく.

Apache2を入れる.

とりあえずコレ的な.

$ sudo apt install apache2

Rubyも入れる

$ sudo apt install ruby

CGIを有効にする

Debian系の設定は初めてで戸惑った.

$ sudo a2enmod cgid

apacheを再起動.

$ sudo systemctl restart apache2

CGIを有効にする(2)

設定ファイルを変更する.

以下を変更.
(普通は上書きしないと思うが, 手抜き)

/etc/apache2/sites-available/000-default.conf

下記をVirtualHost内に追加する.

ディレクトリは

/var/www/cgi-bin

を使うのが一般的だと思うけど, 諸事情でhomeに作った.

   ScriptAlias /cgi-bin/ "/home/twinbird/cgi-bin/"
    AddHandler cgi-script .cgi .rb
    <Directory "/home/twinbird/cgi-bin">
        AllowOverride None
        Require all granted
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>

別にやらなくても良いと思うけど, ServerNameをGlobal設定しておくと警告も消えた.

ここまでやったらapache2を再起動.(またはリロード)

sudo systemctl restart apache2

CGIを実行にする

業界の常識に従い, とりあえず挨拶しておく.

上記設定のディレクトリ(この場合は/home/twinbird/cgi-bin/)へ以下を配置.

#!/usr/bin/ruby
# /home/twinbird/cgi-bin/sample.cgi

require 'cgi'

cgi = CGI.new

puts cgi.header
puts "Hello, world"

権限変更しておく.

$ sudo chmod +x sample.cgi    # 705にするのがよかろう

ブラウザで

localhost/cgi-bin/sample.cgi

へアクセスして挨拶されればOK.

RubyでCGIとか学生以来じゃなかろうか.

cgi.headerをputsしてなくて30分以上ハマったのはココだけの話.

VB.NET(Windows Forms)で見積管理システムを作った

昨今の技術動向をガン無視ですが, ここ2,3ヶ月ほど深夜にぼちぼちやっていたのが形になったので.

github.com

Releaseにインストーラを入れてみました.

TravisCIが使えるかと思いましたが, 流石にWinformは無理でした.(VBはサポートしてるんですね)

目的

一応ある程度は作った目的があって

  • ある程度モジュール化された設計ができるかやってみる
  • テスト可能な設計ができるかやってみる
  • データバインディングスタイルで実装してみる
  • 使ったことの無いコントロールを知る
  • インストーラで入れて動くとこまで1人で作ってみる

お仕事もほとんどがVB.NET + Winformsなんですけどね.

やっぱシステムインテグレーションの業界にいると人売りか業務知識偏重になっちゃって技術面は仕事で伸ばすのは難しいかなと思います.

(面白いとこもありますけどね)

仕事でできないなら, 一度自分でやってみるかと.

作るもの

業務システムっぽいものを作らないと, あんまりリアリティがないです.

ということで, 単純な見積書を作成するシステムを作ってみる事にしました.

見積書はGoogleで適当に検索して出てきたテンプレートをミックスしてフォーマットにしました.

こんな感じです.

UIは参考にするためにVectorでいくつか類似ソフトを落として見てみましたが, 参考になったのかよくわかってないです.

案外, 世の中にあるものは変わらないなという印象でした.

最終的に下記の様なUIにしました.

そんなわけで, 機能的には雑です.

利用ツール

仕事でやるわけじゃないので, 全部タダでないとなりません.(必死)

今のMSにはVisual Studio Communityがあります.

これのおかげで普通に開発ができました.

帳票が問題でしたが, MS Reportがあったので何とかなりました.

主だったライブラリは以下の通りです.

ライブラリ/ミドルウェア 用途
.NET Framework 4.5 これがないとはじまらない
MS Test テストフレームワーク
MS Report 帳票作成
ADO.NET RDBMSアクセス用
SQLite3 RDBMS
MS VS Installer Projects インストーラ作成

Entity Framework使わないの? という感じですが, あえて使っていません.(便利なのはわかります)

O/Rマッパーが嫌いなわけじゃないんですが

  • システム全体の規模が大きくなると最終的に複雑なSQLを発行する事になる
  • みんな横着してO/Rマッパーを使ってパフォーマンスが酷いことになる
  • みんな横着してO/Rマッパー使ったつもりが逆に辛くなる

というケースも見てきているのであえて使わずにおきました.

ただ, 今回の例だとCRUDばかりなので, 明らかに使った方が良いです.
(実戦ではもっと要件が複雑化するでしょうが)

設計

このアプリケーションは8つのプロジェクトで構成されています.

├ADOWrapper
│  ├Interface
│  └SQLite3
├Application
│  ├Component
│  ├Form
│  ├Report
├Domain
│  ├DomainObject
│  └Repository
├Infrastructure
│  ├DDL
│  └RepositoryImpl
├Setup
├TestADOWrapper
├TestDomain
├TestInfrastructure

Testから始まるプロジェクトは各プロジェクトのテストプロジェクトです.

Setupはインストーラ作成のためのプロジェクトです.

各プロジェクトの依存関係は以下の通りです.(Test, Setupプロジェクトを除く)

---------------        --------------- 
| Domain      |        | ADOWrapper  |
---------------        ---------------
   ^        ^            ^
   |        |            |
   |     ------------------
   |     | Infrastructure |
   |     ------------------
   |        ^
   |        |
---------------
| Application |
---------------

ADOWrapperはADO.NETの簡易なラッパーです.

このソフトウェア全体を通して, DBへのアクセスにはこのADOWrapperを用いています.


Infrastructureは永続化のための機能を提供します. これは, DomainプロジェクトのRepositoryインターフェースに対する実装です. RDBMSを差し替える場合にはおそらくInfrastructure全体を差し替える事になります.

(ADOWrapperもInterfaceと実装が分かれているため, 基本的にはRDBMSの差異を吸収することができます. しかし, たいていの業務アプリケーションはRDBMS実装依存のSQLを使わざるおえないでしょう. そうなるとSQLを記述するInfrastractureプロジェクトの差し替えが必要です.)


Domainは業務的に意味のある塊をクラスにしたものの集まりです.

入力の妥当性確認や計算(見積なら合計金額や税率計算)などもこのプロジェクトのクラスで行っています.


Applicationは普通のWindows Form Application(いわゆるWinformsアプリ)です.

画面とのデータのやり取りは極力データバインディングを利用しています.

Domainプロジェクトのデータ構造をそのままバインディングしている箇所もあれば, 間にPresentation(Data Transfer Object)というクラスを中継してバインディングしている所もあります.

単純なマスタの場合など, 直接Domainプロジェクトのクラスをバインディングしている箇所が多いですが, 検索して表示する一覧などは後からドメインオブジェクトを跨いだ項目表示を要求されることが多いという経験上, Presenterを挟むようにしています.

      -----------------
      | Event Handler |
      -----------------
        | Control  |
        |          |
-------------   ------------------
| Presenter |---| Domain Object  |
-------------   ------------------
        |          |
        | Data     |
        | Binding  |
        |          |
      ------------------
      | User Interface |
      ------------------

と, ここまでの話はほとんど本やWebサイトの見よう見まねです.

できる人がやればもっときれいになりそうですが, 今の私にはこれが限界です.

とはいえ, 値オブジェクト化できるところもたくさんあるし, Helperみたいなのを作ってコントロールの初期化なんかはまだまだ共通化できそうです.

帳票や集計関連の処理なんかも追加/複雑化したらServiceを用意すれば対応できそうです.

実装

Winform + データバインディングでのプログラミングをほぼ経験していないので, 良い機会になりました.

データバインディングめっちゃ便利じゃん.


他にはコントロールを勉強しなおす機会になりました.

というのも, 恥ずかしながら今まで下記のコントロールを使ったことがなかったからです.

  • BindingSource
  • ErrorProvider
  • ReportViewer(MS Report)
  • HelpProvider
  • MDI Window

あとは, DataGridViewのカスタムはほぼやった事がなかったので勉強になりました.

自作コンポーネントで知って良かったのは以下です.

VB化してありがたく使いました.

  • 背景色を変えるコンポーネント(何故か絶対に要件になる)
  • DataGridViewにソート機能を付けるためのBindingList
  • DataGridViewCellのカスタムコントロール

ソースはComponent以下です.

参考URL

参考URLが多すぎるのですが, 多少整理して貼っておきます.

設計

TERASOLUNA Server Framework for Java (5.x) Development Guideline - アプリケーションのレイヤ化

いきなり.NETじゃない.

NTTデータのフレームワークの設計規約みたいです.

なんだかんだ参考になりました.

GUIアーキテクチャパターンの基礎からMVVMパターンへ

ふむー.って感じ.

Microsoft - .NET におけるアプリケーション アーキテクチャ ガイド

このリストの中で唯一読んでない.

というか昨日知った.

もっと早く知りたかった.

実装

とあるコンサルタントのつぶやき - Part 1. 双方向データバインドの基本的な使い方

間違えなく実装面で一番参考になった. Part2も素晴らしい.

とあるコンサルタントのつぶやき - .NETとJavaの例外処理の違い

趣旨とは違うけど, Javaの勉強になった.

コントロール

Microsoft Developer Network - Windows フォーム コントロールの機能別一覧

あまりに無知なので読んだ.

Bug Catharsis - 常識的に考えてErrorProviderを使いたいよね

ごめんなさい.ごめんなさい.

be free - フォーカスがあるテキストボックスの背景色を変えるコンポーネント

ありがとうございました.

DataGridView

.net snippets - C# - SortableBindingList

これをVB移植して利用.

こいつがないとDataGridViewにバインディングしてもソートできない.

+++ 上野メモ帳 +++ 0 DataGridViewのDataSourceに独自クラスのListを指定する場合

DataGridViewに具体的にバインディングする.

方法上記と合わせて.

方法 : Windows フォーム DataGridView Cells でコントロールをホストする

これさえ読めばカスタムセルが作れる.

(コピペできる)

MS Report

インストール

Microsoft Developer Network - VS2015でレポート(ReportViewer)を使用したい

変更から入れるってマジでわからないっす.

Microsoft Rdlc Report Designer for Visual Studio

これ入れる必要あったのかよくわかってない.

SSDT for Visual Studio 2017

これも入れる必要あったのかよくわかってない.

Stack overflow - Reportviewer tool missing in visual studio 2017 RC

最終的にここの2番目の回答のモジュールに参照を全て通したら動いた.

あーリビルドはしたかも.

使い方

Microsoft レポートによる帳票の作成

素晴らしい教材.

導入以外は基本これで済んだ.

あとはサブレポートぐらいだけど, サブレポートはフィーリングでいける.

ReportViewerにおけるサブレポートの使い方について

そもそもサブレポートというものをこれで知った.

SQLite3

職人気質を目指すプログラマの日記 - System.Data.SQLite の GetDateTime でエラー

恐ろしくハマったので.

インストーラ

ドラブロ - Visual Studio 2017 でインストーラを作成する

すごい親切.

Web備忘録 - Visual Studio 2017 Installer Projects でインストーラーを作成する

こちらも中々親切.

疑似個人情報データ生成サービス

デモデータ作るのに使わせてもらった.

プロ生 - マイクロソフトが提供しているアイコンセットまとめ

大抵のアイコンはこれでいい気がする.

参考書籍

設計関連

  • .NETのエンタープライズアプリケーションアーキテクチャ第2版 .NETを例にしたアプリケーション設計原則
  • 実践ドメイン駆動設計
  • エンタープライズアプリケーションアーキテクチャパターン
  • エリック・エヴァンスのドメイン駆動設計

業務知識系

  • グラス片手にデータベース設計 販売管理システム編 第2版
  • グラス片手にデータベース設計 ~会計システム編
  • グラス片手にデータベース設計~生産管理システム編

dbext.vimの使い方

vimからDBアクセスできるという素晴らしいプラグイン.

導入

面倒なのでVundle使う. この辺は個人のお好みで.

以下をvimrcに記述.

Plugin 'vim-scripts/dbext.vim'

設定

プロファイル(接続情報)を書く必要がある.

MySQLの場合

当然だけど, MySQLクライアントが導入されている必要がある.

以下の設定の場合.

項目
プロファイル名 mysqlnodb
ホストIP 127.0.0.1
ユーザ名 root
パスワード password
DB名 test

.vimrcにこんな感じで書く.

let g:dbext_default_profile_mysqlnodb = 'type=MYSQL:host=127.0.0.1:user=root:passwd=password:dbname=test'

Oracleの場合

項目
プロファイル名 myORA
ホスト 127.0.0.1
ユーザ scott
パスワード tiger
let g:dbext_default_profile_myORA = 'type=ORA:srvname=127.0.0.1:user=scott:passwd=tiger'

PostgreSQLの場合

ちょっと試した限りではPostgreSQLが一番癖があった.

項目
プロファイル名 myORA
ホスト 127.0.0.1
ユーザ test_user
DB名 test_db
パスワード test_password
ポート 5432
let g:dbext_default_profile_postgres = 'type=PGSQL:host=127.0.0.1:user=test_user:dbname=test_db:passwd=test_password:port=5432'

記述自体はこれだけなんだけど, 実行すると下記の様に怒られる.

dbext:PostgreSQL requires a '$HOME/.pgpass' file in order to authenticate. This file is missing. If you are using a local connection, you can create an empty .pgpass file.  The b
inary 'psql' does not accept commandline passwords.

.pgpassを作ると怒られずに済んだ.

$ touch ~/.pgpass

あとロケール設定していないと怒られた.

SQLiteの場合

以下の設定の場合.

項目
プロファイル名 sampleSQLite
DBファイルパス ~/test.db
let g:dbext_default_profile_sampleSQLite = 'type=SQLITE:dbname=~/test.db'

プロファイルの外部ファイル化

プロファイルは.vimrcとは別管理したい.

そこで.vimrcに外部ファイルがあれば読み込む様に記述して, ~/.dbext_profileという名前のファイルに上記のプロファイル設定はまとめて書く事にした.

" プロファイルを記述したファイルがあれば読み込む
if filereadable(expand('~/.dbext_profile'))
    source ~/.dbext_profile
endif

履歴ファイル名を変える

履歴機能は便利なんだけど, ホームが汚れるのが嫌なのでファイル名を変えた.

let  g:dbext_default_history_file = '~/.dbext_history'

使い方

これだけあれば仕事にも使えそう.

Normalモード

コマンド 機能
slt テーブルの一覧を取得
sdt カーソル下のテーブル名のテーブル定義を取得
sdta 指定テーブル名のテーブル定義を取得
se カーソル下のSQLを実行
sbp 接続プロファイルの切替
sh Historyを表示
st カーソル上のテーブルをSelect

Insertモード

補完が便利っぽい.

*.sqlファイルを開いていない時には以下の様にfile typeを指定してやる必要がある.

:set ft=sql
コマンド 機能
<C-c>t テーブル名を補完
<C-c>v ビュー名を補完
<C-c>c カラム名を補完
<C-c>a シンタックスを補完
<C-c>L テーブル補完中に押すとカラムを全て出力

何気に辞書登録されているので

<C-x> + <C-k>

が使える.便利.

WSLのUbuntuにsqlplus(Oracle client)を入れる

何でも動いてビビっちゃうWSLですが, sqlplusを入れてみました.

ますますWSL環境に引きこもりそうです.

ダウンロード

この辺からどうぞ.

Oracle Database 12c Release 1 (12.1.0.2.0)

ユーザ登録が要るの, 面倒ですけど.

libaio1とalienをインストール

oracleからはrpm形式で配布されているのでdeb形式に変換します.

変換に必要なalienをとりあえずインストール.

$ sudo apt-get install libaio1
$ sudo apt-get install alien

deb形式に変換する

$ sudo alien oracle-instantclient12.1-basic-12.1.0.1.0-1.x86_64.rpm
$ sudo alien oracle-instantclient12.1-devel-12.1.0.1.0-1.x86_64.rpm
$ sudo alien oracle-instantclient12.1-sqlplus-12.1.0.1.0-1.x86_64.rpm

インストール

sudo dpkg -i oracle-instantclient12.1-basic_12.1.0.1.0-2_amd64.deb
sudo dpkg -i oracle-instantclient12.1-devel_12.1.0.1.0-2_amd64.deb
sudo dpkg -i oracle-instantclient12.1-sqlplus_12.1.0.1.0-2_amd64.deb

環境設定

.profileとか.bashrcとかどこかに.

# oracle client
export LD_LIBRARY_PATH=/usr/lib/oracle/12.1/client64/lib
export NLS_LANG=Japanese_Japan.UTF8
export PATH=$PATH:/usr/lib/oracle/12.1/client64/bin

この時点でbash再起動か

$ source .profile

で再読み込みしておきます.

prelinkしておく

この時点で動くかなと思ったのですが, 下記のエラーが出て動作しませんでした.

sqlplus: error while loading shared libraries: libclntsh.so.12.1: cannot enable executable stack as shared object requires: Invalid argument

ここは無能らしくstack overflowの意見を鵜呑みにします

sudo apt-get install prelink
sudo execstack -s /usr/lib/oracle/12.1/client64/bin/sqlplus

これで動作しました.

余談:prelinkって何や

こちらを参考にすると, shared objectをあらかじめ組み込んでしまうソフトだそうです.

へー.知らなかった.

ところで上記で実行したのは

execstack

ですが, こちらはセキュリティ機構の回避のためのコマンドらしいです.

Exec Sheildって初めて聞きました.

さらに余談

HOMEにoradiagディレクトリが出来て邪魔だったのですが消す方法があると知ってとてもうれしかったです.

WSL上のUbuntuのターミナル色テーマを変更する

色テーマを、変えたい

Ubuntu on WSL(bash on windows)は非常に使い勝手が良くて, すっかりこれ無しでは仕事ができなくなってしまった.

しかし色テーマ, これだけが不満だった. (赤が見づらい)

まぁ, プロパティからポチポチ変えりゃいいんですが, あまりにも面倒くさい.

うーむ, と色々Webを徘徊していると下記のページを見つけた.

Introducing the Windows Console Colortool

おぉ, そうなんすよ.

色テーマを簡単に変える方法が無いかをずっと探していたんだけど, どうも「colortool」というものをMicrosoftが出してくれているらしい.

Githubにリポジトリされている.

これは便利すぎる.

使ってみる

  1. Githubからまずはzipをダウンロードします
  2. 解凍して, cmd.exeを開き, 解凍したフォルダへ移動します
  3. コマンドを入れます
> colortool -d [色テーマ]

サンプルではsolarized_darkが紹介されていますね.

> colortool -d solarized_dark

私はOneHalfDarkにしてみました.

とても美しいです.

psqlコマンド自分用チートシート

PostgreSQLのコマンド, psql.

バージョンは9.6

個人的にはMySQLより分かりやすい気がする.

インストール

$ sudo apt install postgresql-client

9.6限定にするには以下.

$ sudo apt install postgresql-client-9.6

WSL上だとUbuntu Xenialだった.

9.5までしかなかったので先にリポジトリを追加した,下記手順を先に実行すればよい.

$ sudo add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main"
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ sudo apt-get update

接続

$ psql -h [ホスト名] -U [ユーザ名] -d [データベース名]

クエリ

\xで拡張表示(縦表示)できる.

\eで直前に編集したSQLを編集できる.

終了

\q

コマンドの実行履歴

~/.psql_historyに残る

バックアップ

$ pg_dump -h [ホスト名] [データベース名] > [バックアップファイル名]

リストア

$ psql [データベース名] < [バックアップファイル名]

MySQLコマンド自分用チートシート

インストール

ubuntuの場合(WSL可)

$ sudo apt install mysql-client

接続

WSLのUbuntu上からローカルへ接続する場合は[127.0.0.1]と指定が必要だった.
(localhostではダメだった)

長いので開発時はalias組んだ方がいい.

普通につなぐ
$ mysql -h [ホスト名] -u [ユーザ名] -p[パスワード(pとの間にスペース入れない)] [スキーマ名]
縦表示でつなぐ

縦表示(psqlでの拡張表示)で常に表示したい場合は-Eを付ける.

$ mysql -h [ホスト名] -u [ユーザ名] -p[パスワード(pとの間にスペース入れない)] [スキーマ名] -E
ページャ指定でつなぐ

とりあえずless指定してみる.

$ mysql -h [ホスト名] -u [ユーザ名] -p[パスワード(pとの間にスペース入れない)] [スキーマ名] -E --pager="less" 
エンコーディング指定でつなぐ

utf8にすると

$ mysql -h [ホスト名] -u [ユーザ名] -p[パスワード(pとの間にスペース入れない)] [スキーマ名] -E --pager="less"  --default-character-set=utf8

クエリ

縦表示(拡張表示)

クエリの末尾に\Gを付けると縦表示になる.
(コマンド起動時に-Eを付けている場合はデフォルトで縦表示になる)

> SELECT * FROM users\G
編集

エディタでクエリを編集できる.

> edit

エディタ終了後に;でクエリ実行.

データベースの一覧
> show databases;
テーブルの一覧
> show tables;

終了

> quit

コマンドの実行履歴

デフォルトでは以下にある.

~/.mysql_history

バックアップ

mysqldumpコマンドを使う.

$ mysqldump -u [ユーザ名] -p[パスワード(pとの間にスペース入れない)] -h [ホスト名] -t [スキーマ名] > [出力ファイル名]

リストア

mysqlコマンド経由で標準入力からSQLを投入するだけ.

必要であれば事前にCREATE DATABASEを実行.

接続方法は前掲通り.

$ mysql -h [ホスト名] -u [ユーザ名] -p[パスワード(pとの間にスペース入れない)] [スキーマ名] < [リストアファイル名]