1. Куча / Говнокод #23477

    −7

    1. 1
    Про убогость ООП подхода.

    Итак, вот допустим наследование. Есть всякие там тупые примеры ООП, типа "котик и собачка наследуется от четырехногих" и проч., где подобный бред вполне работает. Но давайте попробуем рассмотреть более интересные ситуации.

    Допустим что мы пишем некую игру. В игре есть некое оружие, например там есть огнестрел и дубинки. И мы делаем ружье, которое одновременно и огнестрел и дубинка, т.е. ружьем можно и как палкой уебать, и пальнуть как из револьвера. У родительского класса "огнестрел" есть свойства, типа дальности выстрела, точности, используемых боеприпасов, уровень прочности(износ), вес, наносимый урон при попадании. У дубинки есть свойства длины дубинки, уровень прочности(износ), вес, наносимый урон при ударе. Вес для ружья нам нужен только один, т.е. нет смысла делать два "веса" одному предмету. И огнестрел и дубинка наследуется от родительского класса "объект инвентаря", в общем тут ромбовидное наследование, которое в разных языках решается разными способами. Ну ок, допустим что мы там каким-то образом указали компилятору некоего языка X, что наследовать свойство "вес" надо лишь один единственный раз, как и прочие хрени, которые являются общими для родительского класса "объект инвентаря". Теперь надо решить с прочностью. Не все "объекты инвентаря" в этой игре имеют свойство прочности, есть например какие-то расходные материалы, типа патронов, для которых понятие прочности неприменимо. Использование ружья как дубинки изнашивает его не таким же самым образом, как использование ружья как огнестрела, но при этом слишком большой износ ружья-как-дубинки может настолько повредить его, что как огнестрел его уже и не поиспользовать из-за погнутого ствола. Но использование ружья как огнестрел никак на износ ружья-как-дубинки не влияет, типа это механический износ спускового механизма, износ ствола при стрельбе...

    Запостил: j123123, 02 Ноября 2017

    Комментарии (255) RSS

    • Т.е. надо не просто унаследовать свойство "прочность огнестрела" и "прочность дубинки", но и какие-то дополнительные ограничения втулить, если эта хрень на вот столько единиц износилась как дубинка, то как огнестрел его использовать нельзя уже, можно только использовать в роли дубинки. А если оно износилось как огнестрел, то на свойства этой штуки как дубинки оно вообще не влияет.
      Короче, если мы хотим от этих двух говен унаследоваться так, как надо по такому вот хитровыебаному условию, надо иметь некий способ чтобы указать то, как правильно эти хрени накладывать, какие общие свойства двух родительских классов будут сведены к одному, какие будут дублироваться (типа "прочность как огнестрела" и "прочность как дубины") и их взаимное влияние(т.е. если ружье сильно раздолбать как дубинку, стрелять из него тупо нельзя).
      Ответить
      • И обычное говноООП, которое существует например в говноплюсах, тут не поможет. Тут нужна ГОМОИКОННОСТЬ или какая-то кодогенерация, возможность на этапе компиляции обрабатывать всякое такое говно, и конструировать на основе него новое говно по каким-то там хитрым правилам т.е. некая хрень, которая бы могла на этапе компиляции читать исходник и произвольно наметушить любую хуйню из имеющихся классов, функций, да вообще из чего угодно, т.е. предоставить стандартный обобщенный механизм для преобразований. А наследование в ООП это такая domain specific недометушня, проблема ромбовидного наследования в разных говноООП языках решается вообще разными способами.

        https://ru.wikipedia.org/wiki/Ромбовидное_наследование :

        > Common Lisp пытается реализовать и разумное поведение по умолчанию, и возможность изменить его. По умолчанию выбирается метод с наиболее специфичными классами аргументов; затем, методы выбираются по порядку, в котором родительские классы указаны при определении подкласса. Однако программист вполне может изменить это поведение путём указания специального порядка разрешения методов или указания правила для объединения методов.

        Вот что Lisp животворящий делает!
        Ответить
        • во всех симулоообразных япах (жаба, кресты, сисярп, котлин) ООП говно

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

          ынтерфейс лишь контракт на обработку сообщений. сообщения можно отказаться принимать
          Ответить
          • # во всех симулоообразных япах (жаба, кресты, сисярп, котлин) ООП говно

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

            ООП везде одинаковое, хоть это Smalltalk, хоть это C++, хоть это Java, отличаются только их причуды.

            Или нет? Кто сможет привести убийственную фичу у Python, Ruby, Smalltalk и докажет их сильное отличие от C#, тот молодец.
            Ответить
            • Не совсем одинаковое. Конечно, можно юзать любой подход везде.
              Можно юзать ООП даже в языках без ооп (hint: object manager в windows executive):

              HANDLE user = CreateUser();
              SendEmail(user, "fuck yeah");
              
              HANDLE beer = CreateBeer();
              Dirnk(user, beer);
              
              DestroyObject(user);
              DestroyObject(beer);


              Просто смалток говорит: "объекту можно послать сообщение, он может его обработать, может форварднуть дальше (делегировать), сохранить итд. Объекта можно спросить: умеет-ли он получать сообщение".

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

              https://stackoverflow.com/questions/1143993/what-are-the-schools-of-oop
              Ответить
              • # объекту можно послать сообщение
                # сообщения просто вызывают функцию

                Но чем эти два подхода лучше другого?
                Ответить
                • Возьмем руби. Я сейчас им активно интересуюсь, но через неделю меня попустит.

                  require 'forwardable'
                  
                  class Dog # Собака умеет говорить
                    def talk
                      'rraf'
                    end
                  end
                  
                  
                  class Cat # кошка умеет
                    def talk
                      'mio'
                    end
                  end
                  
                  # Фурри косплеит кошку или собаку. В Java бы furry наследовал кошку или собаку.
                  # Лучше конечно применить делегирование, но в джаве сахара для делегирования нет 
                  # А в руби есть, потому что вызов метода это просто message который можно переслать (forward)
                  class Furry 
                    extend Forwardable
                  
                    def initialize(cosplay) # в конструктор получили адресата делегата
                      @cosplay = cosplay
                    end
                  
                    def_delegator :@cosplay, :talk # форвардим ему сообщение talk
                  end
                  
                  
                  furry = Furry.new Cat.new # Cosplay can. Delegation, not inheritance!
                  
                  puts furry.talk # mjau
                  
                  #  А если бы было наследование то началось бы говно
                  
                  # Поведение при получении меседжей можно менять на лету.
                  # Допустим, предки пришли домой и наш фурри стал говорить как человек
                  
                  def parents_at_home(furry)
                    def furry.talk # меняем ответку на message у конкретного объекта, хуй так вджаве сделаешь
                      p "hi mom"
                    end
                  end
                  
                  
                  furry.talk #мяучит
                  parents_at_home(furry)
                  furry.talk #говорит по человекчески
                  
                  # еще удобно проверять наличие метода. В жабе ты бы тут делал интерфейс и проверял бы instanceof
                  # а тут я могу сделать так
                  
                  def govori_syka(talker)
                    if talker.respond_to? :talk # а принимает-ли он вообще такой message?
                      puts talker.talk
                    else
                      puts "This one does not know how to talk"
                    end
                  end
                  
                  govori_syka "" # This one does not know how to talk 
                  govori_syka furry # mio


                  Технически можно тоже самое сделать в java, просто это будет многобуквенно, не естественно
                  Ответить
                  • Я всё равно не понимаю, приведи аналог на Java или C#, используя их философию.
                    Ответить
                    • Да почти та же хуйня в данном случае.
                      Вместо
                      def_delegator :@cosplay, :talk

                      будет
                      public void talk()
                      {
                          cosplay.talk();
                      }

                      Обычное делегирование. Да, в жабе многобуквенней, но она никогда и не претендовала на краткость.
                      Ответить
                      • # def_delegator :@cosplay, :talk


                        Толи дело Сишарпик:

                        void talk() => cosplay.talk();
                        Ответить
                        • а теперь представь что у тебя 20 методов в интерфейсе
                          ты всех их будешь так писать?

                          еще раз подчеркиваю!

                          "Технически можно тоже самое сделать в java, просто это будет многобуквенно, не естественно"

                          Ответить
                          • а в руби ты не явно список методов выписываешь?
                            Ответить
                            • нет, там же нету стат. типизации. можно не указывать


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

                              а вот в obj-c типизация статическая есть, но там все равно можно спросить у объекта отвечает-ли он на message, и если да то послать
                              Ответить
                          • # 20 методов в интерфейсе

                            А что, так бывает?
                            Ответить
                            • Бывает, к сожалегнию.
                              Вот тебе еще прымер
                              class Dog
                                def talk
                                  "waf"
                                end
                              
                                def jump
                                  "high"
                                end
                              
                                def best_known_for
                                  "sniff"
                                end
                              end
                              
                              class FatDog
                                def initialize(dog)
                                  @dog = dog
                                end
                              
                                def method_missing(*args) # Вся неизвестная херня отправляется к тому, кому мы всё делегируем
                                  @dog.send *args
                                end
                              
                                def jump # Кроме метода jump, я его переопределю
                                  "no so high"
                                end
                              
                              end
                              
                              
                              fat_dog = FatDog.new Dog.new
                              
                              p fat_dog.jump # not so high
                              p fat_dog.talk # not so high
                              .

                              В C# ты тоже так можешь сделать, но понадбится наверное рефлексия.

                              Понимаеш что тут происходит? когда мне шлют message на который у меня нет ответа (method missing) я просто форварджу его дальше
                              Ответить
                              • # В C# ты тоже так можешь сделать, но понадбится наверное рефлексия.

                                Тут вообще плохая архитектура, масса должна быть обычным свойством, а jump должен считать высоту на основе массы
                                Ответить
                            • Нате вот вам вообще охуенчик (меня прет!)
                              class LazyOne
                              
                                def method_missing(*args) # Вся неизвестная херня cохраняется
                                  @missing ||= [] # создадим массив если пустой
                                  @missing << args # пульнем в него message  с аргументами
                                end
                              
                                def go
                                  @missing.each {|args| send(*args)} # идем по всем месседжам и шлем их сами себе
                                end
                              end
                              
                              
                              lazy = LazyOne.new
                              lazy.say(42) # ничего не произошло
                              
                              # прошло три часа, мы добавили новый метод
                              def lazy.say(n)
                                p n
                              end
                              
                              lazy.go #запусти все пропущенные метлды. Выведет 42
                              Ответить
                  • > А в руби есть, потому что вызов метода это просто message который можно переслать

                    Хуита. В руби вызов метода это все еще вызов метода, просто создатели обчитались статей с хабра о Правильном ООП и начали называть это пересылкой сообщений, потому что в их представлении именно этот факт и отделяет обычные реализации от Правильного ООП. Технически то же самое можно сделать и на жабе через прокси.
                    А манки патчинг и дак тайпинг это все еще манки патчинг и дак тайпинг.
                    Ответить
                    • # манки патчинг

                      Из Википедии:

                      К тому же использование такого подхода нарушает принцип инкапсуляции объектно-ориентированного программирования.
                      Ответить
                    • Прости, создатели руби и обжектив си перечитались хабра, я верно понял?
                      Ответить
                      • ну, японского хабра двадцатилетней давности
                        Ответить
                  • Какой всё же мунспик этот руби
                    Ответить
                  • ужасное говно
                    Ответить
        • > И обычное говноООП, которое существует например в говноплюсах, тут не поможет.

          кресты и OOP тут ни причем. ты просто ОО еще пользоватся не научился.

          > Ромбовидное_наследование

          вообще тут ни причем. читай ООАиД - и учись классы из предметной областы выделять.

          и если правильно научишься "классифицировать", тебе уже будет по барабану язык программирования - ОО или не ОО. потому что те же яйца вид с боку. или как классики говорили: наследование это всего лишь синтаксический подсластитель аггрегации.
          Ответить
          • > кресты и OOP тут ни причем. ты просто ОО еще пользоватся не научился.

            ООП просто для этого НЕ ПОДХОДИТ. Оно ограничено. ООП-наследование подразумевает что у чего-то там есть родитель, и "наследник" у родителя все свойства копирует себе, но это часто не нужно. Есть четвероногие, мы наследуем псов от четвероногих. Потом у нас появляются в игре псы-мутанты с 5 ногами, мы хотим унаследовать их от обычных псов, но без унаследования четвероногости. Т.е. скопировать все что есть у псов кроме отдельных кусков, связанных с четвероногостью. Как это решается в ООП наследовании?
            Ответить
            • Нужен просто ОБЩИЙ механизм брать какой-то код и на основе него собирать новый код, а не какие-то частные узкие случаи. Иметь возможность произвольно разбирать готовые классы на кирпичики и из этих кирпичиков строить новые классы
              Ответить
              • как я и говорю: ты не умеешь классы выделять. ты как школота бросаешься на очевидное, абсолютно игнорируя требования задачи.

                ночью лень тебе много писать. но еще одна - сопряженная - тема для медитации: поразмышляй на тему отношений/реляций/relationships между классами. и более конкретно над ответом на вопрос: в ОО, что такое реляция? (или: сколькими способами ее можно представить?)
                Ответить
                • > как я и говорю: ты не умеешь классы выделять. ты как школота бросаешься на очевидное, абсолютно игнорируя требования задачи.

                  Требование какой задачи я игнорирую?

                  Спрашиваю еще раз:
                  Как мне с этой ООП моделью взять из некоторого одного класса некую одну часть, из некоторого другого класса другую часть? Не унаследовать и то и то целиком, а просто взять там и там куски?
                  Ответить
                  • В гугл mixins
                    Ответить
                  • # Не унаследовать и то и то целиком, а просто взять там и там куски?

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

                    кучи уже понаписали, а времени/мозгов у меня читать все уже нету (мля уже опять ночь).

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

                    все зависит от того *чем* 4-ре- и 5-ти- ногие собаки отличаются от друг друга - с точки зрения требований решаемой задачи.

                    например в графических играх они от друг друга вообще ничем отличаться не будут - кроме номера модели/текстур которыми они будут рисоватся на экране.

                    та же херня и относительно твоих {свойство "прочность огнестрела" и "прочность дубинки"}. вопрос не в том как словарь русского языка смотрить на эти вещи - а что с ними нужно делать. в большинстве програм которые что-то будут с ними делать все будет намного сложнее - и все в лоб будет своим отдельным классом/интерфейсом, и поверху еще будут стэки эффектов, и все будет считаться скорее всего процедурально. в добавок эти все мелочи еще будут state machine'ами потому что например игры любят это все через effect-over-time делать (т.е. эффект аттаки применяется не мнгновенно, а за, например, 0.5 секунд).

                    поэтому то твои жалобы на ООП выглядят весьма глупо. почему я и говорил о реляциях. классы/объекты как-то к друг другу относяться. и более того: некоторые реляции приходится описывать своим классом, потому что у реляций (тот же damage в играх) тоже могут быть свойства.
                    Ответить
                • http://blogerator.org/page/oop_why-objects-have-failed

                  Наследование — это самая большая провокация в индустрии. Ни в каком моделировании наследования не существует (и в реальной жизни его нет тоже) — ни в электронике, ни в бухгалтерии, ни в политике, ни где бы то ни было еще. Есть лишь одна область, где наследование теоретически встречается — генеалогия (эй, парни, лучше не путать это с гинекологией). Но это не имеет ни малейшего отношения к тому, что называется наследованием в программировании. Все эти многоэтажные иерархии классов только усложняют жизнь программиста, вместо того, чтобы упрощать по своему замыслу.
                  Ответить
                  • вот ты и сам написал, что ты вообще зря тащишь в задачу наследование
                    Ответить
                  • Феерически глупая статья.

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

                    Запишите уже себе на лбу: наследовать нужно интерфейсы (протоколы) а не реализации.
                    Ответить
            • > Наследование
              А я всегда говорил, что наследование - говно (т.к. все пытаются наследовать реализацию, городить уёбищные иерархии и рано или поздно наступают на грабли). Самая сомнительная часть ООП.

              А твоя задача даже на обычных языках вполне решается внешними хелперами, интерфейсами, агрегацией и какой-то матерью...
              Ответить
              • Если можно, расскажите про какую-то мать подробнее. Очень интересно, что (и главное, как) с её помощью можно решить.
                Ответить
                • Она понадобится чтобы писать гору однострочных прокси-функций в каждой реализации.
                  Ответить
              • Любая задача решается ассемблером без всяких там ООП и даже без процедурного программирования.

                Разберем ООП применительно к плюсам (в других языках могут быть свои ньюансы):

                Плюсовый класс это такая хрень типа структуры(можно наобъявлять там переменных всяких), но с возможностью там объявлять еще функции(которые в данном случае называют методами), и это все (переменные, методы) еще размещается (помечается) в public protected private кусках, в которых различаются права доступа к этим штукам. Protected хрень доступна для классов, производных от данного, public доступна всем, private доступна только членам класса и friend-ам. ОК, а если я хочу сделать помимо public private protected еще одну хрень, специфицирующую доступ, назову ее huekted, которая например будет доступна всем функциям/методам кроме членов класса и friend-ов (хуй знает нахуй это нужно, просто придумал от балды) то что тут можно сделать? Нихуя!

                А есть ведь еще и public, private, protected наследование. Почему я не могу добавить еще какой-то способ наследования? Почему нельзя было все это реализовать в максимально общем (кастомизируемом) виде, чтобы помимо public private protected можно было вводить свои принципиально новые модификаторы доступа, придумывать свои хитровыебаные способы отнаследоваться и прочее прочее?
                Ответить
                • В общем я склоняюсь к точке зрения, что всякие кривые узкоспециализированные хуевины, придуманные мудаками-стандартизаторами нахуй не нужны, нужна лишь некая хрень, которой было бы достаточно для имплементации любой вообразимой компилтайм-метушни, чтоб можно было свои классы со всяким своим хитровыебанным говном сделать, чтоб там не только бублик-хуюблик хуектед, но еще какая-то придуманная произвольная хуита могла бы быть всунута, чтоб можно было свои ключевые слова объявлять, которые бы действовали только в области видимости какой-то там поеботы, переопределять(перегружать) готовые зарезервированные ключевые слова языка на этапе компиляции, т.е. вообще не должно быть никаких таких вот захардкоженых говен, как этот паблик приват протектед
                  Ответить
                  • # В общем я склоняюсь к точке зрения

                    Очень хорошая точка зрения. А теперь приведи пример, где бы тебя это спасло.
                    Ответить
                • # хуй знает нахуй это нужно, просто придумал от балды
                  # то что тут можно сделать? Нихуя!

                  Т.е. С++ не нужен, потому, что ты не можешь на нём сделать фичу, не имеющую практического применения?
                  Ответить
                  • Потому что в этой хрени нельзя реализовать никакую фичу. Есть только паблик приват протектед, больше нифига.
                    Ответить
                    • # Есть только паблик приват протектед, больше нифига.

                      Но зачем тебе больше?
                      Ответить
                      • А почему нужно останавливаться именно на этих трех? А может и этого не надо, хватит и обычных структур отдельно, функций отдельно?
                        Ответить
                        • GOTO хватит всем.
                          /thread
                          Ответить
                        • # А почему нужно останавливаться именно на этих трех

                          Предложи ещё, но чтобы они были полезны.
                          Ответить
                          • Предлагаю сделать private2. Методы, объявленные как private2 не могут в своем коде вызывать методы данного класса, которые public.

                            Или сделать public2. Методы, объявленные как public2 не могут в своем коде вызывать методы данного класса, которые public или public2 кроме ситуаций с рекурсией.

                            В такой способ мы говорим программисту, что public методы только извне вызывать разрешено.
                            Ответить
                            • # Методы, объявленные как private2 не могут в своем коде вызывать методы данного класса, которые public.

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

                              Я вот не понимаю, это ограничения помогут как-то сделать более понятный код, помогут при составлении документации, благодаря им ты сможешь избежать уязвимостей? Что тебе это даст?
                              Ответить
                              • > Я вот не понимаю, это ограничения помогут как-то сделать более понятный код

                                А чем помогают ограничения, накладываемые private? Что они дают? Давайте все методы делать public, настоящие цари ж лучше компилятора знают, что им там можно и чего нельзя откуда вызывать.

                                Таким ограничением мы декларируем что вот функции эти - внешние и их можно дергать только извне класса - они не предназначены для внутреннего использования внутри классов. Интерфейс для взаимодействия с объектом из внешнего мира нужен только как интерфейс, и не должен внутри как-то сильно задействоваться в самой логике класса, т.е. пусть он просто вызывает какие-то внутренние функции или что-то там сам по себе делает. Изнутри он вызываться не должен т.к. нужен именно для взаимодействия с внешним миром
                                Ответить
                                • # А чем помогают ограничения, накладываемые private

                                  Дают они очень важную вещь: скрыть детали реализации от внешнего мира.

                                  А вот то, что ты предлагаешь (скрывать публичных членов от самого себя) - глупость.
                                  Ответить
                                  • > Дают они очень важную вещь: скрыть детали реализации от внешнего мира.

                                    А зачем их скрывать? Можно просто не обращать внимания, т.е. тупо НЕ ВЫЗЫВАТЬ те методы, которые являются деталями реализации.

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

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

                                    Всю логику выносим в приватные методы, а публичные просто вызывают приватные. Кроме того, можно придумать несколько слоев приватных методов. Например, первый слой приватных методов может вызывать методы из первого слоя приватных методов, и методы из второго слоя приватных методов. А приватные методы из второго слоя только такие же методы могут вызывать, или методы еще более глубокого слоя. И чем глубже слой, тем ближе к "железу" работает тот метод.
                                    Ответить
                                    • > Например, первый слой приватных методов может вызывать методы из первого слоя приватных методов

                                      Не нужны для этого никакие хитрые изменения прав доступа, просто вкладываешь объекты разного уровня друг в друга.
                                      Ответить
                                      • > Не нужны для этого никакие хитрые изменения прав доступа, просто вкладываешь объекты разного уровня друг в друга.

                                        Если вкладывать объекты разного уровня друг в друга, это поможет мне поставить ограничения вида "public метод уровня N имеет доступ только к public методам уровня N и N+1, но не более низкого уровня"?

                                        Вот например, пишем допустим хрень для создания-удаления файла. Функции типа open() fstat() lseek() unlink() и прочая такая хрень - public. Им можно обращаться к слою функций, которые абстрагируются вообще от всей питушни, и совершенно не предполагают прямой доступ к жесткому диску. Ну там может быть FUSE или подмонтированная NFS или SMB хрень. В одном из случаев этот слой доступных из юзерспейса функций будет взаимодействовать с каким-то уровнем драйвера ФС. Рассмотрим такой случай

                                        Уровнем ниже будет питушня ФС. Например, если это какой-то там EXT3 то это журналируемая ФС и она там пишет в внутренний журнал какую-то питушню при удалении-создании файлов и прочее, управляет свободными блоками ФС, делает какие-то там манипуляции со структурами данных, специфичных для конкретной ФС. В общем эта какая-то внутренняя питушня для конкретной ФС, которую нельзя вызывать из юзерспейсного слоя, потому что можно что-то легко запороть. Из юзерспейсного слоя можно вызывать только питушню open() read() write(), которая уже у себя делает вызовы более низкого уровня абстракции.

                                        А еще слоем ниже будет какая-то питушня, которая отпавляет ATA команды к жесткому диску на запись каких-то там блоков в какие-то там области, и эти ATA команды можно вызывать только из слоя на один выше т.е. из слоя драйвера ФС. Из слоя, где разрешено вызывать open() read() write их вызывать нельзя. Т.е. есть строгий набор правил, из какой питушни что можно, и что нельзя делать
                                        Ответить
                                        • > Если вкладывать объекты разного уровня друг в друга, это поможет мне поставить ограничения вида "public метод уровня N имеет доступ только к public методам уровня N и N+1, но не более низкого уровня"?

                                          Да. Именно так я обычно и структурирую приложения. Для этого даже ООП никакого не нужно.
                                          Ответить
                                    • # тупо НЕ ВЫЗЫВАТЬ те методы, которые являются деталями реализации

                                      Не надейся на чужую порядочность. Для этого и создан private.

                                      # Я вот может хочу

                                      Хотеть не вредно (с).

                                      # а вызывать публичные методы из приватных и публичных нафиг не надо

                                      Тебе не надо - не вызывай, в чём проблема? Тем более это почти никогда не требуется, разве что в конструкторах.
                                      Ответить
                                      • > Не надейся на чужую порядочность. Для этого и создан private.

                                        Вот я тоже на чью-то там порядочность не надеюсь, и создаю особые private2 из которых нельзя вызвать public

                                        > Тебе не надо - не вызывай, в чём проблема?

                                        Вот правильно, давайте тогда и private уберем, чтоб все public было. Если кому-то не надо что-то там вызывать, пусть не вызывает.
                                        Ответить
                                        • # Вот я тоже на чью-то там порядочность не надеюсь, и создаю особые private2 из которых нельзя вызвать public

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

                                          # Вот правильно, давайте тогда и private уберем, чтоб все public было. Если кому-то не надо что-то там вызывать, пусть не вызывает.

                                          Ты вообще понимаешь, что ты поехавший. Не я поехавший, не он поехавший, а ты?

                                          Приватные члены созданы для сокрытия логики реализации, публичные - для проверок данных извне. Ты хочешь такой модификатор, которым ты хочешь запретить САМОМУ СЕБЕ из логики вызывать другую логику с защитой. Что ты этим добьёшься? На небе появится радуга, а на ней будут скакать анимешные девочки на розовых пони?
                                          Ответить
                                    • Ты только что придумал, как добавить в более-менее понятный ООП кучу бойлерплейта, и каждый публичный метод, который понадобится нам из приватного, придётся сделать приватным и дописать к нему соответствующий публичный, состоящий из одного вызова.
                                      Ответить
                                      • >Ты только что придумал, как добавить в более-менее понятный ООП кучу бойлерплейта, и каждый публичный метод, который понадобится нам из приватного, придётся сделать приватным и дописать к нему соответствующий публичный, состоящий из одного вызова.

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

                                        Моя претензия к всей этой ерунде с публичными приватными и защищенными методами класса заключается в том, что это всего лишь какой-то частный случай, заложенный на уровне стандарта самого языка, т.е. язык не позволяет добавлять какие-нибудь private2 виды методов, для которых работают какие-то иные правила доступа. Т.е. на мой взгляд вся подобная ерунда должна быть не захардкожена (типа вот есть ключевое слово public - там такие-то правила для таких методов, private - такие-то правила...), должна быть возможность самому свои типы методов делать, самому придумывать всякие произвольные правила для них.
                                        Ответить
                                        • Ты уже второй день заявляешь, что public и private, такие, кикими мы их имеем, -- это какая-то захардкоженная частность, и до сих пор не смог привести пример, где нельзя было бы ими ограничиться. Может всё-таки public и private -- это что-то абстрактное и фундаментальное, из чего ты как раз можешь построить частности своей мечты?

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

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

                                          Ты вот там приводил пример со слоями методов. Это ты предлагаешь, чтобы один объект был многослойным? Чтобы в пределах одного объекта какие-то его члены имели или не имели друг к другу доступ сложным образом? Это идиотизм, ты огребёшь кучу бойлерплейта и сложнейшую документацию. Кроме того, ты вряд ли придумаешь красивый синтаксис для этого. Не числами же слои обозначать. Стало быть, заворачивать в какие-нибудь обертки, нижние слои завернуты в более верхние. Ну и чем это отличается от где надо -- заворачивания объекта в объект, где надо -- наследования.

                                          ---> см. далее
                                          Ответить
                                          • В примере про файловые системы ты вообще фундаментально неверно смотришь на ситуацию, как будто ты только и читал солнечные синтетические учебники по ооп про зоопарк с четвероногими собачками. То, что тебе кажется низом -- наоборот верх. Никто не должен наследоваться от низкоуровневой вещи типа файловой системы или драйвера жесткого диска, иначе как ты будешь менять одну реализацию на другую, если у тебя это корень дерева? Всё дерева спиливать и менять? Тут надоборот надо завернуть низкий уровень ровно в одну абстракцию -- типа адаптер, и передавать его в другие абстракции как аргумент или как отношением has. С наследованием это совсем не связано.

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

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

                                            Скорее всего, так и есть.
                                            Ответить
                                          • > Ты уже второй день заявляешь, что public и private, такие, кикими мы их имеем, -- это какая-то захардкоженная частность, и до сих пор не смог привести пример, где нельзя было бы ими ограничиться.

                                            Можно вообще одним public ограничиться, и никакие private нафиг не нужны. Ничего фундаментального в этом говне нет и быть не может. Так что если исходить из позиции "если этим говном можно и ограничиться, то другого не надо" то давайте вообще все нахер выкинем, оставим только public
                                            Ответить
                                          • > Ты вот там приводил пример со слоями методов. Это ты предлагаешь, чтобы один объект был многослойным? Чтобы в пределах одного объекта какие-то его члены имели или не имели друг к другу доступ сложным образом? Это идиотизм, ты огребёшь кучу бойлерплейта и сложнейшую документацию.

                                            Я считаю что никакой это не идиотизм. Не нравится - не пользуйся. Возможность доопределять новые фичи ЛУЧШЕ чем отсутствие такой возможности. Эта хренота с классами может быть расширена только запатчиванием самого компилятора, т.е. это говно встроено в само ядро языка, и доопределить новые спецификаторы доступа нельзя вообще никак. Нельзя придумать новый способ наследования. Нельзя добавить новые языковые сущности, помимо классов, структур.

                                            Ведь по-хорошему, всю эту хрень с классами, все эти варианты наследования, это все можно реализовать как некую компилтайм-библиотеку, добавляющую эти конструкции. Типа вот есть чистая сишка, подключаем какую-то библиотеку, и вот в сишке уже есть классы. Подключаем еще библиотеку - и вот лямбды появились. Еще одну библиотеку подключили - добавились констэкспры. И так далее. Но таких механизмов нет, да и реализовать их поверх сишного говносинтаксиса будет затруднительно(если вообще возможно), тут разумеется нужна гомоиконность с нормальными макросами т.е. возможностью легко и удобно обрабатывать код самого себя и трансформировать его произвольным образом.
                                            Ответить
                                            • > если вообще возможно
                                              http://libcello.org/
                                              Ответить
                                              • Знаю про эту штуку. Оно требует gnu экстеншены и недостаточно универсально
                                                Ответить
                                            • > доопределить новые спецификаторы доступа нельзя вообще никак. Нельзя придумать новый способ наследования. Нельзя добавить новые языковые сущности, помимо классов, структур.

                                              Не припонмю, что ты писал на ГК раньше, но почти уверен, что ты нигде не работаешь, не имеешь опыта поддержки чужого кода и целыми днями пишешь синтетические хелоуворлды.
                                              Ответить
                                              • Ну, если тебе это так интересно...

                                                У меня нет сейчас обычной работы (такой, где надо было б каждый будний день ходить в офис и какой-то там хренью заниматься) но вообще я работаю над кое-чем. Опыт поддержки чужого кода у меня есть. Мне вот например недавно в Киеве предлагали постоянную работу с з.п. 3000$ в месяц, но я отказался. Постоянную работу мне найти несложно, просто мне это нафиг не надо
                                                Ответить
                                • Твои примеры какие-то надуманные.

                                  Я могу захотеть запретить вызывать публичные методы из приватных, к примеру, когда я пишу класс для коммуникации потоков, и (почти) все публичные методы захватывают локи, а приватные работают в предположении, что лок уже взят.
                                  Но и для этого использовать private/public — говно, потому что локов может быть больше одного. Уж лучше использовать специализированные инструменты
                                  https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
                                  Ответить
                                  • > и все публичные методы синхронизированные захватывают локи, а приватные работают в предположении, что лок уже взят.

                                    См. мое предыдущее предложение про слои методов.
                                    Ответить
                                    • > См. мое предыдущее предложение про слои методов.

                                      Зачем мне на него смотреть? Я описал ситуацию, когда твои слои могут выглядеть как что-то полезное, но на самом деле всё равно говно по сравнению с алтернативами.
                                      Ответить
                    • >>только паблик приват протектед, больше нифига.

                      Это вообще совсем никак не относится к ООП.
                      Ответить
                    • > Есть только паблик приват протектед, больше нифига.

                      Бери язык, в котором есть кое-что ещё.

                      https://docs.racket-lang.org/reference/createclass.html#%28part._clmethoddefs%2 9
                      Ответить
                      • Вот вообще, что пишут умные дядьки:

                        https://stackoverflow.com/questions/29379758/in-rackets-class-system-what-do-augment-overment-augride-etc-do

                        To clarify the difference between overriding and augmentation, when an overridden method is called, the overriding implementation is executed, which may optionally call the superclass's implementation via inherit/super. In contrast, in an augmented method, the superclass's implementation receives control, and it may optionally call the subclass's implementation via inner.

                        Песдец какой-то !!111
                        Ответить
                        • Это типа виртуального метода, только вывернуто наизнанку?
                          Ответить
                          • Ну типа видимо можно спроектировать метод родителя с тем расчётом, что он может позвать такой же метод у потомка. Или не позвать.
                            Ответить
                          • #lang racket
                            
                            (define test-class%
                              (class object%
                                (define/pubment (something)
                                  (* 200 (inner 1 something)))
                                (super-new)))
                            
                            (define very-test-class%
                              (class test-class%
                                (define/augment (something)
                                  2)
                                (super-new))
                              )
                            
                            (send (new test-class%) something)
                            (send (new very-test-class%) something)


                            выведет

                            200
                            400
                            Ответить
                        • Вспомнил анекдот.

                          Урок домоводства. Учительница:
                          –— Сегодня мы будем выполнять выворачивание канта наизнанку. Тема сложная, поэтому не отвлекайтесь.
                          —– Марья Ивановна, это что же получается, моральный закон над нами и звёздное небо внутри нас?
                          Ответить
                          • Прочитал как "каната" и не понял в чём шутка. Потом прочитал правильно, но всё равно не понял.
                            Ответить
                            • Подсказка:
                              https://ru.wikipedia.org/wiki/Кант_(элемент_одежды)
                              https://ru.wikipedia.org/wiki/Кант,_Иммануил

                              Я даже видел в интернетах срач на тему, можно ли вывернуть кант. Оказывается, можно. Есть специальный крючок из проволоки для выворачивания канта:
                              https://www.nadel.ru/upload/iblock/7f3/Prym611346.jpg

                              Что же касается, второй части анекдота, она восходит к цитате Иммануила Канта: «Две вещи наполняют душу всегда новым и всё более сильным удивлением и благоговением, чем чаще и продолжительнее мы размышляем о них, — это звёздное небо надо мной и моральный закон во мне». В оригинале она звучала так: «Zwei Dinge erfüllen das Gemüt mit immer neuer und zunehmender Bewunderung und Ehrfurcht, je öfter und anhaltender sich das Nachdenken damit beschäftigt: Der bestirnte Himmel über mir, und das moralische Gesetz in mir».
                              Ответить
                • > public private protected
                  В динамическах языках -- понятно куча рантайм проверок, поэтому в том числе дорогая абстракция, а в языках типа C++ это реально какие-то "защищенные" области (памяти?), у одного нет права доступа к другому, или это просто компилятор смотрит, не нарушил ли программист в коде какие-либо полномочия?

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

                  (Возможно, я сейчас объявил своё глубочайшее непонимание ООП.)
                  Ответить
                  • Защита на этапе компиляции. Просто проверка соблюдения программистом некоторых контрактов.

                    Как мы на этапе выполнения проверим, откуда вызван метод? Компилятор должен в преамбулу метода втыкать код проверки и таблицу адресов памяти, из которых разрешён вызов? Но это получится уже динамическая питушня.
                    Ответить
                    • > Компилятор должен в преамбулу метода втыкать код проверки и таблицу адресов памяти, из которых разрешён вызов?
                      Кстати, в «Винде» именно так сделан «Control Flow Guard»: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard.
                      Ответить
                      • Кокококой оверхед )))

                        Можешь привести реальный пример ассемблерного выхлопа cl /guard:cf test.cpp?
                        Ответить
                        • Держи: https://gcc.godbolt.org/z/odiiR2.
                          Этот самый «__guard_dispatch_icall_fptr» на самом деле является синонимом ntdll!LdrpDispatchUserCallTarget и выглядит так:
                          nop dword ptr ds:[rax],eax
                          mov r11,qword ptr ds:[0x7FFE8D56F370]
                          mov r10,rax
                          shr r10,0x9
                          mov r11,qword ptr ds:[r11+r10*8]
                          mov r10,rax
                          shr r10,0x3
                          test al,0xF
                          jne label_1
                          bt r11,r10
                          jae label_1
                          jmp rax
                          label_1:
                          or r10,0x1
                          bt r11,r10
                          jae fail
                          jmp rax
                          mov r10d,0x1
                          label fail:
                          jmp <ntdll.LdrpHandleInvalidUserCallTarget>
                          Ответить
                          • nop dword ptr ds:[rax],eax
                            mov r11,qword ptr ds:[0x7FFE8D56F370]
                            mov r10,rax
                            shr r10,0x9
                            mov r11,qword ptr ds:[r11+r10*8]
                            mov r10,rax
                            shr r10,0x3
                            test al,0xF
                            jne label_1
                            bt r11,r10
                            jae label_1
                            jmp rax
                            
                            label_1:
                            or r10,0x1
                            bt r11,r10
                            jae fail
                            jmp rax
                            mov r10d,0x1
                            
                            fail:
                            jmp <ntdll.LdrpHandleInvalidUserCallTarget>

                            *fxd
                            Ответить
                      • Но это же просто все места, которые откуда-то можно вызвать. То, что из данного конкретного места это можно сделать никто не проверяет.
                        Ответить
                        • Ну да, а как их проверишь-то? Вот, например:
                          void f(Huj &someHuj)
                          {
                              someHuj.erect();
                          }

                          Конпелятор же не знает, что в эту «f» могут передать. Может, её вообще из дллки будут дёргать. Вот в «Microsoft» и нашли довольно элегантный выход.
                          Ответить
              • наследование реализации не является обязательным для ООП
                не нужно наследовать реализацию
                Ответить
            • # четвероногие, мы наследуем псов от четвероногих.
              # псы-мутанты с 5 ногами

              Так унаследуй их от n-ногих

              А вообще, достаточно одного класса для всех видов крипов.
              Ответить
      • # но и какие-то дополнительные ограничения втулить

        Возьми и втуль, чем тебе ООП то мешает?
        Ответить
    • вореции какие-то
      нарисуй-ка класс диаграмму.

      Пока я вижу что можно сделать абстрактный метод у интерфейса IУёбыбл (родителя у всех, кем можно уебать)

      метод назвать isМожноУебать()
      который у дубинки будет всегда true, а у огнестрела -- функцией от количества уёбанных раз (потом ружжо сломается)
      Ответить
      • Ладно, вот тебе более динамично, в духе смалтоков и рубей:

        интерфейс IУёбыбл можно удалить из цепочки наследования как только сломается ружье

        if item is IУёбыбл
        либо
        if item.acceptsMessage(уебать)

        тогда item.уебать()
        else
        print "извини чувак, ЭТИМ уебать нельзя"
        Ответить
      • Можно так сильно дубинкой кого-то уебать, что дубинка нахрен сломается
        Можно не суметь стрелять огнестрелом аж по трем причинам - износился огнестрел (типа там спусковой механизм раздолбался). Износилась дубинка (ствол погнули, когда кого-то уебывали). И нет патронов.
        Ответить
        • Дык в чем проблема-то? Оверрайд метода Выстрелить() с нужными проверками на прочность дубинки и вызов super(), если все хорошо, отменили что ли?
          Ответить
          • > Оверрайд

            Тогда ж будут виртуальный методы, будет создана таблица виртуальных методов для такого класса. Что вообще говоря нафиг не нужно для решения той мелкой задачи. Можно все решить статически, без всей ерунды. Тут не нужно позднее связывание
            Ответить
      • > IУёбыбл

        Ахахахахахахахахах бляяяяя
        Ответить
    • # убогость ООП

      Какой текст, какие слова!

      И чем же ты предлагаешь его заменить?

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

      В твоей задаче я поступил бы примерно так: каждый предмет обладает набором свойств: вес, износ, размеры, изображение, тип патронов и т.п. Для каждого предмета также можно получить список доступных с ним действий (да, действия — это значения, а не методы). Действия можно применять к паре объектов и изменять их нужным образом. Например, Hit.apply(дубина, враг), Fire.apply(дубина, враг), Load.apply(пушка, патроны_нужного_калибра). Поскольку действия конструируют пользователи в рантайме, не все из них будут валидны, на этапе компиляции недопустимые комбинации не поймаешь. Можно добавить Action.canApply, чтобы показывать пользователю жирный крестик, когда но пытается зарядить гранатомёт патронами девятого калибра.

      Это очень базовая ограниченная модель. Кстати, объекты часто определяют в каком-нибудь скриптовом языке (или просто текстовом файле), который используется движком. Указание объекта в качестве простого набора атрибутов в таком случае гораздо проще и удобнее, чем сложные схемы наследования.
      Ответить
      • >>Когда ты пытаешься использовать наследование, обычно ты создаёшь себе проблем больше, чем решаешь. ООП нинужно.

        А если у меня все классы final, то я не использую ООП?
        Ответить
        • Под ООП каждый понимает что-то своё, ООП-питушки часто готовы перегрызть друг другу горло, выясняя, адаптер там у них или фасад.

          Кмк, сама концепция класса и наследования ущербна. Что по-настоящему нужно, так это модульная система,
          абстрактные типы данных и интерфейсы модулей. Наследование реализации в OOP-стиле — это убожество.

          Имхо, близкая к идеальной система организации кода — это ML-style модули с first-class modules (т.е. когда можно создавать оперировать объектами модулей, например, складывать модули с одинаковым интерфейсом в коллекции).

          Отвечу на твой вопрос: если у тебя все классы final, то можно найти взаимно-однозначное соответствие между твоим "OOP"-кодом и модульной системой, похожей на ML.
          Классы будут соответствовать типам, объявленным в модуле, публичные методы — интерфейсу модуля, приватные методы — деталям реализации модуля.
          // godforsaken inferior OOP code
          class TimeInterval {
            // ...
          }
          class Date {
            public Date(int utc_ts);
            public Date Add(TimeInterval t);
            private void WowSoPrivate();
          }
          
          // strictly superior module-based code
          module TimeInterval : sig
            // public interface
          end = struct
            // impl details
          end
          
          module Date : sig
            type t
            val make : utc_ts:int -> t
            val add : t -> TimeInterval.t -> t
          end = struct
            type t = int
            let make = ...
            let add = ...
            wow_so_private : unit -> unit
          end
          Ответить
          • # модульной системой, похожей на ML

            Я после неё боюсь слова "модуль". Мне страшно представить, во что может превратиться C++20 (если введут модули), хоть он мне и не нужен.
            Ответить
            • > Я после неё боюсь слова "модуль"

              "Модуль" — слово довольно безобидное. Я вот опасаюсь слова "функтор", поскольку в разных коммьюнити оно означает совершенно разные вещи:
              1. Термин из теории категорий
              2. Класс типов Functor из Haskell/Idris/...
              3. "Функциональный объект" в C++, т.е. класс с перегруженным operator()()
              4. Модуль в ML, параметризованный другим модулем (т.е. по сути функция на модулях)
              Ответить
          • Интересно, а взлетит ли система со статической типизацией, состоящая только из абстрактных типов данных и мультиметодов (т.е. если не пытаться группировать методы в интерфейсы/модули)?
            Ответить
            • Я не понимаю, как абстрактные типы данных вообще возможны без чего-то вроде модулей. Это же по сути тип + набор операций над ним. Кмк, без явных интерфейсов для АТД будет такая же фигня, как с плюсовыми шаблонами: код будет хрупким, все будут ныть и просить концепты.
              Ответить
          • > интерфейсы модулей

            - очень нравится, как сделано в Racket (и, возможно, в остальных схемах).

            (provide blabla)
            Ответить
            • Нанравился тебе за щеку, проверь.
              Ответить
            • > как сделано в Racket

              А что там такого сделано? Почитал доку, там вроде всё довольно примитивно. Один файл — один модуль, есть явные списки экспорта, но нет явных списков импорта. Непонятно, как делать локальные алиасы модулей.

              Детский сад по сравнению с ML. Даже в Haskell лучше.

              Или я чего-то не понимаю?
              Ответить
              • Напонимал тебе за щеку, проверь.
                Ответить
              • Мне нравится не конкретная реализация, а идея инкапсуляции на уровне модулей
                Ответить
                • >>идея инкапсуляции на уровне модулей
                  Очень хорошая идея, в полностью процедурных подходах ее тоже уважают
                  Ответить
    • вывод - ромбовидное наследование нинужно. ООП это не только ромбовидное наследование
      Ответить
    • >2017
      >доказывать кому-то ущербность ООП
      Ответить
      • Ну а чем ещё заниматься? Не летающие машины или самошнурующиеся кроссовки же изобретать.
        Ответить
      • ))это примерно как устроить срач linux vs freebsd
        Ответить
        • Да о чём тут спорить? Время показало, что Линукс жизнеспособнее.

          И чуть не забыл: Hurd не нужен.
          Ответить
        • # linux vs FreeBSD

          А ещё Linux это ядро, а FreeBSD это операционная система.
          Ответить
          • вот ты зануда
            Linux-based OS vs FreeBSD.
            Ответить
            • # Linux-based OS vs FreeBSD.

              Ты серьёзно думаешь, что любой дистрибутив Linux лучше FreeBSD?
              Ответить
              • Ты серьезно думаешь что ооп это всегда плохо или всегда хорошо?

                Ответить
                • # серьезно думаешь что ооп это всегда плохо или всегда хорошо

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

                    Тем не менее у тебя парадокс балба
                    Ответить
                    • > может быть лучший в своей нише

                      Что за ниша? Лучший объекто-ориентированный си-подобный язык для платформы .NET под Windows? Тесновато.
                      Ответить
                      • Лучший статически типизированный язык с рефлексией и сборкой мусора под виртуальную машину

                        Понятно же что я сравнил его с жабой, и конечно жаба хуже
                        Ответить
                        • Да, C# -- это очень красивый и приятно пахнущий цветок, который распустился на куче навоза под названием Microsoft products. Вонь кучи, безусловно, перебивает аромат цветка. Жаль, что на другой почве он не растёт. В пизду его.
                          Ответить
                          • MS продукты не так уж и плохи. WPF, WCF, WF, MVC.NET, MSSQL итд: все это весьма юзабельно.

                            А C# бывает и за пределами MS: Например Xamarin. А Xamarin же единственный способ шарить логику между аппликухами под IOS и Android не трогая вонючее говно типа javascript
                            Ответить
                            • > единственный способ шарить логику

                              Не все могут себе это позволить, но связка "ядро на C++ + нативный гуй" неплохо работает.
                              Ответить
                              • Это отличная связка, особенно когда тебе нужен хай перформанс. А вот писать бизнес-логику все таки лучше на С#, чем на С++, правда?

                                Тем более что ios у нас на arm, а android бывает на mips, x86/atom и тоже arm.
                                У ябла clang, а у андроида наверное gcc, да?
                                Так что писать придется очень осторожно: подразные компиляторы и разные платформы
                                Ответить
                                • Не столько хай-пирфоманс, сколько лоу-мемори-энд-бэттери-консумпшен. Впрочем, для приложений вроде карт первое тоже крайне важно.

                                  Не знаю, про какую бизнес-логику в приложениях ты говоришь, вся бизнес-логика не сервере, клиенты в основном качают из сети, кэшируют и рисуют формочки.
                                  Ответить
                                  • То-есть ты никогда не видел приоложений в которых есть логика, и которые работают оффлайн?

                                    Например, в которых ты можешь составить заявку, и она отошлется когда будет связь с Инетом, и такое приложение должно ее валидировать, например?

                                    Или ты не видел приложений которые имеют локальную БД (CoreData в IOS, sqlite в android) и что-то по ней ищут?
                                    Ответить
                                    • Я всё это видел, я не понимаю, почему C# должен быть сильно лучше чем C++ для работы с локальной базой.

                                      Валидировать заявки на сервере тоже надо.

                                      Если сервер написан на C++, то вообще сплошной вин.

                                      Ты, видимо, хороших либ для C++ не видел.
                                      Ответить
                                      • >>я не понимаю, почему C# должен быть сильно лучше чем C++ для работы с локальной базой.

                                        Потому что LINQ, например) Или потому что рефлексия упрощает ORM.
                                        Но речь была не об этом, а о бизнес логике

                                        >>Валидировать заявки на сервере тоже надо.
                                        конечно.

                                        >>Если сервер написан на C++, то вообще сплошной вин.
                                        Да, но обычные люди скорее напишут бекенд на C#, чем на С++.
                                        Конечно, если они не Гугл, Фейсбук или Яндекс. Я говорю про обычных людей.

                                        >>Ты, видимо, хороших либ для C++ не видел.
                                        Обычно нужно выбирать максимально высокоуровневый инструмент из всех возмжных, ты согласен?

                                        C# более высокоуровневый, в нем сложнее выстрелить себе в ногу, да и программисты дешевле)
                                        Ответить
                                        • > рефлексия упрощает ORM
                                          Если структура базы не меняется после конпеляции - разницы особо нет, просто без рефлексии будет лишний шаг при сборке проекта.
                                          Ответить
                                          • ты имеешь ввиду кодогенерацию?
                                            Ответить
                                            • > ты имеешь ввиду кодогенерацию
                                              Ага.
                                              Ответить
                                              • тоже правда
                                                причем это еще и будет работать во много раз быстрее:)


                                                Ну всё равно всякую хуйню про "скидка 23 процента если чел из города КоньКолодезь" и "длина фамилии не больше 10 буков" в общем случае лучше писать на c#, чем на С++

                                                Хотя такие штуки вообще лучше выносить в какие-нить таблицы
                                                Ответить
                              • Читаю "гуй" как "хуй"
                                Ответить
                            • По мне, когда кто-то большой типа мастдая вкладывает бабки в что-то типа до диеза, делает что-нибудь хорошее и экспериментальное -- надо спокойно исследовать фичи, использовать лучшее (и си шарп, вроде бы как повлиял на джаву-то, проверь), переносить в нормальные места нормальный фичи, а это мс-говно пусть дальше себе гниёт
                              Ответить
                              • Ну сейчас там кое-что опенсорснули, кое-что кое-куда портировали, но в целом 90% c# проектов работает под винду.

                                Если бы было две реализации (открытая и не очень) SDK и VM под Linux, Windows и Mac (как это есть у жабы) то было бы в тыщу раз круче.
                                Я думаю многие перешли бы на C# с java.
                                Ответить
                    • # Сишарп хороший, может быть лучший в своей нише.

                      Он лучший во ВСЕХ нишах. На нём можно писать под что угодно, под телефоны, под древние игровые приставки, операционные системы, приложения рабочего стола, веб-программирование.
                      Ответить
                      • Толсто.
                        Ответить
                        • # Толсто

                          А теперь докажи, что есть язык, который лучше Сишарпика и при этом под все платформы, на которых можно запустить Сишарпик (т.е. просто под все существующие платформы)
                          Ответить
                          • Для этого тебе придется определить "лучше".
                            Ответить
                            • более выразительный
                              больше полезных идиом, литералов, операторов, сахара
                              Ответить
                              • По выразительности, количеству идиом и литералам все сосут у крестов. Но я бы не сказал, что это "лучше".
                                Ответить
                                • perl еще:))

                                  есть просто такие вещи которые однозначно полезны

                                  например, сахар для аксесоров/мутаторов или вывод типов или генерики в рантейме
                                  Ответить
                          • C.
                            Ответить
              • После появления Docker -- да
                Ответить
      • Цыпа, я за одиннадцать лет, проведённых в WEB-программировании на "PHP", не написал ни одного класса; загадочные слова "public", "private" и "interface" до сих пор остаются для меня покрытыми туманом тайны, ибо их великий смысл мне до сих пор так и не понадобился - я не люблю искусственно создавать себе сложности; да и я не индиец, которому платят за буквы и строки, что бы они ни значили.
        Всех пытаются пересадить на "PHP7" с расширением "mysqli_*"; я же до сих пор пишу под "PHP5" с расширением "mysql_*", и при этом все довольны (особенно клиенты, которым, в целом, похуй, как работает, лишь бы работало). В случае, если требуется миграция на "PHP7", я просто подключаю готовую библиотеку с функциями-обёртками для "MySQL", и всё заебца.
        По сути, объектно-ориентированный подход (а точнее - троебучий MVC) является всего лишь одним из агрегатных состояний того языка программирования, в рамках которого применяется. Мне этот кипяток, бурлящий лишними файлами, директориями, ключевыми словами и т.д., весьма неприятен; я предпочитаю процедурный подход комнатной температуры.
        Ответить
        • даже без stdClass и юнит тестов?
          Ответить
          • Без них (толком и не понял, что ты сейчас пизданул).
            Ответить
          • Хуярить массивами вместо stdClass
            Ответить
        • Суперхаккиллер одна тысяча девятьсот девяносто семь, перелогинься
          Ответить
        • Нахуй нужны библиотеки? Почему в index.php все не сложить?
          Ответить
          • # Почему в index.php все не сложить

            А теперь представь, какого размера будет index.php у более-менее крупного проекта.
            Ответить
            • И правда
              Тогда лучше разбить на index2.php и index3.php
              Ответить
              • Ещё лучше для каждой страницы свой php-файл: govnokod.php, kabinka.php, login.php, logout.php.

                Или вообще так: govnokod23477.php, govnokod23478.php, kabinka25723.php, kabinka1659.php.
                Ответить
                • а вот да! пускай каждая страничка живет в своем файле
                  это удобно
                  Ответить
                  • Может, ГК перестал бы тормозить. Явно тут больше читают, чем пишут (вон Пи, по-видимому, сидит и почитывает, ещё псина_из_укр и ещё набор олдфагов - тоже).
                    Ответить
                  • Собственно говоря, именно такова архитектура разрабатываемых мною Интернет-проектов. Разве что с помощью ".htaccess" или "nginx.conf" отсекаю окончание ".php", заменяя его на слэш...
                    Ответить
                    • В такой архитектуре мне импонирует удобство навигации. Скажем, если я хочу добавить страницу, посвященную распродажам, то я просто добавляю файл rasprodazhi.php, и там есть и HTML верстка и все нужные SQL запросы.

                      Добавить страницу очень просто. Никакие MVC и иже с ними такой гибкости не дают.

                      ахахахахахахаххаха
                      Ответить
                      • > и там есть и HTML верстка и все нужные SQL запросы...
                        ... а также все необходимые стили и скрипты для фронтенда.
                        Ответить
                        • Да, именно так. Хотя стили всего сайта можно хранить в stili.css и просто подключать в каждую страничку.
                          А скрипты для фронтэнда тоже можно подключать. Например, страничка может выглядеть вот такт
                          <SCRIPT LANGUAGE=JavaScript SRC="jquery.js"></SCRIPT>
                          <SCRIPT LANGUAGE=JavaScript SRC="jquery.ui.js"></SCRIPT>
                          <SCRIPT LANGUAGE=JavaScript SRC="carousel.js"></SCRIPT>
                          <SCRIPT LANGUAGE=JavaScript SRC="bdccbcfef4526.js"></SCRIPT>
                          <SCRIPT LANGUAGE=JavaScript SRC="stranitsa_pokupok.js"></SCRIPT>
                          <SCRIPT LANGUAGE=JavaScript SRC="script.js"></SCRIPT>

                          Главное тут не перепутать порядок подключения включая нужные скрипты в каждую страничку
                          Ответить
                          • А ещё главное кавычки не забыть.
                            Ответить
                            • Как их забудешь, если строчки для подключения скриптов просто копируешь с других страниц?
                              Ответить
                          • https://pbs.twimg.com/media/D_bLs-SWwAAv6bB.jpg
                            Ответить
                          • Сьома риал куда-то пропал, заметили?
                            Ответить
                            • Да, стало немного скучнее.
                              Ответить
                              • Файку SemaReal забанило.

                                SemaReal это barop aka Roskomgovno, сейчас сидит под гостем. Возможно Stallman тоже его файка.
                                Ответить
                                • > сейчас сидит под гостем

                                  про него и речь
                                  Ответить
                                • Stallman это сильно древний акк для РКГ
                                  Ответить
                                  • А помоемеу это один тот же, они похожи, оба дрочат на всякие руби и ксмли.
                                    Ответить
                • мои годы странствий в поиске идеального паттерна закончены
                  Ответить
        • 1. Как часто тебе в поддержку попадает чужой большой старый проект?
          2. Скольким программистам ты испортил жизнь, вынуждая их поддерживать твои процедурные write and throw проекты без MVC?

          Либо ты сайтист-визиточник, но что тогда ты делаешь одиннадцать лет?

          Странно всё это.
          Ответить
          • Послушайте, автор языка сказал что mvc не нужно, человек просто выбрал официальный подход
            Ответить
            • дураки минусаторы, гуглите "The no-framework PHP MVC framework" Rasmus' Toys Page
              Ответить
              • Читал статью давным давно. Речь там не о том, что MVC нинужен, а о том, что фреймворки нинужны. Это даже из названия понятно всем кроме тебя.
                п.с. минуснул не я.
                Ответить
                • Ну да, конечно. Не открывая статью скажи мне, к какой буковке в MVC относится этот волшебный кусок кода
                  <?php
                  $db = new items();
                  if($_SERVER['REQUEST_METHOD']=='POST') {
                    header("Content-type: application/json");
                    // Load an item entry from backend and send JSON request to populate form
                    if(isset($_POST['load_item'])) {
                      $entry = $db->load($_POST['load_item']);
                      $entry[0]['submit'] = 'Modify Item';
                      if($entry) echo json_encode(array('formName'=>$_POST['formName'],
                                                        'load_item'=>$entry));
                      exit;
                    }
                    // Validate form fields
                    foreach($_POST as $k=>$v) {
                      if(substr($k,0,5)=="desc_") {
                        if(isset($_POST[substr($k,5)]) && $_POST[substr($k,5)]==$v) {
                          echo json_encode(array('validate_error'=>'f_'.substr($k,5)));
                          exit;
                        }
                      }
                    }
                    // Save changes and display status message
                    $status = "Failure";
                    if($_POST['f_submit']=='Modify Item') {
                       $ret = $db->modify($_POST);
                       if($ret) $status = "Modified";
                    } else {
                       $ret = $db->insert($_POST);
                       if($ret) $status = "Added";
                    }
                    echo json_encode(array('status'=>$status,
                                           'elem'=>'tItems',
                                           'reset'=>$ret,
                                           'formName'=>$_POST['formName']));
                    exit;
                  }
                  
                  
                  if(!isset($categories)) load_list('categories');
                  if(!isset($item)) $item = array('cat'=>'');
                  $items = $db->load();
                  ?>
                  Ответить
          • Да он троллит. Не понял что-ли?
            Ответить
      • Ну нихуя себе кто проснулся. То-то я запах вореций учуял.
        Ответить
    • Раз пошла такая флудильня, спрошу и я.
      Есть у меня привычка использовать protected вместо private, просто потому что я никогда до конца не уверен, что потом не придется на базе текущего класса создавать иерархию.
      Это совсем плохо или жить можно?
      Ответить
      • > я никогда до конца не уверен, что потом не придется на базе текущего класса создавать иерархию

        Если не уверен, делай всё private. Классы для создания иерархий должны проектироваться специальным образом, а не когда вздумается. Т.е. если вздумается, всё равно рефакторить придётся. private, вероятно, будет наименьшей из проблем.
        Ответить
        • > иерархия
          Как мне кажется, иерархии вообще нинужны.

          В любой иерархии смешиваются 2 концепции - няшное наследование публичного интерфейса и сомнительное наследование реализации. А из-за наследования реализации:
          1) растёт связность между классами;
          2) реализация размазывается тонким слоем по всей иерархии, её становится сложно понять;
          3) в классах накапливается мусор - поля и методы, которые напихали про запас или ради реализации соседних классов;
          4) начинается херня в духе "а от чего мне наследовать ружьё, чтобы прикрутить его в иерархию?"

          Поэтому, имхо, в иерархии стоит объединять только интерфейсы. А общие куски реализации лучше прикручивать чем-нибудь типа mixin'ов (аля CRTP), а не совать в "базовый класс".
          Ответить
          • Я абсолютно согласен. В плюсах я обычно использую наследование для двух основных юзкейсов:
            1. Собрать класс из микс-инов, часто с CRTP, никакая динамическая диспетчеризация тут не нужна
            2. Реализация интерфейса, как правило, через Non-Virtual Interface Idiom и общей логикой (проверки пред- и пост- кондишенов) в "интерфейсе".
            Ответить
            • > Non-Virtual Interface Idiom
              Ололо, кто-то реально это делает.
              Ответить
          • > общие куски реализации лучше прикручивать чем-нибудь типа mixin'ов
            - а потом назвать это дело аспектами. Дело хорошее, но как-то на практике всё упирается в то, что сделать грамотный и универсальный mixin посложнее, чем решить вопрос, "а от чего мне наследовать ружьё"
            Ответить
      • Это плохо.

        "Проектируйте наследование явно или запрещайте его".

        Сделать класс, который можно наследовать не превратив его в говно -- тяжкий труд. Нужно очень четко понять какие методы можно открыть, и какая у них должна быть политика оверрайда (вызов super перед/после/никогда).

        А идеале 99.9% твоего проекта должны быть финальными и не поддерживать наследование.
        Наследовать надо интерфейсы, а не классы.
        Ответить
        • А если нужна "такая же, но с перламутровыми пуговицами"? Возможность унаследоваться (часто от чужого класса) и чуть-чуть изменить так манит малым количеством кода по сравнению с переписыванием реализации. Это грешно?
          Ответить
          • Это нужно использовать mixins или делегирование.

            Наследоваться просто чтобы переюзать код это не правильно
            Ответить
          • > чуть-чуть изменить
            Вот так в жабе и унаследовали Properties от HashTable....

            Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead.
            Ответить
            • Здесь бы приватное наследование помогло.

              Но тут с LSP проблемы какие-то. Это как целое число от действительного наследовать. Вот если и правда перламутровые пуговицы были бы только добавкой к уже существующему...

              А, или дело тут ещё и в том, что если мы публично наследуемся, то в последующих версиях они могут сами сделать с перламутровыми пуговицами, и тогда все, кто использовал сам класс, не пострадают (обратная совместимость), а все, кто унаследовался - окажутся в зоне риска (конфликты имён, конфликты реализаций).
              Ответить
    • Не совсем втему, но все-таки втему. Я вот нашел в Смолток Репорт статью про БОСС (это статья про то как в 1994, в Смолтоке изобрели велосипед по типу протобафа). Замечательно в ней все: студенческий фанатизм автора, и его приверженость идеологии ООП, рекламные объявления, где объекты продают и еще всякие странные вещи с ними делают, и совсем недорого. Ну и конечно то, что не смотря на потуги и пафос автора, статья на 99% состоит из описаний того, как эта хуета вобщем-то по большому счету нихуя не работает, и как нужно очень осторожно ей пользоваться, а то ща как ебанет!

      Для тех, кому важна хронологическая точность: The Smalltalk Report, October 1994, Volume 4, Number 2. Страницы с 4 по 10.
      Ответить
      • >The Smalltalk Report, October 1994
        Вот год очень кстати. И уже тогда автор начал просекать: "что-то здесь не то".

        >приверженость идеологии ООП, рекламные объявления, где объекты продают и еще всякие странные вещи с ними делают, и совсем недорого.
        Помнится один умный человек говаривал что "это ваше ООП напоминает гербалайф".
        Ответить
        • Слушайте, ну ООП это просто удобный сахар. В нем нет ничего такого, чего нельзя было бы добиться с помощью процедурного подхода. И ничего адски плохого в нем тоже нет.
          Ответить
          • > В нем нет ничего такого, чего нельзя было бы добиться с помощью процедурного подхода.
            - я, конечно, боюсь быть осмеянным вореционными профессорами, но всё же поинтересуюсь, как в процедурном подходе мне что-нибудь заmockать, чтобы потом заюзать в юнит-тестах тестовую реализацию вместо обычной?
            Ответить
            • int result;
              void add(int a, int b) {
                  InitializeAdderService();
                  SetAdderServiceFirstArg(a);
                  SetAdderServiceSecondArg(b);
                  result = CallAdderService();
              }
              
              void add_mock(int a, int b) {
                  InitializeMockAdderService();
                  SetMockAdderServiceFirstArg(a);
                  SetMockAdderServiceSecondArg(b);
                  result = CallMockAdderService();
              }
              
              void test_add() {
                  add_mock(40, 2);
                  assert(result == 42);
              }

              Смекаешь?..
              Ответить
              • какой позор )))
                Ответить
              • А чтобы два раза не писа́ть одно и то же, можно использовать мокросы.
                Ответить
              • С интами каждый gost может. А структуры, батька, структуры?
                Ответить
                • Да как нехуй делать.
                  typedef struct HttpResponse_s {
                      int statusCode;
                      char *content;
                      size_t contentLen;
                      char *headers;
                      size_t headersLen;
                  } HttpResponse;
                  
                  void getPage(const char *url, HttpResponse *outResponse) {
                      char *hostAddr = NULL;
                      size_t hostAddrLen = resolveUrlHostname(url, &hostAddr);
                  
                      TcpResponse rawData;
                      memset(&rawData, 0, sizeof(TcpResponse));
                      loadRawData(hostAddr, url, &rawData);
                  
                      parseRawResponse(&rawData, outResponse);
                  }
                  
                  void getPage_mock(const char *url, HttpResponse *outResponse) {
                      char *hostAddr = NULL;
                      size_t hostAddrLen = resolveUrlHostname_mock(url, &hostAddr);
                  
                      TcpResponse rawData;
                      memset(&rawData, 0, sizeof(TcpResponse));
                      loadRawData_mock(hostAddr, url, &rawData);
                  
                      parseRawResponse_mock(&rawData, outResponse);
                  }


                  Приведи реальный пример кода, который нельзя «замокать» при помощи «Ctrl+Ins, Shift+Ins».
                  Ответить
                  • Именно поэтому я за "gost".
                    Ответить
                  • Ну да, problem solved. Это так реально цари тестируют или всё смехуёчки?
                    Ответить
                    • Цари ничего не тестируют. Цари сразу пишут максимально точный и оптимизированный код.

                      Да как и везде тестируют: берут какую-нибудь «Цмоку»* и вперёд, на баррикады. Именно поэтому я за «цмок».

                      *https://cmocka.org/
                      Ответить
                      • Это для каких-то заедушников.

                        Цари вставляют printf прямо в рабочий код, а перед выпуском программы его комментируют.
                        Ответить
                        • #ifdef DEBUG
                              #define TRACE printf
                          #else
                              #define TRACE(...)
                          #endif
                          Ответить
                        • Нет, ты обделался.

                          Я уже объяснял вам, клоунам, про то что сишка первична.

                          А потом прибегают ублюдки, берут printf и прикручивают поверх него примитивный if.

                          Или хуже того — пилят свои говнологгеры.

                          Это работает через жопу.

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

                          По причине, что авторы этого мусора — биомусор.

                          Цари же добавляют сишнокрестовому компилятору флаг -DNDEBUG и сливают анскильных лалок в хламину.
                          Ответить
                          • Слышь пацанчик, ты базар то фильтруй. Походу ты такой смелый только в виртуале? А слабо в живую, глаза в глаза, такой порожняк прогнать? Ведь стопудово зассышь задрот ты мелкий. Ты если зашёл вспомнить детство (хотя я не уверен, что ты взрослый человек), так вспоминай всё то, что тебе дорого в своём детстве. А для срача другие форумы есть, т олько там тебе похоже вставили и ты припёрся на нормальный сайт, где люди нормально общаются и мозги тут парить начинаешь. не по понятиям это. А по IP адресу вычислить тебя в реале при нынешних технологиях не представляет труда. Так что уймись, пока не началось. Потом извиняться нечем будет.
                            Ответить
                            • Собственно, мы видим прибежавшего опущенца.

                              Хотя тут даже ненужны прошлые фиксации — всё видно сейчас.

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

                              Ничего нет — есть попытка включать идиота, будто бы этот клоун не знает того о чём я говорю, хотя понятие «препроцессора в Си» вполне себе очевидно.

                              Второе и самое важное - тут сразу можно заметить, как это отребье начинает меня обзывать и в чём-то обвинять.

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

                              Это явный офтоп, это явные оскорбления, это явный тупняк, это явная мразь. Фиксируем.
                              Ответить
                              • Браво, гениально! Идеальный генератор универсальных ответов на любые посты.
                                Ответить
    • Сходу въебал минус, даже не читая.
      Ответить

    Добавить комментарий