将计算保存到代码或数据库中? [英] Save Calculation in Code or Database?

查看:117
本文介绍了将计算保存到代码或数据库中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个系统,该系统将对原始数据进行各种计算,并根据计算结果提供输出.

I'm setting up a system which will carry out various calculations on primitive data, and the provide an output based on the calculation.

我的主要问题是更多的建议,而不是方法.

My main question, is more advice rather than a how-to.

使用MySQL数据库和php进行访问.

Using a MySQL database, and php to access.

目前需要完成约200种不同的计算,但这些计算分为4种计算类型,即,一种计算类型用x除以y,而不同的计算将是x或y的不同原始值.

There are currently ~200 different calculations that need done but these fall into 4 calculation types ie one calculation type is x divided by y, while the different calculations will be different primitive values for x or y.

系统将需要在系统的各个部分进行不同的计算,因此我创建了一个函数来进行计算.目前,我已经将用于实际计算的代码(带有少量错误处理)保存在数据库中,就像这样;

The system will need to carry out the different calculations at various sections of the system, so I've created one function to carry out the calculation. Currently I have the code for the actual calculation (with a tiny bit of error handling) saved in the database, like this;

**calc_id** | **calc_code**
aDIVb       | if($primBVal != 0){ $result = ($primAVal / $primBVal);} else {$result = 'NA';}
aPERCb      | if($primBVal != 0){ $result = (100 / $primBVal) * $primAVal;} else {$result = 'NA';}

等 然后使用eval( $calcArray['calc_code']);

etc. These are then calculated in php using eval( $calcArray['calc_code']);

这4种计算永远不会改变,尽管将来可能会增加更多.

The 4 calculations will never change, though more may be added in the future.

问题是,我应该将此代码构建到PHP函数中,还是可以原样保留在数据库中?基于可能会添加更多内容的事实,我倾向于数据库,因为我可以在其中添加新行以处理新的计算类型,而不必编辑任何代码.

The question is, should I build this code into the PHP function, or is it ok to stay in the database as is? Based on the fact that more may be added, I'm leaning towards the database, as I can add new rows in to handle the new calculation types, rather than having to edit any code.

希望这对所有问题都有意义,对冗长的问题表示歉意,并且可能使用狡猾的格式.

Hopefully this all makes sense, apologies for the long question and probably dodgy formatting.

谢谢.

推荐答案

Eval is Evil

首先:除非有充分的理由,否则不要使用eval(). 从来没有很好的理由 .

Eval is Evil

First of all: don't use eval() unless there is a good reason. And there is never a good reason.

在最坏的情况下,eval()会使您的应用程序容易受到注入攻击,而且速度很慢.大量的研究揭示了为什么eval是大禁忌的许多原因.

in the worst case eval() makes your application vulnerable to injection attacks and also it's very slow. A bit of research reveals plenty of reasons why eval is a big no-no.

如果这样做,并且希望从PHP切换到另一种语言,则数据库中仍将包含PHP代码.这确实使迁移语言变得非常困难.您应该始终努力使应用程序的尽可能多的部分尽可能独立.

If you do so and you would like to switch from PHP to another language you would still have PHP code in your database. It makes it really hard to migrate languages. You should always strive to make as many parts of your application as independent as possible.

在这种情况下,您需要将使用的语言紧密耦合到数据库.这是一个坏习惯.

In this case you would tight-couple the language you use, to the database. That's a bad practice.

从数据库运行计算的唯一可能性就是评估它们(这很糟糕,请参见上文)或使用字符串操作或正则表达式反汇编字符串,这会导致不必要的工作.

Also the only possibilities to run your calculations from the database would be to eval them (which is bad, see above) or to disassemble the string with string operations or regex which causes unnecessary effort.

为了解决您的问题,您必须根据所需的计算执行代码.这可以通过switch-case-statement或if-statement完成.但这也不是一个非常优雅的解决方案.假设您将来需要进行其他操作,然后再进行计算或扩展功能.您将需要更新所有案例或if语句.

In order to solve your problem you must execute code dependent of which calculation you need. That could be either done with switch-case-statements or if-statements. But that's also not a very elegant solution. Imagine you would need to execute other operations before calculating in the future, or extend functionality. You would need to update all your cases or if-statements.

有一个很好的设计模式,称为策略模式.当可以用不同的方式处理一个用例时,这种策略模式可以解决问题.

There is a nice design-pattern which is called Strategy Pattern. The strategy pattern solves problems when one use-case can be handled differently which is probably what you want.

您要计算某种东西(用例),并且有不同的计算类型(不同的策略)

要实现策略模式,您基本上需要三件事.

