LINUX.ORG.RU

Что происходит с популярностью Go?

 ,


3

2

Примерно с лета прошлого года популярность языка программирования Go неуклонно падает. По крайней мере если верить индексам TIOBE и PYPL. В начале прошлого года Go входил в первую десятку самых популярных языков программирования, но сейчас он уже во второй десятке - ближе к её нижней границе. Если TIOBE и PYPL не отражают действительность, то какие другие индексы отражают её лучше? Хотя на https://langpop.com/ Go всё ещё в первой десятке. Что вообще происходит с Go и каковы ваши прогнозы на ближайшие пару лет?

Ну и чтобы два раза не вставать, дополнительный вопрос. Один из конкурентов Go - это JavaScript/TypeScript на платформе node.js. Когда популярность Go росла, значительный процент новых программистов на Go был представлен теми, кто переходил на него с JS/TS. Однако если сейчас посмотреть на объявления о работе (живу не в России), то там какое-то засилие именно JS/TS, причём в основном это молодые компании и стартапы. Можно ли это объяснить банальной экономией на найме, когда одни и те же люди делают и бэкэнд и фронтэнд? Иначе я никак не могу понять тягу к языку, в котором нет нормальной параллельности и вообще куча костылей и легаси.

Update: большой брат подслушал и порекомендовал в ютубе: www.youtube.com/shorts/Vh97uPhmhqI



Последнее исправление: hummer (всего исправлений: 2)
Ответ на: комментарий от kaldeon

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

А какой-нибудь сишник скажет, что this можно передавать в любую функцию явно первым аргументом, и vtable руками составлять, так что этот ваш ООП вообще не нужен.

dimgel ★★★★★
()
Ответ на: комментарий от dimgel

Я не спорю с тем, что Си — не ОО-язык.

Современное определение ООП таково: инкапсуляция, наследование, полиморфизм, абстракция. Среди них главенствующие принципы: инкапсуляция и абстракция. (Си не поддерживает ни то, ни другое.) Наследование считается «столпом» только из-за того, что это была общепринятая практика в ранних ОО-языках. Другими словами, так исторически сложилось.

Причём как минимум в 1994 году люди уже поняли, что что-то не так с наследованием. Популярная книжка Design Patterns [1] уже тогда выдвинула принцип “favor composition over inheritance.” Стало быть, никакой это не «столп», если ему отведено второстепенное место в ОО-дизайне.

Поэтому Go вполне поддерживает ОО-стиль, если судить по существу.

[1]: https://en.wikipedia.org/wiki/Design_Patterns

kaldeon ★★
()
Ответ на: комментарий от dimgel

> «favor» != «ALWAYS use»

Мне не нужно доказывать, что наследование ВСЕГДА неуместно. Я этого не утверждал. (Что угодно уместно в определённом контексте, даже goto.) Я говорил о том, что это второстепенная роль в ОО-дизайне.

> Впрочем, мне надоел этот разговор.

Так нельзя. Отрицать наличие ООП в языке, вопреки фактам и устоявшейся позиции, не надоело, а объяснять надоело. Не можете аргументировать — откажитесь от своих слов.

kaldeon ★★
()
Ответ на: комментарий от dimgel

совместимая с жавой

Проблема в том, что пока ты живёшь в уютном мирке котлина или например кложи, то всё хорошо. Но без интерконекта с жабой ты далеко не уедешь. А как только ты наступаешь в жабу, то сразу тонешь в ней по шею.

no-such-file ★★★★★
()
Ответ на: комментарий от kaldeon

наследование есть элемент нормального дизайна и дает одну важную фичу, которую не перешибешь.

а именно - совместимость указателей по базовому классу. когда нужно, имея много обектов разных классов, но с общим базовым, рассматривать как обьекты с общими свойствами.

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

в голанге грузит слишким высокий напор на правила форматирования, и имена идентификаторов, типа публичный с заглавной. что за фигня. введите pub и не морочьте голову.

