Главная страница
Навигация по странице:

  • Оптимизация принятия решений

  • Применяйте стандарты разумно, когда они приносят очевидную пользу

  • Системам необходимы предметно- ориентированные языки

  • Формирование архитектуры Джефф Лангр Четыре правила

  • Правило № 1: выполнение всех тестов

  • Правила № 2–4: переработка кода

  • Создание, анализ ирефакторинг


    Скачать 3.16 Mb.
    НазваниеСоздание, анализ ирефакторинг
    Дата29.09.2022
    Размер3.16 Mb.
    Формат файлаpdf
    Имя файлаChistyj_kod_-_Sozdanie_analiz_i_refaktoring_(2013).pdf
    ТипКнига
    #706087
    страница23 из 49
    1   ...   19   20   21   22   23   24   25   26   ...   49

    194
    Глава 11 . Системы
    Хотя код XML занимает много места и плохо читается
    1
    , определяемая в этих конфигурационных файлах «политика» все же проще сложной логики посред- ников и аспектов, скрытой от наших глаз и создаваемой автоматически . Архитек- тура выглядит настолько заманчиво, что инфраструктуры вроде Spring привели к полной переработке стандарта EJB для версии 3 . EJB3 в значительной мере следует характерной для Spring модели декларативной поддержки поперечных областей ответственности с использованием конфигурационных файлов XML и/или аннотаций Java 5 .
    В листинге 11 .5 приведен объект
    Bank
    , переписанный для EJB3 2
    листинг 11 .5 . Компонент Bank для EBJ3
    package com.example.banking.model;
    import javax.persistence.*;
    import java.util.ArrayList;
    import java.util.Collection;
    @Entity
    @Table(name = "BANKS")
    public class Bank implements java.io.Serializable {
    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    @Embeddable // Объект "встраивается" в запись базы данных Bank public class Address { protected String streetAddr1; protected String streetAddr2; protected String city; protected String state; protected String zipCode;
    }
    @Embedded private Address address;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="bank")
    private Collection accounts = new ArrayList();
    public int getId() {
    return id;
    }
    1
    Приведенный пример можно упростить — существуют специальные механизмы, исполь- зующие правила конфигурации и аннотации Java 5 для сокращения объема явно опреде- ляемой «связующей» логики .
    2
    По материалам http://www .onjava .com/pub/a/onjava/2006/05/17/standardizing-with-ejb3- java-persistence-api .html .
    194

    Аспекты AspectJ
    195
    public void setId(int id) {
    this.id = id;
    }
    public void addAccount(Account account) {
    account.setBank(this);
    accounts.add(account);
    }
    public Collection getAccounts() {
    return accounts;
    }
    public void setAccounts(Collection accounts) {
    this.accounts = accounts;
    }
    }
    Этот вариант кода намного чище исходного кода EJB2 . Некоторые подробности о сущностях все еще присутствуют в аннотациях . Тем не менее, поскольку эта информация не выходит за пределы аннотаций, код остается чистым, понятным, а следовательно, простым в тестировании, сопровождении и т . д .
    Часть информации о сохранении объектов, содержащейся в аннотациях, можно при желании переместить в дескрипторы XML, оставив действительно чистый
    POJO-объект . Если детали сохранения объектов изменяются относительно ред- ко, многие группы отдадут предпочтение аннотациям, но с гораздо меньшими отрицательными последствиями по сравнению с EJB2 .
    Аспекты aspectJ
    Наконец, самым полнофункциональным инструментом для разделения областей ответственности посредством использования аспектов является язык AspectJ
    1
    — расширение Java, предоставляющее «полноценную» поддержку аспектов как модульных конструкций . Чистых Java-решений на базе Spring и JBoss достаточно для 80–90% ситуаций, в которых применяются аспекты . Тем не менее AspectJ предоставляет очень мощный и разносторонний инструментарий для реализа- ции разделения ответственности . Недостатком AspectJ является необходимость освоения нескольких новых инструментов, а также изучения новых языковых конструкций и идиом .
    Эти проблемы отчасти компенсируются появившейся недавно «аннотационной» формой AspectJ, в которой аннотации Java 5 используются для определения аспектов в «чистом» коде Java . Кроме того, Spring Framework также содержит ряд функций, существенно упрощающих внедрение аспектов на базе аннотаций в рабочих группах с ограниченным опытом применения AspectJ .
    1
    См . [AspectJ] и [Colyer] .
    195

    196
    Глава 11 . Системы
    Полное описание AspectJ выходит за рамки книги . За дополнительной инфор- мацией обращайтесь к [AspectJ], [Colyer] и [Spring] .
    Испытание системной архитектуры
    Трудно переоценить потенциал разделения ответственности посредством аспект- ных решений . Если вы можете написать логику предметной области своего при- ложения в виде POJO-объектов, отделенных от любых архитектурных областей ответственности на кодовом уровне, то перед вами открывается возможность проведения полноценных испытаний вашей архитектуры . Вы сможете развивать ее от простого к сложному, как потребует ситуация, подбирая новые технологии по мере надобности . Не обязательно создавать Большой Изначальный Проект
    (BDUF, Big Design Up Front)
    1
    . Более того, это даже вредно, потому что BDUF снижает возможность адаптации к изменениям из-за нашего психологического нежелания расставаться с результатами уже затраченных усилий; кроме того, изначально принятые решения влияют на наши последующие представления об архитектуре .
    Архитекторы, занимающиеся строительством зданий, вынуждены работать по принципу BDUF, потому что они не могут вносить радикальные архитектурные изменения в наполовину возведенное физическое строение
    2
    . Программные про- дукты тоже обладают собственной физикой
    3
    , но радикальные изменения в них могут оказаться экономически оправданными — при условии, что в программном проекте эффективно реализовано разделение ответственности .
    Это означает, что мы можем начать программный проект с «простой до наи- вности», но лишенной жестких привязок архитектуры, быстро реализовать пожелания пользователей, а затем добавлять новую инфраструктуру по мере масштабирования . Некоторые из крупнейших мировых сайтов достигли высочай- ших показателей доступности и производительности, с применением сложного кэширования данных, безопасности, виртуализации и т . д ., и все это делается эффективно и гибко — и только потому, что на каждом уровне абстракции их архитектура оставалась простой и обладала минимальными привязками .
    Конечно, это не означает, что за проект нужно браться по принципу «как-нибудь по ходу разберемся» . Вы уже в определенной степени представляете себе общий масштаб, цели и график проекта, а также общую структуру итоговой системы .
    Однако при этом необходимо сохранить возможность «смены курса» в соответ- ствии с изменяющимися обстоятельствами .
    1
    Не путайте с полезной практикой упреждающего проектирования . BDUF — привычка проектировать заранее все без исключения, до написания какого-либо кода реализации .
    2
    Впрочем, даже после начала строительства идут серьезные итеративные исследования и обсуждения подробностей .
    3
    Выражение «физика программного продукта» впервые было использовано в [Kolence] .
    196

    Применяйте стандарты разумно, когда они приносят очевидную пользу
    197
    Ранняя архитектура EJB была всего лишь одним из многих API, которые отлича- лись излишней сложностью, нарушавшей принцип разделения ответственности .
    Впрочем, даже хорошо спроектированный API может оказаться «перебором» в конкретной ситуации, если его применение не объясняется реальной необходи- мостью . Хороший API должен исчезать из вида большую часть времени, чтобы большая часть творческих усилий группы расходовалась на реализацию пожела- ний пользователей . В противном случае архитектурные ограничения помешают оптимальной реализации интересов клиента .
    Подведем итог .
    Оптимальная архитектура системы состоит из модульных областей ответственно- сти, каждая из которых реализуется на базе POJO-объектов. Области интегриру- ются между собой при помощи аспектов или аналогичных средств, минимальным образом вмешивающихся в их работу. Такая архитектура может строиться на базе методологии разработки через тестирование, как и программный код.
    Оптимизация принятия решений
    Модульность и разделение ответственности позволяют децентрализовать управ- ление и принятие решений . В достаточно крупной системе, будь то город или программный проект, один человек не может принять все необходимые решения .
    Как известно, ответственные решения лучше всего поручить самому квалифи- цированному . Однако мы часто забываем, что принятие решений лучше всего откладывать до последнего момента . Дело не в лени или безответственности; просто это позволяет принять информированное решение с максимумом воз- можной информации . Преждевременное решение принимается на базе неполной информации . Принимая решение слишком рано, мы лишаемся всего полезного, что происходит на более поздних стадиях: обратной связи от клиентов, возмож- ности поразмышлять над текущим состоянием проекта и опыта применения решений из области реализации .
    Гибкость POJO-системы с модульными областями ответственности позволяет при- нимать оптимальные, своевременные решения на базе новейшей информации.
    Кроме того, она способствует снижению сложности таких решений.
    Применяйте стандарты разумно,
    когда они приносят очевидную пользу
    Строительство кажется настоящим чудом из-за темпов, которым возводятся новые здания (даже в разгар зимы), и из-за необычных архитектурных дизайнов, ставших возможными благодаря современным технологиям . Строительство стало
    197

    198
    Глава 11 . Системы развитой областью промышленности с высокой оптимизацией частей, методов и стандартов, сформированных под давлением времени .
    Многие группы использовали архитектуру EJB2 только потому, что она считалась стандартом, даже если в их проектах хватило бы более легких и прямолинейных решений . Я видел группы, которые теряли голову от разрекламированных стан- дартов и забывали о своей главной задаче: реализовывать интересы клиента .
    Стандарты упрощают повторное использование идей и компонентов, привлече- ние людей с необходимым опытом, воплощение удачных идей и связывание ком- понентов. Тем не менее, процесс создания стандарта иногда занимает слишком много времени (а отрасль не стоит на месте), в результате чего стандарты теря- ют связь с реальными потребностями тех людей, которым они должны служить.
    Системам необходимы предметно-
    ориентированные языки
    В области строительства, как и в большинстве технических областей, сформи- ровался богатый язык со своим словарем, идиомами и паттернами
    1
    , позволяю- щими четко и лаконично передать важную информацию . В области разработки программного обеспечения в последнее время снова возобновился интерес к предметно-ориентированным языкам
    2
    (DSL, Domain-Specic Languages) — отдельным маленьким сценарным языкам или API стандартных языков, код которых читается как структурированная форма текста, написанного экспертом в данной предметной области .
    Хороший предметно-ориентированный язык сводит к минимуму «коммуникаци- онный разрыв» между концепцией предметной области и кодом, реализующим эту концепцию — по аналогии с тем, как гибкие методологии оптимизируют обмен информацией между группой и ключевыми участниками проекта . Реа- лизация логики предметной области на языке, используемом экспертом в этой области, снижает риск неверного представления предметной области в коде .
    Предметно-ориентированные языки, когда они используются эффективно, под- нимают уровень абстракции над программными идиомами и паттернами проек- тирования . Они позволяют разработчику выразить свои намерения на соответ- ствующем уровне абстракции .
    Предметно-ориентированные языки позволяют выразить в форме POJO-объектов все уровни абстракции и все предметные области приложения, от высокоуровне- вых политик до низкоуровневых технических подробностей.
    1
    Работа [Alexander] оказала особенно заметное влияние на сообщество разработчиков ПО .
    2
    Например, см . [DSL] . [JMock] — хороший пример Java API, создавшего свой предметно- ориентированный язык .
    198

    Литература
    199
    Заключение
    Чистым должен быть не только код, но и архитектура системы . Агрессивная, «все- проникающая» архитектура скрывает логику предметной области и снижает гиб- кость . Первое приводит к снижению качества: ошибкам проще спрятаться в коде, а разработчику труднее реализовать пожелания пользователей . Второе оборачи- вается снижением производительности, а также потерей всех преимуществ TDD .
    Намерения разработчика должны быть четко выражены на всех уровнях аб- стракции . Это произойдет только в том случае, если он создает POJO-объекты, и использует аспекты (или другие аналогичные механизмы) для неагрессивного воплощения других сторон реализации .
    Независимо от того, проектируете ли вы целую систему или ее отдельные модули, помните: используйте самое простое решение из всех возможных .
    литература
    [Alexander]: Christopher Alexander, A Timeless Way of Building, Oxford University
    Press, New York, 1979 .
    [AOSD]: Aspect-Oriented Software Development port, http://aosd .net
    [ASM]: ASM Home Page, http://asm .objectweb .org
    [AspectJ]: http://eclipse .org/aspectj
    [CGLIB]: Code Generation Library, http://cglib .sourceforge .net
    [Colyer]: Adrian Colyer, Andy Clement, George Hurley, Mathew Webster, Eclipse
    AspectJ, Person Education, Inc ., Upper Saddle River, NJ, 2005 .
    [DSL]: Domain-speci
    fic programming language, http://en .wikipedia .org/wiki/
    Domain-speci
    fic_programming_language
    [Fowler]: Inversion of Control Containers and the Dependency Injection pattern, http://martinfowler .com/articles/injection .html
    [Goetz]: Brian Goetz, Java Theory and Practice: Decorating with Dynamic Proxies, http://www .ibm .com/developerworks/java/library/j-jtp08305 .html
    [Javassist]: Javassist Home Page, http://www .csg .is .titech .ac .jp/

    chiba/javassist
    [JBoss]: JBoss Home Page, http://jboss .org
    [JMock]: JMock — A Lightweight Mock Object Library for Java, http://jmock .org
    [Kolence]: Kenneth W . Kolence, Software physics and computer performance measurements, Proceedings of the ACM annual conference—Volume 2, Boston,
    Massachusetts, pp . 1024–1040, 1972 .
    [Spring]: The Spring Framework, http://www .springframework .org
    [Mezzaros07]: XUnit Patterns, Gerard Mezzaros, Addison-Wesley, 2007 .
    [GOF]: Design Patterns: Elements of Reusable Object Oriented Software, Gamma et al ., Addison-Wesley, 1996 .
    199

    Формирование
    архитектуры
    Джефф Лангр
    Четыре правила
    Разве не хотелось бы вам знать четыре простых правила, выполнение которых помогало бы повысить качество проектирования? Четыре правила, помогающих составить представление о важнейших особенностях структуры и архитектуры кода, упрощающих применение таких принципов, как SRP (принцип единой ответственности) и DIP (принцип обращения зависимостей)? Четыре правила, способствующих формированию хороших архитектур?
    Многие полагают, что четыре правила простой архитектуры [XPE]Кента Бека оказывают значительную помощь в проектировании программных продуктов .
    12
    200

    Четыре правила
    201
    Согласно Кенту, архитектура может считаться «простой», если она:
    
    обеспечивает прохождение всех тестов,
    
    не содержит дублирующегося кода,
    
    выражает намерения программиста,
    
    использует минимальное количество классов и методов .
    Правила приведены в порядке их важности .
    Правило № 1: выполнение всех тестов
    Прежде всего система должна делать то, что задумано ее проектировщиком . Си- стема может быть отлично спланирована «на бумаге», но если не существует про- стого способа убедиться в том, что она действительно решает свои задачи, то ре- зультат выглядит сомнительно .
    Система, тщательно протестированная и прошедшая все тесты, контролируема .
    На первый взгляд утверждение кажется очевидным, но это весьма важно . Невоз- можно проверить работу системы, которая не является контролируемой, а непро- веренные системы не должны запускаться в эксплуатацию .
    К счастью, стремление к контролируемости системы ведет к архитектуре с ком- пактными узкоспециализированными классами . Все просто: классы, соответ- ствующие принципу SRP, проще тестировать . Чем больше тестов мы напишем, тем дальше продвинемся к простоте тестирования . Таким образом, обеспечение полной контролируемости системы помогает повысить качество проектирования .
    Жесткая привязка усложняет написание тестов . Таким образом, чем больше тестов мы пишем, тем интенсивнее используем такие принципы, как DIP, и та- кие инструменты, как внедрение зависимостей, интерфейсы и абстракции, для минимизации привязок .
    Как ни удивительно, выполнение простого и очевидного правила, гласящего, что для системы необходимо написать тесты и постоянно выполнять их, влияет на соответствие системы важнейшим критериям объектно-ориентированного программирования: устранению жестких привязок и повышению связности .
    Написание тестов улучшает архитектуру системы .
    Правила № 2–4: переработка кода
    Когда у вас появился полный набор тестов, можно заняться чисткой кода и клас- сов . Для этого код подвергается последовательной переработке (рефакторингу) .
    Мы добавляем несколько строк кода, делаем паузу и анализируем новую архи- тектуру . Не ухудшилась ли она по сравнению с предыдущим вариантом? Если ухудшилась, то мы чистим код и тестируем его, чтобы убедиться, что в нем ничего не испорчено . Наличие тестов избавляет от опасений, что чистка кода нарушит его работу!
    201

    202
    Глава 12 . Формирование архитектуры
    В фазе переработки применяется абсолютно все, что вы знаете о качественном проектировании программных продуктов . В ход идут любые приемы: повышение связности, устранение жестких привязок, разделение ответственности, изоляция системных областей ответственности, сокращение объема функций и классов, выбор более содержательных имен и т . д . Также применяются три критерия простой архитектуры: устранение дубликатов, обеспечение выразительности и минимизация количества классов и методов .
    Отсутствие дублирования
    Дублирование — главный враг хорошо спроектированной системы . Его послед- ствия — лишняя работа, лишний риск и лишняя избыточная сложность . Дубли- рование проявляется во многих формах . Конечно, точное совпадение строк кода свидетельствует о дублировании . Похожие строки часто удается «причесать» так, чтобы сходство стало еще более очевидным; это упростит рефакторинг . Кроме того, дублирование может существовать и в других формах — таких, как дубли- рование реализации . Например, класс коллекции может содержать следующие методы:
    int size() {}
    boolean isEmpty() {}
    Методы могут иметь разные реализации . Допустим, метод isEmpty может исполь- зовать логический флаг, а size
    — счетчик элементов . Однако мы можем устранить дублирование, связав isEmpty с определением size
    :
    boolean isEmpty() {
    return 0 == size();
    }
    Чтобы создать чистую систему, необходимо сознательно стремиться к устра- нению дубликатов, пусть даже всего в нескольких строках кода . Для примера рассмотрим следующий код:
    public void scaleToOneDimension(
    float desiredDimension, float imageDimension) {
    if (Math.abs(desiredDimension - imageDimension) < errorThreshold)
    return;
    float scalingFactor = desiredDimension / imageDimension;
    scalingFactor = (float)(Math.floor(scalingFactor * 100) * 0.01f);
    RenderedOp newImage = ImageUtilities.getScaledImage(
    image, scalingFactor, scalingFactor);
    image.dispose();
    System.gc();
    image = newImage;
    }
    public synchronized void rotate(int degrees) {
    RenderedOp newImage = ImageUtilities.getRotatedImage(
    image, degrees);
    202

    Четыре правила
    1   ...   19   20   21   22   23   24   25   26   ...   49


    написать администратору сайта