22
Introductory Software Engineering with a Focus on Dependency Management Christine Hofmeister

Introductory Software Engineering w ith a Focus on Dependency Management

Embed Size (px)

DESCRIPTION

Introductory Software Engineering w ith a Focus on Dependency Management. Christine Hofmeister. Software Engineering Course Constraints. At East Stroudsburg University, the Software E ngineering course is completed in the 3 rd or 4 th year of undergraduate study. - PowerPoint PPT Presentation

Citation preview

Page 1: Introductory Software Engineering  w ith a Focus on  Dependency Management

Introductory Software Engineering with a Focus on Dependency Management

Christine Hofmeister

Page 2: Introductory Software Engineering  w ith a Focus on  Dependency Management

Software Engineering Course Constraints

At East Stroudsburg University, the Software Engineering course is completed in the 3rd or 4th year of undergraduate study.

Only one semester course (3 credits): 3 hours of instruction per week 14 weeks

Typical student expertise before this course: writing programs (not systems!) ad-hoc testing.

Page 3: Introductory Software Engineering  w ith a Focus on  Dependency Management

Why Focus on Dependency Management?

Problem: Students need to learn the challenges of

large-scale development, yet most have had little experience with even small-scale development.

Solution: Focus on design, since that is closest to the

code. Focus on dependency management, since

dependencies are fundamental to design.

Page 4: Introductory Software Engineering  w ith a Focus on  Dependency Management

Approach

Key techniques for dependency management: Interfaces (for static dependencies) Factory design pattern (for object creation

dependencies). Use UML models to reveal dependencies:

Students learn to abstract key design details into a model.

Models reveal how interfaces and factory patterns remove dependencies.

Page 5: Introductory Software Engineering  w ith a Focus on  Dependency Management

FlexibleHello1: Creates a Name object, either

with an Encryptor or not. Calls Name’s firstName() and

lastName() methods, and prints the result.

Name: Creates two Message objects: _textin and _textout. Methods firstName() and lastName() do the

following: Use _textout to set and show the prompt. Use _textin to capture the user’s input, which is returned

to the caller.

Hello Example: Version 1

Page 6: Introductory Software Engineering  w ith a Focus on  Dependency Management

Message: setMessage(): saves the message string (saves

it encrypted, if applicable). showMessage(): displays the current message

string (decrypted, if applicable) on the console. readMessage(): reads a string

from the console and returns it (encrypted, if applicable).(We don’t decrypt in this case simply because we want to see which version of Message was used.)

Hello Example (Version 1 cont.)

Page 7: Introductory Software Engineering  w ith a Focus on  Dependency Management

FlexibleHello1 knows about all the variants of Message that exist. For the plain text variant, it uses 0 as the Encryptor*. For the secure text variant, it creates an Encryptor.

FlexibleHello1 passes the Encryptor* to Name. Name does not know about the Message variants.

Name simply passes the Encryptor* when it constructs its Message objects.

Message is capable of using both plain text and encrypted messages. It uses the Encryptor* object if available (if it’s non-

null).

V1: FlexibleHello Dependencies

Page 8: Introductory Software Engineering  w ith a Focus on  Dependency Management

To add a third kind of Message, numerous code changes are required: Modify Message to handle 3 variants instead of

2. Modify main() to pick one of the 3 variants and

pass a flag to Name. Modify Name to pass the variant flag to

Message. Students also see that the Encryptor object

was doing double duty, both as a flag to pick the variant and as the object itself.

Student Lab Exercise: Add LoudMessage (all caps)

Page 9: Introductory Software Engineering  w ith a Focus on  Dependency Management

Instead of making the Message class handle multiple message variants, create a separate class for each variant.

Hide these message variants behind interface IMessage.

Improvement: Use an Interface

Page 10: Introductory Software Engineering  w ith a Focus on  Dependency Management

C++ is the language used for this course: It’s a prevalent, mainstream language. It’s a rich language:

Two kinds of variable declarations. No garbage collection. Two kinds of method binding. No interface support.* Methods can exist outside of classes.

These “features” make it an excellent vehicle for teaching polymorphism, interfaces, factory patterns, libraries, and linking.

* Note that sometimes the class declaration in the .h file is called the class’s “interface.” This is not a true interface.

Implementation Language: C++

Page 11: Introductory Software Engineering  w ith a Focus on  Dependency Management

In C++ we create an interface by using an abstract class with only abstract public operations.

Example of interface in C++:

class IMessage {

public:

virtual void setMessage(std::string) = 0;

virtual void showMessage() = 0;

virtual std::string readMessage() = 0;

virtual ~IMessage() {}

};

