Программа для нарезки хлеба

Автор оригинала: John D. Cook
  • Перевод
Ниже краткое изложение опубликованного ранее поста Почему я ненавижу фреймворки :

В средневековые времена программирования, к данным мы применяли функции. Для того, чтобы нарезать хлеб, брали структуру «хлеб» и передавали ее как параметр функции «нарезать»:

нарезать(хлеб);

Потом пришла эпоха объектно-ориентированного программирования. И вместо функии «нарезать», нам надо попросить «хлеб» нарезать себя — вызываем метод «нарезать» у объекта «хлеб»:

хлеб.нарезать();

Очевидно, что это значительное улучшение.

В настоящее время объектно-ориентированное программирование стало еще изысканнее. Сначала мы создаем объект «хлеборезка» и затем просто передаем ему «хлеб» для «нарезки»:

Хлеборезка хлеборезка = new Хлеборезка();
хлеборезка.нарезать(хлеб);


Прогресс налицо.

Вывод: Во всем нужно знать меру. Иногда мне нужен просто банан, а не горилла с бананом.

Похожие публикации

Средняя зарплата в IT

113 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 5 709 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 81

    +18
    зато можно сделать не просто хлеборезку, а Нож, который будет резать все, что ему дадут. Это и есть создание инструментов вместо грубого ручного труда каждый раз
      +4
      Просто нож — это уже устарело. Надо уже нож со сменными насадками (для хлеба, для мяса,...)- более современно и универсально. Правда, еще надо будет функцию дописать — «смена_насадки».
        +4
        DI как механизм для насадок в самый раз :)
          +2
          Очень удобно нарезать хлеб, создавая у него метод нарезки через фабрику резалок! Лучше это делать в конструкторе.

          var bread = new Bread();
          bread.cutter = Factory.cutter( bread );
          bread.cutter.cut()
            +7
            почему cutter агрегирован в bread? вот представьте вы едите хлеб, а в нём… абстрактный нарезатель. единственная ситуация, в которой это хорошо, если вы сидите например в темнице, а нарезатель реализован напильником
              +1
              А почему Вы думаете, что такая ситуация не вероятна? Мы должны всё предусмотреть!
                +2
                а если в батон нужно засунуть не реализацию нарезателя, а записку? или батон с начинкой сделать? тогда нам нужен обобщённый батон, батон с дженериками!
            0
            Нож со сменными насадками тоже устарело.
            +3
            Зачем мне Нож, которым можно резать все, что дадут, если мне нужно нарезать хлеб? (Конечно, если вы не хотите, чтобы вашу хлеборезку можно было потом легко переделать в жатку зерноуборочного комбайна или, например, сделать из нее оружие против зомби)
              0
              А как вы себе представляете нарезку хлеба без ножа? Ниткой? Или так?

              куски множество_кусков = [количество_кусков];
              for ( int счетчик = 0; счетчик < количество_кусков; ++счетчик )
              {
              множество_кусков[счетчик] = хлеб->мякиш / количество_кусков;
              }


              Вы выполните поставленную задачу, и не нужно будет писать отдельную функцию «нарезать»
                0
                Я имел в виду не совсем это. Я совсем не предлагал резать хлеб ниткой или кредитной картой вместо ножа.

                Вот предположим, что мне нужно нарезать хлеб. Просто нарезать хлеб, и ничего больше.
                Для этого я хочу взять нож, отрезать хлеб, и забыть навсегда о хлебе и ножах.

                Как другой вариант, мне предлагают использовать (или даже сделать самому) ФабрикуРежущихИнструментов, чтобы создать УниверсальныйМегаНож, которым можно резать что угодно. Для УниверсальногоМегаНожа мне нужно сделать ЛезвиеДляХлеба (лезвия съемные, на все случаи жизни, не забывайте). При этом мне нужно знать, какое именно Лезвие я хочу сделать, ведь ФабрикаРежущихИнструментов делает любые лезвия, и мне нужно настроить ее так, чтобы она сделала то лезвие, который идеально мне подойдет. Раобраться в том, какие вообще лезвия я могу произвести, выбрать из них то, которое мне подходит больше всего, и наконец изготовить.
                После этого я, довольный собой, устанавливаю ЛезвиеДляХлеба в УниверсальныйМегаНож, режу хлеб, и… забываю навсегда о хлебе и ножах?

                Конечно, ФабрикуРежущихИнструментов можно потом использовать для других целей. Да и УниверсальныйМегаНож, наверное тоже. Но я хотел сказать, что здесь важно знать меру. Иначе может получится, что мы сделали ФабрикуРежущихИнструментов в расчете на то, что сможем каждый раз делать подходящие инструменты, а потом оказалось, что кроме хлеба и резать-то нечего.
                +1
                Именно поэтому выгодно брать не Нож, а Фабрику Режущих Инструментов, которая сможет создавать хлеборезки, оружие против зомби и комбайны.
              +1
              Ну Вы же сами прекрасно понимаете, что первый вариант работает только на тривиальных задачах? А кроме того даже сейчас никто не запрещает нарезать хлеб функцией. Кроме того, хлеборезка может резать не только хлеб но и батоны и колбасу и всё остальное что наследуется от класса «мягкая небольшая еда».
                +6
                Если ядро Linux — это тривиальная задача, то я с вами соглашусь =)
                  +1
                  У линукса есть преимущество — он покрыл всё железо и работает. Но неприятных моментов в нём такое количество, что только ой. Чего стоит например, возможность любому драйверу звуковой карты обрушить сервер любой сложности.
                    +8
                    А зачем нужен драйвер звуковой карты на сервере? :)
                      +3
                      в этом и печаль ситуации. Драйвер ни к чему, но из-за того что он вызывается, он может все сломать
                        –1
                        Кем же он вызовется, если мы не гоняем на сервере звуковых задач?
                          +8
                          А вот вы полностью уверены, что никакой демон не захочет разочек бипнуть при ошибке?
                            +2
                            А демон если захочет обрушит сервер с любыми драйверами.
                              +3
                              А не должен бы иметь такой возможности. Самоубиться — не вопрос, сколько угодно. Обрушить сервер — ни при каких обстоятельствах.
                                +3
                                Демоны, они такие… Коварные!
                                  +2
                                  «Бииип!» — бикнул демон, довольно потирая руки и устраивая Апокалипсис.
                          +6
                          Потому что с ним собрано дефолтное ядро, а воткнутая USB объявило себя звуковухой.
                            +1
                            собрано это самое ядро с модулями, и запретить загрузку лишнего — вопрос пары строк внутри /etc/modprobe.d
                          0
                          Use kernel preemption, Luke!
                            0
                            Простите, что? Возможность вытеснять часть кода ядра скедулером? Как это поможет от кривого драйвера?
                              0
                              «There are two main benefits to this method in monolithic and hybrid kernels, and answer one of the main criticisms of monolithic kernels from microkernel advocates, which is that;
                              1) A device driver can enter an infinite loop or other unrecoverable state, crashing the whole system
                              2)Some drivers and system calls on monolithic kernels are slow to execute, and can't return control of the processor to the scheduler or other program until they complete execution.»
                                +2
                                Как это спасёт от банального oops? Записал в памяти не туда — panic, прочитал не оттуда — panic, ушёл в дедлок в нижней части прерывания — panic.
                                  0
                                  Расширим список: разлил админ кофе на сервер — oops, случилось наводнение — panic, упала атомная бомба рядом — panicpanicpanic.
                                    0
                                    1) В стойку нельзя разлить кофе :)
                                    2) Случилось наводнение — а зал на высоте
                                    3) В атомную бомбу я верю меньше, чем в кривой драйвер HID и неадекватную реакцию ядра на втыкание странной клавиатуры.
                                      –2
                                      1) Поверьте — можно :) Лично был свидетелем
                                      2) А электричество и интернеты к нему откуда идут? ;)
                                      3) Вероятность — 50%. Или упадет — или не упадет.
                                        0
                                        Электричество к нему идёт с упсов и всякой электрической хрени, названия которой я не знаю. Упсы запитываются от двух вводов и генераторов. Которые (сюрприз) стоят на специальном возвышении.

                                        Интернет к серверам идёт по оптике через несколько колодцев.
                            0
                            В нём так же есть возможность не собирать ненужные драйвера и не загружать собранные, вы же знаете.
                              0
                              И вы действительно на RHEL'е будете собирать СВОЁ ядро вместо штатного от RH? Ну-ну.
                                0
                                Во-первых это «неприятный момент» не линукса, а вашей модели использования дистрибутива.
                                Во-вторых, воспользуйтесь таки /etc/modprobe.d/blacklist.conf или как он в RHEL называется.
                                В-третьих, не вижу большой проблемы собрать своё ядро, при наличии src.rpm. Время от времени я так и делаю, правда для федоры.
                                  0
                                  Надеюсь, вы понимаете разницу между федорой и RHEL'ом? Насчёт blacklist — блеклистить всё — особое развлечение админа.

                                  Кроме того, какой из драйверов вы собираетесь блеклистить? USB-SATA? USB-Firewire? Их же тысячи, а ошибка может быть в банальном USB-HID для мышки.

                                  Проблема тут в другом — в том, что второстепенный драйвер второстепенного устройства может уронить mission-critical задачу.
                                    0
                                    Насчёт blacklist — блеклистить всё — особое развлечение админа.

                                    find + sed — это скорее обычное развлечение.

                                    Кроме того, какой из драйверов вы собираетесь блеклистить?

                                    Вы могли бы блеклистить все драйвера которым вы не доверяете.

                                    Проблема тут в другом — в том, что второстепенный драйвер второстепенного устройства может уронить mission-critical задачу.

                                    У вас были такие случаи на практике? Что же вы предпринимали в качестве контрмер?
                                      0
                                      Падение сервера из-за кривых драйверов — бывали. Решение — кластеризация, поиск прямых драйверов. Короче, ничего хорошоего.
                          +4
                          Первый вариант прекрасно работает в языках с функциональной парадигмой, в которой благодаря этому толпа навороченных паттернов типа фабрик и прочего тупо становится ненужной
                          +23
                          Содержание исходного поста передано неполно.

                          Дальше идет:

                          1. Резалка — интерфейс к хлеборезке (или ножу);
                          2. Фабрика резалок;
                          3. IoC контейнер, служащий для поиска фабрики;
                          4. Средство конфигурации IoC контейнера на основе xml-файла;
                          5. Специализированный редактор конфигурационных файлов;
                          6. Средство для автоматической генерации специализированных редакторов на основе спецификации на промежуточном языке;
                          7. Препроцессор промежуточного языка с поддержкой модульности.
                            +2
                            Вы еще забыли про паттерн костыль чтобы все это дело после небольших изменений как-то продолжило работать :)
                              +2
                              Достаточно. Всё Java-фрэймворки уже перешли на аннотации вместо xml-конфигураций. Пункты 4,5,6,7 можно исключить. Уж не знаю как там у вас в дотнете.
                                0
                                Аннотации — хорошая вещь, если только не нужно предусматривать изменение настроек пользователем.
                                  0
                                  Ну, как раз там в основном не настройки пользователей, конфигурирование приложения.
                                    0
                                    Несколько лет назад один прогер вынес пользовательскую настройку в секцию конфигурационного файла (использовался IoC контейнер Castle.Windsor)… Сколько мы его ругали, но все бесполезно. Тот разработчик давно в Америку улетел, а мы вынуждены поддерживать обратную совместимость.
                              +1
                              >>new Хлеборезка()
                              это круто)
                                +5
                                new ПорезанныйХлеб()
                                Вот что круто)
                                  +1
                                  А что, продаётся же в магазинах порезанный хлеб — вот это забота о прикладных программистах!
                                0
                                Пища пища=new Хлеб(Хлеб.тип.Белый);
                                Резалки резалка = new пища.получитьРезалку().class();
                                резалка.резать(пища);

                                Кто глубже?
                                +5
                                Напомнило метафору «земля.Копайся()» из поста Применимость DDD и последующую дискуссию в комментах.
                                  0
                                  И тем не менее если надо сделать много работы, которую кто то уже делал, то фреймворки помогают. Фрейворки экономят очень мнгоо времени, когда работы много и она более менее стандартна. Я видел самописные ORM. Если бы их создатели использовали Hibernate или что то подобное, они бы сэкономили много усилий.

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

                                  такое печатление, что автор делает выводы о полезности фреймворков на основе того, насколько они полезн6ы для написания Hello World
                                    +5
                                    > Хлеборезка хлеборезка = new Хлеборезка();

                                    Насколько я знаю в яваскриптах можно и так:

                                    Рукомойник рукомойник = new Хлеборезка();

                                    или даже так:

                                    Хлеборезка хлеборезка = new Рукомойник();
                                      +2
                                      если (тип (стол.хлеб) === "нёх") {
                                          стол.хлеб = хлебница.достать("батон");
                                      }
                                      var куски = стол.хлеб.отрезать(5);
                                      
                                        +3
                                        Только бы 1С пронесло мимо этого поста…

                                        P.S. «var» следует заменить на «пер»
                                      0
                                      А чего источник не указали?
                                      www.johndcook.com/blog/2012/03/18/sliced-bread/
                                        0
                                        Извиняюсь, пропустил =)
                                        +1
                                        Аналогии неправильные. Когда я слышу «фреймворки не нужны», это значит, что человек либо не умеет ими пользоваться, либо просто взял не тот инструмент для решения задачи и ругается.

                                        Проводя аналогии, например IC и DI — это стандартные розетки и провода для хлеборезки. То есть до них все делали свою хлеборезку со своим собственным дизелем, своим типом двигателя и своим напряжением питания (а кто-то вообще на бензине), а потом догадались сделать розетку на 220В и 50 Гц и пошл-поехало. А теперь вот приходят люди и говорят: мне не нужна розетка на 220В, я свой дизель-генератор лучше соберу. Ну хозяин-барин, конечно.

                                        Другой вопрос, что ява-фреймоврки излишне утяжелены и усложнены, но это уже не мои проблемы. Также, люди любят делать излишнюю расширяемость: например, нарежут все на кучу абстрактных классов и фабрик с наследоваием, вместо того, чтобы написать if/else. У нас в PHP такой проблемы нет: хочешь, пиши фреймворки с XML-конфигами и DI, хочешь пиши через функции и глобальные переменные.
                                          +25
                                          Итак, код через 5 лет с фреймворком:

                                          var хлеборезалка = new Хлеборезалка()
                                          хлеборезалка.installFeature(Хлеборезалка.Фичи.ЗубчатыйНож);
                                          хлеборезалка.installFeature(Хлеборезалка.Фичи.КонтрольРасстояния);
                                          хлеборезалка.installFeature(Хлеборезалка.Фичи.ОтрезаниеПальцев);
                                          
                                          хлеборезалка.configure(Configuration.FromFile("фичи.xml"));
                                          хлеборезалка.setPreferences(дядяВася.getFeaturesContainer().getFor(typeof(Хлеборезалка)));
                                          
                                          хлеборезалка.setOutputSink(дядяВася.Рука.createInputSink());
                                          
                                          хлеборезалка.нарезать(хлеб);


                                          И без фреймворка:

                                          // функция нарезает хлеб
                                          // результат будет в глобальной переменной global_нарезанный
                                          function нарезать(хлеб) {
                                              var зубчатыйНож = this.caller.equalTo(дядяПетя) || 
                                                  (this.caller.equalTo(дядяВася) && global_target.is(морковка)/*хак для морковки - bug #2114 от 2001-02-11*/);
                                              var номер_куска = 1;
                                              while (true) {
                                                  var размер = is_defined(global_размеры_кусков) ? global_размеры_кусков[номер_куска]; // todo: проверить, что размер массива не меньше количества кусков
                                                  // pbi # 332: теперь мы учитываем персональные размеры кусков
                                                  if (caller.хлеборезалка_размеры_кусков) {
                                                      размер = caller.хлеборезалка_размеры_кусков; // todo: сделать чтобы можно было задать массив и тут
                                                  }
                                                  var кусок = отрезатьКусок(хлеб, размер, зубчатыйНож ? "сложно" : "просто");
                                                  global_нарезанный.push(кусок);
                                                  номер_куска++;
                                                  if (дядяВася && дядяВася.Рука) {
                                                      положить_в_руку(кусок);
                                                  }
                                              }
                                              if (caller.is(дядяПетя) 
                                                      && getFileText("prefs.xml").node('//нарезка[отрезатьПалец]').exists() // bug # 34452 от 2005-02-03: отрезать палец надо только если это задано в насторйках
                                                      ) { 
                                                  нарезать(caller.finger); // тут же отрежем палец дядеПете, если он этого хочет
                                              }
                                          }

                                          Какой из них будет проще забрать в другой проект и (или) сконфигурировать? :)
                                            +5
                                            Такой код нужно читать вслух и с выражением. Чего стоит только
                                            global_нарезанный.push(кусок);

                                              +1
                                              Сконфигурировать проще второй, поскольку его файл конфигурации еще не превратился в программу на мета-языке.

                                              А забирать в другой проект… я лучше уволюсь.
                                                +1
                                                Ни тот ни другой
                                                  +2
                                                  у вас при отрезании пальца нету проверки на существование пальцев, вдруг дядя Вася уже не впервой нарезает хлеб;)
                                                    0
                                                    На какой сам сядешь, на какой мать посадишь?
                                                    0
                                                    Код на русском выглядит так знаком по 1С…

                                                    Процедура ОбработкаВнешнегоСобытия(Кто,Что,Зачем)
                                                    Если Кто="LRC_Modem" Тогда
                                                    Если Что="LRC_Modem" Тогда
                                                    Сообщить(Зачем);
                                                    КонецЕсли;
                                                    КонецЕсли;
                                                    КонецПроцедуры //ОбработкаВнешнегоСобытия
                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                        –1
                                                        Изврат по фреймворковски:
                                                        fact = new FactoryCreatorFactory()
                                                        conf = new BladeConfigurator()
                                                        fact.add(conf)
                                                        conf.setMaterial(new Ferrum())
                                                        realBladeFactory = fact.buildFactory()
                                                        realBladeFactory.setLength(400)
                                                        realBladeFactory.setWeight(30)
                                                        realBladeFactory.addFacet(new BladeFacet('teeth')) // for more usable bread slicing
                                                        blade = realBladeFactory.buildRealBlade()
                                                        blade.sharpen()
                                                        blade.wash()
                                                        bread = realWorldSingleton::getInstance().getStorageCollection().getFoodStorage().getBread()
                                                        bread.sliceYouSelfBy(blade)
                                                        //profit :)
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                            +1
                                                            Можно гыгыкать сколько угодно, но хлеб всё-таки сам себя без привлечения других сущностей не нарежет. Если вас устраивает хлеб, наломанный голыми руками — то пожалуйста. Но самое интересное, что руки тоже кому-то принадлжат.
                                                            Так что — так себе аналогия. ООП не так уж глупо, как его хотят выставить.
                                                              0
                                                              Только надо уметь во врмея остановиться, а то руки с пальцами, а пальцы с ногтями, а ногти с маникюром, а еще из костей мышц и кожи, а все это из клеток, молекул, атомов, протонов, квакрков, струн.
                                                                0
                                                                не вижу в этом ничего плохого, инкапсуляция — это определенно хорошо.
                                                              +1
                                                              Вспомнилось: в колхозе «Рассвет» был сделан первый в мире комбайн по уборке грибов!
                                                              Теперь водителю осталось только найти и гриб и оп… остальное дело техники.
                                                                +1
                                                                Пойду поем
                                                                  –1
                                                                  У меня так

                                                                  $cutted = Bread::Instance() -> getSlices(n);
                                                                  $cutted = Bread::Instance() -> useBlade(«razor») -> getSlices(n);

                                                                  ну и тд.
                                                                    –1
                                                                    простите фигню спорол я с температурой (((

                                                                    Там конечно грамотнее было бы

                                                                    Slicer::Instance() -> setObject(Bread) -> setBlade(«razor») -> getSlices(n);
                                                                    +2
                                                                    Современный подход к ООП — это ещё не самое страшное: всегда можно создать специальный язык программирования для нарезания хлеба. И это я не про DSL на Lisp, а про настоящий — со своими синтаксисом, компилятором и стандартной библиотекой. Тогда решить задачу нарезки хлеба будет очень просто:

                                                                    sliced_bread := Bread new slice

                                                                    Но нужно будет установить 100 МБ софта для компиляции этого кода, а также подождать годик-другой, пока стабилизируется инструментарий, исправятся баги и производительность достигнет приемлемого уровня.

                                                                    А потом кто-нибудь напишет на нём фреймворк...
                                                                      0
                                                                      Шутки шутками… но бедным заказчикам приходится терпеть последствия вот такого (все выше предложенное) полета фантазии разработчиков… а ведь заказчику просто хотелось 'покушать хлеба'.

                                                                      Я к тому что не стоит забывать собственно ту самую главную цель, ради чего затевается разработка чего-либо… спускаясь вниз по цепочки модулей и плагинов, подклассов и фреймворков не забывать о первоочередной цели. Иногда действительно может быть достаточно просто 'нарезать_хлеб(хлеб)'.
                                                                        0
                                                                        А ведь еще раньше, все было еще лучше.
                                                                        (нарезать хлеб)
                                                                        (нарезать хлеб колбаса сыр овощи)
                                                                        (смешать (нарезать овощи сыр) масло)
                                                                        

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

                                                                        Самое читаемое