Translate

Search This Blog

Total Pageviews

Thursday, October 18, 2018

Basic Programming Concepts: Program Structure


A computer program is a set of statements that is used to create an output, such as a screen display, a printed report, a set of data records, or a calculated set of numbers.
The statements in the programs may be statements that are executed in sequence.
A program is written using the statements of a programming language.

Individual statements perform simple operations such as printing an item of text, calculating a single value, and comparing values to determine which set of statements to execute.

Simple instructions are performed in hardware by the computer’s central processing unit(CPU).
Complex instructions are written in programming languages and translated into the machine's internal instruction set by another program(assembler, compiler, interpreter).

Computer memory is generally composed of bytes, which are data items that contain a binary number. These values can range from 0 to 255 (base 2 raised to 8 --the latter is the number of bits that compose a byte--).
Memory locations are referred to by number, known as an address.
A memory location can be used to record information such as a small number, data from a graphics image, part of a memory address, a program instruction, a numeric value representing a single letter(e.g. ASCII or lately Unicode).
Program instructions and data are stored in memory while a program is executing.

                Procedural Languages

Programs written in procedural languages involve a set of statements that are performed in sequence.
Third generation languages are languages that operate at the level of individual data items, “if” statements, loops and subroutines.
A large proportion of actual programs are written using third generation languages.


Data

Data Types

Basic data types include numeric values and strings.

A string is a short text item, and may contain information such as a name or a report heading.

Numeric data may be stored internally as a binary number, which is a distinct format from a set of individual digits stored in a text format.
Several numeric data types may be available.

These may include integer data types, floating point data types and other formats.
Integers are whole numbers and integer data types cannot record fractional numbers.
However, operations with integer data types are generally faster than operations with other numeric data types.
Floating point data types store the digits within a number separately from the magnitude, and can store widely varying values from smallest to huge.
Some languages also support a range of other numeric data types with varying range and precision.

Dates are supported as a separate date type in some languages.

A Boolean data type is a type that records only two values, “true” and “false”.
Boolean data types and boolean expressions are used in checking conditions and performing different actions in different circumstances.

The language COBOL is used in data processing. Data items within COBOL are effectively fields within database  records, and may contain a combination of text and numeric digits.
Individual positions within a data field in COBOL can be defined as holding an alphabetic, alphanumeric or numeric character. Calculations can be performed with numeric fields.

Data Type Conversion

Languages generally provide facilities for converting between data types, such as between two different numeric data types, or between numeric data in binary format and a text string of digits.
This may be done automatically within expressions, through the use of an operator symbol, or through a subroutine call.

When different numeric data types are mixed within an  expression, the value with the lower level of precision is generally promoted to the higher level of precision before the calculation is performed.
The details of type promotion vary with each language.

Variables

A variable is a data item used within a program, and identified by a variable name(identifier).
Variables may consist of fundamental data types such as strings and numeric data types, or a variable name may refer to multiple individual data items(e.g. array variable).

Variables can be used in expressions for calculations, and also for comparisons to perform different sections of code under different conditions.
The value of a variable can be changed using an assignment statement, which changes the value of a variable(on the left of assignment) to equal the value of an expression(on the right of assignment).

Constants

Constants such as fixed numbers and strings can be included directly within program code.
Constants can also be given a name, similar to a variable name, and used in several places with the program.
The value of a constant is fixed and cannot be changed without recompiling the program.

Data Structures

Variables can be defined as a collection of individual data items.
A structure type, also known as a record(or structure), is a collection of several different data items.
An array is a variable that contains multiple data items of the same type. Each item is referred to by number.Arrays can contain structures, and structures can contain arrays and other structures.
An object is an element of object oriented programs. An object is referred to by name and contains individual data items. Subroutines known as methods are also defined within an object.
Some languages support other data structures such as lists.


Pointers & References

