Lecture 28 - Course Review

Lecture Date: Tuesday, May 1

This is it! We wrap up the semester and discuss moving forward with a career in software engineering.

more ...




Lecture 24 - Maintenance

Lecture Date: Tuesday, April 17

"Maintenance" is too often a dirty word in software development... but really only the most skilled developers are good at it! Why does this happen? What skills do you need to be successful?

Slides - Maintenance

more ...


Lecture 22 - Engineering Secure Software

Lecture Date: Tuesday, April 10

We will start with an in-depth discussion of the state of the project before moving into the security material for today.

Securing software is not an afterthought. But too often developers treat it as such, particularly newer developers. We'll discuss some key points to consider when building software with security in mind.

Slides - Engineering Software Security

more ...

Lecture 21 - More Design Patterns

Lecture Date: Thursday, April 5

Design patterns for today:

Singleton

public class Singleton {

    private int value = 0;

    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public void setValue(int x) {
        this.value = x;
    }

    public int getValue() {
        return this.value;
    }
}

Abstract Factory

abstract class PhraseFactory {

    public static final int COOL = 0;
    public static final int LAME = 1;

    public static PhraseFactory getFactory(int TYPE) {
        PhraseFactory factory = null;
        if(TYPE == COOL) {
            factory = new CoolPhraseGenerator();
        }
        else if(TYPE == LAME) {
            factory = new LamePhraseGenerator();
        }
        return factory;
    }

    public abstract String getPhrase();
}

Client Code

public class Client {

    public static void main(String[] args) {
        Singleton mySing1 = Singleton.getInstance();
        Singleton mySing2 = Singleton.getInstance();

        if(mySing1 == mySing2) {
            System.out.println("Same!");
        }
        else {
            System.out.println("Not Same!");
        }

        System.out.println(mySing1.getValue());
        mySing2.setValue(4);
        System.out.println(mySing1.getValue());


        PhraseFactory myPhraseGenerator = PhraseFactory.getFactory(PhraseFactory.COOL);
        System.out.println(myPhraseGenerator.getPhrase());

        myPhraseGenerator = PhraseFactory.getFactory(PhraseFactory.LAME);
        System.out.println(myPhraseGenerator.getPhrase());


    }

}
public class LamePhraseGenerator extends PhraseFactory {
    @Override
    public String getPhrase() {
        return "Cowabunga, dude!";
    }
}
public class CoolPhraseGenerator extends PhraseFactory {
    @Override
    public String getPhrase() {
        return "I think CS 3240 is a wonderful class!";
    }
}

Decorator

Slides - Decorator

more ...

Lecture 20 - Design Patterns: Adapter (Continued)

Lecture Date: Tuesday, April 3

Let's revist the adapter pattern again with a different example.

Here's some code we are going to work with:

import math

class Square_Peg:

    side_length = 0

    def __init__(self, side_length):
        self.side_length = side_length

    def make_fit(self, hole):
        if self.side_length < hole.get_max_square_peg_size():
            print("Square_Peg with side_length", self.side_length, "fits!")
        else:
            print("Square_Peg with side_length", self.side_length, "won't fit!!!")


class Round_Hole:
    def __init__(self, radius):
        self.radius = radius
        print("Round_Hole: max Square_Peg size is", self.get_max_square_peg_size())

    def get_max_square_peg_size(self):
        return self.radius*math.sqrt(2)

# ADD YOUR NEW CLASSES HERE!!!

# One possible solution is:

class Square_Peg_Class_Adapter(Square_Peg):
    def __init__(self, side_length):
        Square_Peg.__init__(self,side_length)


    def make_fit(self, hole):
        if self.side_length > hole.get_max_square_peg_size():
            amount_to_reduce = self.side_length - hole.get_max_square_peg_size()
            print("Square_Peg with side_length", self.side_length, "is currently too big!")
            print("    reducing size by", amount_to_reduce)
            self.side_length = self.side_length - amount_to_reduce
            print("Trying Square_Peg with with new side_length", self.side_length, "!")

        if self.side_length <= hole.get_max_square_peg_size():
            print("Square_Peg with side_length", self.side_length, "fits!")
        else:
            print("Square_Peg with side_length", self.side_length, "won't fit!!!")



class Square_Peg_Object_Adapter:
    def __init__(self, peg):
        self.peg = peg

    def make_fit(self, hole):
        if self.peg.side_length > hole.get_max_square_peg_size():
            amount_to_reduce = self.peg.side_length - hole.get_max_square_peg_size()
            print("Square_Peg with side_length", self.peg.side_length, "is currently too big!")
            print("    reducing size by", amount_to_reduce)
            self.peg.side_length = self.peg.side_length - amount_to_reduce
            print("Trying Square_Peg with with new side_length", self.peg.side_length, "!")

        if self.peg.side_length <= hole.get_max_square_peg_size():
            print("Square_Peg with side_length", self.peg.side_length, "fits!")
        else:
            print("Square_Peg with side_length", self.peg.side_length, "won't fit!!!")

print("TESTING SMALL AND LARGE SQUARE PEG ----")
hole = Round_Hole(5)
peg = Square_Peg(5)
peg.make_fit(hole)

peg = Square_Peg(10)
peg.make_fit(hole)

print("\n\nTESTING CLASS ADAPTER -----------------")
peg_adapter = Square_Peg_Class_Adapter(10)
peg_adapter.make_fit(hole)

print("\n\nTESTING OBJECT ADAPTER ----------------")
peg_adapter = Square_Peg_Object_Adapter(peg)
peg_adapter.make_fit(hole)

Expected output:

TESTING SMALL AND LARGE SQUARE PEG ----
Round_Hole: max Square_Peg size is 7.0710678118654755
Square_Peg with side_length 5 fits!
Square_Peg with side_length 10 won't fit!!!


TESTING CLASS ADAPTER -----------------
Square_Peg with side_length 10 is currently too big!
    reducing size by 2.9289321881345245
Trying Square_Peg with with new side_length 7.0710678118654755 !
Square_Peg with side_length 7.0710678118654755 fits!


TESTING OBJECT ADAPTER ----------------
Square_Peg with side_length 10 is currently too big!
    reducing size by 2.9289321881345245
Trying Square_Peg with with new side_length 7.0710678118654755 !
Square_Peg with side_length 7.0710678118654755 fits!

If we have time, we'll do the Observer pattern:

class Scoreboard:
    def __init__(self):
        self._observers = set()
        self._current_score = 0

    def attach(self, observer):
        observer._subject = self
        self._observers.add(observer)

    def detach(self, observer):
        observer._subject = None
        self._observers.discard(observer)

    def _notify(self):
        for observer in self._observers:
            observer.update(self._current_score)

    @property
    def current_score(self):
        return self._current_score

    @current_score.setter
    def current_score(self, new_score):
        self._current_score = new_score
        self._notify()


class Observer:
    def __init__(self):
        self._subject = None
        self._observer_state = None

    def update(self, arg):
        pass


class ConcreteObserver(Observer):
    def update(self, arg):
        self._observer_state = arg
        print("Observer sees new score!!:", self._observer_state)


def main():
    scoreboard = Scoreboard()
    concrete_observer = ConcreteObserver()
    concrete_observer2 = ConcreteObserver()
    scoreboard.attach(concrete_observer)
    scoreboard.attach(concrete_observer2)
    scoreboard.current_score = 123


if __name__ == "__main__":
    main()

Code adapted from examples provided at http://sourcemaking.com.

more ...