2020年4月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    

最近のコメント

最近のトラックバック

無料ブログはココログ

システム開発

2020年4月19日 (日)

Base64で送信されてきたhtmlから画像ファイルの保存と、相対パスに書き換えるプログラム(C#)

ダウンロード - e8b387e69699.zip

ASP.Net(Web Form)で、クライアント側からBase64で送信されてきた画像ファイルを、html文から抜き出して、Webサーバに保存して、相対パスに置き換えるプログラムです。.aspxのプログラムから一部抜粋しています。



using System.Text.RegularExpressions;
using System.IO;

(省略)

#region SaveBase64ToImageAndReplaceUrl/ Base64で送信されたhtmlから画像ファイルをサーバに保存して、URLを置き換える
        /// 
        /// Base64で送信されたhtmlから画像ファイルをサーバに保存して、URLを置き換える
        /// 
        /// html
        /// 置き換えられたhtml
        public static string SaveBase64ToImageAndReplaceUrl(string htmlContent)
        {
            //base64の正規表現 
            string strImg = @"data\:image/(jpeg|png|gif|jpg|bmp);base64\,(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?";

            //正規表現で、Base64を画像ファイルへの相対パスに置き換える
            string content = Regex.Replace(htmlContent, strImg, new MatchEvaluator(ReceiveImage), RegexOptions.Compiled | RegexOptions.IgnoreCase);
            return content;
        }
        #endregion

        #region ReceiveImage / 画像ファイルを受信して、サーバに保存して、相対パスを返す
        /// 
        /// 画像ファイルを受信して、サーバに保存して、相対パスを返す
        /// 
        /// 正規表現で一致したBase64の文字列
        /// 画像ファイルへの相対パス
        private static string ReceiveImage(Match match)
        {
            return ReceiveImage(match.Value);
        }

        /// 
        /// 画像ファイルを受信して、サーバに保存して、相対パスを返す
        /// 
        /// 正規表現で一致したBase64の文字列
        /// 画像ファイルへの相対パス
        private static string ReceiveImage(string imgBase64)
        {
            
            if (imgBase64.Substring(0, 10) != "data:image")
                return imgBase64;

            //拡張子を取得
            string fileExtention = GetImageFileExtention(imgBase64);

            //Base64の先頭部分を取る
            imgBase64 = Regex.Replace(imgBase64, @"data\:image/(jpeg|png|gif|jpg|bmp);base64\,","");

            //バイト配列にしてから、サーバの設置場所にファイルを保存する
            Byte[] imgByteArray = Convert.FromBase64String(imgBase64);

            string SavePath = HttpContext.Current.Server.MapPath("../Upload/");

            string filename = DateTime.Now.ToString("yyyyMMddHHmmssfff") + fileExtention;

            File.WriteAllBytes(SavePath + filename, imgByteArray);

            //相対パスを返す
            return "../Upload/" + filename;
        }
        #endregion

        #region GetImageFileExtention/ 拡張子を取得する
        /// 
        /// 拡張子を取得する
        /// 
        /// Base64のコード
        /// 
        private static string GetImageFileExtention(string imgBase64)
        {
            //ファイルの種類を取得する
            Regex re = new Regex(@"data\:image/(?.*?);base64\,", RegexOptions.IgnoreCase
                                | RegexOptions.Singleline);
            Match match = re.Match(imgBase64);

            //拡張子にして返す
            return "." + match.Groups["fileExtention"].Value;
        }
        #endregion

2020年3月 8日 (日)

ODP.NET Managed Driverを用いた、Oracle接続用クラスのサンプル(C#)

.Net Framework4以降のバージョンで、オラクルに接続するためのドライバで、Oracleクライアント不要のドライバ ODP.NET Managed Driverが提供されています。

Oracleクライアントがらみで、度々面倒なことが起きたので、プログラムを書き直そうという話になり、元になるサンプルプログラムを書いたので、参考に載せておきます。


using System.Data;
using System.Configuration;
using Oracle.ManagedDataAccess.Client;

namespace CommonClass.DbAccess
{
    #region データベースに対する問い合わせを実行するクラス
    /// 
    /// データベースに対する問い合わせを実行するクラス
    /// 
    public class ExecuteDb
    {
        protected bool _isBeginTrans = false; //接続中 true、切断中 false

        #region プロパティ OracleConnection

        private OracleConnection _cnnDb;

        /// 
        /// プロパティ OracleConnection
        /// 
        public OracleConnection CnnDb
        {
            get { return this._cnnDb; }
            set { this._cnnDb = CnnDb; }

        }
        #endregion

        #region プロパティ OracleTransaction
        private OracleTransaction _tran;

        /// 
        /// Oracle トランザクション
        /// 
        public OracleTransaction Tran
        {
            get { return this._tran; }

            set { this._tran = Tran; }
        }
        #endregion

        #region コンストラクタ
        /// 
        /// コンストラクタ
        /// 
        public ExecuteDb()
        {
            this._cnnDb = new OracleConnection(GetOracleConnectionString());
        }

        /// 
        /// コンストラクタ
        /// 
        /// Oracle Connection
        public ExecuteDb(OracleConnection cnnDb)
        {
            this._cnnDb = cnnDb;
        }
        #endregion


        #region デストラクタ
        /// 
        /// デストラクタ
        /// 
        ~ExecuteDb()
        {

            if(!this._isBeginTrans)
            {
                ///openしていたら、closeする
                if (this._cnnDb.State == ConnectionState.Open)
                {
                    this._cnnDb.Close();
                }
            }

            
        }
        #endregion

        #region GetOracleConnectionString/Configから接続文字列を取得
        public static string GetOracleConnectionString()
        {
            return ConfigurationManager.AppSettings["OracleConString"].ToString();
        }
        #endregion


        #region  BeginTrans トランザクションを開始する
        /// 
        /// トランザクションを開始する
        /// 
        public void BeginTrans()
        {
            if(! this._isBeginTrans)
            {
                //切断していたら再接続
                if(this._cnnDb.State == ConnectionState.Closed)
                {
                    this._cnnDb.Open();
                }
            }

            //前回のトランザクションを破棄
            if(this._tran != null)
            {
                try
                {
                    this._tran.Rollback();
                }
                catch (Exception ex)
                {
                    this._tran.Rollback();
                }
            }

            this._tran = this._cnnDb.BeginTransaction();
            this._isBeginTrans = true;
        }
        #endregion

        #region Commit/コミットを実行する、切断する
        /// 
        /// コミットを実行する、切断する
        /// 
        public void Commit()
        {
            if(this._isBeginTrans)
            {
                this._tran.Commit();

                this._tran.Dispose();

                if(this._cnnDb.State == ConnectionState.Open)
                {
                    this._cnnDb.Close();
                }

                this._isBeginTrans = false;
            }
        }
        #endregion


        #region Rollback/ロールバックを実行して、切断する
        /// 
        /// ロールバックを実行して、切断する
        /// 
        public void Rollback()
        {
            if (this._isBeginTrans)
            {
                this._tran.Rollback();

                this._tran.Dispose();

                if (this._cnnDb.State == ConnectionState.Open)
                {
                    this._cnnDb.Close();
                }

                this._isBeginTrans = false;
            }
        }
        #endregion

        #region RunSql/クエリ以外の処理実行
        /// 
        /// クエリ以外の処理実行
        /// 
        /// OracleCommand
        /// 処理件数
        public int RunSql(OracleCommand cmd)
        {
            try
            {
                int result = 0;

                cmd.Connection = this._cnnDb;

                //トランザクションが開始されていたら、開始する
                if (this._isBeginTrans)
                {
                    cmd.Transaction = this._tran;
                }

                result = cmd.ExecuteNonQuery();

                return result;
            }
            catch (OracleException ex)
            {
                throw new Exception(ex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                if(! this._isBeginTrans)
                {
                    if(cmd.Connection.State == ConnectionState.Open)
                    {
                        cmd.Connection.Close();
                    }
                }

            }

            
        }
        #endregion

        #region RunSelect/クエリを実行する
        /// 
        /// クエリを実行する
        /// 
        /// OracleCommand
        /// DataTable
        public DataTable RunSelect(OracleCommand cmd)
        {
            DataTable dt = new DataTable();

            try
            {
                cmd.Connection = this._cnnDb;

                //トランザクションが開始されていたら、開始する
                if (this._isBeginTrans)
                {
                    cmd.Transaction = this._tran;
                }

                if(_isBeginTrans)
                {
                    //トランザクション中の場合
                    cmd.Transaction = this._tran;
                }
                    
                using (OracleDataAdapter da = new OracleDataAdapter(cmd))
                {
                    da.Fill(dt);
                }
                return dt;
            }
            catch(OracleException ex)
            {
                throw new Exception(ex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion
    }
}
#endregion


2019年11月27日 (水)

システムの商談時のリスク診断の指標について

SEマネージャーのためのプロジェクト管理」(桜田孝 著 青山ライフ出版 )を読んだ中で、参考になりそうなところがいくつかあったのですが、その中でプロジェクトのリスク総合診断というところで、商談時のリスク診断というところを備忘録がてらまとめておこうかなと思います。

商談を開始するときのリスク管理で、リスクが大きいは、コンティンジェンシー予算を増やしたり、リスクを軽減したり、最悪、商談を辞退する必要性があるとしています。

リスクを確認する方法が、書かれていますが、そこを引用しますと


次の9つのうち,3つ以上該当するプロジェクトは、問題を引き起こす可能性が高いとのこと。
1.新規顧客からの受注
2.新システムの要件が「現行どおり」となっている
3.新技術や経験のない処理方式を採用している
4.IT企業と顧客の間で一括請負契約を結んでいる
5.IT企業のプロジェクト原価率が95%以上
6.開発期間が短納期
7.プロジェクト・マネージャーが類似システムの開発経験なし
8.IT企業が下請けに90%以上回している
9.顧客の要件定義能力に問題がある
(「日経コンピュータ 2010/1/15 NTTデータ 岩本副社長(当時)」からの出典とのこと)

さらに著者は経験的に下記の項目を上げています。

10.プロジェクト・マネージャーが過大な自信を持っている
11.ベンダとユーザの間の関係が"馴れ合い"で相互に甘えがある
12.ユーザに過大な期待を売り込んだ「何でもやります」
13.決めたことを一言でひっくり返す「独裁者」がいる
14.既存ベンダが辞退した案件である

『』が参照文献からの引用・一部変更

あと私独自に指標になるかなと思うのを上げますと
15.顧客側のTOPが独断で導入を決めたりして、具体的な要件が無い
16.顧客側の要求が、「完璧な資料を持ってこい」などと要求が高い、ミスがあると激昂したりする
17.経営層が極端が政治的思想を持っていたり、宗教への過度の信仰をしていて、それを社内に徹底している。
18.社風がワンマン企業の会社
19.パッケージ導入をする際に、その業界、業種、規模に導入するのが初めて
20.パッケージへのカスタマイズが多数生じる

チェックする項目は、最大10件程度が良いとしています。(3~4割該当したら、危険と言う感じでしょうか)

 

ホントにあった、炎上した案件に当てはめてみる

ある人材派遣会社への、管理システムを導入プロジェクト(大炎上した)で上の20項目を当てはめようと思います。(ちょっと多いですが)

1.新規顧客からの受注
 →該当

2.新システムの要件が「現行どおり」となっている
 →非該当(あれもやりたい、これもやりたいになっていた)

3.新技術や経験のない処理方式を採用している
 →該当(大規模案件だからとあれこれ、盛沢山になっていた)

4.IT企業と顧客の間で一括請負契約を結んでいる
 →非該当

5.IT企業のプロジェクト原価率が95%以上
 →非該当

6.開発期間が短納期
 →非該当(長期間だったが、後から考えたら足りなかった)

7.プロジェクト・マネージャーが類似システムの開発経験なし
 →該当(技術、分野とも初めてだった、それで余計なことをして火に油を注いだ)

8.IT企業が下請けに90%以上回している
 →非該当(オフショア含めて、50%ぐらいですかね)

9.顧客の要件定義能力に問題がある
 →該当(要件定義を絞れていない、開発側がまとめたものを自分たちは成果を評価するような感じだった)


10.プロジェクト・マネージャーが過大な自信を持っている
 →該当

11.ベンダとユーザの間の関係が"馴れ合い"で相互に甘えがある
 →非該当

12.ユーザに過大な期待を売り込んだ「何でもやります」
 →該当(担当営業は、大風呂敷を広げる人だった、自分では閉じない)

13.決めたことを一言でひっくり返す「独裁者」がいる
 →該当(開発側のPMと顧客側の責任者が独裁者、このせいで病気になったメンバーがいる)

14.既存ベンダが辞退した案件である
 →該当(既存ベンダーは、置き換え案件でも何もしてこなかった)


15.顧客側のTOPが独断で導入を決めたりして、具体的な要件が無い
 →非該当

16.顧客側の要求が、「完璧な資料を持ってこい」などと要求が高い、ミスがあると激昂したりする
 →該当(顧客側の責任者は資料にミスがあると、開発側の社長を呼び出して恫喝している)

17.経営層が極端が政治的思想を持っていたり、宗教への過度の信仰をしていて、それを社内に徹底している。
 →該当(左右どちらかに振り切れています)

18.社風がワンマン企業の会社
 →該当(役員が急に馘になるような会社らしい)

19.パッケージ導入をする際に、その業界、業種、規模に導入するのが初めて
 →非該当

20.パッケージへのカスタマイズが多数生じる
 →該当(パッケージがあることが逆に足を引っ張った)

全体で12件該当

引用元にあったNTTデータの副社長が書いた項目(1~9)で、4項目該当、該当が3つ以上あると炎上する確率が高いらしいので、商談開始の時にこのようなリスク管理ができていれば、辞退するという手もあったかと思います。
(もしくは、要件定義後の再見積もりの段階で辞退するなど)

このような項目を使って、リスク分析を商談の時にすれば、効果はあるかと思います。

ただ、営業の評価が受注金額ベースで、その受注したプロジェクトが最終的にどうなったかを評価しない限り、改善できないだろうなと思っています。それと、戦略的失注をしたときに、マイナス評価にならないような会社の制度がないとダメでしょうね。

「SEマネージャーのためのプロジェクト管理」を読んだ感想

SEマネージャーのためのプロジェクト管理(桜田孝 著 青山ライフ出版 ISBN 978-4-434-21802-6)を読んでみました。

SEと書いてあるので、システム関係のプロジェクト管理について書いてあります。

著者の紹介を見ると、著者は三菱電機の相当大きいプロジェクトを担当していていたようなので、そのことを留意して読まないと、いけないかなと思います。

過剰なプロジェクト管理は、プロジェクトの停滞を招くかと思いますので、このプロジェクトではどのような管理方法が良いか、進め方が良いかは考えていかねばならないかと思いますので。

内容は、プロジェクト管理の、教科書と言う感じで、プロジェクト管理に関する様々な、手法をプロジェクト計画~完了までを網羅したものとなっています。

大学の教科書や社内の研修資料と言った感じで、硬めな雰囲気の本で、いくつかプロジェクト管理を経験した人向けの内容かなと思います。
自分の経験を踏まえたうえで「こういう方法もあるんだ」等と思うことがあるかと思います。

ベンダー向けの本とは思いますが、導入先企業のプロジェクトの担当者が読んでもためになるかなと思います。システム会社はこういうものなのか、と思うと思います。この本でも、ユーザー側の協力が重要と度々言及されています。ユーザーのプロジェクトに関わる姿勢についてもことによっては、リスクとなると書いてあります。(間違った「お客様は神様」精神の担当者だったら、激怒するかもしれませんが)

また、「余談」というコーナーがところどころでてきて、著者が経験したり、見てきたプロジェクトの話(失敗が多い印象)が本書の本当の良さだと私は思います。

2019年8月31日 (土)

「10年戦えるデータ分析入門」(青木峰郎著)を読んでの感想・書評

データ分析を頼まれた関係で「10年戦えるデータ分析入門」(青木峰郎著 SBクリエイティブ)を読んでみました。

本書の副題に「SQLを武器にデータ活用時代を生き抜く」とあるように、SQL文でどのようにデータ分析するかが、載っています。
SQL文の説明も結構な割合で含まれていますので、SQL文を作ったことが無い人でも、読めると思います。

また、サブクエリ(副問合せ)やウィンドウ関数、問い合わせ結果の縦横変換といった、データベースを扱うエンジニアでも対象の業務分野によっては、苦手そうな内容も含まれています。

使用するデータベースはPostgreSQLなので、これをインストールして読んでいった方が良いです。
PostgreSQLはOSS(オープンソースソフトウェア)なので、無料で使用できます。

データベース(DB)は、SQL文の違い(私は説明するのに、訛り、方言なんか言っています)があるので、他のデータベースでは、その違いによりサンプルがエラーになるからです。

本書の中では、下記のような良く使われる分析方法が説明されています。

  • クロス集計
  • バスケット分析(どの商品が一緒に買われやすいか分析する)
  • デシル分析(購入金額の順に顧客を人数ベースで10分割する分析)
  • 時系列データの分析で移動平均法
  • アクセスログのセッション分析

この辺りは、自分が必要としている内容を詳しく読むや「やってみる」などでも良いかと思います。

後半は、データウェアハウス(DWH)の構築や企業全体の分析について説明されたりとなっています。

著者の方もSQL文の説明から後半部分まで1冊にまとめたことを「暴挙」と書いていましたが、細かい内容を知りたかったら別の書籍を読んだ方が良さそうです。
その辺りは、参考文献を細かく掲載されているので、それらを読んだ方が良さそうです。

あくまで、この本は分析の入り口(入門)と考えた方が良いかと思います。

2019年6月19日 (水)

64bitのIIS(Internet Information Services)で32bitのアプリケーションを動かす方法

先日、古いASP.NETのWebアプリケーションの開発環境の構築を頼まれて、PCに構築していたら、Visual Studio上ではコンパイルが通るのに、ブラウザで動かそうとすると、エラーメッセージが出てきて悪戦苦闘しました。

エラーメッセージ「ファイルまたはアセンブリ’・・・’、またはその依存関係の 1 つが読み込めませんでした。間違ったフォーマットのプログラムを読み込もうとしました。」

何だろうか、見当がつかずあれこれやっていたら、そう言えば、サードパーティー製の古いdllを読み込んでいたなと思い出し、64bitのIISで32bitを動かすときは、IISの設定しないと思い出しました。

設定することは、下記の内容になります。
IISのアプリケーションプールの詳細設定で、「32bitアプリケーションの有効化」をTrueにする

設定したのはWindows8.1のIISです。多少他のバージョンでは、画面の構成が異なると思いますが、同じ設定で動くと思います。
IISのアプリケーションプールの詳細設定画面

2019年6月 7日 (金)

詳細設計書が役立たずになる理由や解決策について

※以下の内容は、中規模~小規模なシステムの開発で要件定義~テストまで同一グループで行う場合に当てはまるであろうことで、大規模システムの開発では、通用しないことは断っておきます。また、ユーザの頭の柔らかさや、開発手法の違い等も影響するので、ある一例と考えてもらいたいです。

詳細設計書は、だいたい役立たずになります。あんなに時間をかけて、コードと1対1になるようにExcel方眼紙に文章書いて、SQL文は印刷に収まるように加工したのに、役に立つのは最初だけ、その後は、不具合報告を潰しまくっているうちに、どんどん設計書と乖離していく始末。

教科書通りでは、「詳細設計書を直したうえで、プログラムを直すように」なんて言われますが、その時間は遅れているプロジェクトでどこから捻出できるのでしょうね?

教えて偉い人(プロジェクトマネージャー)
プロジェクトマネージャー「そんなの自己責任だ、どうにかしろ!」

出ました自己責任、新自由主義者かアンタは。

あんまり書くと、パワハラのフラッシュバックが来て「近所迷惑」をしでかすかもしれないので、これぐらいにしておきます、文章が進みませんし。

詳細設計書を書いてからプログラミングという流れって、開発環境がまだ十分でなかったころ(COBOL全盛の頃とか)の名残だと思うのですよ。昔は、端末でコーディングする前に、入念にコーディングシートに記載して、机上デバッグしてから、端末でコードを打ち込むのとよく似ているなと思いまして。

でも、当時と今では、開発する内容も高度化していますし、複雑さも増していて、更に低価格受注、短納期となっていますので、古き良き時代(?)のようには、行かなくなっているかなと思います。

それなのに、このコーディングシートの後継と思われる、詳細設計書は名前を変えながらに残っている。
しかも、JavaやC#を使っているプロジェクトなのに、使用関数と書いてあったりしている。

愚痴をだらだら書くだけでは、居酒屋のサラリーマンと変わらないので、解決策というか、この詳細設計書を誤魔化した実例を載せておきます。上には極秘でこっそりやった方法になります。(色々な要因があるので、「銀の弾丸」では無いと思っていますが、この時は比較的、上手く行きました)

今の時代だと、Excel方眼紙と睨めっこして、プログラムを脳内で作ろうとするよりも、テーブルの定義をとりあえず作ってみたり、考えるためにプログラミングをした方が、開発効率が良いと考えて、実際そうしました。脳内妄想よりは、実際動かして試行錯誤できる分だけ、信頼性は上がるのではと思います。

こんな方法で、プログラムを書くと、品質の悪いコードが出来上がりそうですので、その汚いコードをリファクタリングして綺麗にするか、もう一度、綺麗に清書する必要はあります。

そのときに、最終的にプログラムを完成させるために、上記の未修正のコードと直す指示を出すためのものとして、ドキュメントを作って、プログラム担当者に渡す必要がありました。
(自分で直すなら、大規模修正でない限り、要らないと思いますが)

それで、プログラムが完成した後に、プログラムの説明を記すものとして、プログラムの説明書は作っておいた方が、良いかと思いますが、コード1対1のようなものは、作りませんでした。例えば、画面だったら、ボタンを押すとこういうイベントが発生して、どのメソッドが呼ばれるかなどでいいかなと思います。それ以上細かいことは、コードを読みましょうでいいと思うのです。(実際そうなるのだし)

それ以上に、クラス図などプログラム間の繋がり等を俯瞰できる設計書は必要と思っています。

そもそもプログラムを書くという工程は、製造ではなく設計の最終工程と思っています。プログラムが製造されるのは、コンパイルで、実行可能ファイルが出来上がるところだと思います。(コンパイル不要な言語でしたら、適宜読み替えましょう)

でも、「プログラムは人件費の安い中国(この頃は東南アジア?)にオフショアだ」とお考えの方々には、プログラミングは、製造なんでしょうね。

2019年6月 3日 (月)

会社標準の開発プロセス(ウォーターフォールモデル)に関する、あるユーザー側の評価と私見

今、勤務している会社はウォーターフォールが大好きです。
ウォーターフォールを必要としないような、小規模開発などについても、ウォータフォールに沿った手順を踏まされます。
では、ウォーターフォールで上手くできているかというと、決してそういう訳ではないのですが...

先日、システムを導入した会社の担当者(システム担当でなく、業務担当)と話をする機会があり、そのとき、ウォーターフォールに関する進め方についての、ユーザー側の意見を訊きました。

前提

  1. 弊社開発のパッケージソフトの導入で、パッケージ部分の導入については、ほぼパッケージ通り(一部カスタマイズあり)
  2. 小規模なサブシステムを機能を新規で追加する(マスター・帳票含めて10画面程度)
  3. ユーザー側は、システム担当1名、業務担当1名という状態で、とてもドキュメントの確認に手が回らない状態
  4. 会社の方針で、標準に定められているウォーターフォールで勧めろとの指示(パッケージ導入とカスタマイズ部分を同時に導入しろとのこと)

これに対する意見

  1. 要件を出してくださいと言われても、いざ動かしてみないと分からない箇所や見落としがあるので、要件定義・基本設計で仕様凍結をしてしまうのは、問題がある
  2. バインダーに挟まれた大量の紙資料をもらっても、システムの動くイメージまではどうしてもできなかった。
  3. 動かせる部分は、早く操作して、業務との乖離を確認したかった。(多少の設定ミスのバグなどは気にしないとのこと)

開発担当者だった私の意見としては、さっさとパッケージのパラメータ設定してパッケージのままで動かしてしまい、パッケージのカスタマイズ部分と小規模なサブシステムを反復的に開発した方が良かったと思っていましたが、会社の方針でダメだったと伝えました。

そうしたら、担当者からは「そうして進めてもらえれば、良かったかもしれない」との意見でした。

開発プロセスの標準化も結構ですが、あくまでも「標準」であって、絶対では無いと思うのです。標準通りに進めることが「お客さんのため」ではなく、開発側の都合(ISO9000の審査のためなのか、いちいち考えるのが面倒と思っているかは分かりませんが)だと思っています。

プロジェクトでは開発側、ユーザ側、双方が使える資源(費用、人手、時間、技術レベル等)の中で、どのような手段をもって実現していくかを考えて行かないといけないかと考えています。標準の開発プロセスに無理に合わせるのではなく、プロジェクトによってカスタマイズないしは、従わないという選択肢もあっていいのではないかと思います。

それに、管理者は「会社の決まりだから従え」というのではなく、「自分の頭」で考えてもらいたいものだと思います。

2019年3月21日 (木)

2019年3月19日のココログのメンテナンスおける不具合についての私見(3月21日時点)

ココログで2019年3月19日に行ったメンテナンスで、大規模障害が生じています。
21日13時現在、公式な発表などは出ておりませんので推測で書きますが、システム関連の仕事をしているため、他山の石をすべく、まとめておこうかと思います。
現場の担当者の方々は不眠不休で頑張っているかとは思いますし、批判する気はありませんが、ニフティ株式会社に対しては、あまりにお粗末な不具合であり、その後の対応についても利用者は不信を募らせており、怒りを覚えます。

3月19日の作業遅延

切り替え作業は、3月19日の0:00-13:00の予定でしたが、17:00に延長しました。その後、トラブルが続発して、阿鼻叫喚の事態になりました。
予定通りに切り替え作業が進んでいなかったと思われます。
その遅延が、データ量等、本環境での特有の問題でしたら、終了時間の遅延も致し方ないかと思います。
その後のトラブルを見ると、データ以外の問題、例えば、システムに不具合が見つかって、修正していたのではと思いました、このようなことをしていたのなら、潔く延期した方が、良かったのではないかと思います。

切り替え後にシステムが不安定

切替後、ログインができない事象や、ログアウトしてしまうなどの事象が、多数報告されていました。
その後、20日の深夜にサーバを急遽増設をして、しのいでいましたが、新システムのサーバ負荷を過小評価していたのではと当初は思いました。
しかし、その後も不具合が報告されているところを見ると、プログラムのミスで、高負荷の状態が継続していた可能性もあるかと考えています。

移行ミスが見られる

私のブログでも、画像が無くなっていたり、URLが変わってしまっていたりして、ページがGoogleでの検索からページが表示できない事象が見られました。
これらは、移行時の処理に、何らか不具合があり、移行が出来なかった可能性が相当高いと思います。

管理画面の不安定さについて

管理画面の不具合については、いくつか「検証していれば気づくだろう」レベルの不具合が報告されています。
開発側、受け入れ側(ニフティ)の検証が不十分だったのでは、と思っています。

管理画面の操作面の不満

管理画面を一新したため、利用者から「使いづらい、元に戻してもらい」「あの機能が無くなった、代替機能はあるか」という
問い合わせが見受けられます。
慣れの問題もあるかと思いますが、事前に変更後の画面イメージの提示などがあっても良かったのではと思っています。
これは、難しいかもしれませんが、ココログ利用者から、新システムのモニターを募るなどして、利用者の意見を本稼働前に取り入れられるようにできれば、良かったかもしれません。

利用者に対する情報公開の遅れ

トラブル発生時に、どのようなトラブルが生じていて、現在解決したのか、修正見込などの、情報の掲載がされていないため、
利用者が余計に不安になってしまったのではと、考えています。
Excelの表をPDFにしたようなものでも構いませんので、niftyのトップ画面など分かりやすい所に載せてもらいたかったです。

切り替えは、稼働日ありきのスケジュールだったのでは?

ここまで、ひどいものだったら、ニフティで受け入れテストを行った段階で、気が付くと思いますが、それが見過ごされているのは、ニフティ及び協力会社で稼働日ありきのスケジュールでの切替だったのでは、という疑念を持っています。
3月というのも、決算期末の月になる可能性が高く、切替日の決定は会計上の理由もあったのではないかと思っています。

親会社のノジマに対して

ニフティの親会社にあたる、株式会社ノジマに、多少の私怨を交えてには、なりますが、一言苦言を載せておきます。
システム更に言えば、インターネット接続サービスを行う会社のサービスを、家電量販店のノリ(強引に顧客に物を買わせるような販売方法)で、運営してはダメでしょ。
御社の野島廣司社長は携帯電話販売子会社の店長に「使えない」と非難した内容を社内のイントラネットに見えるところに載せたと朝日新聞に報じられたと東洋経済の記事で見かけました。東洋経済の記事の中に『ノジマで採用して教育した社員を送り込んで、ノジマ流を移植する』(原文のまま)と書いてありましたが、ニフティにも同様に、『ノジマ流』を移植して今回の大トラブルを起こしたのでは、ないですか?

2019年1月17日 (木)

「ライト、ついてますか―問題発見の人間学」の感想・書評

「ライト、ついてますか―問題発見の人間学」ドナルド・C・ゴース (著)  G.M.ワインバーグ (著) 木村 泉 (翻訳) (共立出版 ISBN 978-4-320-02368-0)を久々に読んでみました。

問題の解が書いてあるのではなく、「問題の発見」について書いてある書籍になります。

コンサルタントやシステムエンジニア(SE)のような、「問題を発見」して「解決策」を探すような職種の人は、読む必要があると言われている本です。

(どのような職種の人も「問題を発見して、解決策を探す」ということはしますので、読む価値は十分にあるかと思います。)

問題の発見についても、たとえ話(高層ビルのエレベータが遅い問題やトンネルでのヘッドライト点灯の注意看板など)から教訓を結びつけるという書き方をしていて、分かりやすいです。やや、文章がまわりくどく、分かりづらい「問題」があり、何度か読むと良いのかと思います。