chapter 6 actions, methods, refactoringcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf ·...

12
VERSION 1 ACTIONS, METHODS, REFACTORING – 61 – CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in more depth and show how to easily create additional actions in a script by using a technique known as REFACTORING. The chapter covers two forms of refac- toring supported in TouchDevelop. One form provides an easy way to create new actions, while the other form provides an easy way to add declarations for new variables to a script. We also show an extension to the second form of refactoring which promotes a local variable to become a new global data item. 6.1 ACTIONS 6.2 PARAMETER PASSING MECHANISMS 6.3 METHODS IN THE API 6.4 REFACTORING 6.1 ACTIONS An ACTION in TouchDevelop is very similar to a function in C or Python, or to a static method in Ja- va or C#. It is an independent sequence of statements which has a name, it optionally has input pa- rameters, and it optionally has result parameters. Let us take a look at the short example in Figure 6.1. This is similar to how the code would appear on the phone’s screen. Figure 6.1: The send invite Action action send invite( recips, msg ) returns n n := 0 for each s in recips where true do social → send email(s, “party invitation”, msg) n := n + 1 This send invite action has some properties which can be viewed by tapping the first line of the ac- tion, tapping the edit button, and swiping left-to-right. The PARAMS property will show the names

Upload: others

Post on 05-Aug-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

VERSION 1 ACTIONS, METHODS, REFACTORING

– 61 –

CHAPTER 6

ACTIONS, METHODS, REFACTORING

In this chapter we cover ACTIONS in more depth and show how to easily create additional actions

in a script by using a technique known as REFACTORING. The chapter covers two forms of refac-

toring supported in TouchDevelop. One form provides an easy way to create new actions, while the

other form provides an easy way to add declarations for new variables to a script. We also show an

extension to the second form of refactoring which promotes a local variable to become a new global

data item.

6.1 ACTIONS

6.2 PARAMETER PASSING MECHANISMS

6.3 METHODS IN THE API

6.4 REFACTORING

6.1 ACTIONS

An ACTION in TouchDevelop is very similar to a function in C or Python, or to a static method in Ja-

va or C#. It is an independent sequence of statements which has a name, it optionally has input pa-

rameters, and it optionally has result parameters.

Let us take a look at the short example in Figure 6.1. This is similar to how the code would appear

on the phone’s screen.

Figure 6.1: The send invite Action

action send invite( recips, msg ) returns n

n := 0

for each s in recips where true do

social → send email(s, “party invitation”, msg)

n := n + 1

This send invite action has some properties which can be viewed by tapping the first line of the ac-

tion, tapping the edit button, and swiping left-to-right. The PARAMS property will show the names

Page 2: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

ACTIONS, METHODS, REFACTORING VERSION 1

– 62 –

and the datatypes of all the input parameters. For the send invite action, the listing of the parame-

ters is as shown in Figure 6.2.

Figure 6.2: The send invite PARAMS Property

Similarly, the RETURNS property provides more information about the result returned by the ac-

tion. It is shown in Figure 6.3.

Figure 6.3: The send invite RETURNS Property

The input parameters work in a similar manner to parameters of methods in Java or C#. In other

words, the parameters are considered to be local variables of the action and, each time the action is

invoked, the parameters are initialized by copying values supplied by the caller.

Suppose, for example, that one of the other actions in our script is bulk mailer as shown in Figure

6.4. This action creates a String Collection value as the value of variable addr list and initializes the

variable msg to hold a String value. When send invite is invoked, its first parameter recips is ini-

tialized so that it refers to the same String Collection as addr list. Similarly, the second parameter

msg is initialized to hold the same string as the caller’s local variable named msg. Now that the pa-

rameters of send invite have been initialized, the body of the send invite action is executed. We will

not go into any detail about what this action does (suffice to say it will likely annoy everyone whose

name begins with ‘j’ in the contacts collection held on your phone if you actually run it). However,

while the action is running, it is computing a value held in the variable n. This variable is declared

as an output parameter, but while the action is executing, it should be considered to be just like any

