Lessons Learned. Johnny Bigert, Ph.D., Skype/Microsoft October 26, 2011

Similar documents
SOLID Principles. Equuleus Technologies. Optional Subheading October 19, 2016

Software Engineering

Philosophy of Unit Testing

CSC207H: Software Design SOLID. CSC207 Winter 2018

Object Oriented Software Design - I

Single Responsibility Principle

Test-driven development

Dependency Inversion, Dependency Injection and Inversion of Control. Dependency Inversion Principle by Robert Martin of Agile Fame

Object-Oriented Design I - SOLID

Agile Architecture. The Why, the What and the How

Object-Oriented Design II

Lecture: Modular Design

Welcome to Design Patterns! For syllabus, course specifics, assignments, etc., please see Canvas

Open Closed Principle (OCP)

Intro to: Design Principles

GRASP Design Patterns A.A. 2018/2019

Introduction to Testing and Maintainable code

CSC207 Week 3. Larry Zhang

Produced by. Agile Software Development. Eamonn de Leastar

Analysis of the Test Driven Development by Example

Software Engineering CSC40232: SOFTWARE ENGINEERING. Guest Lecturer: Jin Guo SOLID Principles sarec.nd.edu/courses/se2017

COURSE 2 DESIGN PATTERNS

Single Responsibility Principle (SRP)

Optimize tomorrow today.

Software Quality in a Modern Development Team. Presented by Timothy Bauguess and Marty Lewis

OO Frameworks. Introduction. Using Frameworks

OO Class Design Principles

Master Project. Refactoring the Legacy Code. Software Construction. EVU Master Thesis Aarhuus University

11/2/09. Code Critique. What goal are we designing to? What is the typical fix for code smells? Refactoring Liskov Substitution Principle

Inheritance and Interfaces

S.O.L.I.D: Software Engineering Principles

Test Driven Development TDD

Last Time: Object Design. Comp435 Object-Oriented Design. Last Time: Responsibilities. Last Time: Creator. Last Time: The 9 GRASP Patterns

Design Principles: Part 2

Design Principles: Part 2

The following topics will be covered in this course (not necessarily in this order).

Outline. Design Principles: Part 2. e.g. Rectangles and Squares. The Liskov Substitution Principle (LSP) ENGI 5895: Software Design.

Index. Index. More information. block statements 66 y 107 Boolean 107 break 55, 68 built-in types 107

Ingegneria del Software Corso di Laurea in Informatica per il Management. Software quality and Object Oriented Principles

3 Continuous Integration 3. Automated system finding bugs is better than people

Abstraction. Design fundamentals in OO Systems. Fundamental Software Development Principles

Test, Code, Design: Inverting the Waterfall

Software Design and SOLID Principles

CS 520 Theory and Practice of Software Engineering Fall 2017

CPSC 410? Advanced Software Engineering Mid-term Examination (Term I ) SOLUTION Instructor: Gail Murphy

(Practical) SW Architectures. November 14, 2013

The Power of Unit Testing and it s impact on your business. Ashish Kumar Vice President, Engineering

CS 520 Theory and Practice of Software Engineering Fall 2018

1 Software Architecture

Object Oriented Programming

A few more things about Agile and SE. Could help in interviews, but don t try to bluff your way through

Liskov Substitution Principle

Object-Oriented Design I

From Feature to Code. SCRUM + NetBeans RCP + Featureous. John Kostaras JCrete August 2014

Component-Level Design. Slides copyright 1996, 2001, 2005, 2009 by Roger S. Pressman. For non-profit educational use only

Design patterns. Jef De Smedt Beta VZW

09. Component-Level Design

C++ Modern and Lucid C++ for Professional Programmers

CS 320 Introduction to Software Engineering Spring March 06, 2017

CS 320 Introduction to Software Engineering Spring March

11/4/15. Review. Objec&ves. Refactoring for Readability. Review. Liskov Subs&tu&on Principle (LSP) LISKOV SUBSTITUTION PRINCIPLE

Application Architectures, Design Patterns

Understading Refactorings

Eliminate enterprise software design instability - protect variations! Nickolay Kofanov

