架构师 0 期第二周作业(命题作业)

发布于: 2020 年 06 月 17 日
架构师 0 期第二周作业(命题作业)

1.请描述什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?

在传统的开发思想中,软件应该存在分层,高层代码调用低层代码,高层依赖低层。而依赖倒置原则颠覆了这种传统的开发思维,高层不能依赖低层,而应该依赖抽象,不管是高层还是低层,都应该依赖于抽象,这样当低层代码剧烈变动的时候,上层代码的变动也不会太大,这是因为抽象的变化概率小。比如我说要明天要骑单车上班,万一明天下大雨,单车就骑不成了,如果我说明天要使用交通工具上班,那么即使下雨,也可以改乘公共汽车上班。交通工具比单车要更加的抽象,也更有包容性,更不容易改变。

依赖倒置原则另一个使用场景是软件架构方面,架构使用者的代码不要去调架构的东西,而是由架构来负责去调用户的代码,并且串起整个软件的运行流程。类似于我们开发后台服务器,我们只是负责编写前端每个请求对应的处理逻辑,而前端请求接收,线程的创建和执行,都全部由框架去完成。

依赖倒置原则之所以被称为好莱坞原则,是因为它与好莱坞运作机制有类似的地方。好莱坞的星探就好比是软件的架构,那些准明星们就好比架构使用者没编写的代码。不存在准明星主动去找星探进好莱坞当明星,而从来都是由好莱坞的那些星探们主动去物色有潜力的准明星。

2.请描述一个你熟悉的框架,是如何实现依赖倒置原则的。

Webrtc源码中很多地方都有使用依赖倒置的原则进行开发的地方,我们来看看其中的日志模块,是如何使用依赖倒置的

首先webrtc内部定义了一个日志的抽象类:

class LogSink {

 public:

  LogSink() {}

  virtual ~LogSink() {}

  virtual void OnLogMessage(const std::string& msg,

                            LoggingSeverity severity,

                            const char* tag);

  virtual void OnLogMessage(const std::string& message,

                            LoggingSeverity severity);

  virtual void OnLogMessage(const std::string& message) = 0;

};

这个抽象类里有三个虚函数OnLogMessage,这三个函数仅仅是参数不同而已,其目的都是为了日志的输出。

webrtc的使用者需要自己去实现这三个虚函数(其中有一个是必现实现得,剩下的两个可以不实现)

class MyLogStream : public rtc::LogSink {

public:

    MyLogStream();

    virtual ~MyLogStream();

    virtual void OnLogMessage(const std::string& message);

    void OpenLogFile();

    void CloseLogFile();

private:

    FILE* _fp = NULL;

    std::mutex mutex_;

    int currentFileId_;

};

#define MAX_SIZE 10485760

#define MAXFILEPATH_SIZE  512

#define MAXFILENAME_SIZE  64

MyLogStream::MyLogStream() : currentFileId_(0) {

    int n = 0;

    char fileName[MAXFILENAME_SIZE];

    char curPath[MAXFILEPATH_SIZE];

    char completeFile[MAXFILENAME_SIZE + MAX_FILEPATHSIZE];

    int minSize = INT_MAX;

    struct _stat info;

    _getcwd(curPath, sizeof(curPath));

    strcat(curPath, "\\Logs\\");

    while (n < 10)

    {

        strcpy(completeFile, curPath);

        sprintf(fileName, "webrtcnative%d.log", n);

        strcat_s(completeFile, fileName);

        int ret = _stat(completeFile, &info);

        if (ret != 0)

        {

            n++;

            continue;

        }

        if (minSize >= info.st_size)

        {

            minSize = info.st_size;

            currentFileId_ = n;

        }

        n++;

    }

    strcpy(completeFile, curPath);

    sprintf(fileName, "webrtcnative%d.log", currentFileId_);

    strcat_s(completeFile, fileName);

    fp = fsopen(completeFile, "a+", SHDENYNO);

}

MyLogStream::~MyLogStream() {

    if (_fp) {

        fclose(_fp);

        _fp = NULL;

    }

}

void MyLogStream::OpenLogFile()

{

    char fileName[MAXFILENAME_SIZE];

    char curPath[MAXFILEPATH_SIZE];

    char completeFile[MAXFILENAME_SIZE + MAX_FILEPATHSIZE];

    _getcwd(curPath, sizeof(curPath));

    strcat(curPath, "\\Logs\\");

    strcpy(completeFile, curPath);

    sprintf(fileName, "webrtcnative%d.log", currentFileId_);    

    strcat_s(completeFile, fileName);

    fp = fsopen(completeFile, "a+", SHDENYNO);

}

void MyLogStream::CloseLogFile()

{

    if (_fp) {

        fclose(_fp);

        _fp = NULL;

    }

}

void MyLogStream::OnLogMessage(const std::string& message) {

    if (!_fp) {

        return;

    }

    mutex_.lock();

    if (ftell(fp) > MAXSIZE) {

        fclose(_fp);

        _fp = NULL;

        currentFileId = (currentFileId + 1) % 10;

        char fileName[MAXFILENAME_SIZE];

        char curPath[MAXFILEPATH_SIZE];

        char completeFile[MAXFILENAME_SIZE + MAX_FILEPATHSIZE];

        sprintf(fileName, "webrtcnative%d.log", currentFileId_);

        _getcwd(curPath, sizeof(curPath));

        strcat(curPath, "\\Logs\\");

        strcpy(completeFile, curPath);

        strcat_s(completeFile, fileName);

        fp = fsopen(completeFile, "w+", SHDENYNO);

    }

    mutex_.unlock();

    SYSTEMTIME tmSys = { 0 };

    GetLocalTime(&tmSys);

    char str[50];

    sprintf(str,

        "%04d-%02d-%02d %02d:%02d:%02d.%03d",

        tmSys.wYear, tmSys.wMonth, tmSys.wDay,

        tmSys.wHour, tmSys.wMinute, tmSys.wSecond,

        tmSys.wMilliseconds);

    std::string msg = str + message;

    fwrite(msg.cstr(), 1, msg.length(), fp);

    fflush(_fp);

}

使用的时候,需要把这个类创建的对象注册到webrtc的框架代码中,这样webrtc框架就可以使用你的日志对象进行日志的输出了

3.请用接口隔离原则优化 Cache 类的设计,画出优化后的类图。

用户头像

何伟敏

关注

还未添加个人签名 2018.03.11 加入

还未添加个人简介

评论

发布
暂无评论
架构师 0 期第二周作业(命题作业)