css 六角形

A hexagonal  architecture simplifies deferring or changing technology decisions. You  want to change to a different framework? Write a new adapter. You want  to use a database, instead of storing data in files? Again, write an  adapter for it.

六角形的体系结构简化了推迟或更改技术决策的过程。 您想更改为其他框架吗? 编写一个新的适配器。 您要使用数据库,而不是将数据存储在文件中? 同样,为其编写适配器。

Draw a boundary around the business logic. The hexagon. Anything inside the hexagon must be free from technology concerns. The  outside of the hexagon talks with the inside only by using interfaces,  called ports. Same the other way around. By changing the implementation  of a port, you change the technology.

围绕业务逻辑绘制边界。 六角形。 六角形内的任何东西都必须没有技术上的顾虑。 六边形的外部仅通过使用称为端口的接口与内部对话。 反之亦然。 通过更改端口的实现,可以更改技术。

Isolating  business logic inside the hexagon has another benefit. It enables  writing fast, stable tests for the business logic. They do not depend on  web technology to drive them, for example.

在六边形内部隔离业务逻辑还有另一个好处。 它使您能够为业务逻辑编写快速,稳定的测试。 例如,它们不依赖于网络技术来驱动它们。

Here’s  an example diagram. It shows Spring MVC technology as boxes with dotted  lines, ports and adapters as solid boxes, and the hexagon without its  internals:

这是一个示例图。 它将Spring MVC技术显示为带有虚线框,端口和适配器的显示为实心框,而六角形没有内部显示:

An adapter translates between a specific technology and a technology free port. The PoemController adapter on the left receives requests and sends commands to the IReactToCommands port. The PoemController is a regular Spring MVC Controller. Because it actively uses the port, it's called a driver adapter.

适配器在特定技术和技术自由端口之间转换。 左侧的PoemController适配器接收请求并将命令发送到IReactToCommands端口。 PoemController是常规的Spring MVC控制器。 由于它主动使用端口,因此称为驱动程序适配器。

IReactToCommands is called a driver port. Its implementation is inside the hexagon. It's not shown on the diagram.

IReactToCommands称为驱动程序端口。 它的实现位于六边形内部。 该图未显示。

On the right side, the SpringMvcPublisher adapter implements the IWriteLines port. This time, the hexagon calls the adapter through the port. That's why SpringMvcPublisher is called a driven adapter. And IWriteLines is called a driven port.

在右侧, SpringMvcPublisher适配器实现IWriteLines端口。 这次, 六角形通过端口调用适配器。 这就是为什么SpringMvcPublisher被称为驱动适配器的原因。 IWriteLines称为从动端口。

I show you how to implement that application. We go all the way from a  user story to a domain model inside the hexagon. We start with a simple  version of the application that prints to the console. Then we switch  to Spring Boot and Spring MVC.

我向您展示了如何实现该应用程序。 我们从用户故事一直到六边形内部的域模型。 我们从打印到控制台的应用程序的简单版本开始。 然后我们切换到Spring Boot和Spring MVC。

从用户案例到端口和适配器 (From a user story to ports & adapters)

The company FooBars.io decides to build a Poetry App. The product owner and the developers agree on the following user story:

FooBars.io公司决定构建一个诗歌应用程序。 产品所有者和开发人员就以下用户故事达成了共识:

As a readerI want to read at least one poem each daySo that I thrive as a human being

作为读者,我每天至少要读一首诗,这样我才能像人类一样being壮成长

As acceptance criteria, the team agrees on:

作为接受标准,团队同意:

  • When the user asks for a poem in a specific language, the system displays a random poem in that language in the console当用户要求使用特定语言的诗歌时,系统会在控制台中显示该语言的随机诗歌
  • It's ok to "simulate" the user at first, i.e. no real user interaction. (This will change in future versions.)首先可以“模拟”用户,即没有真正的用户交互是可以的。 (这将在将来的版本中更改。)
  • Supported languages: English, German支持的语言:英语,德语

The developers meet and draw the following diagram:

开发人员见面并绘制下图:

So the SimulatedUser sends commands to the IReactToCommands port. It asks for poems in English and German. Here's the code, it's available on Github.

因此, SimulatedUser将命令发送到IReactToCommands端口。 它要求用英语和德语写诗。 这是代码,可以在Github上找到 。

poem/simple/driver_adapter/SimulatedUser.java

诗/简单/ driver_adapter / SimulatedUser.java

public class SimulatedUser {private IReactToCommands driverPort;public SimulatedUser(IReactToCommands driverPort) {this.driverPort = driverPort;}public void run() {driverPort.reactTo(new AskForPoem("en"));driverPort.reactTo(new AskForPoem("de"));}
}