Designing with patterns - Refactoring. What is Refactoring?

Essential Skills for the Agile Developer. Agile. copyright Net Objectives, Inc.

5. Application Layer. Introduction

Principles of OO Design

Object-oriented programming. and data-structures CS/ENGRD 2110 SUMMER 2018

1: Introduction to Object (1)

Object-Oriented Design

Conception Orientée Objets. Programmation SOLID

Inheritance. OOP: Inheritance 1

The Adapter Pattern. Interface with anything!

Patterns and Practices for Embedded TDD in C and C++ How we introduced TDD into our company

Object Oriented Software Design - I

Contents. Management issues. Technical issues. Mark Fewster.

Topics. Software Process. Agile. Requirements. Basic Design. Modular Design. Design Patterns. Testing. Quality. Refactoring.

Maintainable Software. Software Engineering Andreas Zeller, Saarland University

Shift Left, Automation, and Other Smart Strategies for Getting Ahead in QA

Object-Oriented Programming and Design

Object-Oriented Design

How technical excellence helps in LeSS adoption. Anton Bevzuk Dodo Pizza Chief Agile Officer

Chapter 8: Class and Method Design

Dependency Injection & Design Principles Recap Reid Holmes

Software Development Project. Kazi Masudul Alam

Build Testable Client and Service Applications

Agile Model-Driven Development with UML 2.0 SCOTT W. AM BLER. Foreword by Randy Miller UNIFIED 1420 MODELING LANGUAGE. gile 1.

PROCESS DEVELOPMENT METHODOLOGY The development process of an API fits the most fundamental iterative code development

INHERITANCE WITH JAVA INTERFACES

Object-Oriented Design II - GRASP

The de constructed. Magento module

CSS 343 Data Structures, Algorithms, and Discrete Math II. Polymorphism. Yusuf Pisan

Top 7 Lessons From My First Big Silverlight Project

Completely

Technical Metrics for OO Systems

Test Code Patterns. How to design your test code

CSE wi Final Exam 3/12/18. Name UW ID#

The Design Patterns Matrix From Analysis to Implementation

Hovedopgave. Bringing a Legacy System under Test Control. Master i informationsteknologi Linien i softwarekonstruktion

Transcription:

Lessons Learned Johnny Bigert, Ph.D., Skype/Microsoft johnny.bigert@skype.net October 26, 2011

Why do we do the things we do?

Software Development Object-orientation, design principles, timeboxing, teams, geographic colocation, Scrum, lean, continuous improvement, refactoring, design patterns, prototyping, continuous integration, unit tests, test driven development, modularity, readability, testability, layering, reuse, interfaces, APIs, decoupling, cohesion, revision control Sure, but why?

Problem Description Develop a software system according to requirements (functional and nonfunctional) Sounds simple!

Constraints Cost of development, testing, on-boarding, Time to market changing/unclear requirements, new features, Quality bugs, regressions, user experience, Or good/cheap/fast choose two

Tools At Our Disposal Focus on internal quality (good code) Quality assurance (testing) Software development methodology (Scrum etc, not covered today) Etc

Constraints Internal Quality Cost of development, testing, on-boarding, Time to market changing/unclear requirements, new features, Quality bugs, regressions, user experience, Testing SW development methodology

What is it? Why do we need it? How do we get it?

Internal Quality = Good code! = Clean, consistent, well-structured, readable, extensible, adaptable, decoupled, testable, well-tested etc

Constraints (revisited) Cost of development, testing, on-boarding, Time to market changing/unclear requirements, new features, Quality bugs, regressions, user experience, Poor internal quality affects them all!

Obtaining Internal Quality Examples: Object-Oriented Design Principles Head First Design Patterns by Freeman and Freeman Design Patterns Design Patterns by Gamma et. al. Code should be easy to read (you write it once, but read it hundreds of times!) Code Complete by McConnell Code reviews, Pair programming, Code metrics, Test-driven development,

A networking application

Example Networking application class Application { void buttonpushed() { network->senddata(data); } Network *network; };

Example (continued) class Network { void packetreceived(...) { app->ondatareceived(data); } Application *app; };

