Software Development Practises

课程设计答辩

崔利伟
哈尔滨工业大学

WHAT

做了什么?

  • 一个文件传输工具
  • 支持多种文件压缩算法
  • 支持网络传输
  • 拥有类 Unix 命令行交互

HOW

怎么做到的?

  • 一个比特流模块
  • 一个算法模块
  • 一个网络间传输模块
  • 一个Json 序列化/反序列模块
  • 一个交互模块
  • 一个定制的优先队列模块

WHY

为什么要这么做?

  • 将算法用于真正的工程
  • 体会模块化的思想
  • 重温OOP 设计

代码展示 CODE SHOW

First.算法模块

  namespace ca {
    class CompressAlgs {
    public:
        virtual void compress(std::istream&, bit::oBaseStream&) = 0;
        virtual void expand(bit::iBaseStream&, std::ostream&) = 0;
    };
    CompressAlgs &Huffman_algs();
    CompressAlgs &AdaptiveHuffman_algs();
}

Second.比特流模块

  class iBaseStream {
    public:
        iBaseStream():sum{1 << (SIZE - 2)}, cnt{0}, valid{true} {}
        virtual ~iBaseStream(){}
        iBaseStream(const iBaseStream &) = delete;
        iBaseStream(iBaseStream &&) = delete;
        iBaseStream& operator=(const iBaseStream &) = delete;

        operator bool() {return valid;}
        iBaseStream &read_bit(bool &);
        iBaseStream & read_byte(char&);

    protected:
        virtual void read_buffer() = 0;
        bool read_bit();
        char read_byte();

        std::bitset<SIZE> buffer;
        unsigned long sum;
        unsigned long cnt;
        bool valid;
    };

Third.网络模块

class NetService {
public:
    NetService(int cfd = -1):connfd{cfd} {}
    NetService(const NetService&) = delete;
    NetService &operator=(const NetService&) = delete;
    NetService(const std::string &hostname, int port):connfd{-1} {
        open_connfd(hostname, port);}

    ~NetService() {close(connfd);}

    ssize_t read_str(std::string &str) {
        str.clear(); rio_read(connfd, str); return str.length();}
    NetService& write_str(const std::string &str) {rio_write(connfd, str); return *this;}

private:
    int connfd;

    void open_connfd(const std::string &, int);
    void rio_write(int fd, const std::string& usrbuf);
    void rio_read(int fd, std::string &usrbuf);
};

Fourth. 定制优先队列

    template<typename T, 
        typename Con = std::vector<MobileAtomic<T>>,
        typename Cmp = std::less<typename Con::value_type>>
    class PriorityQueue {
    private:
        using read_lock = rbl::read_guard<rbl::RBLock<std::mutex>>;
        using write_lock = rbl::write_guard<rbl::RBLock<std::mutex>>;
        static const int BEG = 1;
    public:
        friend void swap(PriorityQueue &first, PriorityQueue &second) {
            using std::swap;
            // Hope that array and compare have defined their own move constructor
            swap(first.array, second.array);
            swap(first.compare, second.compare);
        }
        PriorityQueue(const Cmp& c = Cmp()):array{1}, compare{c} {}
        template <typename InputIt>
        PriorityQueue(InputIt first, InputIt last, const Cmp& c = Cmp())
            :PriorityQueue{c} {
            while (first != last) push(*first++);
        }
        ~PriorityQueue() {}
        PriorityQueue(const PriorityQueue &other):array{other.array}, compare{other.compare} {}
        PriorityQueue(PriorityQueue &&other):PriorityQueue{} {swap(*this, other);}
        PriorityQueue& operator=(PriorityQueue other) {swap(*this, other); return *this;}
        T top() {read_lock guard(protector); return array[BEG]; }
        int size() {read_lock guard(protector); return array.size() - BEG; }
        bool empty() {read_lock guard(protector); return !size(); }
        void push(const T& data);
        void pop();
    private:
        void up(size_t index);
        void down(size_t index);
        Con array; Cmp compare;
        rbl::RBLock<std::mutex> protector;
    };
}
#include "Queue.impl.hpp"

Fifth.交互

        bool compress = true;
        bool adaptive = true;
        Options options(argv[0], " - command line options");
        options.add_options() 
        ("c,compress", "Compress file")
        ("e,expand", "Expand compressed file")
        ("s,static", "Use static huffman coding")
        ("a,adaptive", "Use adaptive huffman coding")
        ("i,input", "Input file", value<string>())
        ("o,output", "Output file", value<string>()->default_value("Processed.out"))
        ("n,hostname", "hostname", value<string>())
        ("h,help", "Print help")
        ; 
        options.parse(argc, argv); 
        if (options.count("h")) {
            cout << options.help({""}) << endl; 
            exit(0);
        }

Thanks for looking :-)