Re[10]: Статические методы в любом их обличии это зло!
От: dimgel Россия https://github.com/dimgel
Дата: 23.10.13 13:11
Оценка:
Здравствуйте, Ромашка, Вы писали:

Р>Здравствуйте, Tom, Вы писали:

Tom>>Я про то что статические методы ставят крест на DI/IoC и убивают все прелести данных патернов

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


Это всё концептуально ортогонально. Технически ты не сделаешь DI на статических методах, но точно также ты не сделаешь на них прозрачную подмену реализаций зависимостей, которая суть единственная практическая польза от DI. О чём тут уже говорили. Категорически отрицать полезность DI — так же глупо, как и категорически отрицать полезность статических функций.
Re: Статические методы в любом их обличии это зло!
От: Basil2 Россия https://starostin.msk.ru
Дата: 23.10.13 13:12
Оценка: -1
Здравствуйте, Tom, Вы писали:

Tom>Думаем что статические методы в любом их обличии это зло, будь то в классах и тем более в интерфейсах.


Как вы собираетесь создавать фабрику объектов без статического метода?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[19]: Статические методы в любом их обличии это зло!
От: _NN_ www.nemerleweb.com
Дата: 23.10.13 13:40
Оценка:
Здравствуйте, dimgel, Вы писали:

Не совсем понятно.

Скажем C#:
public class MyType
{
 public static int operator+(MyType l, int r) { return 1; }
}


Или вы имеете ввиду добавить новую операцию для типа внешнего типа ?
В С++ это можно сделать, но тут friend уже не поставишь
Скажем тот же operator<< можно перегрузить пост фактум, но пользоваться можно будет только публичными данными.

В Nemerle нельзя добавить операции потом , т.к. классы не открытые и глобальных функций нет.
Но можете решить добавив макрос который будет использоваться локально.
В макрооператорах можно задавать ассоциативность и приоритеты:
// Операция "==" , не унарная , левоассоциативная (приоритеты: 165<166)
[assembly: Nemerle.Internal.OperatorAttribute ("Nemerle.Core", "==",    false, 165, 166)]

// Операция "::" , не унарная , правоассоциативная (приоритеты: 221>=220)
[assembly: Nemerle.Internal.OperatorAttribute ("Nemerle.Core", "::",    false, 221, 220)]
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[20]: Статические методы в любом их обличии это зло!
От: dimgel Россия https://github.com/dimgel
Дата: 23.10.13 13:45
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Скажем C#:

_NN>
_NN>public class MyType
_NN>{
_NN> public static int operator+(MyType l, int r) { return 1; }
_NN>}
_NN>


_NN>Или вы имеете ввиду добавить новую операцию для типа внешнего типа ?


Нет, для своего, как в твоём примере выше. Но я не вижу, как это делается в твоём примере ниже, то есть где собственно кодируется и где подхватывается реализация алгоритма для MyType.:: в Nemerle:

_NN>
_NN>// Операция "::" , не унарная , правоассоциативная (приоритеты: 221>=220)
_NN>[assembly: Nemerle.Internal.OperatorAttribute ("Nemerle.Core", "::",    false, 221, 220)]
_NN>
Re[21]: Статические методы в любом их обличии это зло!
От: _NN_ www.nemerleweb.com
Дата: 23.10.13 15:22
Оценка: 6 (1)
Здравствуйте, dimgel, Вы писали:

Что-то сходу я не нашел как сделать для операций в самом классе.
Без указания выходит левая ассоциативность.
Как найду, сообщу.

Но есть вариант через макрос:

using Nemerle;
using Nemerle.Compiler;

// Left (100<200)
[assembly: Nemerle.Internal.OperatorAttribute("Test", "!!!", false, 100, 200)]

// Right (200>100)
[assembly: Nemerle.Internal.OperatorAttribute("Test", "^^^", false, 200, 100)]

namespace Test
{
  public macro @!!!(l, r)
  {
    <[ Q.AA($l, $r) ]>
  }
  
  public macro @^^^(l, r)
  {
    <[ Q.AA($l, $r) ]>
  }
}


Test:
using Nemerle.Collections;

using System;
using System.Console;

namespace Test
{
  class Q
  {
    public W : int { get; }
  
    public this(w : int)
    {
      WriteLine($"Constructor: $w");
      W = w;
    }
  
    public static AA(l : Q, r : Q) : Q
    {
      WriteLine($"Left: $(l.W), Right: $(r.W)");
      Q(l.W + r.W)
    }
  }

  module Program
  {
    Main() : void
    {
      def q1 = Q(1);
      def q2 = Q(10);
      def q3 = Q(100);
    
      WriteLine("\nLeft associative");
      def qq = q1 !!! q2 !!! q3;
    
      WriteLine("\nRight associative");
      def qq = q1 ^^^ q2 ^^^ q3;
    
      _ = ReadLine();
    }
  }

}


