2005 6 7 8 9 10 11 12
2006 1 2 3 4 5 6 7 8 9 10 11 12
2007 1 2 3 4 5 6 7 8 9 10 11 12
2008 1 2 3 4 5 6 7 8 9 10 11 12
2009 1 2 3 4 5 6 7 8 9 10 11 12
2010 1 2 3 4 5 6 7 8 9 10 11 12
2011 1 2 3 4 5 6 7 8 9 10 11 12
2012 1 2 3 4 5 6 7 8 9 10 11 12
2013 1 2 3 4 5 6 7 8 9 10 11 12
2014 1 2 3 4 5 6 7 8 9 10 11 12
2015 1 2 3 4 5 6 7 8 9 10 11 12
2016 1 2 3 4 5 6 7 8 9 10 11 12
2017 1 2 3 4 5 6 7 8 9 10

ホーム

2009年06月30日

まぁ、今風の言い方をするなら、アニマルデベロップメント
といった感じか。野生と理性の折り合いが開発成功の鍵を
握るといったところ。野生をすべて開放すれば混沌が待ち
受けているし、かといって角をすべて矯めれば力がなくなる。

本家Permlink


2009年06月29日

http://ja.wikipedia.org/wiki/%E5%8D%B1%E9%99%BA%E4%BA%88%E7%9F%A5%E8%A8%93%E7%B7%B4

ソフトウェア開発で労働災害やヒヤリハットといった
ものは起きにくくはある (過労死などを別にすれば)。

しかし、安全に働くということは、労働者すべてにとって
必要なことであり、心がけるべきことである。そして、
安全な仕事の進め方というものは、ソフトウェア開発にも
役立つのである。

ソフトウェアの不具合は、いってみれば災害のような
ものである。不具合も災害も、予知予防、真因追求、
恒久対策が大切である。

本家Permlink


2009年06月24日

予測できないからこそ不具合は生まれるんだけど。
でも、予測できないからってあきらめるわけには
いかないよね。

結局、『3つの「り」』、これしかないんだよね。

* 気配り
* 目配り
* 思いやり

ユーザへの「3つのり」がなければ、不具合は
減らない。

FromフィールドとToフィールドで、Fromのほうに
大きな値が入ったらどうなるの?

半角文字と全角文字の間が詰まってて判読しにくい。

こういう気配りや目配りは、結局は、ユーザへの
思いやりということになる。

--

最近、「おもてなし」という言葉も流行っているけど、
「おもてなし」っていうのは、外向きの言葉で、だけど、
「思いやり」は外向きにも内向きにも使える。

あ、こないだも書いたけど、外っていうのは組織の外
っていう意味。

--

だから、4番でエースみたいな人がいること自体、
弱小であることの証なんだよね。そういうチーム
事情でどう上げていくかっていうことを考えなきゃ
いけない。弱者の戦略っていうのは、誰も教えて
くれないんだよ、フツーは。

本家Permlink


2009年06月19日

まぁ、何度も書いてることだけど。

自分らの立場をわかってない。自分たちが弱者だという
ことをわかってない。

自分たちが弱者だとわかってれば、その戦略も自ずと
決まってくる。

守り重視。バグを出さない。

1点をガムシャラに取りにいく。これは守り重視と矛盾
することもあるが、待っていても弱者には仕事は来ない。

力を合わせる。弱者なんだから当たり前。

さらにいえば、教育ということも視野に入ってくる。

本家Permlink


2009年06月18日

だから、結局、お客さん、最終的なエンドユーザのほうを
向いてないと、下請けが上に向かって意見をいうのは
難しくなる。自分たちだけ、あるいは元請けだけを満足
させることしか考えていないと、やっぱりいいものは
できない。

本家Permlink


2009年06月17日

政党作ったら駅前で拡声器使って布教活動できるってか。

せめて宗教法人からの政治献金には課税すべきだろう。

本家Permlink


2009年06月16日1

でも、4Sにしても、7つのムダにしても、それはそれで
大切なんだけど、一番大切なのは『3つの「り」』なんだろうね。

* 気くばり
* 目くばり
* 思いやり

結局のところ、商売というものは、お客さんやユーザの
ほうを向いてないといけないわけで。『3つの「り」』って
いうのは、組織内の、つまり、内向きの言葉として捉える
だけでなく、やっぱり外向きの言葉としても捉えておいた
ほうがいい。