A pointer is a variable that contains a reference to another variable. The second variable can be accessed indirectly by referring to the pointer variable.
Pointers are used to link data items together, when data structures are dynamically created as a program executes.
In some languages, pointers can be increased and decreased(pointer arithmetic) to scan through memory
and access different elements within an array, or individual bytes within a block of data.
A reference to a variable is also known as an address, and refers to the location of the variable in memory.
The value of a pointer variable can be set to the address of another data item by using a reference operator with the data item.
The data item that a pointer points to can be accessed by using a de-referencing operator.


Variable Scope

Individual variables can only be accessed within certain sections of a program.
 An independent copy of the local variables is created each time that a subroutine is called.
Where a local variable has the same name as a global variable, the name would refer to the variable with the tightest scope, which in that case would be the local variable(is said the local variable hides the global variable).

Parameters are data values or variables that are passed to a subroutine when it is called.
Parameters can be accessed from within the subroutine.
Some languages have multiple levels of scope. In these cases, subroutines may be defined within other subroutines, and variables may be defined within inner code blocks.
Variables within the current level of scope and outer levels of scope can be accessed, but not variables within an inner level of scope or in an independent part of the system.
Modules and objects may have public and private subroutines and variables.
Public variables are accessible outside the module, while private variables are only accessible within the module.
The use of global variables can lead to interactions between different parts of the code, which may make debugging and modifying the code more difficult.

Variable Lifetime

Global variables exist for the period of time that the program is running.
Local variables are created when a subroutine is called, and expire when the subroutine terminates.
Static variables may have a scope that applies within a single subroutine, however they have a lifetime that exists for the full period that the program is executing, and they retain their value from one call to the subroutine to the next.
Dynamically created data items exist until they are freed. Dynamic memory allocation involves creating data items while a program is running.
This may be done explicitly, or it may occur automatically when the last remaining variable that points to the item is assigned a different value, or expires as its level of scope terminates.


 Execution

Expressions

An expression is a combination of constants, variables and operators that is used to calculate a value.
An assignment operation involves a variable name and an expression. The expression is evaluated, and the value of the variable is changed to equal the result of the expression.
Expressions are also used within control flow statements such as “if” statements and loops.

Numeric expressions include the standard arithmetic operations of addition, subtraction, multiplication and division and exponentiation.

The basic string operations are concatenating two strings to form a single string, extracting a substring, and comparing strings.

String expressions may include constant strings(string literals), string variables, and operators such as a
concatenation operator.

Boolean variables and expressions have only two possible values, “true” and “false”.
An expression containing a relational operator, such as “<=”, is a Boolean expression. e.g. “5 < 3” has the value “false”.
The Boolean operators “and”, “or” and “not” can also be used in expressions.
An “and” expression has the value “true” when both parts are true, an “or” expression has the value “true” when either value is true, and a “not” expression reverses the value.
Boolean expressions are used within “if” statements to execute code under certain conditions and within loops to repeat a series of statements while a condition remains
true.


Statements

Assignment Statements

An assignment statement contains a variable name, an assignment symbol such as an “=” sign, and an expression.
The expression is evaluated, and the value of the variable is set to equal the result of the expression.
Some languages are expression- focused rather than statement-focused. In these languages, an assignment operation may itself be an expression, and may be used within other expressions.


Control Flow

If Statements

An “if” statement contains a Boolean expression and an associated block of code.
The expression is evaluated, and if the result is true then the statements within the block are executed, otherwise they are skipped.
An “if” statement may also have a block of code attached to an “else ” section. If the expression is false, then the code within the “else” section is executed, otherwise it is
skipped.


Loops

A loop statement may contain a Boolean expression. The expression is evaluated, and if it is true then the code within the block is executed. The control flow then returns to the beginning of the loop, and the cycle repeats the loop each time that the condition evaluates to true.

Other loop statements may also be available, such as statements that specify a fixed number of iterations(for), or statements that loop through all items in a language data structure(enhanced for).
 

Goto

Some languages support a “goto” statement. A goto statement causes a jump to a different point in the program to continue execution.
Code that uses goto statements can develop very complex control flow and may be very difficult to debug and modify.
Some languages also support structured goto operations, such as a statement that terminates the current loop mid-way through the loop code(break).
These operations do not complicate the control flow to the same extent as general goto statements, however these operations can be easily missed when code is being read.