короче, все мои лично попытки на нем писать, заканчивались полным расстройством, и отскоком на что нить другое.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от no-such-file

А как только ты наступаешь в жабу, то сразу тонешь в ней по шею.

Красивый образ, но вообще-то весь страшный интерконнект с жабой в кложе делается как-то так:

;; создадим instance java.util.Date
(java.util.Date.)
#inst "2026-08-02T11:09:42.926-00:00"
;; вызовем метод класса
(.toString (java.util.Date.))
"Sun Aug 02 13:09:55 CEST 2026"
;; то же самое, но с аргументом и эквивалентным синтаксисом конструктора, просто так
(def d (new java.util.Date))
(.setYear d 1)
d
#inst "1901-08-02T12:11:49.285-00:00"

Надеюсь, никого не напугал этакими ужосами.

ugoday ★★★★★
()
Ответ на: комментарий от alysnix

Когда в этот ваш С++ мультиметоды завезут? А то на других ругаетесь, а у самих язык по фичам до сих пор уступает CLOS (более чем сорокалетней давности).

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

А то на других ругаетесь

ни в коем разе.

Когда в этот ваш С++ мультиметоды завезут?

когда вы предложите эффективную реализацию.

alysnix ★★★
()
Ответ на: комментарий от alysnix

> наследование есть элемент нормального дизайна и дает одну важную фичу, которую не перешибешь.

Было бы интересно выслушать.

> а именно - совместимость указателей по базовому классу.

Где здесь, собственно, дизайн? Скорее zero CPU cost заморочка. Это очень удобный стандарт: можно очень многое принести в жертву.

Идея наследования вообще не привязана к какой-либо реализации. Это абстрактное понятие и судить его нужно именно как абстрактное понятие, если более специфичный контекст не указан явно.

Если опустить zero CPU cost, то это банальный полиморфизм. Полиморфизм — не существенная характеристика наследования. Аспект наследования реализации оказывает куда большее влияние не дизайн.

kaldeon ★★
()
Ответ на: комментарий от ugoday

Когда в этот ваш С++ мультиметоды завезут?

А в Go?

а у самих язык по фичам до сих пор уступает CLOS (более чем сорокалетней давности).

А как с этим дело обстоит у Go?

eao197 ★★★★★
()
Ответ на: комментарий от kaldeon

Где здесь, собственно, дизайн?

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

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

Если опустить zero CPU cost, то это банальный полиморфизм.

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

Аспект наследования реализации оказывает куда большее влияние не дизайн.

у кого как. любую сильную концепцию можно использовать во вред. в том ее сила. используйте на пользу.

критковать наследование за излишнюю зависимость реализаций, это все равно что критиковать вилку за то, что ею можно ткнуть в глаз.

само определение наследования не преполагает, что вы будете его использовать там, где не стоит.

если вам неохота, чтобы у вас наследники тырили реализацию из базового класса - обьявите методы приватными.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 3)
Ответ на: комментарий от kaldeon

Идея наследования вообще не привязана к какой-либо реализации. Это абстрактное понятие и судить его нужно именно как абстрактное понятие, если более специфичный контекст не указан явно.

А подскажите, пожалуйста, как в Go реализуется вот такой элементарный паттерн, легко доступный в классических ОО-языках:

class base {
protected: // Хотя тот факт, что это protected роли не играет.
  virtual void do_specific_action() = 0;

public:
  void do_something() {
    ... // Какие-то начальные действия.
    do_specific_action();
    ... // Какие-то финальные действия.
  }
  ...
};

void f(base & obj) {
  obj.do_something();
  ...
}

class derived_one : public base {
  void do_specific_action() override { ... }
  ...
};

class derived_one : public base {
  void do_specific_action() override { ... }
  ...
};

И в f можно передать ссылку на любого наследника от base.

eao197 ★★★★★
()
Ответ на: комментарий от alysnix

Т.е. мультиметодов нету и не предвидется? Ладно, оставим С++ в категории отсталых языков из 80-х. Вернусь к вопросу лет через 10.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

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

