Please open notebook rsepython-s4r5.ipynb
Let’s import the context for this chapter.
from context import *
In this reading, we will finally discuss the thing most people think of when they refer to “Software Engineering”: the deliberate design of software.
We will discuss processes and methodologies for planned development of large-scale software projects: Software Architecture.
The software engineering community has, in large part, focused on an object-oriented approach to the design and development of large scale software systems.
The basic concepts of object orientation are necessary to follow much of the software engineering conversation.
In addition to object-oriented architecture, software engineers have focused on the development of processes for robust, reliable software development.
These codified ways of working hope to enable organisations to repeatably and reliably complete complex software projects in a way that minimises both development and maintenance costs, and meets user requirements.
Software engineering theory has largely been developed in the context of commercial software companies.
The extent to which the practices and processes developed for commercial software are applicable in a research context is itself an active area of research.
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def grow_up(self):
self.age+=1
jameel=Person("Jameel",27)
jameel.home="London"
Notice, that in Python, you can add properties to an object once it’s been defined. Just because you can doesn’t mean you should!
Class: A user-defined type
class MyClass:
pass
Instance: A particular object instantiated from a class.
my_object = MyClass()
Method: A function which is “built in” to a class
from context import *
class MyClass:
def someMethod(self, argument):
pass
my_object=MyClass()
my_object.someMethod(value)
Constructor: A special method called when instantiating a new object - ‘ init’
class MyClass:
def __init__(self, argument):
pass
my_object = MyClass(value)
Member variable: a value stored inside an instance of a class.
class MyClass:
def __init__(self):
self.member = "Value"
my_object = MyClass()
assert(my_object.member == "Value")
Smell: A data structure made of nested arrays and dictionaries becomes unwieldy
Before:
from random import random
birds = [{"position": random(),
"velocity": random(),
"type": kind} for kind in bird_types]
average_position = average([bird["position"] for bird in birds])
After:
class Bird(object):
def __init__(self,type):
from random import random
self.type = type
self.position = random()
self.velocity = random()
birds = [Bird(type) for type in bird_types]
average_position = average([bird.position for bird in birds])
Smell: A function is always called with the same kind of thing
Before:
def can_see(source,target):
return (source.facing-target.facing)<source.viewport
if can_see(hawk,starling):
hawk.hunt()
After:
class Bird(object):
def can_see(self,target):
return (self.facing-target.facing)<self.viewport
if hawk.can_see(starling):
hawk.hunt()
Smell: A variable is nearly always used in arguments to a class.
class Person(object):
def __init__(self, genes):
self.genes=genes
def reproduce_probability(self,age): pass
def death_probability(self,age): pass
def emigrate_probability(self,age): pass
After:
class Person(object):
def __init__(self, genes, age):
self.age=age
self.genes=genes
def reproduce_probability(self): pass
def death_probability(self): pass
def emigrate_probability(self): pass
Smell: A global variable is referenced by a few functions
name = "Terry Jones"
birthday = [1, 2, 1942]
today = [22, 11]
if today == birthday[0:2]:
print(f"Happy Birthday, {name}")
else:
print("No birthday for you today.")
No birthday for you today.
class Person(object):
def __init__(self, birthday, name):
self.birth_day = birthday[0]
self.birth_month = birthday[1]
self.birth_year = birthday[2]
self.name = name
def check_birthday(self, today_day, today_month):
if not self.birth_day == today_day:
return False
if not self.birth_month == today_month:
return False
return True
def greet_appropriately(self, today):
if self.check_birthday(*today):
print(f"Happy Birthday, {self.name}")
else:
print("No birthday for you.")
john = Person([5, 5, 1943], "Michael Palin")
john.greet_appropriately(today)
No birthday for you.
Next: Reading - Class design