Download presentation
Presentation is loading. Please wait.
1
The STREAM process – programming in practice
2
RHS – SOC 2 What are we trying to do? Tools Language Specifications Intellect Programs that work… HOW?
3
RHS – SOC 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
RHS – SOC 4 The ideal world ThinkUnderstand Code
5
RHS – SOC 5 The real world Think Understand Code Test
6
RHS – SOC 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
RHS – SOC 7 Stepwise refinement public class MyMainClass { public void solveProblem() { // Just add code here… }
8
RHS – SOC 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
RHS – SOC 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
RHS – SOC 10 Activity diagram Extension Refinement Restructuring The Goal You are here!
11
RHS – SOC 11 Stepwise refinement Extension Refinement Restructuring The Goal Now we understand the problem com- pletely, start coding!
12
RHS – SOC 12 Stepwise improvement Extension Refinement Restructuring The Goal
13
RHS – SOC 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
RHS – SOC 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 E.g a single Use Case
15
RHS – SOC 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
RHS – SOC 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
RHS – SOC 17 The STREAM process Stubs Test Representations Evaluation Attributes Methods
18
RHS – SOC 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
RHS – SOC 19 Stubs public class BankAccount { public void deposit() {} public void withdraw() {} public double getBalance() { return 0.0; }
20
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 24 Evaluation REM doubleString depositEasyAverage withdrawEasyAverage getBalanceTrivialEasy
25
RHS – SOC 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
RHS – SOC 26 Attributes public class BankAccount { double balance; public BankAccount() { balance = 0.0; } public void deposit() {} public void withdraw() {} public double getBalance() { return 0.0; } }
27
RHS – SOC 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
RHS – SOC 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
RHS – SOC 29 The mañana principle public 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 35 Date class – Stubs public class Date { public Date(int year, int month, int day) { } public void advanceToNextDate() { } public String toString() { return null; }
36
RHS – SOC 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
RHS – SOC 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
RHS – SOC 38 Date class – Evaluation REM StringMulti IntOne Int Date EasyTrivialHard advance… HardChallengingTrivial toString TrivialEasyHard
39
RHS – SOC 39 Date class – Attributes public 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
RHS – SOC 40 Date class – methods The only task left now is to implement the advanceToNextDate() method First attempt: public void advanceToNextDate() { date = date + 1; }
41
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 44 Date class – methods private void handleDayOverflow() { if (day > daysInMonth()) { day = 1; month = month +1; handleMonthOverflow() } } private int daysInMonth() { return 30; } private void handleMonthOverflow() {}
45
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 48 Smelly code… private void hDO() { if (d > dIM()) { d = 1; m++; hMO() } private int dIM() { return stdDiM; } Hmm, bad choice of names…?
49
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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
RHS – SOC 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)www.refactoring.com NetBeans offers some help in refactoring Best tools are experience and skill
53
RHS – SOC 53 Assignment Try to solve Programming Exercise P4.14 in Big Java (page 178) Follow the steps in the STREAM process when solving the exercise – make notes as you proceed When done, examine the code for any opportunities for restructuring of the code
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.