zoukankan      html  css  js  c++  java
  • 我的2017年终总结(PF项目框架设计心得分享 1.0rc new)

    一晃眼又过去了一年,在这一年里尽管有许多不如意的事,却阻挡不了我前进的脚步。先用一句话来总结去年一年的状态,那就是“无休无止的忙碌”。而这样的忙碌状态对我来说是不可取的,因为匮乏的忙碌只能让头脑处于一种混乱而机械的状态中。在去年的时间就是工作上的烦心事困扰着我,虽有许多不错的主意终究因为忙碌而没有坚持,最后发现这的确是自己犯下的最大错误,因为后来不得不花更多时间来弥补。希望我的总结能够帮助到更多的朋友,从错误里汲取经验教训。

    总结

      所得:在工作中我能涉及到许多我以前认为十分复杂的领域,结果发现它们并没有想象中的困难。从这一点里我学习到一切看似困难的东西,只是我们自己胆怯造成的,在没有尝试之前就妄下结论是多么愚蠢啊。之前我在另一个城市里就是因为不相信自己,而丧失了许多的机会,如果有了这些机会我事业上恐怕不会如今天这般不顺。所以我希望所有在困难面前畏首畏尾的朋友,你们大胆一点放开你们的怀抱,去拥抱那即将靠近的梦想,虽然无法保证结果可能是一次惨痛的失败。可是你不趁着你还敢梦想的年纪,那么后面的生活你就只能活在遗憾当中了。

      所失:忙碌让我的神经麻木,甚至身体也有点力不从心,这就造成我在自己理想面前放慢了脚步。在此我也希望各位朋友要重视自己的健康,就算工作再怎么幸苦也不能因为拼命而轻视了它,别将生活的压力想象的太大。毕竟只有一个完好的人,才能体会到美好的生活,而工作只不过是为了生活而服务的。

    PF NEW

      虽然自己的确因为时间和身体的原因,在这个框架上花费的时间少了许多,可是我却没有停止我对它的期许,那便是做到真正的简单易用。为了做到这个我从2015年开始到现在几乎花了三年时间修改了两次结构,而PF框架现在的版本已经到了2.1,其基本的功能和性能得到了一定的保证。其中过程的艰辛,恐怕没有几个人能体会到。

      PF改动:plain server(2014)-> plain framework 1(2015-2016) -> plain framework 2(2017) -> plain framework new(2018)

      我只有一个简单的年份和版本变化来表示PF框架的蜕变过程,其实是一场非常不容易的变化。一开始这个还不能称之框架,那个时候我只是想简单的应付工作上的事情,为服务器打造一个稳定的底层库,即2014年的plain server。接着我发现只争对服务器来说根本无法满足我的要求,于是我重新修改了结构让它能够支持几乎所有的常见应有。接着说道现在比较稳定的版本PF2,它的改动最大的就是从语法上直接用到了C++11,使得框架本身能够支持更多新特性。然而PF2还是不能满足我,我将要进行各大一步的调整,在PF2的基础上我修改了框架的目录结构,让它看起来更加清晰易懂。

      PFnew的新特性:快速安装(框架、插件)、单元测试(框架、应用)、灵活封装(接口)

      对于现在的PFnew的快速安装目前只支持UNIX/LINUX的平台,当然后续会想办法支持WINDOWS系统。而单元测试则使用了gtest,目的是让一些问题更能及早的发现,这一点我也会征求更多的意见,因为我之前虽然接触过这个框架,只是一直没有使用,而对这个测试框架来说也不知道它的优缺点。至于灵活封装就是移除了核心接口中的许多依赖,我将这部分东西移到了插件中,现在的插件中就有如脚本插件(lua)、数据库插件(odbc)、网络协议插件(google protobuf),而这些插件可以根据应用的需要又框架本身提供接口来加载使用。而且如果有人用心的话,可能会在框架里发现一个有趣的模块,那就是数据库的语法封装部分(DB QUERY BUILDER),会支持大部分的数据库语法,这样使得我们想要随意切换不同数据库提供了良好的支持,当然这部分仍旧是尝试阶段。而且关于这个语法封装器,我参考了Laravel(PHP框架)的代码,有兴趣的同仁可以去了解一下。

      在这里贴一段代码来看看我们PFnew的数据库语法的支持以及单元测试示例:

    #include "gtest/gtest.h"
    #include "pf/engine/kernel.h"
    #include "pf/db/query/grammars/grammar.h"
    #include "pf/db/query/grammars/mysql_grammar.h"
    #include "pf/db/connection.h"
    #include "pf/db/query/builder.h"
    #include "pf/support/helpers.h"
    
    enum {
      kDBTypeODBC = 1,
    };
    
    using namespace pf_db::query;
    using namespace pf_basic::type;
    
    class DBQueryBuilder : public testing::Test {
    
     public:
       static void SetUpTestCase() {
         
         GLOBALS["log.print"] = false; //First forbid the log print.
    
         GLOBALS["default.db.open"] = true;
         GLOBALS["default.db.type"] = kDBTypeODBC;
         GLOBALS["default.db.name"] = "pf_test";
         GLOBALS["default.db.user"] = "root";
         GLOBALS["default.db.password"] = "mysql";
    
         engine_.add_libraryload("pf_plugin_odbc", {kDBTypeODBC});
    
         engine_.init();
    
         auto connection = new pf_db::Connection(engine_.get_db());
         unique_move(pf_db::Connection, connection, connection_);
         auto builder = new Builder(connection_.get(), nullptr);
         unique_move(Builder, builder, builder_);
         
         auto mysql_grammar = new grammars::MysqlGrammar();
         unique_move(grammars::Grammar, mysql_grammar, mysql_grammar_);
         auto mysql_builder = new Builder(connection_.get(), mysql_grammar_.get());
         unique_move(Builder, mysql_builder, mysql_builder_);
       }
    
       static void TearDownTestCase() {
         //std::cout << "TearDownTestCase" << std::endl;
       }
    
     public:
       virtual void SetUp() {
         builder_->clear();
         mysql_builder_->clear();
       }
       virtual void TearDown() {
       }
    
     protected:
       static pf_engine::Kernel engine_;
       static std::unique_ptr<pf_db::Connection> connection_;
       static std::unique_ptr<grammars::Grammar> mysql_grammar_;
       static std::unique_ptr<Builder> builder_;
       static std::unique_ptr<Builder> mysql_builder_;
    
    };
    
    pf_engine::Kernel DBQueryBuilder::engine_;
    std::unique_ptr<pf_db::Connection> DBQueryBuilder::connection_{nullptr};
    std::unique_ptr<Builder> DBQueryBuilder::builder_{nullptr};
    std::unique_ptr<Builder> DBQueryBuilder::mysql_builder_{nullptr};
    std::unique_ptr<grammars::Grammar> DBQueryBuilder::mysql_grammar_{nullptr};
    
    TEST_F(DBQueryBuilder, construct) {
      Builder object(nullptr, nullptr);
      pf_db::Connection connection(engine_.get_db());
      Builder builder_test1(&connection, nullptr);
      grammars::Grammar grammar;
      Builder builder_test2(&connection, &grammar);
    }
    
    TEST_F(DBQueryBuilder, testBasicSelect) {
      builder_->select({"*"}).from("users");
      ASSERT_STREQ("select * from "users"", builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testBasicSelectWithGetColumns) {
      builder_->from("users").get();
      ASSERT_TRUE(builder_->columns_.empty());
      
      ASSERT_STREQ("select * from "users"", builder_->to_sql().c_str());
      ASSERT_TRUE(builder_->columns_.empty());
    }
    
    TEST_F(DBQueryBuilder, testBasicSelectUseWritePdo) {
    
    }
    
    TEST_F(DBQueryBuilder, testBasicTableWrappingProtectsQuotationMarks) {
      builder_->select({"*"}).from("some"table");
      ASSERT_STREQ("select * from "some""table"", builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testAliasWrappingAsWholeConstant) {
      builder_->select({"x.y as foo.bar"}).from("baz");
      ASSERT_STREQ("select "x"."y" as "foo.bar" from "baz"", 
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testAliasWrappingWithSpacesInDatabaseName) {
      builder_->select({"w x.y.z as foo.bar"}).from("baz");
      ASSERT_STREQ("select "w x"."y"."z" as "foo.bar" from "baz"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testAddingSelects) {
      builder_->select({"foo"}).
                add_select({"bar"}).add_select({"baz", "boom"}).from("users");
      ASSERT_STREQ("select "foo", "bar", "baz", "boom" from "users"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testBasicSelectWithPrefix) {
      builder_->get_grammar()->set_table_prefix("prefix_");
      builder_->select({"*"}).from("users");
      ASSERT_STREQ("select * from "prefix_users"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testBasicSelectDistinct) {
      builder_->distinct().select({"foo", "bar"}).from("users");
      ASSERT_STREQ("select distinct "foo", "bar" from "users"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testBasicAlias) {
      builder_->select({"foo as bar"}).from("users");
      ASSERT_STREQ("select "foo" as "bar" from "users"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testAliasWithPrefix) {
      builder_->get_grammar()->set_table_prefix("prefix_");
      builder_->select({"*"}).from("users as people");
      ASSERT_STREQ("select * from "prefix_users" as "prefix_people"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testJoinAliasesWithPrefix) {
      builder_->get_grammar()->set_table_prefix("prefix_");
      builder_->select({"*"}).from("services").join(
          "translations AS t", "t.item_id", "=", "services.id");
       ASSERT_STREQ(
           "select * from "prefix_services" inner join "prefix_translations" 
    as "prefix_t" on "prefix_t"."item_id" = "prefix_services"."id"",
           builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testBasicTableWrapping) {
      builder_->select({"*"}).from("public.users");
      ASSERT_STREQ("select * from "public"."users"",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testWhenCallback) {
      auto callback = [](Builder *query, const variable_t &condition) {
        ASSERT_TRUE(condition.get<bool>());
        query->where("id", "=", 1);
      };
      builder_->select({"*"}).from("users").when(true, callback).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    
      builder_->clear();
      builder_->select({"*"}).from("users").when(false, callback).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "email" = ?",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testWhenCallbackWithReturn) {
    
    }
    
    void assertEquals(
        const variable_array_t &a, const variable_array_t &b, int32_t line = -1) {
      if (line != -1)
        std::cout << "assertEquals: " << line << std::endl;
      ASSERT_TRUE(a.size() == b.size());
      for (size_t i = 0; i < a.size(); ++i)
        ASSERT_STREQ(a[i].data.c_str(), b[i].data.c_str());
    }
    
    TEST_F(DBQueryBuilder, testWhenCallbackWithDefault) {
      auto callback = [](Builder *query, const variable_t &condition) {
        ASSERT_STREQ(condition.c_str(), "truthy");
        query->where("id", "=", 1);
      };
      auto def = [](Builder *query, const variable_t &condition) {
        ASSERT_TRUE(condition == 0);
        query->where("id", "=", 2);
      };
    
      builder_->select({"*"}).
                from("users").when("truthy", callback, def).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    
      assertEquals({1, "foo"}, builder_->get_bindings(), __LINE__);
    
      builder_->clear();
    
      builder_->select({"*"}).
                from("users").when(0, callback, def).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    
      assertEquals({2, "foo"}, builder_->get_bindings(), __LINE__);
    }
    
    TEST_F(DBQueryBuilder, testUnlessCallback) {
      auto callback = [](Builder *query, const variable_t &condition) {
        ASSERT_FALSE(condition.get<bool>());
        query->where("id", "=", 1);
      };
    
      builder_->select({"*"}).
                from("users").unless(false, callback).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    
    
      builder_->clear();
      builder_->select({"*"}).
                from("users").unless(true, callback).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "email" = ?",
                   builder_->to_sql().c_str());
    
    }
    
    TEST_F(DBQueryBuilder, testUnlessCallbackWithReturn) {
    
    }
    
    TEST_F(DBQueryBuilder, testUnlessCallbackWithDefault) {
      auto callback = [](Builder *query, const variable_t &condition) {
        ASSERT_TRUE(condition == 0);
        query->where("id", "=", 1);
      };
      auto def = [](Builder *query, const variable_t &condition) {
        ASSERT_STREQ(condition.c_str(), "truthy");
        query->where("id", "=", 2);
      };
    
      builder_->select({"*"}).
                from("users").unless(0, callback, def).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    
      assertEquals({1, "foo"}, builder_->get_bindings(), __LINE__);
    
      builder_->clear();
    
      builder_->select({"*"}).
                from("users").unless("truthy", callback, def).where("email", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    
      assertEquals({2, "foo"}, builder_->get_bindings(), __LINE__);
    }
    
    TEST_F(DBQueryBuilder, testTapCallback) {
      auto callback = [](Builder *query) {
        query->where("id", "=", 1);
      };
    
      builder_->select({"*"}).from("users").tap(callback).where("email", "foo"); 
      ASSERT_STREQ("select * from "users" where "id" = ? and "email" = ?",
                   builder_->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testBasicWheres) {
      builder_->select({"*"}).from("users").where("id", "=", 1);
      ASSERT_STREQ("select * from "users" where "id" = ?",
                   builder_->to_sql().c_str());
      assertEquals({1}, builder_->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testMySqlWrappingProtectsQuotationMarks) {
    /**
      builder_->select({"*"}).from("some`table");
      ASSERT_STREQ("select * from `some``table`",
                   builder_->to_sql().c_str());
    **/
    }
    
    TEST_F(DBQueryBuilder, testDateBasedWheresAcceptsTwoArguments) {
      auto builder = mysql_builder_.get();
      builder->select({"*"}).from("users").where_date("created_at", "1");
      ASSERT_STREQ("select * from `users` where date(`created_at`) = ?",
                   builder->to_sql().c_str());
    
      builder->clear();
      builder->select({"*"}).from("users").where_day("created_at", "1");
      ASSERT_STREQ("select * from `users` where day(`created_at`) = ?",
                   builder->to_sql().c_str());
    
      builder->clear();
      builder->select({"*"}).from("users").where_month("created_at", "1");
      ASSERT_STREQ("select * from `users` where month(`created_at`) = ?",
                   builder->to_sql().c_str());
    
      builder->clear();
      builder->select({"*"}).from("users").where_year("created_at", "1");
      ASSERT_STREQ("select * from `users` where year(`created_at`) = ?",
                   builder->to_sql().c_str());
    }
    
    TEST_F(DBQueryBuilder, testWhereDayMySql) {
      auto builder = mysql_builder_.get();
      builder->select({"*"}).from("users").where_day("created_at", "=", 1);
      ASSERT_STREQ("select * from `users` where day(`created_at`) = ?",
                   builder->to_sql().c_str());
      assertEquals({1}, builder->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testWhereMonthMySql) {
      auto builder = mysql_builder_.get();
      builder->select({"*"}).from("users").where_month("created_at", "=", 5);
      ASSERT_STREQ("select * from `users` where month(`created_at`) = ?",
                   builder->to_sql().c_str());
      assertEquals({5}, builder->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testWhereYearMySql) {
      auto builder = mysql_builder_.get();
      builder->select({"*"}).from("users").where_year("created_at", "=", 2018);
      ASSERT_STREQ("select * from `users` where year(`created_at`) = ?",
                   builder->to_sql().c_str());
      assertEquals({2018}, builder->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testWhereTimeMySql) {
      auto builder = mysql_builder_.get();
      builder->select({"*"}).from("users").where_time("created_at", "=", "22:00");
      ASSERT_STREQ("select * from `users` where time(`created_at`) = ?",
                   builder->to_sql().c_str());
      assertEquals({"22:00"}, builder->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testWhereDatePostgres) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereDayPostgres) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereMonthPostgres) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereYearPostgres) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereDaySqlite) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereMonthSqlite) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereYearSqlite) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereDaySqlServer) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereMonthSqlServer) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereYearSqlServer) {
    
    }
    
    TEST_F(DBQueryBuilder, testWhereBetweens) {
      builder_->select({"*"}).from("users").where_between("id", {1, 2});
      ASSERT_STREQ("select * from "users" where "id" between ? and ?",
                   builder_->to_sql().c_str());
      assertEquals({1, 2}, builder_->get_bindings());
    
      builder_->clear();
      builder_->select({"*"}).from("users").where_notbetween("id", {1, 2});
      ASSERT_STREQ("select * from "users" where "id" not between ? and ?",
                   builder_->to_sql().c_str());
      assertEquals({1, 2}, builder_->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testBasicOrWheres) {
      builder_->select({"*"}).
                from("users").where("id", "=", 1).or_where("email", "=", "foo");
      ASSERT_STREQ("select * from "users" where "id" = ? or "email" = ?",
                   builder_->to_sql().c_str());
      assertEquals({1, "foo"}, builder_->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testRawWheres) {
      builder_->select({"*"}).
                from("users").where_raw("id = ? or email = ?", {1, "foo"});
      ASSERT_STREQ("select * from "users" where id = ? or email = ?",
                   builder_->to_sql().c_str());
      assertEquals({1, "foo"}, builder_->get_bindings());
    }
    
    TEST_F(DBQueryBuilder, testRawOrWheres) {
      builder_->select({"*"}).
                from("users").where("id", "=", 1).or_where_raw("email = ?", {"foo"});
      ASSERT_STREQ("select * from "users" where "id" = ? or email = ?",
                   builder_->to_sql().c_str());
      assertEquals({1, "foo"}, builder_->get_bindings());
    }

      PFnew地址

      https://github.com/viticm/plain

  • 相关阅读:
    大型网站的数据库分割问题。
    大型网站的数据库分割问题。
    分布式集群的Session问题
    大型网站架构设计摘要
    大型网站的架构概要
    公司产品的优势
    java.util.concurrent 学习笔记(2) 线程池基础
    《Java 7 并发编程指南》学习概要 (6) Fork/Join
    《Java 7 并发编程指南》学习概要 (5) 线程池
    《Java 7 并发编程指南》学习概要 (4) 并发集合
  • 原文地址:https://www.cnblogs.com/lianyue/p/8470821.html
Copyright © 2011-2022 走看看