忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


2024/05/02 10:39 |
そこで非を認めるお客様は、出来るお客様。
「前は使えていた機能Aが、新型機になった途端、使えなくなったんですけど!責任者出せ謝罪と賠償ぶらぶらぶら!」
というようなクレームが、お客さんから直接舞い込んでくることがよくあります。

そ、そういえば新型機で機能Aが動くかどうかは、ちゃんと確認した記憶も記録も無い...
泣きそうになりながら
「すみません生まれてごめんなさい今すぐ確認します責任とって坊主になります既に坊主ですが」と、音速でメールをしたためる傍ら、ふと疑問が。

あれ?そもそも機能Aって、動作を保証してたか?
保証していたら、仮に俺がアホ過ぎて確認を怠ったとしても、後工程の偉い方々も動作を確認するので、そこで動かなくて超怒られるだけで済むはず。出荷されている以上、確認してOKだったわけで、少なくとも「使えない」なんて事は無いはず。

膨大なメールの海を漂い、過去の俺の職場日記を探ってみる。
そこで以下のような事が分りました。というか思い出しました。
・機能Aは保証はしていないが、搭載はされている。
・機能Aよりも高機能な、機能Sは保証している。
・3年前にも、同じような苦情を受けている。結果的にはお客さんの設定間違いだった。
・もっと言えば7年前にも、同じような苦情を受けている。担当が替わるたびに、引継ぎがされていないらしく、同じ事言うてきてはる。

これを知った途端、少し安堵。真っ青だった顔色も、いつものキモい酒焼け色に戻りました。

念のため、新型機で機能Aを試してみると、すんなり動作した。
ただ、間違えやすい設定がある事も分った。
これ、お客さんが色々間違えてるだけっぽいな。

これを知った途端、右の口角上がる上がる。いつもの意地悪顔に戻りました。完全に俺のターンです。

準備を整え、いざ返信。
弊社の製品でご迷惑をおかけして、申し訳ありませんと、まずは謝罪。実は悪くないけど謝罪。あぁ日本人。
機能Aは保証しておりません。機能Sであれば保証していますと、相手の認識ミスの可能性を、さりげなくアピール。ここでちょっとお怒りになっても、即気持ちを鎮められるように、すぐさま次。
ただし、保証はしておりませんが、機能Aも問題なく動作する事を確認しておりますと、安心していいよ安らぎに抱かれてSleep My Dearと歌っておく。
過去にも2度ほど同じ問い合わせがあり、その際は○○の設定に間違いがある事が原因でしたと、ここでトドメ。担当が替わるたびに同じ事言ってんじゃねーよと、暗に含ませておく。
今一度、お客様の設定をご確認いただけますでしょうかと、綺麗にまとめて終了。

数時間後に
「大変失礼しました」
という返信を受けました。ここまで含めて、過去の2回とほぼ同じ流れでした。

生産的な仕事は一切していないけど、今日も日が暮れました。

拍手


2015/04/03 19:02 | Comments(0) | 仕事
Microsoft Expression Blend 2とVC++で作る、windows CE 6.0アプリケーション その2
では早速、サンプルアプリケーションのソースを公開します。
サンプルアプリケーションの概要は、以下の通り。

・開発環境はVisual Studio2005 VC++ 6.0
・ダイアログ無しベース。画面はMicrosoft Expression Blend 2で作成した、XAML(ざむる)を呼び出す事で実現。
・2つの画面を用意。画面は交互に行き来が可能。
・画面遷移時にデスクトップが見えてしまう事を防ぐ為に、背景用のXAMLを常に表示。
・各画面にボタンを用意し、ボタンクリック、キーアップ、キーダウンを取れるようにしています。
・windows messageのHookにより、100msタイマ、ジェスチャ(フリック等)に対応。

開発中に見つかった不可解な問題と、回避策についても一部言及しています。

ソース全文のダウンロードはこちらから。
http://nagisa.okoshi-yasu.net/blog/Subproject1.zip

まずは定義から。

#define XLOOPTIMER_ID    1
#define XBTNEVENTMAX     (10+1)    //1画面の最大登録ボタン数
#define XTEXTBLOCKMAX    (2+1)    //1画面の最大登録テキストブロック数
#define EM_UI_MAX        2        //最大画面数
IXRVisualHostPtr  g_UiMainvhost;
IXRVisualHostPtr  g_UiBackvhost = NULL;
IXRApplicationPtr g_Mainapp;
int gPanelNo = 0;
static UINT g_nTimer;
HANDLE ghBackThreadHandle;
IXRButtonBasePtr m_btnControl[XBTNEVENTMAX];
IXRDelegate<XRMouseButtonEventArgs>* g_ButtonEventTBL[XBTNEVENTMAX];
IXRDelegate<XRMouseButtonEventArgs>* g_ButtonDownEventTBL[XBTNEVENTMAX];
IXRDelegate<XRMouseButtonEventArgs>* g_ButtonUpEventTBL[XBTNEVENTMAX];
IXRTextBlockPtr m_txtblockControl[XTEXTBLOCKMAX];
\\画面XAMLの定義です。1つ目にTOPPAGE、2つ目にNEXTPAGEを定義しています。
const WCHAR gc_PanelFileTBL[][64] = {
    L"\\TEST\\XAML\\TOPPAGE.xaml",
    L"\\TEST\\XAML\\NEXTPAGE.xaml",
};
\\各画面のボタンオブジェクト名の定義です。Microsoft Expression Blend 2で作成する際のオブジェクトのName定義と全く同じ名称である必要があります。
const WCHAR gc_ButtonNameTBL[EM_UI_MAX][XBTNEVENTMAX][32] = {
    {    L"BTN_NEXT", L"BTN_END", 0x00,    },
    {    L"BTN_BACK",0x00,    },
};
\\各画面のテキストブロックオブジェクト名の定義です。ボタンと同じく、Name定義と全く同じ名称である必要があります。
const WCHAR gc_TextBoxNameTBL[EM_UI_MAX][XTEXTBLOCKMAX][32] = {
    {    L"TXT_TITLE", 0x00,    },
    {    L"TXT_TITLE", L"TXT_DATE",0x00,    },
};


次にWinMainです。