никому в с++ такой хоккей не нужен. даже если его туда вставят - он сто пудов будет отключаться ключиком компилятора, который будет стоять по умолчанию в «отключить».

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Ну, это уже отмазки лирика. Я же, предлагаю вам взглянуть на себя со стороны и увидеть, что логика «ну нету и хрен с ним. На то есть причины» прекрасно работает и против ваших претензий к Go.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

мои «претензии» к голангу я же сформулировал - слишком жесткие рамки для форматирования и правила для идентификаторов. остальное терпимо. а некоторое - каналы и корутины - даже приятно.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от no-such-file

Давайте лучше вы сформулируете свои тезисы в явном виде, чтоб мне не додумывать за вами в чём суть претензии.

ugoday ★★★★★
()
Ответ на: комментарий от alysnix

По местным правилам это не баг, это фича. Как в армии, безобразие, но единообразие. Оно, может, и претит истинному художнику, но для художеств есть Perl. А тут промышленный код, который выглядит и устроен абсолютно одинаково и предсказуемо. Можно любого среднего гошника бросить в любой средний проект и он практически сразу разберётся и начнёт приносить пользу. Ситуация, когда каждый программист выбирает и пишет на своём подмножестве языка исключена настолько, насколько это вообще возможно.

ugoday ★★★★★
()
Ответ на: комментарий от alysnix

> вы можете вынести работу с базовыми(общими) свойствами объектов в отдельный класс или функцию, инкапсулировать эту обработку там, и не морочится с совместимотью по указателю на эти обьекты. и все это зерокост.

Обещан был «элемент нормального дизайна». Нужен хотя бы один пример, который бы оправдал наличие наследования в языке. А вы объяснили общий принцип работы, справедливый в любом случае использования.

Это не опровергает тезис, что «[наследованию] отведено второстепенное место в ОО-дизайне». ОО-дизайн — это один шаг выше механики, про поиск лучших (а не любых) методов решения проблем.

> как раз зерокост решения . . . и есть самые ценные

Не для всех и не для любой цели.

> полиморфизм не может быть банальным

Я не называл полиморфизм банальным. Я указал, что полиморфизм *сам по себе* — не существенная характеристика наследования как понятия.

Существенная характеристика должна отражать то, без чего понятие не было бы тем, чем оно является. Такой характеристикой является аспект наследования *реализации*: именно этот аспект делает понятие наследования уникальным, выделяющем его на фоне остальных форм полиморфизма.

И именно этот аспект является самым проблематичным с точки зрения ОО-дизайна. Он ослабляет инкапсуляцию [sny86].

> используйте на пользу.

Наследование позволяет легче изменить переиспользуемую реализацию. Вот и вся польза.

В контексте ОО-дизайна это ничтожная польза, несоизмеримо маленькая с масштабом сложностей в эксплуатации.

> если вам неохота, чтобы у вас наследники тырили реализацию из базового класса . . .

Дело не в желании. Воровство реализации — это часть определения наследования. В том виде, в котором наследование существует в C++ или Java, формально оно называется «наследование *класса*». Реализация — это часть класса. Наследование без реализации — это и есть использование инструмента не по назначению.

> . . . обьявите методы приватными.

Этого недостаточно, чтобы полностью изолировать реализации. Приватные члены базового класса всё ещё могут обращаться к дочерним методам, *изменяя наследуемую реализацию*. Для полной изоляции нужно дополнительно запретить переопределять методы.

Это оставит нас с чистым наследованием *типа*. Это позволяет нам аккуратно выразить отношения вида is-a. Проблема только в том, что это редко нужно и когда нужно, то правильным инструментом является *подтип*, а не наследование класса.

[sny86]: Alan Snyder. Encapsulation and inheritance in object-oriented languages.

kaldeon ★★
()
Ответ на: комментарий от eao197

как в Go реализуется вот такой элементарный паттерн

Напрямую — никак, ибо наследование реализации отсутствует. Это, кстати, защищает от проблемы хрупкого базового класса [1].

