All streams
Search
Write a publication
Pull to refresh
14
0
boris podchezertsev @speakingfish

Системный архитектор

Send message
Впервые подагра у меня возникала на фоне употребления в пищу говяжих почек. Конечно можно сказать что количество почек по сравнению с остальной едой смешное. Также симптомы начинали появлятся на фоне употребления острого перца — а ведь его количество смехотворно.
Безфторовые пасты выпускаются несмотря на то что никто не ест специально пасты со фтором.
>> Для использовании наследования, Builder разделяется на две части (один с полями, другой — с методом создания) следующим образом:
Так делать не стоит, сейчас объясню почему

Это написано про минимальный билдер, который сооружается из double brace initialization, а он не является fluent-интерфейсом.
Mega Builder является fluent-интерфейсом, но он не может поддерживать такого сокращённого наследования с помощью пареадресации унаследованному билдеру, поскольку в унаследованном классе могут быть вообще совершенно другие валидные сочетания параметров, и поэтому их надо полностью описывать заново.
В статье есть все ссылки на описываемый код: github.com/speaking-fish/java-sf-builder-mega github.com/speaking-fish/java-sf-builder-simple-example
Пример билдера который никак нельзя воткнуть ни в конструктор ни в основной билдер:
public class LocalBuilderExample {
    
    protected final double base;
    
    public LocalBuilderExample(double base) {
        super();
        this.base = base;
    }

    public class BaseBuilder extends NewBaseClass.BuilderImpl {
        public NewBaseClass create() {
            if(!Double.isNaN(base)) {
                first  = (int) Math.round(base) + first;
                if(!Double.isNaN(base)) {
                    second = base + second;
                } else {
                    second = base;
                }
            }
            return new NewBaseClass(this);
        };
    }
}

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

Скажем, вот код, эквивалентный вашим NewBaseClass.java и NewChildClass.java (где-то в два раза короче):

В вашем коде не хватает констант для дефолтных значений — это соответственно увеличит код.
Добавим их и сравним построчно код игнорируя пустые строки (я убрал модификаторы доступа чтобы влезло):
C#                                              Java
class BaseClass {                           =   class BaseClass {                                       
                                             
                                                                                                                       
                                             +  static class BuilderImpl {                                                                                                          
                                             +      int    first  = -1        ;                                                                                                        
                                             +      double second = Double.NaN;                                                                                                        
                                             +      String third  = null      ;                                                                                                        
                                             +  }                                                                                                                                             
                                             +5
                                             +  static class Builder extends BuilderImpl {                                                                                                                                                                
                                             +      BaseClass create() { return new BaseClass(this); }                                                                                                                                              
                                             +  }                                                                                                                                                                                                                
                                             +3                                                                                                                                               
const int    DEFAULT_First  = -1        ; +       
const double DEFAULT_Second = double.NaN; +       
const string DEFAULT_Third  = null      ; +       
                                          +3                                                                         
const int    First  { get; }                =   final int    first ;                                           
const double Second { get; }                =   final double second;                                       
const string Third  { get; }                =   final String third ;                                       
                                                                                                                     
                                             +  int    first () { return first ; }                            
                                             +  double second() { return second; }                            
                                             +  String third () { return third ; }                            
                                             +3                                                                      
BaseClass(                                  =   BaseClass(                        
    int    first  = DEFAULT_First ,         =       BuilderImpl builder                  
    double second = DEFAULT_Second,       +                                       
    string third  = DEFAULT_Third ,       +
) {                                       +2=   ) {                                       
    First  = first;                         =       this.first = builder.first ;                                     
    Second = second;                        =       this.second= builder.second;                                     
    Third  = third;                         =       this.third = builder.third ;                                     
}                                           =   }                               
                                                  
}                                           =   }                                  
                                                                                  
                                            =12                                                                                                                                 
                                          +5 +11
                                             +6
                                          17  23    
                                              
class ChildClass : BaseClass {              =   class ChildClass extends BaseClass {                                      

