среда, 11 мая 2011 г.

с. 167


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

среда, 27 апреля 2011 г.

c. 166 Связывание Измерения и Показателя


Что ж, получилось нечто похожее, как и у меня... Но так явно включать Показатель в Измерение... Мне не нравится. В моём коде эта функциональность выглядит так:
Quantity.
this.rangeName = resolutionType.getResolutionRangeName(value);
То есть Количество, которое является результатом некоторого измерения, само определяет, к какому численному диапазону оно относится. Класс Измерение никак не вмешивается в этот процесс.
-----
"Нет необходимости чересчур формально подходить к выполнению проекта и пытаться использовать абсолютно все возможности языка UML. Вполне достаточно пользоваться только теми из них, которые представляются вам полезными."
"Если ... я сочту, что диаграмма ... не вносит никакой дополнительной ясности в программный код, то сдам её в архив."
-----

вторник, 19 апреля 2011 г.

с. 165 Модификация модели спецификации (Фаулер)


Итак... Для Типа Показателя смоделирована квалифицированная роль Строка. Что это такое?.. Показатель связан с Типом Показателя посредством роли Строка. В каждом экземпляре Показателя Тип Показателя представлен Строкой?.. В Показателе Строка, т.е. Тип Показателя, может присутствовать, а может и отсутствовать. А зачем нужен Показатель без Типа Показателя?.. Что он показывает, такой Показатель?.. Смотрим в другом направлении. Строка (Тип Показателя) ассоциирована с Показателем (максимум с одним), либо не ассоциирована... Строка Типа Показателя связана с максимум одним Показателем... Непонятно. Вот тот же пример взять. Есть два Показателя: "мужчина" и "женщина". Оба они ассоциируются с Типом показателя "род". Что в этом случае есть Строка?.. Строка01 связана с "мужчина", Строка02 связана с "женщина". Получается, что Строка - это интегрированный в Тип Показателя Показатель... Ну вот, начало потихоньку проясняться... И всё равно как-то плохо смотрится, что Показатель может быть сам по себе, без Типа Показателя. И именно поэтому Наблюдение имеет отдельную ассоциацию с Типом Показателя. Кстати, класс Observation, созданный по мотивам Наблюдения, не имеет выделенной связи с Типом Показателя, только через Показатель...
Прямую связь с Типом Показателя имеет Измерение, которое наследует Наблюдение. А на диаграмме это не отмечено. 
Интересно, а если Наблюдение будет иметь связь с Показателем, который имеет связь с Типом Показателя, то нужно будет вводить проверку, чтобы Наблюдение не было связано с другим экземпляром Типа Показателя? Запутанно как...
Удаление класса Измерение требует изменения класса Наблюдение. И в нём добавляется куча контролей, например, с тем же нулевым количеством. Каким же в итоге получится интерфейс этого класса и сколько трудов понадобится для его внутренней реализации? Не нравится мне это.


пятница, 1 апреля 2011 г.

с.164

Новый класс Quantity. Опять самому придумывать?..
-----
Measurement. Метод public String toString().
Переменная _amounts - это на самом деле _amount ?
Экземпляр класса PhenomenonType используется в методе toString(), однако это класс не имеет аналогичного метода, значит выводиться будет чёрт знает что.
-----
Observation. Метод protected void initialize(Patient patient, Date whenObserved).
Это тот же самый конструктор, но без Показателя. Measurement не может использовать настоящий конструктор своего родителя. Как-то это странно выглядит, однако.
-----
NullQuantity - из серии "тоже сам выдумывай"...
И Observation.isMeasurement() тоже.
И Measurement.amount() ...
Я понимаю, что в книге необязательно размещать весь код, но как-то всё равно неприятно.
-----
"Роль от Типа Показателя к Показателю моделируется как некая квалифицированная роль, поскольку это главный интерфейс класса Тип Показателя. Аналогично показана связь Наблюдения с Типом Показателя, поскольку и здесь существует интерфейс, хотя имеется только одно измерение с прямым указателем на Показатель."
Честно говоря, полная белиберда для меня... Не могу отсюда выудить ни одного полезного момента. Попробую подумать очень хорошенько...