Но вообще аналогичный код пишется так:

1. Пишем derived1 и derived2

2. Пишем base, который при создании принимает derived1 или derived2 через общий интерфейс. Именно к нему будем обращаться в base.DoSomething.

3. В f передаём только инстанс base

В целом, прямое применение принципа “favor composition over inheritance.”

Важно и то, что интерфейс привязан только к base. Это расслабляет порядок написания: можно сначала реализовать derived1/derived2 и уже потом написать base/doer.

Код выглядит как-то так:

type doer interface{ Do() }

type base struct{ doer doer }

type derived1 struct{}

type derived2 struct{}

func (b *base) DoSomething() {
	b.doer.Do()
}

func (d *derived1) Do() { fmt.Println("hello world") }

func (d *derived2) Do() { fmt.Println("hello existence") }

func main() {
	b := &base{
		doer: &derived2{},
	}
	b.DoSomething()
}

[1]: https://en.wikipedia.org/wiki/Fragile_base_class

kaldeon ★★
()
Последнее исправление: kaldeon (всего исправлений: 2)
Ответ на: комментарий от kaldeon

Существенная характеристика должна отражать то, без чего понятие не было бы тем, чем оно является. Такой характеристикой является аспект наследования реализации: именно этот аспект делает понятие наследования уникальным, выделяющем его на фоне остальных форм полиморфизма.

нет там никакого «наследования реализации» по дефолту. наследование это в чистом виде отношение - «is a» композиция - отношение «consists of»

и второе никак не заменяет первое. потому что автомобиль есть «средство передвижения», а «consists of» - мотор и 4 колеса.

если вы инкапсулируете «средство передвижения» в автомобиль - у вас просто неверно устроенный класс. ибо автомобиль не может состоять из «средства передвижения».

Наследование без реализации — это и есть использование инструмента не по назначению

аналогично вы не можете отнаследовать автомобиль от мотора и 4 колес. и именно такую дурь обычно и эксплуатируют в своих аргументах критики «наследования».

у вас нет способа коректно отразить is_a, усли у вас нет наследования хоть тушкой, хоть чучелом.

если вам в разработке такое отношение is_a - даром не надо, то пробуйте без воды и костылей спроктировать библиотеку для гуя, где вся ветвистая иерархия растет от базового класса window или типа того. вам по-любому придется делать квазинаследование через задний проход, ну или виде «наследования» интерфейсов.

Наследование без реализации — это и есть использование инструмента не по назначению

в кондовом ооп можно наследовать хоть с реализацией, хоть без.

class Base {
public:
  void fun1();
  Base();
}

или так

class HiddenBase;
class Base {
  HiddenBase* _hidden;
public:
  void fun1();
  Base();
}

если у вас есть общие свойства, то они должны быть где-то реализованы.

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

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от kaldeon
> type doer interface{ Do() }
> 
> type base struct{ doer doer }
> 
> type derived1 struct{}
> 
> type derived2 struct{}
> 
> func (b *base) DoSomething() {
>   b.doer.Do()
> }
> 
> func (d *derived1) Do() { fmt.Println("hello world") }
> 
> func (d *derived2) Do() { fmt.Println("hello existence") }
> 
> func main() {
>   b := &base{
> 	doer: &derived2{},
>   }
> 
> 	b.DoSomething()
> 
> }

что по простому пишется так

class Base {
  virtual void Do();
}

void DoSomething(Base& b) {
   b.Do()
}

class Derived1: public Base {
  void Do() override {fmt.Println("hello world")}
}

class Derived2: public Base {
  void Do() override {fmt.Println("hello existence")}
}

void main() {
  Derived2 b;
  DoSomething(b);
}