                                             +  static class BuilderImpl extends BaseClass.BuilderImpl {                                                                    
                                             +      Object fourth = null;                                                                                                         
                                             +3 }                                                                                                                                        
                                                                                                                                                                                         
                                             +  static class Builder extends BuilderImpl {                                                                                        
                                             +      ChildClass create() { return new ChildClass(this); }                                                                    
                                             +3 }
                                                                                                                                                                                        
const object DEFAULT_Fourth = null;       +          
                                          +1    
const object Fourth { get; }                =   final Object fourth;

                                             +  Object fourth() { return fourth; }
                                             +1 
ChildClass (                                =   ChildClass(
    int    first  = DEFAULT_First ,         =       BuilderImpl builder
    double second = DEFAULT_Second,       +     
    string third  = DEFAULT_Third ,       +                                                                          
    object fourth = DEFAULT_Fourth        +                                                  
) : base(                                 +3=   ) { super(                                                                     
    first ,                                 =       builder                        
    second,                               +                                                                          
    third                                 +                                  
) {                                       +2=       );                                                  
    Fourth = fourth;                        =       this.fourth = builder.fourth;                                    
}                                           =   }                                                                    
                                                                                                                       
}                                           =   }                                                                        
                                            =10      
                                          +6 +7
                                             +1    
                                          16 17
                                          
                                            =22
                                         +11 +18
                                             +7
                                         33   40              

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

Ну конечно в варианте с большим количеством параметров гораздо легче ошибиться (несоответствие типа, несоответствие порядка)

В C# 7 планируется сделать что-то вроде этого

Генерация конструкторов? Но тогда проверки сделать не получится.

Многоуровневая.

Можно пример?
По своему опыту не рекомендавал бы «реминерализующие» добавки в том числе и SPLAT Биокальций людям склонным к подагре. При этом другими SPLAT пользуюсь нормально.
По поводу варианта А — в этом случае наверное не может быть final полей и не могут выполнятся проверки.
Вот вариант Б — да, именованные параметры со значениями по умолчанию сделали бы многие простые билдеры ненужными, однако…
Сейчас я добавил сокращённые версии классов с минимальным билдером. Там по новым ссылкам можно их увидеть github.com/speaking-fish/java-sf-builder-simple-example — классы New*
В них в конструктор класса передаются не все параметры, а только билдер. Т.е. теперь не надо перечислять все параметры в функциях.
Вы же согласны что лучше иметь сложные проверки отдельно от конструктора, в билдере.
Т.е. тогда в C# билдер останется, но не отдельным классом а отдельной функцией, так?
Тогда возникает вопрос, а как будет работать наследование?
Если у меня наследуется класс билдера — то он наследует все свои поля и их потом не надо опять все перечислять.
А что с параметрами функции? Их можно унаследовать или в унаследованных классах придётся как перечислять всё больше и больше параметров и делать какие-то проверки чтобы их случайно не упустить, и в каждом классе потом искать и исправлять дефолтные значения или определять еще для них константы и использовать константы?
Поясните этот момент.
Это вообще скорее не C# касается, а всех языков с возможностью использования именованных параметров функций.
Т.е. в результате, отдельный класс билдера будет проще использовать и в таких языках.
PS. А инициализация коллекций и словарей многоуровневая или только первый уровень поддерживается?
Книга про компьютеры которая произвела на меня в детстве неизгладимое впечатление — «Компьютер Творец». Авторы: Дональд Мичи, Рори Джонстон. Издательство «Мир» 1987г.
www.ozon.ru/context/detail/id/28159440/?utm_source=livelibru&utm_medium=partner
www.libex.ru/detail/book58203.html
Книга двух английских авторов, ученого и журналиста, в увлекательной форме рассказывает о современном уровне и перспективах развития одной из самых молодых наук — искусственного интеллекта, о создании «умных» машин, которые все решительнее внедряются во все сферы человеческой деятельности: производство, науку, административно-управленческую деятельность, транспорт и даже искусство.
Адресована всем, кто интересуется достижениями современной науки и техники.
Содержание
Новые знания от ЭВМ
1. Слепой поиск и незнание
2. Машина становится экспертом
3. Машинные и человеческие возможности
4. Мысли о мышлении
5. Опыт и открытие
6. Созидание нового знания
7. Метафора наизнанку
8. На пути к модельным небесам
9. А была ли кошка?
10. Изобретения на благо человечества

