Client-side Class Inheritance

Learn how to inherit from and modify the behavior of TinyChain client classes

Client-side methods

The recommended way to do object-oriented programming in TinyChain is to host Model classes as part of a Service. This minimizes the amount of work the developer has to do in terms of keeping track of the difference between the compile-time and run-time state of their program. However, in some cases, instance methods must be defined entirely client-side, meaning they are defined and executed only at compile-time in order to construct Ops that are executed at run-time.

For these reasons, client-side instance methods are used extensively in the TinyChain Python client. For example, Table.insert is only defined in the client (the host has no /insert handler) because insert is not idempotent and therefore is not safe when replaying the low-level write operations recorded in a Block of a BlockChain. Code like this is not straightforward to read or write.

Easy: helper classes based on Map and Tuple

Consider this example:

@tc.post_op
def force(mass: tc.Tuple, acceleration: tc.Tuple) -> tc.Tuple:
    mass_quantity = tc.Number(mass[0])
    mass_unit = Mass(mass[1])
    acceleration_quantity = tc.Number(acceleration[0])
    acceleration_unit = Velocity(acceleration[1])**2
    return mass_quantity * acceleration_quantity, mass_unit * acceleration_unit

Because Tuple by itself doesn't contain any type information, there's a lot of boilerplate destructuring code here and a lot of room for error. For example, is the Unit of acceleration already Velocity**2? It's hard to see if there's a bug. Readability and usability can be improved by a helper class:

Now the business logic is much more readable:

Challenging: construct a deep neural net

This example highlights the distinction between compile-time and run-time state which the developer must be mindful of in order to define a client-side instance method. As a general rule, a parameter which is a native Python state known at compile-time (like the integer n above) is safe to reference when constructing a class or method, but a TinyChain State in the calling context has to be referenced using self. The nested class idiom (where the create method defines a custom subclass of cls) is only necessary when the structure of a compute graph which the class defines depends on a compile-time parameter (like n in DNN.forward).

Last updated