Search
Write a publication
Pull to refresh
2
0
Eduard @Edison

Software Engineer

Send message
По «классике», зависимости уменьшаются путем выделения общих сущностей (например, интерфейсов) в отдельную библиотеку.

Никто не мешает вам так сделать, если вы так привыкли. Пример с io.Reader сами привели. Иногда так даже лучше делать. Я стараюсь такого избегать.

вы сейчас смешали все в кучу. Есть пользователь реализации (пакет, структура) а есть пользователь моей библиотеки (как бы уже реальный пользователь).


Так вот я имел ввиду, что пакет, который нуждается в каком-то функционале (хочет использовать сторонний сервис, как тот же логгер), что бы не вызывать прямой зависимости от других пакетов, объявляет у себя интерфейс, убирая прямую зависимость от других пакетов.
Если вы скажете про логическую зависимость, покажите пример в джаве (или другом языке с implements интерфейсов), где такой зависимости не будет.


Чем мешает явная зависимость размещению интерфейса у пользователя?

У какого пользователя? Приведите пример кода, а то уж слишком много путаницы.

То есть весь упрек в том, что контракт (документация?). Так когда реальный код я буду писать, я напишу доку и интерфейсу, и структуре Сервис и методу Сенд.


Я очень часто писал либы, сервисы, где у меня был интерфейс Logger. И никакой зависимости от реализации не было.
Логическая зависимость — это демагогия. Я создаю интерфейс, я выдвигаю требования, тот кто использует мою библиотеку должен выполнить мое требование.


Так вот, с чего это интерфейс будет написан после реализации? Вы так и не ответили на вопрос, с чего этот спор начался. Конечно он может быть написан после, это совершенно не обязательно. Что я вам и показал выше на примере Логгера.

вы так и не ответили на вопрос.
С чего это интерфейс будет написан после реализации?


Как узнать, подходит какая-то структура семантически для использования в Send() или нет?

Где тут зависимость от реализации Publisher?

С чего это он будет написан после реализации?


package service

import "encoding/json"

type Publisher interface {
    Publish([]byte) error
}

type Service struct {
   pub Publisher
}

func NewService(p Publisher) *Service {
    return &Service{
        pub: p,
    }
}

func (s *Service) Send(msg Message) error {
    data, err := json.Marshal(msg)
    if err != nil [
        return err
    }
    return s.pub.Publish(data)
}

Где тут зависимость от реализации Publisher?

Интерфейс это не общее, интерфейс описывает реализацию.
Каким образом интерфейс будет зависеть от реализации в случае когда интерфейс объявлен в месте, где он используется?

Но размещение интерфейса у пользователя позволяет уменьшить зависимости пакета, ничего не нужно импортить. Тоже самое про другую сторону — когда реализация не знает про интерфейс.


Смысл интерфейса стремится к нулю, когда у вас каждый про каждого знает.

во-первых есть gogland (даже ссылку вам уже дали). Во вторых, я говорю про сам язык и комьюнити.
В стандартной библиотеке есть go/ast, go/parser, go/printer, etc которые позволяют очень просто создавать свои тулзы для работы с Go кодом (то ли генерация, то ли рефакторинг), которые потом очень просто интегрировать с vim/emacs/sublime/atom.
Потому опять же скажу — не могу вспомнить я других языков с таким большим набором тулзов для работы с кодом которые поставляются с языком, как есть у Go.

только вот IDEA это не тулза из коробки которая идет с Java. Это IDE которая разрабатывается отдельной компанией, а не комьюнити.


В Go же gorename, guru, govet, golint, gofmt, etc и все это разрабатывается Go сообществом.

ну это все субъективно — я называю одной, иногда двумя буквами и мне ок.
На счет рефакторинга — какой другой язык из коробки имеет такойбольшой набор тулзов? Я вот прям и не могу вспомнить.

можешь совсем ничего не делать.
Но ты не сможешь переименовать, если код после этого не будет компилироваться.

вручную надо это делать, gorename'ом переименовывать каждый ресивер.

Я же сказал принято, не обязательно. Если ресиверы будут именоваться по-разному — то golint ворнинг выдаст.
Иногда и я пишу не первую букву, например вот в таких случая (p AsyncProducer), хотя опять же — первая важной части названия.

  1. Тут идея интерфейсов другая, не "я хочу быть вот таким то", а "мне нужно вот такое то"
  2. Есть принятые стандарты — ресивер как первая буква типа. Например (p *Producer), (c *Client), etc.
  3. https://github.com/golang/go/issues/2016
это разрабатывается той же командой, что и язык и это часть проекта Go, иногда либы с golang.org/x/ включают в релиз языка, как случилось с context, http2.
Еще там много тулинга для Go, типа guru, golint
могу сделать вывод, что вы не читали совсем, потому что это написано в самом начале доки про cgo — https://golang.org/cmd/cgo/
If the import of «C» is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package.
тот C код не будет комментарием только тогда, когда сразу же после этого блока будет идти `import «C»`
Вот cgo:
// #include <stdio.h>
// #include <errno.h>
import "C"


Вот комментарий просто:
// #include <stdio.h>
// #include <errno.h>

import "C"
да, дорого стоят. Но опять же — это удобства за которые нужно платить.
Можно и без них код писать.
и почти все используется только для в специфических местах:
1. для работы под солярисом и фрибсд
2. для работы с журналд.
куча? во всем проекте вместе с вендорами С используется 47 раз.

Information

Rating
Does not participate
Location
Киев, Киевская обл., Украина
Registered
Activity