int WINAPI WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR     lpCmdLine,
                     int       nCmdShow)
{
    HRESULT retcode;

    if (!XamlRuntimeInitialize())
        return -1;
 
    if (FAILED(retcode=GetXRApplicationInstance(&g_Mainapp)))
        return -1;
 
    if (FAILED(retcode=g_Mainapp->AddResourceModule((HINSTANCE)hInstance)))
        return -1;

    XRWindowCreateParams wp;
 
    ZeroMemory(&wp, sizeof(XRWindowCreateParams));
 
    wp.Style       = WS_BORDER;
    wp.pTitle      = L"TEST";
    wp.Left        = 0;
    wp.Top         = 0;
    wp.pHookProc = HookProc;

    XRXamlSource xamlsrc;

    //背景用スレッド起動
    ghBackThreadHandle = CreateThread(NULL, 0, ThreadBackGroundUI, NULL, 0,    NULL);

\\不可解な現象その1。通常のwindowsなら以下の方法でマウスカーソルを非表示に出来ますが、CE+Expression Blendでは何故か、画面遷移の瞬間だけカーソルが出てしまいます。これを避けるために、画面サイズギリギリの場所にマウスカーソルを飛ばして、見えなくしています。ただし、画面サイズよりも大きい場所を指定すると、指定が無効になってしまうので、サイズギリギリの800,480にする必要があります。このためよく見ると、右下に1ドットだけカーソルが見えていて、画面遷移時に出たり消えたりしています。ダサい対処法。
   while(ShowCursor(FALSE) >= 0);    //マウスカーソル消去 これだけでは画面遷移時にカーソルが出てしまう

    //マウスカーソルを画面外に飛ばしてしまうことで、非表示とする
    RECT recta;
    recta.top = recta.bottom = 800;
    recta.right = recta.left = 480;
    ClipCursor((const RECT *)&recta);

\\ここからが、繰り返し処理。1画面を表示-破棄を繰り返します。
    for( ; gPanelNo != -1; ) {
\\XAMLをメモリにロード
        xamlsrc.SetFile(gc_PanelFileTBL[gPanelNo]);


        if (FAILED(retcode=g_Mainapp->CreateHostFromXaml(&xamlsrc, &wp, &g_UiMainvhost))) {
            break;
        }
        IXRFrameworkElementPtr root;
        //ルートエレメントの作成
        if (FAILED(retcode=g_UiMainvhost->GetRootElement(&root))) {
            break;
        }

        int i;
        EventHandler handler;
        //ボタン登録
\\各画面に応じたボタンイベントを作成
        for( i = 0; gc_ButtonNameTBL[gPanelNo][i][0] != 0x00; i++) {

            //名前からオブジェクト取得
            if (FAILED(retcode=root->FindName(gc_ButtonNameTBL[gPanelNo][i], &m_btnControl[i])))
            {
                continue;
            }
            //クリックイベント登録
            if (FAILED(retcode=CreateDelegate(&handler,&EventHandler::OnClickEvent,    &g_ButtonEventTBL[i]))) {
                continue;
            }
            if (FAILED(retcode=m_btnControl[i]->AddMouseLeftButtonDownEventHandler(g_ButtonEventTBL[i])))
            {
                continue;
            }
            //キーダウンイベント登録
            if (FAILED(retcode=CreateDelegate(&handler,&EventHandler::KeyDownEvent,    &g_ButtonDownEventTBL[i]))) {
                continue;
            }
            if (FAILED(retcode=m_btnControl[i]->AddMouseLeftButtonDownEventHandler(g_ButtonDownEventTBL[i])))
            {
                continue;
            }
            //キーアップイベント登録
            if (FAILED(retcode=CreateDelegate(&handler,&EventHandler::KeyUpEvent,    &g_ButtonUpEventTBL[i]))) {
                continue;
            }
            if (FAILED(retcode=m_btnControl[i]->AddMouseLeftButtonUpEventHandler(g_ButtonUpEventTBL[i])))
            {
                continue;
            }
        }
   
\\各画面に応じたテキストブロックイベントを作成。これらを応用すれば、どんなオブジェクトのイベントでも、作れるようになると思います。
        //テキストブロック登録

        for( i = 0; gc_TextBoxNameTBL[gPanelNo][i][0] != 0x00; i++) {
            //名前からオブジェクト取得
            if (FAILED(retcode=root->FindName(gc_TextBoxNameTBL[gPanelNo][i], &m_txtblockControl[i])))
            {
                continue;
            }
        }
        SYSTEMTIME stTime;
        GetLocalTime(&stTime);
        //初期表示
\\ボタンの非表示、テキストブロックのテキスト更新のサンプルです。
        //次画面であれば日時を表示

        if(gPanelNo == 1) {
            WCHAR    wStrW[128];
   
            memset(wStrW,0x00,sizeof(wStrW));
            wsprintf(wStrW, L"%04d/%02d/%02d %02d:%02d:%02d", stTime.wYear, stTime.wMonth, stTime.wDay, stTime.wHour, stTime.wMinute, stTime.wSecond );
            ControlSetText(1,wStrW);
        }
        //TOP画面のエンドボタンを奇数秒の場合に非表示
        if(gPanelNo == 0 && (stTime.wSecond % 2)) {
            BYTE visible = 0;    //不可視
            ObjectInvisible(1,0,visible);
        }
        HWND hwnd = NULL; 
        UINT exitcode;
        g_UiMainvhost->GetContainerHWND(&hwnd);     
\\常に背景XAMLよりも前に出す必要があるため、前面表示指定します。
        //前面表示

        ShowWindow(hwnd, SW_SHOW);

        //画面表示
\\ここでようやく、XAMLが表示されます。close()が呼ばれるまで、ここに留まります。
        if (FAILED(retcode=g_UiMainvhost->StartDialog(&exitcode))) {

            break;
        }
    }
\\ここからは、アプリケーション終了処理
    //背景用スレッドの
終了
    g_UiBackvhost->EndDialog(0);
    CloseHandle(ghBackThreadHandle);


    //これを行うと異常終了する ->Release()でも同様
\\不可解な現象その2。お片づけしようとすると、例外で落ちます。ふしぎー。
//    g_UiMainvhost.Release();

    //生成しているのに、FALSEが返るのは何故?
\\不可解な現象その3。お片づけしようとすると、FALSEが返ります。他のスレッドを作成する直前までであれば、呼ぶとTRUEが返ります。スレッド作ったらあかんの?ふしぎー。
    if(XamlRuntimeUninitialize() == FALSE) {

    }
    //スレッドの終了を待つ
    //87(パラメータ異常)が返る理由が分からない
\\不可解な現象その4。タスクの終了を待つと、何故かエラーが返り、lastcodeは87(パラメータ異常)となります。引数は間違ってないはずなんですが、どんなに調べても分からんので無視。
    DWORD res = WaitForMultipleObjects(1, (const HANDLE *)ghBackThreadHandle, TRUE, INFINITE);

    if(res == (DWORD)-1) {
    }
 
    return 0;
}