local variable. When the action’s body has finished executing, the value of this local variable is re-

turned as the result. Its value will be assigned to variable cnt in the caller.

Page 3: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

VERSION 1 ACTIONS, METHODS, REFACTORING

– 63 –

Figure 6.4: A Caller of the send invite Action

action bulk mailer( )

var my j friends := social → search contacts("j")

var addr list := collections → create string collection

for each c in my j friends where true do

var addr := c → email → address

addr list → add(addr)

// a more realistic example would assign several lines

// of text to the msg variable

var msg := "Will you come to my party on Friday? "

var cnt := ▷send invite(addr list, msg)

(cnt || " friends have been invited") → post to wall

Unlike many programming languages, there is no return statement in TouchDevelop. Execution

must reach the end of the action before control returns to the caller and any results are returned.

Now for some details which serious script developers need to know.

6.2 PARAMETER PASSING MECHANISMS

This is a topic which has been partially covered in Chapter 3 already. To recap, there are two kinds

of datatypes in the TouchDevelop scripting language. There are VALUE TYPES, where the variable

holds the value directly. For example, a variable of type Number corresponds to a word in the

memory of the phone which holds the number directly (as a bit pattern). And there are REFERENCE

TYPES. Every collection type in TouchDevelop is an example of a reference type. Suppose, for ex-

ample, a variable has the Link Collection type. The link collection value is a data structure located

somewhere in memory and the starting point for that data structure has a memory address (or a

location number). A variable in the script which has the type Link Collection would correspond to a

word in memory which holds the memory address of the data structure. When a variable which has

a reference type is assigned to another variable or is passed as a parameter to an action, we have

two references to the same data structure in memory.

This situation is diagrammed in Figure 6.5 where the variable num1 has the Number type, while

both links1 and links2 are variables with the Link Collection type. After creating a link collection as

a list of three e-mail addresses and assigning it to links1, another assignment

var links2 := links1

has been executed. Now any changes to the links1 link collection will change the links2 collection

and vice versa, because they are both references to the same collection.

Page 4: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

ACTIONS, METHODS, REFACTORING VERSION 1

– 64 –

Figure 6.5: Value Types and Reference Types

Exactly the same behavior is observed for passing parameters to actions. If the parameter has one

of the value types then the action has a completely independent copy. If the parameter has one of

the reference types, then the caller and the action share references to the same value held in the

phone’s memory.

Which are the value types exactly? They are Number, Boolean, DateTime and Vector3. Every other

type is a reference type.

RETURNING RESULTS

The TouchDevelop editor allows an action to have any number of return parameters. What does

this mean? It simply means that the action can return several results at once and they can have dif-

ferent types. As a highly contrived example, consider the action shown in Figure 6.6.

Figure 6.6: An Action with Two Results

action random stuff( ) returns song, pic

var all songs := media → songs

var all pics := media → pictures

song := all songs → random

pic := all pics → random

Page 5: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

VERSION 1 ACTIONS, METHODS, REFACTORING

– 65 –

All that matters for our example is that it has two result parameters, one of type Song and the other

of type Picture. When it is invoked, the caller can assign the result to two variables simultaneously.

Here is an example of how to write the calling code:

var s, p := ▷random stuff( )

s→play

p→post to wall

It declares s and p as local variables with type Song and Picture respectively, and then those varia-

bles are assigned the result of invoking the random stuff action.

Not many programming languages support functions or methods which return multiple results.

(Programmers in such languages must use various workarounds or less readable programming

constructs.) This feature of TouchDevelop can be used to make scripts shorter and more readable.

TouchDevelop treats a result parameter as a local variable with an invalid initial value. The action

must assign a value to the result parameter before the action returns to the caller. To enforce that

requirement, TouchDevelop analyzes the code of the action and checks that at least one assignment

happens on every possible execution path through the action.

6.3 METHODS IN THE API

The API provides various globals which have methods that can be invoked by a TouchDevelop

script. For example, one such global is languages and one of its methods is ‘detect language’. (A

Java or C# programmer might think of languages as being a class type and ‘detect language’ as be-

ing a static method of the class.)

