Lecture 29 - KA Day 3: Maintenance & Security / Professional Issues

Lecture Date: Tuesday, April 30

General Info

Each Knowledge Assessment is expected to take around 30 minutes to complete. On each KA day, there will be two KAs available, based on whatever the latest two major subject areas of the class were:

  • KA Day 1: Software Process and Requirements
  • KA Day 2: Verification & Validation and Architecture & Design
  • KA Day 3: Maintenance & Security and Professional Issues

All Knowledge Assessments are bound by the Honor System as any other assessment at UVA. You are forbidden to speak of specifics of any assessment with other students who have not yet taken the assessment.

Each KA is worth 10000 XP. Each question will be graded wholistically. That is, each question can either earn full XP, no XP, or a single partial level of XP. For example, a KA with 5 questions would assign 2000 XP to each question, and each question could earn 2000 XP, 1000 XP, or 0 XP. Students will have the opportunity to earn back at least a portion of missed XP during the Final Exam period as you can retake some portions of previous KAs.

Maintenance & Security Knowledge Assessment

  • Expect to answer questions regarding:
    • Design Patterns - You don't have to have them memorized, but you may be given one to evaluate, and you definitely need to know why they are important.
    • Maintenance - Why is it the most costly of the phases? What are the different types of maintenance - perfective, adaptive, corrective? Why would developers want to do continuous refactoring, identifying code smells? What skills does a developer need to have to be good at maintenance?
    • Security - Know in general what can be done during each phase of development to engineer more secure software.

Professional Issues Knowledge Assessment

  • Expect to answer questions regarding:
    • Given a particular ethics problem, what would you do? (you do not need to have the code memorized, but you should know the general overall concept of what the code is asking you to do - we will provide relevant parts of the code as needed)
    • Why do you think a developer might not follow the code of ethics?

Make sure to listen to the lecture from 4/25 for a full review of what to know!

more ...

Lecture 28 - Course Review

Lecture Date: Thursday, April 25

A review for Tuesday plus a whole lot of logistics!

(There was an error in the 11:00 recording, but the 2:00 is fine.)

more ...



Lecture 25 - Adam Glaser, Appian

Lecture Date: Tuesday, April 16

Guided Practice H Today

Today, Adam Glaser, VP of Product Development at Appian, will be joining us to talk about Appian's development process.

No audio recording

more ...


Lecture 23 - Engineering Software Security

Lecture Date: Tuesday, April 9

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 - Maintenance

Lecture Date: Tuesday, April 2

Guided Practice H: Maintenance In-Class Today

"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

11:00 Lecture:

2:00 Lecture:

more ...

Lecture 20 - Design Patterns

Lecture Date: Thursday, March 28

Today we will discuss software design patterns. These are similar to the architecture patterns we have already discussed in theory, but are more around specfific programming solutions, rather than high-level solutions.

Slides - Software Design Patterns

Adapter Pattern

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)

# 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!

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()

Singleton Pattern

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;
    }
}
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());

Abstract Factory Pattern

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();
}
PhraseFactory myPhraseGenerator = PhraseFactory.getFactory(PhraseFactory.COOL);
System.out.println(myPhraseGenerator.getPhrase());

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

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

more ...