The IReactToCommands port has only one method to receive any kind of command.

IReactToCommands端口只有一种方法可以接收任何类型的命令。

poem/boundary/driver_port/IReactToCommands.java

poem / boundary / driver_port / IReactToCommands.java

public interface IReactToCommands{void reactTo(Object command);
}

AskForPoem is the command. Instances are simple, immutable POJOs. They carry the language of the requested poem.

AskForPoem是命令。 实例是简单的,不变的POJO。 它们带有所要求的诗歌的语言。

poem/command/AskForPoem.java

诗/命令/ AskForPoem.java

public class AskForPoem {private String language;public AskForPoem(String language) {this.language = language;}public String getLanguage() {return language;}
}

And that's it for the left, driver side of the hexagon. On to the right, driven side.

这就是六角形的左侧,驾驶员侧。 在右侧,从动侧。

When the SimulatedUser asks the IReactToCommands port for a poem, the hexagon:

SimulatedUserIReactToCommands端口询问一首诗时,六边形为:

  1. Contacts the IObtainPoems port for a collection of poems

    联系IObtainPoems端口以获取诗集

  2. Picks a random poem from the collection从收藏中挑选一首随机诗
  3. Tells the IWriteLines port to write the poem to the output device

    告诉IWriteLines端口IWriteLines首诗写到输出设备

You can't see Step 2 yet. It happens inside the hexagon, in the  domain model. That's the business logic of the example. So we focus on  Step 1 and Step 3 first.

您还看不到步骤2。 它发生在域模型中的六边形内部。 这就是示例的业务逻辑。 因此,我们首先关注步骤1和步骤3。

In Step 1, the collection of poems is a language dependent, hard coded array. It's provided by the HardcodedPoemLibrary adapter that implements the IObtainPoems port.

在步骤1中,诗集是一种与语言相关的硬编码数组。 它是由提供HardcodedPoemLibrary适配器实现IObtainPoems端口。

poem/boundary/driven_port/IObtainPoems.java

poem / boundary / driven_port / IObtainPoems.java

public interface IObtainPoems {String[] getMePoems(String language);
}

poem/simple/driven_adapter/HardcodedPoemLibrary.java

诗/简单/ driven_adapter / HardcodedPoemLibrary.java

public class HardcodedPoemLibrary implements IObtainPoems {public String[] getMePoems(String language) {if ("de".equals(language)) {return new String[] { /* Omitted for brevity */ };} else { return new String[] { /* Omitted for brevity */ };}}
}

In Step 3, the ConsoleWriter adapter writes the lines of the poems to the output device, i.e. the console.

在步骤3中, ConsoleWriter适配器将这些诗行写入输出设备(即控制台)。

poem/boundary/driven_port/IWriteLines.java

poem / boundary / driven_port / IWriteLines.java

public interface IWriteLines {void writeLines(String[] strings);
}

poem/simple/driven_adapter/ConsoleWriter.java

poem / simple / driven_adapter / ConsoleWriter.java

public class ConsoleWriter implements IWriteLines {public void writeLines(String[] lines) {Objects.requireNonNull(lines);for (String line : lines) {System.out.println(line);}System.out.println("");}
}

We have created all the ports, and a simple implementation of all the  adapters. So far, the inside of the hexagon remained a mystery. It's up  next.

我们创建了所有端口,并创建了所有适配器的简单实现。 到目前为止,六角形的内部仍然是个谜。 接下来。

命令处理程序(在六边形内) (Command handlers (inside the hexagon))

When a user asks for a poem, the system displays a random poem.Similar in the code: when the IReactToCommands port receives an AskForPoemcommand, the hexagon calls a DisplayRandomPoem command handler.

当用户要求一首诗时,系统会显示一首随机的诗。代码IReactToCommands :当IReactToCommands端口接收到AskForPoem命令时,六边形调用DisplayRandomPoem命令处理程序。

The DisplayRandomPoem command handler obtains a list of  poems, picks a random one and writes it to the output device. This is  exactly the list of steps we talked about in the last clause.

DisplayRandomPoem命令处理程序获取一首诗列表,随机选择一首诗并将其写入输出设备。 这正是我们在最后一个子句中讨论的步骤列表。

poem/boundary/internal/command_handler/DisplayRandomPoem.java

诗/边界/内部/command_handler/DisplayRandomPoem.java

