Posts Tagged 'Practice'

F*: Let’s Swing the Undo Functionality

I have implemented the undo functionality for XML support in ee-xml and I am doing the same for the text editor.

Undo is a little bit interesting in application development, and it’s a good case study for F* development: in F*, we try to keep ‘features’ separate and self-contained.

An undo manager needs to coordinate actions triggered by several, separate features – by ‘features’, I mean ‘value increments’ and by ‘separate’, I mean, bundled in separate package, and written in such a way that deleting a feature package will remove a feature completely without otherwise threatening the integrity of an application.

Generic Undo Functionality

When I wrote the {undo} feature for XML, I see in retrospect that I planned on sharing code. This uses the following classes.

  • UndoSetup. This is a feature setup class and is typical of F*. In this case, UndoSetup adds a couple of menu items in each new application frame (as an AppFrameCreated.Listener), and registers a listener on a Keyboard class.
  • History. This manages a list of undo actions and provides the undo/redo actions. More interestingly, this implements ModelAction.Listener, which allows it accumulate UndoableAction items
  • Undo, Redo and HistoryKeyHandler. These are just UI event handlers allowing the user to invoke History methods.
  • All classes are bundled in the same package (except Keyboard, which belongs to an amorphous utilities package). notification interfaces are all bundled in an event package as notifications are normally made available to all actors in the system.

Undoing XML actions

All XML edits are created as UndoableAction instances, then applied, then a notification is generated via ModelAction. I packaged XML actions separately, which may be OK (several features may need to use the same actions). Where I’m less convinced is that these actions are really provided only so that they can be undoed, and the packaging doesn’t really reflect that. Here, following feature and value driven separation, I have two problems:

  1. The {undo} feature is generic. It doesn’t do anything and is meant to be shared by actual features (ie, undoing XML actions, text actions, image edits… ). Eventually I’ll want to resolve this. generic {undo} is a framework feature targetting developers, not an application feature targetting end users.
  2. The undo functionality for XML (the actual value increment) is not represented anywhere. XML-actions was designed as a utilities package. As such it is ill formed, because it generates application level notifications. In the meantime, it is really the basic xml edit feature, {xml-edit}, that supports the undo functionality by relying on XML actions and notifying ModelAction.

Undoing text actions

My first reflex was to hook a (swing) DocumentListener onto my text components to generate UndoableAction instances from DocumentEvent. However, the structure of document events in swing is somehow intimidating. I didn’t intend to spend so much time on this, and I spotted nearly simultaneously that I could register an UndoableEditListener.

Behind UndoableEditListener, there is a structure very similar to what I originally designed – but provided at API level, and slightly more complex. From UndoableEditListener, we get swing UndoableEdits intended to be operated upon by an UndoManager. As I already have my own undo manager (the History class) I wrap the UndoableEdits using an adapter class. I then notify my edits using the ModelAction dispatcher.

This works (almost) like a charm, especially considering that (unlike with XML, where I actually had to painstakingly define each action and it’s undoing) we don’t need to distinguish between edit types. Leaving a couple of open questions…

  • Using an adapter worked fine to the extent that swing’s UndoableEdit and my UndoableAction share core functionality. However, the swing interface provides a die() method used to release resources (if any). In order to ensure that die() is invoked, I had to provide a secondary interface and do some typecasting from History. Obviously I had no intention to grow my existing UndoableAction interface. But then I still find myself with an additional interface (in this case, just a resource release interface, Heavy). Frustrating…
  • When undoing text actions, we don’t generally expect or want to undo input character by character. UndoableEdit distinguishes between significant and non significant edits (and I’d rather if special symbol inputs/deletions counted as significant versus alphanumerical input) but… …whatever implementation is underlying the edits fired by swing’s PlainDocument is a quick affair that doesn’t distinguish between significant and non significant edits. Pity considering I actually spent the time to fit an edit accumulator in my implementation, based on the significant/non significant distinction…

Conclusion

Writing this article and implementing the undo functionality for text took 110 minutes.

Overall, I somehow prefer the implementation of undo for text. Unlike what I did for XML, the feature is completely self contained and advertises itself as such.

It may seem that not having undo for XML actions defined as an actual feature makes no difference. I think it makes a huge difference: I could get rid of undo for text by deleting the package and crossing one line in the features registry. In contrast, removing undo functionality for XML would require updating several classes within the {xml-edit} feature.

More importantly, undo functionality for text is easier to upgrade than it’s XML counterpart.

Source?

Well… you might as well ask, or maybe I’ll link bits and pieces later on (mind, the java tutorial does have an article about this).

Programming Using State Transitions

Actions Pass, State Remains

Many widely used languages today are imperative. Essentially, most code written using those languages can be reduced to statements, such as:

System.out.println("Hello World");

I had the idea of programming using state transitions while trying to find reasonable ways to formally encourage writing simple, readable code. There are two drawbacks of classic imperative programming that pointedly led me to state transitions:

  • Complex control structures – imperative programming often results in lengthy method bodies – so called ‘bulleted functions’ that could not exist without a complex control structure (I’ll write about this sometimes)
  • Sequential ordering – this allows programmers to write APIs in such a way that using them requires invoking several functions in a predefined order.
  • No matter how convoluted imperative programming can get, actions within a program ultimately aim at modifying runtime or persistent state.

Could modeling and programming using state transitions help increase the clarity and readability of code? This is the question I tried to answer. I’m now looking at typical function types, and what a state oriented perspective tells us about them:

Constructors

Constructors are used to setup the original state of an object. Ideally, the original state of an object can be easily specified using a hierarchy of elements – however, using imperative languages, we often need replacing this by lists of statements like:

ChildType x=new ChildType();
parentObject.addSomething(x);

Actions

An action is a function that modifies the runtime or persistent state of a system. In object oriented programming, an action executes from a locale and modifies state that is reasonably easy to reach from such locale. Often, the crux of any action is to prepare and execute a statement that will add, remove, set or clear a property related to the locale.
Invoking an action allows us to export state to a remote locale.

Queries

A query is a function which, ideally, modifies no state and is merely used to collect information from a given locale. Invoking a query allows us to import state from a remote locale.

Can I use this to improve code readability and simplicity?

Alas, how oft have I started writing a function with clear, straightforward intentions and eventually produced monsters that only the sleep of reason could emulate?

  • Functions that dilute their original purpose in scores of preparation statements.
  • Functions that modify program state in too many ways, with no clear view of where (within the function body) the states are affected.
  • ‘Hidden’ actions modifying the state of my program while advertising query semantics.

As a rule of the thumb, if I can’t concurrently visualise the name of a function and the statement that realises its purpose, I feel something is wrong. Proposed remedies:

  • After writing a function, immediately reconsider its implementation and sprout methods for complex preparation code. It is usually handy to add preparation code wherever needed while writing code, however this eventually makes implementations impossible to read (I wouldn’t sprout methods until after writing the code, because preparation code often needs researching, which requires a different kind of concentration).
  • Avoid functions that concurrently return and modify state – with some exceptions: factory methods are usually fine; returning metadata (succes/failure flags) is sometimes okay (granted many of us think exception handling’s just better).

Even small functions can become fairly confusing because the preparation steps required to realise a state transition typically precede the statement realising the transition. The typical remedy is to bundle preparation code into separate methods. This allows shifting the emphasis back to the target statement while leaving granular details ‘for further reading’.

Pushing state orientation into language design

Recently, I’ve been trying to design a language to better support state orientation. Read on.



Follow

Get every new post delivered to your Inbox.