For example, a statement in an early part of a complex loop may result in the loop being exited when it is executed.
This statement complicates the control flow and may make interpreting the loop code more difficult.

Exceptions

In some languages, exception handling subroutines and sections of code can be defined.
These code sections are automatically executed when an error occurs.


Subroutine Calls

Including the name of a subroutine within a statement causes the subroutine to be called. The subroutine name may be part of an expression, or it may be an individual
statement.

When the subroutine is called, program execution jumps to the beginning of the subroutine and execution continues at that point. When the code in the subroutine has been executed, or a termination statement(return) is performed, the subroutine terminates and execution returns to the next statement following the original subroutine call.


Subroutines

Subroutines are independent blocks of code that are referred to by name.
Programs are composed of a collection of subroutines.
When execution reaches a subroutine call the program execution jumps to the beginning of the subroutine.
Control flow returns to the point following the subroutine call when the subroutine terminates.

Subroutines may include parameters. These are variables that can be accessed within the subroutine. The value of the parameters is set by the calling code when the subroutine call is called.
Calling code can pass constant data values or variables as the parameters to a subroutine call.
Parameters are passed in various ways.
  • “Call-by-value” passes the value of the data to the subroutine. 
  • “Call-by-reference” passes a reference to the variable in the calling routine, and the subroutine can alter the value of a parameter variable within the calling routine.
Call by value leads to fewer unexpected effects in the calling routine, however returning more than one value from a subroutine may be difficult.
Subroutines may also contain local variables. These variables are accessible only within the subroutine, and are created each time that the subroutine is called.
In some languages, subroutines can also call themselves. This is known as recursion and does not erase the previous call to the subroutine. 
A new set of local variables is created, and further calls can be made.
This process is used for functions that involve branching to several points at each stage in a process. As each subroutine call terminates, execution returns to the previous level.


Comments
Comments are included within program code for the benefit of a human reader.
Comments are identified as separate text items, and are ignored when the program is compiled.
Comments are used to include additional information within the code that is relevant to a particular calculation or process, and to describe details of the function within a
complex section of code.


                    Declarative Languages
A declarative program defines structures and patterns, and may contain a set of information and facts.
In contrast, procedural code specifies a set of operations that are executed in sequence.
Declarative code is not executed directly, but is used as input to other processes.
For example, a declarative program may define a set of patterns, which is used by a parser to identify patterns and sub-patterns within a set of input data.
Other declarative systems use a set of facts to solve a problem that is presented.
Declarative languages are also used to define sets of items, such as records within data queries.

Declarative programs are very powerful in the operations that can be performed, in comparison to the size and complexity of the code.
For example, all possible programs can be compiled using a definition of the language grammar.
Also, a problem solving engine can solve all problems that fall within the scope of the information that has been provided.
Facts may include basic data, and may also specify that two things are equivalent.
For example:
x+ y= z* 2
Month30Days = April OR June OR September OR November

FieldName = 342-???-453

expression: number “+” expression
The first example is a mathematical statement that two expressions are equivalent,
the second example specifies that “Month30Days” is equal to a set of four months,
the third example matches the set of field names beginning with 342 and ending with 453,
and the fourth example specifies a pattern in a language grammar.

Patterns may be recursively defined, such as specifying that brackets within an expression may contain an entire expression, with potentially infinite levels of sub-expressions.

Declarative code may involve patterns, which have a fixed structure, and sets, which are unordered collections of items.


Code Structure

Declarative code may contain keywords, names, constants, operators and statements.

Keywords are language keywords that may be used to separate sections of the program and identify the type of information that is recorded.

The names may identify patterns, while the operators may be used to create a new pattern from other patterns.

Statements may be entered in the form of specifying that two expressions are equivalent.

The chain of connections is defined by the appearance of names within different statements. There is no order within a statement or from one statement to the next.


                           Other Languages

Programming languages appear in a wide variety of forms and structures.
In the language LISP, for example, all processing is performed with lists, and a LISP program consists of multiple brackets within brackets defining lists of data and
instructions.