отличия очевидны. первый код - кишки наружу. есть просто данные классов, сами по себе, и байндинги к этим данным, которые тоже раскиданы по файлу сами по себе. чтобы понять - какие методы данный «класс» реализует - надо просмотреть весь файл в три тыщи строк. опять же - квазивиртуальный метод Do реализован ручками - через хранение в base указателя на реальную функцию. который потом инитится опять же ручками при создании обьекта. такая вот квази VMT прямо в обьекте. а что если таких методов - десяток?

короче в такой манере можно и на си написать.

второй код - все классы описаны целостно, посмотрел и все понял. Никакой ручной VMT нет. пиши хоть сто виртуальных методов. это и называется ооп

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от kaldeon

Напрямую — никак, ибо наследование реализации отсутствует.

ИМХО, это полностью опровергает ваш тезис о том, что наследование – это «Это абстрактное понятие и судить его нужно именно как абстрактное понятие». Поскольку есть вполне себе конкретные примеры кода, которые демонстрируют наличие или отсутствие этого самого «наследования».

Это, кстати, защищает от проблемы хрупкого базового класса [1].

Если вы эмулируете ООП вручную, то вы получаете те же самые «проблемы», но еще и обмазанные говном этой самой ручной реализации.

Впрочем, опыт (да и аргументы в этом треде) показывает, что Go-шники с удовольствием жрут говно с двух рук и еще и с радостью доказывают, что все правильно, что так и надо.

eao197 ★★★★★
()
Ответ на: комментарий от alysnix

> нет там никакого «наследования реализации» по дефолту. наследование это в чистом виде отношение - «is a» композиция - отношение «consists of».

Вы правы в том, что is-a — тоже существенная характеристика. Но я не утверждал обратного. Я утверждал, что аспект наследования реализации тоже существенный и, в особенности, очень проблематичный.

Наследование в C++ или Java называется наследованием *класса*. Реализация — часть класса. Если это не дефолт, то я не знаю что такое «дефолт». Наследования реализации *возможно* избежать, но нам придётся бороться против языка, поэтому намного проще и надёжнее будет просто отказаться от наследования.

> и второе [«consists of»] никак не заменяет первое [«is a»]. потому что автомобиль есть «средство передвижения», а «consists of» - мотор и 4 колеса.

consists-of заменяет не is-a, а унаследованную реализацию. Не Car и Bike имеют общий двигатель от Vehicle, а Car и Bike имеют двигатель через интерфейс Engine. В этом и есть смысл “favor composition over inheritance.”

«Автомобиль есть средство передвижения» легко выражается интерфейсом Vehicle и классом Car, реализующим интерфейс. Наследование не нужно.

> ибо автомобиль не может состоять из «средства передвижения».

Я почему вообще сказал, что is-a — это редкость. Потому что абсолютная уверенность в том, что есть что, возможна при моделировании *существующей* системы. Черепаха есть животное, ручка есть пишущий инструмент и т.д. Но как только мы погружаемся в *создание* новой системы, такие чёткие границы редко присутствуют. MyClient — это is-a Client или consists of Client? Оба варианта верны. А сам выбор между is-a и has-a очень рискованный и преждевременный.

> имейте базу со скрытыми кишками. но в тех же гуях так не извращаются.

Если скрытая реализация имеет доступ к базе, то всё это бессмысленно.

Но вообще это именно «изврат», потому что нам приходится бороться против ожиданий языка программирования. И наши намерения всё равно вряд ли кто-нибудь оценит. Есть намного более чистое решение — композиция.

> пробуйте без воды и костылей спроктировать библиотеку для гуя

Можно смело пробовать. Исторический тренд — не доказательство.

Принцип “favor composition over inheritance” — это не вода и не костыли. Вот его я бы и применил. Уверен, что уже есть GUI, которые прошли этот путь.

> у вас два выхода. или написать в базовом классе такую реализацию и закрыть вопрос(забив на критиков наследования). . . . или написать одну, но вызывать ее в разных классах. что есть симуляция наследования через тавтологию и самоистязяние.

Второй вариант — это не симуляция наследования, а композиция. «Самоистязание» — это преувеличение.

