清洁架构:遥不可及的理想——给开发者的寓言

清洁架构:遥不可及的理想——给开发者的寓言

在西藏宁静的山区高处,一座古老寺院安静的大厅里,住着一位年轻的学徒。他致力于追求和谐——不仅在他自己内部,而且在他的编程技巧中。他的目标是创建一个完美的应用程序,一个能够体现清洁架构深刻原理的应用程序,就像山间溪流的清澈一样。但他意识到这条道路的艰辛,于是向一位可敬的明师寻求智慧。

徒弟谦卑地走近师父问道

—“噢,明智的师父,我已经构建了一个应用程序来管理购买。我的建筑干净纯粹吗?”

师父耐心地观察弟子,回答道:

—“向我展示你所创造的东西,我们将一起辨别真相。”

学徒展示了他的作品,其中数据库逻辑和用例流程交织在一起——业务逻辑与技术框架紧密地交织在一起,就像一张错综复杂的网中的线。

// app.tsimport sqlite3 from 'sqlite3';import { open, database } from 'sqlite';interface purchase {    id: number;    title: string;    cost: number;}async function initializedatabase(): promise {    const db = await open({        filename: ':memory:',        driver: sqlite3.database,    });    await db.exec(`    create table purchases (      id integer primary key,      title text,      cost real    )  `);    return db;}async function addpurchaseifcan(db: database, purchase: purchase): promise {    const { id, title, cost } = purchase;    const row = await db.get(        `select sum(cost) as totalcost from purchases where title = ?`,        [title]    );    const totalcost = row?.totalcost || 0;    const newtotalcost = totalcost + cost;    if (newtotalcost  {    const db = await initializedatabase();    await addpurchaseifcan(db, { id: 3, title: 'rice', cost: 2 });})();

登录后复制

大师思考代码后说道:

——“你的代码就像一条河流,目的的清水与实现的泥浆混合在一起。业务和技术问题本应分开进行,但它们已合而为一。为了在你的建筑中实现真正的纯粹,你必须将它们分开,就像天空与大地分开一样。”

道路上的第一步

听从师父的话,徒弟开始着手重构他的代码。他开始分离各层,在数据库和业务逻辑流之间划出明显的界限。他还引入了接口,使他的代码与依赖倒置原则保持一致,这是清洁架构的神圣教义之一。现在,他的应用不再依赖于具体的实现,而是依赖于思想的抽象。

// app.tsimport { initializedatabase } from './db/init';import { purchaserepository } from './db/purchaserepository';import { addpurchaseifcan } from './usecases/addpurchaseifcan';(async () => {  const db = await initializedatabase();  const purchaserepository = new purchaserepository(db);  await addpurchaseifcan(purchaserepository, { id: 3, title: 'rice', cost: 2 });})();

登录后复制

// usecases/addpurchaseifcan.tsimport { ipurchaserepository, purchase } from './ipurchaserepository';export async function addpurchaseifcan(  purchaserepository: ipurchaserepository,  purchase: purchase): promise {  const { id, title, cost } = purchase;  const totalcost = await purchaserepository.gettotalcostbytitle(title);  const newtotalcost = totalcost + cost;  if (newtotalcost < 99999) {    await purchaserepository.add(purchase);    console.log('purchase added successfully.');  } else {    console.log('total cost exceeds 99999.');  }}

登录后复制

// usecases/ipurchaserepository.tsexport interface ipurchaserepository {  add(purchase: purchase): promise;  gettotalcostbytitle(title: string): promise;}export interface purchase {  id: number;  title: string;  cost: number;}

登录后复制

// db/init.tsimport sqlite3 from 'sqlite3';import { open, database } from 'sqlite';export async function initializedatabase(): promise {  const db = await open({    filename: ':memory:',    driver: sqlite3.database,  });  await db.exec(`    create table purchases (      id integer primary key,      title text,      cost real    )  `);  return db;}

登录后复制