Resources

The black art of programming by Mark McIlroy

Wednesday, October 10, 2018

Java Operators Precedence Rules

Advice: in case of dubt don’t confuse yourself or the reader of your program; use parentheses liberally.


If you use several operators in one expression, and if you don’t use parentheses to explicitly indicate the order of evaluation, then you have to worry about the precedence rules that determine the order of evaluation.

Here is a listing of the operators, listed in order from highest precedence (evaluated first) to lowest precedence (evaluated last):

Unary operators:  ++ --, !, unary -, unary +, type-cast
Multiplication and division: *,  /, %
Addition and subtraction: +, -
Relational operators: <, >, <=, >=
Equality and inequality: ==, !=
Boolean and:  &&
Boolean or:  ||
Conditional operator: ?:
Assignment operators: =, +=, -=, *=, /=, %=

Operators on the same line have the same precedence.
When operators of the same precedence are strung together in the absence of parentheses the rules of associativity are, unary operators and assignment operators are evaluated right-to-left, while the remaining operators are evaluated left-to-right. 
For example,
A*B/C means (A*B)/C, while
A=B=C means A=(B=C)
(Can you see how the expression A=B=C
might be useful, given that the value of B=C as an expression is the same as the value that is
assigned to B?)


Resources

Introduction to Programming Using Java - David J. Eck

Java Type Conversion

 Assignment = is really an operator in the sense that an
assignment can itself be used as an expression or as part of a more complex expression.
The value of an assignment such as A=B is the same as the value that is assigned to A. 
So, if you want to assign the value of B to A and test at the same time whether that value is zero, you could say:
if ( (A=B) == 0 )   // Usually don’t do things like that!

In general, the type of the expression on the right-hand side of an assignment statement must be the same as the type of the variable on the left-hand side.
However, in some cases, the computer will automatically convert(Implicit casting) the value computed by the expression to match the type of the variable.
Implicit casting(or promotion) happens when the source type has smaller range than the target type.


                      Numeric primitive casting

Consider the list of numeric types:
byte, short, int, long, float, double.
A value of a type that occurs earlier in this list can be converted automatically to a value that occurs later.
The idea is that conversion should only be done automatically(Implicit casting) when it can be done without changing the semantics of the value. 
//Implicit casting
byte byteVar = 42;
short shortVar = byteVar;
int intVar = shortVar;
long longVar = intvar;
float floatVar = longVar;
double doubleVar = floatVar;


char char1 = 1, char2 = 2;
short short1 = 1, short2 = 2;

// char1 = char1 + char2;  // Error: Cannot convert from int to char;
// short1 = short1 + short2; // Error: Cannot convert from int to short;



Any int can be converted to a double with the same numeric value. However, there are int values that lie outside the legal range of shorts.
There is simply no way to represent the int 100000 as a short, for example, since the largest value of
type short is 32767.
In some cases, you might want to force a conversion that wouldn’t be done automatically(Explicit casting). For this, you can use what is called a type cast.
Explicit casting has to be done when the source type has larger range than the target type.

 //Explicit casting
double doubleVar = 42.0d;
float floatVar = (float) doubleVar;
long longVar = (long) floatVar;
int intVar = (int) longVar;
short shortVar = (short) intVar;
byte byteVar = (byte) shortVar;


You can do type casts from any numeric type to any other numeric type.
However, you should note that you might change the numeric value of a number by type-casting it. 
For example, (short)100000 is -31072.
(The -31072 is obtained by taking the 4-byte int 100000 and throwing away two of those bytes to obtain a short—you’ve lost the real information that was in those two bytes.)
When you type-cast a real number to an integer, the fractional part is discarded. 
For example, (int)7.9453 is 7.
When casting floating point primitives (float, double) to whole number primitives, the number is rounded down.

As another example of type casts, consider the problem of getting a random integer between 1 and 6.
The function Math.random() gives a real number between 0.0 and 0.9999. . . 
and so 6*Math.random() is between 0.0 and 5.999. . . .
The type-cast operator, (int), can be used to convert this to an integer: (int)(6*Math.random()) is one of the integers 0, 1, 2, 3, 4, and 5..

