【问题标题】:Php Separation of Concerns & Dependency Injection关注点分离和依赖注入
【发布时间】:2013-03-28 13:54:25
【问题描述】:

根据 stackoverflow 上的一些好的建议,我需要更多指导。有人告诉我,关注点分离对于保持代码整洁和模块化很重要,我发现确实如此。

我的问题是:根据我对 SOC 的了解,我开发了 2 个类。供应商类和 CSV 类。供应商仅从数据库中检索有关我的不同供应商的数据。 Csv 类从正在导入的 csv 文件中检索数据,我需要解析它的所有信息,最终目标是将数据插入到我的供应商表中。为了实现将 csv 数据插入数据库的目标,我需要使用这两个类中的方法。我是创建一个名为 ImportSuppliersCsv 之类的第 3 个类,还是将导入函数创建为 Suppliers 类的方法更有意义?

为了节省空间而缩短,我的课是这样的:

class Suppliers
{


    public $db;
    public $inv;
    public $table;


    public function __construct (PDO $db)
    {

        $this->db = $db;
        $this->inv = 'lightsnh_inventory';
        $this->table = 'suppliers';

    }


    public function getSuppliers() 
    {               

        $sql = 'SELECT * FROM `'.$this->inv.'`.`'.$this->table.'`';
        $statement = $this->db->query($sql);
        $result = $statement->fetchAll(PDO::FETCH_ASSOC);

        return $result;

    }


    public function getActiveSuppliers() 
    {               

        $suppliers = $this->getSuppliers();     
        $active = array();      
        foreach($suppliers as $supplier) {

            if($supplier['exclude'] == 0)           
                    $active[] = $supplier;

        }

        return $active;

    }


    public function getDistributors() 
    {               

        $suppliers = $this->getSuppliers();     
        $distributors = array();        
        foreach($suppliers as $supplier) {

            if($supplier['type'] == 1)          
                    $distributors[] = $supplier;

        }

        return $distributors;

    }



    class Csv
    {


        public $form;


        public function __construct($form_name)
        {

            $this->form = $form_name;

        }


        public function getFile()
        {

            if(isset($_POST[$this->form.'-upload-submit'])) {

                return $_FILES[$this->form.'-file'];

            }

        }


        public function getName()
        {

            $file = $this->getFile();
            return $file['name'];

        }


        public function getExtension()
        {

            return end(explode('.',$this->getName()));

        }


        public function getType()
        {

            $file = $this->getFile();
            return $file['type'];

        }   etc.....

【问题讨论】:

    标签: php oop class dependencies code-injection


    【解决方案1】:

    您不需要新类即可从 CSV 插入新供应商。您可以简单地添加一个新方法并将一个 Csv 对象传递给它。这样,所有与供应商相关的活动都将封装在一个类中。

    或者,如果您打算拥有其他信息源,除了 CSV,您可以让供应商方法接受解析的信息,而不是 CSV 对象。

    【讨论】:

      【解决方案2】:

      两者都没有。 OOP/SoC/DI 等不是目的,它们是一种手段。 SoC 的目的是使维护更容易的模块化架构,尽管分离关注点总是通过模糊问题来扩大问题。 我发现在 PHP 中提出一个好的设计的最好方法是首先让它工作,然后重构。您也可以先在您的想象中执行此操作以节省一些时间。以您认为最好的方式组织它。毕竟,这个想法是为了让要维护代码的人能够轻松找到自己的方式,因为他们是以这种方式组织代码的。简而言之,谨防过度设计。

      在你的例子中,如果它只用于一个地方,我不会费心去做一个类。举个例子:通常一个可以将 CSV 记录导入数据库的应用程序,也有一个表单来编辑这些行,所以我假设 Suppliers 类中有一个“保存”功能,因为它已经抽象了查询(糟糕- 没有缓存、没有 WHERE 子句、SQL 注入等)。现在导入 CSV 文件的问题是如何将数据有序地呈现给这个“保存”功能。

      现在,将 CSV 文件导入数据库的基本代码本身就是这样简单:

      $data = array_map( 'str_getcsv', explode("\n", file_get_contents( $filename ) ) );
      $columns = array_shift( $data );
      $sth = $db->prepareStatement( "INSERT INTO suppliers( " . implode( ',', $columns )
        . ") VALUES ( " . substr(str_repeat(",?",count($columns)),1) . ")"
      );
      foreach ( $data as $line )
        $sth->execute( $line );
      

      通常它不是那么理想 - 但这本质上是核心功能。它只有 4 个语句,四个关注点:解析 CSV、映射字段、更新数据库和效率/一致性(使用准备好的语句)。

      OOP 仍然依赖于函数式编程——按功能组织。以上内容可以保留为脚本,由 cron 作业或网页调用。它可以放在函数“import_csv”中,供这些任务重用。但是把它放在一个班级里是矫枉过正的。 SoC 还使用外观或接口。函数就是这样,如果需要,可以很容易地分组到一个类中。您只需要一个函数 import_csv( $filename, $profile )。 $profile 将指示表(或表)、列映射等。通过将它们分开,您可以制作通用的 CSV 到 DB 映射编辑器 - 或者至少支持仅通过更改配置将任何 CSV 文件导入任何表。如果您对所有内容进行分类,您最终会为您将要导入的每个 CSV 文件编写一个类。你当然可以创建一个 CSVImporter 类,但这只有在还有其他 Importer 类的情况下才有用 - 毕竟,创建一个类是对功能的抽象,你不能只从一个示例中抽象出来。

      想像一个通用的导入器,而不考虑数据。专注于功能,因为这就是代码。这是一种更好的方法,因为您的代码将不依赖于数据库结构 - 您已经抽象了它(通过使用公共接口扩展 Table 基类,以便您可以 $table->save())。您不会抽象 CSV(这不值得,如第一行代码所示),而是映射。

      这不是您期望的答案,但我确定您不希望答案是您给出的答案,因为您将其作为问题提出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-15
        • 2021-11-19
        • 2017-07-17
        • 1970-01-01
        • 2018-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多