本家Permlink


2009年06月16日

ぱねっす。まじぱねっす。

--

しかしなぁ、キヨシローだろ、秀行先生だろ、三沢だろ。
ほんと、時代の終わりすぐるよな。

--

『7つのムダ』なんていうのがあったのか。

* 作り過ぎのムダ
* 在庫のムダ
* 不良のムダ
* 加工のムダ
* 運搬のムダ
* 動作のムダ
* 手待ちのムダ

まぁ、詳しいことは平鍋さんが解説してるだろうから。

でも、わかりにくいよな。加工のムダとかは。加工の
ムダは、ソフトウェアでいうと、過剰仕様とか、過剰
ドキュメントとか、そういう感じだろうね。

在庫のムダ。ソフトウェアだと物理的な場所は取らない
から気になんないんだけど。でも、使われてないソフト
ウェアっていうのは在庫なわけで、その保守コストを
考えたら、やっぱり少ないほうがいいんだよね。

運搬のムダは、配備 (deployment) のムダってことに
なるのかな。

本家Permlink


2009年06月12日

#include "stdafx.h"
#include "Postem.h"

#include "MainFrm.h"
#include "PostemDoc.h"
#include "PostemEntry.h"
#include "PostemParser.h"
#include "PostemView.h"
#include "tkoutil.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

using namespace std;
using namespace tko;

CPostemApp theApp;

BEGIN_MESSAGE_MAP(CPostemApp, CWinApp)
    ON_COMMAND(ID_APP_ABOUT, &CPostemApp::OnAppAbout)
    ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
    ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
END_MESSAGE_MAP()

CPostemApp::CPostemApp() : postem(NULL)
{
    postem = new Postem();
}

BOOL
CPostemApp::InitInstance()
{
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinApp::InitInstance();

    if (!AfxOleInit()) {
        AfxMessageBox(IDP_OLE_INIT_FAILED);
        return FALSE;
    }
    AfxEnableControlContainer();
    SetRegistryKey(_T("Local AppWizard-Generated Applications"));
    LoadStdProfileSettings(4);
    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,
                                          RUNTIME_CLASS(CPostemDoc),
                                          RUNTIME_CLASS(CMainFrame),
                                          RUNTIME_CLASS(CPostemView));
    if (!pDocTemplate)
        return FALSE;
    AddDocTemplate(pDocTemplate);

    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);

    if (!ProcessShellCommand(cmdInfo))
        return FALSE;

    postem->doPostem();
    exit(0);
    return TRUE;
}

class CAboutDlg : public CDialog
{
public:
    enum { IDD = IDD_ABOUTBOX };

    CAboutDlg();

protected:
    virtual void DoDataExchange(CDataExchange* pDX);

protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void
CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()

void
CPostemApp::OnAppAbout()
{
    CAboutDlg aboutDlg;
    aboutDlg.DoModal();
}

void
Postem::doPostem()
{
    bool ret = parseEntries();
    if (!ret)
        return;
    recordOpenWindows();
    launchEntries();
}

bool
Postem::parseEntries()
{
    PostemParser parser(this);
    return parser.parseEntries(entries);
}

static BOOL CALLBACK
eachWindowForRecordOpenWindows(HWND hwnd, LPARAM postem)
{
    Postem* app = (Postem*)postem;
    return app->addOpenWindow(hwnd);
}

void
Postem::recordOpenWindows()
{
    EnumWindows(eachWindowForRecordOpenWindows, (LPARAM)this);
}

BOOL
Postem::addOpenWindow(HWND hwnd)
{
    openWindows.insert(hwnd);
    return TRUE;
}

void
Postem::launchEntries()
{
    for (size_t i = 0; i < entries.size(); ++i) {
        HWND hwnd = entries[i]->launch();
        if (!hwnd)
            continue;
        addOpenWindow(hwnd);
    }
}

bool
Postem::isOpenWindow(HWND hwnd)
{
    set<HWND>::iterator it = openWindows.find(hwnd);
    return it != openWindows.end();
}
#pragma once

#ifndef __AFXWIN_H__
    #error "include 'stdafx.h' before including this file for PCH"
#endif

#include "resource.h"

class PostemEntry;

class Postem {
private:
    std::set<HWND> openWindows;
    std::vector<PostemEntry*> entries;

public:
    virtual void doPostem();
    virtual BOOL addOpenWindow(HWND hwnd);
    virtual bool isOpenWindow(HWND hwnd);

private:
    virtual bool parseEntries();
    virtual void recordOpenWindows();
    virtual void launchEntries();
};

class CPostemApp : public CWinApp
{
private:
    Postem *postem;

public:
    CPostemApp();

public:
    virtual BOOL InitInstance();

