我该如何处理行为组合?

时间:2022-10-19 21:55:16

I am considering the problem of validating real numbers of various formats, because this is very similar to a problem I am facing in design.

我正在考虑验证各种格式的实数的问题,因为这非常类似于我在设计中遇到的问题。

Real numbers may come in different combinations of formats, for example: 1. with/without sign at the front 2. with/without a decimal point (if no decimal point, then perhaps number of decimals can be agreed beforehand) 3. base 10 or base 16

实数可能有不同的格式组合,例如:1。前面带/不带符号2.带/不带小数点(如果没有小数点,则可能事先约定小数位数)3。基数10或基地16

We need to allow for each combination, so there are 2x2x2=8 combinations. You can see that the complexity increases exponentially with each new condition imposed.

我们需要允许每个组合,因此有2x2x2 = 8种组合。您可以看到,每增加一个新条件,复杂性就会呈指数级增长。

In OO design, you would normally allocate a class for each number format (e.g. in this case, we have 8 classes), and each class would have a separate validation function. However, with each new condition, you have to double the number of classes required and it soon becomes a nightmare.

在OO设计中,您通常会为每种数字格式分配一个类(例如,在这种情况下,我们有8个类),每个类都有一个单独的验证函数。但是,对于每个新条件,您必须将所需类的数量增加一倍,并且很快就会变成一场噩梦。

In procedural programming, you use 3 flags (i.e. has_sign, has_decimal_point and number_base) to identify the property of the real number you are validating. You have a single function for validation. In there, you would use the flags to control its behaviour.

在过程编程中,使用3个标志(即has_sign,has_decimal_point和number_base)来标识要验证的实数的属性。您有一个验证功能。在那里,您将使用标志来控制其行为。


// This is part of the validation function

if (has_sign) check_sign();

if(has_sign)check_sign();