To get a number between 1 and 6, we can add 1:
(int)(6*Math.random()) + 1”.
(The parentheses around 6*Math.random() are necessary because of precedence rules; without the parentheses, the type cast operator would apply only to the 6.)

              Non-numeric primitive casting

 The boolean type cannot be cast to/from any other primitive type.

int badInt = (int) true;  // Compiler error: incompatible types


 A char can be cast to/from any numeric type by using the code-point mappings specified by Unicode.
A char is represented in memory as an unsigned 16-bit integer value (2 bytes), so casting to byte (1 byte) will drop 8 of those bits (this is safe for ASCII characters). The utility methods of the Character class use int (4 bytes) to transfer to/from code-point values, but a short (2 bytes) would also suffice for storing a Unicode code-point.

The type char is almost an integer type. You can assign char values to int variables, and you can assign integer constants in the range 0 to 65535 to char variables.
You can also use explicit type-casts between char and the numeric types. 
For example,
(char)97 is ’a’,
(int)’+’ is 43, and
(char)(’A’ + 2) is ’C’.

char char1    =  (char) 65;  // A
byte byte1    =  (byte) 'A'; // 65
short short1  =  (short) 'A'; // 65
int int1          =  (int) 'A'; // 65


char char2 = (char) 8253; // ‽
byte byte2 = (byte) ' '; // 61 (truncated code-point into the ASCII range)
short short2 = (short) ' '; // 8253
int int2  = (int) ' '; // 8253


                           Object casting

