OO编程实践之“同步文件夹”——实现(1)

标题写的是设计,其实这里应该是写测试。刚才开始很难写出测试来,因为传统编程思维的影响。如果是以前,这段代码也许很快就能写出个能用的版本。但现在我需要提高的我代码质量,不能永远停留在那个脚步。

根据前面的需求,首先想到的是,我如何判断source中的文件比dest中的新。噢,我们只需比较最后的修改时间就行了。

于是我写了关于修改时间的简单测试

    FileModifyTime source(std::time(NULL));

    FileModifyTime dest(std::time(NULL)-1000);

    CPPUNIT_ASSERT(source.isNewerThan(dest));

    CPPUNIT_ASSERT(!source.isNewerThan(source));

    CPPUNIT_ASSERT(!dest.isNewerThan(source));

  接着,我就写实现代码了。

    class FileModifyTime

    {

    public:

        FileModifyTime(time_t modifyTime) : itsModifyTime(modifyTime){}

        bool isNewerThan(const FileModifyTime& fi){ return itsModifyTime > fi.itsModifyTime;}

    private:

        time_t itsModifyTime;

    };

运行测试,通过了。太简单了,离我实际应用太远了。

对于第一次尝试TDD开发,我真不知道如何来写测试。考虑到测试一般而言,是给定一系列输入,然后查看输出是否与期望的相符合。在这个小程序中,我的输入是什么呢?我的输出又是什么呢?于是进入了漫长的思考中...

考虑这个程序的核心作用在source中找出已经改动的文件或者文件夹,那么测试的输入应该是各种文件信息的输入,输出是应该是是否需要更新的bool值,于是测试代码大概是这样:

Folder source("sourceFolder");

Folder dest("destFolder");

SynchronousSystem SS(&source,&dest);



CPPUNIT_ASSERT(SS.isNeedUpdate("File1"));

CPPUNIT_ASSERT(SS.isNeedUpdate("File2") == false);

这一步可能跨度有点大,因为我需要写2个类。

先写个空类能保持编译通过。

class Folder

{

public:

    Folder(const std::string& path){}

};
class Folder;

class SynchronousSystem

{

public:

    SynchronousSystem(Folder* source,Folder* dest){}

    bool isNeedUpdate(const std::string& filename)

    {

        return true;

    }

};

编译通过,但测试不通过。引文这里的我直接返回了true。为了使其通过测试,我修改了isNeedUpdate函数

    bool isNeedUpdate(const std::string& filename)

    {

        if(filename == "File1")

            return true;

        else

            return false;

    }

测试通过了,但isNeedUpdate的作用应该是判断文件修改时间,这个需要从source和dest中读取文件信息,于是继续编写测试代码:

    Folder source("sourceFolder");

    Folder dest("destFolder");



    CPPUNIT_ASSERT(source.getFileModifyTime("File1").isNewerThan(dest.getFileModifyTime("File1"));

    CPPUNIT_ASSERT(source.getFileModifyTime("File2").isNewerThan(dest.getFileModifyTime("File2") == false);

于是在Folder中需要增加成员函数getFileModifyTime

    FileModifyTime getFileModifyTime(const std::string& filename)

    {

        return FileModifyTime(std::time(NULL));

    }

为了使测试通过,我们需要在Folder中做一些工作。

class Folder

{

public:

    Folder(const std::string& path):itsPath(path){}

    FileModifyTime getFileModifyTime(const std::string& filename)

    {

        if (filename == "File1" && itsPath == "destFolder")

            return FileModifyTime(std::time(NULL)-1000);

        if (filename == "File2" && itsPath == "sourceFolder")

            return FileModifyTime(std::time(NULL)-1000);

        return FileModifyTime(std::time(NULL));

    }

private:

    std::string itsPath;

};

这样所有测试都通过了,再回过头来看SynchronousSystem,它的isNeedUpdate函数应该调用Folder看查询文件的修改时间,类SynchronousSystem修改为

class SynchronousSystem

{

public:

    SynchronousSystem(Folder* source,Folder* dest):itsSourceFolder(source),itsDestFolder(dest){}

    bool isNeedUpdate(const std::string& filename)

    {

        return itsSourceFolder->getFileModifyTime(filename).isNewerThan(itsDestFolder->getFileModifyTime(filename));

    }

private:

    Folder* itsSourceFolder;

    Folder* itsDestFolder;

};

一切很好,所有测试都通过了。

 

这样看来,一个功能1差不多完成了,考虑功能2的情况,如果dest中的文件不存在,那么isNeedUpdate中应该返回true。测试代码:

    Folder source("sourceFolder");

    Folder dest("destFolder");

    SynchronousSystem SS(&source,&dest);

    CPPUNIT_ASSERT(SS.isNeedUpdate("FileNotExist"));

测试不通过,我们更新isNeedUpdate函数

    bool isNeedUpdate(const std::string& filename)

    {

        if(!itsDestFolder->isExist(filename))

            return true;

        return itsSourceFolder->getFileModifyTime(filename).isNewerThan(itsDestFolder->getFileModifyTime(filename));

    }

类Folder中增加

    bool isExist(const std::string& filename)

    {

        if(filename == "FileNotExist")

            return false;

        else

            return true;

    }

测试通过了。

 

 

你可能感兴趣的:(文件夹)