记浅析开源电商框架《flamingo-commerce》

Ralap_ · · 2696 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

初识

开源地址:https://github.com/i-love-flamingo/flamingo-commerce

  1. 首先我们看看效果
    官方示例:https://demoshop.flamingo.me
    我部署的示例:http://www.itfan.top:3210
  2. 尝试自己部署
    提供了DEMO,地址:https://github.com/i-love-flamingo/commerce-demo-carotene
  3. 我部署的过程(略显坎坷)
    1. 踩过的坑:
      1. 首先我使用阿里云服务器(国内节点),搭建环境,包括golang、nodejs(当前最新版);部署的过程中发现版本不兼容,回退go(v1.13.6)、node(v12.16.3)
      2. 报错 Get https://accounts.google.com/.well-known/openid-configuration: dial tcp 172.217.27.141:443: i/o timeout 这里发现oauth认证使用的是google,我是国内的节点,无法访问,只能vpn解决了,借了mac,上了vpn一顿环境搭建,最后发现还是 timeout
      3. MAC部署,一样超时,浏览器访问google认证正常,查阅资料有说是google的秘钥认证失败后也不会给结果,同样是超时效果,然后去配了自己的秘钥,还是超时。最后发现mac终端是不走这个代理的,用了各种办法,无果;
      4. 直接上国外的节点,我的是香港的节点,20分钟搞定
      5. 总结,网络问题,奔溃
      6. 下列指令来自remark:
    # clone the repo:
    git clone https://github.com/i-love-flamingo/commerce-demo-      carotene.git
    cd commerce-demo-carotene
    # Download the test catalog  - you only need to do it once - it includes             products.csv and images:
    make download-product-data
    # Prepare translation files:
    make translation
    # Build the flamingo-carotene bases templates:
    make frontend-build
    # Run flamingo with flamingo-commerce
    make serve 
    
  4. 整体架构
    进入正题,项目采用前后端分离,各司其职,后端是基于commerce,
    commerce集成各个模块(模块边界采用DDD领域驱动设计思想),每个模块又基于flamingo框架进行具体的设计开发,系统间的交互采用了六边形的架构思想,通过端口与适配器达到一个可插拔的灵活性;首先我们看下flamingo框架做了什么事;

Flamingo框架特性

  1. 这里官网提供了demo 地址:git clone git@github.com:i-love-flamingo/example-helloworld.git

  2. 依赖注入(Dingo):用在端口 + 适配器、扩展点,上下文的准确映射

    injector.Bind().To();

  3. config:配置信息的读取、解析、映射封装

  4. even:事件的出发与监听

  5. session:支持多种存储(通过配置中心注入)


    image.png
  6. Healthcheck:系统指标监控

  7. router:路由规则(支持配置 + 代码)

    image.png

    image.png

  8. cache:响应数据、基础数据缓存


    image.png
  9. template:数据对view渲染,该框架集成了bug,通过


    image.png

    image.png
  10. SSO:支持单点登录


    image.png
  11. security:提供了功能权限、CSRF

  12. Logger trace :日志最终

  13. form ->controller : 通过将数据封装到FormHandlerFactory注入到控制层 获取数据

  14. GraphQL :自动生成,映射数据库,提供数据操作;

flamingo-commerce模块简绍

1.png
  1. 项目采用DDD(领域驱动设计)的设计思想,将整个电商业务领域分析和建模,划分为各个子领域,再将各个子域分层处理,提供了一套完整的默认电商实现