The API also provides a number of datatypes, and values possessing those datatypes have associat-

ed methods. For example, chapter 2 used the Picture datatype in an example and it created a local

variable named pic with that type. One of the examples used the ‘set pixel’ method on that pic var-

iable. (A Java or C# programmer might consider pic to be a reference to a class instance and ‘set

pixel’ to be an instance method.)

When we write code to invoke these methods, parameter values may be passed into the methods

and results may be returned from them. Although the API’s methods are all implemented in the C#

language (as is the whole TouchDevelop application), the methods all behave similarly to Touch-

Develop actions. Value types are passed in to the methods using the call-by-value mechanism and

reference type values are passed in using call-by-reference.

Although methods provided by the API have the potential to return multiple results, none does.

Every method provided in the API so far either returns a single value or it returns Nothing.

Page 6: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

ACTIONS, METHODS, REFACTORING VERSION 1

– 66 –

6.4 REFACTORING

The word REFACTORING is used in software engineering to mean a reorganization of a program

which does not change its behavior. Such a reorganization is normally performed to improve the

quality of the software in some way, such as to make the code more efficient or to be more readable

by humans. Most modern environments for software development, such as Visual Studio and

Eclipse, provide a variety of tools to support different forms of refactoring.

The TouchDevelop editor provides two forms of refactoring. One form extracts a group of state-

ments from an action and creates a new action, with appropriate parameters, from those state-

ments. We might want to perform such refactoring if we have an action which has become too long

to comfortably display on the screen and we simply want to split the action up into smaller pieces.

Or, perhaps we have recognized that there is a particular group of statements which we will need to

execute several times with different parameterization. These are both excellent reasons to extract

and create a new action. Finally, a TouchDevelop user is likely to find this form of refactoring to be a

time saver because fewer taps and few swipes are needed to create a script composed of multiple

actions.

The second form of refactoring is to extract an expression or a subexpression, replace it with a

newly created variable, and insert an initialization of that new variable with the extracted expres-

sion.

A further step beyond extracting an expression and creating a new local variable is to convert that

local variable into a new globally visible data item. This would make the value of the variable acces-

sible to all the actions in the script (as well as preserving the value of the data item from one invo-

cation of the script to the next invocation – a feature known as persistence.)

REFACTORING: EXTRACTION OF STATEMENTS TO A NEW ACTION

Let’s go through an example of refactoring in TouchDevelop. Chapter 2 contained an example, the

‘Random circles’ script, which was constructed and entered as two separate actions. Suppose that

we had entered the script as just one action. It would look like the script shown in Figure 6.7.

There is nothing wrong with this version of the script, it is not too long and it runs perfectly well.

However, we might decide that the group of statements which draws the circle is so useful that we

want to extract that code and make a new action from it.

Page 7: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

VERSION 1 ACTIONS, METHODS, REFACTORING

– 67 –

Figure 6.7: A Monolithic ‘Random circles’ Script

action Random circles( )

pic := media→create picture(400, 400)

for 0 ≤ i < 20 do

var radius := 5 + math→random(95)

var x := math→random(400) // x coordinate of center

var y := math→random(400) // y coordinate of center

var color := colors→random

for 0 ≤ i1 < 2 * math→ * radius do

var xofs := x + radius * math→cos(i1 / radius)

var yofs := y + radius * math→sin(i1 / radius)

pic→set pixel(x + xofs, y + yofs, color)

pic→post to wall

Here are the steps we might perform extract the circle drawing code (which corresponds to the in-

ner for loop).

1. Touch anywhere in the first line of the group of statements we wish to extract. For our exam-

ple, that is the inner for loop (the one which uses i1 as the index variable). The screen should

now look like this:

Page 8: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

ACTIONS, METHODS, REFACTORING VERSION 1

– 68 –

2. Now touch the button labeled ‘select more’ and the screen changes to look like this:

3. It so happens that everything we want has been selected because it is a single statement (the

entire for loop) identified by the red bar on the left and show between the upper and lower

