架构之路--实战项目记录(二) 忘记数据库 开始抽象

简介: 对我而言,认识BLL层的作用,或者领域模型驱动的含义,最大的干扰来自数据库。我们很清楚的知道UI层的含义,也知道数据层是做什么的。但对于一个简单的(甚至是相当复杂的)系统而言,实在不知道除了对数据库进行增删改查以外,还能做些什么?发布一篇博客,不就是在数据库里插入一条记录么?点击一下推荐,不就是在数据库里做一个update么?为了避免数据库的干扰,这里,我们设定:不使用关系数据库做存储!请大家牢记,为了更清晰,更深刻的认识到这一点,我们再次明确,我们将使用最流行的NoSQL技术。
对我而言,认识BLL层的作用,或者领域模型驱动的含义,最大的干扰来自数据库。

我们很清楚的知道UI层的含义,也知道数据层是做什么的。但对于一个简单的(甚至是相当复杂的)系统而言,实在不知道除了对数据库进行增删改查以外,还能做些什么?发布一篇博客,不就是在数据库里插入一条记录么?点击一下推荐,不就是在数据库里做一个update么?

为了避免数据库的干扰,这里,我们设定:不使用关系数据库做存储!请大家牢记,为了更清晰,更深刻的认识到这一点,我们再次明确,我们将使用最流行的NoSQL技术。牛叉吧!兴奋吧?

打满了鸡血吧!

好的,设计的任务交给你了,小李同学。

接下来,你怎么办?哎呀,我对NoSQL还不熟呀(不熟?其实除了名字知道以外,其他什么都根本就不知道)。马上开始研究一下NoSQL,看看里面有没有什么库呀,表呀之类的,好像那里面用的是集合?

如果你这样走下去的话,就偏离了DDD的宗旨了(但也不能说你“错”了)。

我是这样做的。

问:这个系统要做什么?有哪些功能?

答:发布博客,博客可以评论。可以提问题,回答问题。当然,做这些事,都得注册登录……

好,根据以上信息,我们可以抽象出这几个对象。

这是一个良好的开端。再细致点,博客和问题,都必须有标题;而博客的评论和问题的答案,不需要标题;但不管是博客还是问题,评论还是回答,都会有一个作者,都要发布时都要记录下

发布的时间,甚至发布者的IP(基于中国人都知道的原因)。博客和问题,还要记录下浏览量……

到这里,你是不是嗅到了一种什么味道?“不管……还是……都……”,共同的东西!那么想到面向对象的三大特征,“继承”就呼之欲出了。所以我们通过抽象,得到了以下的对象。

View Code
     ///   <summary>
    
///  Article is abstract, means it's not a really entity
    
///   </summary>
     public  abstract  class Article : Entity< int>
    {
         #region Properties

         #region Content
         public  virtual  string Body {  getset; }
         #endregion

         #region Log
         ///   <summary>
        
///  Need not set manually in most scenarios
        
///   </summary>
         public  virtual  string PublishIP {  getset; }
         ///   <summary>
        
///  Need not set manually in most scenarios
        
///   </summary>
         public  virtual DateTime? LastModifiedTime {  getset; }
         #endregion

         #region Associates
         public  virtual User Author {  getset; }
         #endregion

         #endregion

         #region Public Methods

         public  virtual  void Publish()
        {
             #region set some default value

            setCreatedTime();
            setLastModifiedTime();
            setPublishIP();

             #endregion
        }

         #endregion

         #region Protect Methods

         protected  virtual  void setLastModifiedTime()
        {
             if (LastModifiedTime ==  null)
            {
                LastModifiedTime = DateTime.Now;
            }
        }

         protected  virtual  void setPublishIP()
        {
             if ( string.IsNullOrEmpty(PublishIP))
            {
                PublishIP = HttpContext.Current.Request.UserHostAddress;
            }
        }

         #endregion
    }


     ///   <summary>
    
///  represent article can be regarded as the main part of one page, e.g. Blog and Question
    