Результат

Constructor: 1
Constructor: 10
Constructor: 100

Left associative
Left: 1, Right: 10
Constructor: 11
Left: 11, Right: 100
Constructor: 111

Right associative
Left: 10, Right: 100
Constructor: 110
Left: 1, Right: 110
Constructor: 111

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[22]: Статические методы в любом их обличии это зло!
От: dimgel Россия https://github.com/dimgel
Дата: 23.10.13 18:09
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>namespace Test

_NN>{
_NN> public macro @!!!(l, r)
_NN> {
_NN> <[ Q.AA($l, $r) ]>
_NN> }
_NN>}
_NN>[/nemerle]

_NN>
_NN>namespace Test
_NN>{
_NN>  class Q
_NN>  {
_NN>    public static AA(l : Q, r : Q) : Q
_NN>    {
_NN>      WriteLine($"Left: $(l.W), Right: $(r.W)");
_NN>      Q(l.W + r.W)
_NN>    }
_NN>  }
_NN>


Я так понимаю, это позднее применение типизатора — после того, как макросы развёрнуты. Соответственно, оператор !!! будет работать со всеми классами, в которых есть метод AA. А как объявить на классе оператор "+" (т.е. один из тех, которые для других типов уже существуют)? Точно так же внутри namespace, чтобы при импорте этого namespace новая реализация "+" скрыла глобальную? Тогда получается, каждая реализация "+" должна дублировать функционал глобальной для стандартных типов, и вообще муть какая-то, не говоря уже о том, что вдруг я захочу работать сразу с несколькими разными типами, у каждого из которых свой "+". (А был бы "+" членом класса, а не статическим членом namespace, таких вопросов не возникло бы. Впрочем, возник бы вопрос про Int + Complex, ради решения которого в скале ввели такую мерзость как implicits.)
Re[23]: Статические методы в любом их обличии это зло!
От: _NN_ www.nemerleweb.com
Дата: 23.10.13 18:57
Оценка: 3 (1)
Здравствуйте, dimgel, Вы писали:


Конечно на все типы распространять операцию не стоит, неправильно и вредно.

В Nemerle нет проблем объявить практически любой оператор в классе.
class A
{
  public static @!^!(l : int, r : this) : this { A() }
}


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

Насчет макро-оператора.
Этот молоток помощнее всего , но и требует большей ответственности конечно.
Можно в макро-операторе проверять тип. (Тут есть всякие моменты типа отложенной типизации и прочего, пропустим =) )

Скажем:
namespace Test
{
  public macro @!!!(l, r)
  {
    T.Do1(ImplicitCTX(), l, r)
  }  
  
  module T
  {
    private Check(ty : Typer, e : PExpr) : void
    {
      // Это код чисто для примера, так делать не стоит :)
      when (ty.TypeExpr(e).Type.TypeInfo.FullName != "Test.Q")
        Message.FatalError("You must pass Test.Q");
    }
    
    public Do1(ty : Typer, l : PExpr, r : PExpr) : PExpr
    {
      Check(ty, l);
      Check(ty, r);
      
      <[ Test.Q.AA($l, $r) ]>
    }
  }
}


Если написать 1 !!! q2 то получим:

Main.n(40,16): error : You must pass Test.Q

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[22]: Статические методы в любом их обличии это зло!
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.10.13 23:55
Оценка: 16 (1)
Здравствуйте, _NN_, Вы писали:

_NN>Что-то сходу я не нашел как сделать для операций в самом классе.

_NN>Без указания выходит левая ассоциативность.

Дык теми же атрибутами. Только в первом параметре пустую строку надо задать.
Это задаем в макробиблиотеке:
[assembly: Nemerle.Internal.OperatorAttribute("", "^^^", false, 200, 100)]

А далее (в программе куда она подключена):

using System.Console;

[Record]
class A
{
  _value : int;
  
  public static @^^^(a : A, b : A) : A
  {
    A(a._value / b._value)
  }

  public override ToString() : string { $"A($_value)" }
}

module Program
{
  Main() : void
  {
    WriteLine(A(100) ^^^ A(50) ^^^ A(2));
    _ = ReadLine();
  }
}


В результате будет:
A(4)
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Статические методы в любом их обличии это зло!
От: Ромашка Украина  
Дата: 24.10.13 07:00
Оценка:
Здравствуйте, dimgel, Вы писали:
D> О чём тут уже говорили. Категорически отрицать полезность DI — так же глупо, как и категорически отрицать полезность статических функций.

Где я отрицал полезность DI? Я вообще не считаю что-либо в программировании полезным или вредным.