Реальный вопрос — можно ли оправдать наследование удобством. Вы предполагаете, что без наследования будет больно, но не учитываете тот факт, что композиция лучше масштабируется и поддерживает в системе разделение зон ответственности.

kaldeon ★★
()
Ответ на: комментарий от alysnix

> чтобы понять - какие методы данный «класс» реализует - надо просмотреть весь файл в три тыщи строк

Надуманная проблема. Как правило, методы одного типа всегда сгруппированы. Вперемешку никто не пишет. Это не сложно. В остальном, всё как в C++/Java: достаточно найти первую и последнюю строчку.

> опять же - квазивиртуальный метод Do реализован ручками - через хранение в base указателя на реальную функцию. который потом инитится опять же ручками при создании обьекта. такая вот квази VMT прямо в обьекте. а что если таких методов - десяток?

Вы смотрите на пример сквозь призму «Go эмулирует наследование». Но так никто код на Go не пишет. Никто не начинает с цели создания базового класса и потом не пытается механически натянуть язык. Так делают в Си. В Го начинают с того, какое поведение нужно, и абстрагируют его в интерфейс.

Десять виртуальных методов — для какой цели? Всё зависит от того, что мы абстрагируем и ради какой цели. Если мы, например, реализуем паттерн шаблона (абстрагируем мелкие различия от одной базы), то можно хоть все 10 методов вынести в один интерфейс.

> пиши хоть сто виртуальных методов. это и называется ооп

Сто виртуальных методов — это как раз тот самый «ООП», с которым начали бороться десятилетиями назад. Go в значительной степени продолжает эту традицию.

kaldeon ★★
()
Ответ на: комментарий от eao197

> Поскольку есть вполне себе конкретные примеры кода, которые демонстрируют наличие или отсутствие этого самого «наследования».

Вы говорите о том, что я не могу выразить наследование другими средствами. Это правда и я с этим не спорю. Хотя вы тоже должны учитывать, что некоторые основные аспекты (полиморфизм, is-a) не уникальны для наследования.

Но я вообще имел ввиду нечто другое. Наследование — это абстрактное понятие не в том плане, что оно существует везде, даже в ассемблере (я не отбрасываю контекст о поддержке языка), а в том плане, что в нём не содержится привязка к zero CPU cost реализации. Это просто удобная деталь реализации. Именно об этом шла речь в исходном сообщении.

(А заговорил я об этом, увидев формулировку «совместимость указателей».)

> Если вы эмулируете ООП вручную, то вы получаете те же самые «проблемы», но еще и обмазанные говном этой самой ручной реализации.

Это не эмуляция, а совершенно другой паттерн. И нет, моя реализация точно, на 100% лишена проблемы хрупкого базового класса.

> Go-шники с удовольствием жрут говно с двух рук

Как по мне, жрать говно — это использовать средства языка, не осознавая их пределы. Гошники подверженны этому пороку в куда меньшей степени.

kaldeon ★★
()
Ответ на: комментарий от kaldeon

Вам эту заумную хрень нести не надоело?

Читаю вас и как на совещании с прожжеными эффективными менеджерами – умных словесов много, толку мало.

Если язык поддерживает наследование нативно, то у вас есть выбор – можете применять is-a, можете не применять и ограничиваться has-a (если вам так уж милы современные тренды).

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

Только вот язык – это инструмент. И оценивать язык можно по тому, какие возможности язык дает разработчику.

Язык Go исходит из того, что разработчики криворукие дебилы, поэтому лучше им большие пушки в руки не давать.

Удивление вызывает то, что этот подход мало того, что кому-то нравится, так его еще и защищают. Типа да, все хорошо, мы дебилистые дебилы, мы лучше if nil != err будем вписывать по 20 раз на функцию, и про is-a забудем как страшный сон.

И нет, моя реализация точно, на 100% лишена проблемы хрупкого базового класса.

Блажен кто верует.

eao197 ★★★★★
()
Ответ на: комментарий от kaldeon