下面我们具体分析DDD在项目中如何落地的

  1. 整个电商系统是一个领域,项目业务将这整个领域细分为产品子域、客户子域、价格子域、订单子域、付款子域、结账子域、交货子域等,通过分析边界,定义了各个子域的界限上下文,通过分析与建模将各个子域领域模型抽象出来,通过DDD的分层思想,将各个领域服务分层
  2. 下面具体看下car项目的分层


    image.png
  1. application:包含了购物车的缓存、获取、修改操作,主要协调组织了业务的流程,当前模块与其模块比如:consumerService、userService进行一个交互
  2. domain:主要提现业务的概念、状态、规则,包含以下内容
    实体:Car;值对象:Address;聚合:Delivery;工厂:DeliveryInfoBuilder;
    car:其中包含了觉和信息,如Car(// Cart Value Object (immutable data - because the cartservice is responsible to return a cart).)是一个值对象,其中包含了对送货的操作、对购物车的操作、对总价计算操作,
    属性 + 行为
  3. infrastructure:提供了基于内存的购物车管理、email的集成
    这里可以重代码中看到框架的灵活
   func (m *Module) Inject(routerRegistry *web.RouterRegistry,config *struct {
    UseInMemoryCart bool `inject:"config:commerce.cart.useInMemoryCartServiceAdapters,optional"`
    EnableCartCache bool `inject:"config:commerce.cart.enableCartCache,optional"`
    UseEmailAdapter bool `inject:"config:commerce.cart.useEmailPlaceOrderAdapter,optional"`
},) {
m.routerRegistry = routerRegistry
if config != nil {
    m.useInMemoryCart = config.UseInMemoryCart
    m.enableCartCache = config.EnableCartCache
    m.useEmailAdapter = config.UseEmailAdapter
}
    if m.useInMemoryCart {
    injector.Bind((*infrastructure.CartStorage)(nil)).To(infrastructure.InMemoryCartStorage{}).AsEagerSingleton()
    injector.Bind((*infrastructure.GiftCardHandler)(nil)).To(infrastructure.DefaultGiftCardHandler{})
    injector.Bind((*infrastructure.VoucherHandler)(nil)).To(infrastructure.DefaultVoucherHandler{})
    injector.Bind((*cart.GuestCartService)(nil)).To(infrastructure.InMemoryGuestCartService{})
    injector.Bind((*cart.CustomerCartService)(nil)).To(infrastructure.InMemoryCustomerCartService{})
}

配置指定,通过依赖注入到容器,这里主要就是系统提了默认的数据存储方式,里面是数据的一个存储细节比如增、删、改、查

  1. interfaces:通过Form将请求数据封装,Controller接收后获取数据,并渲染前端页面;
    主要的逻辑 :
    1. 从*web.Request 中获取数据等一系列操作,底层看框架提供了通用的方法
    func (p *DeliveryFormService) GetFormData(ctx context.Context, req *web.Request) (interface{}, error)
    2. 注入service,并调用相应业务
    controller:func (cc *CartViewController) Inject(
    applicationCartService *application.CartService,
    applicationCartReceiverService *application.CartReceiverService,
    3. 在grgraphQL中提供查询统计方法
    func (cs CartSummary) SumGrandTotalWithGiftCards() *domain.Price {
    sum, err := cs.cart.SumGrandTotalWithGiftCards()
    if err != nil {
    return nil
    }
    return &sum
    }
  1. 总结,通过清晰的领域定义,我们可以很清晰的看到购物车模块的设计与每一层的作用,体会到DDD设计的可测试、可维护性、灵活性、可扩展性

在项目中六边形架构是如何落地实现的

  1. 首先总结六边形架构的优点
    优点:使用六边形架构开发的软件与通道独立,因此能支持多通道
    易于置换入站和出站整合点
    测试软件变得更简单,因为可以很容易地模拟集成点
  2. 通俗讲,该架构就是为了处理系统交互的,通过内部开通单端口,外部实现端口的适配器进行交互,这样我的核心服务不需要变动,可以支持多种协议或组件,做到灵活可插拔性,同时也为测试提供了方便
  3. 在项目中的实现
    cartServicePorts提供了端口,其中包括GuestCartService、CustomerCartService、ModifyBehaviour、、、等系列端口
    我们就拿GuestCartService端口来说,


    image.png

    这里是定义的一些借口方法,外部实现这些方法通过adapter,
    看下系统如何实现的


    image.png

    通过Adaptter 实现了对数据的内存储
  4. 总结上面的实现: 这里很清晰的感觉到,模块不会关心你的数据是如何存储的,我给你开了端口,你去实现,如何存储是外部的时,这样就可以兼容通道

总结

这里我主要介绍了项目的几个点,基础框架依赖flamingo,flamingo提供了通用域的实现比如配置、依赖注入、安全、缓存与前前端的一个模板渲染,在此基础上项目只需要关心业务,整个项目采用DDD(领域驱动设计)的架构思想,完成领域的拆分,各个模块依赖降到最低,通过对模块的分层,将各个层的职责单一化;同时结合六边形架构,解耦了模块间的依赖,通过端口 + 适配器的模式,实现多通道、多协议的支持,使项目扩展性更加强


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Ralap_

查看原文:记浅析开源电商框架《flamingo-commerce》

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2696 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传