Websites don't in general start as technical projects but as stories; descriptions, sometimes accompanied by pictures, of what the site should do. Stories are written by domain experts, not programmers. These are the customers who commission us to meet their real-world needs by constructing a new website, and success depends on how well we match our solutions to the expectations expressed in their stories.
To explain this I have an example called Here On The Map, which you can see working at https://hereonthemap.com. It's a demo website built to illustrate some specific technical features rather than meet any particular need. In design terms it's simple; what matters most is its functionality and the stories that describe it.
Here On The Map (HOTM) has quite a simple user story, which goes something like this. We have a live map on which there are colored pins. The user can zoom and pan to reveal any part of the Earth's surface, and when they click a pin a panel appears containing information about the location of that pin. Users can register with the site; they are then able to add their own pins and write about them using a rich text editor. Images can be accessed by URL or uploaded to the system using the file manager provided. Here's what it looks like when viewing:
and while editing:
The above is just one of several stories that together constitute a full specification of the website's functionality from the point of view of its users. Most projects start with a similar outline description; a 'project brief' that can be taken to an engineering team to implement. But before we jump into the coding, here are some general issues.
To start with, the platform used here is WordPress. Why? Because it's the simplest way to get basic functionality in place, on top of which we can build our website. A load of useful functionality is provided, that we can use or ignore as we please. The theme is fairly irrelevant; I chose one called No Header, a very basic theme that provides little more than a sidebar leaving two-thirds of the screen for my own content. It also provides some responsiveness for mobile compatibility by adjusting font sizes and moving the sidebar. The HOTM application knows nothing about the theme and in fact doesn't interact with WordPress at all.
The website is front-end driven. This is partly preference and partly practical. It's not impossible to deliver a similar site with traditional server-side code, but good responsiveness to user actions would be harder to achieve. Furthermore, the visual structure is pretty basic so it's quite feasible - maybe even preferable - to implement it entirely in browser code. There's a rather fuzzy line between a web page and a browser application; the former suggests more emphasis on content and the latter on function. Here we're rather leaning towards a browser application.
One thing that stands out when looking at the website is the way it's made up of functional blocks. Quite big ones, in fact. In particular:
• A Google Map
• A user registration/login module
• A Rich Text editor component
• Picture upload and storage
The usability of the website is crucially dependent upon the ways these blocks interact with each other, but it's hard to predict all of the details without first building an outline prototype of the site. Once it's running, the nature of some of the interactions will become clearer. There's a Catch-22 here, that without knowing all the interactions it's hard to set up a framework to encompass them all, but until it's built you won't know what all the interactions might be, and you might need to go back to square 1 again. The solution - and the whole point of this article, as you'll see - is in the use of APIs (Application Programming Interfaces) to separate stories from components.
Here are some of the interactions, i.e. the Business Logic:
"When you click a pin you see the corresponding article. You also get a link to the author and a list of tags. When any of these are clicked, the map updates to show only the pins matching what was selected."
"A line of text appears under the map to tell you what filter you currently have in place."
"As you zoom the map the current zoom level is shown at the end of a line of text below the map."
"When you log out by clicking the link in the line under the map, the viewer or editor panels disappear, just in case you were viewing something that should only be seen by registered users."
"If you are viewing a pin you created yourself it will be colored green. When you log out it goes yellow."
There are also various rules, such as what state information gets persisted as the application runs. We preserve the current latitude, longitude and zoom, also the name of the pin we're viewing. In the File Manager we hold onto the directory path so the user can return there next time. And so on.
These interactions and rules together form stories that belong to the domain expert. They tend to be rather fluid and subject to unpredictable change at short notice as a result of factors such as responding to competition, the introduction of new product types or the need to meet changing regulations.
Stories rarely get into the details of how a component works, only of how it interacts with other components. They should be expressed in such a way as to ensure quick understanding by both domain experts and programmers and kept where they can easily be accessed to make changes, not buried in arcane code. Ideally they should coded so as to bear at least a passing resemblance to the original project proposals or the discussions that lead up to a change request. Think long-term and think of the site maintainer, who will often be someone other than the original site builder.
There are two different kinds of programming going on here. Components are highly optimised, contained functionality with well-known, unchanging interfaces, but stories are random "glue" logic that expresses frequently-changing relationships between components. A component can be as complex as you like because few are ever going to see inside it, but a story should strive for clarity at all costs. These two aims are directly contradictory when applied to the same entity but not if the entities themselves are separated.
From the above we can see a structure begin to emerge, one of functional components joined together by stories. If we can find a way to manage these two things independently the website will be much easier to work with than if we jumble everything up together. With interactive websites, maintenance is a serious issue. If the stories are not easy to find in the code, a future maintainer will have trouble understanding what should be happening and is likely to break things.
The rest of the components might be provided as standard libraries, WordPress plugins, one-off code specifically written for this project or some combination of code and library. Whichever is the case, we should design our application to use components in a clean and consistent manner.
That just leaves the stories. As I've already explained, these should remain visible in a form that's as close to the original as it's possible to get, and a good precedent for this exists in the form of SQL. Database applications may do all sorts of things with data, whether transforming it for display or using it to control layout, but the actual process of extracting it from a database is done in a way that is readily understood by database domain experts as well as by programmers. Can we express our stories in a similar way?
When we come across an unfamiliar entity in daily life, rather than spell it out longwindedly every time we encounter it we give it a name such as a Gazebo or a Defibrillator. Or, to return to the context of HOTM, a Map and an RTF Editor. We don't concern ourselves with how the item works, only with what it does, that is, the interfaces it presents to us. This works in the computer world too. You can draw a map with just 3 items of information, by saying
"draw a map in the box, with latitude 45.234, longitude 5.82 and zoom 5.5"
The one and only absolute requirement for a viable computer language is that it must be unambiguous, so the instruction above qualifies as a valid computer language statement while remaining perfectly readable English.
None of this is visible to the people implementing the stories. All they see is a syntax that lets them express all the features they want to use and that provides access to the APIs of the major components.
By layering our application in this way we can maintain high readability, which gives us some confidence that future modifications can be made quickly and safely by whoever is available to do the work.
Here On The Map was built to demonstrate the principles outlined above. It's written entirely in high-level script, using a syntax derived from English and a vocabulary that encompasses all the concepts and activities required. The compiler and runtime package are a WordPress plugin called EasyCoder (https://easycoder.software) that's available from the WordPress plugin library. To illustrate the general flavor, here's a simple fragment from a user story:
"When given the id of a particular pin record in the database, read the record, set up the map and display the article for that pin"
and here's the corresponding section of EasyCoder script:
rest get Record from `_/ec_markers/id/` cat RequestedID or begin print `Failed to load the requested pin. Error: ` cat the error stop end if property `id` of Record is not 0 begin set the latitude of Map to property `latitude` of Record set the longitude of Map to property `longitude` of Record set the zoom of Map to property `zoom` of Record update Map fork to ShowStory end
As you can see, there is no computer code to learn since everything is expressed in English words. Admittedly, the syntax is a bit clunky, but it's still understandable. Names of things are camel-cased while language commands remain in all lower case.
The first command requests a record from the database by calling a REST server. There's a basic one included with the plugin and it has an extension facility to enable the provision of the extra code needed to handle the specific commands associated with maps. In the event of an error a report is logged but nothing else happens and the screen remains unchanged.
Assuming a valid record came back it will have a non-zero id, so we can extract the 3 map parameters and update the map. Here we're using the Google Maps module, wrapped in simple commands that let us access its API without worrying about the details.
A website can be built very quickly using EasyCoder, partly owing to the way each command does a lot of work and partly because the scripts express concepts that directly map to what you see on the screen, but also because so much of the usual infrastructure needed by websites is already provided. The bulk of HOTM took less than 2 weeks from an initial idea to a fully working website. Errors are rare because the internal functions are used over and over again, leaving bugs with few places to hide. However, it has to be acknowledged that this is a fairly small website using readily available technologies, so what if you need to build some really complex functionality?
A key feature of React is that it's a component technology. This works well in the environment described here, where major units of functionality are built as components and joined together by the random glue of stories. Anything with a well-defined API can be a component, including complex visual elements built using a modern framework.
Remember at all times that what we're doing is creating a top-level syntax that's readily understandable by English speakers who are also domain experts. The complexity needed to implement this syntax is handled by the programmer, who is then free to pick the best tools for the job. If you wish, you can construct a language that has just one word; "doit", everything else being hidden inside that one command. That's how websites are in effect built today, but I don't advocate doing it that way. We can do better.
To a certain extent, adopting this strategy tends to focus the mind on building better reusable components. When you build a component alongside the code that uses it there's a tendency for ad-hoc interfaces to be added to solve short-term needs, making it progressively more difficult for the component to be used outside of the context for which it was originally built. The discipline of having to build the component in such a way that it can be accessed solely through published interfaces forces a reappraisal of just what the component is offering to the world, and in the process makes it a better component. And better components lead to better, more reliable and less costly websites.