次にイベント定義。

class EventHandler
{
public:
 
\\その名の通り、キーダウン、キーアップ、クリックイベント発生時にコールされる関数どもです
    HRESULT KeyDownEvent(IXRDependencyObject* source,XRMouseButtonEventArgs* args)

    {
        return S_OK;
    }
    HRESULT KeyUpEvent(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
    {
        return S_OK;
    }
    HRESULT OnClickEvent(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
    {
        BSTR pName;
        //クリックボタン名取得
        source->GetName(&pName);
        //ボタン名との比較
\\ボタン名称との比較で、どのボタンのイベントであるか判断しています。
        if (_tcscmp(L"BTN_NEXT", pName) == 0) {

            MainPanelChange(1);
        }
        else if (_tcscmp(L"BTN_BACK", pName) == 0) {
            MainPanelChange(0);
        }
        else if (_tcscmp(L"BTN_END", pName) == 0) {
            //終了
            gPanelNo = -1;
            g_UiMainvhost->EndDialog(0);
        }
        return S_OK;
    }
};

次にwindows messageのフック。

BOOL CALLBACK HookProc(VOID* pv, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* pRetVal)
{
    ULONG ulStyle;

    switch(msg)
    {
        case WM_CREATE:
            ulStyle = ::GetWindowLong(hwnd, GWL_STYLE);
            ulStyle = ulStyle & ~ulStyle;
            ::SetWindowLong(hwnd, GWL_STYLE, ulStyle);
\\タイマイベント周期をmsで指定。この例では100ms周期。
            g_nTimer = ::SetTimer(hwnd, XLOOPTIMER_ID, 100, NULL);

            //ジェスチャの登録
\\これを行うと、ジェスチャのメッセージも飛んでくるようになります。逆に言えば、ジェスチャを受けたくないときはこれを行わなければ、飛んできません。
            EnableGestures(hwnd, TGF_GID_ALL,TGF_SCOPE_PROCESS);

            //下の処理も実行させるために、break無し
\\周期タイマイベントです
        case WM_TIMER:

            if (wParam == XLOOPTIMER_ID) {
            }
            break;
\\特に用事が無くても、このイベントは拾っておく必要があります。画面遷移時に変更のある部分しか更新されなくなります。
        case WM_PAINT:    //DefWindowProcに渡すと、画面更新の仕方によっては、変更部分しか画面更新がされなくなる

            break;
        case WM_DESTROY:  // ウィンドウ破棄
            PostQuitMessage( 0 );
            break;
\\ジェスチャイベントは、これでくくられています。下のコメントにもあるとおり、かなりクセの有るイベントとなっています。スマホのようなサクサク動作を想定すると、かなりガッカリします。
        case WM_GESTURE:

            GESTUREINFO gi;
            gi.cbSize = sizeof(GESTUREINFO);
\\ここで、ジェスチャの種類とポイント(座標)が取得できます。
            if (GetGestureInfo(reinterpret_cast<HGESTUREINFO>(lParam), &gi))

            {
                //動作検証結果
                //フリックイベントは、かなり力強くフリックしないと来ない
                //軽いフリックの場合、イベントが来たとしても、なぜか終了ポイントが開始と同じ
                //フリックイベントを拾うよりも、まず最初に必ず来るパンイベントを拾って、
                //そのポイントを追いかけたほうが、結果的に反応が良くなる。
                //ただしこの場合、画面上をゆっくり時間をかけて指を動かしても、フリック扱いになってしまう。
                //これを避けたいのなら、開始から終了までの時間を取得し、一定時間以上かかっていれば無視するなどの小細工が必要。ああめんどくさい。
                switch(wParam){
                    case GID_DOUBLESELECT:    //ダブルタップ
                        break;
                    case GID_HOLD:            //ホールド
                        break;
                    case GID_PAN:            //パン
                        break;
                    case GID_SELECT:        //タップ
                        break;
                    case GID_BEGIN:            //ジェスチャ開始
                        break;
                    case GID_SCROLL:        //フリック
                        break;
                    case GID_END:            //ジェスチャ終了
                        break;
                }
            }
            //HGESTUREINFOの開放
            CloseGestureInfoHandle((HGESTUREINFO)lParam);
            break;
\\Expression Blend 2は綺麗な画面と引き換えに、メモリやCPUをバカ食いします。イベントのうち、アプリめがけて来ている情報は、不要でも受け止めておいたほうがいいみたいです。
            //このアプリで止めてしまって良い情報は、負荷軽減のために止めておく

            //この程度の負荷が、わりと馬鹿にならない。
        case WM_SETCURSOR:
            break;
        case WM_LBUTTONUP:
            break;
        case WM_LBUTTONDOWN:
            break;
        case WM_MOUSEMOVE:
            break;
        default:
            return DefWindowProc( hwnd, msg, wParam, lParam );
    }
    return 0;
}

次に背景画像用スレッド。

DWORD WINAPI ThreadBackGroundUI(LPVOID arg)
{
    XRXamlSource xamlsrc;
    HRESULT retcode;

    XRWindowCreateParams wp;
 
    ZeroMemory(&wp, sizeof(XRWindowCreateParams));
 
    wp.Style       = WS_BORDER;
    wp.pTitle      = L"BACKGROUND";
    wp.Left        = 0;
    wp.Top         = 0;

    xamlsrc.SetFile(_T("\\TEST\\XAML\\BackGround.xaml"));
    //Host XAMLの作成
    if (FAILED(retcode=g_Mainapp->CreateHostFromXaml(&xamlsrc, &wp, &g_UiBackvhost))) {
        return -1;
    }
     
    IXRFrameworkElementPtr root;
     
    //ルートエレメントの作成
    if (FAILED(retcode=g_UiBackvhost->GetRootElement(&root))) {
        return -1;
    }
     
    HWND hwnd = NULL; 
    g_UiBackvhost->GetContainerHWND(&hwnd);     
    /* 前面表示しない */
    ShowWindow(hwnd, SW_SHOWNA);

    UINT exitcode;
     
    if (FAILED(retcode=g_UiBackvhost->StartDialog(&exitcode))) {
    }

    return 0;
}

次に画面遷移時に必要な処理です。

void MainPanelChange(int no)
{
\\不可解な現象その5。画面遷移時に、元画面のコントロールを開放する必要がありますが、開放時に稀に例外が出ます。なのでtry-catchしています。よく分りませんが、いつの間にか勝手に開放されている事があるみたいです。まだガーベジコレクトなんて無いはずですしね。ふしぎー。
    //画面を閉じた際に、勝手に開放されている事があり、その時は例外になるのでtry-catchで無視する

    for( int i = 0; i < XBTNEVENTMAX; i++) {
        if(m_btnControl[i] != 0x00) {
            try    {    m_btnControl[i].Release(); } catch(...) { }
        }
    }
    for( int i = 0; i < XTEXTBLOCKMAX; i++) {
        if(m_txtblockControl[i] != 0x00) {
            try    {    m_txtblockControl[i].Release(); } catch(...) { }
        }
    }
    gPanelNo = no;
    //今の画面から抜けさせる
\\これを実行する事で、メインのスレッドはStartDialog()から抜けてきます。
    g_UiMainvhost->EndDialog(0);

}


最後にサブ関数。
渡されたオブジェクトの操作をします。

void ObjectInvisible(int idx, BYTE type, BYTE visible)
{
\\表示、非表示を切り替えます
    if(type == 0) {

        if(m_btnControl[idx] != NULL) {
            m_btnControl[idx]->SetVisibility((XRVisibility)!visible);
        }
    }
    else if(type == 1) {
        if(m_txtblockControl[idx] != NULL) {
            m_txtblockControl[idx]->SetVisibility((XRVisibility)!visible);
        }
    }
}
void ControlSetText(int idx, const WCHAR *text)
{
\\テキストブロックのテキストを更新
    if(m_txtblockControl[idx] != NULL) {

        m_txtblockControl[idx]->SetText(text);
    }
}

最低限はこんな感じです。
迷えるIT戦士たちの魂に、救いのあらんことを。

拍手


2015/02/11 12:15 | Comments(0) | 仕事
Microsoft Expression Blend 2とVC++で作る、windows CE 6.0アプリケーション その1
はい。たまには技術者らしい記事も書きたいと思います。

組み込み技術者はわりと、古い開発環境でのソフト作成を余儀なくされる事があります。
システム全体を入れ替えるのはお金がかかるから、他はそのままで、ソフトだけを新しくしたいという要求にこたえる際なんかに、よくそーなります。
全部新しくしてくれたほうが、当然楽なんですがね。最新の環境なら当然ある、便利で愉快な機能が無い時代の作り方をしなければならんので、わりと、いや、物凄く大変です。

windows XPのサポートが終了して久しいですが、XPなんてまだまだ新しいほうです。
JRではwindows2000が未だに現役(この間BSoDになってるの見た)ですし、どこぞの役所では、windows NT4.0が現役でした。

そして取り出したりますはwindows CE。
主に組み込み用途の、極小windowsという扱いのOS。かつてのカーナビなんかは、ほとんどこれで動いていました。
しかし時代は変わり、小型機は全てアンドロイドに代表されるフリーOSが使われるようになり、もともとニッチだったCEは、ますます表舞台に出てこなくなりました。
開発サイドから言わせていただくと、CEは本当に本当に使いづらく、不具合と紙一重の癖がいっぱいあり、超使えない子でした。
もう二度と関わりたくないので、このまま息を引き取っていただければ、俺としては大変ありがたいと内心思っていたのですが。

ソフト技術者は、開発環境が使えなかろうが、古かろうが、お客さんが求めれば使わざるを得ません。
そうして今回、「Microsoft Expression Blend 2(Silverlight for Windows Embedded)」にて画面を作成し、「windows CE 6.0」上で動作するVC++アプリケーション(win32)を開発する羽目になった技術者のために、俺が作り方の基本を記したいと思います。自分の覚書の意味もこめて。

あちこちに情報は転がっているんですが、いかんせんみんなごく一部だったり、エラーについては端折られていたりして、肝心の情報が無かったりします。
散々苦労してようやくそれっぽいものができるようになりましたので、古参システムに立ち向かい、産みの苦しみを味わう仲間たちへ、少しでも負担が軽減する事を祈って。

コード紹介は次回以降にして、それまでに必要な情報はこつら。

<概要
Windows Embedded CEアプリケーション開発手法 
Silverlight for Windows Embeddedの実装方法
上記2つで、「プロジェクトの作成→ボタンが押されたらアニメーションさせる、またはアプリ終了」という、必要最小限の知識は得られるかと思います。

<windows7へのvisual studio 2005のインストール
Visual Studio 2005をWidows 7にインストールしようとしてみた
Visual Studio 2005 はWindows7 でも(一応)サポートされる
インストール関連の情報はこのあたりに。

<コーディング文献(英語)
Microsoft Silverlight under Windows CE 6.0 R3
Programming Microsoft Silverlight for Windows Embedded Using .NET(ワポ文献)
特に重要なサンプル紹介が、P35あたりにあります。

<フォントの問題について
CEの環境にもよるみたいですが、XAMLの日本語表示が文字化けすることがあります。
フォントは、Windowsフォルダに存在します(cour.ttf,Symbol.ttf,tahoma.ttf,times.ttf,wingdingなど)。その中で、日本語フォントは、"msgothic.ac3"になります。

色々試した結果、Windowsフォルダにmsgothic.ttcを保存し、以下のレジストリ「HKEY_LOCAL_MACHINE\Software\Microsoft\FontLink\SystemLink」の "Tahoma"のフォント名を「msgothic.ac3」から「msgothic.ttc」へ拡張子を変更したところ、Silverlight for Windows Embeddedでも日本語が表示されるようになりました。

次回から、実際のVCソースやXAMLについて、触れていきます。

拍手


2015/02/10 18:54 | Comments(0) | 仕事
ITものづくりの現場で起きていること
現在、電化製品開発現場で起きている事を、お伝えします。

電化製品というのは、ハードとソフトが組み合わされて、動いています。
例えばジュースの自動販売機。
お金を金庫に入れたり、ジュースを取り立ち口に出すのはハード(機械)の仕事です。
ジュースのボタンを押された時に、入金額とジュースの金額を比較して、ジュースを出すか出さないかを決めるのは、ソフト(プログラム)の仕事です。
機械仕掛けがハード、考えるのがソフト、とも言えます。

こうして、ハードとソフトが仲良く共同作業することで、電化製品は正しく動きます。
(ハードとソフトの担当者同士が、必ずしも仲良しとは言ってない)

一昔前は、基本的にハードに重点が置かれ、ソフトは補助みたいな役割でした。
例えば、昔の車。
ギアを手作業で変え、タイヤに直結された重いハンドルを動かし、窓ガラスは手をくるくる回して開く。人間の力を、そのまま機械に伝えることで、動いています。
これらはほぼ、ハードのみで行える機能です。

かたや、今の車。
ギアは状況に応じて勝手に変化し、ハンドルは指先一つで回せるほど軽く、窓ガラスはスイッチひとつで開閉。他にも、カーナビやリモコンドア、自動操縦や衝突回避なんてものまでありますね。これらは、高度なソフト無しには絶対に不可能な機能ばかりです。まぁもちろん、モノとしてハードも絶対必要なんですがね。

このように、現在ではソフトの重要度はますます上がり、ますます複雑化していきます。

はい。ここまでダラダラ書いたことをまとめると
「昔に比べてソフトは大規模になり、複雑になりましたとさ」
となります。めでたしめでたし。

なのに。

なのに、やでしかし。

近年。
ソフトにかけられるお金や、開発期間は、どんどん短くなっています。
お客さんサイドから見たら、当然安いほうが良いし、早く手元に届く方が良いに決まっています。だからより早く、より安く、そして品質も良い(と思われる)会社を選ぶ事になります。このため、世にあるたくさんの会社たちは、無理をしてでも安く、早くすることを余儀なくされます。でなければ、仕事がもらえませんからね。
もはや、誰が一番安くて早いと言い出すかの、業界全体でのチキンレースの様相を呈してます。
ここ数年ではそのチキンレースに、日本だけでなく中国やベトナムなんてーのも加わってきて、ますます競争は激化。壁に激突しちゃう人たちが続出してもーてます。

そのしわ寄せはモロ、現場のぺーぺーである僕たち私たちに圧し掛かってきます。
安く作れ!
早く作れ!
でも品質は落とすな!
といったムリゲーが、ずーっと続いています。

その結果。
・これ作るのに何時間かかる?と聞かれて、素直に回答すると「何でそんなに時間がかかるんだ!○時間でやれ!」というコントに付き合わされる
・スケジュールどおりにこなしてても「前倒しで作業しろ!」と強制的に残業(タダ働き)させられる
・確認作業の時間を削った結果、出荷後に大炎上。それにかかる修正作業は全て残業(タダ働き)

もうね。こういうの止めませんか本当。
本当に底までの過剰な品質やサービスを、みんな求めてないと思うんですよね。
運送業とか、多分もっとシャレならない現状だと思うんですよ。頼んだものが次の日に届くとか、明らかにやりすぎでしょ。

こんなに必死に仕事をしても、結果的に市場で大爆発して、お客さんには迷惑がかかり、会社の名も落ち、不具合対応で経費がかかり、利益はみるみる目減り。
見事なLOSE-LOSEの関係。

これはあかんて。病むて。心を。
これからもIT業界は、「心を病む人が多い業界」上位を、守り続ける事を確信します!

拍手


2015/01/26 19:07 | Comments(0) | 仕事
それ以外でお金を稼ぐ ネット広告編
※広告の位置説明は、PCで閲覧した場合のもので、かつ当時のものです。現在はほとんど撤去しています。

前回、ポーカーで大金(1.2ドル。あの後もう1回上位に留まれて1.5ドル増えた。)を掴む事に成功した俺は、次なる野望へとコマを進めました。
こんどはネット広告です。
このブログの右側に、ウザい広告が6つ並んでいるかと思いますが、これがクリックされたり、広告先でお買い物をしてもらえると、俺に収益があります。クリックは、1人1日1回のみ有効。俺がクリックしてもOKとのことなので、この一ヶ月、気がついたらクリックするようにしてました。

そして、広告設置から一ヶ月が過ぎ、集計を確認してみました。

右に並んだ広告の上の3つが、A8.netという、ネット広告のサイトからの提供。
クリックで1~2円。広告先サイトの申し込みで、キックバックがあるというもの。
ちなみに、ブログ更新と同時に、広告の内容をランダムに入れ替えてます。入れ替えは手作業が面倒なので、それ専用のプログラムを作って、半自動化しました。

以下、広告を一ヶ月張った結果です。

83クリック。120えん。
お、おおう。俺しかクリックしていないと思ったけど、もしかして協力者がいてくれたりする?
愛してます。誰だか知らないけど。

次は、この忍者ブログの提供広告。
6つの広告のうち、一番下と、そのひとつ上のものの、合計2つです。
このブログは無料なので、強制的に広告が出てしまいます。(一番下)
それに加えて、閲覧回数に応じて収益がある、というものが貼ってあります。(そのひとつ上)
22円。ザ・小商い!
こちらのクリックは、全部俺かもしれません。
流石の協力者も、こんな下の広告までクリックする手間は避けたようです。それでも感謝。

最後にグーグルさんのアドセンス。6つのうち、下から3番目の広告です。
グーグルさんだけは、貼り付けるサイトに審査があります。ある程度の記事の数と歴史、公序良俗、閲覧者数が必要らしいです。グーグル様が俺のごときブログを読んでくれているのかと、審査の期間中はちょっとドキドキしてました。まぁグーグル様のことだから、自動解析かもしれませんが。ついでに利用規約に「自分で踏むのは絶対に許しません」とか書いてありました。これといい審査があることといい、他の広告に比べて厳格な雰囲気。
自分で踏んだらどうなるのかは知りません。だから動作確認すら出来ていません。おそろしググル。
286円!
どういうカウントでの金額算出方法なのかは不明ですが、他の二つに比べて随分と太っ腹!

全広告の合計収益が、428円。これがあての月収ですね。
まぁ、一定期間に一定額まで達しないと、どこかで期限切れになってゼロになってしまうらしいので、結局1円も手に入らない事になりそうですがー。

ちなみに、通称アフィと呼ばれる、こういったネット広告でお金を稼ぐ人のうち、99%は年間1万円未満の収益なんだそうです。
これで俺も、99%の仲間入りです♪

拍手


2014/11/25 21:34 | Comments(0) | 仕事

<<前のページ | HOME | 次のページ>>
忍者ブログ[PR]