Я сказал, что если есть возможность написать без IoC или DI, то нужно писать без них. Я подозреваю, что это продолжение моей нелюбви к инверсии контроля в реальной жизни. Но мир несовершенен и IoC/DI приходится использовать в реальности и соответственно, моделируя эту реальность, в коде.


Всё, что нас не убивает, ещё горько об этом пожалеет.
Re[7]: Статические методы в любом их обличии это зло!
От: IT Россия linq2db.com
Дата: 24.10.13 23:35
Оценка: +1 :))) :)
Здравствуйте, Tom, Вы писали:

Tom>Т.е. если ты считаешь что в тестах никогда не надо подменять поведение даже строго детерминированной функции то можно считать что статические функции ок.


Вот они, люди с исковерканной DI судьбой.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Статические методы в любом их обличии это зло!
От: IT Россия linq2db.com
Дата: 24.10.13 23:40
Оценка: :)
Здравствуйте, Tom, Вы писали:

Tom>
Tom>void MakePayment(int account, DateTime paymentDate)
Tom>{
Tom>  var now = DateTime.UtcNow;

    ....
Tom>}
Tom>


Не вижу ни одного статического метода.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Статические методы в любом их обличии это зло!
От: dimgel Россия https://github.com/dimgel
Дата: 25.10.13 08:32
Оценка:
Здравствуйте, IT, Вы писали:

Tom>>Т.е. если ты считаешь что в тестах никогда не надо подменять поведение даже строго детерминированной функции то можно считать что статические функции ок.


IT>Вот они, люди с исковерканной DI судьбой.


А можно поподробнее? (Мне интересно, исковеркана ли моя судьба тоже и почему.)
Re[9]: Статические методы в любом их обличии это зло!
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 25.10.13 09:03
Оценка: 413 (17) +5
Здравствуйте, dimgel, Вы писали:

Tom>>>Т.е. если ты считаешь что в тестах никогда не надо подменять поведение даже строго детерминированной функции то можно считать что статические функции ок.


IT>>Вот они, люди с исковерканной DI судьбой.


D>А можно поподробнее? (Мне интересно, исковеркана ли моя судьба тоже и почему.)


Мой любимый вопрос коллегам, когда речь заходит о DI такой: так, что, эта штука помогает или мешает. И, к сожалению, в 90% случае ответ такой: "Блин, код настолько слабосвязный, что просто не понятно, с чего начинать вносить измененя и фиг поймеш, почему это дело перестает работать. При этом все покрыто тестами, но добавление нового теста занимает два ведра времени и содержит 40 строк инициализации моков. При этом на проде багов все равно два ведра".

Я довольно подробно изучал эту тему, что вылилось в целый цикл постов (они должны скоро появиться и на RSDN в виде нескольких статей):

Управление зависимостями
Фреймворки, библиотеки и зависимости
Аксиома управления зависимостями
Наследование vs. Композиция vs. Агрегация
Критический взгляд на принцип инверсии зависимостей
Инверсия зависимости на практике
Тестируемый дизайн vs. Хороший дизайн
Пример тестируемого дизайна
DI Паттерны. Construction Injection
DI Паттерны. Property Injection
DI Паттерны. Method Injection
DI Паттерны. Service Locator

При этом мне все еще кажется, что эту тему очень плохо понимают и слишком часто используют этот инструмент не по назначению!

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

Тут же вопрос такой: зачем мы используем все эти инструменты, типа DI, тестов, думаем над дизайном? Ведь тестируемость — это не самоцель, очевидно. Хороший дизайн и покрытие тестами — это попытка упростить сопровождаемость кода, что, в конечном итоге приводит к уменьшение таких показателей, как time-to-market. Вот наша цель, создать систему, которая будет отвечать требованиям, не будет ломаться от каждого чиха, в него будет легко вносить изменения и использовать повторно.

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

Как тут уже писали: чистые функции (функции без побочных эффектов) — это идеальный инструмент построения сложных систем, поскольку проверив их однажды мы гарантируем их работу в любом другом контексте. Именно об этом писал Буч при описании проблем построения сложных систем и принципов борьбы со сложностью. Так, во всех этих примерах, я привожу примеры комбинации ОО и ФП подхода, когда я заворачиваю в объекты операции, по сути, являющиеся "чистыми" функциями. Даже в рамках ООП мы можем оставаться без побочных эффектов, когда все, что делает объект это берет аргументы и возвращает результат, а конструктор является лишь другим способом протаскивания входных данных этой операции (и мы получаем такие себе ОО фасады, под которыми прячется ФП подход).

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