To implement the Strategy pattern you basically need three things.

  • 一个课程,您可以在其中插入自己的策略.基本上,它是您的战略任务的包装器.
  • 将由您的策略实现的界面
  • 您的策略

您的界面可能如下所示:

Your interface could look like this:

<?php
interface CalculatableInterface {

    public function calculate();

}

该界面将确保您所有的策略都提供一种实际运行计算的方法.没什么特别的.

The interface will make sure that all your strategies provide a method to actually run the calculation. Nothing special.

接下来,您可能需要一个基类,该基类将计算运算符作为构造函数参数并将其存储到属性中.

Next you may want to have a base class that takes your calculation operators as constructor arguments and stores them into properties.

<?php
abstract class Calculatable {

    protected $valueA;
    protected $valueB;

    public function __construct($valueA, $valueB)
    {
        $this->valueA = $valueA;
        $this->valueB = $valueB;
    }

}

现在,它变得越来越严重.我们正在执行我们的策略.

Now it's getting serious. We are implementing our strategies.

<?php
class Division extends Calculatable implements CalculatableInterface {

    public function calculate()
    {
        return ($this->valueB != 0) ? $this->valueA / $this->valueB : 'NA';
    }

}

class Percentage extends Calculatable implements CalculatableInterface {

    public function calculate()
    {
        return ($this->valueB != 0) ? (100 / $this->valueB) * $this->valueA : 'NA';
    }

}

您当然可以稍微清理一下,但是我想在这里指出的是类声明.

Of course you could clean this one up a bit, but what I want to point out here is the class declaration.

我们正在扩展Calculatable类,以便我们可以通过构造函数传递算术运算,并且正在实现CalculatableInterface,它告诉我们的类:"嘿!您必须提供一个calculate方法,我不知道.不管您是否想要.

We are extending our Calculatable class so that we can pass the arithmetic operations via constructor and we are implementing the CalculatableInterface which tells our class: "Hey! You must provide a calculate method, I don't care whether you want or not.

我们将在后面看到为什么这是模式不可分割的一部分.

We'll see later why this is an integral part of the pattern.

因此,我们有两个具体的类,它们包含用于实际算术运算的实际代码.如果需要,您可以轻松地对其进行更改,如您所见. 要添加更多操作,只需添加另一个类.

So we have two concrete classes that contain the actual code for the actual arithmetic operation. If you would ever need to, you could change it easily as you see. To add more operations just add another class.

现在,我们将创建一个可以注入我们的策略的类.稍后,您将实例化此类的对象并对其进行处理.

Now we will create a class where our strategies can be injected. Later you will instantiate an object of this class and work with it.

这是它的样子:

<?php 
class Calculator {

    protected $calculatable;

    public function __construct( CalculatableInterface $calculatable )
    {
        $this->calculatable = $calculatable;
    }

    public function calculate()
    {
        return $this->calculatable->calculate();
    }

}

这里最重要的部分是构造函数.在此处查看我们如何键入提示.通过这样做,我们确保只能注入对象(依赖注入),类实现接口.我们不需要在这里要求具体的课程.这是关键点.

The most important part here is the constructor. See how we type-hint our interface here. By doing that we make sure that only an object can be injected (Dependency Injection) whose class implements the interface. We do not need to demand a concrete class here. That's the crucial point here.

那里也有一个计算方法.这只是我们执行其计算方法的策略的包装.

Also there's a calculate method in there. It's just a wrapper for our strategy to execute it's calculate method.

所以现在我们只需要创建一个Calculator类的对象,并传递一个我们的策略类(包含用于算术运算的代码)的对象.

So now we just need to create an object of our Calculator class and pass an object of one of our strategy classes (that contain the code for the arithmetic operations).

<?php
//The corresponding string is stored in your DB
$calculatable = 'Division';

$calc = new Calculator( new $calculatable(15, 100) );
echo $calc->calculate();

尝试将存储在$calculatable中的字符串替换为Percentage,您会看到将执行计算百分比的操作.

Try replacing the string stored in $calculatable to Percentage and you see that the operation for calculating the percentage will be executed.

该策略模式允许您创建一个干净的界面来处理仅在运行时才具体化的动态任务.您的数据库都不需要知道我们如何计算事物,您的实际计算器也不需要.我们唯一需要确保的是针对接口编码,该接口提供了一种让我们计算事物的方法.

The strategy pattern allowed you to create a clean interface for working with dynamic tasks that are only made concrete during runtime. Neither your database needs to know how we calculate things, nor your actual calculator does. The only thing we need to make sure is to code against an interface that provides a method to let us calculate things.

这篇关于将计算保存到代码或数据库中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