for (int i = 0; i < len; i++) { if (has_decimal_point) // Check if number[i] is '.' and do something if it is. If not, continue

for(int i = 0; i ;>

if (number_base = BASE10)
    // number[i] must be between 0-9
else if (number_base = BASE16)
    // number[i] must be between 0-9, A-F

}

Again, the complexity soon gets out of hand as the function becomes cluttered with if statements and flags.

同样,复杂性很快就会失控,因为函数变得混乱了if语句和标志。

I am sure that you have come across design problems of this nature before - a number of independent differences which result in difference in behaviour. I would be very interested to hear how have you been able to implement a solution without making the code completely unmaintainable.

我确信您之前遇到过这种性质的设计问题 - 一些独立的差异会导致行为上的差异。我很想知道如何在不使代码完全无法维护的情况下实现解决方案。

Would something like the bridge pattern have helped?

像桥梁模式这样的东西有帮助吗?

5 个解决方案

#1


In OO design, you would normally allocate a class for each number format (e.g. in this case, we have 8 classes), and each class would have a separate validation function.

在OO设计中,您通常会为每种数字格式分配一个类(例如,在这种情况下,我们有8个类),每个类都有一个单独的验证函数。

No no no no no. At most, you'd have a type for representing Numeric Input (in case String doesn't make it); another one for Real Number (in most languages you'd pick a built-in type, but anyway); and a Parser class, which has the knowledge to take a Numeric Input and transform it into a Real Number.

不不不不不。最多,你有一个表示数字输入的类型(如果String不能成功);另一个用于实数(在大多数语言中你选择内置类型,但无论如何);和一个Parser类,它具有获取数字输入并将其转换为实数的知识。

To be more general, one difference of behaviour in and by itself doesn't automatically map to one class. It can just be a property inside a class. Most importantly, behaviours should be treated orthogonally.

更一般地说,行为本身和行为本身的一个区别并不会自动映射到一个类。它可以只是一个类中的属性。最重要的是,应该正确地对待行为。

If (imagining that you write your own parser) you may have a sign or not, a decimal point or not, and hex or not, you have three independent sources of complexity and it would be ok to find three pieces of code, somewhere, that treat one of these issues each; but it would not be ok to find, anywhere, 2^3 = 8 different pieces of code that treat the different combinations in an explicit way.

如果(想象你编写自己的解析器)你可能有一个符号或不符号,小数点与否,十六进制与否,你有三个独立的复杂来源,可以找到三段代码,在某处,每个都处理其中一个问题;但是,在任何地方找到2 ^ 3 = 8个不同的代码片段以明确的方式处理不同的组合是不行的。

Imagine that add a new choice: suddenly, you remember that numbers might have an "e" (such as 2.34e10) and want to be able to support that. With the orthogonal strategy, you'll have one more independent source of complexity, the fourth one. With your strategy, the 8 cases would suddenly become 16! Clearly a no-no.

想象一下,添加一个新的选择:突然,你记得数字可能有一个“e”(如2.34e10),并希望能够支持它。使用正交策略,您将拥有一个独立的复杂来源,第四个。根据你的策略,8个案例会突然变成16个!显然是禁忌。

#2


I don't know why you think that the OO solution would involve a class for each number pattern. My OO solution would be to use a regular expression class. And if I was being procedural, I would probably use the standard library strtod() function.

我不知道为什么你认为OO解决方案会涉及每个数字模式的类。我的OO解决方案是使用正则表达式类。如果我是程序性的,我可能会使用标准库strtod()函数。

#3


You're asking for a parser, use one:

你要求一个解析器,使用一个:

Also: http://en.wikipedia.org/wiki/Parser_generator

Now how do I handle complexity for this kind of problems ? Well if I can, I reformulate.

现在我该如何处理这类问题的复杂性?好吧,如果我能,我重新制定。

In your case, using a parser generator (or regular expression) is using a DSL (Domain Specific Language), that is a language more suited to the problem you're dealing with.

在您的情况下,使用解析器生成器(或正则表达式)使用DSL(域特定语言),这是一种更适合您正在处理的问题的语言。

Design pattern and OOP are useful, but definitely not the best solution to each and every problem.

设计模式和OOP很有用,但绝对不是解决每个问题的最佳解决方案。

#4


Sorry but since i use vb, what i do is a base function then i combine a evaluator function so ill fake code it out the way i have done it

很抱歉,但是因为我使用vb,我所做的是一个基本功能,然后我结合了一个评估器功能,所以生病的假代码就像我做的那样

function getrealnumber(number as int){ return  getrealnumber(number.tostring) }
function getrealnumber(number as float){ return  getrealnumber(number.tostring) }
function getrealnumber(number as double){ return  getrealnumber(number.tostring) }
function getrealnumber(number as string){
if ishex(){ return evaluation()}
   if issigned(){ return evaluation()}
   if isdecimal(){ return evaluation()}
 }

and so forth up to you to figure out how to do binary and octal

等等,由你来弄清楚如何做二进制和八进制

#5


You don't kill a fly with a hammer.

你不要用锤子杀死苍蝇。

I realy feel like using a Object-Oriented solution for your problem is an EXTREME overkill. Just because you can design Object-Oriented solution , doesn't mean you have to force such one to every problem you have.

我真的觉得为你的问题使用面向对象的解决方案是一种极端的过度杀伤力。仅仅因为您可以设计面向对象的解决方案,并不意味着您必须将此类问题强加给您所遇到的每个问题。

From my experience , almost every time there is a difficulty in finding an OOD solution to a problem , It probably mean that OOD is not appropiate. OOD is just a tool , its not god itself. It should be used to solve large scale problems , and not problems such one you presented.

根据我的经验,几乎每次在找到问题的OOD解决方案时都很困难,这可能意味着OOD不合适。 OOD只是一种工具,它不是上帝本身。它应该用于解决大规模问题,而不是你提出的问题。

So to give you an actual answer (as someone mentioned above) : use regular expression , Every solution beyond that is just an overkill.

所以为了给你一个真正的答案(正如上面提到的那样):使用正则表达式,除此之外的每个解决方案都只是一种矫枉过正。

If you insist using an OOD solution.... Well , since all formats you presented are orthogonal to each other , I dont see any need to create a class for every possible combination. I would create a class for each format and pass my input through each , in that case the complexity will grow linearly.

如果你坚持使用OOD解决方案....好吧,因为你呈现的所有格式都是正交的,我不认为有必要为每个可能的组合创建一个类。我会为每种格式创建一个类,并通过每个格式传递我的输入,在这种情况下,复杂性将线性增长。

#1


In OO design, you would normally allocate a class for each number format (e.g. in this case, we have 8 classes), and each class would have a separate validation function.

在OO设计中,您通常会为每种数字格式分配一个类(例如,在这种情况下,我们有8个类),每个类都有一个单独的验证函数。

No no no no no. At most, you'd have a type for representing Numeric Input (in case String doesn't make it); another one for Real Number (in most languages you'd pick a built-in type, but anyway); and a Parser class, which has the knowledge to take a Numeric Input and transform it into a Real Number.

不不不不不。最多,你有一个表示数字输入的类型(如果String不能成功);另一个用于实数(在大多数语言中你选择内置类型,但无论如何);和一个Parser类,它具有获取数字输入并将其转换为实数的知识。

To be more general, one difference of behaviour in and by itself doesn't automatically map to one class. It can just be a property inside a class. Most importantly, behaviours should be treated orthogonally.

更一般地说,行为本身和行为本身的一个区别并不会自动映射到一个类。它可以只是一个类中的属性。最重要的是,应该正确地对待行为。

If (imagining that you write your own parser) you may have a sign or not, a decimal point or not, and hex or not, you have three independent sources of complexity and it would be ok to find three pieces of code, somewhere, that treat one of these issues each; but it would not be ok to find, anywhere, 2^3 = 8 different pieces of code that treat the different combinations in an explicit way.

如果(想象你编写自己的解析器)你可能有一个符号或不符号,小数点与否,十六进制与否,你有三个独立的复杂来源,可以找到三段代码,在某处,每个都处理其中一个问题;但是,在任何地方找到2 ^ 3 = 8个不同的代码片段以明确的方式处理不同的组合是不行的。

Imagine that add a new choice: suddenly, you remember that numbers might have an "e" (such as 2.34e10) and want to be able to support that. With the orthogonal strategy, you'll have one more independent source of complexity, the fourth one. With your strategy, the 8 cases would suddenly become 16! Clearly a no-no.

想象一下,添加一个新的选择:突然,你记得数字可能有一个“e”(如2.34e10),并希望能够支持它。使用正交策略,您将拥有一个独立的复杂来源,第四个。根据你的策略,8个案例会突然变成16个!显然是禁忌。

#2


I don't know why you think that the OO solution would involve a class for each number pattern. My OO solution would be to use a regular expression class. And if I was being procedural, I would probably use the standard library strtod() function.

我不知道为什么你认为OO解决方案会涉及每个数字模式的类。我的OO解决方案是使用正则表达式类。如果我是程序性的,我可能会使用标准库strtod()函数。

#3


You're asking for a parser, use one:

你要求一个解析器,使用一个:

Also: http://en.wikipedia.org/wiki/Parser_generator

Now how do I handle complexity for this kind of problems ? Well if I can, I reformulate.

现在我该如何处理这类问题的复杂性?好吧,如果我能,我重新制定。

In your case, using a parser generator (or regular expression) is using a DSL (Domain Specific Language), that is a language more suited to the problem you're dealing with.

在您的情况下,使用解析器生成器(或正则表达式)使用DSL(域特定语言),这是一种更适合您正在处理的问题的语言。

Design pattern and OOP are useful, but definitely not the best solution to each and every problem.

设计模式和OOP很有用,但绝对不是解决每个问题的最佳解决方案。

#4


Sorry but since i use vb, what i do is a base function then i combine a evaluator function so ill fake code it out the way i have done it

很抱歉,但是因为我使用vb,我所做的是一个基本功能,然后我结合了一个评估器功能,所以生病的假代码就像我做的那样

function getrealnumber(number as int){ return  getrealnumber(number.tostring) }
function getrealnumber(number as float){ return  getrealnumber(number.tostring) }
function getrealnumber(number as double){ return  getrealnumber(number.tostring) }
function getrealnumber(number as string){
if ishex(){ return evaluation()}
   if issigned(){ return evaluation()}
   if isdecimal(){ return evaluation()}
 }

and so forth up to you to figure out how to do binary and octal

等等,由你来弄清楚如何做二进制和八进制

#5


You don't kill a fly with a hammer.

你不要用锤子杀死苍蝇。

I realy feel like using a Object-Oriented solution for your problem is an EXTREME overkill. Just because you can design Object-Oriented solution , doesn't mean you have to force such one to every problem you have.

我真的觉得为你的问题使用面向对象的解决方案是一种极端的过度杀伤力。仅仅因为您可以设计面向对象的解决方案,并不意味着您必须将此类问题强加给您所遇到的每个问题。

From my experience , almost every time there is a difficulty in finding an OOD solution to a problem , It probably mean that OOD is not appropiate. OOD is just a tool , its not god itself. It should be used to solve large scale problems , and not problems such one you presented.

根据我的经验,几乎每次在找到问题的OOD解决方案时都很困难,这可能意味着OOD不合适。 OOD只是一种工具,它不是上帝本身。它应该用于解决大规模问题,而不是你提出的问题。

So to give you an actual answer (as someone mentioned above) : use regular expression , Every solution beyond that is just an overkill.

所以为了给你一个真正的答案(正如上面提到的那样):使用正则表达式,除此之外的每个解决方案都只是一种矫枉过正。

If you insist using an OOD solution.... Well , since all formats you presented are orthogonal to each other , I dont see any need to create a class for every possible combination. I would create a class for each format and pass my input through each , in that case the complexity will grow linearly.

如果你坚持使用OOD解决方案....好吧,因为你呈现的所有格式都是正交的,我不认为有必要为每个可能的组合创建一个类。我会为每种格式创建一个类,并通过每个格式传递我的输入,在这种情况下,复杂性将线性增长。