    afx_msg void OnAppAbout();
    DECLARE_MESSAGE_MAP()
};

extern CPostemApp theApp;
#include "StdAfx.h"
#include "PostemEntry.h"

#include <Psapi.h>
#include "Postem.h"
#include "tkoutil.h"

using namespace tko;

PostemEntry::PostemEntry(Postem *postem, CString fileName, CString imageName,
                         CRect position)
    : postem(postem), fileName(fileName), imageName(imageName),
      position(position), newWindow(NULL)
{
}

PostemEntry::~PostemEntry()
{
}

HWND
PostemEntry::launch()
{
    bool ret = execute();
    if (!ret)
        return NULL;
    Sleep(3000);
    findNewWindow();
    if (!newWindow)
        return NULL;
    moveNewWindow();
    return newWindow;
}

bool
PostemEntry::execute()
{
    BOOL ret = FALSE;
    LPTSTR p = fileName.GetBuffer(1);
    {
        SHELLEXECUTEINFO info;
        ZeroMemory(&info, sizeof(info));
        info.cbSize = sizeof(info);
        info.fMask = SEE_MASK_NOCLOSEPROCESS;
        info.lpFile = fileName;
        info.nShow = SW_SHOW;
        ret = ShellExecuteEx(&info);
    }
    fileName.ReleaseBuffer();
    return ret != FALSE;
}

static BOOL CALLBACK
eachWindowForFindNewWindow(HWND hwnd, LPARAM postemEntry)
{
    return ((PostemEntry*)postemEntry)->setNewWindow(hwnd);
}

void
PostemEntry::findNewWindow()
{
    EnumWindows(eachWindowForFindNewWindow, (LPARAM)this);
}

BOOL
PostemEntry::setNewWindow(HWND hwnd)
{
    if (postem->isOpenWindow(hwnd))
        return TRUE;
    CString path = queryImageName(hwnd);
    CString base = getBasename(path);
    if (imageName != base)
        return TRUE;
    newWindow = hwnd;
    return FALSE;
}

void
PostemEntry::moveNewWindow()
{
    if (!newWindow)
        return;
    CRect rect;
    BOOL ret = GetWindowRect(newWindow, &rect);
    if (!ret)
        return;
    int w = (position.Width() > 0) ? position.Width() : rect.Width();
    int h = (position.Height() > 0) ? position.Height() : rect.Height();
    MoveWindow(newWindow, position.left, position.top, w, h, FALSE);
}
#pragma once

class Postem;

class PostemEntry
{
private:
    Postem *postem;
    CString fileName;
    CString imageName;
    CRect position;
    HWND newWindow;

public:
    PostemEntry(Postem *postem, CString fileName, CString imageName,
                CRect position);
    virtual ~PostemEntry();