вторник, 29 марта 2011 г.

c. 163 Поиск последнего наблюдения показателя


Неужели у меня тоже получится так сложно?..
-----
Patient
public Phenomenon phenomenonOf (PhenomenonType phenomenonType)
По названию метода никак не понятно, что он возвращает последний показатель указанного типа.
---
public Phenomenon phenomenonOf (PhenomenonType phenomenonType).
return ( latestObservation(phenomenonType) == null ? new NullPhenomenon() : latestObservation(phenomenonType).phenomenon() );
Неясно, что такое NullPhenomenon. Как именно этот объект будет использоваться? Почему не возвращается простой null? Это нужно знать, чтобы правильно его написать.
По идее, NullPhenomenon должен наследовать Phenomenon, однако для Phenomenon не определён конструктор Phenomenon(). Соответственно, нет такого конструктора и у NullPhenomenon. И как это должно заработать?

public class NullPhenomenon extends Phenomenon {
    public NullPhenomenon() {
        super (name, type); // Какие значения я должен сюда положить? Особенно интересует type, который не может быть null.
    }
}
-
Два раза вычисляется latestObservation(phenomenonType).
Observation. Метод phenomenon() нужно дописать самому.
---
private Enumeration observationsOf (PhenomenonType value).
Enumeration e = observations();
Метод observations() тоже нужно писать самому. И если это просто _observations.elements(), то зачем отдельный метод?
---
Observation. Метод whenObserved() тоже не описан. Выдавать просто дату?
---
После "парного программирования" с Лёнькой получился такой код:
public Observation getLatestObservation (ResolutionType resolutionType) {
 List resolutionTypeObservations = this.getObservations (resolutionType);
 return resolutionTypeObservations.isEmpty () ? new NullObservation (resolutionType) : Collections.max (resolutionTypeObservations); 
    }
    
      private List getObservations (ResolutionType resolutionType) {
 List resolutionTypeObservations = new ArrayList();
 for (Observation observation : this.history) {
     if (observation.getResolutionTypeName().equals(resolutionType.getName())) {
  resolutionTypeObservations.add(observation);
     }
 }
 return resolutionTypeObservations;
    }

понедельник, 28 марта 2011 г.

с. 162 Создание наблюдения


Для того, чтобы заработал это код, пришлось написать несколько методов. Надеюсь, их интерфейс я понял и реализовал правильно. Посмотрим, что будет дальше.
А мой код для создания наблюдения получился таким:
ResolutionType sex = new ResolutionType("gender");
 String[] sexes = {"male", "female"};
 sex.addNewResolutionValues (sexes);
 Patient patient = new Patient("Adams");
 Calendar dateAndTime = Calendar.getInstance();
 dateAndTime.set(96, 3, 1);
 Observation observation = 
  new Resolution (sex.getResolutionValue ("male"), dateAndTime);
 patient.addObservation(observation);

Страничка закончилась. Код пока не работает. С интересом перехожу на следующую...

понедельник, 14 марта 2011 г.

с. 161 Создание типа показателя "gender"


Так как класс QuantityRange до сих пор не создан, выполнение кода завершается с ошибкой "Unresolved compilation problem: QuantityRange cannot be resolved to a type". Для того, чтобы всё-таки проверить код, создаю пустышку.
Кроме этого, создал класс BigStore, который реализует интерфейс с persist() и get(). Потом посмотрим, правильно ли я интерпретировал текст.
-----
Как лихо Фаулер завернул, однако. Создал тип показателя "пол", для которого не предусмотрена количественная характеристика. А ведь на с.154 сам ввёл в рассмотрение класс Количественный Диапазон, что и отражено в диаграмме на с. 156. А сейчас у него получились показатели без диапазонов. Интересно, как он будет создавать показатели с диапазонами, если у него никак пока не прописано их использование.
И что же мне делать? Для типа показателя "пол" нужно создавать особый как бы диапазон, в котором будет только имя и никаких границ. Но какой тогда это диапазон? Просто какой-то подтип типа показателя: "пол.мужской", "пол.женский"... А какую единицу измерения использовать? Выходит, тип показателя может быть без единицы измерения. Но тогда такой тип показателя нельзя использовать в веточке для измерений. И что же? Две группы типов показателей формировать из-за этого, вводить дополнительные условия? Нут уж, некрасиво это.
-----
В связи со всем этим, пришлось переделать диаграмму. И получилось вот что...


