The Object Network

NetObject Programming and Architecture

Programming and distributing with state dependencies

Say you want to model a system with a payment object that depends on an object representing an itemised order being fulfilled.

You may want to set up dependencies between the states of such objects: the payment should perhaps update to reflect any changes in what is to be delivered. A collection of payments could be aggregated into a line-by-line report summary.

Take, for example, the payment and the fulfilment ticket: they have a current state - the payment has a state of "total to pay" and the ticket may have "description", "quantity", "price", etc. Say we want the payment to depend on the ticket.

It's possible to let the payment object itself determine how its state depends on the fulfilment ticket, without centralised, monolithic, imperative coding.

That's how the Object Network works, modelling the world using "NetObjects". NetObjects allow you to write software to model such direct, peer-to-peer interactions very naturally. NetObjects represent an easy and powerful programming model.

NetObjects for state dependencies

NetObjects are persisted objects that are essentially lists of properties such as order descriptions and prices. They can be rendered to JSON-like text and are found on URL-like identifiers or links, which can be used to link up to other local and remote peer NetObjects.

They can then observe each other's state and be notified of changes to their state. These interactions can occur over local or wide networks. They use a single, end-to-end, peer-to-peer protocol (which may be run over HTTP) that can work across the internet, linking up different players, sites and collaborators.

NetObjects make it easy to program the data transfers and update notifications in your distributed systems. Updates to NetObject properties are notified to other NetObject listeners via a local or remote peer network, around and between sites. NetObjects can be used to create a single, shared space of updating data. They allow you to build a simple distributed system comprising clients and servers communicating state changes over the 'net.

NetObjects can see each other's properties or current state through their links, whether they're local or remote, making it easy to program dynamic mutual dependencies between data that can be held in the same process or across the planet.

How NetObjects model your domain

Each type of object (fulfilment ticket, payment) can have its own NetObject representing its current state in the form of a persisted bundle of properties with current values (such as "price: 3.52"). If anything changes its state - e.g. a price or amount updates - then its corresponding NetObject's state can update to reflect that new property value.

Now, obviously the payment NetObject needs to know about the ticket, in order to depend on it.

NetObjects have unique identifiers to locate them by called UIDs. UIDs can be formed into network identifiers which are like Web URLs: short strings that you can use to view content from the net - domain state or property data in our case.

Again, just like on the Web, content can itself contain more links, more UIDs. Our NetObjects can contain the UIDs of their peers.

So we just need a link within the payment's NetObject pointing to the UID of the ticket's NetObject in order for it to have a handle on the ticket so it can depend on it.

Now, if a NetObject is watching or observing the state of another NetObject, via its link UID, then it gets notified of the updating property values of that observed peer. This link-observe-update-notify mechanism is built in to NetObjects.

So the payment may be observing the linked ticket and will be notified as the ticket changes state in its items, prices, etc. Then the payment can itself change state (update the cost to charge) in reaction to that.

Further, anything watching the payment's state, such as that line-by-line statement, can update its own state in turn.

Here's what that looks like in a picture:

Notice how the payment observes the ticket state through asking for the value of 'ticket:price' - which jumps through the link to the ticket and attempts to access the ticket's 'price' property. This kicks off the observation of the whole ticket NetObject state.

The simple path "ticket:price" encapsulates everything that is interesting and useful about how NetObjects work:

The "ticket" property of the payment is a link to the ticket NetObject. That NetObject has a "price" property. By asking for "ticket:price", you're jumping 'over' that link and trying to see the "price" property, but if you don't have a local copy, this won't be possible and will return null.

But simply asking for this also sets up an observation of the remote NetObject, so when that state is available - once the remote NetObject is cached in locally - its "price" property can be read. And if the ticket NetObject updates, the payment NetObject is notified and can respond accordingly.

Here's more on the data format and on the protocol.

NetObjects and other approaches

This may all seem so incredibly obvious that you'd wonder why no-one else does things this way! But NetObjects are completely unique.

This simple modelling and interaction approach differs from existing approaches using messages or events, which have to be laboriously marshalled around using a low-level interface, or remote function calls within imperative client and server programs.

NetObjects give you a higher level perspective - of the current and updating state of local and remote data. The underlying NetObject protocol deals with proxy-cacheing of NetObjects (probably using HTTP caching) and cache updates (then not using HTTP in the traditional way).

A NetObject representing a domain object simply watches its peer NetObjects - whether in the same process or even right across the planet - and is notified of changes in those peers' states. Instead of a network passing around messages or commands or function calls, you get a network of local or intermediary caches of NetObjects' state being updated following observation requests.

