Why you don't need design patterns in Python?
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 160 | |
Author | ||
License | 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 | |
Identifiers | 10.5446/33797 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
IntelSoftwareSoftware developerLine (geometry)Charge carrierCodeComputer animationLecture/Conference
00:28
Line (geometry)Software developerSoftware frameworkWeightUltraviolet photoelectron spectroscopySet (mathematics)BuildingBlock (periodic table)Range (statistics)Software design patternSoftware frameworkAbstractionProjective planeMereologySocial classPower (physics)Component-based software engineeringFitness functionModule (mathematics)Computer configurationSet (mathematics)Endliche ModelltheorieGenderBuildingView (database)Software design patternSoftware engineeringDifferent (Kate Ryan album)WeightJava appletLibrary (computing)Software developerMachine codeObject (grammar)OntologyWebsiteGoodness of fitClient (computing)CoroutineGodWordCuboidBlock (periodic table)Pattern languageCore dumpSoftware testingTemplate (C++)CodeEvent horizon
06:17
Cartesian coordinate systemPattern languageComputer programSoftware design patternResultantCuboidLecture/Conference
06:43
Instance (computer science)Modul <Datentyp>Module (mathematics)BlogSocial classCodeClient (computing)Object (grammar)ComputerMetropolitan area networkFunction (mathematics)Bit rateStandard deviationLibrary (computing)Discounts and allowancesData structurePattern languageParsingSocial classImplementationModule (mathematics)Functional (mathematics)System callConnected spaceInstance (computer science)Level (video gaming)Physical systemObject (grammar)Multiplication signInterface (computing)Block (periodic table)FunktorLibrary (computing)Pattern languageDefault (computer science)Graphical user interfaceProjective planeAbstract syntax treeMoment (mathematics)Content (media)InformationComplex (psychology)Group actionAuthenticationDependent and independent variablesWeightCodeBuildingData structureClient (computing)Flow separationStatement (computer science)Run time (program lifecycle phase)Attribute grammarAtomic numberMereologyComputer programRight angleGreatest elementInformation retrievalLogicBlogState of matterComponent-based software engineeringGene clusterClassical physicsSynchronizationWordParameter (computer programming)CASE <Informatik>Single-precision floating-point formatEndliche ModelltheorieComputer filePlanningMenu (computing)Staff (military)
15:41
Electronic meeting systemOvalJava appletImplementationData typeSocial classPattern languageFunction (mathematics)Run time (program lifecycle phase)Type theoryAttribute grammarDefault (computer science)Exception handlingReal numberPublic domainTwitterSoftware design patternObject (grammar)MultiplicationSocial classAttribute grammarMultiplication signDefault (computer science)Exception handlingParameter (computer programming)Single-precision floating-point formatSoftware engineeringJava appletFunctional (mathematics)CASE <Informatik>Type theoryWordImplementationPattern languageNatural numberComputer programPresentation of a groupRevision controlSoftwareCodeFormal grammarLevel (video gaming)Data dictionaryPoint (geometry)Category of beingLogicFormal languageRootField (computer science)Projective planePublic domainElement (mathematics)Different (Kate Ryan album)Statement (computer science)Arithmetic meanOrder (biology)Database normalizationMereologyReduction of orderSupersymmetryLink (knot theory)Run time (program lifecycle phase)Fundamental theorem of algebraNumberMarkup languageQuantum stateCoefficient of determinationAreaQuicksortStaff (military)Process (computing)Dynamical systemStrategy gameData structureModule (mathematics)Real number
24:40
Software design patternPattern languageJava appletSoftware developerNetwork topologyQuicksortAxiom of choiceLecture/Conference
25:39
MereologyMultiplication signSet (mathematics)Software design patternLecture/Conference
Transcript: English(auto-generated)
00:04
Hi everyone, I want to tell you a little story. Of course, not about myself, it will be a story of a Python developer. Not so long ago, there was a Python developer and throughout his career that lasted
00:22
already several years, he write a few thousands of lines of code and he was in love with his favorite framework and he became so proficient in the tools he used daily that he even became a mentor for his teammates.
00:42
And he praised all the tools he used because they were able to solve all his problems he dealt with in daily work. And after all, he was quite good. And this really boosted his self-confidence and this isn't surprising. Of course, knowing a framework was not his only asset.
01:05
He practiced writing tests rigorously and applied TDD whenever it was applicable. He was doing his best to make sure that the code he written was not only correct and well tested but also readable and easy to understand by any other teammates.
01:21
And every night before falling asleep, he was reading a Zen of Python to write a code that would never violate any of its verses. In other words, he was doing his best and he was expecting the other teammates to do the same, do the same thing. And then, he was assigned to a new project
01:42
that changed everything. Well, despite the fact that our hero was proficient with his tools and he know them inside out, they were not well suited for the project he was assigned to.
02:01
Because how valuable this experience may be when the weight of the project, it's very business part, is far outside this framework. And it can no longer be solved by this framework, essentially. So, he started to create his own classes,
02:20
his own modules, and his own abstractions. And he felt that they were clumsy and they do not be as good as the well thought components of a framework he used daily. You see, frameworks are sets of powerful building blocks. If you use them for problems that they were created for,
02:44
you're fine and you shouldn't bother any other options. But the problem arises when there is an issue that they simply don't fit. And you try to, I know, effectively screw driving using a hammer.
03:00
And, for example, what would be the Django good for if you did not need to use its models at all? So, what's left? I don't know the views, the template system, and the routing, and that's all. Any other rich capabilities of Django are not used, so why would you do that?
03:21
And the problem why our developer was stuck was that he lacked the thinking outside the box beyond his manual. And luckily, he noted this problem early enough to came up with an idea of asking someone maybe more experienced, maybe more interested in software engineering.
03:41
And he had a friend, a Java developer, and he asked her for an advice. What should I do if my tools are not good enough for me for this particular problem? And he said, she said, take a look at design patterns. They are meant to be reusable concepts to produce elegant code and nice solutions
04:02
and are based on many years of experience, people that are much smarter than we are. So our hero took the design patterns, took the 23 years old book, and tried to implement some of those using examples there.
04:22
However, the design patterns are not like libraries or tools that he dealt so far, so they are not easy to use solutions that you just import in your code and start using. They are more like recipes, like drafts for solutions. If you have this particular problem and they fit, like you have analogy, then you can use them.
04:44
But they are just outlines. They are not ready to use. Maybe you are thinking, what are the good for you if they are written in some old books by some C++ guys?
05:01
Well, there's a funny fact about IT. Namely, our brand has some kind of amnesia. Any 20 or 30 years or so. We forgot about old concepts, old ideas, and then we discovered them again, and we were like, oh my god, this is so amazing.
05:20
Cool. For example, let's take an async.io and its core routines, yeah? Cool idea, the event loop. Except it's nothing new, because this is almost 50 years old now, and it's been around in 70s. But we just now got it to the Python.
05:43
Another thing to consider when you think about patterns is that are they applicable today? And well, the book was written 23 years ago, which there were different tools in charge instead of Python.
06:00
So Python simplifies a lot of things, and this is what this talk will be about. More about the tools and less about the design patterns, because you will see that some of them are also present in Python, but they are already invisible or you cannot differentiate one from another, because they are so, so simple. But the main benefit from design patterns,
06:22
or at least learning the application in Python in some limited way, would be for you to extend your toolbox as a programmer, and as a result, become not only a better Python programmer but a better programmer in general.
06:41
Okay, so let's start with the first pattern. There is sometimes considered an anti-pattern, a singleton. This is a situation when you have a class, and in any moment of lifetime of a program, you need only one instance of a given class. Only one object has sense. There may be several reasons for that.
07:02
Maybe all the objects will be the same. Why should I bother, and why create new things every time? Maybe there is a business motivation behind this that there would be no more than one object. Or maybe creating an object costs a lot, takes a lot of time, and you just want to avoid it
07:21
to get some speed up. For such cases, we can use a singleton pattern, and beside uniqueness, there is also one requirement. Namely, you need to have a clear way to get an instance and know that this is a singleton. So after googling a little, you may find following solution.
07:41
This uses a magic done there new method that is using during creation. This solution comes down to using a class level attribute that will store your only instance and eventually return this whenever it's
08:03
necessary. Using this is quite simple. You just create as usual as you would like to create the other object. And, of course, you can use this implementation in your programs, but please don't call yourself Pythonistas anymore, because, you know, there is one very serious flaw, I can see this,
08:23
and this is that it's not clear for a client of this class if he creates a singleton if it's really a unique object, because we use unusual syntax for creating a new object. So you might get surprised if that you really use
08:41
getting is the same thing over and over again. A slightly better approach is to use a class method. Class method has disadvantaged, this is more clear, and it also does not block you from creating an usual instance. Well, you could do the same by clearing that class level instance variable,
09:02
but we don't want to go that far. However, since we have Python and it's 2017, there is a simpler way, and actually it's been around in Python for several years, I guess, or more. And this is, you can just create an instance object
09:20
in your module, and later in your code, just import the object instead of class. And this will achieve actually the same thing. So I told you that some patterns are present in Python, and this is true about singletons. This is not an obvious fact,
09:42
but there is a creature in Python that you use it countless times, and actually meets the requirements for singletons. And this creature is called a module. So let's consider this. After importing a module at least once, there is exactly one instance of it
10:02
in sys.modules.dict object. You can very easy and very clearly get an instance of a module using import statement. And if you need, you can recreate the instance using reload, so this actually adds something to this pattern.
10:22
So the conclusion about singletons is that using the most simplest solutions would be our way out instead of creating some clumsy classes. And if I am speaking about modules, there is another pattern that very gets simplified thanks to them, and this is facade.
10:44
Let's say we have a project that is consisting of many distinct components, and we can quite easily assign them to some groups responsible for certain functionalities. For example, we have a group with users that is responsible for getting user authentication
11:02
and so on. We have a group responsible for blog posts, creation, retrieving, and other stuff. And we have some things related to getting advertisements based on the contents. A net of connection between these classes might look like this. And I don't have to tell you that this is a terrible idea
11:22
because you get a tight coupling between these classes, and any time you want to change something in a class that has many connections with others, then there is a probability that you will break things. Also, it's very complicated to get a desired functionality
11:41
because you may not know what's behind this subsystem. This is what Facades, this is the issue what Facades tries to address. You introduce in your original pattern an extra class that will be your interface to the entire sub-module. You are no longer allowed to use these classes directly
12:03
under no circumstances. All requests that go to this subsystem must go through the Facades. And of course you can go on with default implementation like using class methods all over and creating another class,
12:21
but perhaps this is an over-engineered solution in Python if all you need is just a top-level package that will get a bunch of functions inside. Just look how clear it looks compared to the idea of modules. The only thing you use outside this package
12:41
is imports from this init file. Everything that's in these sub-packages is hidden. You may not use it outside. And this is how you hide the complexity of probably very complicated advertisement subsystem. This pattern, it doesn't sound like
13:03
very original or something, but it helps you organize your code and there is very little need for class in Python. If you can do, this is the same in plain module. Another pattern is a command. A command is an object-oriented callback.
13:23
The original implementation assumed that it will be helpful, for example, doing graphical user interfaces because you see when you want, for example, have a reaction on clicking an item in the menu, you don't want to pass too many information
13:40
to the graphical interface with the same reasons as the facets, so you don't want to have too many connections in your system. And the command was meant to pass and configure during runtime your things. Its interface assumed that you have only one method, which is execute.
14:00
And the thing that uses command would just run execute when it needs to. Of course, in Python, it's over-engineered because we can use just a plain function to achieve the same thing. And since functions are first-class citizens in Python, which means that we can create by function
14:20
during runtime, we can pass it to another function and we can return it, then there is no need to create a class. But I remind you, these were quite different times where the basic building block was class, so you have classes everywhere. And if everything that your command is doing is just calling another functions of another object
14:43
with some parameters, then maybe you can use the standard library's goodies, which is functors partial. And this one allows you to just prepare a collable object that will be accessible later to use. By the conclusion, we do rarely stuff like this in Python,
15:04
which making graphical user interfaces. So this is pattern of very little usage in Python right now. And another pattern is a visitor. And this is actually adopted in Python, and it's used, but for a certain amount of problems.
15:25
Let's say we have a complicated, nested structure that we need to traverse, and for each such node, we would like to execute our own logic. And this is an example of abstract syntax trees. And this is your code represented a substructure.
15:42
And this is really use of pylint and other linters, which get your code, turn them into such structure, and then, for each node, does distinct logic. For example, a root element is always a module, and this is represent the whole code.
16:02
The first thing you have, this is import statement. And this is represented as distinct node, yeah? And pylint has different checkers, different strategies, different guidelines for any of these elements. So it is much more clear to just separate this.
16:23
And this is what visitor is about. It's about getting know what is this node and separating this parsing from others. If we had a static typing, just like in Java, then we could just implement it like this. We would have a method visit,
16:42
and the arguments would point us what type is this implementation about, yeah? We get a clear distinction about what to do next. Of course, we don't have such things in Python, and the first naive implementation will amount
17:01
to using big if elif statements, which I don't have to add to you that this is ugly, and this is gross quickly, and it's slow. Luckily, we can use the dynamic nature of Python and create functions that we will call them later as usual methods.
17:24
After we assemble a method's name, we can just get it from our object and call it just as usual function. And this will work fine, too. But having Python at least three dot, sorry,
17:40
having at least Python three dot four, we have this single dispatch functionality, which this is the closest what we can get comparing to Java. So it's directing implementations per argument type. Its usage is quite complicated. I will get it step by step. So first of all, we implement the single dispatch,
18:02
and we get a default implementation. Of course, the default, if we did not have a specialized version for this time, we will want to raise exception that this no handler is for this thing. Then we would start implementing
18:21
our all specialized implementations using, take a look at this decorator, because we don't use single dispatch, we use the visit decorator dot register. And this decorator gets the only argument, which is a type, a type of a first argument to this function,
18:42
and whenever you call a visit with a type, like in this place, then this registered function will be called. Unluckily, this has a major disadvantage, and namely it cannot be used in classes, because there's always a first argument is a class.
19:03
It would have to be re-implemented by hand in such case. Okay, and the last design pattern is decorator. And decorator pattern is not what you might think of
19:21
when you hear a word decorator. It's not a decorator function in Python. It will become more clear when I will show in an examples, and now some requirements. It can extend the behavior of a given object during runtime, and it can be used multiple times with different decorator patterns,
19:41
and no order is not important. They should work in the same way, or at least have a meaning desired. So a decorator, when you decorate an object, you have to get the same thing back, which means as a user of class,
20:01
you shouldn't be aware that this uses a decorator. So if there is any attribute on the object, then it should be also present on a decorator. And for example, if we have such class that has two methods, getText and getNumber, and we would like to decorate one of them
20:24
by adding some bold HTML markup, then we have also to re-implement the other function, which is also, which is of course redundant, and this is just writing a code for art, not for making functionalities.
20:40
But what happens, actually, if we request an attribute on the class and we use the dot? The methods on classes and its fields are just attributes, and this is a logic we can plug in. So first of all, Python calls a special dunder get attribute method, and this looks for properties in object.
21:03
If it wasn't found, then dunder get attr, I know, wonderful naming, is called, and by default it just raises an exception that this property was not found. Looking for properties is by dictionaries
21:20
that are per class and per object level. If the same property is present on class and on object, then an object has priority. So to get decorator simplified, we can just implement the method we need, and for any other thing,
21:42
we just return the stuff from the original object, and this frees you from need to implement all this unnecessary stuff. Okay. To get a full compatibility, you would also have to implement the other methods,
22:02
but that's a different story, I guess. So to sum up, Python is a very flexible tool, much different from what we have almost 25 years ago, and many of these things you might think are either redundant or extra hard to just for it,
22:22
but in Python there are multiple places when we can plug in our own logic and customize on nearly every aspect of creation objects to runtime. However, the very important question arises, is magic, they showed you in some limited way,
22:45
is worth the effort? Should we use really the magic? Well, it depends. The readability wins. There are cases when using this stuff will spare you some effort,
23:00
and any other things that we just create, I know I see a fancy Python feature, let's use it, it's probably a wrong idea. And there are three things from me that I want you to take from this presentation to become better programmers in general. So first of all, get to know with your tools, and know them well, and this is like a vocabulary,
23:25
like having a name for everything you see. The second way is to get inspiration from other languages and communities, because there is not much interest in Python community in general in software engineering.
23:41
There is not much talks on this subject, on conferences, there is not much books. And the last thing I haven't spoken earlier is to know a business domain of your project. Because if you know your tools, you have a vocabulary. If you get inspiration from the languages,
24:00
you know the software engineering stuff, you have a grammar. But a real value, a real meaning, what you do is in this point. So even if you write a beautiful code and know all the tricks, and you still won't be able to solve the problems of your business, of a company you work for, then this is all for nothing.
24:24
And just to sum up, my name is Sebastian Butrinsky, I work for Stakes Next, the biggest software Python house in Europe. I block under breadcrumbs, collector.tech. And that's all, folks.
24:47
Okay, we have time for about two to three quick questions. So who has a quick question? Anyone? No, everyone has hungry, there's one. So it's less of a question,
25:01
but more asking for a comment of you, because in my opinion, actually, I come from the Java development community, and design patterns are really important, and I also realize they're really important in Python. For example, the facade pattern you mentioned. Sorry, I will keep it short. But my question for your comment is,
25:20
you said that design patterns are not really important in Python, but of the 23 patterns in the Gang of Four book, sorry, are they actually really not important, or are they important to implement sometimes, or just forget about them? So what's your opinion on the design patterns and the importance in Python?
25:45
Okay, so, I mean, your title was design patterns are not important in Python. But honestly, is it important to learn these, and then implement them? I'm sorry, I can't really make my question.
26:00
Okay, so your question was about, is it worth to learn the, okay, so, essentially, I think that this is a tricky part for less experienced people, yeah, because they learn unnecessary stuff. There is a gap in our community, yeah, and this is an established set of well-thought best practices
26:24
I think this should be prepared by someone, maybe, and this should be well propagated throughout the community, so they do not have to learn from other, from 23 years old books, yeah, because they are not relevant today.
26:42
So we need just a new set, and counterpart for Python. Okay, anyone has a question? One more question? Nope. Well, then it's time for lunch, I would say. Give him a hand. Thank you.