    virtual HWND launch();
    virtual BOOL setNewWindow(HWND hwnd);

private:
    virtual bool execute();
    virtual void findNewWindow();
    virtual void moveNewWindow();
};
#include "stdafx.h"
#include "PostemParser.h"

#include "PostemEntry.h"
#include "tkoutil.h"

using namespace std;
using namespace tko;

bool
PostemParser::parseEntries(vector<PostemEntry*>& results)
{
    vector<CString> lines;
    CString file_name = getEntryFileName();
    bool ret = readLinesCString(file_name, lines);
    if (!ret)
        return false;
    vector<CString> entryLines;
    for (size_t i =0; i < lines.size(); ++i) {
        if (lines[i].IsEmpty() || lines[i][0] == L'#')
            continue;
        if (lines[i].Find(L"File:") == 0) {
            if (!entryLines.empty()) {
                parseEntry(entryLines, results);
                entryLines.clear();
            }
        }
        entryLines.push_back(lines[i]);
    }
    if (!entryLines.empty())
        parseEntry(entryLines, results);
    return true;
}

CString
PostemParser::getEntryFileName()
{
    return getImageDirectory() + L"\\PostemEntry.txt";
}

CString
PostemParser::getImageDirectory()
{
    CString path = queryCurrentImageName();
    return getDirname(path);
}

void
PostemParser::parseEntry(vector<CString>& entryLines,
                         vector<PostemEntry*>& results)
{
    CString fileName;
    CString imageName;
    CString position;
    for (size_t i = 0; i < entryLines.size(); ++i) {
        if (entryLines[i].Find(L"File:") == 0)
            fileName = parseValue(entryLines[i]);
        else if (entryLines[i].Find(L"Image:") == 0)
            imageName = parseValue(entryLines[i]);
        else if (entryLines[i].Find(L"Position:") == 0)
            position = parseValue(entryLines[i]);
    }
    CRect rect = positionToRect(position);
    PostemEntry* entry = new PostemEntry(postem, fileName, imageName, rect);
    results.push_back(entry);
}

CRect
PostemParser::positionToRect(CString& line)
{
    vector<CString> numbers;
    split(line, L",", numbers);
    for (size_t i = 0; i < numbers.size(); ++i) {
        numbers[i].TrimLeft();
        numbers[i].TrimRight();
    }
    int left = 0;
    int top = 0;
    int right = 0;
    int bottom = 0;
    wchar_t *endptr = NULL;
    if (numbers.size() >= 1) {
        left = (int)wcstol(numbers[0], &endptr, 10);
        right = left;
    }
    if (numbers.size() >= 2) {
        top = (int)wcstol(numbers[1], &endptr, 10);
        bottom = top;
    }
    if (numbers.size() >= 3)
        right = (int)wcstol(numbers[2], &endptr, 10);
    if (numbers.size() >= 4)
        bottom = (int)wcstol(numbers[3], &endptr, 10);
    return CRect(left, top, right, bottom);
}

CString
PostemParser::parseValue(CString& line)
{
    int index = line.Find(L':');
    if (index < 0)
        return L"";
    CString result = line.Right(line.GetLength() - index - 1);
    result.TrimLeft();
    result.TrimRight();
    return result;
}
#pragma once

class Postem;
class PostemEntry;

class PostemParser {
private:
    Postem* postem;

public:
    PostemParser(Postem* postem) : postem(postem) {}
    virtual ~PostemParser() {}

    virtual bool parseEntries(std::vector<PostemEntry*>& results);
    virtual CString getImageDirectory();
    virtual CString getEntryFileName();
    virtual void parseEntry(std::vector<CString>& entryLines, std::vector<PostemEntry*>& results);
    virtual CString parseValue(CString& line);
    virtual CRect positionToRect(CString& line);
};
#include <stdafx.h>
#include "tkoutil.h"

#include <Psapi.h>

using namespace std;

static void
queryProcessImageName(HANDLE hProc, CString& result)
{
    const DWORD size = 1024 * 4;
    wchar_t buf[size];
    ZeroMemory(buf, sizeof(buf));
    DWORD ret = GetModuleFileNameEx(hProc, NULL, buf, size);
    if (!ret) {
        ret = GetLastError();
        TRACE("%d\n", ret);
    }
    if (ret)
        result = buf;
}

CString
tko::queryImageName(HWND hwnd)
{
    DWORD idProc = 0;
    DWORD idThr = GetWindowThreadProcessId(hwnd, &idProc);
    if (idProc == 0)
        return L"";
    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, idProc);
    if (!hProc)
        return L"";
    CString result;
    queryProcessImageName(hProc, result);
    CloseHandle(hProc);
    return result;
}

CString
tko::queryCurrentImageName()
{
    HANDLE hProc = GetCurrentProcess();
    CString result;
    queryProcessImageName(hProc, result);
    return result;
}

CString
tko::getBasename(CString &path)
{
    int index = path.ReverseFind(L'\\');
    if (index < 0)
        return path;
    return path.Right(path.GetLength() - index - 1);
}

CString
tko::getDirname(CString &path)
{
    int index = path.ReverseFind(L'\\');
    if (index < 0)
        return path;
    return path.Left(index);
}

