Lasso Soft Inc. > Home

Object Oriented Programming Primer for Lasso

Introduction to OOP

The introduction to Lasso 9 brings in some new functionality, as well as an increased exposure to object-oriented programming (OOP). Lasso in an object-oriented language, however before version 9, it was generally received as a language that could perform either procedurally, or had the tools to get into OOP. This article is meant to clarify how OOP works, how Lasso developers have been using OOP techniques without knowing them, and clarify some of the terminology.

Parentheses syntax will be used for code demonstration.

Objects

It can be assumed that every Lasso developer has used the Lasso language in order to provide a way of getting information into a database. A table might be to hold data on cars, books, recipes, etc. OOP looks at these items as definable entities and strives to encapsulate management of these items through using variables and handlers that modify these objects. When we approach an application using OOP, we spend time defining such objects and give them the tools they need to survive on their own.

OOP is easy once you get how it works. The toughest part about OOP is understanding how it works, and keeping your head around those concepts. OOP is the art of defining our types. Data types are sets of values that we commonly use to store structured information. Examples are integers, strings, arrays, and maps. These are objects that are already defined within Lasso, so we don't need to provide a define_type in order to use these. We use define_type in order to define objects that we want to work with.

A Lasso type is what's known as a class in OOP. When we define types, we are providing an object's class definition. As an example, we define a "user". A user has information associated with it such as username, password, address, city, country, postal code, email, phone, etc. Those aspects of a user are known as properties or attributes. Every time we make a "user" object, there are internal places inside that are available to hold such items. Every user has a username, a password, etc.