А теперь непосредственно код.

"интерфейс" Наблюдение

package main.alexded;

import java.util.Calendar;

public interface Observation {

/** Результат наблюдения */
String getResult();

/** Название типа показателя */
String getResolutionTypeName();

/** Момент времени наблюдения */
Calendar getDateAndTime();

}


Показатель package main.alexded; import java.util.Calendar; /** Показатель */ public class Resolution implements Observation { @SuppressWarnings("unused") private Resolution() { } public Resolution ( ResolutionValue inputValue, Calendar inputDateAndTime) { this.value = inputValue; this.dateAndTime = inputDateAndTime; } public Calendar getDateAndTime() { return this.dateAndTime; } public String getResolutionTypeName() { return this.value.getResolutionTypeName(); } public String getResult () { return this.value.getResolutionName(); } private ResolutionValue value; /** Момент времени наблюдения */ private Calendar dateAndTime; }
Значение package main.alexded; public class ResolutionValue { private ResolutionType resolutionType; private String name; /** Значение показателя */ public ResolutionValue ( String inputName, ResolutionType inputResolutionType) { this.name = inputName; this.resolutionType = inputResolutionType; this.resolutionType.addResolutionValue(this); } /** Блокировка конструктора */ @SuppressWarnings("unused") private ResolutionValue () {} /** Название показателя */ public String getResolutionName () { return this.name; } public String getResolutionTypeName() { return this.resolutionType.getName(); } }
Тип показателя package main.alexded; import java.util.ArrayList; /** Неколичественный тип показателя */ public class ResolutionType { /** Название типа показателя */ private String name; /** Диапазоны показателей */ private ArrayList resolutionValues = new ArrayList(); @SuppressWarnings("unused") private ResolutionType() {} public ResolutionType(String inputName) { this.name = inputName; } public void addResolutionValue (ResolutionValue inputResolutionValue) { this.resolutionValues.add (inputResolutionValue); } public void addNewResolutionValue (String resolutionValueName) { new ResolutionValue (resolutionValueName, this); } public void addNewResolutionValues (String[] resolutionValuesNames) { for (int i = 0; i < resolutionValuesNames.length; i++) { this.addNewResolutionValue(resolutionValuesNames[i]); } } public String getName() { return this.name; } }
Диапазон package main.alexded; /** Диапазон показателя */ public class ResolutionRange extends ResolutionValue { /** Верхняя граница диапазона */ private int maxValue; /** Нижняя граница диапазона */ private int minValue; public ResolutionRange ( String inputName, int inputMinValue, int inputMaxValue, QuantitativeResolutionType inputResolutionType) { super(inputName, inputResolutionType); this.minValue = inputMinValue; this.maxValue = inputMaxValue; } }
Количественный тип показателя package main.alexded; /** Количественный тип показателя */ public class QuantitativeResolutionType extends ResolutionType { private Unit unit; public QuantitativeResolutionType (String typeName, Unit typeUnit ) { super(typeName); this.unit = typeUnit; } public String getResolutionRangeName (Integer resolutionResult) { return null; } public void addResolutionRange (ResolutionRange inputResolutionRange) { if (validateResolutionRange (inputResolutionRange)) { super.addResolutionValue(inputResolutionRange); } else { throw new IllegalArgumentException("Not valid Resolution Range"); } } private boolean validateResolutionRange(ResolutionRange inputResolutionRange) { /* TODO : Проверить, может ли вписаться данный диапазон в коллекцию уже существующих. Можно, конечно, предстваить себе ситуацию, когда один диапазон охватывае несколько других, но такие обощения пока оставим на потом */ return true; } }