Interfaces in C++

Page 12: Introductory Software Engineering  w ith a Focus on  Dependency Management

Create two separate message classes: Message and SecureMessage. The Encryptor is now encapsulated in SecureMessage.

Provide an interface to the message classes (IMessage).

FlexibleHello2 (main()) chooses which variant of IMessage is used, creates the IMessage object and passes it to Name.

V2: Hello Example with Interfaces

Page 13: Introductory Software Engineering  w ith a Focus on  Dependency Management

To add a third kind of message, students see that no changes are needed for Name.

However, since Name requires two message objects, FlexibleHello2 must create both and pass both

objects to Name. FlexibleHello2 could create two different

kinds of messages to pass to Name. The fundamental problem is that Name

should create the IMessage objects, but to do so it needs to call the appropriate constructor.

Student Lab Exercise: Add LoudMessage to V2

Page 14: Introductory Software Engineering  w ith a Focus on  Dependency Management

(a.k.a. Abstract Factory design pattern in Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides. Addison-Wesley 1995.)

Use a class factory when the creator of an object does not know what kind of object to create.

A class factory separates the decision of which object to create from the actual creation of the object.

A class factory is a class that simply creates objects, e.g.:

MessageFactory::MessageFactory(){ }

MessageFactory::~MessageFactory(){ }

IMessage* MessageFactory::newMessage() {

return new Message();

}

Different class factories create different kinds of objects.

Class Factory

Page 15: Introductory Software Engineering  w ith a Focus on  Dependency Management

Name uses only the interfaces IMessageFactory and IMessage, even though the objects it accesses via these interfaces are really either MessageFactory and Message or SecureMessageFactory and SecureMessage.

V3: Hello Example with Class Factory

main() picks (creates) the Factory.Name uses the IMessageFactory to create an IMessage object (without knowing exactly what type of object it is creating).

Page 16: Introductory Software Engineering  w ith a Focus on  Dependency Management

To add a third kind of message, students must provide a new class: LoudMessageFactory.

To switch to another kind of message, students must edit FlexibleHello3.cpp to call the

constructor for the appropriate factory rebuild the application.

Student Lab Exercise: Add LoudMessage to V3

Page 17: Introductory Software Engineering  w ith a Focus on  Dependency Management

Idea: For each interface, provide a C++ method

(not part of a class) that creates an object of the desired class.

Because it’s a C++ method, the linker matches the declaration to the definition it is given.

V4: Hello Example with Factory Method

IMessage* NewMessage();

IMessage* NewMessage(){ return new SecureMessage(); }

IMessage* NewMessage(){ return new Message(); }

Page 18: Introductory Software Engineering  w ith a Focus on  Dependency Management

Comparison of Factory Patterns

Page 19: Introductory Software Engineering  w ith a Focus on  Dependency Management

The class factory (V3) is used to create a coherent set of objects for a variant. CatFactory creates PetCat and FoodCat DogFactory creates PetDog and FoodDog

The factory method (V4) is used on the class factory to allow us to select different factories at link time. At runtime, link in one of these:

Cat.lib (contains CatFactory, PetCat, and FoodCat) Dog.lib (contains DogFactory, PetDog, and

FoodDog)

Maximum Flexibility: Combine Both Factory Patterns

Page 20: Introductory Software Engineering  w ith a Focus on  Dependency Management

Evaluation

Dependency management focus motivated by my prior 7 years in industry: Projects needed interfaces but didn’t have them. Factory design pattern was essential in one family

of systems. Course has evolved over the course of 14

years. Students value the content:

Survey comments Exit interviews Spontaneous feedback

Page 21: Introductory Software Engineering  w ith a Focus on  Dependency Management

Numeric Course Evaluations

Page 22: Introductory Software Engineering  w ith a Focus on  Dependency Management

Summary

Dependency management: Interfaces are used to control call-dependencies, and by using C++

(which has no native interface), student learn exactly how an interface differs from a class.

Factories are used to control creation dependencies, by enabling object creation while hiding the type of object being created.

Through their UML modeling work, the students: Learn the UML language. Reinforce their understanding of object-oriented design concepts,

because they are abstracting these aspects of the code. Develop a deeper understanding of C++ language features, e.g.

static vs. dynamic memory allocation, the meaning of the ‘static’ keyword, virtual vs. non-virtual methods, and the meaning of ‘pure virtual’.

Learn to recognize design idioms, e.g. when interfaces and/or factory patterns are used.