在软件开发中,创建与业务需求紧密相关的健壮且可维护的应用程序是一项持续的挑战。领域驱动设计(DDD)通过将领域置于开发过程的核心,为解决这一挑战提供了有效的策略。DDD能够使开发人员创建出高度可扩展、模块化且面向业务的解决方案。本文将探讨在DDD中应用生成式AI的潜力。

实验概述

在一项实验中,我们开发了一个时间跟踪应用程序,利用生成式AI工具来探索其在软件工程中的能力和局限。通过OpenAI的Python聊天完成API,我们为应用程序生成了领域模型和服务API。这一API允许开发人员与模型交互,应用提示工程技术,并创建与语言模型和相关工具无缝交互的有效提示。

DDD技术

在DDD中,有几种技术对于开发鲁棒的领域模型至关重要:

  • 实体关系建模:帮助可视化和记录领域中实体与值对象之间的关系和依赖性,确保对结构的清晰理解。
  • 边界上下文识别:为每个子域定义边界上下文,限制每个子域的功能。
  • 域服务:处理复杂的操作或协调实体间的交互,为业务逻辑提供集中的位置。

领域模型开发步骤

  1. 识别并定义代表高级业务目标的史诗。
  2. 将史诗分解为更小的用户故事,提高可管理性。
  3. 分析用户故事,识别不同子域。
  4. 创建上下文图,可视化子域间的关系。
  5. 定义边界上下文,表示具有特定模型和概念的隔离区域。
  6. 优化域模型,包括基本实体、关系、行为和域服务。
  7. 与领域专家合作,验证和调整模型。
  8. 迭代模型,确保其符合业务需求。
  9. 开发领域模型图、ER图和服务API定义,帮助团队开发。 有关实验中使用的方法和工具的更多详细信息,请查阅文档

DDD 方法与生成式 AI 的结合应用

一、生成长篇故事和用户故事在时间跟踪应用程序的开发过程中,我们利用生成式人工智能技术,实现了以下步骤的自动化:

  1. 故事生成:AI 根据给定的提示,创造性地生成长篇故事和用户故事。2. 内容整合:将生成的故事与应用程序的功能和需求紧密结合,确保故事的实用性和相关性。3. 用户反馈:收集用户对生成故事的反馈,以优化和调整 AI 的生成策略。

二、识别领域模型在进一步的开发中,我们通过以下步骤定义了领域模型:

  1. 子域分析:使用 OpenAI 聊天完成端点的应用程序,分析并识别应用程序的子域。2. 上下文映射:创建上下文映射,以明确不同子域之间的关系和边界。3. 边界上下文定义:定义每个子域的边界上下文,以帮助理解它们在整体系统中的角色和职责。

三、生成域模型利用从子域分析中得到的域上下文响应(变量:domain_context_response),我们进一步通过以下步骤生成域模型:

  1. 生成提示定义:创建一个用于生成域模型的提示(变量:domain_model_prompt)。2. 模型生成:根据提示,AI 生成符合 DDD 原则的领域模型。3. 模型验证:验证生成的模型是否满足业务需求,并进行必要的调整。 通过上述步骤,我们不仅提高了开发效率,还确保了应用程序的质量和可维护性。
<span id="b998" data-selectable-paragraph="">  
domain_model_prompt = f"""  
Epics and User Story list of application: ```  
<span>{epics_story_response}</span>  

Domain Context = ```
{domain_context_response}

  
Your task is to analyse the product epics, story list, and domain context in   
detail and generate the following :  
1. Using Domain Driven Design techniques, Identify the Entities, Value Objects with list  
of attributes and behaviours for each.  
2. List the services, repositories, etc. required for the application.   
  
"""  
domain_model_response = get_completion(domain_model_prompt)
<span id="7f4a" data-selectable-paragraph="">Domain Model Entities and Value Objects:  
User:  
 - Attributes: id, name, email, password, role  
 - Behaviours: register, login, reset password  
Project:  
 - Attributes:id, name, description, client  
 - Behaviours: create, update, delete  
Task:  
 - Attributes: id, name, description, project  
 - Behaviours: create, update, delete   
Time Entry:  
 - Attributes: id, user, project, task, start_time, end_time, notes  
 - Behaviours: create, update, delete  
Report:  
 - Attributes: id, project, task, employee, date range  
 - Behaviours: generate, customise  
