PL/SQL を構造的に考える
PL/SQL
で業務コードを書くという仕事があり、元々は俺の部署に仕事の依頼を流すということだったので、どうやったら運用保守も楽になるのか考えていたんだけど。結局、別部署の人たちがうんこなコードを書いて、俺にレビューを通さずに作って「ソースコードの管理をお願います」とか言ってきてる。
仕様書もコードをちら見したけどダメダメっぽいし、レビューすらしないで常に負債を作り続けるのなら、この業界引退してくれんかな。
インタビューで聞いた大雑把な要件はこんな感じ。
要件
- 今まで各業務でバラバラだった送信先データの取得する PL/SQL をつくる
- 仕様統一するつもりだが、部署によって違う可能性がある
数テーブルから、A にデータが無ければ B、B に無ければ C
というようになっているらしい。この順序が各業務によってバラバラで、且つ、何らかの条件に寄ってもテーブルの順序が変わるらしい。 - 各業務から呼ぶ PL/SQL は一つで統一する
各業務のデータの取得する仕様は違うが、各業務呼び出す PL/SQL
は一つにする。
結果
ハッキリは見てないが、これを引数 9 ~ 11 個の冗長的な PL/SQL
を作ってやがった…
だれがその物凄いパターンのテストを行い、今後の保守をするんだ。
俺ならこうする
- 各業務で共通的な仕様を決定し、その PL/SQL を作る
- 共通仕様に則れない業務は業務固有の PL/SQL を作る
- これらの PL/SQL をラップする PL/SQL を作る
こうすることでのメリットは次の通り。
- 共通仕様が明確になる
- 共通仕様から外れている業務が明確になる
- 各 PL/SQL のバグが影響を及ぼすスコープの範囲が縮まる
- 単体テストがやりやすい
- 共通仕様から外れている業務が共通仕様に移る時の修正が他業務に影響を及ぼさない。逆も又然り
よーし、ちょっと久々に ORACLE やってみるかー!
sqlplus でログイン
sqlplus misono/misono@misono
misono 好きすぎてすみませんすみません。
共通仕様の関数を作成する
CREATE OR REPLACE FUNCTION misono.DEFAULT_SENDTO
(
USERID IN NUMBER
)
RETURN VARCHAR2
IS
RTN VARCHAR2(32); -- Return Text
BEGIN
RTN := 'DEFAULT_' || USERID;
RETURN RTN;
END;
/
hoge 業務の関数を作成する
CREATE OR REPLACE FUNCTION misono.HOGE_SENDTO
(
USERID IN NUMBER
)
RETURN VARCHAR2
IS
RTN VARCHAR2(32); -- Return Text
BEGIN
RTN := 'HOGE_' || USERID;
RETURN RTN;
END;
/
各関数をラップする関数を作成する
set serveroutput on;
CREATE OR REPLACE FUNCTION misono.SENDTO
(
CODE IN VARCHAR,
USERID IN NUMBER
)
RETURN VARCHAR2
IS
IS_FUNC CONSTANT VARCHAR(60) := 'SELECT COUNT(*) FROM USER_SOURCE WHERE NAME = :data1';
NAME VARCHAR2(32); -- Function Name
FLG NUMBER DEFAULT 0; -- Function Exists
RTN VARCHAR2(32); -- Return Text
TXT VARCHAR2(500); -- Work
BEGIN
NAME := CODE || '_SENDTO';
-- Function Exists
EXECUTE IMMEDIATE IS_FUNC INTO FLG USING NAME;
if FLG = 0 then
NAME := 'DEFAULT_SENDTO';
end if;
TXT := 'SELECT ' || NAME || '(:data1) FROM DUAL';
EXECUTE IMMEDIATE TXT INTO RTN USING USERID;
dbms_output.put_line(TXT);
RETURN RTN;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('nodata');
END;
/
実際に試してみるとこんな感じで、hoge 業務以外は default に落ちている
SQL> select sendto('fuga', 2345) from dual;
SENDTO('fuga',2345)
----------------------------------------------------
DEFAULT_2345
SQL> select sendto('HOGE', 2345) from dual;
SENDTO('HOGE',2345)
----------------------------------------------------
HOGE_2345
SQL> select sendto('HOG', 2345) from dual;
SENDTO('HOG',2345)
----------------------------------------------------
DEFAULT_2345
ディスカッション
コメント一覧
まだ、コメントがありません