【问题标题】:Is it better to have one setter method or multiple for objects with a fixed number of fields?对于具有固定数量字段的对象,使用一个 setter 方法还是多个方法更好?
【发布时间】:2019-02-12 02:47:06
【问题描述】:

我有一个类,其成员变量为对象类型。该对象具有固定数量的字段。我正在尝试决定是否应该使用一个 setter 函数或多个来改变这些字段。

为了使问题更具体,我编写了以下类来以两种不同的方式对简单的组织管理结构进行建模:

  1. 多个设置器函数

    class Management {
        constructor() {
            this.numberOfManagers = 100;
            this.salaryDetails = {
                regionalManagerSalary: 80000,
                stateManagerSalary: 110000,
                executiveManagerSalary: 200000
            };
        }
    
        setRegionalManagerSalary(salary) {
            this.salaryDetails.regionalManagerSalary = salary;
        }
    
        setStateManagerSalary(salary) {
            this.salaryDetails.stateManagerSalary = salary;
        }  
    
        setExecutiveManagerSalary(salary) {
            this.salaryDetails.executiveManagerSalary = salary;
        }
    }
    
    const management = new Management();
    management.setRegionalManagerSalary(100000);
    management.setStateManagerSalary(120000);
    management.setExecutiveManagerSalary(210000);
    
  2. 一个设置器函数

    class Management {
        constructor() {
            this.numberOfManagers = 100;
            this.salaryDetails = {
                regionalManagerSalary: 80000,
                stateManagerSalary: 110000,
                executiveManagerSalary: 200000
            };
        }
    
        setManagerSalary(typeOfManagerSalary, salary) {
            this.salaryDetails[typeOfManagerSalary] = salary;
        }
    }
    
    const management = new Management();
    management.setManagerSalary('regionalManagerSalary', 100000);
    management.setManagerSalary('stateManagerSalary', 120000);
    management.setManagerSalary('executiveManagerSalary', 210000);
    

实施 1. 会更好还是实施 2. 更好?

【问题讨论】:

  • 我认为 2 会更好。代码行少,可读性好
  • 但是,如果您有需要检查或过滤要设置的值的要求,那么相同的代码示例 2 将变得复杂。

标签: javascript architecture readability maintainability


【解决方案1】:

如果不牺牲很多可写性,我将始终考虑更高可读性的方法。第二个更通用,但第一个更清晰。

所以我认为第一个更好,因为它更清楚salaryDetails 中只有 3 个字段。考虑一下你不是作者,当你看到第二个时,你不知道salaryDetails 中有多少字段,因为有人可以在某个地方调用management.setManagerSalary('someNewSalary', 100000); 来添加一些新字段。

除非您有多个管理对象,并且每个管理对象都可能在salaryDetails 下有一些特定字段,否则我认为第二种方法不会更好。

【讨论】:

    【解决方案2】:

    我的建议是使用一种方法,即 setSalaryDetails,它将薪水对象作为您可以直接设置的输入。类似的东西 -

    setSalaryDetails(salaryDetails){this.salaryDetails = SalaryDetails; }

    当您调用此方法时,您可以适当地使用您将传递给它的那些字段集来创建此对象。

    【讨论】:

    • 这很危险,因为调用者可能不知道salaryDetails 的确切结构。调用者可能会传递一个缺少字段的对象或无意中覆盖现有字段。
    • 不,因为在当前代码中,调用者也需要知道他需要设置的属性/键。如果调用者知道一个属性,为什么他不知道其他属性。如果此代码是库的一部分,那么我们希望我们与消费者共享 JSON 合约(就像您为 REST 服务所做的那样)。调用者和被调用者需要相互同意合同。所以这并不危险等人。
    【解决方案3】:

    最好根本没有任何二传手。在构造函数中初始化所有必需的属性(让构造函数为此需要参数)。

    您发布的代码不是 OOP,而是伪装的程序代码。如果要使其成为 OOP,则代码必须保留在数据所在的位置,即在类中。

    作为改进的第一步,您的代码应如下所示:

    class Management {
        constructor(nb, regionalSalary, stateSalary, executiveSalary) {
            this.numberOfManagers = nb;
            this.salaryDetails = {
                regionalManagerSalary: regionalSalary,
                stateManagerSalary: stateSalary,
                executiveManagerSalary: executiveSalary
            };
        }
    }
    
    const management = new Management(100, 100000, 120000, 210000);
    

    更短、更简洁、更不容易出错。

    您发布的片段不足以说明您想要实现什么,但构造函数的新签名告诉我您将太多职责混合到一个类中。

    更简洁的设计是为每种经理类型使用单独的类:

    /* abstract */ class Manager {
        constructor(salary) {
            this.salary = salary;
        }
    }
    
    class RegionalManager extends Manager { }
    class StateManager extends Manager { }
    class ExecutiveManager extends Manager { }
    
    class Management {
        constructor(nb, regionalManager, stateManger, executiveManager) {
            this.numberOfManagers = nb;
            this.managers = {
                regionalManager: regionaManager,
                stateManager: stateManager,
                executiveManager: executiveManager
            };
        }
    }
    
    const management = new Management(
        100,
        new RegionalManager(100000),
        new StateManager(120000),
        new ExecutiveManager(210000)
    );
    

    您现在可以在 Manager 类中实现所有管理器类型共有的逻辑、特定于其类中每个管理器类型的逻辑以及按编号处理管理器的逻辑,而无需关心它们的个体特征,在类Management。这样代码使用更少的ifswitch条件,更容易阅读、理解和进一步开发。

    【讨论】:

      猜你喜欢
      • 2022-12-14
      • 2013-08-26
      • 2011-02-05
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多