the stream process – programming in practice
DESCRIPTION
The STREAM process – programming in practice. What are we trying to do?. Tools Language Specifications Intellect. Programs that work…. HOW?. The programming process. What elements are involved in writing a (correct) program? In the ideal world: - PowerPoint PPT PresentationTRANSCRIPT
The STREAM process –
programming in practice
2
What are we trying to do?
ToolsLanguage
SpecificationsIntellect
Programsthat
work…HOW?
3
The programming process
• What elements are involved in writing a (correct) program?
• In the ideal world:– Understand – read the specification until you are
sure you understand it completely– Think – now think hard about how to solve the
program– Code – now write the program!
• A simple, linear process…but it does not work that way in real life
4
The ideal world
ThinkUnderstand Code
5
The real world
Think
Understand
Code
Test
6
How to get started
• We will not address the problem of understanding – and develop-ing – the specification here (Software Design)
• Given a reasonable under-standing of the problem to solve, how do we get started at all?
• The traditional approach is stepwise refinement
7
Stepwise refinement
public class MyMainClass
{
public void solveProblem()
{
// Just add code here…
}
}
8
Stepwise refinement
• From this point, simply break down the problem into smaller and smaller pieces
• Code evolves from being abstract to becoming concrete
• Not a bad strategy, but still too naive– Assumes perfect knowledge of problem– Still a linear process
• A more realistic process is stepwise improvement
9
Stepwise improvement
• The Stepwise improvement process adds two more activities to the Refinement process
• Extension: we extend the code to cover more of the specification – for instance include an additional case
• Restructuring: we change the structure of the code, without changing the functionality of the code
10
Activity diagram
Extension
Refinement
Restructuring
The Goal
You are here!
11
Stepwise refinement
Extension
Refinement
Restructuring
The Goal
Now we understand the problem com-pletely, start coding!
12
Stepwise improvement
Extension
Refinement
Restructuring
The Goal
13
Embrace change…
• Is Stepwise Improvement completely chaotic!?• No, but it can appear confusing • There is no given order of the three types of
activities, they can ”happen” at any time during program development
• Notice, however, that they are separate activities• We can provide advice about how to perform
each activity
14
Extension
• In real life, a full specification is often very large, hard to under-stand, incomplete and ambiguous
• Does not really make sense to try to make a complete program in one attempt
• Instead, select a part of the functionality, and make it work
15
Extension
• Once the selected part of the specification works, we can proceed to including more parts of the specification
• Before that, we may possibly do some refinement and restructuring
• The specification itself might change as well…
16
Refinement
• In this activity, we try to actually implement some part of the specification
• This activity only involves programming• Do not try to be too clever here!• Refinement is complicated enough in itself• The STREAM process is a simplified process for
the refinement activity
17
The STREAM process
• Stubs
• Test
• Representations
• Evaluation
• Attributes
• Methods
18
Stubs
• What are ”stubs” – methods which do not yet have code inside them
• We assume that at this point, we are about to implement some well-known classes
• Well-known: The expected behavior of the classes is known
• We should be able to figure out the public interface to the classes
19
Stubs
public class BankAccount
{
public void deposit() {}
public void withdraw() {}
public double getBalance()
{
return 0.0;
}
}
20
Stubs
• We can create classes with stub methods for all classes under consideration
• Our program will compile…but do nothing
• This state of a program is often called a walking skeleton
21
Test
• We assume we fully understand the classes under consideration
• We should thus be able to write test cases for them, before proceeding further
• Gives us a clear target – once the program passes our tests, we are done with the activity
• Usual considerations about test still apply…
22
Representation
• During the ”stub” part, we did not pay any attention to data representation
• Data representation is not part of the public interface
• Need to make a choice, however…• Think about alternatives for represen-
tation – you should come up with at least two alternatives
23
Evaluation
• Given some alternatives for representation, we must now evaluate them
• Evaluate: How hard will it be to implement the methods in the public interface, given that we use some specific representation
• Will of course be a subjective evaluation• Evaluate each representation alternative for
each public method• REM: Representation Evaluation Matrix
24
Evaluation
REM double String
deposit Easy Average
withdraw Easy Average
getBalance Trivial Easy
25
Attributes
• Now we have chosen a representation for our data, so implement the representation
• That is:– Define instance fields– Set proper values in class constructors
• This does not mean that we are done with representation – we may need more instance fields when implementing methods
• Can still use REM
26
Attributespublic class BankAccount{
double balance;
public BankAccount(){
balance = 0.0;}public void deposit() {}public void withdraw() {}public double getBalance(){
return 0.0;}
}
27
Methods
• All that remains now is to fill in the code in the public methods…
• …but that is also the hardest part!• In a sense, we try to re-apply
parts of the STREAM steps when implementing a method
• We have a set of method implementation rules to assist us during implementation
28
Methods
• Again, the guiding principle is to manage the complexity, by breaking problems into smaller, more manageable pieces
• In practice – push your problems ahead of you!• Keep method implementations simple, by
inventing new methods as you go along• Implement the new methods as stubs, and
return to them later on• The mañana principle (or the Good Fairy)
29
The mañana principlepublic void convertFromInchesToCm(){
double inches = getInchesFromUser();double cm = calculateCmFromInches(inches);presentCmToUser(cm);
}
private double getInchesFromUser() {
return 0.0;}private double calculateCmFromInches(double inches) {
return 0.0;}private void presentCmToUser(double cm) {}
30
The mañana principle
• When to use the mañana principle– Special case: Move implementation of a special case
to a separate method– Nested loop: If you have a nested loop, move the
inner loop to a separate method– Hard problem: If you need the answer to a problem
that you cannot immediately solve, make it a separate method
– Heavy functionality: If a sequence of statements or an expression becomes long or complicated, move some of it into a separate method
31
Methods
• The mañana principle is not a rule, but a principle – apply when necessary
• The ”threshold” for when to apply it is individual• Rule-of-thumb: Methods which cannot fit into a
single screen are too long, and should be divided into more methods
• Remember we still have the test cases to guide us – when the tests are passed, we are done
32
Keeping the compiler happy
• This is a very practical advice • Compilers try to find all errors in
the code, but often get it wrong…• Error messages from the compiler
can be quite confusing• Only try to fix those errors which
make sense• Fortunately, compilation is fast!
33
Keeping the compiler happy
• Compile often!• Try to keep the program free of
syntax errors at all times• Fix errors immediately• If the compiler only reports one or
a few errors, they are much easier to fix
• Error(s) must be in the code you have just entered…
34
Example: a Date class
• We are given the task of implementing a Date class, specified as follows:– The Date class represents a date, given by year,
month number and day number– When created, a Date object is initialised with a year,
month and day (it can be assumed that the input data always represents a valid date)
– It must be possible to advance the date in a Date object to the next valid date
– It must be possible to retrieve the data as a String
35
Date class – Stubspublic class Date{
public Date(int year, int month, int day){}public void advanceToNextDate(){}public String toString(){
return null;}
}
36
Date class – Test
• We will not detail this now, but there are actually a lot of cases to test– Simple advance of date– Advance of date across month– Advance of date across year– Leap years– …etc.
• But we can just write up the test cases, without worrying about implementation
37
Date class – Representation
• What are possible – and reasonable – represen-tations of a date?– String – we need to get it back as a String– Multiple integers – one for day, one for month and
one for year– One integer – days since Jan 1st, 0001
• We evaluate the alternatives using the REM (Representation Evaluation Matrix)
38
Date class – Evaluation
REM String Multi Int One Int
Date Easy Trivial Hard
advance… Hard Challenging Trivial
toString Trivial Easy Hard
39
Date class – Attributespublic class Date{
private int year;private int month;private int day;
public Date(int year, int month, int day){
this.year = year;this.month = month;this.day = day;
}public void advanceToNextDate(){}public String toString(){
return year + ”-” + month + ”-” day;}
}
40
Date class – methods
• The only task left now is to implement the advanceToNextDate() method
• First attempt:
public void advanceToNextDate()
{
date = date + 1;
}
41
Date class – methods• A little naive, but actually works in 97 % of all
cases • We do need to handle special cases• Next attempt:
public void advanceToNextDate()
{
date = date +1;
handleDayOverflow();
}
42
Date class – methods• Now advanceToNextDate() is done, assuming
that handleDayOverflow()works!• The mañana principle at work!• Now on to handleDayOverflow()
private void handleDayOverflow()
{
if (day > 30)
{
day = 1;
month = month + 1;
}
}
43
Date class – methods• This will work, except for two situations
– Month does not have 30 days– Across a new year
• Once again, we fix this by inventing some new methods and implement them later:– daysInMonth()– handleMonthOverflow()
44
Date class – methodsprivate void handleDayOverflow()
{
if (day > daysInMonth())
{
day = 1;
month = month +1;
handleMonthOverflow()
}
}
private int daysInMonth()
{
return 30;
}
private void handleMonthOverflow() {}
45
Date class – methods• And we just keep going like this…• The final implementation will – of course –
handle all cases correctly, including leap years• Manage the complexity – only try to solve one
problem at a time!• Do not think too much about whether or not the
code is optimally structured – this is adressed during the restructuring activity
46
Restructuring
• During a refinement activity, focus is on achieving functionality
• Should not be too concerned with code structure
• During a restructuring activity, we restructure code but preserve functionality
• Easy to forget/neglect this activity in real life…
47
Restructuring
• How do I know what to restructure…?
• Not an easy task, requires some experience
• You have to develop an ability to ”smell bad code”
• What does bad code smell like?
48
Smelly code…
private void hDO(){
if (d > dIM()){
d = 1;m++;hMO()
}}
private int dIM(){
return stdDiM;}
Hmm, bad choice of names…?
49
Restructuring
• It could be as simple as that…• In the heat of the fight, we might have chosen
names which are ”non-informative”• Similar ”clean-up” activities could be:
– Non-consistent naming– Replace magic numbers with constants– Fixing alignments– Eliminate unused parameters
• Remember, no change in functionality!
50
Smelly code…public void printWorkerInfo(Employee worker)
{
System.out.println(”Worker information”);
System.out.println(”-------------------------”);
System.out.println(worker.GetName());
System.out.println(worker.GetAddress());
}
public void printManagerInfo(Employee manager)
{
System.out.println(”Manager information”);
System.out.println(”-------------------------”);
System.out.println(manager.GetName());
System.out.println(manager.GetAddress());
}
51
Nice, clean code…public void printWorkerInfo(Employee worker)
{
printEmployeeInfo(worker, ”Worker information”);
}
public void printManagerInfo(Employee manager)
{
printEmployeeInfo(manager, ”Manager information”);
}
public void printEmployeeInfo(Employee person, String header)
{
System.out.println(header);
System.out.println(”------------------------”);
System.out.println(person.GetName());
System.out.println(person.GetAddress());
}
52
Restructuring
• Restructuring works on several levels– Inside methods– Among methods, inside classes– Among classes
• Restructuring is often referred to as refactoring, an important – and fairly large – topic in itself (www.refactoring.com)
• Best tools are experience and skill