• Эволюция программного проекта и ООП

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


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


      Стало интересно выполнить анализ применимости этих понятий для общепринятых парадигм программирования, например для ООП. Хорошо, если результат этой работы будет полезен и Вам.


      image

      Читать дальше →
    • Код живой и мёртвый. Часть третья. Код как текст

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


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


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

        Читать дальше →
      • Код живой и мёртвый. Часть вторая. Действия и свойства

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


          Сложно оценить героя, не поняв его "статы" и "абилки". Что он может и на что способен — вот следующий уровень сложности, на который нам придётся нырнуть. Мало с помощью точного имени отразить внутреннее святилище объекта, ещё следует убедиться, что это таки святилище, а не конюшни из геттеров.


          Об этом — в статье.

          Читать дальше →
        • Код живой и мёртвый. Часть первая. Объекты

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


            И вместе с этим мы видим повсеместную эпидемию менеджеров, хелперов, сервисов, контроллеров, селекторов, адаптеров, геттеров, сеттеров и другой нечисти: всё это мёртвый код. Он сковывает и загромождает.


            Бороться предлагаю вот как: нужно представлять программы как текст на естественном языке и оценивать их соответственно. Как это и что получается — в статье.

            Читать дальше →
          • Язык программирования, помещающийся на почтовой открытке

            image
            Источник


            Ральф Джонсон, один из членов "Банды четырёх", однажды показал, как синтаксис языка Smalltalk-80 можно уместить на почтовой открытке. Сейчас, спустя почти 30 лет после появления первой версии Smalltalk, самым быстроразвивающимся диалектом Smalltalk является Pharo, почтовую открытку которого далее и разберём.

            Читать дальше →
          • Наследование в C++: beginner, intermediate, advanced

              В этой статье наследование описано на трех уровнях: beginner, intermediate и advanced. Expert нет. И ни слова про SOLID. Честно.


              Beginner


              Что такое наследование?


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


              Класс, который наследует данные, называется подклассом (subclass), производным классом (derived class) или дочерним классом (child). Класс, от которого наследуются данные или методы, называется суперклассом (super class), базовым классом (base class) или родительским классом (parent). Термины “родительский” и “дочерний” чрезвычайно полезны для понимания наследования. Как ребенок получает характеристики своих родителей, производный класс получает методы и переменные базового класса.


              Наследование полезно, поскольку оно позволяет структурировать и повторно использовать код, что, в свою очередь,

              Читать дальше →
            • Инкапсуляция для настоящих самураев, или нюансы, связанные с ключевым словом internal в C#

              Пролог: internal is new public


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


              image

              Случился такой проект и в моей жизни. Очередной. Причём делаю я его под добровольным надзором, где за каждой моей строчкой следят. Соответственно, уже не только хотелось, но и надо было делать всё правильно. Одним из «правильно» было «чти инкапсуляцию и закрывайся по максимуму, потому что открыться всегда успеешь, а закрыться обратно потом будет поздно». И поэтому я везде, где только мог, стал использовать для классов модификатор доступа internal вместо public. И, естественно, когда ты начинаешь активно использовать новую для тебя фичу языка, возникают некоторые нюансы. О них по порядку и хочу рассказать.

              Читать дальше →
            • Реклама
              AdBlock похитил этот баннер, но баннеры не зубы — отрастут

              Подробнее
            • Три дзена reactive extensions

                "Reactive Extensions" — это больше, чем фреймворк. Хотя бы потому, что существует практически идентичная реализация (с поправкой на особенности конкретного языка и соответствующих практик оптимизации) под каждый популярный ЯП. Есенин утверждает, что «большое видится на расстояньи». В этой записке я буду отходить на разные «расстоянья» и описывать то, что видится мне.
                Читать дальше →
              • Как устроен фреймворк tiOPF для delphi/lazarus. Шаблон «Посетитель»

                • Tutorial

                От переводчика


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

                1. Несколько лет назад я, познав многие прелести работы с Entity Framework как ORM для платформы .Net, тщетно искал аналоги для среды Lazarus и в общем для freepascal.
                Удивительно, но хорошие ORM для нее отсутствуют. Всё, что тогда удалось найти — open-source проект под названием tiOPF, разработанный еще в конце 90-х годов для delphi, позже портированный под freepascal. Однако этот фреймворк коренным образом отличается от привычного вида больших и толстых ORM.

                Визуальные способы проектирования объектов (в Entity — model first) и сопоставления объектов с полями таблиц реляционной базы данных (в Entity — database first) в tiOPF отсутствуют. Разработчик сам позиционирует этот факт как один из недостатков проекта, однако в качестве достоинства предлагает полную ориентацию именно на объектную бизнес-модель, стоит лишь один раз похардкодить…
                Читать дальше →
              • ООП мертво, да здравствует ООП

                • Перевод
                image

                Источники вдохновения


                Этот пост возник благодаря недавней публикации Араса Пранцкевичуса о докладе, предназначенном для программистов-джуниоров. В нём рассказывается о том, как адаптироваться к новым ECS-архитектурам. Арас следует привычной схеме (объяснения ниже): показывает примеры ужасного ООП-кода, а затем демонстрирует, что отличным альтернативным решением является реляционная модель (но называет её «ECS», а не реляционной). Я ни в коем случае не критикую Араса — я большой фанат его работ и хвалю его за отличную презентацию! Я выбрал именно его презентацию вместо сотен других постов про ECS из Интернета потому, что он приложил дополнительные усилия и опубликовал git-репозиторий для изучения параллельно с презентацией. В нём содержится небольшая простая «игра», используемая в качестве примера выбора разных архитектурных решений. Этот небольшой проект позволил мне на конкретном материале продемонстрировать свои замечания, так что спасибо, Арас!

                Слайды Араса выложены здесь: http://aras-p.info/texts/files/2018Academy — ECS-DoD.pdf, а код находится на github: https://github.com/aras-p/dod-playground.

                Я не буду (пока?) анализировать получившуюся ECS-архитектуру из этого доклада, но сосредоточусь на коде «плохого ООП» (похожего на уловку «чучело») из его начала. Я покажу, как бы он выглядел на самом деле, если бы правильно исправили все нарушения принципов OOD (object-oriented design, объектно-ориентированного проектирования).

                Спойлер: устранение всех нарушений OOD приводит к улучшениям производительности, аналогичным преобразованиям Араса в ECS, к тому же использует меньше ОЗУ и требует меньше строк кода, чем ECS-версия!

                TL;DR: Прежде чем прийти к выводу, что ООП отстой, а ECS рулит, сделайте паузу и изучите OOD (чтобы знать, как правильно использовать ООП), а также разберитесь в реляционной модели (чтобы знать, как правильно применять ECS).
                Читать дальше →
              • KISS Architecture. От микросервиса до монолита

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


                Читать дальше →
              • Внутренние и вложенные классы java. Часть 3

                Внутренние и вложенные классы java. Часть 3
                Локальные классы

                <<< Часть 1
                <<< Часть 2

                Локальный класс — это вложенный класс, объявленный внутри другого класса и некоторого блока кода этого класса, то есть объявленный между фигурными скобками {}. Этот блок может быть статическим блоком, циклом, телом if и т.д.

                Можно объявить вложенный класс внутри блока кода, например метода, конструктора или блока инициализации. Он будет называться локальным вложенным классом. Чаще всего локальные классы объявляются внутри тела метода.

                Локальный класс объявленный внутри блока кода другого класса не является членом класса, к которому относится блок, а принадлежит самому блоку, точно так же, как обычная локальная переменная. Такие классы недоступны за пределами внешнего класса, поскольку нет никаких способов обращения к ним, но их экземпляры – это обычные объекты, которые позволяется, например, передавать в качестве аргументов или возвращать из методов.
                Время жизни локального внутреннего класса, это время пока существует хотя бы одна ссылка на него. Такой класс существует внутри блока кода и время его жизни ограниченно этим блоком.

                Напишем пример:

                /*Учебный пример №12 */
                package localclasses;
                
                /**
                 *
                 * @author Ar20L80
                 */
                public class OuterStaticInit {
                     static 
                     { 
                         class LocalInit{
                         LocalInit(){
                         System.out.println("From static iniz"); 
                         }
                         }
                     LocalInit localInit = new LocalInit();
                     System.exit(0); 
                     } 
                     public static void main(String[] args) {
                        System.out.println("From main"); 
                    }
                }
                




                В нашем примере локальный класс «просуществовал» только в области локальной статичной инициализации. Тело «main» не было вызвано. Единственный модификатор, который допускается применять в объявлении локального класса, – это final, предотвращающий, как обычно, возможность расширения класса. Члены локального класса могут быть объявлены как закрытыми, так и открытыми. К ним применяются модификаторы, которые применимы к обычному классу.( java 8)

                Еще раз повторим коротко: Локальный класс – это класс, объявленный в блоке Java кода.

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

                /**
                 * Учебный пример №13
                 * @author Ar20L80
                 */
                public class OuterLocal {
                    OuterLocal(){
                        // начало блока конструктора
                
                        /*объявление локального класса в конструкторе OuterLocal*/
                        class LocalInnerClass {
                            LocalInnerClass(){}
                        }
                    /* создаем экземпляр в том же блоке*/
                        LocalInnerClass localObj = new LocalInnerClass();
                      // окончание блока конструктора
                    }
                



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

                 
                 /**
                 * Учебный пример №14
                 * @author Ar20L80
                 */
                public class OuterLocal {
                    OuterLocal(){
                        
                        /*объявление локального класса в конструкторе OuterLocal*/
                        class LocalInnerClass {
                            LocalInnerClass(){}
                        }
                    /* создаем экземпляр в том же блоке*/
                        LocalInnerClass localObj = new LocalInnerClass();
                    }
                    
                    
                    public static void main(String[] args) {
                       //  LocalInnerClass localObj = new LocalInnerClass(); не можем создать объект локального класса 
                	   // вне области видимости содержащего его блока
                    }
                }
                 
                 



                Свойства локального класса:
                Подобно вложенным нестатическим классам, локальные классы связаны с окружающим экземпляром и имеют доступ ко всем членам, включая private члены окружающего класса. Локальный класс нельзя объявить с каким-либо модификатором доступа, кроме как static final.

                 /*Учебный пример пример №15 */
                public class OuterStaticLocal {
                    
                	OuterStaticLocal(){
                	   // static class Local{}  ошибка не может быть статичным
                	}
                } 
                



                Потому что, модификаторы доступа для членов класса мы можем применять только к членам класса. Эти модификаторы не доступны для объявления локальных переменных или классов, находящихся в блоке и не являющиеся членами класса.

                  /**
                 * Учебный пример №16 
                 * @author Ar20L80
                 */
                public class OuterLocal2 {
                    OuterLocal2(){
                      final  class LocalInnerClass {
                            LocalInnerClass(){}
                        }
                    }
                } 
                


                Как и нестатические вложенные классы, и по тем же причинам, локальные классы не могут иметь static поля, исключение составляют константы, объявленные как static final.

                 /**
                 *  Учебный пример №17
                 
                 * @author Ar20L80
                 * тут я вернул переменную локального класса через iTemp внешнего класса
                 */
                public class OuterClass {
                     
                    private int iTemp;
                    OuterClass(){
                    // объявим внутри конструктора класс
                    
                    /* здесь мы не можем использовать private, public
                    применительно к локальному классу*/
                     final  class LocalInnerClass01{ 
                      /* сам локальный класс может содержать 
                         как private, так и public */
                      private static final int INT_FIN = 10;
                      LocalInnerClass01(){
                       iTemp = Return_INT_FIN();
                      }
                      int Return_INT_FIN(){
                      return INT_FIN;
                      }
                      
                     }
                    
                     class LocalInnerClass02{
                      // public static int i=11; ошибка не может быть не константой внутри 
                     // локального вложенного класса
                     }
                     
                     /* создаем локальные объекты  локальных классов в том же конструкторе*/
                     LocalInnerClass01 localInnerClass1 = new LocalInnerClass01();
                     LocalInnerClass02 localInnerClass2 = new LocalInnerClass02();
                     
                     
                    }
                     
                    public static void main(String[] args) {
                     OuterClass outerClass = new OuterClass();
                     
                     System.out.println(outerClass.iTemp ); // = 10
                    //OuterClass.LocalInnerClass1 innerObject = outerClass.new LocalInnerClass1(); ошибка - это не 
                   // внутренний класс, а локальный. И мы не имеем к нему доступа.
                    }
                
                    
                    
                }
                



                Применение:
                Основное применение локальные классы находят в тех случаях, когда необходимо написать класс, который будет использоваться внутри одного метода. Создание локального класса – способ не загромождать пространство имен.

                Если класс определяется в теле метода, то его называют локальным внутренним классом. Пример доступа к переменным внешнего класса из локального внутреннего класса:
                Читать дальше →
              • Внутренние и вложенные классы java. Часть 2

                Внутренние и вложенные классы java. Часть 2

                02.03.2017 — 2019 год

                <<< Часть 1
                Часть 3 >>>

                Часть 2

                Внутренние классы

                Inner Classes — Внутренние классы

                Внутренний класс связан с экземпляром его обрамляющего класса (из документации).

                Пример внутреннего класса есть в документации.

                Создадим класс:

                /* Пример №7 */
                 
                class OuterClass {
                    ...
                    class InnerClass {
                        ...
                    }
                }
                 

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

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

                 OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 


                Пример:

                
                 /* Пример №8 файл Outer.java*/
                package inner;
                
                /**
                 *
                 * @author Ar20L80
                 */
                public class Outer {
                    
                   
                    class InnerClass {
                        
                    }
                    Outer(){}
                    
                    public static void main(String[] args) {
                    Outer outerObject = new Outer();
                    Outer.InnerClass innerObject = outerObject.new InnerClass(); // создание экземпляра 
                 внутреннего класса
                    }
                }
                 


                По-другому мы можем написать так:
                Читать дальше →
              • Внутренние и вложенные классы java. Часть 1

                Внутренние и вложенные классы java. Часть 1

                02.03.2017 — 2019 год

                Часть 1. Начало



                Цель статьи: Рассказать о внутренних, вложенных, локальных, анонимных классах. Показать примеры их использования. Написать и протестировать классы в коде на java. Рассказать о свойствах этих классов. Материал предназначен для лучшего понимания безымянных классов, лямбда выражений, адаптеров и многопоточности. То есть перед их изучением.

                Читать дальше →
                • +11
                • 26,3k
                • 8
              • 9 альтернатив плохой команде (шаблону проектирования)

                image

                Что это и зачем?


                При проектировании разработчик может столкнуться с проблемой: у существ и объектов могут быть разные способности в разных сочетаниях. Лягушки прыгают и плавают, утки плавают и летают, но не с гирей, а лягушки могут летать с веткой и утками. Поэтому удобно перейти от наследования к композиции и добавлять способности динамически. Необходимость анимировать летающих лягушек привела к неоправданному отказу от методов способностей и выносу их кода в команды в одной из реализаций. Вот она:
                Читать дальше →
              • Паттерн Интерактор (Interactor, Operation)

                • Tutorial

                Данный текст представляет собой адаптацию части руководства фрэймворка Hanami под фрэймфорк Laravel. Чем вызван интерес именно к этому материалу? В нём даётся пошаговое описание с демонстрацией таких общих для языков программирования и фрэймворков вещей как:


                • Использование паттерна "Интеракторы".
                • Демонстрация TDD\BDD.

                Сразу стоит отметить, что это не только разные фрэймворки с разной идеологией (в частности, что касается ORM), но и разные языки программирования, каждый из которых имеет свою специфическую культуру и сложившиеся "bests practics" в силу исторических причин. Разные языки программирования и фрэймворки тяготеют к заимствованию друг у друга наиболее удачных решений, поэтому несмотря на различия в деталях, фундаментальные вещи не различаются, если мы конечно не берём ЯП с изначально разной парадигмой. Достаточно интересно сравнить, как одну и туже задачу решают в разных экосистемах.


                Итак, исходно мы имеем фрэймворк Hanami (ruby) — достаточно новый фрэймворк, идеологически больше тяготеющий к Symfony, с ORM "на репозиториях". И целевой фрэймворк Laravel\Lumen (php) с Active Record.

                Читать дальше →
              • JavaScript: Публичные и приватные поля классов

                • Перевод

                Несколько предложений расширяют существующий синтаксис классов в JavaScript новой функциональностью. Эта статья объясняет новый синтаксис публичных полей классов в V8 v7.2 и Chrome 72, а также грядущих приватных полей.


                Вот пример кода, который создает экземпляр класса IncreasingCounter:


                const counter = new IncreasingCounter();
                counter.value;
                // logs 'Getting the current value!'
                // → 0
                counter.increment();
                counter.value;
                // logs 'Getting the current value!'
                // → 1

                Отметим, что обращение к value выполняет некоторый код (вывод сообщения в лог) перед тем, как вернуть значение. Теперь спросите себя: как бы Вы реализовали этот класс на JavaScript?

                Читать дальше →
              • Композиция против наследования, паттерн Команда и разработка игр в целом


                  Дисклеймер: По-моему, статья об архитектуре ПО не должна и не может быть идеальной. Любое описанное решение может покрывать необходимый одному программисту уровень недостаточно, а другому программисту — слишком усложнит архитектуру без надобности. Но она должна давать решение тем задачам, которые поставила перед собой. И этот опыт, вместе со всем остальным багажом знаний программиста, который обучается, систематизирует информацию, оттачивает новыки, и критикует сам себя и окружающих — этот опыт превращается в отличные програмные продукты. Статья будет переключаться между художественой и технической частью. Это небольшой эксперимент и я надеюсь, что он будет интересным.
                  — Слушай, я тут придумал отличную идею игры! — гейм-дизайнер Вася был взъерошен, а глаза — красные. Я ещё попивал кофе и холиварил на Хабре, чтобы убить время перед стенд-апом. Он выжидательно посмотрел на меня, пока я закончу писать в комментариях человеку, в чем он не прав. Вася знал, что пока справедливость не восторжествует, а правда не будет защищена — смысла продолжать со мной разговор нету. Я дописал последнее предложение и перевел на него взгляд.

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

                  Он убежал по своим гейм-дизайнерским делам, а я — открыл IDE.
                  Читать дальше →
                • Цена композиции в Javascript-мире

                    Мысль о том, что в разработке любой более-менее сложной бизнес-логики приоритет должен отдаваться композиции объектов, нежели наследованию популярна в среде разработчиков программных продуктов самых разных типов. На очередной волне популярности функциональной парадигмы программирования, запущенной состоявшимся успехом ReactJS, разговоры о преимуществах композиционных решений пришли и во фронтенд. В данном посте есть немного раскладки по полкам теории о композиции объектов в Javascript, конкретный пример, его разбор и ответ на вопрос сколько стоит смысловая элегантность для пользователя (спойлер: немало).

                    В.Кандинский - Композиция X
                    Василий Кандинский — «Композиция X»
                    Читать дальше →
                  • Архитектурный шаблон «Итератор» («Iterator») во вселенной «Swift»

                      «Итератор» – один из шаблонов проектирования, которые программисты чаще всего не замечают, потому что его реализация, как правило, встроена непосредственно в стандартные средства языка программирования. Тем не менее, это тоже один из поведенческих шаблонов, описанных в книге «Банды четырех» (“Gang of Four”, “GoF”) “Шаблоны проектирования” (“Design Patterns: Elements of Reusable Object-Oriented Software”), и понимать его устройство никогда не помешает, а иногда даже может в чем-то помочь.
                      Читать дальше →
                      • +14
                      • 4,8k
                      • 2

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