Test-driven development: a case study

1,445 views
1,388 views

Published on

How test-driven development enabled Gnowsis to reimplement Refinder's basic data model.

Talk at Warsaw DjangoPiwo meetup on 2011-11-02.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,445
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Test-driven development: a case study

    1. 1. TDD
    2. 2. RED GREENREFACTOR
    3. 3. Effect?
    4. 4. More code
    5. 5. More simple code
    6. 6. More simple code, delivered faster
    7. 7. Cleanerinterfaces
    8. 8. Betterunderstanding of codebase
    9. 9. Fast & precise regression discovery
    10. 10. Easyrefactoring
    11. 11. Casestudy
    12. 12. Things come together. Semantic socialcollaboration platform
    13. 13. Things come together.Python/DjangoPostgreSQLApache SolrCustom Java backend
    14. 14. RDF-based APIsGraphs of linked dataURIs as identifiersSubject-Predicate-Objecttriples
    15. 15. <_:me> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .<_:me> <http://xmlns.com/foaf/0.1/family_name> "Pasternacki" .<_:me> <http://xmlns.com/foaf/0.1/givenname> "Maciej" .<_:me> <http://xmlns.com/foaf/0.1/homepage> <http://www.pasternacki.net/> .<_:me> <http://xmlns.com/foaf/0.1/mbox> <mailto:maciej@pasternacki.net> .<_:me> <http://xmlns.com/foaf/0.1/name> "Maciej Pasternacki" .<_:me> <http://xmlns.com/foaf/0.1/nick> "japhy" .<_:me> <http://xmlns.com/foaf/0.1/workplaceHomepage> <http://www.gnowsis.com/> . @prefix : <#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . :me a foaf:Person . :me foaf:family_name "Pasternacki" . :me foaf:givenname "Maciej" . :me foaf:homepage <http://www.pasternacki.net/> . :me foaf:mbox <mailto:maciej@pasternacki.net> . :me foaf:name "Maciej Pasternacki" . :me foaf:nick "japhy" . :me foaf:workplaceHomepage <http://www.gnowsis.com/> .
    16. 16. Item Relation uuid : uuid type : uri rdf_type : URI * label : string created : dateTime lastModified: dateTime Description text : string target (1) Thing Annotation Rating value : normalizedFloat InformationElement Wiki text : string Property File type : uripath : string lexicalForm : stringmimeType : string... Webpage url : string summary : string StringProperty Email subject : string value : string ... IntProperty value : integer Blogpost Tweet DatetimeProperty timestamp : dateTime author : string value : datetime author : string text : string ... ...
    17. 17. def promote(self): if not hasattr(self, _promoted): if isinstance(self, self.get_class()): self._promoted = self else: self._promoted = getattr( self, getattr( self.get_class(), self._root_class_name + _ptr ).field.related_query_name() ) return self._promotedSELECT … FROM "pim_annotation"LEFT OUTER JOIN "pim_related"ON ("pim_annotation"."id" = "pim_related"."annotation_ptr_id")WHERE ( "pim_annotation"."thing_id" = E∴ OR "pim_related"."related_to_id" = E∴ )ORDER BY "pim_annotation"."lastModified" DESC;
    18. 18. NoSQL?
    19. 19. NoSQL?
    20. 20. “How FriendFeeduses MySQL to store schema-less data”-- http://bret.appspot.com/entry/how-friendfeed-uses-mysql
    21. 21. Use PostgreSQLas RDF document-oriented database
    22. 22. Single Thing classMany concreteAnnotation classesTEXT field `attributes’for free-form RDF
    23. 23. No JOINs
    24. 24. RulesKeep existing code(when possible)Keep existing behaviourKeep magic localized
    25. 25. I. New codeRDFField & URIRefField usingrdflibCustomized RDF serialization
    26. 26. II. AnalysisExtract existing schema frommodel codeDeclare schema in RDFGlue code for attribute access toRDF data
    27. 27. nfo:Bookmark rdfs:subClassOf pimo:Thing ; grfs:className "Bookmark" ; grfs:label "nfo:Bookmark" ; grfs:pluralLabel "nfo:Bookmarks" ; grfs:isGuiCreatable "true"^^xsd:boolean ; grfs:labelProperties ( dct:title rdfs:label nfo:bookmarks ) ; grfs:shortSummaryInfoProperties ( nfo:bookmarks ) .nao:description a rdfs:Property ; rdfs:domain pimo:Thing, pimo:Person, pimo:Event, nfo:Bookmark,pimo:Project, pimo:Person, nfo:FileDataObject, pimo:Topic, pimo:Location,pimo:Task, nmo:Email, pimo:Question, pimo:Organization, pimo:Note,pimo:Collection; grfs:attributeName "description" ; grfs:ftsFullText "true"^^xsd:boolean ; grfs:additionalShortSummaryInfo "false"^^xsd:boolean .nfo:bookmarks a rdfs:Property ; rdfs:domain nfo:Bookmark ; grfs:attributeName "bookmarks" ; grfs:ftsFullText "true"^^xsd:boolean ; grfs:additionalShortSummaryInfo "true"^^xsd:boolean .
    28. 28. SELF_URI = URIRef(self:#)def __getattr__(self, attr): property_uri = attribute_uri(attr) oo = list(self.attributes.objects( self.SELF_URI, property_uri)) if not oo: raise AttributeError(attr) if len(oo) == 1: return oo[0].toPython() return set([o.toPython() for o in oo])
    29. 29. III. DetailsRun test suiteFind most common errorAdapt test or change codeRepeat for three weeks
    30. 30. IV. TweakingData migrationRefactor APIsOptimize
    31. 31. Success!
    32. 32. Things come together.http://www.getrefinder.com/

    ×