1.13k likes | 1.36k Vues
Software engineering. Lecture 1 – Software development processes. Table of Contents. Part I: Tools for Your OO Toolbox Sample Application: Book Inventory Basics of Well Designed Applications Development Approaches Applying Practices, Principles and Patterns
E N D
Software engineering Lecture 1 – Software development processes
Table of Contents Part I: Tools for Your OO Toolbox • Sample Application: Book Inventory • Basics of Well Designed Applications • Development Approaches • Applying Practices, Principles and Patterns Part II: Agile Model Driven Development • AMDD Lifecycle • Sample Application: Second Hand Store • Initial Modeling • Development Iterations
1 Sample Application: Book Inventory John Doe, the owner of a small second hand store decided to throw out his paper-based system for keeping track of books, and start using a computer based system to store its inventory. John required a search tool to match the customers need for books. John hired a computer programming firm, Direct Coding, to build a prototype for book inventory management.
2 Basics of Well Designed Applications 2.1 A First, Misguided Solution 2.2 Analyzing the First Solution 2.3 Add Tools to Your OO Toolbox
2.1 A First, Misguided Solution Direct Coding built a prototype for book inventory management. Direct Coding programmers proceeded as follows: • they started from requirements, • built a simple UML model, then • they directlyimplemented their model. Finally, Direct Coding delegated a programmer to present a prototype of the Book Inventory: • John Doe’s acceptance test • Preparing the prototype • Presenting the results
A. Requirements Analysis The programmers extracted from John Doe’s requirements the following requirements list: • the second hand store has a book repository composed of many books. • a search tool is required to match the customers need for books. Because the programmers know a lot about books they considered it is clear what they have to do.
B. Design This class represents the entire second hand’s book repository Here, the most expected method that returns book information Method used to add books to John’s second hand repository Each book is represen-ted as an instance of this class A unique book number is assigned to each new book Attributes used to search for books
C. Implementation (Book) Other fields and their corresponding getters not shown here to save space... public class Book { private int bookNumber; ... public int getBookNumber() { return bookNumber; } ... public Book(int bookNumber, String isbn, String authors, String title,String publisher, int year, double price) { this.bookNumber = bookNumber; ... } public String toString() { return authors + title + publisher + year; } } Other field initializations also not shown...
C. Implementation(BookRepository) All books represented here import java.util.ArrayList; import java.util.List; public class BookRepository { private List<Book> books; public BookRepository() { books = new ArrayList<Book>(); } public void add(String isbn, String authors, String title, String publisher, int year, double price) { Book book = new Book(books.size(), isbn, authors, title, publisher, year, price); books.add(book); } //...
C. Implementation (BookRepository) All searching attributes can be left null or empty. public Book findBook(Book searchBook) { for(Book book: books) { //we ignore bookNumber and price attributes String isbn = searchBook.getIsbn(); if ( (isbn != null) && (!isbn.equals("")) && (!isbn.equals(book.getIsbn())) ) continue; String authors = searchBook.getAuthors(); if ((authors!=null) && (!authors.equals("")) && (!authors.equals(book.getAuthors()))) continue; String title = searchBook.getTitle(); if ( (title != null) && (!title.equals("")) && (!title.equals(book.getTitle())) ) continue; String publisher = searchBook.getPublisher(); if ((publisher != null) && (!publisher.equals("")) && (!publisher.equals(book.getPublisher())) ) continue; float year = searchBook.getYear(); if ( (year != 0) && (year != book.getYear()) ) continue; } return null; } } //end of BookRepository nulls and empty values satisfies the criteria, so if the non-empty values do not match the book values we continue
D. Customer Acceptance Test John Doe: • Could you show me please how can I use the application in order to find “Implementation Pattern” books written by “Kent Beck”? Direct Coding enthusiastic representative: • (He expects to obtain possible more than one book...) • Give me please a couple of minutes to prepare a short test...
E. Acceptance Test Implementation (TestBookRepository) Looking for books that have a given author and title. public class TestBookRepository { public static void main(String[] args) { BookRepository repository = new BookRepository(); initializeRepository(repository); Book bookSpecRequired = new Book(0, "", "Kent Beck", "Implementation Patterns", "", 0, 0); Book book = repository.findBook(bookSpecRequired); if (book != null) { System.out.println("You might like this book: " + book); } else { System.out.println("Sorry, we have nothing for you."); } } private static void initializeRepository(BookRepository bookRepository) { bookRepository.add("0321413091", "Kent Beck", "Implementation Patterns", "Addison-Wesley", 2006, 12.5); // other books could also be added } } Other attributes left empty Particular book repository prepared for John Doe’s requirements
F. Acceptance Test Result... • Running the test • John Doe is a little bit disappointed • What goes wrong? • What’s the first thing they should change?
2.2 Analyzing the First Solution • How do we write great software, every time? • Customer-friendly programmer says: • Great software does what the customer wants it to. • OO programmer says: • Great software is object-oriented, not a bunch of duplicate code. • The code should be easily to extend. • Design-guru programmer says: • Great software is when you use tried-and-true design patterns and principles.
A. Great Software in Three Easy Steps Don’t create problems to solve problems. Apply good OO programming techniques (e.g. eliminate duplicate code, etc) Apply good OO principles and patterns to ensure your application is ready to use for years to come.
B. What’s Wrong with Their Requirements? • An extract from the initial John’s requirements: • “We need a search tool to match the customer needs for books.” • But, Direct Coding representative did not investigated what the customer wants. • Now they understand that “the search result should return a list of books.” Modification needed here. The method must return a list of books.
C. What’s Wrong with Their Model? The test class was created after writing the code for search. The findmethod was not tested before presenting the solution. Book class is responsible for spec attributes and also for holding the price (Violates Single Responsibility Principle). Book specification is not encapsulated. A change request, “add a new book spec attribute”, would affect all classes. Authors and publishers are not strings in the real world! They are entities, so they should be designed as classes.
D. What’s Wrong with Their Code? Bad smell... A lot of duplicated code... public Book findBook(Book searchBook) { for(Book book: books) { //we ignore bookNumber and price attributes String isbn = searchBook.getIsbn(); if ( (isbn != null) && (!isbn.equals("")) && (!isbn.equals(book.getIsbn())) ) continue; String authors = searchBook.getAuthors(); if ((authors!=null) && (!authors.equals("")) && (!authors.equals(book.getAuthors()))) continue; String title = searchBook.getTitle(); if ( (title != null) && (!title.equals("")) && (!title.equals(book.getTitle())) ) continue; String publisher = searchBook.getPublisher(); if ((publisher != null) && (!publisher.equals("")) && (!publisher.equals(book.getPublisher())) ) continue; float year = searchBook.getYear(); if ( (year != 0) && (year != book.getYear()) ) continue; } return null; }
2.3 Add Tools to Your OO Toolbox Approaches to building, deploying, and possible maintaining software. What tasks/steps could be taken? In which order? Good ideas to adopt, collected from several development approaches. • Development Approaches Guidelines to consider while performing these activities, common to almost all development approaches. • Practices • Requirements • OO Principles • Analysis & Design • Implementation • Design Patterns A design pattern is a general repeatable solution to a commonly occurring problem in software design. A design principle is a basic tool or technique that can be applied to designing or writing code to make that code more maintainable, flexible, or extensible.
3 Development Approaches 3.1 Requirements, Practices, and Development Approaches 3.2 Introduction to Agile Model Driven Development (AMDD) 3.3 Introduction to Test Driven Development (TDD)
3.1 Requirements, Practices, and Development Approaches Evans, 2004 Practices Developers (who know how to build) and domain experts (who know the domain) should have a close relationship. Model in small increments – organize a larger effort into smaller portions that you release over time (incremental development). Requirements Good requirements ensure your system works like your customers expect. Capture the lists of features your software is supposed to do. Development Approaches Feature Driven Development – focuses on a single feature, and codes all the behavior of that feature, before moving on to anything else in the application. Palmer, 2002 Ambler, 2004
3.1 Requirements, Practices, and Development Approaches (cont) • A feature is a small, client-valued function expressed in the form • <action> <result> <object>, and • typically can be implemented within a few hours. • Example: • Add a book to the book repository. • But customers prefer long lists of features to be organized in feature sets • Example: • Administering, Searching Ambler, 2004 In order to be easy to make estimates!
3.1 Requirements, Practices, and Development Approaches (cont) Book Inventory Features: • Administering • Adda new book to book repository • Searching • Listthe books that satisfy a given book specification criteria. • List the authors that have registered books into the second-hand store. • Listthe publishers that have registered books into the second hand store. Model in small increments: • 1.a), 2.b), 3.a), etc Feature sets Model, and code this feature Then, model, and code this one
3.2 Introduction to Agile Model Driven Development (AMDD) Practices Developers (who know how to build) and domain experts (who know the domain) should have a close relationship. Model in small increments – organize a larger effort into smaller portions that you release over time (incremental development). Requirements Good requirements ensure your system works like your customers expect. Capture the lists of features your software is supposed to do. Development Approaches Feature driven development – focuses on a single feature, and codes all the behavior of that feature, before moving on to anything else in the application. Agile Model Driven Development – focuses on creating just barely good enough models (agile models) before writing the source code.
3.2 AMDD (cont)AMDD Development Lifecycle Each iteration focuses to model, and code a subset of the system requirements (e.g. feature 1.a, “add a book to the repository”) Activity Sub activity The system grows, incrementally The result of each iteration is an executable.
3.2 AMDD (cont)Analysis and Design: Attributes vs. Classes • Example – a “barely” good enough model for the following feature: • “Add a new book to book repository”. • How to model authors and publishers? • Guideline: Attributes vs. Classes • If we do not think of some thing X as a number or text in the real world, X is probably a conceptual class, not an attribute. Matching strings to authorsand publisher could be encapsulated in these classes. Moreover, we need to add these concepts because we must manage the list of authors, and publishers.
3.2 AMDD (cont)Analysis and Design: Description Classes • How to model the relationships between book and authors, and publishers classes? • A description class contains information that describes something else. • Guideline: When Are Description Classes Useful? Add a description class (for example, BookSpecification) when: • There needs to be a description about an item or service, independent of the current existence of any examples of those items or services. • It reduces redundant or duplicated information.
3.2 AMDD (cont)Layered Architecture Pattern A layered architecture and typical relationships between layers • How to organize a complex program? • Layered Architecture Pattern: • Partition a complex program into layers. • Concentrate all the code related to the domain model in one layer and isolate it from the others. • Ensure each layer is cohesive and depends on the layers below. show info, and interpret user’s commands tasks coordinator, jobs, services concepts of business, business rules technical capabilities: messages, persistence, etc
3.2 AMDD (cont)New Tools for Your OOAD Toolbox Practices Developers (who know how to build) and domain experts (who know the domain) should have a close relationship. Model in small increments – organize a larger effort into smaller portions that you release over time (incremental development). Requirements Good requirements ensure your system works like your customers expect. Capture the lists of features your software is supposed to do. • Analysis & Design • If a design isn’t flexible then, CHANGE IT! • Make sure each class is cohesive – focused on doing ONE THING really well. • Model things that are not numbers or strings in the real world as concepts. • Use description classes to reduce redundant or duplicate information. • OO Principles • Single Responsibility: Assign each responsibility to one class, and only one class. • Encapsulation: The grouping of related concepts into one item, such as a class, package, etc. • Design Patterns • Layered Architecture:Partition a complex program into layers.Ensure each layer is cohesive. Development Approaches Agile Model Driven Development – focuses on creating just barely good enough models (agile models) before writing the source code. Evans, 2004
3.2 AMDD (cont)How to implement “adding books” feature? • The refined domain model: • How to implement the model? • Is this a good model? Are there other guidelines for improving the model? • What steps could we follow for implementation?
3.3 Introduction to Test Driven Development (TDD) Practices Developers (who know how to build) and domain experts (who know the domain) should have a close relationship. Model in small increments – organize a larger effort into smaller portions that you release over time (incremental development). Requirements Good requirements ensure your system works like your customers expect. Capture the lists of features your software is supposed to do. Development Approaches Feature driven development – focuses on a single feature, and codes all the behavior of that feature, before moving on to anything else in the application. Agile Model Driven Development – focuses on creating just barely good enough models (agile models) before writing the source code. Test driven development – writes test scenarios for a piece of functionality before writing the code for that functionality. Then you write software to pass all the tests. Beck, 2002
3.3 TDD (cont)What is it? One goal is specification, not validation. Second, it’s one way to think about your design, before you write your functional code. TDD = Test First Design + Refactoring TFD Steps: • Add just enough code to fail. • Runthe tests, to ensure that the new test does in fact fail. • Update your functional code to make it pass the new tests. • Run your tests again. • If they fail you need to update your functional code and retest. • Once the tests pass the next step is to start over. 1 2 3 4 Third, it’s a way to write clean code that works. TFD Steps
3.3 TDD (cont)Model, and code the Author class • This task can be considered part of the iteration 1: “Add a book to book repository” that can be decomposed as: • Model, and code Author, and Publisher classes, then • Model, and code BookSpecification class, then finally • Model, and code Book class. • Can we implement directly the model for authors? We need to: • create Author instances, and • match authors by name. • But, another feature requires to “List the authors that have registered books”. How to proceed? • An object defined primarily by its identity is called an ENTITY.ENTITY identities must be defined so that they can be effectively tracked.
3.3 TDD (cont)Model, and code the Author class • Author instances are entities! • We divide this task in two test-driven development cycles, focused on • Creating Author instances, and • Matching authors by name. • Each test-driven development cycle will include the following subtasks: • 1. Add a test case. • 2. Run the tests. • 3. Implement the required functionality. • 4. Run the tests again. A uniqueinteger generated value will be assigned for each Author instance. Customers mayalready have such ids for their entities, so the programmer could use them.
3.3 TDD (cont)Model, and code the Author class • 1 Creating author instances cycle: • 1.1 Create authors test case package test; import domain.Author; import junit.framework.TestCase; publicclass AuthorTest extends TestCase { publicvoid testCreate(){ final String authorName = "Kent Beck"; Author author = new Author(authorName); assertEquals(authorName, author.getName()); } } The constructor and the getter method do not exist. So, the test case does not compile.
3.3 TDD (cont)Model, and code the Author class • 1 Creating author instances cycle: • 1.2 Create authors test case (cont) package domain; publicclass Author { privateint id; private String name; public Author(String authorName) { // TODO Auto-generated constructor stub } public String getName() { // TODO Auto-generated method stub returnnull; } } Add required elements to Author class in order tocan run the test case. We enhanced our design!!! Method bodies not completed (TODO...).
3.3 TDD (cont)Model, and code the Author class • 1 Creating author instances cycle: • 1.2 Run the tests, to ensure that the new test does in fact fail. Failed because the methods were not yet implemented public void testCreate() { final String authorName = "Kent Beck"; Author author = new Author(authorName); assertEquals(authorName, author.getName()); }
3.3 TDD (cont)Model, and code the Author class • 1 Creating author instances cycle: • 1.3 Update your functional code to make it pass the new tests. package domain; publicclass Author { privateint id; private String name; public Author(String authorName) { this.name = authorName; } public String getName() { returnname; } } Method bodies completed. Now we can run the tests.
3.3 TDD (cont)Model, and code the Author class • 1 Creating author instances cycle: • 1.4 Run your tests again. The tests passed. The next step is to start over.
3.3 TDD (cont)Model, and code the Author class • 2 Matching authors cycle: • 2.1 Matches authors test case public void testMatches() { final String authorName = “Kent Beck"; Author author = new Author(authorName); final String searchAuthorName = “Beck"; assertTrue(“Author: " + authorName + " matches: “ + searchAuthorName, author.matches(searchAuthorName)); } • 2.3 Matches author method public boolean matches(String searchAuthorName) { return name.contains(searchAuthorName); }
3.3 TDD (cont)New Tools for Your OOAD Toolbox Practices Developers (who know how to build) and domain experts (who know the domain) should have a close relationship. Model in small increments – organize a larger effort into smaller portions that you release over time (incremental development). Requirements Good requirements ensure your system works like your customers expect. Capture the lists of features your software is supposed to do. • OO Principles • Single Responsibility: Assign each responsibility to one class, and only one class. • Encapsulation: The grouping of related concepts into one item, such as a class, package, etc. • Analysis & Design • If a design isn’t flexible then, CHANGE IT! • Make sure each class is cohesive – focused on doing ONE THING really well. • Model things that are not numbers or strings in the real world as concepts. • Use description classes to reduce redundant or duplicate information. • Implementation • The basic rhythm for development is to write a little test code, then write a little production code, make it pass the test, then write some more test code, and so forth. • Design Patterns • Layered Architecture:Partition a complex program into layers.Ensure each layer is cohesive. • Entity: Determine the entities within your system and establish their identities. Development Approaches Test driven development – writes test scenarios for a piece of functionality before writing the code for that functionality. Then you write software to pass all the tests.
4 Applying Practices, Principles, and Patterns 4.1 Our Development Approach 4.2 Project Plan 4.3 Iteration Plan 4.4 Repository Pattern 4.5 Value Object Pattern 4.6 Service Layer Pattern
4.1 Our Development Approach Our development approach in this course: • For a couple of requirements (features) our system must fulfill consider an iteration • For each iteration do: • Break the iteration in work items • For each work item/task do: • Model a little bit ahead (if necessary) • Break the work item into several TDD small steps and perform for each step: • Add a a little test code • Run the tests • Add a little production code • Run the tests again Document the result in a project plan. Write the work items into an iteration plan. TDD steps In order to save space, the next slides will show only these steps. AMDD Development iteration steps FDD practices
4.2 Project Plan • A project plan gathers all information required to manage a project. • For simplicity, we are going to consider only the iteration plan (part of a project plan). • Book Inventory Project Plan Fragment
4.3 Iteration Plan (I1) Iteration I1. Adda new book to book repository Iteration Workitems/Tasks Tasks to be performed in this iteration. In which order? Who should perform the task?
4.4 Repository Pattern A respon-sible layer must be chosen. e.g. Author • Context/Problem: • Some objects must be globally accessiblethrough a search based on object attributes. • Free database queries can actually breach the encapsulation of domain objects. • Exposure of technical infrastructure and database access mechanisms complicates the client and violates Layered Architecture. • Solution: • For each type of object that needs global access, create an object (called Repository) that can provide the illusion of an in-memory collection of all objects of that type. • Provide methods to add and remove objects. • Provide methods that select objectsbased on some criteria and return fully instantiated objects whose attribute values meet the criteria. • Repository objects encapsulate the actual storage and query technology. Do not choose ui, or app!!! e.g. AuthorRepository, put in domain
4.4 Repository Pattern (cont)Iteration 1. Task - Tracking Author Instances AuthorRepository class added to domain layer Model storming result • Model a bit ahead • Repository pattern applied • TDD Cycle 1: Add an author to the repository • Add author test case public void testAddAuthor() { AuthorRepository authorRepository = new AuthorRepository(); Author author = new Author("Kent Beck"); assertTrue(author.getId() == 0); authorRepository.add(author); assertFalse(author.getId() == 0); } • Add author production code private List<Author> authors; public AuthorRepository() { authors = new ArrayList<Author>(); } public void add(Author author) { author.setId(authors.size()+1); authors.add(author); } The model after adding the test case New methods designed Author.id set by repository
4.4 Repository Pattern (cont)Iteration 1. Task - Tracking Author Instances (cont) setUp called before execu-ting each testXxx() method. We initialize authorRepository. • TDD Cycle 2: Find all authors • Find authors test case public class AuthorRepositoryTest extends TestCase { private AuthorRepository authorRepository; protected void setUp() throws Exception { authorRepository = new AuthorRepository(); super.setUp(); } protected void tearDown() throws Exception { authorRepository = null; super.tearDown(); } public void testGetAuthors() { assertTrue(authorRepository.getAuthorSize() == 0); Author author1 = _addAuthor(“Kent Beck”); assertTrue(authorRepository.getAuthorSize() == 1); Author author2 = _addAuthor(“Martin Fowler”); List<Author> authors = authorRepository.getAuthors(); assertTrue( ((authors.get(0) == author1) && (authors.get(1) == author2)) || (authors.get(1) == author1) && (authors.get(0) == author2)); } private Author _addAuthor(String authorName) { Author author = new Author(authorName); authorRepository.add(author); return author; } } Don’t forget to call the base class method! tearDown called after each testXxx() method is executed. Running the tests - possible execution paths: 1,3,2,1,4,2 OR 1,4,2,1,3,2 Don’t assume the order in which tests within a test case run!
4.4 Repository Pattern (cont)Iteration 1. Task - Tracking Author Instances (cont) • TDD Cycle 2: Find all authors • Find authors production code ... private List<Author> authors; ... public int getAuthorSize() { return authors.size(); } public List<Author> getAuthors() { return authors; } The model after adding the test cases ”add author”, and “find all authors”