///   </summary>
     public  abstract  class MainArticle : Article
    {
         #region Properties

         #region Content
         public  virtual  string Title {  getset; }
         public  virtual  string Keywords {  getset; }
         #endregion        

         #region Credit
         public  virtual  int ViewCount {  getset; }
         #endregion

         #region Log
         #endregion

         #endregion

         #region Methods

         public  virtual  void View()
        {
            ViewCount++;
        }

         #endregion

    }

     public  class Blog : MainArticle
    {
         #region Properties

         #region Associates
         public  virtual CategoryOfBlog Category {  getset; }
         #endregion

         #region Content
         public  virtual  string BlogAbstract {  getset; }
         #endregion

         #endregion
    }


     public  class CommentOfBlog : AttachedArticle
    {
         #region Properties

         #region Associates
         public  virtual Blog ReferredBlog {  getset; }
         public  virtual CommentOfBlog ReferredComment {  getset; }       
         #endregion

         #endregion
    }

     public  abstract  class AttachedArticle : Article
    {

    }

     public  class Answer : AttachedArticle
    {
         #region Properties

         #region Associates
         public  virtual Question ReferredQuestion {  getset; }
         public  virtual Answer ReferredAnswer {  getset; }
         #endregion

         #endregion  
    }

这样做的好处,很明显的,就是减少了重复代码。“代码越少越好”,我深以为然。当然,随之而来,还有其他好处,容后再表,呵呵。这里只说一句,良好的抽象是实现设计模式的基础。

其实,只要有面向对象的思想,进行这样的抽象是相当容易的(这样的抽象也是不对的,以后再论述)。但我们常常会被关系型数据库所干扰(尤其是有一定开发经验的程序员),而不敢进行这种“大胆的”抽象。因为即使将代码写到这里了,也得面临一个很现实的问题,接下来怎么办?最终我们怎么把这些对象持久化(保存到数据库或其他媒介中去)。这就是我们接下来要进行的工作了。

最后,对那些还想着数据库的同学,再重复强调一点:这个项目,我们用NoSQL!哦,sorry,改主意了,大家反映NoSQL太难了,又说干脆用xml文件吧。

相关文章
|
1月前
|
设计模式 前端开发 测试技术
Flutter 项目架构技术指南
探讨Flutter项目代码组织架构的关键方面和建议。了解设计原则SOLID、Clean Architecture,以及架构模式MVC、MVP、MVVM,如何有机结合使用,打造优秀的应用架构。
Flutter 项目架构技术指南
|
1月前
|
NoSQL Java 数据库
【问题篇】springboot项目通过数据库限制实例端口号
【问题篇】springboot项目通过数据库限制实例端口号
19 0
|
1月前
|
数据库
ABAP 泛型编程实战 - 分享一个数据库表内容的拷贝工具试读版
ABAP 泛型编程实战 - 分享一个数据库表内容的拷贝工具试读版
20 0
|
1月前
|
SQL NoSQL 前端开发
基于BS架构的饰品购物平台设计与实现(程序+文档+数据库)
基于BS架构的饰品购物平台设计与实现(程序+文档+数据库)
|
2月前
|
存储 监控 安全
360 企业安全浏览器基于阿里云数据库 SelectDB 版内核 Apache Doris 的数据架构升级实践
为了提供更好的日志数据服务,360 企业安全浏览器设计了统一运维管理平台,并引入 Apache Doris 替代了 Elasticsearch,实现日志检索与报表分析架构的统一,同时依赖 Doris 优异性能,聚合分析效率呈数量级提升、存储成本下降 60%....为日志数据的可视化和价值发挥提供了坚实的基础。
360 企业安全浏览器基于阿里云数据库 SelectDB 版内核 Apache Doris 的数据架构升级实践
|
27天前
|
SQL 关系型数据库 MySQL
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
96 0
|
1月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
148 0
|
6天前
|
SQL 关系型数据库 MySQL
Python与MySQL数据库交互:面试实战
【4月更文挑战第16天】本文介绍了Python与MySQL交互的面试重点,包括使用`mysql-connector-python`或`pymysql`连接数据库、执行SQL查询、异常处理、防止SQL注入、事务管理和ORM框架。易错点包括忘记关闭连接、忽视异常处理、硬编码SQL、忽略事务及过度依赖低效查询。通过理解这些问题和提供策略,可提升面试表现。
25 6
|
7天前
|
SQL 监控 druid
Druid数据库连接池简介及应用推广(老项目翻出来做下记录)
Druid数据库连接池简介及应用推广(老项目翻出来做下记录)
|
10天前
|
SQL 数据库
数据库SQL语言实战(二)
数据库SQL语言实战(二)

热门文章

最新文章