对基于窗口和Web的应用程序的业务逻辑层设计的看法

发布于 2024-09-24 17:59:29 字数 445 浏览 1 评论 0原文

我需要一些关于为基于 Web 的业务层函数选择哪些签名的意见:

function void CreateUser(Company UserCompany, string name...)

function void CreateUser(int CompanyID, string name. ..)

如果这是基于窗口的,我会选择函数来获取对象而不是 int,因为既然公司已经加载到窗口表单,为什么不直接使用它呢。另外,我认为业务层应该采用业务对象并且它是类型安全的(防止意外传入 0 或 -1)。

但另一方面,如果这是一个基于 Web 的应用程序,则只有 id 会加载到客户端站点。因此加载公司对象有点多余,因为最终只有companyID 会保存在数据库中。

希望我的描述不会太混乱=P 感谢您的阅读。

I need some opinions on choosing which signatures for my web based business layer function:

function void CreateUser(Company UserCompany, string name...)

or

function void CreateUser(int CompanyID, string name...)

If this is a window based I would choose function to take object instead of int because since the company already loaded to the window form, why not just utilize it. Also, I think business layer should take business objects and it's type safe(preventing accidently pass in 0 or -1).

But on the other hand, if this is a web based application, only id will be loaded to client sites. So it's kind of redundant to load company object because eventually only companyID will be saved in the dabasebase anyway.

Hopefully my description is not too confusing =P
Thank you for reading.

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

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

发布评论

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

评论(1

橘虞初梦 2024-10-01 17:59:29

我认为您回答了自己的问题,这取决于您使用的表示层。但是,当您想要保持此业务层通用时,您必须使用 ID。

这是另一个想法。我个人喜欢将所有突变包装到类中,我称之为命令。例如,您可以有一个从基本命令继承的CreateUserCommand。这将允许您像这样使用它(我在这里假设 C#):

var command = new CreateUserCommand();

command.UserCompanyId = companyId;
command.UserName = name;

command.Execute();

将此逻辑包装在命令中是非常好的模式。它允许您将单个用例放入单个命令中。特别是当命令中的逻辑量增加时,您会欣赏这种模式,但我发现它对于 CRUD 操作也非常有效。

此模式还允许您在基类中抽象事务模型。基类可以包装调用以在数据库事务中执行。这是一个简单的实现:

public abstract class CommandBase
{
    public void Execute()
    {
        this.Validate();

        using (var conn = ContextFactory.CreateConnection())
        {
            conn.Open();
            using (var transaction = conn.BeginTransaction())
            {
                using (var db = ContextFactory.CreateContext(conn))
                {
                    this.ExecuteInternal(db);

                    db.SubmitChanges();
                }

                transaction.Commit();
            }
        }
    }

    protected virtual void Validate() { }

    protected abstract void ExecuteInternal(YourDataContext context);
}

这就是 CreateUserCommand 的样子:

public class CreateUserCommand : CommandBase
{
    public int UserCompanyId { get; set; }
    public string UserName { get; set; }

    protected override void ExecuteInternal(YourDataContext context)
    {
       this.InsertNewUserInDatabase(context);
       this.ReportCreationOfNewUser();
    }

    protected override void Validate()
    {
        if (this.UserCompanyId <= 0) 
            throw new InvalidOperationException("Invalid CompanyId");
        if (string.IsNullOrEmpty(this.UserName))
            throw new InvalidOperationException("Invalid UserName");
    }

    private void InsertNewUserInDatabase(YourDataContext context)
    {
       db.Users.InsertOnSubmit(new User()
       {
          Name = this.UserName,
          CompanyId = this.CompanyId
       });
    }

    private void ReportCreationOfNewUser()
    {
        var message = new MailMessage();
        message.To = Configuration.AdministratorMailAddress;
        message.Body = "User " + this.Name + " was created.";

        new SmtpClient().Send(message);
    }
}

我希望这会有所帮助。

I think you answered your own question, it depends on the presentation layer you're using. But when you want to keep this business layer generic, you'll have to go with the ID.

Here's another idea. I personally like to wrap all mutations into classes, that I call commands. You could for instance have an CreateUserCommand that inherits from a base command. This would allow you to use it like this (I'm assuming C# here):

var command = new CreateUserCommand();

command.UserCompanyId = companyId;
command.UserName = name;

command.Execute();

When wrapping this logic in a command is very nice pattern. It allows you to put a single use case in a single command. Especially when the amount of logic in a command grows you will appreciate this pattern, but I found it to be very effective for CRUD operations as well.

This pattern also allows you to abstract the transactional model away in the base class. The base class can wrap a call to execute in a database transaction. Here is an simple implementation:

public abstract class CommandBase
{
    public void Execute()
    {
        this.Validate();

        using (var conn = ContextFactory.CreateConnection())
        {
            conn.Open();
            using (var transaction = conn.BeginTransaction())
            {
                using (var db = ContextFactory.CreateContext(conn))
                {
                    this.ExecuteInternal(db);

                    db.SubmitChanges();
                }

                transaction.Commit();
            }
        }
    }

    protected virtual void Validate() { }

    protected abstract void ExecuteInternal(YourDataContext context);
}

And this is what the CreateUserCommand would look like:

public class CreateUserCommand : CommandBase
{
    public int UserCompanyId { get; set; }
    public string UserName { get; set; }

    protected override void ExecuteInternal(YourDataContext context)
    {
       this.InsertNewUserInDatabase(context);
       this.ReportCreationOfNewUser();
    }

    protected override void Validate()
    {
        if (this.UserCompanyId <= 0) 
            throw new InvalidOperationException("Invalid CompanyId");
        if (string.IsNullOrEmpty(this.UserName))
            throw new InvalidOperationException("Invalid UserName");
    }

    private void InsertNewUserInDatabase(YourDataContext context)
    {
       db.Users.InsertOnSubmit(new User()
       {
          Name = this.UserName,
          CompanyId = this.CompanyId
       });
    }

    private void ReportCreationOfNewUser()
    {
        var message = new MailMessage();
        message.To = Configuration.AdministratorMailAddress;
        message.Body = "User " + this.Name + " was created.";

        new SmtpClient().Send(message);
    }
}

I hope this helps.

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