“Once you know the name of a thing, you have power over it.”

 Ursula K. Le Guin

The fourth principle of the FLUID methodology is intuitive interface: components should allow all reasonably expected interactions without unexpected behaviours.

In computer science, the concept of interface has multiple meanings. The overwhelming diffusion of Object Oriented Programming has solidified one of its interpretations: that of the list of operations that can be applied on an object  often to be publicly advertised as a set of well known functionalities, published as a formal contract.

In this article, I continue to refer to the more generic concept of component over the OOP class: any element of a system which is given the purpose of performing a specific task, be it a module, a microservice, a class, a library or a set of correlated functions.

In general,

The interface is the boundary of an independent system, defined by the set of effects happening in response to a defined set of external or internal events.

The systems (functions, classes, applications, services etc.) are interesting because they do something when something happens to them. The interface is the clear definition of what can happen to them and what they do.

Given this broad definition, an interface is intuitive when the relationship between events (inputs, commands, methods, parameters, exceptions, internal state transitions etc.) and the effects (outputs, logs, error messages, status changes, etc.) are the least surprising.

The concept of “least surprising” can be seen through multiple lenses:

  • Mapping to Reality: FLUID entities will be coded analogs for real-world entities; mostly, they will follow the business logic, but where that concept doesn’t apply (i.e. because they aren’t meant to be part of a codified business logic procedure) they will still resemble some real-world, easily identifiable reality.
  • Explicit and Meaningful: FLUID entities will do what they say. They will have simple names and bound to perform simple tasks.
  • Cognitively Minimal: FLUID entities should require minimal understanding of their internals when being used. The interface should describe explicitly which operations are performed by each call, and how each parameter influences it.

Ideally, a FLUID code base should be “least surprising” across all those dimensions.

Least Surprising as Mapping to Reality

Entities in a FLUID components should be recognisable, so that they make sense intuitively for anyone coming in touch with the project. To achieve that, the project can focus on matching real-world data and/or processes determining the real world use case (usually, the business logic):

  • Following the Data: the entities in the application abstract real-world entities present in the business logic: customers, documents, invoices, inventory items, physical message boards and so on.
  • Following the Processes: the entities in the application are modelled after the actual processes comprising the business logic: order dispatch, warehouse loading, on-site client servicing, phone order evasions and so on.

The technology selected for the application development shouldn’t dicate which approach to prefer:

  • even in OOP, a process can be modelled classes. For example, a WarehouseLoading class could abstract the operation of loading some items in the warehouse, where each instance represents a single loading activity.
  • Similarly, even in a functional language it’s possible to abstract physical entities as data types. For example, WarehouseItem type can become a monadic type flowing through a set of load and unload operations.

Conversely, choosing which mapping style to adopt (or mix of them) should be driven solely by how well the mapping allows to model the underlying business problem. The simpler, more direct and thus more intuitive the mapping, the better.

Least Surprising as Explicit and Meaningful

Naming is defining: Once you know the name of a thing, you have power over it.

Starting from understanding how the FLUID component maps to reality, its parts should be broken down in sub-components that are easily named either for their significance as data or as processes.

Any entity in a FLUID component should have the shortest and most specific name possible. If the name doesn’t describe what the entity is or does exhaustively, that probably means it should be split into more specific elements.

Choosing the appropriate name for an entity is more an art than a science, but while this stays true, there is a simple, almost socratic technique that can help us determining if we have reached an adequate level of detail in naming an entity:

A name for a FLUID entity is “least surprising” when no other name could describe the same entity, or part of it, just as well.

Suppose a project has an entity named DataManager. The name is quite generic; is that the best name for the entity?

Suppose also that the data handled by the entity comprises customers, orders and invoices; also, no other data is managed by the application.

In this scenario, it would be impossible to find a better, more descriptive and simple name: DataManager is the manager for all the data the application is meant to manage.

A more specific name would require to break the entity down. That may give origin to three entities: OrderManager, CustomerManager and InvoiceManager.

There are other software engineering philosophies that would suggest to do that: breaking an entity down to a point where only it takes care only of a very limited aspect of the application (single concern). FLUID recommends the same; however, the definition of “limited aspect” is& FLUID.

In the specific context of your application, is the name DataManager enough to clearly describe what that entity is meant to do?  if that is so, then it’s the perfect name, and the entity named by it it’s the perfect size to handle your problem. If more specific names as i.e. OrderManager may better encapsulate and address the specificities of handling orders differently from Customers in your application, then that should be the naming (and the scope of the concern) the application should follow.

Least Surprising as Cognitively Minimal

One of the golden engineering rules followed by FLUID is: Keep it simple. A FLUID component is cognitively minimal if it all aspects of it can easily be understood: to know how to use it to achieve some desired results.

While writing a component that feels natural is, again, more an art than a science, the following guidelines are markers cognitively minimal components:

  • Minimal Configuration/Parameters: try and keep the parameters and/or the configuration required to make a component ready to usage to a minimum.
  • Intuitive Defaults: when more options are required, be sure to cover most of them with intuitive and solid defaults, so that users are not forced to know all the possible usage of a component before employing them in their simplest form.
  • Automatic Configuration: try and determine automatically as many options as possible. For example, use system temporary directories rather than require the user to select a work environment, set the default parallel agent count to a number near the available cores, configure garbage collector thresholds to sensible portions of available memory and so on.
  • Clear and Unambiguous Outputs: simple enumerations, error codes, clear descriptions are better than combinations of statuses stored in different outputs, and then must be interpreted to understand what actually happened. Error codes stored in specific exceptions are better than vague, all-catching exceptions.

Conclusions

Like all methodologies, FLUID requires discipline. A clear understanding of the interface concept, and of how to make them intuitive is crucial to a well designed FLUID application.

Interfaces are the boundaries between components, and they are intuitive when they respect the principle of least surprise across the three dimensions of mapping to reality, being explicit and meaningful and cognitively minimal.

A well-designed FLUID component presents interface that represents the reality it abstracts well, does so explicitly and has minimal requirements for its immediate usage.