Ведь помим преждервеменной оптимизации более насущной проблемой в индустрии является преждевременное обобщение (premature generalization). Мы не знаем, где в коде узкое место и точно также мы не знаем, в каком конкретно месте в системе нам потребуется расширение функционала. Поэтому лучший способ борьбы со сложность — это простота: простые компоненты с минимумом зависимостей и с минимум побочных (а лучше вообще без них) .

В общем я это все к чему: используйте DI, статические функции, goto и все что угодно еще, если их использование обеспечивает радость для вашей системы в виде простоты сопровождения и уменьшения времени ее выпуска (time-to-market). Пользуйтесь любым инструментом, просто делайте это с умом
Re[5]: Статические методы в любом их обличии это зло!
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.10.13 11:03
Оценка: +4
Здравствуйте, Tom, Вы писали:

Tom> var now = DateTime.UtcNow;


Мне вот интересно, почему всегда приводят в пример DateTime.Now? Ничего поинтереснее не удается придумать?
Этот пример — дурной, потому что использовать в конкретном вычисляющем методе явный вызов Now — отличный способ прострелить себе ногу. Обычно интервалы времени передают в рассчетную функцию в параметрах, потому что рассчеты к документам привязываются, а не к текущему времени на компьютере.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: Статические методы в любом их обличии это зло!
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.10.13 11:38
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Я про то что статические методы ставят крест на DI/IoC и убивают все прелести данных патернов


Вы просто не умеете статические методы готовить.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[11]: Статические методы в любом их обличии это зло!
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.10.13 11:38
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>А SRP это уже совсем не ООП.


Круто, чо. А low coupling/high cohesion это тоже совсем не ООП?
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[12]: Статические методы в любом их обличии это зло!
От: artelk  
Дата: 25.10.13 12:59
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Tom, Вы писали:


Tom>>А SRP это уже совсем не ООП.


AVK>Круто, чо. А low coupling/high cohesion это тоже совсем не ООП?


А что, они и для модулей имеют смысл, причем тот же.
Хотя да, "совсем не" != "не только".
Re[10]: Статические методы в любом их обличии это зло!
От: Evgeny.Panasyuk Россия  
Дата: 25.10.13 14:22
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Как тут уже писали: чистые функции (функции без побочных эффектов) — это идеальный инструмент построения сложных систем, поскольку проверив их однажды мы гарантируем их работу в любом другом контексте. Именно об этом писал Буч при описании проблем построения сложных систем и принципов борьбы со сложностью. Так, во всех этих примерах, я привожу примеры комбинации ОО и ФП подхода, когда я заворачиваю в объекты операции, по сути, являющиеся "чистыми" функциями. Даже в рамках ООП мы можем оставаться без побочных эффектов, когда все, что делает объект это берет аргументы и возвращает результат, а конструктор является лишь другим способом протаскивания входных данных этой операции (и мы получаем такие себе ОО фасады, под которыми прячется ФП подход).


Кстати, если побочные эффекты не мешают — то можно даже с ними. Функции результат которых полностью зависит от входных аргументов, но которые могут иметь side-effect'ы (не влияющие на возвращаемый результат), называются регулярными.
Re[10]: Статические методы в любом их обличии это зло!
От: . Великобритания  
Дата: 26.10.13 23:22
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST> Как тут уже писали: чистые функции (функции без побочных эффектов) — это идеальный инструмент построения сложных систем, поскольку проверив их однажды мы гарантируем их работу в любом другом контексте. Именно об этом писал Буч при описании проблем построения сложных систем и принципов борьбы со сложностью. Так, во всех этих примерах, я привожу примеры комбинации ОО и ФП подхода, когда я заворачиваю в объекты операции, по сути, являющиеся "чистыми" функциями. Даже в рамках ООП мы можем оставаться без побочных эффектов, когда все, что делает объект это берет аргументы и возвращает результат, а конструктор является лишь другим способом протаскивания входных данных этой операции (и мы получаем такие себе ОО фасады, под которыми прячется ФП подход).

Мне не совсем это понятно. Тут наверное имеется в виду, что объекты должны быть stateless или immutable? Да, конечно, это делает всё проще, но теряется эффективность; в большинстве промышленных языков с этим будет проблемой.
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[11]: Статические методы в любом их обличии это зло!
От: alex_public  
Дата: 28.10.13 09:26
Оценка:
Здравствуйте, ., Вы писали:

.>Мне не совсем это понятно. Тут наверное имеется в виду, что объекты должны быть stateless или immutable? Да, конечно, это делает всё проще, но теряется эффективность; в большинстве промышленных языков с этим будет проблемой.


Ну например в D это встроено в язык. Т.е. там сам компилятор отслеживает эти вещи. При этом D — язык системного программирования с доступом к указателям, ассемблеру и т.п.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.