Chapter 4. A bank account

We're going to see now how types and factories are created and used in Obix. This will be illustrated by the example of a bank account. To keep the exercise simple, the objects we will create will be a bit simplified compared to objects in a real-world application. The goal is to quickly get a general insight and discover important concepts that are necessary to write more reliable code in less time.

[Note]Note

In the following paragraphs there will be a number of links to Obix's programming manual. These links are provided for the reader who immediately wants more information about the treated subject. However, it is not necessary to visit each link before continuing reading. You can skip the links if you just want to quickly get an overview about how to program in Obix.

Our example will be based on the following specifications:

Types, factories and services are stored in logically organized libraries (similar to packages in Java, or namespaces in C#). Obix uses the file system for storing libraries and there components. The physical structure of the directories reflects the logical structure of the libraries. A new library is created by simply creating a new directory whose name must be equal to the library's prefixed identifier. For more information on libraries, see the section called “Libraries” in the programming manual.

Let's create a new library for our purpose and choose li_bank as its identifier.

Create directory li_bank as a sub-directory of the existing directory programming/source_code/li_explore under the root directory of Obix (e.g. /usr/local/obix/programming/source_code/li_explore/li_bank on Linux and Unix, or c:\program files\obix\programming\source_code\li_explore\li_bank on Windows). The structure should look like this:

Let's now create type bank_customer. Select Source code / Create new ... from the menu and enter the following code:

type bank_customer default_factory:yes
  
   attribute identifier type:positive32 end
   attribute name type:string end
   attribute city type:string end
  
end type

Save the text into file ty_customer.osc in directory li_bank. That's all for the type.

[Note]Note
For more information on types, see the section called “Type” in the programming manual.

You may now want to compile the code to be sure there is no syntax error. Select Compiler / Compile all from the menu.

How would a new customer be created? In Obix, objects are always created with factories. However, in our case we don't need to explicitly define a factory for creating bank_customer objects. The default_factory:yes clause in the type instructs the compiler to automatically create factory fa_bank_customer.

[Note]Note
For more information on the default_factory:yes clause, see Table 5.1, “Type” in the programming manual.

A new customer could now be created and stored in a variable like this:

var bank_customer customer_giovanni1 =2 fa_bank_customer.co_create3 ( &4
   identifier = 285 &
   name = "Giovanni Spiridigliotzky"6 &
   city = "Rome"7 )8
1

declare variable customer_giovanni of type bank_customer. For more information on the variable declaration instruction, see the section called “Variable declaration instruction” in the programming manual.

2

assignment operator

3

use creator command create of factory bank_customer to create an object of type bank_customer

4

& is the line continuation character in Obix. For more information, see the section called “Line continuation” in the programming manual.

5

assign the value 28 to input argument identifier

6

assign "Giovanni Spiridigliotzky" to input argument name

7

assign "Rome" to input argument city

8

In Obix, instructions must not be terminated with an ; at the end of line, such as in Java and C#.

We can now proceed with the bank account. First enter the following code and save it in file ty_bank_account.osc of directory li_bank:

type bank_account
  
end type

Each account is assigned to one customer. Hence we add attribute customer:

type bank_account

   attribute customer type:bank_customer end 

end type

Another attribute of type bank_account is the account's balance.

The initial balance of an account is 0. This is coded by setting property default to 0.

The value of balance can change over time; therefore property kind must be set to variable.

Attribute balance must be protected against setting it directly with and instruction such as account.balance = 1000. Only the factory is allowed to change the balance, whenever a pay_in or withdraw operation is executed. Therefore property setable is set to factory

This leads to the following code for attribute balance:

   attribute balance type:zero_positive32 default:0 kind:variable setable:factory end
[Note]Note
For more information on the properties of attributes, see the section called “Attribute” in the programming manual.

Finally we have to add commands pay_in and withdraw. Both commands take an amount as input argument. Command pay_in can be defined as:

   command pay_in
      in amount type:positive32 end
   end command

withdraw is similar to pay_in. Thus, the complete code for type bank_account becomes:

type bank_account

   attribute customer type:bank_customer end 

   attribute balance type:zero_positive32 default:0 kind:variable setable:factory end 

   command pay_in
      in amount type:positive32 end
   end command 

   command withdraw
      in amount type:positive32 end
   end command 

end type

Whenever a type has at least one command, Obix cannot provide a default implementation for the factory. So we have to create factory bank_account ourselves.

Create the following code and save it into file fa_bank_account.osc in directory li_bank:

factory bank_account type:bank_account
  
end factory

As we can easily see, we are creating factory bank_account that implements type bank_account.

Obix always provides a default implementation for attributes in factories. This default implementation is based on how the attributes are defined in the type. In our case the default implementation is suitable, so we don't have to code anything for the attributes in the factory.

Command pay_in is easy to implement. The account's balance is simply incremented by the amount paid in. Hence, the code looks like this:

   command pay_in
      script
         a_balance = a_balance + i_amount
      end script
   end command

Command withdraw is similar:

   command withdraw
      script
         a_balance = a_balance - i_amount
      end script
   end command

What remains to be done is to define the following creator for factory bank_account:

   creator create
      in customer type:bank_customer end

      out result type:bank_account end

      script
         o_result.a_customer = i_customer
         o_result.a_balance = 0
      end script
   end creator

The creator takes a bank_customer as input argument, and returns a bank_account as result.

The creator's script simply assigns input argument customer to attribute customer and sets attribute balance to 0.

Nothing needs to be done for attribute balance. Type bank_account specifies a default value of 0 for balance, therefore the compiler automatically initializes balance with 0.

The complete code for factory bank_account is as follows:

factory bank_account type:bank_account

   command pay_in
      script
         a_balance = a_balance + i_amount
      end script
   end command 

   command withdraw
      script
         a_balance = a_balance - i_amount
      end script
   end command 

   creator create
      in customer type:bank_customer end

      out result type:bank_account end

      script
         o_result.a_customer = i_customer
         o_result.a_balance = 0
      end script
   end creator 

end factory

Enter the above code and save it in file fa_bank_account.osc. Then compile again to see if there are no errors.

[Note]Note
For more information on factories, see the section called “Factory” in the programming manual.

We now have a first working solution. There are still some improvements neglected for the moment, but that will be fixed in a subsequent chapter. It's time now to test the code we have written so far. The next chapter introduces Obix's integrated facilities to test code.