Essentially, NetObjects create a single, shared space of updating, interdependent data linked across and within hosts.

NetObjects and Microservices, REST, CQRS, P2P, ICN, Reactive and Functional styles

The NetObject approach is clearly resonant with the popular Microservice architectural style, being fundamentally peer-to-peer, where clients hosting observing NetObjects can also act as servers and vice-versa. NetObjects can be easily migrated between services, and groups of NetObjects partitioned and recombined. An extreme Microservice would host a single NetObject.

Obviously NetObjects on UIDs map directly onto REST's resources on URLs, including hypermedia through ther interlinks. REST would use JSON and HTTP, where we may use the simpler 'ONF' over UDP or WebSocket connections. REST isn't supposed to allow pub-sub or the observer pattern, partly because of HTTP's design, although the CoAP protocol supports that.

NetObjects are also used in a similar way to the CQRS pattern: in order to achieve a command or a request, you have to create a NetObject to represent it, which is similar to the write side of CQRS. Then the read-side NetObjects depend on that command or request. You could even change the request (e.g. update an order) and see the corresponding update on the dependent read-side NetObjects (e.g. the fulfilment ticket updating).

Peer-to-Peer architectures have come and gone, but remain a visionary dream of the decentralisation movement. NetObjects are inherently P2P and decentralised.

Information-Centric Networking is a current research topic, with the goal of replacing IP with content chunks, low-level message or event-based networking with retrieval of data by id. NetObjects are exactly in that space.

Another popular architectural style is Reactive programming, and NetObjects are clearly right in that space, with their state updating in sync with the changing state of peer NetObjects. The difference is that NetObjects are chunkier - being whole objects with UIDs - and also that the dependency function can be more complex.

Finally, Functional Programming is becoming more mainstream, and NetObjects are perfect for that style. The next state of a NetObject can be a pure function of its current state including the state of peers visible through links.

NetObjects and the browser user

Users are represented by NetObjects, animated within their browser. This object links to and observes whatever the user wants to view - it links-in to part of the global network of NetObjects, showing not only the NetObject directly linked to, but potentially one or more levels down from that as nested sub-items or sub-panels. (It could even link directly to another user NetObject, to see what they're looking at - with permission of course!)

For example, if the user linked to the itemised payment statement list, each item could link to the respective payment object, visible when opening up the entry with a '+' symbol, perhaps. Then inside the payment would be a link to the fulfilment ticket being payed for, then perhaps another link to an original order NetObject.

Using this approach, interactive and dynamic pages could be created using just NetObject state or declarations. A generic Javascript script could assemble pages client-side from linked NetObjects, so you could build applications without custom Javascript coding. Obviously pages built as views over nested NetObjects will update in sync with the NetObjects in view. This could use Ajax, WebSockets or whatever.

A page could be rendered server-side as a relatively static, initial view into the NetObject mesh, then animated client-side once the user object has linked to and observed the objects shown. The same render Javascript could be used on both sides.

Mobile

There is a long-running debate in mobile around whether native or browser-based apps are better, or some hybrid technology in between. NetObjects solves this issue very neatly by bringing the two sides together without being an awkward hybrid.

A NetObject operating system such as Onex is really like a web browser in that it is generic, yet much closer to native, as the NetObjects being rendered are more abstract and interactive data rather than the lower level text and layout information of the web.

Internet of Things

NetObjects map neatly to the Things of the IoT. There's a separate article that looks similar to this one, on the NetObject approach to the IoT.

Augmented Reality and Virtual Reality/Worlds

NetObjects create a global landscape of linked up interactive data, including users. Which is actually an immersive cyberspace. Indeed, NetObjects are a great way to blend the IoT with AR and Virtual Worlds.

Why the NetObject model is good for your next distributed system

Working with the model of 'NetObjects observing linked NetObjects' means you don't have to think about or manage all of the low-level, piecemeal network activities at all. There's no need to think about messages or events coming and going and then working out the current state of your data by yourself, or scripting everything and trying to keep track manually.

You just think in terms of the current state of all the NetObjects as if they're all local (even though they may be in another country) and how they update when peer NetObject state changes.

This is a much higher-level model that lets you view your and other's state and set your own state for others to then themselves view. NetObjects make sure you're told when data changes, and your changes are propagated where needed.

Also, this approach works peer-to-peer, not requiring monolithic servers or central cloud services. This is more secure, robust and efficient.

NetObjects:

Duncan Cragg, 2016

Contact me and/or subscribe to my blog and/or follow me on Twitter.