fxtivity
The Effectivity pattern on JavaFX: things in effect for a period, values that change over time, and observable collections that all follow one application-wide effective date.
Why
Most data that matters changes over time. People change jobs and names, companies are renamed, a post is held by one person and then another. Keeping only the current state throws away the history, and with it the ability to answer what was true on this date? — often the question that matters most.
Fowler's pattern gives each object a period during which it is in effect, and filters by date. Its cost, as he says himself, is that every query wanting current information has to remember to check the period.
On JavaFX that cost all but disappears. A user interface is always showing the world as it was on some date, so make that date one observable value and have every effective collection filter itself against it. Moving the date is then a single call, and every table, tree and chart bound to those collections updates on its own:
MultiEffectiveList<Employment> employments = new MultiEffectiveList<>(); employments.add(new Employment(indiaInc, LocalDate.of(1999, 12, 1), LocalDate.of(2000, 5, 1))); employments.add(new Employment(peninsulaInc, LocalDate.of(2000, 4, 1))); table.setItems(employments.effective()); Effectivity.forDate(LocalDate.of(2000, 4, 15)); // the table shows both Effectivity.forDate(LocalDate.of(2000, 6, 1)); // the table shows Peninsula Inc alone
Nothing there tells the table the date moved. It finds out because the list does. And there is exactly one effective date per application — two collections disagreeing about what “now” means would be a defect, not a feature.
Have a look
The specification
Scenarios built on Fowler's own example — people, companies and the employments between them — and extended with what his pattern leaves to others: a name that changes over time, an office with one holder at a time, a board whose seats each have their own history, and departments related to people at both ends. Each scenario comes with a picture of how its periods line up, before its action and after, under its After hook.
Read the scenarios →The worked example
The model the scenarios run against: a person whose employments overlap and whose name changes, and a company with a succession of chief executives, a board, and departments that manage people and have them assigned. Small enough to read in one sitting, and every class implements the pattern the way a consumer would.
Explore the model →Using it
<dependency>
<groupId>io.github.ctgnz</groupId>
<artifactId>fxtivity</artifactId>
<version>1.0.0</version>
</dependency>
Implement Effective — a start, an end, and their setters — and the rest follows.
Periods are closed-open: in effect from the first day up to but not including the last, so one period hands over to
the next on the same date with no overlap and no gap.
Pick the collection by how many things can be in effect at once. MultiEffectiveList for any number,
like a person's employments. SingleEffectiveList for one at a time, like a company's chief executive.
EffectiveMap for one at a time per key, like the seats on a board. And EffectiveProperty
for a value that changes during its owner's lifetime, like a person's name.