Golang的关注点分离与可用性

huangapple go评论216阅读模式
英文:

golang separation of concerns vs usability

问题

我一直在努力保持go模块的整洁分离,避免循环依赖。

现在我有这样的代码:

package chain

type Block struct{
    Content []byte
    Number int
}

var Chain []Block = make([]Block, 10)

func AddBlockToChain(block Block){
    // 进行一些检查
    //...
    // 添加到链上
    Chain[block.Number] = block
}

func GetBlock(number int) Block {
    // 进行一些检查
    //...
    // 从链上获取
    return Chain[number]
}

为了实现共识,我需要一些额外的关于区块的信息。这些信息可能因使用的共识算法而异。我希望共识算法可以互换(例如通过启动时的标志)。

将信息作为区块的字段存储会很方便,这样当我调用GetBlock(3)或从其他地方获取一个区块时,不仅可以访问区块本身,还可以访问该区块当前所处的共识状态的信息。

另一方面,我希望将仅与特定共识算法相关的数据与基本区块数据分开存储,甚至可以放在一个单独的包中。

我应该如何设计我的程序?在哪里存储与特定共识算法相关的数据?

一些背景信息:

我正在尝试从头开始构建一个区块链应用程序。我有一个负责存储数据块的"chain"模块,以及一个负责在运行我的程序实例的多个节点之间创建共识的"consensus"模块。

英文:

I have always struggled keeping go modules neatly separated and avoiding cyclic dependencies.

Right now I have code like this:

    package chain


type Block struct{
	Content []byte
	Number int
}

var Chain []Block = make([]Block, 10)

func AddBlockToChain(block Block){
	// do some checks
	//...
    // add to chain
    Chain[block.Number] = block
}

func GetBlock(number int) Block {
	// do some checks
    //	...
    // get from chain
    return Chain[number]
}

To achieve consensus I need some extra info on the block. The info may be different depending on which consensus algorithm I use. I want the consensus algorithm to be interchangeable (e.g. by flag on start up).

It would be convenient to store the info as fields in the block, so that when I call GetBlock(3) or get a block from anywhere else I can not only access the block but also the info on what state of consensus this block is in at the moment.

On the other hand I wanted to keep data that is only relevant for a certain consensus algorithm separate from basic block data - maybe even in a separate package.

How should I design my program? Where should I keep data relevant for a certain consensus algorithm?

Some background info:

I am trying to build a block chain application from scratch. I have a "chain" module responsible for storing blocks of data and a "consensus" module responsible for creating consensus between multiple peers running an instance of my program on what that data is.

答案1

得分: 3

consensus.Blockchain.Block是两种不同的类型,但由于你将chain.Block嵌入到了consensus.Block中,所以你可以从一个类型中访问另一个类型。

只需在AddBlockToChain()中传递consensus.Block

func AddBlockToChain(block consensus.Block)

然后通过block.Block来访问它。

示例代码:

package main

import "fmt"

type ChainBlock struct {
    id int
}

type ConsensusBlock struct {
    ChainBlock
    idCons int
}

func printChainBlockId(consBlock ConsensusBlock) {
    fmt.Println(consBlock.ChainBlock.id)
}

func main() {
    test := ConsensusBlock{
        ChainBlock: ChainBlock{
            id: 42,
        },
        idCons: 44,
    }

    printChainBlockId(test)
}

请注意,我将admin更改为test,以使代码正确运行。

英文:

consensus.Block and chain.Block are two separate types but since you are embeddding chain.Block in consensus.Block, you can access one from another.

Just pass consensus.Block in AddBlockToChain():

`func AddBlockToChain(block consensus.Block)`

and then access it by: block.Block

Example:

package main

import "fmt"

type ChainBlock struct {
	id int
}

type ConsensusBlock struct {
	ChainBlock
	idCons int
}

func printChainBlockId(consBlock ConsensusBlock) {
	fmt.Println(consBlock.ChainBlock.id)
}

func main() {
	test := ConsensusBlock{
		ChainBlock: ChainBlock{
			id: 42,
		},
		idCons: 44,
	}

	printChainBlockId(admin)
}

答案2

得分: -1

为了完整起见,我想添加一个解决方案,将共识算法的代码和数据放在一个与区块和链码不同的包中:

在区块中添加一个额外的字段,如下所示:

Extra []byte

然后,在该算法包中,将共识算法所需的额外数据存储在一个结构体中,并将其编码为JSON或其他格式,以存储在额外字段中。

这种解决方案将不同的关注点分开。没有共识算法,链条就没有意义,但它们可能看起来非常不同,并且可能需要不同的数据。这样,不同的算法可以存储不同的数据。

然而,我没有选择这个解决方案,因为像 @syntagma 建议的那样,将所有代码放在一个包中似乎更简单。

英文:

For completeness I want to add a solution that keeps the code and data of the consensus algorithm in a different package than the block and chain code:

Add an extra field to the block like this:

Extra []byte

Then keep the extra data needed for a consensus algorithm in that algorithms package in a struct and encode it to json or some other format to store it in the extra field.

This solution keeps separate concerns separate. The chain would not make sense without a consensus algorithm, but they can look very different and might need different data. This way different algorithms can store different data.

I did not go with this solution however, because it just seemed simpler to keep all the code in one package as @syntagma suggested.

huangapple
  • 本文由 发表于 2017年5月30日 16:55:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/44257729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定