Page trail: Topic map-based informatio... :: ActionScript 3 programming... :: Agile software development...
Agile software development models in Python 3
Agile software development models in Python 3
Some links:
Managing development teams
Trying to effectively manage several teams of developers is a challenge, to say the least.
Obviously, in a typical software development process there are quite a few different actors and entities, including (in no specific order):
- backlog items
- bugs
- developers
- iterations (in the Agile/Scrum sense of the word)
- (project) portfolio
- projects
- products
- release criteria
- requirements
- risks
- stakeholders
- tasks
- teams
Each one of the above actors or entities have their own properties and/or include references to the other actors/entities. For example, a bug has a description, a severity and a priority. A bug in itself, is linked back to a specific backlog-item. Backlog-items, however, also have a list of associated tasks, and so on.
Anyway, code speaks louder than words, so take a look at the (unfinished, Python 3) source below:
entity.py:
import uuid
from datetime import datetime
#===============================================================================
class Entity():
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True):
self.__identifier = (uuid.uuid1() if identifier is None else identifier)
self.__creation_date = datetime.now()
self.name = name
self.comment = comment
self.active = active
@property
def identifier(self):
return self.__identifier
@property
def creation_date(self):
return self.__creation_date
developer.py:
import uuid
from entity import Entity
#===============================================================================
class Developer(Entity):
def __init__(self,
identifier=uuid.uuid1(),
name='undefined',
comment='',
position='undefined'):
super().__init__(identifier, name, comment)
self.__position = position
self.__knowledge_areas = []
@property
def position(self):
return self.__position
@property
def knowledge_area(self):
return self.__knowledge_areas
def add_knowledge_area(self, knowledge_area):
self.__knowledge_areas.append(knowledge_area)
def remove_knowledge_area(self, knowledge_area):
self.__knowledge_areas =
list(item for item in self.__knowledge_areas if item != knowledge_area)
task.py:
from entity import Entity
from developer import Developer
#===============================================================================
class Task(Entity):
def __init__(self,
description,
identifier=None,
name='undefined',
comment='',
active=True):
super().__init__(identifier, name, comment, active)
self.description = description
# one of: not started, in progress, impeded or done
self.__status = 'not started'
# list of Developer objects of which the first one is the point person
self.__developers = []
# minimum amount of time that a task can take
self.__estimated_hours = 1
@property
def status(self):
return self.__status
@status.setter
def status(self, value):
states = {'not started', 'in progress', 'impeded', 'done'}
if len(states - {value.lower()}) == 4:
# temporary code, should raise an appropriate exception,
# i.e., unknown status
pass
else:
self.__status = value
@property
def developers(self):
return self.__developers
@property
def estimated_hours(self):
return self.__estimated_hours
@property
def point_person(self):
return self.__developers[0]
@point_person.setter
def point_person(self, value):
# check to see if the point person (passed through as a parameter)
# is already in the list of developers assigned to this task and
# if she is, set her as the first person in the list of developers
# effectively making her the point person for this task
# (see the 'point_person' property). If the point person is not
# in the list of developers (i.e., assigning a new developer to
# the task), then prepend her to the list of developers.
pass
def add_developer(self, developer):
self.__developers.append(developer)
def remove_developer(self, identity):
pass
backlogitem.py:
from entity import Entity
from task import Task
#===============================================================================
class BacklogItem(Entity):
def __init__(self,
description,
identifier=None,
name='undefined',
comment='',
active=True):
super().__init__(identifier, name, comment, active)
self.description = description
self.__tasks = [] # list of Task objects
self.__bugs = [] # list of Bug objects
@property
def tasks(self):
return self.__tasks
@property
def bugs(self):
return self.__bugs
def add_task(self, task):
self.__tasks.append(task)
def remove_task(self, identity):
pass
def add_bug(self, bug):
self.__bugs.append(bug)
def remove_bug(self, identity):
pass
Updated on May 03, 2010
team.py:
from entity import Entity
class Team(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True):
super().__init__(identifier, name, comment, active)
self.__developers = [] # list of Developer objects
@property
def developers(self):
return self.__developers
def add_developer(self, developer):
self.__developers.append(developer)
def remove_developer(self, identity):
pass
stakeholder.py:
from entity import Entity
#===============================================================================
class Stakeholder(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True):
super().__init__(identifier, name, comment, active)
risk.py:
from entity import Entity
#===============================================================================
class Risk(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True,
description='undefined',
probability=1,
impact=0,
response_plan=False):
super().__init__(identifier, name, comment, active)
self.description = description
self.probability = probability
self.impact = impact
self.response_plan = response_plan
@property
def score(self):
return self.probability * self.impact
requirement.py:
from entity import Entity
from stakeholder import Stakeholder
#===============================================================================
class Requirement(Entity):
def __init__(self,
description,
identifier=None,
name='undefined',
comment='',
active=True,
requestor=None):
super().__init__(identifier, name, comment, active)
self.description = description
self.__requestor = requestor # reference to a Stakeholder object
@property
def requestor(self):
return self.__requestor
@requestor.setter
def requestor(self, value):
# Do we want to limit the requestor to being the product owner? If that is the case,
# then we can remove this property completely from the Requirement class as the
# product owner is already tracked in the Product class.
self.__requestor = value
releasecriterion.py:
#===============================================================================
class ReleaseCriterion:
def __init__(self,
description,
comment=''):
self.description = description
self.comment = comment
self.specific = True
self.measurable = True
self.attainable = True
self.relevant = True
self.trackable = True
@property
def is_valid(self):
return self.specific
and self.measurable
and self.attainable
and self.relevant
and self.trackable
projectscope.py:
from product import Product
#===============================================================================
class ProjectScope:
def __init__(self, description):
self.description = description
self.__products = [] # list of Product objects
self.__dependencies = [] # list of other Project objects, i.e., dependencies
self.__release_critera = [] # list of ReleaseCriterion objects
@property
def products(self):
return self.__products
@property
def dependencies(self):
return self.__dependencies
@property
def release_criteria(self):
return self.__release_criteria
@property
def is_valid(self):
result = True
for release_criterion in self.__release_criteria:
if release_criterion.is_valid == False:
result = False
break
return result
project.py:
from entity import Entity
from projectscope import ProjectScope
from risk import Risk
from iteration import Iteration
#===============================================================================
class Project(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True,
description='undefined'):
super().__init__(identifier, name, comment, active)
self.__scope = ProjectScope(description)
self.__stakeholders = [] # list of Stakeholder objects
self.__risks = [] # list of Risk objects
self.__iterations = [] # list of Iteration/Sprint objects
# What about the 'project driver' matrix? That is:
# Priority Rank
# ======================
# Release date 1
# Feature set 2
# Low defects 3
@property
def scope(self):
return self.__scope
@property
def stakeholders(self):
return self.__stakeholders
@property
def risks(self):
return self.__risks
@property
def iterations(self):
return self.__iterations
def add_stakeholder(self, stakeholder):
pass
def remove_stakeholder(self, identity):
pass
def add_risk(self, risk):
pass
def remove_risk(self, identity):
pass
def add_iteration(self, iteration):
pass
def remove_iteration(self, identity):
pass
product.py:
import uuid
from entity import Entity
#===============================================================================
class Product(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True,
description='undefined',
product_owner=None):
super().__init__(identifier, name, comment, active)
self.description = description
self.__requirements = [] # list of Requirement objects
self.__product_owner = product_owner
@property
def requirements(self):
"""Return a list of the software functionality."""
return self.__requirements
@property
def product_owner(self):
return self.__product_owner
@product_owner.setter
def product_owner(self, value):
self.__product_owner = value
def add_requirement(self, requirement):
self.__requirements.append(requirement)
def remove_requirement(self, identity):
pass
portfolio.py:
from entity import Entity
from project import Project
from team import Team
#===============================================================================
class Portfolio(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True):
super().__init__(identifier, name, comment, active)
self.__projects = [] # list of Project objects (sinks)
self.__teams = [] # list of Team objects (sources)
@property
def projects(self):
return self.__projects
@property
def teams(self):
return self.__teams
def add_project(self, project):
self.__projects.append(project)
def remove_project(self, identity):
pass
def add_team(self, team):
self._teams.append(team)
def remove_team(self, identity):
pass
iteration.py:
from entity import Entity
from backlogitem import BacklogItem
#===============================================================================
class Iteration(Entity):
def __init__(self,
start_date,
end_date,
identifier=None,
name='undefined',
comment='',
active=True):
super().__init__(identifier, name, comment, active)
self.start_date = start_date
self.end_date = end_date
self.__backlog_items = [] # list of (committed) BacklogItem objects
@property
def backlog_items(self):
return self.__backlog_items
def add_backlog_item(backlog_item):
self.__backlog_items.append(backlog_item)
def remove_backlog_item(backlog_item):
pass
bug.py:
from entity import Entity
#===============================================================================
class Bug(Entity):
def __init__(self,
identifier=None,
name='undefined',
comment='',
active=True,
description='undefined',
severity='critical',
priority='now'):
super().__init__(identifier, name, comment, active)
self.description = description
self.__severity = severity
self.__priority = priority
@property
def severity(self):
return self.__severity
@property
def priority(self):
return self.__priority
@severity.setter
def severity(self, value):
# Severity is Technical but Absolute: an assessment of the impact of the bug
# without regard to other work in the queue or the current schedule.
states = {'critical', 'high', 'medium', 'low'}
if len(states - {value.lower()}) == 4:
# temporary code, should raise an appropriate exception, e.g., unknown severity
pass
else:
self.__severity = value
@priority.setter
def priority(self, value):
# Priority is Business, but Relative: a subjective evaluation of how important
# an issue is, given other tasks in the queue and the current schedule.
states = {'now', 'p1', 'p2', 'p3'}
# Now: drop everything and take care of it as soon as you see this (usually
# for blocking bugs)
# P1: fix before next build to test
# P2: fix before final release
# P3: we probably won't get to these, but we want to track them anyway
if len(states - {value.lower()}) == 4:
# temporary code, should raise an appropriate exception, e.g., unknown priority
pass
else:
self.__priority = value
To be continued
Click here to be able to create pages, upload images and file attachments, and link to other users and their pages.
blog comments powered by Disqus