rows of buttons. If we wanted to selected additional statements, we could drag the group of

statements upward to increase the range of statements to be extracted. In our example, we do

not need to do that, so we can proceed to tap the extract button. At this point, we are asked to

provide a name for the extracted code (the new action). We enter the desired name, ‘draw cir-

cle’, and tap another extract button.

4. The screen should change to show the revised ‘Random circles’ action after the refactoring has

been performed. Here is a screenshot:

Page 9: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

VERSION 1 ACTIONS, METHODS, REFACTORING

– 69 –

5. The editor has created an invocation of the new action, with the name we gave it and with

whatever parameters were needed to transmit values of variables from the caller (the Random

circles action) to the callee (the new draw circle action).

At this point, the refactoring has been completed. The modified script should work just as before.

Finally, here is a quick way to see the code of the new action (or of any action being invoked in a

script). We touch the line of code containing the call to the action. This brings up the edit statement

menu, which looks like the following for our example:

The go to button will take us to the code for the action invoked in the selected statement. After

touching it, the screen will show our refactored action:

The code is remarkably similar to the code originally shown in Chapter 2. The only differences are

the order in which the parameters appear and the name used for the index variable of the for loop.

These would usually be considered to be trivial and unimportant differences.

REFACTORING: EXTRACTION OF AN EXPRESSION TO A VARIABLE

If you discover that you have constructed an expression whose value you would like to reuse, or if

you have a complicated expression which you would like to break up into smaller pieces, this form

of refactoring is just what you need.

Let’s take a small example. Suppose that you have just entered the following script which calculates

the length of the diagonal side of a right-angled triangle whose sides are x1 and y2:

Page 10: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

ACTIONS, METHODS, REFACTORING VERSION 1

– 70 –

Perhaps we are now going to extend this script to perform more calculations and we will need to

reuse the values of x1*x1 and x2*x2 in some statements we will add to the bottom. Here are the

steps to follow.

1. Tap the line containing the expression you wish to extract. In our sample script, that is the

line beginning “var x := …”

2. Tap the first element of the expression, which is the first x1 appearing in that line.

3. Swipe from left to right, to highlight all the elements of the selected expression. For our exam-

ple, the screen should now look like this, with a menu of available editing actions at the bottom:

4. Tap the extract to local button. The statement shown on the screen changes to the following,

indicating that a new local variable named x3 has been created.

5. Let’s repeat steps 2 to 4 in the same way to extract the expression x2*x2 into a new local varia-

ble named x4.

6. We can tap the phone back button to see how the code for our script has been transformed.

Page 11: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

VERSION 1 ACTIONS, METHODS, REFACTORING

– 71 –

7. If we do not like the default names provided for the new local variables, they are easy to re-

name. One just has to tap any line where the name appears, choose the option to edit the line,

select an occurrence of the variable, and there will be a rename button provided on the screen.

REFACTORING: PROMOTING A LOCAL VARIABLE TO A GLOBAL DATA ITEM

Perhaps we are going to expand the example script by adding many new actions to it and lots of

these actions will need access to the values of the new variables x3 and x4. One possibility is to

pass x3 and x4 as parameters to the various actions. Another possibility is to convert x3 and x4

into global data items. TouchDevelop provides an easy way to make that transformation.

The steps for converting the local variable x3 in the preceding example into a new data item are as

follows.

1. Tap the line which declares and initializes the local variable.

2. Tap the edit button.

3. Tap the variable on the left-hand side. An edit menu like that shown below appears.

4. Tap the promote to ◳ button. The code displayed on the screen changes to that shown below,

indicating that x3 is now being accessed as a global data item. A return to the main screen for

the script would show that the script now includes x3 as a data item.

Page 12: CHAPTER 6 ACTIONS, METHODS, REFACTORINGcdn.touchdevelop.com/c03/smqv-bookchapter6.pdf · 2012-02-28 · CHAPTER 6 ACTIONS, METHODS, REFACTORING In this chapter we cover ACTIONS in

ACTIONS, METHODS, REFACTORING VERSION 1

– 72 –