Advanced Software Development Practices Contents Module 1: Java Refresher................................................................................................................................................. 2 Module 2: Version Control ............................................................................................................................................... 5 Module 3: Association, Inheritance and Advanced Flow of Control .............................................................................. 8 Module 4: The Collections Framework Overview ........................................................................................................... 9 Module 5: Recursion ...................................................................................................................................................... 11 Module 1: Java Refresher Java Program Structure: Class Declaration: This line declares a class named MyClass. In Java, classes are the fundamental building blocks of programs. The keyword public indicates that this class is accessible by any other class. Class Body: Where the contents of the class are defined, including methods, variables, and other nested classes. Method Body: This where the code for method is stored. Method Header: “public static void main(String[] args)” defines the methods parameters. Reserved Words: Keywords that are predefined by the language and have special meaning. NOTE: These words cannot be used for naming variables, methods, classes, or other identifiers because they are part of the language syntax. Objects, Classes and Inheritance: Class: Blueprint for creating objects. It defines a datatype by bundling data and methods that work on the data into one single unit. Objects: An instance of a class. When a class is defined, no memory is allocated until an object of that class is created. Inheritance: It allows one class to inherit fields and methods from another class, promoting code reuse and establishing a natural hierarchical relationship between classes. Example: A Superclass (Parent class) methods and properties will be inherited by a Subclass (Child Class). The keyword “extends” establishes inheritance between classes (E.g. dog is inherited from the animal class). Variables, Expressions and Types: Character Strings: A string literal is represented by putting double quotes around the text Examples: "This is a string literal." NOTE: String concatenation “+” is used to mesh 2 different strings together Variable: A numerical value that is held in memory. A variable declaration specifies the variable's name and the type of information that it will hold NOTE: The assignment “=” statement is used to change the value or a variable (“total = 55) Constants: Similar to a variable that cannot be changed or modified. The compiler will issue an error if you try to change the value of a constant Characters: A char variable stores a single character. Character literals are delimited by single quotes NOTE: The difference between a primitive character variable, which holds only one character, and a String object, which can hold multiple characters. Boolean: A boolean value represents a true or false condition. The reserved words true and false are the only valid values for a Boolean type. NOTE: A boolean variable can also be used to represent any two states, such as a light bulb being on or off. Expressions: An expression is a combination of one or more operators and operands. Arithmetic expressions compute numeric results and make use of the arithmetic operators. NOTE: If either or both operands are floating point values, then the result is a floating-point value. Division and Remainder: If both operands to the division operator (/) are integers, the result is an integer (the fractional part is discarded) The remainder operator (%) returns the remainder after dividing the first operand by the second Assignment Operators: Casting: Casting is the most powerful, and dangerous, technique for conversion Both widening and narrowing conversions can be accomplished by explicitly casting a value To cast, the type is put in parentheses in front of the value being converted. Without the cast, the fractional part of the answer would be lost Classes and Objects: Generally, we use the new operator to create an object Creating an object is called instantiation An object is an instance of a particular class Invoking Methods: We've seen that once an object has been instantiated, we can use the dot operator “.” to invoke its methods. A method may return a value, which can be used in an assignment or expression. A method invocation can be thought of as asking an object to perform a service. String Indexes: The indexes begin at zero in each string. Example: In the string "Hello", the character 'H' is at index 0 and the 'o' is at index 4. The import Declaration: When you want to use a class from a package, you could use its fully qualified name. The toString Method: The toString method returns a character string that represents the object in some way It is called automatically when an object is concatenated to a string or when it is passed to the println method. Data Scope: The scope of data is the area in a program in which that data can be referenced (used) Data declared at the class level can be referenced by all methods in that class. Data declared within a method can be used only in that method. Data declared within a method is called local data. Visibility Modifiers: In Java, we accomplish encapsulation through the appropriate use of visibility modifiers. Java has three visibility modifiers: public, protected, and private. Accessors and Mutators: Because instance data is private, a class usually provides services to access and modify data values An accessor method returns the current value of a variable. A mutator method changes the value of a variable. The names of accessor and mutator methods take the form getX and setX, respectively, where X is the name of the value. NOTE: They are sometimes called “getters” and “setters” The return Statement: The return type of a method indicates the type of value that the method sends back to the calling location. A method that does not return a value has a void return type. A return statement specifies the value that will be returned. Parameters: When a method is called, the actual parameters in the invocation are copied into the formal parameters in the method header. Constructors: A constructor is used to set up an object when it is initially created. A constructor has the same name as the class. Conditional Statements: A conditional statement lets us choose which statement will be executed next. Boolean Expressions: Logical Operators: Is true is a and b are false. Is true if both a AND b are true. is true if a OR b OR both are true. The if Statement: Executes command if statement is true. An else clause can be added to an if statement to make an if-else statement. NOTE: A nested if statement executes as a result of an if or else clause could be another if statement. Comparing Strings: The equals method can be called with strings to determine if two strings contain exactly the same characters in the same order Repetition Statements: Repetition statements allow us to execute a statement multiple times. Often, they are referred to as loops. The while Statement: If the condition is true, the statement is executed. Then the condition is evaluated again, and if it is still true, the statement is executed again. The statement is executed repeatedly until the condition becomes false. NOTE: Nested if statements can be iterated within another loop. The switch Statement: Executes one statement from multiple conditions. Often a break statement is used as the last statement in each case's statement list Sometimes this may be appropriate, but often we want to execute only the statements associated with one case. The Conditional Operator: If the condition is true, expression1 is evaluated; if it is false, expression2 is evaluated. The do Statement: Executes a block of code at least once and then repeatedly executes the block as long as a given condition is true. The for Statement: Allows you to execute a block of code a specific number of times. It is commonly used when you know beforehand how many times you want to iterate through a block of code. NOTE: a For-each Loops is a variant of the for loop simplifies the repetitive processing of items in an iterator. Arrays: A particular value in an array is referenced using the array name followed by the index in brackets. Declaring Arrays: The type of the variable scores is int[] (an array of integers) The reference variable scores are set to a new array object that can hold 10 integers. Initializer Lists: An initializer list can be used to instantiate and fill an array in one step. The values are delimited by braces and separated by commas. Module 2: Version Control What is Version Control? Version Control is a system that manages and tracks changes to computer files, including documents, source code, and other data. It helps developers and teams collaborate by keeping a detailed history of modifications, allowing for easy retrieval of previous versions, and facilitating the merging of changes from multiple contributors. Revision Control: Management of changes to documents, source code or other information stored as computer files. A Version Control System (VCS) is a software tools designed to support revision control. Motivation: Individual Usage Example: You’re trying to improve something quickly, so you make a fast change to your library. After many attempts, your project is worse off than when you started. Proper use of VCS can prevent scenarios by allowing you to easily revert to a previous, stable version of your work. The "I'll Roll My Own" Approach Example: You might create backup files like Prac01NoIdea.java. It becomes unclear what each file contains, and which is the correct version. VCS provides a clear, organized history of changes, eliminating the need for confusing file naming and manual backups. Team Usage Example: A new team member makes a change that disrupts the project. An experienced member makes a significant improvement. Others don’t know exactly what was changed. With VCS If something breaks, you can quickly revert to a previous version. Also, you can easily see and understand the differences between versions. NOTE: VCS provide centralized storage, easy access to the latest versions, and tools for reviewing changes. Version Control Systems: Constantly used in software engineering (e.g. while working with documents, during software development). Changes are identified with an increment of the serial number (“version number”, e.g. 1.0, 2.0, 2.17). Version numbers are historically linked with the person who created them. NOTE: A change log is a detailed record of all changes made to a project over time. Terminology: Repository: A server that stores the files (documents) (Keeps a change log). Revision, Version: Individual version (state) of a document that is a result of multiple changes Check-out: Retrieves a working copy of the files from the repository into a local directory. Change: A modification to a local file (document) that is under version control. Change List: A set of changes to multiple files that are going to be committed at the same time Commit, Check-in: Applying the changes made on the working copy to the files in the repository (Automatically creates a new version). Conflict: The simultaneous change to a file by multiple users. Update, Get Latest Version: Checking-out the changed files from the repository to a local directory. Undo Check-out: Cancels the changes to a group of files, restores their state from the repository. Merge: Combining the changes to a file simultaneously made by different users. Trunk: The unique line of development that is not a branch Label, Tag: Labels mark with a name a group of files in a given version, e.g. a release Branching: Division of the repositories in a number of separate workflow Client Server Example: Typical Client Server System: NEED THIS EXPLAINED Versioning Models: Lock - Modify – Unlock: Only one user works on a given file at a time -> no conflicts. Problems: Someone locks a given file and forgets about it. Time is lost while waiting for someone to release a file. Unneeded locking of the whole file. Copy - Modify – Merge: Users make parallel changes to their own working copies. The parallel changes are merged, and the final version emerges. Problems: If a given file is concurrently modified, it is necessary to merge the changes (Merging is hard!). It is not always possible to do it automatically. Responsibility and coordination between the developers is needed. Subversion (SVN) Overview: What is Subversion (SVN)? Subversion is an open-source version control system used to manage changes to files and directories over time. Where Can It Run? SVN can run on various operating systems including UNIX, Linux, and Windows. Repository: File-based database called the SVN repository. Contains all historic data about your project. Developers work from a sandbox which contains working copies of the files in your project. Changes from a sandbox are committed to the repository. Changes in the repository, but not in your sandbox, are updated from the repository. Module 3: Association, Inheritance and Advanced Flow of Control Key Concepts: Inheritance supports software reuse. New classes can be derived from existing classes. Derived classes can add or modify variables and methods. Derivation can be used to build class hierarchies. NOTE: In object-oriented programming, defining class relationships is crucial for structuring a program effectively. Two principal types of class relationships are association and inheritance. Inheritance: Allows a class to inherit properties and behaviours (methods) from another class. To create a subclass in Java, you use the extends keyword. NOTE: Inheritance provides flexible reuse of code. “Is-A Relationship: This is a fundamental concept in inheritance. It means that an object of the subclass (child) is also an object of the superclass (parent). For example: If Student extends Person, then a Student is a Person. This reflects that all properties and behaviours of a Person are applicable to a Student, but a Student can have additional properties and behaviours unique to them. Visibility: the protected Modifier: Public: All classes (including derived classes) can access public methods and variables. Private: Private methods and variables are only accessible within the class where they are defined. They are not inherited by derived classes, which means they cannot be accessed directly by subclasses. Protected: The protected modifier allows access to methods and variables within the same package and to derived classes, even if they are in different packages. The super Reference: To maximise code reuse, the parent class constructor can be called from the child class constructor to initialise the inherited variables. The parent class is called by the name super(). NOTE: For overriding methods Often a derived class needs to modify (rather than extend) the behaviour of the parent class. No special syntax required. Class Hierarchy: A parent class can have more than one child class. For example: Student and Employee classes derived from Person. A child class can itself be a parent of another class. For example: PostGradStudent derived from Student. This allows class hierarchies to be formed. Association: Association is a relationship where one class uses or is connected to another class. It represents "has-a" relationships. Unlike inheritance, association does not imply a hierarchy but rather a usage relationship. Module 4: The Collections Framework Overview The collections framework is a unified architecture for representing and manipulating collections, allowing them to be manipulated independently of the details of their representation. The framework is based on nine collection interfaces. Why use the collection framework? It reduces programming effort while increasing performance. Code faster and more efficiently Collections design and implementation focuses on reuse. java package: java.util.* Set Interface: Only one instance of each object (no duplicates, adding a duplicate has no effect). Implemented by: HashSet Class: A collection of items where every item is unique For sets where fast search/access is important Based on a hash table TreeSet Class: Objects are stored in a sorted and ascending order. Based on a TreeMap List Interface: Ordered - elements kept in a sequence. May contain duplicate elements. Has methods to insert/remove elements to/from a list at index: set(index,e), get(index), remove(index) NOTE: A ListIterator can be used to traverse the List in both directions. Previous() is appropriate Aan adds method to insert at current position. ArrayList Class: A List implemented with an array. Like a normal array except it can grow and shrink as needed Fast random element access. Slow insertion/removal. NOTE: ArrayList, is similar to an array, but normal arrays can’t be changed after being declared, an ArrayList can! LinkedList Class: Uses a sequence of linked nodes. Each node stores a value and a reference to the next node in the sequence Slow random element access Speedy insertion/removal. ArrayList vs LinkedList The ArrayList class has a regular array inside it. When an element is added, it is placed into the array. If the array is not big enough, a new, larger array is created to replace the old one and the old one is removed. The LinkedList stores its items in "containers." The list has a link to the first container and each container has a link to the next container in the list. To add an element to the list, the element is placed into a new container and that container is linked to one of the other containers in the list. When to Use: Use an ArrayList for storing and accessing data, and LinkedList to manipulate data. LinkedList has more methods to change or manipulate data. Stacks: A stack is a linear collection whose elements are added and removed from the same end Stacks are processed in a last in, first out (LIFO) manner Usually, stacks are depicted vertically, and we refer to the top of the stack as the end to which elements are added and removed. Stack Operations: Implementing Stacks with Arrays: Using an array is an efficient and straightforward solution to implement a stack. Given that all activity on a stack occurs at one end, fixing the bottom of the stack at array index 0 makes the implementation relatively easy. In addition, we’ll also need an integer variable to indicate: The number of elements that are currently on the stack, and To represent the index in the array where the next item pushed onto the stack will be stored. Our array-based version of a stack will be located in a class named ArrayStack. Implementing Stacks with Links: An alternate implementation can use a linked structure to represent the stack. Because a stack is a linear structure, the elements of a stack can be maintained using a linked list. We’ll reuse the LinearNode class from earlier in this module to implement the nodes of the list. An integer variable called count is used again to keep track of the number of elements currently in the stack. Queues: A queue is a linear collection whose elements are added on one end and removed from the other. We say that queue elements are processed in a first in, first out (FIFO) manner. Elements are removed from the queue in the same order in which they are placed on the queue. Queue Operations: Module 5: Recursion What is Recursion? Recursion is the process in which a function calls itself directly or indirectly. Recursion is often used to break down complex problems into smaller, more manageable problems. The code of a recursive method must be structured to handle both the base case and the recursive case. Key Concepts in Recursion: Base Case: The condition under which the recursion stops. It prevents the method from calling itself indefinitely. Recursive Case: The part of the method where the method calls itself with a simpler or smaller input. Example of Recursion in Java: Factorials A classic example of recursion is calculating the factorial of a number. The factorial of a number n (denoted as n!) is the product of all positive integers less than or equal to n. Example: 5! (5 factorial) is equal to 5 * 4 * 3 * 2 * 1. Recursion vs Iteration: Just because we can use recursion to solve a problem, doesn't mean we should. Everything that can be done with recursion can also be done with iteration (loops). You must be able to determine when recursion is the correct technique to use NOTE: Recursion can be more confusing than iteration - why use it? – FOR SOME PROBLEMS the recursive solution is simpler. Direct and Indirect Recursion: Direct recursion occurs when a method calls itself directly. The method includes a call to itself within its body, and this is the most straightforward form of recursion (e.g. the example seen above for factorial). Indirect recursion occurs when a method calls another method, which in turn calls the first method (or another method that eventually leads back to the first method). This creates a chain of method calls that eventually leads back to the original method. How to Write Recursive Methods: 1. Start with the algorithm - Determine whether the problem can be broken down into smaller subproblems that resemble the original problem. 2. Each recursive method must have a base case that does not involve a recursive call. 3. The condition for the base case must be checked before the recursive call is made. 4. Each time a recursive call is made, it should be closer to the base case than the previous call.