美文网首页
2020-06-17 框架设计

2020-06-17 框架设计

作者: ShutLove | 来源:发表于2020-06-17 23:30 被阅读0次
    1. 请描述什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?
      依赖倒置原则是一种解耦模块间关系的方法,它要求上层模块不能依赖于底层模块,他们应该共同依赖于一个抽象;抽象不能依赖于实现,实现应该依赖于抽象。
      在底层实现发生变化或者引入新的底层实现时,通过共同依赖于抽象,可以使得改动对上层模块的影响最小化。
      好莱坞原则通俗讲是你不要调用我,让我来调用你。这个关系的反转和依赖倒置的核心思想是一致的,好莱坞所讲的可以理解为框架会定义一系列的接口,各种基于框架开发的应用程序只需要实现这些接口,框架在启动之后它会来调用应用程序实现的这些接口,让程序运行起来。

    2. 请描述一个你熟悉的框架,是如何实现依赖倒置原则的。
      最近在做一个对图片做离线处理的pipeline系统,主要基于https://github.com/digitalocean/firebolt这个框架进行的开发。
      此框架定义了consumer中接收消息的source node的接口,以及pipeline处理中算子node的接口,作为使用框架的开发人员只需要按接口要求把处理逻辑封装在这些接口方法中,然后在程序启动前,将实现注册到firebolt框架,然后启动firebolt,框架就会按照开发者定义的处理流程配置文件来按序执行pipeline处理。

    source node负责接收消息

    type Source interface {
        Setup(config map[string]string, recordsch chan []byte) error
        Start() error
        Shutdown() error
        Receive(msg fbcontext.Message) error
    }
    

    sync node 负责处理业务逻辑的算子

    type SyncNode interface {
        Setup(config map[string]string) error
        Process(event *firebolt.Event) (*firebolt.Event, error)
        Shutdown() error
        Receive(msg fbcontext.Message) error
    }
    

    config file 用来定义这个pipeline处理流程

    source:                                 # one and only one source is required
      name: kafkaconsumer
      params:
        brokers: ${KAFKA_BROKERS}           # environment variables are supported
        consumergroup: testapp
        topic: logs-all
        buffersize: 1000                    # sources do not normally need buffering; this value is a pass-thru to the underlying kafka consumer
    nodes:
      - name: firstnode
        workers: 1                          # each node can be configured to run any number of workers (goroutines), the default is 1
        buffersize: 100                     # each node has a buffered input channel for the data that is ready to be processed, default size is 1
        params:                             # params are passed as a map to the node's Setup() during initialization
          param1.1: value1.1
          param1.2: value1.2
        children:                           # a node may have many children, the events returned by the node are passed to all child node's input channels
          - name: secondnode
            error_handler:                  # errors returned by 'secondnode' will be passed to this error handler
              name: errorkafkaproducer      # we provide built-in 'errorkafkaproducer' that writes JSON error reports to a Kafka topic
              buffersize: 100
              discard_on_full_buffer: true  # if the buffer is full discard messages to avoid sending backpressure downstream for a low priority function
            children:
              - name: thirdnode
                id: third-node-id           # you can use the same node type in your hierarchy twice, but its id (defaults to name) must be unique
                workers: 3
                buffersize: 300
                params:
                  param3.1: value3.1
                  param3.2: value3.2
    

    主程序通过node.GetRegistry().RegisterNodeType注册已实现的node,并启动executor

    // first register any firebolt source or node types that are not built-in
        node.GetRegistry().RegisterNodeType("jsonconverter", func() node.Node {
                return &jsonconverter.JsonConverter{}
            }, reflect.TypeOf(([]byte)(nil)), reflect.TypeOf(""))
        
        // start the executor running - it will build the source and nodes that process the stream
        ex, err := executor.New(configFile)
        if err != nil {
            fmt.Printf("failed to initialize firebolt for config file %s: %v\n", configFile, err)
            os.Exit(1)
        }
        ex.Execute() // the call to Execute will block while the app runs
    

    由于golang没有Java强大的泛型和annotation,因此需要在主程序中显示的注册各种实现好的node

    1. 请用接口隔离原则优化 Cache 类的设计,画出优化后的类图
    type CacheConfig interface {
    }
    
    type CacheStorage interface {
        Get(key string) (interface{}, error)
        Set(key, value string) error
        Delete(key string) error
    }
    
    type CacheHandler interface {
        ReBuild(conf CacheConfig) (CacheStorage, error)
    }
    
    type CacheProxy struct {
        ActiveCache CacheStorage
        CacheHandler
    }
    

    应用程序中使用时,使用方法为

    var (
      err error
      activeCache CacheStorage
    )
    activeCache, err = NewCacheProxy(cacheConf)
    

    远程系统调用时,使用方法为

    var (
      err error
      var cacheHandler CacheHandler
    )
    cacheHandler, err = NewCacheProxy(cacheConf)
    

    相关文章

      网友评论

          本文标题:2020-06-17 框架设计

          本文链接:https://www.haomeiwen.com/subject/nfgexktx.html