在哪里存储值以传输到业务层?

发布于 2024-09-14 13:24:49 字数 1814 浏览 3 评论 0原文

想象一个具有许多属性的假设对象:

伪代码:

class Student
{
   Name: String;
   Birthdate: DateTime;
   Height: int; //inches
   GPA: float; //"Grade Point Average"
   Citizenship: string;
}

现在用户输入值,对象获取它们:

名称:Shelby Lake
出生日期:1991/6/19
身高:63
平均绩点:5.6
公民身份:美国

具有所有业务逻辑的层可以验证它:

BusinessLayer.ValidateStudent(student);

在这个示例中,它可以抛出异常:

ClientException
GPA cannot exceed 4.00 (5.60)

好的,很好。但并非用户输入的所有内容都可以“适合”对象:

名称:Shelby Lake
出生日期:19 年前
身高:5'3
GPA:不适用
公民身份:n/a

事实上,我们的用户可以在业务决策中输入更友好的值。同时,还有全局业务规则决定某些输入何时有效,例如

GPA:5.6 (无效)
GPA:不适用(有效)
公民身份:n/a (有效)
公民身份: (无效)
身高:(无效)
高度:5'3 (有效)

我的问题是,我在哪里存储这些 string 值,因为我无法将它们纯粹存储在对象中。他们需要进入业务层,该层知道如何将输入的文本解析为值。

我的第一个想法是更改类:

class Student
{
   Name: String;
   Birthdate: DateTime;
   BirthdateFreeForm: string;
   Height: int; //inches
   HeightFreeform: string;
   GPA: float; //"Grade Point Average"
   GPAFreeform: string;
   Citizenship: string;
}

这允许将更多任意值发送到业务层:

名称:Shelby Lake
出生日期自由形式:19 年前
自由高度:5'3
平均绩点:4.6 公民身份:n/a

BusinessLayer.ValidateStudent(student);

业务层可以将自由格式值转换为规范值,报告任何错误:

ClientException
Country of citizenship must be entered ("n/a")

但这似乎是一个丑陋的答案,我什至不想考虑它。

使用业务规则解析用户输入的企业方法是什么?

Imagine a hypothetical object with a number of attributes:

pseudocode:

class Student
{
   Name: String;
   Birthdate: DateTime;
   Height: int; //inches
   GPA: float; //"Grade Point Average"
   Citizenship: string;
}

Now the user enters in values, and the object gets them:

Name: Shelby Lake
Birthdate: 6/19/1991
Height: 63
GPA: 5.6
Citizenship: United States

And the layer with all the business logical can validate it:

BusinessLayer.ValidateStudent(student);

In this example it could, for example, throw an exception:

ClientException
GPA cannot exceed 4.00 (5.60)

Okay, fine. But not everything the user types in can "fit" inside the object:

Name: Shelby Lake
Birthdate: 19 years ago
Height: 5'3
GPA: n/a
Citizenship: n/a

The fact that our users are allowed to enter in more friendly values in a business decision. At the same time there are global business rules that decide when some input is valid, e.g.

GPA: 5.6 (invalid)
GPA: n/a (valid)
Citizenship: n/a (valid)
Citizenship: (invalid)
Height: tall (invalid)
Height: 5'3 (valid)

My problem is, where do i store these string values, since i cannot store them purely in the object. They need to get to the business layer, which knows how to parse entered text into values.

My first thought is to change the class:

class Student
{
   Name: String;
   Birthdate: DateTime;
   BirthdateFreeForm: string;
   Height: int; //inches
   HeightFreeform: string;
   GPA: float; //"Grade Point Average"
   GPAFreeform: string;
   Citizenship: string;
}

This allows the more arbitrary values to be sent to the business layer:

Name: Shelby Lake
BirthdateFreeform: 19 years ago
HeightFreeform: 5'3
GPA: 4.6
Citizenship: n/a

BusinessLayer.ValidateStudent(student);

And the business layer can convert free-form values into canonical values, reporting any errors:

ClientException
Country of citizenship must be entered ("n/a")

But that seems like such an ugly answer i don't even want to consider it.

What's the enterprisey way to parse user input with business rules?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丘比特射中我 2024-09-21 13:24:49

当用户输入的数据与模型表示数据的方式显着不同时,我采取的一种方法是使用视图模型的特定类,并在此类中提供辅助方法以将该视图模型转换为适当的域对象:

 class StudentViewModel {
    StudentViewModel(Student s) {
       // map the properties of Student to the appropriate view model 
       // properties.
    }

    StudentViewModel() {
       // use this for creating a new student.
    }

    Name: string
    Height: string
    GPA: string
    // etc.

    Student GetUpdatedStudent() {
        // map your view model properties to the Student class 
        // and return an updated Student.
    }
 }

尽管涉及一些额外的工作,但这种方法非常灵活。您可以直接针对 ViewModel 而不是域对象进行验证,并保证您的模型不需要适应无效数据,这使它们能够专注于表示域的真正目的,而不是不断防范无效数据。

此外,当您拥有可转换为深度对象图的“扁平”用户体验时,这种方法会变得非常有用。

One approach I've taken when data entered by the user differs significantly from the way the model represents data is to use a specific class for a view model, and provide helper methods within this class to translate that view model to a proper domain object:

 class StudentViewModel {
    StudentViewModel(Student s) {
       // map the properties of Student to the appropriate view model 
       // properties.
    }

    StudentViewModel() {
       // use this for creating a new student.
    }

    Name: string
    Height: string
    GPA: string
    // etc.

    Student GetUpdatedStudent() {
        // map your view model properties to the Student class 
        // and return an updated Student.
    }
 }

This approach is extremely flexible, although there is some additional work involved. You can validate directly against the ViewModel rather than the domain object, and be guaranteed that your models do not need to accomodate against invalid data, which allows them to focus on their true purpose of representing your domain, rather than constantly guarding against invalid data.

In addition, this approach becomes incredibly useful when you have a "flat" user experience that translates into a deep object graph.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文