As with primitives, objects can be cast both explicitly and implicitly.
Implicit casting happens when the source type extends or implements the target type (casting to a superclass or interface).
Explicit casting has to be done when the source type is extended or implemented by the target type (casting to a subtype). This can produce a runtime exception (ClassCastException) when the object being cast is not of the target type (or the target's subtype).
Float floatVar = new Float(42.0f);
Number n = floatVar;   //Implicit (Float implements Number)
Float floatVar2 = (Float) n;  //Explicit
Double doubleVar = (Double) n; //Throws exception (the object is not Double)

 

Testing if an object can be cast using instanceOf

Java provides the instanceOf operator to test if an object is of a certain type, or a subclass of that type. The program can then choose to cast or not cast that object accordingly.

Object obj = Calendar.getInstance();
long time = 0;
if(obj instanceOf Calendar) {
    time = ((Calendar)obj).getTime();
}
if(obj instanceOf Date) {  

    // This line will never be   reached, obj is not a Date type.
     time = ((Date)obj).getTime();
}


Type conversion between String and other types cannot be done with type-casts.
One way to convert a value of any type into a string is to concatenate it with an empty string.
For example,
"" + 42 is the string "42".
But a better way is to use a static member function in the String class aka the function String.valueOf(x): returns the value of x, converted into a string.
For example,
String.valueOf(42) is the string "42", and
if ch is a char variable, then String.valueOf(ch) is a string of length one containing the single character that is the value of ch.

It is also possible to convert certain strings into values of other types.
For example, the string "10" should be convertible into the int value 10, and the string "17.42e-2" into the double value 0.1742.
In Java, these conversions are handled by built-in functions.
The standard class Integer contains a static member function for converting from String to int.
In particular, if str is any expression of type String, then Integer.parseInt(str) is a function call that attempts to convert the value of str into a value of type int.
For example,
the value of Integer.parseInt("10") is the int value 10.
If the parameter to Integer.parseInt() does not represent a legal int value, then an error occurs.
Similarly, the standard class Double includes a function Double.parseDouble(str) .
If str is a String, then the function call Double.parseDouble(str) tries to convert str into a value of
type double.
An error occurs if str does not represent a legal double value.


Resources

Introduction to Programming Using Java - David J. Eck
 Java Notes for Professionals - Compiled from StackOverflow documentation (3.x)

Java and Relational Operators

These operators can be used to compare values of any of the numeric types.
They can also be used to compare values of type char. For characters, < and > are defined according the numeric Unicode values of the characters.
(This might not always be what you want. It is not the same as alphabetical order because all the upper case letters come before all the lower case letters.)
You can also assign boolean-valued expressions to boolean variables, just as you can assign numeric values to numeric variables. And functions can return boolean values.
By the way, the operators == and != can be used to compare boolean values too. This is occasionally useful. For example:

boolean sameSign;
sameSign = ( (x > 0) == (y > 0) );


One thing that you cannot do with the relational operators <, >, <=, and >= is to use them to compare values of type String.
You can legally use == and != to compare Strings, but because of peculiarities in the way objects behave, they might not give the results you want.
(The == operator checks whether two objects are stored in the same memory location, rather than whether they contain the same value. Occasionally, for some objects, you do want to make such a check—but rarely for strings.) 

Instead, you should compare strings using subroutines such as equals() and compareTo()

Another place where == and != don’t work as you would expect is with Double.NaN, the constant that represents an undefined value of type double.
The values of x == Double.NaN and x != Double.NaN are both defined to be false in all cases, whether or not x is Double.NaN! 
To test whether a real value x is the undefined value Double.NaN, use the boolean-valued function Double.isNaN(x).


Resources

Introduction to Programming Using Java - David J. Eck

Tuesday, September 18, 2018

SDKMAN aka installer and manager of parallel versions of multiple SDKs on Unix-based systems.

  The Software development kit Manager

SDKMAN! is a tool for managing parallel versions of multiple Software Development Kits on most Unix based systems. It provides a convenient Command Line Interface (CLI) and API for installing, switching, removing and listing Candidates. Formerly known as GVM (the Groovy enVironment Manager), it was inspired by the very useful RVM and rbenv tools, used at large by the Ruby community.

                           Java all the way down

Install Software Development Kits for the JVM such as Java,--> OpenJDK, Groovy, GroovyServ, Sshoogr, Infrastructor, VisualVM Scala, Kotlin, kscript and Ceylon. Ant, Gradle, Grails, Maven, sbt, Spark, Spring Boot, JBake, Glide, Vert.x, AsciidoctorJ, Bpipe, CRaSHCUBA CLI, CXF, Gaiden, Lazybones, Leiningen(Clojure), Micronaut, actually that's all i guess


First off all we have to "install it"
  $ curl -s "https://get.sdkman.io" | bash
That's it let's go to test it opening a shell and execute sdk

sometimes we get the red warning in picture (probably we're downloading heavily or our connection actually temporarily sucks ) because sdkman needs to be connected on the net to do his work
However sdkman can work also in offline mode most commands will still work even though they will operate in a scaled down capacity.

Usage of sdkman is simple and straightforward


Sunday, September 16, 2018

TDD with Objects

                                          A Web of Objects

Alan Kay’s (one of the authors of Smalltalk he also  coined the term “object-oriented.” ) concept of objects:
being similar to biological cells that send each other messages. 
Object-oriented design focuses more on the communication between objects than on the objects themselves. As Alan Kay wrote:
The big idea is “messaging” [...] The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.
An object communicates by messages:
It receives messages from other objects and reacts by sending messages to other objects as well as, perhaps, returning a value or exception to the original sender.

An object has a method of handling every type of message that it understands and, in most cases, encapsulates some internal state that it uses to coordinate its communication with other objects.

An object-oriented system is a web of collaborating objects.
A system is built by creating objects and plugging them together so that they can send messages to one another.
The behavior of the system depend of the composition of the objects—the choice of objects and how they are connected
This lets us change the behavior of the system by changing the composition of its objects (adding and removing instances, plugging different combinations together) rather than writing procedural code.
The code we write to manage this composition is a declarative definition of the how the web of objects will behave. It’s easier to change the system’s behavior because we can focus on what we want it to do, not how.


                                    Values and Objects

When designing a system, it’s important to distinguish between values that model unchanging quantities or measurements, and objects that have an identity, might change state over time, and model computational processes.

In the object-oriented languages that most of us use, the confusion is that both concepts are implemented by the same language construct: classes.

Values are immutable instances that model fixed quantities. They have no individual identity, so two value instances are effectively the same if they have the same state.
This means that it makes no sense to compare the identity of two values; doing so can cause some subtle bugs i.e. think of the different ways of comparing two copies of
    new Integer(999)
That’s why we’re taught to use
    string1.equals(string2)
in Java rather than
    string1 == string2

Objects, on the other hand, use mutable state to model their behavior over time. Two objects of the same type have separate identities even if they have exactly the same state now, because their states can diverge if they receive different messages in the future.
In practice, this means that we split our system into two “worlds”:
  1. values, which are treated functionally, 
  2. and objects, which implement the stateful behavior of the system.


                                      Follow the Messages

We can benefit from this high-level, declarative approach only if our objects are designed to be easily pluggable. In practice, this means that they follow common communication patterns and that the dependencies between them are made explicit.

A communication pattern is a set of rules that govern how a group of objects  talk to each other: the roles they play, what messages they can send and when, and so on.
In languages like Java, we identify object roles with (abstract) interfaces, rather than (concrete) classes—although interfaces don’t define everything we need to say.

In our view, the domain model is in these communication patterns, because they are what gives meaning to the universe of possible relationships between the objects.
Thinking of a system in terms of its dynamic, communication structure is a significant mental shift from the static classification that most of us learn when being introduced to objects. The domain model isn’t even obviously visible because the communication patterns are not explicitly represented in the programming languages we get to work with.
We hope to show how tests and mock objects help us see the communication between our objects more clearly.

Here’s a small example of how focusing on the communication between objects guides design.
In a video game, the objects in play might include:  
actors, such as the player and the enemies;  
scenery, which the player flies over;
obstacles, which the player can crash into; and
effects, such as explosions and smoke.
There are also scripts spawning objects behind the scenes as the game progresses.
This is a good classification of the game objects from the players’ point of view because it supports the decisions they need to make when playing the game —i.e. when interacting with the game from outside.
This is not, however, a useful classification for the implementers of the game. The game engine has to
display objects that are visible,
tell objects that are animated about the passing of time,
detect collisions between objects that are physical, and
delegate decisions about what to do when physical objects collide to collision detection resolvers.
The two views, one from the game engine and one from the implementation of the in-play objects, are not the same. The objects in the game play different roles depending on what the engine needs from them at the time.

This mismatch between static classification and dynamic communication means that we’re unlikely to come up with a tidy class hierarchy for the game objects that will also suit the needs of the engine.
At best, a class hierarchy represents one dimension of an application, providing a mechanism for sharing implementation details between objects; for example, we might have a base class to implement the common features of frame-based animation.
At worst, here's too many codebases (including our own) that suffer complexity and duplication from using one mechanism to represent multiple concepts.

Roles, Responsibilities, Collaborators
We try to think about objects in terms of roles, responsibilities, and collaborators, as best described by Wirfs-Brock and McKean . 
  1. An object is an implementation of one or more roles; 
  2. a role is a set of related responsibilities;
  3. and a responsibility is an obligation to perform a task or know information. 
  4. A collaboration is an interaction of objects or roles (or both).
Sometimes we step away from the keyboard and use an informal design technique that Wirfs-Brock and McKean describe, called CRC cards (Candidates, Responsibilities, Collaborators).
The idea is to use low-tech index cards to explore the potential object structure of an application, or a part of it. 
These index cards allow us to experiment with structure without getting stuck in detail or becoming too attached to an early solution.

                                   Tell, Don’t Ask

We have objects sending each other messages, so what do they say?
Our experience is that the calling object should describe what it wants in terms of the role that its neighbor plays, and let the called object decide how to make that happen.
This is commonly known as the “Tell, Don’t Ask” style or, more formally, the Law of Demeter. Objects make their decisions based only on the information they hold internally or that which came with the triggering message; they avoid navigating to other objects to make things happen.
Followed consistently, this style produces more flexible code because it’s easy to swap objects that play the same role.
The caller sees nothing of their internal structure or the structure of the rest of the system behind the role interface. We reduce the risk that a design change might cause ripples in remote parts of the codebase.
When we don’t follow the style, we can end up with what’s known as “train-wreck” code, where a series of getters is chained together like the carriages in a train.

As well as hiding information, there’s a more subtle benefit from “Tell, Don’t Ask.” It forces us to make explicit and so name the interactions between objects, rather than leaving them implicit in the chain of getters.


                                       But Sometimes Ask

Of course we don’t “tell” everything; we “ask” when getting information from values and collections, or when using a factory to create new objects. Occasionally, we also ask objects about their state when searching or filtering, but we still want to maintain expressiveness and avoid “train wrecks.”
We try to be sparing with queries on objects (as opposed to values) because they can allow information to “leak” out of the object, making the system a little bit more rigid.
At a minimum, we make a point of writing queries that describe
the intention of the calling object, not just the implementation.


                          Unit-Testing the Collaborating Objects

We appear to have painted ourselves into a corner. We’re insisting on focused objects that send commands to each other and don’t expose any way to query their state, so it looks like we have nothing available to assert in a unit test.

For example, assume an  object will send messages to one or more of its three neighbors when invoked. How can we test that it does so correctly without exposing any of its internal state?
One option is to replace the target object’s neighbors in a test with substitutes, or mock objects.
We can specify how we expect the target object to communicate with its mock neighbors for a triggering event; we call these specifications expectations.
During the test, the mock objects assert that they have been called as expected; they also implement any stubbed behavior needed to make the rest of the test work.
With this infrastructure in place, we can change the way we approach TDD.
So we’re just trying to test the target object and  we already know what its neighbors look like. In practice, however, those collaborators don’t need to exist when we’re writing a unit test.
We can use the test to help us tease out the supporting roles our object needs, defined as Java interfaces, and  fill in real implementations as we develop the rest of the system.
We call this interface discovery.


              Support for TDD with Mock Objects

To support this style of test-driven programming, we need to create mock instances of the neighboring objects,
define expectations on how they’re called and
then check them, and implement any stub behavior we need to get through the test.

We use the term mockery(this is a pun by Ivan Moore) for the object that
holds the context of a test,
creates mock objects, and
manages expectations and stubbing for the test.
The essential structure of a test is:
  • Create any required mock objects.
  • Create any real objects, including the target object.
  • Specify how you expect the mock objects to be called by the target object.
  • Call the triggering method(s) on the target object.
  • Assert that any resulting values are valid and that all the expected calls have been made.
The unit test makes explicit the relationship between the target
object and its environment. It creates all the objects in the cluster
and makes assertions about the interactions between the target object and its collaborators.
We can code this infrastructure by hand or, these days, use one of the multiple mock object frameworks that are available in many languages.

The important point is to make clear the intention of every test, distinguishing between
the tested functionality,
the supporting infrastructure, and
the object structure.

Resources

Growing Object-Oriented Software, Guided by Tests by
Steve Freeman, Nat Pryce

Monday, September 7, 2015

The IPOS Cycle

The IPOS cycle represents the four basic tasks of any computer:
  • input : Input is obtaining data from the outside world and delivering it to one or more components in the computer.
  • processing : Processing is the execution of one or more computer programs on the data. Processes can vary greatly in size, complexity, and function,  i.e. Processes will often perform mathematical operations, string operations, computer graphics, storage operations, and/or operating system activities.
  • output : Output is taking information stored in the computer and
    delivering it to the outside world, usually for humans to view.You might think of input as the raw data for a process and output as the results of the process.
  • storage : Storage is applied today to both data and program code. Storage usually refers to secondary storage, that is, the permanent placement of information on a device like a disk, but it can also refer to temporary storage in some form of memory such as main memory (RAM) or short-term storage such as registers and cache.
The IPOS cycle
 Although a computer will do all four of these, it is not necessarily the case that all four of them are done in this sequence. For instance, a program may require some input followed by processing followed by additional input followed by more processing.
Also, results from a process can either be output or stored in a file, thus omitting either output or storage.




Resources


Linux with Operating System Concepts by Richard Fox