Downsides Tightly coupled: Can t easily replace network Application Can t easily test application logic without real network Can t reuse network Hard to understand which parts are used by the other Network

Dilemma The Application needs to communicate with the Network (and vice versa) The Application must not know about the Network (and vice versa)

Object-Oriented Design Principles High-level guidelines for object-oriented development Fundamental to good software architecture

SOLID Design Principles Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation principle Dependency inversion principle http://en.wikipedia.org/wiki/solid_%28object-oriented_design%29

Single Responsibility Principle A class should have a single responsibility = A class (or interface, or module) should have a single reason to change http://en.wikipedia.org/wiki/single_responsibility_principle

Single Responsibility Principle Applied Example: A network class that both 1. formats the data to send and 2. sends the data over the wire The class will change if 1. the data format changes or 2. the sending of the data changes Changes to one might break the other Split into two classes!

Open/Closed Principle A class (or module) should be open for extension but closed for modification = Make sure that there are ways to modify the behavior of your software without changing it http://en.wikipedia.org/wiki/open/closed_principle

Open/Closed Principle Applied We want to avoid code changes: if(condition) listener = new SomeListener; else if(condition2) listener = ; Instead, move the decision out of the class Constructor/setter injection (setlistener) Add/remove (addlistener)

Open/Closed Principle Applied (cont) We want to create an application that can send messages over the network Application doesn t care how things are sent UDP/TCP, HTTP, binary, email, smoke signals Application::Application(INetworkSender) Network strategy - the strategy design pattern We can modify the application behavior without changing its code

Liskov Substitution Principle You should be able to substitute a class with any of its subclasses without altering the properties of the program (correctness etc.) = Subclasses should obey the semantics of super-classes they inherit (or interfaces they implement) Design by contract http://en.wikipedia.org/wiki/liskov_substitution_principle

Liskov Substitution Principle Applied A classic: Is a circle an ellipse? (= Is Circle a subclass of Ellipse)? Contract on Ellipse: calling setheight should not affect getwidth Circle: setheight will change width If Circle is a subclass of Ellipse, it violates LSP

Interface Segregation Principle Many client specific interfaces are better than one general purpose interface = A class should only depend on functions it uses http://en.wikipedia.org/wiki/interface_segregation_principle

Interface Segregation Principle Applied Example: A Network class delivers messages to the application If the Network class knows about the Application class then Network will know Application s full public interface = bad Create a client specific interface INetworkReceiver, let Application inherit

Dependency Inversion Principle Depend on abstractions, do not depend on concretions The inversion is the core of objectoriented programming http://en.wikipedia.org/wiki/dependency_inversion_principle

Breaking dependencies

The Dependency Inversion Principle Depend on abstractions, not on concretions. = Application should not talk directly to the Network implementation (and vice versa) = Application should talk to a Network abstraction We will use an interface!

The Dependency Inversion Principle Procedural programming Application Network Function call Application Function call INetworkSender Network Inheritance = inverted!

Observation Three principles: Open/closed Interface segregation Dependency inversion All give us the same result But for different reasons! Application Function call INetworkSender Network (inheritance)

Interfaces Abstract base classes in C++ class INetworkSender { virtual ~INetworkSender() {} virtual void senddata( const std::string &data) = 0; };

Interfaces (continued) class INetworkReceiver { virtual ~INetworkReceiver() {} virtual void ondatareceived( const std::string &data) = 0; };

Example (revisited) class Application : public INetworkReceiver { void buttonpushed() { network->senddata(data); } INetworkSender *network; };

Example (continued) class Network : public INetworkSender { void packetreceived(...) { app->ondatareceived(data); } INetworkReceiver *app; };

Example (continued) Constructor and setter injection: Network network; // ctor takes INetworkSender! Application app(network); // setter takes INetworkReceiver! network.setreceiver(app);

A useful building block

The Diamond shape (inherits) Application senddata INetworkReceiver INetworkSender ondatareceived Network (inherits)

The Diamond shape (inherits) Application senddata INetworkReceiver ondatareceived Network INetworkSender (inherits)