Invoice:  
 - Attributes: id, client, project, billing_rate, payment_terms, status  
 - Behaviours: create, customise, preview, send

生成 ER 图和域模型图

带有域模型上下文的完整响应被传递到提示中,以生成域模型和 ER 图 PlantUML 代码。生成的 PlantUML 代码可以复制粘贴到 PlantUML 编辑器中,例如 PlantText (https://www.planttext.com),生成非常详细的域模型图)以及所需的域服务和存储库。

根据 PlantUML 代码为应用程序生成的 ER 图:

在域模型中识别的实体及其属性非常适合解决手头的问题陈述。实体的行为或行动符合问题陈述中指定的要求和功能。

生成 RESTful API 设计

带有域模型上下文的完整响应进一步传递到提示中,用于生成带有 yaml 中 OpenAPI 文档的服务 API 端点。

<span id="04c3" data-selectable-paragraph=""> service_api_endpoints_prompt = f"""  
 Epics and User Story list for the application : ```  
<span>{story_response}</span>  

Domain Model = ```
{domain_model_response}

  
 Your task is to analyse the entities and services listed in the domain model  
 and generate:  
  1. List the RESTful service API endpoints for the application.  
  2. Generate OpenAPI documentation in YAML for the services.  
 """  
 service_api_endpoints_response = get_completion(service_api_endpoints_prompt)

服务 API 的响应包含所需服务和 restful 端点的列表。在设计 restful API 时要记住的最佳实践之一是使用名词而不是动词。HTTP 谓词已在生成的 API 端点中正确使用。
关于如何参数化和使用 API 的详细信息也相当不错。一些端点:

<span id="b9ea" data-selectable-paragraph=""> Project:  
   - GET /projects/{id}  
   - GET /projects?client={client}  
 Task:  
   - GET /tasks?project={project}  
 Time Entry:  
   - GET /time-entries?user={user}&amp;project={project}  
 Report:  
   - GET /reports?project={project}&amp;task={task}&amp;employee={employee}&amp;start_date={start_date}&amp;end_date={end_date}

我们能够使用 editor.swagger.io 生成 swagger 文档。

 洞察与挑战

合并这些提示不会产生令人满意的结果,从而导致结果被截断并丢失预期信息。提示必须清晰具体。
例如:最初,在生成服务 API 的提示中,提示指令并未提及“RESTful 服务 API 端点”,这导致端点是 RPC 风格的方法(请参阅下面的 API 列表)。

<span id="ec16" data-selectable-paragraph="">AuthService API:  
    registerUser(userDetails)  
    loginUser(email, password)  
    resetPassword(email)  
      
UserService API:  
    getUserById(userId)  
    updateUser(userId, userDetails)  
    deleteUser(userId)  
  
ProjectService API:  
    createProject(projectDetails)  
    getProjectById(projectId)  
    getProjectsByClient(clientId)  
    updateProject(projectId, projectDetails)  
    deleteProject(projectId)  
........

在设计域名时,清晰的指导原则对于生成有效的响应至关重要。这通常需要通过迭代实验来不断优化和完善提示,以确保它们能够指导语言模型(LLM)提供准确的输出。以下是对这一过程的详细描述:

迭代实验的重要性- 定义明确的领域模型:在简单的案例中,我们能够快速获得一个清晰定义的领域模型。- 复杂领域的挑战:在更复杂的领域中,可能需要采用迭代方法,逐步为LLM提供更详细的领域上下文。

域名设计过程的加速- 交付速度:通过迭代方法,可以加快产品或服务的交付速度。- 利益相关者价值:通过这种方式,可以增加利益相关者的价值创造。- 结构化设计方法:促进了一种结构化和系统的领域设计方法。- 开发生命周期效率:提高了整个开发生命周期的效率和有效性。

OpenAPI与OpenAI的结合- OpenAPI框架:在OpenAPI框架中使用OpenAI的聊天完成端点。- 开发人员的工具:这种方法被证明是开发人员在域名设计过程中的宝贵工具。

开发人员的角色- 设计思维的应用:开发人员必须应用设计思维来指导和验证工具的输出。- 领域专业知识:同时,也需要利用自己的领域专业知识来改进生成的输出。

注意事项- 生成式AI工具的限制:虽然生成式AI工具功能强大,但它们不能替代人类的创造力和专业知识。- 验证与改进:开发人员应验证并不断改进这些工具生成的输出,以确保其质量和适用性。