public class DisplayRandomPoem implements Consumer<AskForPoem> {/* Omitted for brevity */@Overridepublic void accept(AskForPoem askForPoem) {List<Poem> poems = obtainPoems(askForPoem);Optional<Poem> poem = pickRandomPoem(poems);writeLines(poem);   }/* Rest of class omitted for brevity */
}

It's also the job of the command handler to translate between the domain model data and the data used in the port interfaces.

在域模型数据和端口接口中使用的数据之间进行转换也是命令处理程序的工作。

将命令绑定到命令处理程序 (Tying commands to command handlers)

In my implementation of a hexagonal architecture, there is only a single driver port, IReactToCommands. It reacts to all types of commands.

在六边形体系结构的实现中,只有一个驱动程序端口IReactToCommands 。 它对所有类型的命令作出React。

public interface IReactToCommands{void reactTo(Object command);
}

The Boundary class is the implementation of the IReactToCommands port. It creates a use case model using a library. The use case model maps each command type to a command handler. A ModelRunner runs the model and dispatches commands based on the use case model.

Boundary类是IReactToCommands端口的实现。 它使用库创建用例模型。 用例模型将每种命令类型映射到命令处理程序。 ModelRunner运行模型并根据用例模型调度命令。

poem/boundary/Boundary.java

poem / boundary / Boundary.java