и хотя я с вами категорически не во всем согласен, спасибо вам за спокойный тон разговора, ибо в инетах так принято, что со второго поста дискуссии начиается переход на личности и закидывание какашками оппонента.

чуть позже дам развернутый ответ на проблему «наследования», котороая не стоит по моему выеденного яйца.

alysnix ★★★
()
Ответ на: комментарий от eao197

> Вам эту заумную хрень нести не надоело? . . . умных словесов много, толку мало.

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

Ваше упорство тоже вызывает вопросы. Как будто у вас есть какие-то личные счёты с Go.

> у вас есть выбор – можете применять is-a, можете не применять и ограничиваться has-a (если вам так уж милы современные тренды)

«Если у них нет хлеба, пусть едят пирожные». Я это к тому, что личные предпочтения не решают системных проблем.

> И оценивать язык можно по тому, какие возможности язык дает разработчику.

Это очень недальновидная позиция. Она справедлива только в контексте вроде «сейчас я напишу программу и хочу сделать так-то и так-то, никак иначе». Это очень авторитарный «я художник и я так вижу» подход (хотя это плохо даже в искусстве).

У любой системы, будь это ПО, книга или язык программирования, есть некая абстрактная цель. Цитирую себя:

> Например, Go — «современный, минимальный язык с низким порогом входа» (приблизительное определение). C++ — «мощные абстракции без издержек CPU» (тоже приблизительное определение). И там, где системе нужно принять выбор какой она должна быть, решение принимается на основании того, что ближе к цели системы.

Когда люди выбирают Go, они думают не только о своём личном комфорте, а том, чтобы их код было легко понять, легко обслуживать, чтобы он легко масштабировался и т.д. Выбор слишком щедрого языка здесь неоптимален: наличие лишних фич влияет на всю экосистему и культуру так сильно, что их невозможно игнорировать. Придётся плыть против течения стандартной библиотеки, сторонних API, привычек коллег и просто удобств языка. Неверный путь становится лёгким.

Согласно вашей логике, можно даже C++ закопать. Там указывали на отсутствие неких мультиметодов. Если вы согласны принять данный стандарт — отлично. Но ожидать того же от других людей странно.

> Язык Go исходит из того, что разработчики криворукие дебилы

Это вы исходите из такой логики. Попробуйте перестать делить людей на умных и тупых. Может, придёт просветление.

> Блажен кто верует.

Я не верую (вообще). Я привёл конкретный код. «Мяч на вашей стороне», как говорится. Попробуйте указать где там хрупкий базовый класс или откажитесь от своих слов.

kaldeon ★★
()
Последнее исправление: kaldeon (всего исправлений: 1)
Ответ на: комментарий от kaldeon

Как будто у вас есть какие-то личные счёты с Go.

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

Что меня удивляет, так это «то, что этот подход мало того, что кому-то нравится, так его еще и защищают».

Я это к тому, что личные предпочтения не решают системных проблем.

А я к тому, что вы несете херню в стиле «за все хорошее и против всего плохого». Умных слов много, толку мало.

Согласно вашей логике, можно даже C++ закопать.

Согласно «моей логике»? Вы через интернет ко мне в голову залезли?

С++ и так закапывают, без меня. У C++ полно недостатков, но часть из них – это продолжение того многообразия, которое C++ дает разработчику. Что нужно для задачи, то и выбирайте. Кто не хочет выбирать, то пишет жесткие гайдлайны и заставляет команду строем по ним ходить.

Тогда как в Go идут прямо противоположным путем. Что лично мне кажется противоестественным. И, например, то, как развивается C# (куда впихивают много всякого разного), мне лично кажется более логичным: разработчику нужны инструменты, разные, для разных случаев, так лучше их разработчкам дать, чем заставлять программиста обходиться костылями.

Я привёл конкретный код.

Не видел я кода, который бы демонстрировал проблему хрупкого базового класса и ее решение в случае с Go-шными костылями. Go-шные костыли видел, а вот иллюстрации для проблемы хрупкого базового класса – нет.

eao197 ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)