Pythonic Refactoring: Protecting Your Users From Change

Video in TIB AV-Portal: Pythonic Refactoring: Protecting Your Users From Change

Formal Metadata

Pythonic Refactoring: Protecting Your Users From Change
Title of Series
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this license.
Release Date

Content Metadata

Subject Area
Pythonic Refactoring: Protecting Your Users From Change [EuroPython 2017 - Talk - 2017-07-14 - PythonAnywhere Room] [Rimini, Italy] So you've released a library! Now you need to maintain it. You want to add features, restructure the code, fix bugs, and maybe improve the library's usability. Your users just want their code to carry on working. That's okay! This talk will cover techniques in both code and project management to allow you to keep your code moving forwards without breaking your users' code. It is aimed at developers with a little experience of writing libraries in Python, and will cover some intermediate subjects like function decorators and magic methods. Refactoring in Python is a mixed bag - on the one hand you have powerful tools like the @property decorator, dunder methods, and even metaclasses. On the other hand, because Python code has no concept of private or protected like some other languages, it can be difficult to know what your public interface even is. I'll talk about how to identify your public interface, and make that clear to your users. I'll cover how to structure your tests so you know when you've broken your public interface. I'll discuss how to use some of Python's language features to trick your users into thinking your code hasn't changed at all (except for those brilliant new features you've just added!). And finally, I'll cover how you know it's time to break backwards compatibility and how to break it to your users
Mathematics Intel Electronic data interchange Software Code refactoring Event horizon Smith chart
Group action Roundness (object) Software developer Code Software developer
Web page Point (geometry) Code Java applet Multiplication sign Client (computing) Mereology Formal language Product (business) Goodness of fit Mathematics Code refactoring Data structure Computer architecture God Code Interface (computing) Representational state transfer Software maintenance System call Message passing Process (computing) Order (biology) Code refactoring Convex hull Pattern language Resultant Library (computing)
Dynamical system Functional (mathematics) Code Multiplication sign Decision theory Data recovery 1 (number) Control flow Parameter (computer programming) Client (computing) Interface (computing) Variable (mathematics) Product (business) Web 2.0 Causality Hierarchy Negative number Boundary value problem Software framework Utility software Data structure Stability theory Social class Exception handling Module (mathematics) Interface (computing) Bit Variable (mathematics) Type theory Function (mathematics) Order (biology) Library (computing)
Bytecode Functional (mathematics) Code Helmholtz decomposition Function (mathematics) Order (biology) Data structure Interface (computing) Rule of inference Variable (mathematics)
Addition Functional (mathematics) Code Interface (computing) Analogy Source code Object (grammar) Variable (mathematics) System call Social class Exception handling Library (computing)
Module (mathematics) Functional (mathematics) Server (computing) Implementation Computer file Code Multiplication sign Interface (computing) Electronic mailing list Interface (computing) Client (computing) Flow separation System call Message passing Ideal (ethics) Endliche Modelltheorie Right angle Object (grammar) Endliche Modelltheorie Logic gate Library (computing) Compact space
Point (geometry) Functional (mathematics) Implementation Module (mathematics) Code Source code Revision control Goodness of fit Term (mathematics) Different (Kate Ryan album) Analogy Gastropod shell Series (mathematics) Social class Module (mathematics) Default (computer science) Namespace Software developer Weight Interface (computing) Code Bit Letterpress printing Machine code Line (geometry) Software maintenance Order (biology) Interface (computing) Data structure Writing Library (computing)
Addition Default (computer science) Functional (mathematics) Run time (program lifecycle phase) Code Interface (computing) Code Software documentation Software maintenance Formal language Type theory Mathematics Goodness of fit Interface (computing) Software testing Software testing Library (computing) Asynchronous Transfer Mode
Euclidean vector Code INTEGRAL Multiplication sign 1 (number) Instance (computer science) Interface (computing) Mathematics Type theory Object (grammar) Category of being Information security Monster group Social class Electric generator Block (periodic table) Constructor (object-oriented programming) Electronic mailing list Attribute grammar Unit testing Instance (computer science) Category of being Interface (computing) Code refactoring Software testing Information security Physical system Reading (process) Resultant Point (geometry) Functional (mathematics) Mobile app Link (knot theory) Patch (Unix) Real number Disintegration Control flow Branch (computer science) Automatic differentiation Attribute grammar Revision control Latent heat Goodness of fit Software testing Code refactoring Implementation Default (computer science) Module (mathematics) Execution unit Patch (Unix) Interface (computing) Gender Surface Code Machine code Numerical analysis Mathematics Software Function (mathematics) Factory (trading post) Object (grammar) Communications protocol Library (computing)
Functional (mathematics) Module (mathematics) Hoax Multiplication sign Instance (computer science) Protein folding Fluid statics Object (grammar) Energy level Category of being Social class Default (computer science) Module (mathematics) Mobile app Default (computer science) Interface (computing) Bit Ultraviolet photoelectron spectroscopy Instance (computer science) Variable (mathematics) Numerical analysis Type theory Category of being Personal digital assistant Object (grammar) Resultant
Module (mathematics) Category of being Functional (mathematics) Module (mathematics) Object (grammar) Multiplication sign Electronic mailing list Instance (computer science) Object (grammar) Cartesian coordinate system Category of being Food energy
Point (geometry) Functional (mathematics) Randomization System call Code State of matter Parameter (computer programming) Mass Rule of inference Different (Kate Ryan album) Object (grammar) Cuboid Endliche Modelltheorie Set theory Social class Exception handling Constructor (object-oriented programming) Electronic mailing list Instance (computer science) Variable (mathematics) System call Demoscene Numerical analysis Mathematics Type theory Category of being Function (mathematics) Social class Iteration Quicksort Object (grammar) Arc (geometry)
Email Dynamical system Code Patch (Unix) Multiplication sign Control flow Client (computing) Software bug Formal language Mathematics Different (Kate Ryan album) Software testing Set theory Address space Exception handling Data type Default (computer science) Dependent and independent variables Multiplication Email Military base Interface (computing) Electronic mailing list Code Client (computing) Bit Machine code Twitter Category of being Type theory Personal digital assistant Code refactoring Iteration Exception handling Probability density function
few hello verbally and things very much for coming in on social event was pretty successful so uh and even more glad that you made it and were trying to shout too much during the talk and so before I go through the topic of this talk 1st about like to some talk about something more important so my name is
Mark Smith uh I'm a developer of because next month um by run the user group Python in Edinburgh or my handle on most social networks is gtk for reasons on this funny and as you might think of uh II and known for writing C Python code and then showing it to people for my own amusement um and despite the Viking helmet that I kind of users my my general round I'm not a viking all
Norwegian for Scandinavian here in any way and so we're talking about
next month at briefly uh sponsor the conference a new promise but may be spoken to me on the base if not then you would like to come and talk to me at some point later today and we've got REST API is for sending receiving uh SMS messages and making phone calls and can I just do a quick show of hands uh we we generally do this um because not many people have heard of this usually so before this Conference who heard of next the yeah it's getting better and so much of next most to maintain our client libraries uh for Python and Java and my and so am I maintain a library for God um and so I think a lot about compatibility and maintaining compatibility um and and just kind of work at my job is really to communicate with developers and find out what they want and trying to feed that back into product pipeline and so this talk really ended up not quite being about refactoring it's related but it's not quite about refactoring if you do you want to know more about refactoring uh I highly recommend this book has been around for a while I think it the concept generally um it contains 72 refactoring recipes um for kind of uh modifying your code in order to improve the quality of the structure in the architecture of the code that's very job centric um but it's got lots of experience in in the pages of the book but it's lots of good advice but some other patterns also don't really transfer to place job is a very different language to point the main theme of the book is to be prepared to all the time to be modifying your code to keep it clean up until our new architectures to emerge as you kind of distress discover them through developing and extending the library what the library's not really worried about is whether you break your users carried it doesn't worry so much about interfaces this is more worried about kind of code that is kind of you're allowed to change any time this this isn't
really true both libraries um this talk is really about Python library maintenance and it's got this assumption that the you have released code with 2 or more users um and so what that results in is you got a 1 to many relationship so if you break up the possibility in your 1 codebase your users in order to upgrade are going to have to change their code that's can be many changes so that's something that should be avoided so this is what the other part of this talk is about hiding change from new users and so it allows you to change things internally without affecting you users make to negative ways so a really of about is keeping our
interface stable while changing the coach um so the reasons you want a stable interface um I mean I think they're pretty obvious but go through them anyway is is really to keep your customers happy you keep you users happy and every scientist if you keep breaking backwards compatibility and they're gonna get unhappy in general because you making more work for them nobody likes being given work that they didn't necessarily want and and also every time you break backwards compatibility you're giving your users an opportunity to switch to competing products competing open-source library that if they go have to rewrite the code in order to keep on using your library when just switch to the new hot things and and this is happens in web frameworks set me a long time ago uh frameworks which I don't really want to name because I feel like I'm maybe demonizing little but but then uh there was a big lots of frameworks about 15 years ago In abuse really sure the right way to do things were and as they land often they brought back this compatibility and really war ended up the successful frameworks the ones that were still using today were really the ones that that worried a lot about maintaining backwards compatibility with the users so many libraries only survive if stable and that's why we want salient facts to talk about
this idea of an interface whoops and what is an interface and I think it is the boundary of your coat so it's it's the it's the the code that no user interfaces with so it's where you use a uses you present and and which if you change it its where your user will be affected and it consists of various components and so the obvious 1 is a module go go be importing you modular package so change name of fabless going to break things uh the thing we usually think about is that the module consists of classes and functions and methods and that interface agreement with the use of um to go sledding finer-grained recover parameters that functions methods school you change the names the expected types return values as well uh and this is going to affect your user negative ways we got global variables usually static but potentially you might want to change was something dynamic um announced that may cause problems something that people often don't think about up from these exceptions so if you change the names of your exceptions only the hierarchy of your exceptions and that's going to cause problems for your users and we've got a structure of our coat so this is really a Conway lives if you start off with a big uh and single namespace and you've got a kind of utility function you use might find that decide it's useful start using it and then if you decide to take it away and you tools packets package later on uh that's gonna break clients code that is not something you necessarily expected and finally there's is a little bit of a silly example but not by code as well so potentially even changing your bike carried could cause problems for your users so I don't know if people saw
Sebastian knocks um go to hack at the light talks that a couple days ago but he's got a decorator that decompose function and modifies the bytecode and recompiles it again in order to allow teams go to use and in the code so potentially changing the structure of your current might also break um you compatibility with you users this is really something you have to worry about is really they've broken all the rules of do that kind of thing this is really challenging the bigger topic of the talk is is making an agreement with your cost so
ideally interfaces your your deal with your customers as strict as possible I think of it as kind of of these kids
toys and so you got the idea of well-defined objects passing through the at the wall of the interface the validated on the way in and you may call functions methods with these objects and then ultimately well-defined stable well understood objects surpassed back or exceptions erased In the ideal world it's impossible to refer to classes methods functions or variables that aren't exposed by the interface the a couple days ago um and in
talk he used the analogy of roughly allegiance to the appropriate given where we are um and the idea that that you interfaces like the past the keeps the uh the filling of your your of yearly separate from the tasty tasty source stocks your past stopped addition just being a max and but the concept is really the idea is that even if you're not publishing your library if you don't even if you don't have external customers your code should be divided up this way it's much easier to understand but small well contained code libraries so
talking about strict interfaces here's some things that are like that like the definition of a strict interface like the Tory um and but they'll be a few snickers suspect looking at this list of technologies because none of these 2 technologies apart from maybe the first one we particularly enjoy working with the role a little bit painful if you want to define interfaces the GATE this you it essentially define your client code your server code and the 3rd module they shared between the 2 that is you all well understood interface um with soap you define it was still file which defines again incoming and outgoing objects so you define your interface separate from your implementation um and these are both of these ideas have been around for a long time the dates on kind of 16 17 years ago the 17 or 18 years ago and it goes back to corpora as well which is a hideous technology it's enormous and horrible to deal with the best and 26 years old and so these are the these of things or like a right that begins wars are ideal world places like that let's have a look at a quick example so this is a bit silly but firm imported requests um and just listing the stuff that's inside the requests library I'm sure we've all used at some point and we've got a magic thing that begins and ends with a double underscore we've got a private thing that starts with a single on the store and we've got some things with interesting names like gets the function compact which is a submodular modern models and then is not immediately obvious to some of these with the and private or public with respect to the use and and something stupid we can do that is we can import those modules that we can then define a function and then we can modify the request module is imported with our own get function um and than anywhere else in our
codebase where somebody imports requests to they get our modified requests and when the call get it doesn't make an HTTP request it is princess the city message but it gives the idea you can dig as deep as you want them to somebody else's Python code and switch out things um but they may not want to um and so we've gone from by
appropriate seaside analogy we we've gone from the idea of a library as having a kind of tough shell was difficult to break through that only gives you access to things on its terms and to more Python is which is really just kind of a box of like you can you can reach in you can grab anything you want you can take it apart and put it together in different ways and put it back in the box and so we really need to
do is kind of below this thank so we need to work with the tools that we have uh in order to build an agreement with you so we need to make our interface notable because we can't stop people from getting into our code so we have to make sure they understand what we expect from them and how do we do that we've got a few conventions um and that's so here I've got a private methods that it we know it's private because it begins with a single on the skull the single on the school doesn't change the behavior of the method a toll we can still call it and see the last line of code I call it works um but we know just by reading the name of the method that is considered to be an internal detailed were not really supposed to call from outside the scope and so we should be using these this is this is something that you can't get for free in agreement with your customers a private and implementation details detail the we sometimes see in less experienced developers codes is that they've read a book they've discovered this this double underscore prefix and start to use that for for private methods especially and and that is and what this was designed for this was designed to avoid namespace conflicts so this does change the behavior of some of the class that that the method name internally is changed and it's just prefix for the name of the class and a single on the school and so you can still call you haven't stopped me from calling it you just made it a little bit more difficult and alternate the user really wants to call that method they can call anyway all over by this point that probably copy and paste the code into the impact but it's it's a different kind of problem and a 3rd convention we have in Python world is just a kind of move the code of the weights so often you find in some quite popular libraries and there's a public module package of the top and this submodule internally that really contains all the codes and then in the public module that is the thing that the cost the user is expected to import and they just kind of imported the public interface is a public functions and classes from private submodular so just puts out the way somebody imports you'll your public module and and as a DIR everything they see is something that the expected to work with and that's that's good so I recommend that to but these are kind of you get this for free these the the conventions and Python what something a little bit more expensive but infinitely valuable this documentation documentation is the primary way to communicate with you users the place ecosystem has excellent documentation so much so that its spawned a series of international conferences dedicated to documentation read the docks conferences that I would say spun largely out of Python community and the reason documentation so proper in the Python wealth is that we've learned that users will use the interface that you document we usually distribute source code um as that our libraries has source code so somebody can read the code but you don't really want to if you don't write documentation users will reach OK it if you don't write documentation users will guess your interface and I guess rock which is not something that you want the so for documentation and I recommend Sphinx all make docs make doctors especially of the capital the Diggle the maintainer of my doctor sitting in front of me and so on the up before I I don't recommend also generating new documentation as it's a really bad idea it um by default everything is going to be published as documentation that's not what you want you want to filter your documentation down to the things you want your customers use um slightly related to this
is tight pants so means a recent additions to the language and I think it's still pretty controversial doesn't change the behavior of the code at run time by default and but it is used by IT to help users use the right types in going types into your functions and and return types as well it kind of gives the user an idea of what working with so in general I think they're a good idea whether they're worth the cost of maintenance is difficult to tell what I'm trying out and in the next mode Python library to kind of see see whether that's something we want to expand full but once again for sharing an understanding with the users which is a good thing so in answer to the original question what is our interface uh the answer really is code document and because that really is what the users will see and it gives them no reason then to dig into your code to get confused about what this post is supposed to work with and and so this is a good place to the so once we've created in agreement with our users uh then how do we stop ourselves from breaking promises that we made
and the answers test and so is famous
uh courts at which although i've attributed to take a couple months he denies ever having said so really it's kind should be should synonymous and so I would say there's a cholera this which is if you're not testing your interface definition then you don't have an interface definition and and to look at code the standard testing permit the idea here is that at the bottom we've got unit tests that we want as many of those as possible we want more of proportionally is they're they're quick to run she to right and they're easy to maintain an anatomical manual test which are heavy and slow and you don't do this in the middle somewhere I would say you want fewer than integration test but you definitely want to have your integrate your interface test divided up that means that when you find yourself changing your interface tests you know you've changed your interface which means that you need to work out what you do you later on and you need to communicate these changes to your users and the way you communicate changes to users history versioning and recommend semantic versioning um so that's the thing here is that your major number which is the 1st number in assuming we've all seen this uh but the major number indicates backwards compatibility so whenever you break up the possibility that 1st number changes and new users then know that this is going to cost them some effort to upgrade and minor and patch numbers of the less aggressive changes and usually 1 change uh the compatibility with the user uh this is documented in detail on some further Aug and it's on their own version 2 . 0 . 0 the specifications of the reading of the um along with versioning we release notes that I recommend you check out keep a changelog . come and they offer a clear guidelines for maintaining your release notes that they say that every release you should avoid your changes and into a list of the things that were added change deprecated removed fixed for our security changes so the 2 that were really interesting here are changed or removed those things changing compatibility so the things that we need to do we really really need to make sure I use is now because to break the code so although we're talking a lot about not breaking codes and it is OK to bake break backwards compatibility and the monster occasionally I recommend keeping a branch of breaking changes and pushing them unless the essential pushing them kind of in a block so you not drip feeding changes to users that's that's a pretty negative thing to do and in general ads and add new functionality alongside the existing functionality and deprecate the existing functionalities to letting users know that they should be migrating courage however deprecation policy and I quite like genders deprecation policy and anything that they markers deprecated gets removed in apart from a couple of caveats gets removed in the next major release but you could leave it to release this gives the user more time to kind of adjust to the changes that you need to make but so the real thing of this so far
is that good engineering practices that allow you to make that allow you to protect your users from changing your library so documentation testing and versioning things you should be so i'm gonna skin threesome technical solutions now however I the lost my stalking ran over 40 minutes so I'm really going to be by give you some ideas but as a of give you a link at the end of the talk which links to some code that demonstrates over the examples I'm about to get and so the first one is pretty common suspects ever been rooms used at some point or not you've but uh you've got a class and with a static actually it's so it's pre-generated and you want to change it to dynamically generated and value and on the way to do this is to use the app property decorator um which just make something look like it's a static actually uh look up but in fact calls the functions that's and generate value about point so you can have a chance generated based on the network value or time for um calculated from other values inside the class but pretty straightforward but it's a good example of 1 of the things you can do in place and you can't do many other languages and and the way that works it's down to something in that that you can read about Python documentation called the descriptor protocol which I highly recommend they gave me a real understanding of science of what's going on beneath the surface of the classes and attributes that so the next kind of refactoring thing you might want to do is to change the way that classes are instantiated so this might be so that you're near the have 1 instance of the class so essentially singleton I'm also you have a factories are objects that may be expensive to produce of pooled when the non-use and then you return something from the pool of this 1 available or a forward we generate a new 1 demand that's not very all possibly block until ones but back in the in the catch and so in the refactoring but this is article replace constructor with factory method but the nice thing about Python is we don't need to do that um so we can implement uh the lesser-used uh don't and you uh method method and and then inside that we can either return a new fast by calling on the uh superclass uh or we can look something up and just return the value is there's no you um the kind of prerequisite that you have to create a new class when you when you call a constructor which is kind of neat and so we can make these changes transparent to the user they don't know the switch from instantiating each time to return and stuff from a pole and you've done under the hood which is good for uh the 3rd example is replacing functions with methods so when I start a new module design I tend to start the function so I prefer those 2 classes generally but sometimes what you find is you end up with some global stating your module and which then if you change it in the module it's essentially a singleton value so you can't have multiple configured the modules that's really the way that you do that is to define a class inside you module and instantiate up and for the different places that you have and so if you've publish library already with these top-level functions um that's kind of a problem and but we can get around the school because presence of some pretty cool features and so this is the end result of this so the idea is that you had a module with we do the things top-level function and what we want to do is put inside a class um
so it's start with rephrase that class which they take taken the top level function and we moved it um under the AP class as so this is great we can now instantiate act and we can call methods but this is broken backwards compatibility so we need to fix that and the way that we fix eyes we create the default instance of a class uh we can either make the public thing or private thing I think it's quite nice to make it public so that you can people can start to use more to adopt folds to refer to it um and then what we do is a bit of magic where we take the method um which which can just be assigned to a variable so that's what we've done assigned it's the global variable do things and now it looks like a function it's not function it's a bound method on your instance and managed is quite a nice way you do this with each 1 of your top level functions that you put inside the clocks yeah and finally
and this is a slightly silly example um but it's neat and again it shows some some features of flexible Python is with being up to switch out certain types with other types of uh when necessary as so in this case so I have a module which I would really want want to replace with the object and so this is the module and has got a single global variable in there called salt and you can see static it's number 4 but somebody comes to us and tells us education before that should be generated there should be the result of time and so that's awkward because people are already using a module and they're calling modeled ourselves to get sick when this important also uh to get access to that value these generated dynamically so you really want to gender replace of other function but you can't do that because brake shoe interface with you user um and if it was inside a class you could use the property decorator uh but you can't do that because they don't work on top level functions they work sigh classes and and so we need to do is replace the module with a an object it's so this is like crazy stuff you probably don't want to this new but I just want country how you might do this and so here we got a class called fake module because it's going to pretend to be a module
um it and then we defined a property on it so we can if if we have an instance of this we can refer to the instance stock sold and and get back a value as if it was a but not to be brought to the function and here we instantiate as the objects and uh then we uh we assign it to the module so every module you've loaded inside your home application is put into this dictionary insist on what you can have a list of you can list any time you want to see the modules of loaded but like many things in Python it's readable so you can replace the module has been loaded with an instance and so now anywhere in the coat that refers to the slopes the energy like scuse me
and so anything that refers to that code um uh it will continue to work but will get back a dynamic value from this point on so to just run through some further techniques really what this comes down to is understanding the Python execution model and its various of these magic methods and variables inside Python that you can use them to replace 1 thing for another 2 essentially objects pretending to be other types of objects so we've already seen using done then you to change the construction of a class we can make objects behave like iterators behind the scenes this is how iterations Misérables Work um we could make methods method calls would like catch you access using them together this is property users behind the scenes and we can make classes that acts like functions by implementing the on the course so you can refer you could have replaced global state with a century an instance this callable which is underneath and we then is manually extracting parameters so we can be extremely flexible about how we extract parameters inside a function so you normally you list the functions that you want sometimes you have an asterisk box to kind of collect random stuff that people might send and your function a particular flexible um but is to show me a number of mass destruction is completely and we have that and so uh but we can be much more flexible about that we can kind of define the rules of what's accepted with inside a function and kind of almost deal with different function different sets of functions with different sets of parameters that provided um so that if you were to look if you to look at the document take the low-level documentation for flask for example almost everything in that takes asterisk marks call asterisk asterisk kW arcs and then it just kind of pulls them out the values needs to make the call behind-the-scenes um and if you don't provide the right set your get exception some going to tell you didn't follow the rules of been defined in the documentation and many of the special methods are described in dive into Python which is being available on sort of online
um and here I highly recommend having a look through the list to see what's was possible when he's
these tricks especially the last trick um you have to be aware that every change you make has risks attached to it and the more magic you use the more risk your really taking that you're gonna break compatibility accidently with you users and so just be aware sometimes it's better to often it's better to break it into use magic um so yeah I I would say you generate defaults to the straightforward changes but if you have a lot of users need that might stop me from making changes so so just be aware there or opportunity sometimes use a little bit of magic to me to help you in your relationship you users the use of exceptions include varies wildly between different code bases and so it's very difficult and I would you use a is going to do in their code base to handle exceptions that you throw so I don't really have any advice for this just be aware that any changes you make to the set of exceptions to the may cause problems for your users as another documentation make sure you document clearly what exception conditions are and what will happen in most cases the type assumptions because it's a dynamically typed language um are slightly scary uh in Python so when you switch out ones like for supposedly compatible fights the changes string for a list of characters so you change uh string for and a trouble of characters or something like that but they often look compatible annual test my continues past but some you can't leave more than once because you're dealing with iterator rather than know but they decide that you can in the click through multiple times and so just be aware that we do have different properties and and make sure that your idea documentation changes and to match that for um and that's it you don't make a change toward the monkey patching is always a risk that people be crazy stuff especially for find a bug in your code you don't respond to quickly enough and they will inject the code into your code base there's not really anything you can do about this they've broken to deal with you so it's not something to worry about there's just something to be aware of what will happen if there's no silver bullet you will break all client codes I mean poisons such a dynamic language and so open and transparent that any change you may carry some arrests um but ultimately it's a question of documents and you users what the assumptions on trying as much as possible to keep to the yeah so to sum up of if you
want your interface to be strong and stable um you need to know what it is you need to document it so you users noticed is you need to test it so that you your keeping the promises that you've made when it when you need to change backwards compatibility you need to communicate that with your users and it's better to go up from them after the fact and and it's helpful for most tricks the swapping of coding plant dynamic language like Python and so I've put this get have repository on that that the address which contains some kind of a more low-level details of some of the tricks are showing um and the PDF of the slides if you're interested you can contact me on the e-mail address book feel free to follow me on Twitter and and if using around the conference on usually wearing a pink hat uh feel free to talk to you about next my this talk or anything else thank you very much