bool
tko::readLinesCString(CString filepath, vector<CString>& results)
{
    CStdioFile input;
    CFileException err;
    BOOL ret = input.Open(filepath, CFile::modeRead, &err);
    if (!ret) {
        if (err.m_cause == CFileException::fileNotFound)
            TRACE(L"fileNotFound\n");
        else if (err.m_cause == CFileException::badPath)
            TRACE(L"badPath\n");
        else
            TRACE(L"other\n");
        return false;
    }
    try {
        CString line;
        while (input.ReadString(line)) {
            results.push_back(line);
        }
        return true;
    } catch (CFileException&) {
        return false;
    }
}

void
tko::split(CString str, CString delim, vector<CString>& results)
{
    int from = 0;
    for (;;) {
        if (from >= str.GetLength())
            break;
        int found = str.Find(delim, from);
        if (found < 0) {
            CString substr = str.Mid(from);
            results.push_back(substr);
            return;
        }
        CString substr = str.Mid(from, found - from);
        results.push_back(substr);
        from += found + delim.GetLength();
    }
}
#pragma once

namespace tko {
    CString queryImageName(HWND hwnd);
    CString queryCurrentImageName();
    CString getBasename(CString &path);
    CString getDirname(CString &path);
    bool readLinesCString(CString filepath, std::vector<CString>& results);
    void split(CString str, CString delim, std::vector<CString>& results);
}

本家Permlink


2009年06月09日

  働く側の都合のみで考えれば、時給が変わらないなら
  ダラダラ働いたほうがトク。

なんていうのが多くの人に当てはまることなの?

自分は人生に「空白」を作りたくないんだよね。同じ
時間を過ごすなら、充実した時間を過ごしたい。

「仕事がつまらない」ということはあるかもしれない。
でも、それは人それぞれだから。コンビニのバイトを
楽しいと思ってる人がいたっておかしくないし、
つまらないからといってダラダラやればいいっていう
もんでもない。ダラダラやるとよけいつまんなくなる。

だから、一番の新人教育っていうのは、自分の仕事の
楽しさを伝えることなんだと思う。何度も書いてるけど、
この「楽しさ」っていうのは「厳しさ」も含んだ話で。

いや、ネタはなんだっていいんだよ。成功談でも、
失敗談でも、あーしたい、こーしたいでも。そういう
会話を通じて、新人が仕事について学んでいく。

そういう話ができないんだったら、それは自分が自分の
仕事を真剣に考えてないから。

--

たとえば、こないだのキヤノンの話。あのページ、
自分は新人に紹介したんですよ。別に自分は教育担当でも
なんでもないんだけど。で、「やっぱりさ、一人一人が
いいものを作りたいと思わなきゃダメなんだよね」って
いう話をした。

4Sの話もしてるよ。こういう話を、自分は非公式な
会話でやってるわけ。別に呑みにつれてくわけでもない。

結局、誰もがすぐにプロになるわけじゃない。プロとして
過ごす一日一日の積み重ねがプロを形作るわけで。
その一日一日を少しでも上積みさせるのが先輩の役割
なんだと思う。

本家Permlink


2009年06月07日

剣聖のピアス、ゲットォォォッ!

最後に残しておいたのがラージャンのランス。イチオー、
ランスが今の主武器なんだけど、もともとがガード
ランサーで、オートガードなしにラージャン倒したことが
なかったっていうヘタレなのに、この装備でどうしろと?
っていう感じ。

とりあえず村クエで訓練の練習したんだけど、どうにも
なんない感じ (笑)。かといって、アイテム集めてどう
こうするのもメンドイ。

というわけで、基本戦略としては:

* ブレス (雷球とビーム) のときしか攻撃しない。
* ブレスのとき以外は逃げ回る。
  * 逃げ回るときは、ラージャン戦の基本の時計回り。
  * かつ、正面と真後ろには立たない。
* ラージャンが怒ってるときは、できるだけ攻めない。
* 斬れ味落ちても、できるだけ研がない。
  * ブレスのときなら、はじかれても比較的安全。
  * 抜槍1発目ははじかれても、2発目ははじかれない 
    (はじかれるときもある)。

で、実戦。1番でペイントボールを取る。7番で遭遇して、
上記のように戦闘。ラージャンが3番に移ったのを見て、
7番で毒ナイフ採集。3番で、ラージャンがギアノス掃除
するのを眺めながら、毒ナイフを投げておく。で、6番に
移動して終わり。もちろん、3番でも6番でも、上記の
ように戦う。