The Diamond Fundamental building block Decoupling despite bi-directional communication Frequently used to layer your application Lower layers do not know of upper layers Lower layers can be reused UI Logic Networking

Example Revisited: Can t easily replace network Open/Closed Principle (inherits) Application senddata INetworkReceiver INetworkSender ondatareceived SomeOther NetworkImpl (inherits)

Can t easily test application logic without network Open/Closed Principle (inherits) Application senddata INetworkReceiver INetworkSender ondatareceived Network Mock (inherits)

Can t reuse network Dependency Inversion Principle (inherits) SomeOther Application senddata INetworkReceiver INetworkSender ondatareceived Network (inherits)

Hard to understand which parts are used by the other Interface Segregation Principle (inherits) Application senddata INetworkReceiver INetworkSender ondatareceived Network (inherits)

Testability, Test-Driven Development, Unit Testing

Testing What is testing? Verify that our system conforms to requirements Make sure the system contains no apparent bugs Automated testing Since we need to do the above repeatedly

Testing (continued) Testing on what level? E.g. system, module, single function Testing what characteristics? E.g. behavior, performance, memory footprint Testing how? E.g. from UI, over network, function calls We will focus on unit testing

Unit Testing No clear definition/many names E.g. unit testing, component testing, basic testing, Definition here: Testing through function calls: Test executable by compiling test code with application code Testing behavior (with some exceptions) Testing on function to module level

What is Testability? The ability to test code at a reasonable cost E.g. some network failure or timing scenarios are very hard to reliably reproduce Very expensive to introduce testability late E.g. networking code everywhere Legacy code = code not covered by tests

Test-Driven Development How do we make sure our code is testable? Write the test first! Growing Object-Oriented Software Guided by Tests by Freeman, Pryce

Test-Driven Development (cont) 1. Write a failing unit test. 2. Run tests and watch it fail. 3. Write code to pass the test. 4. Run tests and watch it pass. 5. Refactor. (By definition, the test should still pass.) 6. Start over from (1).

Test-Driven Development (cont) Upsides: All code will be testable, and covered by tests! Decoupling comes natural Good interfaces (your test code is a user) Downsides: Refactoring not sufficient for large-scale architecture Tedious (I know how to implement it, now let me!)

TDD Example When the user clicks the button, data abc should be sent over the network. First, write a failing unit test

TDD Example (continued) First iteration: Created and instantiated class-under-test Application Added (empty) function buttonclicked() Compiles but doesn t fail void whenuserclicksbuttonabcissentovernetwork() { Application app; app.buttonclicked(); }

TDD Example (continued) Second iteration: Added verification code Success!, test fails void whenuserclicksbuttonabcissentovernetwork() { TestNetworkSender testsender; Application app; app.buttonclicked(); testsender.verifycalltosend( abc ); }

TDD Example (continued) No real Network class! Networking is slow and hard to control (may introduce errors, hard to reproduce errors/induce state) We introduced a TestNetworkSender class Implements interface INetworkSender Remembers when senddata is called Alternatively: use mock library (e.g. googlemock, http://code.google.com/p/googlemock/)

TDD Example (continued) Next, write code to pass unit test! Hmm, we cannot get test to pass without changing the test code!

TDD Example (continued) Third iteration: Added new Application(INetworkSender) ctor Good, test still fails void whenuserclicksbuttonabcissentovernetwork() { TestNetworkSender testsender; Application app(testsender); app.buttonclicked(); testsender.verifycalltosend( abc ); }

TDD Example (continued) Now we can write code to pass unit test! See code from earlier Watch test pass Refactor

Unit Testing Modules A unit is what you want it to be I like unit tests on module/application level Why? Stable interfaces, internal restructuring will not change tests Brings business value: clear connection between use-cases and unit tests Less waste from testing things that will never be used etc.

Q&A Skype? Microsoft? Cost/quality/time-tomarket? Internal quality? Development methodology? Scrum? Lean? Software architecture? Design principles? SOLID? Diamond? Layers? Interfaces? Decoupling? Abstraction/compression? Testability? Unit testing? Test-driven development? Books? www.johnnybigert.se/blog