// db/purchaserepository.tsimport { database } from 'sqlite';import { ipurchaserepository, purchase } from 'usecases/ipurchaserepository';export class purchaserepository implements ipurchaserepository {  private db: database;  constructor(db: database) {    this.db = db;  }  async add(purchase: purchase): promise {    const { id, title, cost } = purchase;    await this.db.run(      `insert into purchases (id, title, cost) values (?, ?, ?)`,      [id, title, cost]    );    return purchase;  }  async gettotalcostbytitle(title: string): promise {    const row = await this.db.get(      `select sum(cost) as totalcost from purchases where title = ?`,      [title]    );    const totalcost = row?.totalcost || 0;    return totalcost;  }}

登录后复制

徒弟回到师傅并问道:

——“我已经为我的存储库分离了各层并使用了接口。我的建筑现在干净了吗?”

大师再次检查代码,回复:

——“你们已经向前迈出了一步,但总成本的计算仍然停留在基础设施上,它不属于那里。这不是这种智慧应该存在的地方。总成本的知识属于商业领域,而不是地球上的工具。将其移至用例中,过程的智慧可以保持其纯粹性。”

分离的教训

有了这种洞察力,学徒意识到总成本的计算是业务逻辑的一部分。他再次重构了代码,将逻辑转移到用例中,使业务问题不受技术基础设施的影响。

// usecases/ipurchaserepository.tsexport interface ipurchaserepository {  add(purchase: purchase): promise;-  gettotalcostbytitle(title: string): promise;+  getpurchasesbytitle(title: string): promise;}...

登录后复制

// usecases/addpurchaseifcan.tsimport { ipurchaserepository, purchase } from './ipurchaserepository';export async function addpurchaseifcan(  purchaserepository: ipurchaserepository,  purchasedata: purchase,  limit: number): promise {  const { id, title, cost } = purchasedata;  const purchases = await purchaserepository.getpurchasesbytitle(title);  let totalcost = 0;  for (const purchase of purchases) {    totalcost += purchase.cost;  }  const newtotalcost = totalcost + cost;  if (newtotalcost >= limit) {    console.log(`total cost exceeds ${limit}.`);  } else {    await purchaserepository.add(purchasedata);    console.log('purchase added successfully.');  }}

登录后复制

// db/purchaserepository.tsimport { database } from 'sqlite';import { ipurchaserepository } from './ipurchaserepository';export class purchaserepository implements ipurchaserepository {  ...  async getpurchasesbytitle(title: string): promise {    const rows = await this.db.all(      `select * from purchases where title = ?`,      [title]    );    return rows.map((row) => ({      id: row.id,      title: row.title,      cost: row.cost,    }));  }}

登录后复制

再次回到师父身边,问道:

—“我已将总成本计算转移到用例中,并将业务逻辑与基础设施分开。我的建筑现在纯净了吗?”

师父带着温柔的微笑回答:

——“你已经取得了很大的进步,但要小心——就像山风带来冬天的寒冷一样,你的计算可能会带来隐藏的错误。 javascript 的算术就像新手的思维一样,在处理大数或小数时可能会不精确。”

与无常的相遇

学徒明白javascript中浮点运算的缺陷可能会导致微妙但危险的错误。他修改了代码,转向更可靠的工具,一个专为精确计算而设计的库,寻求工作的清晰度。

// usecases/addpurchaseifcan.ts+ import decimal from 'decimal.js';import { ipurchaserepository, purchase } from './ipurchaserepository';export async function addpurchaseifcan(  purchaserepository: ipurchaserepository,  purchasedata: purchase,  limit: number): promise {  const { id, title, cost } = purchasedata;  const purchases = await purchaserepository.getpurchasesbytitle(title);  let totalcost = new decimal(0);  for (const purchase of purchases) {-    totalcost += purchase.cost;+    totalcost = totalcost.plus(purchase.cost);  }- const newtotalcost = totalcost + cost;+ const newtotalcost = totalcost.plus(cost);- if (newtotalcost >= limit) {+ if (newtotalcost.greaterthanorequalto(limit)) {    console.log(`total cost exceeds ${limit}.`);  } else {    await purchaserepository.add(purchasedata);    console.log('purchase added successfully.');  }}

登录后复制

他再次问师父:

—“我已经改进了我的计算,使用了更好的工具来避免错误。我的建筑现在达到纯粹了吗?”

上人目光坚定如山,答道:

——“你做得很好,但你的架构仍然受到束缚。您的业​​务逻辑现在取决于这个新工具decimal.js的详细信息。如果有一天你需要改变这个工具,你的逻辑基础就会动摇。真正的纯洁是摆脱这种束缚。”

依赖倒置的智慧

认识到大师话语的深度,学徒试图将他的代码从这种执着中解放出来。他抽象了算术运算,颠倒了依赖关系,这样他的业务逻辑就不再依赖于任何一种工具。

// usecases/calculator.tsexport abstract class calculator {  abstract create(a: number): calculator;  abstract add(b: calculator | number): calculator;  abstract greaterthanorequal(b: calculator | number): boolean;}

登录后复制

// usecases/addpurchaseifcan.ts+ import { calculator } from 'usecases/calculator';- import decimal from 'decimal.js';import { ipurchaserepository, purchase } from './ipurchaserepository';

登录后复制

// decimalcalculator.tsimport decimal from 'decimal.js';import { calculator } from 'usecases/calculator.ts';export class decimalcalculator extends calculator {  private value: decimal;  constructor(value: number | decimal) {    super();    this.value = new decimal(value);  }  create(a: number): calculator {    return new decimalcalculator(a);  }  add(b: calculator | number): calculator {    return new decimalcalculator(this.value.plus(b.value));  }  greaterthanorequal(b: calculator | number): boolean {    return this.value.greaterthanorequalto(b.value);  }}

登录后复制

// useCases/addPurchaseIfCan.tsimport { Calculator } from 'useCases/calculator';import { IPurchaseRepository, Purchase } from './IPurchaseRepository';export class addPurchaseIfCan {  private purchaseRepository: IPurchaseRepository;  private calculator: Calculator;  private limit: string;  constructor(    purchaseRepository: IPurchaseRepository,    calculator: Calculator,    limit: number  ) {    this.purchaseRepository = purchaseRepository;    this.calculator = calculator;    this.limit = limit.toString();  }  async execute(purchaseData: Purchase): Promise {    const { id, title, cost } = purchaseData;    const purchases = await this.purchaseRepository.getPurchasesByTitle(title);    let totalCost = this.calculator.create(0);    for (const purchase of purchases) {      totalCost.add(purchase.cost);    }    totalCost = totalCost.add(cost);    if (totalCost.greaterThanOrEqual(this.limit)) {      console.log(`Total cost exceeds ${limit}.`);    } else {      await this.purchaseRepository.add({        id,        title,        cost: parseFloat(cost.toString()),      });      console.log('Purchase added successfully.');    }  }}

登录后复制

最后一次回到师父身边,他问道:

——“我使用依赖倒置抽象了我的操作,确保我的业务逻辑不再与实现绑定。我的建筑现在真的干净了吗?”

师父开示:

——“这条路上你已经走得很远了。但请记住,即使您努力追求纯度,您的用例仍然取决于编写它们的语言。您现在使用的是 javascripttypescript,但有一天这些工具可能会消失。当那一天到来时,你会用新的语言重建一切吗?”

拥抱不完美

学徒对此感到困惑,问道:

——“大师,如果我的用例总是与编写它们的语言联系在一起,我怎样才能在我的架构中实现完美的整洁?”

师父带着理解的柔和微笑回答:

——“就像鸟儿无法离开天空一样,建筑也不能完全脱离其创作的工具。真正的独立是一个崇高的梦想,但却是遥不可及的。然而,对它的追求会给你的建筑带来和谐。 清洁架构的目标不是摆脱所有依赖性,而是创建一个轻松应对变化的系统,并将商业智慧与地球运作分开。理解这种平衡是获得真正智慧的关键。”

学徒,感受到他内心的理解黎明之光,说道:

——“谢谢师父。现在我发现完美不是孤立的,而是责任和目标的和谐。”

师父从座位上站起来,回答:

——“放心吧,学徒。你的旅程才刚刚开始,但你已经找到了自己的路。”

结语

随着时间的流逝,学徒注意到他的应用程序开始变慢。他很困惑,想知道一个曾经运行得如此顺利的系统现在如何在执行任务时陷入困境。