В книге рассказывалось о различных аспектах ИИ — о восприятии и анализе информации, шахматах, экспертных системах, системах логического вывода и многом другом.
Даже в википедии есть ссылки на эту книгу: шахматы, Eurisko.
И действительно.
habrahabr.ru/post/233797
---Add elements ( 6kk )
LinkedList: 2264 ms
ArrayList: 493 ms
ArrayList is faster
Да вы правы, такое не прокатит.
Но, в общем, все уже привыкли не только к особенностям анонимных классов, но и вовсю используют лямбды Java 8 и знают про final/effectively final.
Я например чаще использую for each, тогда в аналогичном коде для Java 8+ ничего не надо будет менять, только для Java < 8 надо будет добавить final:
        for(final int i : new int[] {1,2,3}) {
            new MyClass.Builder(){{ first = i; third = "3"; }}.create();
        }

Идея обвязывать заодно первый уровень коллекций интересная.
По идее, если уж так делать, то можно было бы и следующие уровни обвязывать и не только коллекций но и просто вложенных классов.
Почему коллекции инициализируются только или элементами ли коллекциями? Что если я использую ленивые итераторы?
Непонятно в каком месте реализовывать валидацию.
Посмотрел сгенерированный код projectlombok.org/features/Singular-snippet.html
Метод public SingularExample build() как-то переусложнён — всё это можно было бы спокойно вынести в хелперы.
Почему списки билдера инициализируются ArrayList а не LinkedList?
Непонятно как организовать обязательные поля и как соорудить контекстно-зависимый билдер.
То есть если ветер такой слабый, то буря не смогла раскачать МВА, антенна не смогла сорваться и с Уотни ничего не случилось? О боже, как я теперь смогу спокойно посмотреть фильм?
Зато лошадь хорошо масштабируется в упряжки до 6 штук. Сможете такое провернуть с авто?
Тоже копал в эту сторону. В результате пока сделал обмен через стандартные пайпы ввода-вывода на Java/C++/Pascal Linux/Windows intel/ARM. Но у меня пока синхронный rpc. Делал для простого разделения на процессы, миграции по частям, заворачивания ненадёжных dll в перезапускаемые процессы… Пока в планах стыки на javascript и python. Вообще, дальше в планах добавить к этому shared memory для текущего обрабатываемого пула данных на memory-mapped файлах, чтобы в части случаев не просто сократить передачу данных через пайпы но и вообще избежать её.
«А поскольку топлива будет потрачено мало, то больше энергии останется для обеспечения работы научных инструментов станции.»
Какая тут связь? Двигатели химические на метилгидразине а не ионники, энергоустановка — РИТЭГ а не топливные элементы.
Чтобы такое не прокатывало в таких аттракционах обычно делают болтающееся седло, на котором сложно удержаться не держась за руль.
Ну допустим не в два а в полтора раза дороже. За увеличение скорости до двух раз. Это было бы уже неплохо.
Для целей считывания/записи одновременно двух секторов одного цилиндра — смысла нет. Но для разных цилиндров таки есть, поскольку экономится время позиционирования. Ну и скорость передачи данных будет больше в два раза, хоть и ценой двукратного увеличения стоимости, но зато в одном корпусе.
В момент выхода Windows 95, по сравнению с существующей OS/2 Warp была просто пустой оболочкой для вызова старых 16-битных программ оставшихся от Win3.11. Должно было ещё пройти время чтобы софт начал появляться.
ps. А диалоги неизменяемого размера в винде до сих пор.
Не понял. Почему в статье написано про KUbuntu а на скриншоте второй пункт меню — Справка по SUSE?
ps. Так что у них тогда еще, возможно, Windows 2000 была.

Information

Rating
Does not participate
Location
Yerevan, Yerevan, Армения
Date of birth
Registered
Activity