define_type('user');
	// define properties
	local(
		'id'					= string,
		'username'			= string,
		'password'			= string,
		'addresss'			= string,
		'country'			= string,
		'postalcode'			= string,
		'email'				= string,
		'phone'				= string,
		'fave_colour'			= string
		);

	// define methods

	define_tag('set_colour', -opt = 'colour');
		if(#colour != '');
			self->'fave_colour' = #colour;
		else;
			self->'fave_colour' = 'red';
		/if;
	/define_tag;

	define_tag('set_pass', -req = 'pword');
		if(#pword->length < 8);
			return('password too short');
		else;
			self->'password' = #pword;
		/if;
	/define_tag;

	define_tag('show_country');
		if(self->'country' != '');
			return(self->'country' + ' is where I am from, proud of it');
		else;
			return('I have no idea where I am from');
		/if;
	/define_tag;

	define_tag('DBupdate');
		inline($dbconn, -table = 'users', -SQL = "UPDATE users SET 
			address = self->'address',
			country = self->'country',
			postalcode = self->'postalcode',
			email = self->'email',
			phone = self->'phone',
			fave_colour = self->'fave_colour'
			WHERE id = self->'id')	
			error_code ? return('Uhoh, something wrong writing to database: ' + error_msg);
		/inline
	/define_tag;
/define_type;


// Application methods used for the 'users' class:

var('user1'	= user);			// A
var('user2'	= user(-country = 'Canada'));	// B

$user1->set_colour(-colour = 'blue');		// C
$user2->set_pass(-pword = 'moosehair');	// D

$user1->show_country;					// E
$user2->show_country;					// F

$user1->DBupdate;					// G

 

Code Walkthrough

First we define the type, which is our user class. The properties are defined. Then the methods. The set_colour method is a tag that can only be used in the user type, and it sets the fave_colour property to the 'colour' parameter used with the method. Self is a tag that refers to the current instance of this type. More on that later. The set_pass method is a tool to change the password. The show_country method is to grab the country property and to display it to the user accordingly.

Part A above is where we make a user. We shove it into the $user1 variable. It's just like making any other data type, like a string or integer, but in this case we have a user, with all properties completely empty. Please note, there are ways of automatically setting properties during type instantiation. As well, there are special member tags (methods) that are private to the type which perform specific tasks. onCreate is a tag which gets run automatically when a class is instantiated.

Part B is another variable of the user type, but this time a country parameter was provided. Any property that is supplied automatically goes into the property local. So $user2's country is already set to Canada.

Part C says "set the colour of $user1 to 'blue'". It uses the set_colour method, throws the 'colour' parameter, which gets shoved into that property. This is called a "setter". While we can change properties directly, it isn't proper practice, and setters should be written. Changing and retrieving property values should always be done through member tags. In this way, you can control what properties you have "permission" to view or modify.

Part D changes the password for $user2.

Parts E and F call the show_country method for each user, and ask to display their countries.

Part G is where the current object is written to the database. Similar methods can be written to populate an instance of an object with fields from a record, however you will need to somehow provide which record you need. Usually this is a keyfield. A proper test for this type of updating function would mean to search the database to see if the record is already present. If not, to create the record by using an INSERT SQL command, then grabbing the keyfield value for the id attribute. Methods for INSERT, UPDATE, SELECT and DELETE will often be common in your classes.

As you can see, the direct encapsulated design of the type definition, including properties and methods (member tags) means it's all "black box" functionality. Parameters in, response back. This in turn allows the application to be much shorter and much more direct than in traditional inline procedural coding. This allows your design to get much quicker and more convenient. You will find that polishing your types is something you need to do, and you spend more time in defining types rather than in your applications. But there are some serious benefits in approaching design in this matter, because it forces you to respect your type definitions and their functionality.

Instantiation

As the code demonstrates, two objects were made. They were both of the "user" class. Making objects is commonly labelled the "cookie cutter" process. Every cookie cutter has a different shape, with the overall area and shape being the attributtes of the cookies that are made by each. One is shaped like a star, another shaped like an apple, another shaped like a moose. They are all different classes. When we use them on cookie dough, the actual cookies that are made, come out in the shape of the definition. The cookies are objects. I can say "the third cookie I made is a star, the first cookie I made is a moose".

What "self" Means

An object is an instance of a class. Every object that is created has the ability to look at itself through methods. In order to perform functions on that instance, a method uses the term "self". self->change_colour('red') is an implementation upon the current instance, which is parked inside a variable. It says "change MY colour to red". It is relevant only in the scope of the single instance in which we are speaking. Any call for a method comes from the reference to an instantiation, or from the developer's point of view (outside the type definition), an object.

In Lasso 9, we can use the decimal to represent "this": .'colour' = red

Common Lasso Programming and OOP

The problem that sits in front of us at the introduction of Lasso 9 is that we have been using member tags for so long that we might see them as being part of Lasso, instead of OOP. The following code is essentially a call on a string type member tag (method):

var('myVar')	= 'Amsterdam'; // type instantiation
$myVar->length;		// => for 9

The second line is calling a method which counts the characters in the $myVar. $myVar is obviously a string type, and in the type definition (define_type('string')) there is a method (member tag) called "length". I am guessing it's just a small function that splits up the property where the value is kept into an array, then it returns the size of the array. Not complicated, but highly useful.

When we build custom tags openly, we are essentially taking previously defined data types, and implementing them through an external method. We think it's just a custom tag, but we always have to deal with a previously defined data type.

Terminology

Lasso name OOP name
member tag method
property property/attribute
type class (a class is an object template, or object definition)
single instance of a class   object
making an object object instantiation (the reference to the object is THIS instance)

Pros and Cons of OOP

Cons

  • Learn new way of approaching things
  • Slight increase in processing overhead
  • Sometimes difficult to stay within OOP mindset during development

Pros

  • Wrapping of all associated properties and funcionality (methods) within one manageable black box. This separates how types hold their data and the methods. This allows for compartmentalization of development of objects outside of the scope of an application.
  • Reusable objects become as familiar as common types, and are easily transportable into other applications.
  • Application time is spent on development of the application, not the functionality of the object, so your applications gel much quicker.
  • Objects can contain methods in order to test their instantiation and methods, called unit testing.
  • Ability to store objects in session variables, which makes getting properties very easy.
  • Protection of properties (and methods) through force of usage through getters and setter methods.
  • Integration of Inheritance where you can build hierarchies of types, and rely on previously defined types.

Example: twitter type on tagSwap.net

I am going to walk through an example that is available on http://www.tagswap.net/twitter/. Twitter has an API which Jason Huck has taken advantage of. Essentially you can construct urls to get feedback from the Twitter API, and you have to submit parameters so that Twitter knows what you are asking about. Jason has parked all of this functionality into a type which demonstrates an object, its associated properties, and a slew of methods. In the end, it's a slick set of tricks that are very well packaged, that demonstrate how all of this can be managed.

Walkthrough

  • The referenced file is the downloaded file, not the presented one in the URL's iFrame.
  • The type definition runs from line 92 to line 537, which is made up of 2 properties and 37 methods (disregarding comments).
  • line 96: This line provides the definition for the type properties, which are only two: username and password. It's evident that this type is a Twitter account. Every transaction that goes to Twitter has to include these, so they are held inside the type for when any transaction needs to be done. If they were not properties, they would have to be supplied with every method as parameters.
  • line 101: This onCreate method is special. It is a method that is called every time you make a "twitter" object. Remember, the definition (class) is a description of the type, and an instance is every time you make one of these. Think cookie cutter. The stainless tool you use to make cookies, you define as the type. When you make cookies, you instantiate every single cookie. The cookies then are in your application as individuals, but use the methods you define, on their own. This onCreate essentially says "if a username was provided, then set the internal username property to that parameter". Same for password. In version 8.5 and earlier, named (and unnamed) parameters thrown to a type instance are automagically sent to associated named properties, but this really should be implemented by what's called a setter. Jason has taken this proper way of setting properties upon the instantiation by using the onCreate to directly map both properties when submitted. Lasso 9, from what I understand, enforces such getters and setters without having the ability to manipulate properties in any type, in any direct fashion. It's proper OOP practice, and can save developers a lot of grief. It's also sexy code.
  • line 110: This is the first regular method. Previous to 9, these are called member tags, or members. These are essentially little engines that work on the instance. If I have 3 of my cookies that are parked into variables $c1, $c2 and $c3, I can implement a method on any individual cookie by calling it directly from the variable, which is an instance of a cookie: $c2->sprinkle('red_sprinkles') would change the second cookie only. That method only works on $c2, and the other cookies have the method inside, yet they haven't changed at all. This is how it is said that "properties and methods travel with objects". The method I have described is available to me as a developer as I have demonstrated in the code. Private methods are protected and I cannot call them. They are implemented in different ways, and is outside of the scope of this presentation. This method in question on line 110 returns a boolean true or false to see if the account is filled with both username and password. Any call to the Twitter API will need these filled with something, so this method basically tests this qualifier. The method "retrieve" on line 114 is the method of asking the Twitter API to fetch info.
  • The next handful of methods are to build parameters for the post_parameters in the retrieve method. Methods inside a type can call other methods. Past the scope again, these inside methods called by methods can be private in this fashion, only accessible to other methods inside the definition.

Implementation:

var('t1') = twitter(-username = 'StevePiercy', -password = 'moosehair');
	// $t1 is your twitter type instance, which is an object
$t1->public_timeline->first;
	// this shows the first item from the public timeline of Steve's account
$t1->update('Duke takes me for a walk');
	// this is how he published to the world that his dog Duke owns this guy right now

As you can see, once the type is tested, it is highly reliable and the syntax to implement the functionality associated with any type you make, is really small and precise. This is one of the benefits of OOP, and it's called encapsulation. You rely on storeys or layers of tested, segregated code.

Reusable types, like this Twitter type, can be shoved into any application by including the type definition (class) somehow. You can park all of your definitions into a folder and call them as needed. When developing, methods are called to do anything, and are quite often done using a single line representing the method name, and some named parameters.

Some methods can be designed to implement functionality that's completely relevant to the developer in order to troubleshoot. The method on line 533 is what Jason has implemented to present feedback from Twitter.

Further Reading

A good book I read to get me into OOP is The Object-Oriented Thought Process, Third Edition, by Matt Weisfeld (Addison-Wesley).

Other Relevant Tagswap References:

Knop is a Lasso framework that uses OOP:

Author: Richard Fortnum
Created: 18 Nov 2009
Last Modified: 16 Mar 2011

Comments

No comments found
You must be logged in to comment.

LassoSoft Inc. > Home

 

 

©LassoSoft Inc 2014 | Web Development by Treefrog Inc | PrivacyLegal terms and Shipping | Contact LassoSoft