時間は14:30で、時間がかかってるほうだけど、まぁ、
これで剣聖のピアス取れたんだからゼータクはいって
らんない。

--

上手い人の動画を見ると、ラージャンのデンプシーを
華麗によけたり、デンプシーのあとを追いかけて攻めたり
してるけど、自分にはムリ (笑)。

『できるだけ研がない』っていうのは、自分にとって
1つのポイントだったんだけど、そんなに効果的じゃ
ないかも。でも、研ぐとしたらエリア移動しなきゃ
いけなくって、それがプレッシャーになって死ぬ、って
いうのはモンハンではよくあること (笑)。

本家Permlink


2009年06月05日1


本家Permlink


2009年06月05日

しかし、殺人はOKで、強姦はダメって。
毛唐の考えることはわからんの〜。

そんなもんに振り回される業界団体もカスだけどな。

本家Permlink


2009年06月03日

しつこいようだけど、「設計なんかやらなくっていい」
っていってるわけじゃないよ。

コードを書きはじめる前に準備することは大切。仕様や
実装での落とし穴がないか検討したり、どこをいじって、
どうなったらストーリーが終わったといえるのかとかを
検討したり。

そういう準備を表す言葉は、自分は知らないんだけど、
世間で設計フェーズと呼ぶものが近いんだろうね。

--

デバッガ、あるいはステッパというのは、不具合の
原因を教えてくれるけど、直し方までは教えてくれない
んだよね。

で、直し方っていうのはピンキリなんだよね。

で、デバッガで注意しないといけないのが、デバッガで
追ってるパスだけ見て直そうとすること。そういうのを
自分は「パッチ」とか「ツギハギ」とか呼んでるんだけど。

直すんなら、根本的に直す。

だから、デバッガで原因がわかったとしても、それで
原因追求が終わったわけじゃない。なぜそういうバグが
生まれたか、それを防ぐにはどうすればいいかという
ことにまで踏み込まないといけない。

そこまで踏み込むと、最終的な結論は「みんなで注意
しましょう」っていうことになりがちなんだけど。でも、
それはそれでいいんだよ。人間がやってることなんだから。

もちろん、設計で解決できるのが一番いい。でも、
そういうbig paybackっていうのはなかなか見つかる
もんじゃない。

本家Permlink


2009年06月02日

当たり前のことだし、何度も書いてる話なんだけど。

DRYは、未来を予測することとは違いますよ。

『ここは重複しそうだから1つにまとめておくか』とか。
そういうのはDRYとはそれほど関係ないでしょう。

むしろ、DRYというのを、発見的な態度と捉えたい。

『このコードを入れると、あっちと重複するな』という
発見。それは未来の予測ではなく、これからやろうと
していることに対する指針であり、発見でしょう。

DRYは、コードにだけに限らず、活動すべてに適用
できるもの。それは、DRYが発見だからでしょう。
悪い習慣なんかはDRYの対象の最たるもの。そういう
悪い習慣を見つける、気づくことが大切。

--

ああ、ちょっとわかりにくい書き方かな。

DRYっていうのは、過去と現在の関係で、現在と未来の
関係じゃないっていうこと。そういう意味で、非常に
pragmaticなわけです。未来を夢見てるわけじゃなく、
過去と現在の自分に向き合うっていう。

--

リファクタリングなんかにしても別の見方がありますよね。

設計に時間をかけるのは、失敗するのが恐いから。
なら、失敗を恐れなければ、設計に時間をかけなくたって
いい。

もちろん、匹夫の勇じゃダメで、リファクタリングの他にも、
ユニット・テスト、短いイテレーション、バージョン管理と
いったバックアップは必要ですけど。

そういうわけで、リファクタリングというのを
失敗を恐れない態度という捉え方もできるわけです。

過ちは誰でも犯す。でも、過ちは償えばいい。それが
リファクタリングというわけです。

--

いやぁ、これまでずーっと『ひきふ』と読んでました (笑)。

--

マイルド風味 (笑)。

本家Permlink


2009年06月01日

なんか、最近、説教臭いことしか書いてないよな。

まぁ、「他人事」にしちゃうのは、やっぱダメって
ことなんだよな。

かなり前のテーマだけど、巻き込み、巻き込まれる
っていうのは、結局は他人事にしないってこと
なんだから。

本家Permlink


Copyright © 1905 tko at jitu.org

バカが征く on Rails