poem/boundary/Boundary.javapublic class Boundary implements IReactToCommands {private static final Class<AskForPoem> asksForPoem = AskForPoem.class;private Model model;public Boundary(IObtainPoems poemObtainer, IWriteLines lineWriter) {model = buildModel(poemObtainer, lineWriter);}private Model buildModel(IObtainPoems poemObtainer, IWriteLines lineWriter) {// Create the command handler(s)DisplayRandomPoem displaysRandomPoem = new DisplayRandomPoem(poemObtainer, lineWriter);// With a use case model, map classes of command objects to command handlers.Model model = Model.builder().user(asksForPoem).system(displaysRandomPoem).build();return model;}@Overridepublic void reactTo(Object commandObject) {new ModelRunner().run(model).reactTo(commandObject);}
}

领域模型 (The domain model)

The domain model of the example doesn’t have very interesting functionality. The RandomPoemPicker picks a random poem from a list.

该示例的域模型没有非常有趣的功能。 RandomPoemPicker从列表中选择一首随机诗。

A Poem has a constructor that takes a String containing line separators, and splits it into verses.

一首诗具有一个构造函数,该构造函数接受包含行分隔符的String并将其拆分为诗歌。

The really interesting bit about the example domain model: it doesn’t  refer to a database or any other technology, not even by interface!

关于示例域模型的真正有趣的一点是:它甚至没有通过接口引用数据库或任何其他技术!

That means that you can test the domain model with plain unit tests. You don’t need to mock anything.

这意味着您可以使用普通单元测试来测试域模型。 您无需嘲笑任何东西。

Such a pure domain model is not a necessary property of an  application implementing a hexagonal architecture. But I like the  decoupling and testability it provides.

这样的纯域模型不是实现六边形体系结构的应用程序的必要属性。 但是我喜欢它提供的去耦和可测试性。

将适配器插入端口,就是这样 (Plug adapters into ports, and that's it)

A final step remains to make the application work. The application  needs a main class that creates the driven adapters. It injects them  into the boundary. It then creates the driver adapter,  for the boundary, and runs it.

剩下的最后一步是使应用程序正常工作。 该应用程序需要一个用于创建驱动适配器的主类。 它将它们注入边界。 然后,它为边界创建驱动程序适配器并运行它。

poem/simple/Main.java

诗/简单/ Main.java

public class Main {public static void main(String[] args) {new Main().startApplication();}private void startApplication() {// Instantiate driven, right-side adaptersHardcodedPoemLibrary poemLibrary = new HardcodedPoemLibrary();ConsoleWriter consoleWriter = new ConsoleWriter();// Inject driven adapters into boundaryBoundary boundary = new Boundary(poemLibrary, consoleWriter);// Start the driver adapter for the applicationnew SimulatedUser(boundary).run();}
}

And that's it! The team shows the result to the product owner. And  she's happy with the progress. Time for a little celebration.

就是这样! 团队将结果显示给产品负责人。 她对进度感到满意。 是时候进行一些庆祝了。

切换到Spring (Switching to Spring)

The team decides to turn the poem app into a web application. And to  store poems in a real database. They agree to use the Spring framework  to implement it.Before they start coding, the team meets and draws the following diagram:

团队决定将诗歌应用程序转换为Web应用程序。 并将诗歌存储在真实的数据库中。 他们同意使用Spring框架来实现它。在开始编码之前,团队见面并绘制了以下图表:

Instead of a SimulatedUser, there is a PoemController now, that sends commands to the hexagon.

现在有一个PoemController代替SimulatedUserPoemController命令发送到六边形。

poem/springboot/driver_adapter/PoemController.java

poem / springboot / driver_adapter / PoemController.java

@Controller
public class PoemController {private SpringMvcBoundary springMvcBoundary;@Autowiredpublic PoemController(SpringMvcBoundary springMvcBoundary) {this.springMvcBoundary = springMvcBoundary;}@GetMapping("/askForPoem")public String askForPoem(@RequestParam(name = "lang", required = false, defaultValue = "en") String language,Model webModel) {springMvcBoundary.basedOn(webModel).reactTo(new AskForPoem(language));return "poemView";}
}

When receiving a command, the PoemController calls springMvcBoundary.basedOn(webModel). This creates a new Boundary instance, based on the webModel of the request:

当收到命令时, PoemController调用springMvcBoundary.basedOn(webModel) 。 这将基于请求的webModel创建一个新的Boundary实例:

poem/springboot/boundary/SpringMvcBoundary.java

诗/ springboot / boundary / SpringMvcBoundary.java

public class SpringMvcBoundary {private final IObtainPoems poemObtainer;public SpringMvcBoundary(IObtainPoems poemObtainer) {this.poemObtainer = poemObtainer;}public IReactToCommands basedOn(Model webModel) {SpringMvcPublisher webPublisher = new SpringMvcPublisher(webModel);IReactToCommands boundary = new Boundary(poemObtainer, webPublisher);return boundary;}
}

The call to reactTo() sends the command to the boundary, as before. On the right side of the hexagon, the SpringMvcPublisher adds an attribute lines to the Spring MVC model. That's the value Thymeleaf uses to insert the lines into the web page.

reactTo()reactTo()的调用将命令发送到边界。 在六边形的右侧, SpringMvcPublisher向Spring MVC模型添加属性lines 。 那是Thymeleaf用来将行插入网页的值。

poem/springboot/driven_adapter/SpringMvcPublisher.java

诗/ springboot / driven_adapter / SpringMvcPublisher.java

public class SpringMvcPublisher implements IWriteLines {static final String LINES_ATTRIBUTE = "lines";private Model webModel;public SpringMvcPublisher(Model webModel) {this.webModel = webModel;}public void writeLines(String[] lines) {Objects.requireNonNull(lines);webModel.addAttribute(LINES_ATTRIBUTE, lines);}
}

The team also implements a PoemRepositoryAdapter to access the PoemRepository. The adapter gets the Poem objects from the database. It returns the texts of all poems as a String array.

该团队还实现了PoemRepositoryAdapter来访问PoemRepository 。 适配器从数据库获取Poem对象。 它以String数组的形式返回所有诗歌的文本。

poem/springboot/driven_adapter/PoemRepositoryAdapter.java

poem / springboot / driven_adapter / PoemRepositoryAdapter.java

public class PoemRepositoryAdapter implements IObtainPoems {private PoemRepository poemRepository;public PoemRepositoryAdapter(PoemRepository poemRepository) {this.poemRepository = poemRepository;}@Overridepublic String[] getMePoems(String language) {Collection<Poem> poems = poemRepository.findByLanguage(language);final String[] poemsArray = poems.stream().map(p -> p.getText()).collect(Collectors.toList()).toArray(new String[0]);return poemsArray;}
}

Finally, the team implements the Application class that sets up an example repository and plugs the adapters into the ports.

最后,该团队实现Application类,该类建立示例存储库并将适配器插入端口。

And that's it. The switch to Spring is complete.

就是这样。 到Spring的切换完成。

结论 (Conclusion)

There are many ways to implement a hexagonal architecture. I showed  you a straightforward approach that provides an easy to use, command  driven API for the hexagon. It reduces the number of interfaces you need  to implement. And it leads to a pure domain model.

有许多方法可以实现六边形体系结构。 我向您展示了一种简单的方法,该方法为六边形提供了易于使用的命令驱动的API。 它减少了您需要实现的接口数量。 这导致了纯领域模型。

If you want to get more information on the topic, read Alistair Cockburn’s original article on the subject.

如果您想获得有关该主题的更多信息,请阅读Alistair Cockburn关于该主题的原始文章 。

The example in this article is inspired by a three part series of talks by Alistair Cockburn on the subject.

本文中的示例受Alistair Cockburn关于该主题的三部分系列演讲的启发。

Last updated on 13 April 2020. If you want to keep up with what I’m doing or drop me a note, follow me on dev.to, LinkedIn or Twitter. Or visit my GitHub project. To learn about agile software development, visit my online course.

上次更新时间为2020年4月13日。如果您想跟上我的工作或给我 留言 ,请 dev.to LinkedIn Twitter 上关注我 或访问我的 GitHub项目 要了解敏捷软件开发的知识, 请访问我的在线课程

翻译自: https://www.freecodecamp.org/news/implementing-a-hexagonal-architecture/

css 六角形

css 六角形_实施六角形架构相关推荐

  1. 电脑端京东的我的订单html+css页面_互联网系统架构前后端分离技术体系

    点击「京东数科技术说」可快速关注 「摘要」随着互联网技术的发展以及终端设备的不断增多,前后端分离技术已成为移动互联网领域不可或缺的技术.前后端分离技术的不断完善,让前后端的分工与系统边界划分越来越清晰 ...

  2. bootstrap起步 全局css样式概览 全局css样式_栅格 全局css样式_排版

    http://www.bootcss.com/基本模板 https://v3.bootcss.com/getting-started/#template bootstrap起步 <!DOCTYP ...

  3. 鼠标指向变成英文导航(CSS)_网页代码站(www.webdm.cn)

    1 <title>鼠标指向变成英文导航(CSS)_网页代码站(www.webdm.cn)</title> 2 <style type="text/css&quo ...

  4. css案例_下拉三角翻转

    css案例_下拉三角翻转 css案例_下拉三角翻转常见于 下拉导航 .表单下拉多选 等场景. 原理:三角可以看成是一个只具有右边框和底部边框的方形盒子通过 transform: rotate(45de ...

  5. css网格_使用CSS网格构建的澳大利亚初创企业的周期表

    css网格 by Shooting Unicorns 通过射击独角兽 使用CSS网格构建的澳大利亚初创企业的周期表 (The Periodic Table of Australian Startups ...

  6. re.containerbase.startinternal 子容器启动失败_微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)...

    走过路过不要错过 点击蓝字关注我们 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程.平台提供基础设施.中间件 ...

  7. 用python绘制六角形_使用Python的turtle库实现六角形以及正方形螺旋线的绘制

    1.六角形的绘制 思路:一个六角形可以看作是两个等边三角形具有共同的中心且垂线互成60°角.所以只需实现一个等边三角形的绘制以及第二个三角形绘制起点的移动即可. 代码如下: import turtle ...

  8. 最常使用的css 工具_使用这些非常有用CSS工具更快地实施网站设计

    最常使用的css 工具 CSS is great for creating beautiful websites, but making sure that it works and looks th ...

  9. css餐厅_餐厅的评分预测

    css餐厅 描述 (Description) Restaurants from all over the world can be found here in Bengaluru. From Unit ...

最新文章

  1. MooTools教程(1):认识MooTools
  2. P1219 八皇后 含优化 1/5
  3. SVM(支持向量机)综述
  4. Python爬虫之旅_(数据解析)_Xpath
  5. WordPress函数:wp_nav_menu($args)函数说明
  6. 解决listview中的textview设置了setMovementMethod导致onItemclick无效的问题
  7. linux创建指定大小的文件
  8. linux 脚本1加到100,shell脚本之从1加到100之和的思路
  9. Solaris 添加删除 用户和组
  10. 启动go服务_使用Go构建TCP并发服务器,这种方式原来这么简单
  11. Windows下如何实现Ruby操作MongoDB(环境安装配置)
  12. SQL Server中追踪器Trace的介绍和简单使用
  13. VSTO 3.0 for Office 2007 Programming
  14. Croe文件在线预览
  15. 英特尔主板快捷启动键_BIOS里如何设置U盘启动?硬盘怎么设置第一启动项?
  16. 3.5.1_2 Maven - pom.xml 添加maven-assembly-plugin(官方标准打包插件)
  17. 社区团购猛地火了,有没有美团、拼多多这样的命?
  18. 静态网页项目开发基础
  19. [NOI2010] 航空管制 (构反图+拓扑)
  20. 成品APP直播源码HLS直播(M3U8)回看和下载功能的实现

热门文章

  1. 500强校园招聘中大学生不知道的10件事
  2. 【基础知识】极管类器件的选用
  3. CSS动画——加载的菊花转动画
  4. springMVC的导入导出操作
  5. 转帖:世间最珍贵的是什么?
  6. 文件站项目docu阶段笔记---后台又java转为php
  7. HPL-用于分布式内存计算机的高性能Linpack基准的便携式实现测试
  8. 彻底解决Intellij IDEA中文乱码问题
  9. ubuntu查看网卡型号
  10. Note 7燃损归因电池