Method Chaining

Creating objects with a complex constructor can be a bit of a pain in any language. One technique I have used is method chaining. It is not applicable to every type of class but it can be useful.

Method chain can help simply the use class and allows more complex object initialisation without having to worry about the order of the parameters and be done inline.

Consider the use of an “Account” class that takes Name, Address, Telephone and Country. All of which are strings, the constructor with four strings would not be a great constructor.

So you could have a simple constructor and four properties/methods.. however so set up the object would mean you have spread the setup over multiple lines.

Using method chain you can overcome this and even space in the “value” area of the object in your storage area.


set x to new type Account::Name("xx")::Address("yy") ::Telephone("yy")
::Country("zz")::World("Earth")

The trick of the pattern is to provide methods that always return this/self, so we can change the invokes together… For example:

This technique could even be used to build up a series of items required, for example, the preparation and execution of a sql statement comes to mind… in a similar fashion to Linq.

So… lets look at an example:


$set ilusing"System.Collections.Generic"
program-id. Program1 as "MethodChaining1.Program1".
data division.
working-storage section.
01 accounts type List[type Account] value new type List[type Account].
01 jAccount type Account value
new type Account::Name("Mr Johnson")::Address("Somewhere, some place")
::Telephone("+44 1234 4321").
01 sAccount type Account value
new type Account::Name("Mr Smith")::Address("Nowhere place")
::Telephone("+44 1234 4321")::Country("Wales").
01 lAccount type Account.
procedure division.
invoke accounts::Add(jAccount)
invoke accounts::Add(sAccount)

perform varying lAccount through accounts
display lAccount
end-perform

goback.
end program.

WIth the class being:


class-id Account.

working-storage section.
01 wName string property as "Name".
01 wAddres string property as "Address".
01 wCountry string property as "Country".
01 wTelephone string property as "Telephone".
01 wEmail string property as "Email".

method-id New.
local-storage section.
procedure division.
set wCountry to type System.Globalization.RegionInfo::CurrentRegion::DisplayName
end method.

method-id Name public.
procedure division using uName as string
returning ret as type Account.
set self::Name to uName
set ret to self
end method.

method-id Address public.
procedure division using uAddress as string
returning ret as type Account.
set self::Address to uAddress
set ret to self
end method.

method-id Telephone public.
procedure division using uTelephone as string
returning ret as type Account.
set self::Address to uTelephone
set ret to self
end method.

method-id Email public.
procedure division using uEmail as string
returning ret as type Account.
set self::Address to uEmail
set ret to self
end method.

method-id Country public.
procedure division using uCountry as string
returning ret as type Account.
set self::Country to uCountry
set ret to self
end method.

method-id ToString public override.
procedure division returning ret as string.
set ret to String::Format("Name:{0}, Address:{1}, Telephone:{2}, Email:{3}, Country:{4}",
self::Name, self::Address, self::Telephone,
self::Email, self::Country)
end method.
end class.

Which when run with Visual COBOL gives:


Name:Mr Johnson, Address:+44 1234 4321, Telephone:, Email:, Country:United Kingdom
Name:Mr Smith, Address:+44 1234 4321, Telephone:, Email:, Country:Wales

This entry was posted in CLR, COBOL and tagged , , , , , , . Bookmark the permalink.