Разработка программ Go, чтобы избежать циклических зависимостей

Вы также можете использовать метод compareTo() для сравнения двух строк. Если результат compareTo равен 0, то две строки равны, в противном случае сравниваемые строки не равны.

== сравнивает ссылки и не сравнивает фактические строки. Если вы создали каждую строку, используя new String(somestring).intern(), вы можете использовать оператор == для сравнения двух строк, в противном случае могут использоваться только методы equals () или compareTo.

-3
задан garyc2232 18 January 2019 в 05:34
поделиться

1 ответ

Добро пожаловать в Golang и Stack Overflow!

Похоже, это общий вопрос разработки программного обеспечения о том, как проектировать структуры данных и операции в вашем проекте и их зависимости.

Как вы обнаружили, круговой импорт плох. Есть много способов изменить дизайн, чтобы отделить вещи. Один из них - прозрачные слои - например, Bank, вероятно, должен зависеть от Human, а не наоборот. Однако, если вы хотите предоставить удобную функциональность для перевода денег из Human в Human, вы могли бы сделать одну вещь - определить интерфейс, который будет реализован объектом Bank.

Однако для простоты я бы порекомендовал строгие слои. Нет реальной причины, по которой Human должно зависеть от Bank. В пределе это может оказаться слишком громоздким, поскольку Human нужно больше услуг (вы бы поставили зависимость Human от Bus, чтобы Bus могли перемещать Human с?]


Чтобы ответить на комментарий и обновленный вопрос, я бы сказал, что это просто:

package main

import (
    "fmt"
    "log"
)

type Human struct {
    ID   int64
    Name string
}

type Account struct {
    ID int64

    // Note: floats aren't great for representing money as they can lose precision
    // in some cases. Keeping this for consistency with original.
    Cash float64

    DaysSinceActive int64
}

type Bank struct {
    Accounts map[int64]Account
}

// Not checking negatives, etc. Don't use this for real banking :-)
func (bank *Bank) Transfer(src int64, dest int64, sum float64) error {
    srcAcct, ok := bank.Accounts[src]
    if !ok {
        return fmt.Errorf("source account %d not found", src)
    }
    destAcct, ok := bank.Accounts[dest]
    if !ok {
        return fmt.Errorf("destination account %d not found", dest)
    }
    // bank.Accounts[src] fetches a copy of the struct, so we have to assign it
    // back after modifying it.
    srcAcct.Cash -= sum
    bank.Accounts[src] = srcAcct
    destAcct.Cash += sum
    bank.Accounts[dest] = destAcct
    return nil
}

func main() {
    gary := Human{19928, "Gary"}
    sam := Human{99555, "Sam"}

    bank := Bank{Accounts: map[int64]Account{}}
    bank.Accounts[gary.ID] = Account{gary.ID, 250.0, 10}
    bank.Accounts[sam.ID] = Account{sam.ID, 175.0, 5}

    fmt.Println("before transfer", bank)

    if err := bank.Transfer(gary.ID, sam.ID, 25.0); err != nil {
        log.Fatal(err)
    }

    fmt.Println("after transfer", bank)
}

Этот код использует слабую связь, как упоминалось в моем первоначальном ответе. Все, что банку нужно знать о человеке, - это его удостоверение личности (может быть SSN или что-то, рассчитанное по имени, дате рождения и другим вещам), чтобы идентифицировать их однозначно. Люди должны держать банки (что, если у человека есть счета в нескольких банках?). Банки не должны содержать людей (что делать, если счета принадлежат нескольким лицам, корпорациям, виртуальным объектам?) И так далее. Здесь нет необходимости в интерфейсах, и вы можете безопасно поместить каждый тип данных в свой собственный пакет, если вам действительно нужно.

0
ответ дан Eli Bendersky 18 January 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: