Be agile: take back control over your work
-
Upload
massimo-azzolini -
Category
Business
-
view
454 -
download
1
Transcript of Be agile: take back control over your work
agile.open.connectedEssere agili?
Metodi, strumenti e integrazioniPython “to rule them all” Massimo Azzolini
Massimo Azzolini
Founder - Project manager
RedTurtle - Ferrara - Italy
@massimoazzolini
www.redturtle.it
Massimo Azzolini
Not an agile
guru
being agile...
Massimo Azzolini
The agile manifesto
➡ Individuals and interactions over processes and tools
➡ Working software over comprehensive documentation
➡ Customer collaboration over contract negotiation
➡ Responding to change over following a plan
12 principles of agile manifesto
1. Satisfy the customer
2. Welcome changing requirements
3. Deliver working software frequently
4. Business people and developers work together
5. Build projects around motivated individuals.
6. Face-to-face conversation
7. Working software is the primary measure of progress
8. Agile processes promote sustainable development
9. Attention to technical and design excellence
10. Simplicity is essential
11. The best architectures and requirements emerge from self-organizing teams
12. Retrospective
12 principles of agile manifesto
Kanban?
Scrum?
Scrum
Kanban
so how can I make it
U S E F U L ?
Massimo Azzolini
The structure
Started in 1999 in Ferrara, in 2012 we have had:
★ 14 people in house
★ most backend developers
★ 4 freelancer (not RedTurtle)
★ 3 teams
★ 77 projects
★ 347 customer requests
★ 1943 tickets solved
★ 20K+ hours worked
ISO 9001
no, I mean really
U S E F U L ? !
trainings and conferences
Scrum doesn’t completely fit to us
Kanban doesn’t completely fit to us
LOL
Massimo Azzolini
What is left?
1. Teams
2. Iterations
3. Agile team to embrace the verb
4. Introduce 1-2 new tools/methods after every agile meeting
5. Multiple kanban boards (personal vs group vs project)
6. WIP limit and customers’ delays
7. Value your time
8. Write everything
9. Code review
Massimo Azzolini
Which tools?
➡ Email?!
➡ Share Documents
‣ Google Drive
‣ Dropbox
➡ Organize tasks
‣ Trello o Kanbanery
‣ Simple management (or other plone based solutions)
‣ Basecamp
Penelope
getpenelope.github.com
Project journey
A new
project Google
Documentation
Project Manager
Customer
requests
TracReports
DashboardGoogle
Documentation
Customer
Trac - tickets
Trac - roadmap
Dashboard
Trac
Developer
Time
management
Sentry Customer
requestsTime
management
Show me the code!!!
OAuth/Login
Google OAuth2 example
[app:penelope]...pyramid.includes = velruse.providers.googleprovider.google.consumer_key = 441361239240193provider.google.consumer_secret = 52ef2618a1999eeec6d9cprovider.google.scope = https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/drive.apps.list
wgsi.ini
GDrive integration
GDrive Integration
@documents.auth_gracefuldef get_google_document(context, request, **kwargs): try: folder_entry = request.gclient['DocsClient'].get_doclist(
uri='/feeds/default/private/full/%s/contents/' % folder_id) folder = folder_entry.entry
except (ValueError, RequestError), e: status = u'''Something is not working correctly.''' params.update(folder=folder, status=status)
Trac integration
TicketStore - Trac Integration
class ITicketStore(Interface):
def get_tickets_for_project(self, project, request, query=None, limit=None):
""" """
def get_requests_from_tickets(self, project, ticket_ids, request=None):
""" """
def get_tickets_for_request(self, customer_request, limit=None, request=None): """ """
Deform/Colander
Deform/Colander
@view_config(renderer='templates/form.pt', name='myform')def myform(self): class Mapping(colander.Schema): name = colander.SchemaNode( colander.String(), description='Content name') date = colander.SchemaNode( colander.Date(), widget=deform.widget.DatePartsWidget(), description='Content date') class Schema(colander.Schema): number = colander.SchemaNode( colander.Integer()) mapping = Mapping() schema = Schema() form = deform.Form(schema, buttons=('submit',)) return self.render_form(form)
Deform/Colander
Mandrill
def send(self, from_addr, recipients, data): # Ensure the message complies with RFC2822: use CRLF line endings message = data['msg'] data = data['data']
params = {}
changes_body = data['changes_body'] if changes_body: params['changes_body'] = rest2html(changes_body)
if data['ticket']['new']: params['ticket_new'] = True
params['ticket_body_hdr'] = data['ticket_body_hdr'] params['ticket_link'] = data['ticket']['link'] params['ticket_reporter'] = data['ticket']['reporter'] params['ticket_owner'] = data['ticket']['owner'] params['ticket_description'] = self.wiki2html(data['ticket']['description']) params['ticket_type'] = data['ticket']['type'] params['ticket_status'] = data['ticket']['status'] params['ticket_priority'] = data['ticket']['priority'] params['ticket_milestone'] = data['ticket'].get('milestone') params['change_author'] = data['change'].get('author','') params['change_comment'] = self.wiki2html(data['change'].get('comment','')) params['project_name'] = data['project']['name'] params['project_url'] = data['project']['url']
message.add_header('X-MC-Template', 'ticket') message.add_header('X-MC-MergeVars', json.dumps(params))
message.set_payload('')
message = message.as_string() message = fix_eol(message, CRLF) self.log.info("Sending notification through SMTP at %s:%d to %s" % (self.smtp_server, self.smtp_port, recipients))
server = smtplib.SMTP(self.smtp_server, self.smtp_port) if self.smtp_user: server.login(self.smtp_user.encode('utf-8'), self.smtp_password.encode('utf-8')) server.sendmail(from_addr, recipients, message) server.quit()
Mandrill
Sentry
Sentry-Penelope
class PenelopePlugin(IssuePlugin): def create_issue(self, request, group, form_data, **kwargs): proxy = TracXmlProxy(form_data['trac'], request=request) try: opts = {'type': 'defect', 'issuetype': 'sistemistica', 'customerrequest': '', 'owner': ''} ticket = proxy.ticket.create(form_data['title'], form_data['description'], opts) except Exception, e: msg = unicode(e) raise forms.ValidationError(_('Error communicating: %s') %(msg,))
try: data = int(ticket) except Exception, e: raise forms.ValidationError(_('Error decoding response: %s') % (e,))
return data
Solr - trac full text search
Questions ?
Massimo AzzoliniRedTurtle’s co-founder and project [email protected] tw: @massimoazzolini