model-view-controller - 我应该从这个模型类中提取功能到一个表单类中吗? (事件记录模式)

标签 model-view-controller database-design web-applications sqlalchemy pyramid

我正在设计一个遵循 mvc 范式的应用程序。如果有人好奇,我正在使用 sqlalchemy 表达式语言(不是 orm)和 Pyramid 。

因此,对于代表系统上用户的用户类,我有多种访问器方法用于各种数据,如 avatar_url、name、about 等。我有一个名为 getuser 的方法,它在 db(按名称或ID),检索用户行,并用用户类封装它。

但是,每次创建用户类时都必须进行此查找吗?如果用户正在查看她的控制面板并想要更改头像,并发送一个 xhr 怎么办?必须创建一个用户对象,并在他们甚至不会使用检索到的数据时查找用户行,这不是一种浪费吗?但只是想对列的子集进行更改?我怀疑尽管由于等待 i/o 正确而进行索引,但这种查找可以忽略不计?

更一般地说,必须查询数据库并加载所有模型类的数据以进行任何更改(即使是很小的更改)是不是效率低下?

我想我应该创建一个单独的表单类(因为所做的每个更改都是通过某种表单进行的),并让特定的表单类继承它们,这些 setter 方法将在其中实现。你怎么认为?

例如:类:表单 <- 类:Change_password_form <- 函数:change_usr_pass

我真的很感激有关创建适当设计的一些建议;谢谢。

最佳答案

SQLAlchemy ORM 有一些工具可以简化您的任务。看起来您必须重新发明 ORM 层中已经存在的相当多的轮子:“我有一个名为 getuser 的方法,它在数据库中查找用户(按名称或 ID),检索用户行,并封装它与用户类” - 这就是 ORM 所做的。

  • 使用 ORM,您有一个 Session,它除了其他东西外,还用作 ORM 对象的缓存,因此您可以避免每个事务多次加载相同的模型。您会发现无论如何都需要加载 User 对象来验证请求,因此根本不查询表可能不是一种选择。
  • 您还可以将一些属性配置为 lazily loaded ,因此一些很少需要或庞大的属性仅在您访问它们时加载
  • 您还可以将关系配置为 eagerly loaded在单个查询中,这可以使您免于执行数百个小的单独查询。我的意思是,在您当前的设计中,以下代码会启动多少个查询:
    for user in get_all_users():
        print user.get_avatar_uri()
        print user.get_name()
        print user.get_about()
    

  • 从您的描述看来,它可能需要 1 + (num_users*3) 个查询。使用 SQLAlchemy ORM,您可以在单个查询中加载所有内容。

    结论是:通过主键从数据库中获取单个对象是一种相当便宜的操作,除非您正在构建 facebook 大小的东西,否则您不必担心这一点。您应该担心的是进行数百个单独的小型查询,而一个较大的查询就足够了。这是 SQLAlchemy ORM 非常出色的领域。

    现在,关于“必须创建用户对象并在他们甚至不会使用检索到的数据时查找用户行不是一种浪费;但只是想对列的子集进行更改” - 我明白你正在考虑类似的事情
    class ChangePasswordForm(...):
    
        def _change_password(self, user_id, new_password):
             session.execute("UPDATE users ...", user_id, new_password)
    
        def save(self, request):
             self._change_password(request['user_id'], request['password'])
    

    相对
    class ChangePasswordForm(...):
    
        def save(self, request):
             user = getuser(request['user_id'])
             user.change_password(request['password'])
    

    前一个示例将只发出一个查询,后者必须发出一个 SELECT 并构建 User 对象,然后发出一个 UPDATE。后者似乎“效率翻倍”,但在实际应用中,差异可能可以忽略不计。此外,通常您无论如何都需要从数据库中获取对象,要么进行验证(新密码不能与旧密码相同)、权限检查(是否允许用户 Molly 编辑照片 #12343 的描述?)或日志记录。

    如果您认为执行额外查询的区别很重要(数百万用户不断编辑他们的个人资料图片),那么您可能需要进行一些分析并查看瓶颈所在。

    关于model-view-controller - 我应该从这个模型类中提取功能到一个表单类中吗? (事件记录模式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12549071/

    相关文章:

    ruby-on-rails - #<Micropost::ActiveRecord_Associations_CollectionProxy:0x007ffc26104288> 的 MembersController#index 未定义方法 `total_pages' 中的 NoMethodError

    php - 使用 Zend Framework 2 扩展 ZfcUser

    javascript - extjs4 在 Controller 中获取 View 实例?

    java - oracle 11g xe 的本地主机是什么?

    intellij-idea - IntelliJ 是否有内部 Web 服务器来提供 Web 应用程序的静态内容?

    iphone - 如何让每个类(class)互相交流?

    sql - 创建 Sql 查询的设计模式

    MySQL - 2 路查询检查

    mysql - 体育/游戏结果应用程序中的硬删除与软删除

    javascript - 在浏览器上访问本地文件系统