很明显,问题不在于代码的大小不断增长,而在于总成本计算是在数据库外部进行的。该应用程序花费了大量的精力来传输大量数据,只是为了执行本可以在源头完成的任务。如果计算是在数据库内完成的,则无需在层之间发送数千条记录,并且性能仍将保持强劲。

徒弟想向师父询问此事,但师父已经消失,问题一直没有答案。

望着寂静的寺院,徒弟拿起一本新书,微笑着说道:

—“看来我的启蒙之路给我带来了新的挑战 – 性能优化的艺术。”

以上就是清洁架构:遥不可及的理想——给开发者的寓言的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2664484.html

(0)
上一篇 2025年3月7日 11:39:14
下一篇 2025年3月5日 15:12:45

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 使用 Deno 制作您的第一个项目

    为了介绍这个话题,我们先来定义一下什么是 deno。 deno 是 javascript、typescript 和 webassembly 的运行时环境,由 node.js 的创建者 ryan dahl 开发。它使用 chrome 的 v8…

    2025年3月7日
    200
  • 使用 React 构建租赁物业管理平台

    movin’ in 是一个面向代理的租赁物业管理平台,具有用于管理物业、客户和预订的后端、用于租赁物业的前端和移动应用程序。 通过以下解决方案,您可以通过将其托管在具有至少 1GB RAM 的 Docker Droplet 上,…

    2025年3月7日
    200
  • GitHub Actions 和 CI/CD 管道

    当然!以下是与 github actions 和 ci/cd 管道相关的关键概念和实践的全面摘要,以及我们讨论的示例: github actions 和 ci/cd 管道的关键概念 持续集成(ci): ci 涉及自动构建和测试代码更改,以确…

    2025年3月7日
    200
  • JavaScript JSSSugar 提案、Nodejs Nextjs RCnd 更多

    欢迎来到本周的“本周 JavaScript”! 我们为您提供了一系列令人兴奋的更新,包括关于拆分 JavaScript 的有争议的提案、最新的 Node.js 版本、一些杀手级工具等等。所以系好安全带,让我们开始吧! JavaScript …

    2025年3月7日
    200
  • typescript配置

    要配置 TypeScript,请使用 tsconfig.json 文件:指定目标 JavaScript 版本、模块系统和输出目录。设置类型检查规则,包括严格模式、隐式 “this” 和未使用的局部变量检查。根据需要添…

    2025年3月7日
    200
  • typescript进阶教学

    TypeScript 进阶特性包括:接口:定义契约,强制实现者提供指定方法和属性。泛型:创建可复用代码,可在不同类型值上操作。装饰器:注入额外逻辑到类、方法或属性声明前后。枚举:创建具名常量组。模块化:将代码组织成独立模块,使用 expor…

    2025年3月7日
    200
  • typescript高级用法

    高级 TypeScript 特性包括类型泛型、接口、类和继承、模块和名称空间、装饰器、异步编程以及高级类型系统,可通过联合类型、元组和枚举实现更精确的类型。这些特性增强了 TypeScript 的可重用性、可维护性和可扩展性。 TypeSc…

    2025年3月7日
    200
  • typescript入门版教程_typescript新人入门版详细教程

    TypeScript是一种Microsoft开发的编程语言,在JavaScript的基础上增加了类型系统和面向对象编程功能。它能提供类型安全、可维护性、可扩展性和开发效率提升等优点。具体入门步骤为:安装TypeScript编译器、创建项目、…

    2025年3月7日
    200
  • typescript 多类型

    TypeScript 允许为变量和函数参数定义明确类型,以提高代码健壮性、简化维护和改善 IDE 支持。主要数据类型包括:基本类型(布尔、数字、字符串、空值、未定义)联合类型(允许多种类型)元组(有序且类型不同的元素) TypeScript…

    2025年3月7日
    200
  • typescript 方法重载

    TypeScript 中的方法重载允许在同一类中创建具有相同名称但不同参数的方法,通过签名实现,根据参数类型选择实现。签名:定义方法参数类型和返回值类型。调用:根据提供的参数类型选择最合适实现。优点:代码可读性灵活性和代码重用 TypeSc…

    2025年3月7日
    200

发表回复

登录后才能评论