The Factory Pattern in Python // Separate Creation From Use

แชร์
ฝัง
  • เผยแพร่เมื่อ 23 ธ.ค. 2024

ความคิดเห็น • 262

  • @ArjanCodes
    @ArjanCodes  ปีที่แล้ว +1

    💡 Here's my FREE 7-step guide to help you consistently design great software: arjancodes.com/designguide.

  • @johnstanley1993
    @johnstanley1993 3 ปีที่แล้ว +89

    For me as a data scientist your videos really stepped up my software development game. The Factor Pattern together with having abstract classes as interfaces is something I immediately applied in my current project. This is not something you typically learn in data science courses, even though I think this is crucial when willing to write code in a professional context. Thanks Arjan for sharing those valuable insights!

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank you, John - I'm happy that the videos are helpful to you!

    • @iliasaarab7922
      @iliasaarab7922 2 ปีที่แล้ว +3

      Curious to know how you applied the concept in your current DS project?

    • @mikefochtman7164
      @mikefochtman7164 2 ปีที่แล้ว

      Totally agree. Although Arjan is working in Python, much of the design discussion applies to any language. The OOP and pattern concepts discussed are easily used in other languages (well, okay SOME details aren't perfectly portable, but most)

  • @fazzah777
    @fazzah777 3 ปีที่แล้ว +8

    I'm binging your videos currently and (among other things) there's something I love: the examples are meaningful. They are practical, solve actual problems. Not your another off the mill tutorial with generic class C inheriting class B etc. Seeing that your example applications mimic actually doing something, makes it 100x easier to wrap the application logic and focus on the topic at hand. I'm amazed.

  • @002uzumaki
    @002uzumaki 3 ปีที่แล้ว +44

    I just found out about you today while learning certain design patterns. Now, I started reading about factory patterns just a few hours ago and boom, you're here with the video. Thanks for the video. Maybe adapter pattern in the next video?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +6

      Welcome aboard! The Adapter pattern is in the planning, but it might take a little while.

  • @VCR47527
    @VCR47527 2 ปีที่แล้ว +48

    Unsure if this is mentioned somewhere, but this is the GOF Abstract Factory pattern. Not to be confused with the GOF Factory Method pattern. The Abstract Factory pattern's goal is, as Arjan says, for grouping different class instantiations together. The Factory Method pattern is about extending the functionality of a class.

    • @omarelsebaey9589
      @omarelsebaey9589 2 ปีที่แล้ว +9

      This comment saved me a lot of confusion, thanks a lot!

    • @pinakadhara7650
      @pinakadhara7650 ปีที่แล้ว

      To be more specific, Factory Method pattern delegates object instantiation to the sub-classes and makes rest of the code dependant on an interface or an abstract class

  • @GuRuGeorge03
    @GuRuGeorge03 3 ปีที่แล้ว +8

    I am starting a new fulltime developer position in august and im trying to brush up my basics. your channel is amazing

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank you - glad you like it. And good luck at your new position!

  • @StandardDeviationMusic
    @StandardDeviationMusic ปีที่แล้ว +2

    At 9:53 when you do the dict trick. The value is an Instance of each object type due to the () at the end right? Does that mean this is bad if you have many factories which take up memory and you instantiate them all. Is it better to leave the value instantiated then instantiate once it returns?

    • @18Maxim18
      @18Maxim18 ปีที่แล้ว

      Searched for this comment) I think it's just as an example but yes in general if you have a lot of objects it's pain

  • @ytlagu2010
    @ytlagu2010 2 ปีที่แล้ว

    I really like the idea where you first present the problem and show the solution. Most videos I watched rant about the theory but forgets to tell you the why part.

  • @munotpratik2009
    @munotpratik2009 3 ปีที่แล้ว +2

    Thank you your videos, I understood the design patterns. I implemented it in my current project initially I thought it was lot of work but I persisted and wrote classes for them. I had a requirement to change the data source from DB to file. Some I had implemented it as classes, it was easier me for replacing the spice without impacting the code ! It was a life and a time saver. Thank you !
    Please keep sharing such quality content. I’m sure it must be helpful for a lot of folks!

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      Glad to hear that the videos are helpful!

  • @Vogel42
    @Vogel42 3 ปีที่แล้ว +50

    9:29 doesn't this make the factories dict eagerly instantiate all these object at once? (regardless if they are being used or not)
    I am not sure what's the correct way to do it, but if i had to write it this way i would:
    factories = {
    "low": FastExporter,
    "high": HighQualityExporter,
    "master": MasterQualityExporter
    }
    and then: factories[export_quality]()

    • @CrapE_DM
      @CrapE_DM 3 ปีที่แล้ว +6

      Nothing wrong with this, but seeing that the factories are pretty small it's not a big deal. In a lot of real-world examples, you'll also need to send some arguments into the creation of those factories, so you can't just store the class, you'd have to store a function that returns an instance. Funnily enough, you're essentially storing a factory of the factory. In the end, it's usually just simpler to instantiate them right away. The objects are probably short-lived.

    • @MateHegyhati
      @MateHegyhati 3 ปีที่แล้ว +2

      My thoughts exactly, but I'm more of a cpp guy, so I'm eager to hear what the pythonic way is. Also, repeated calls may create new and new instances. (do they?) That could be solved by moving the map out of the function to the module level I guess. (And thanks for the nice vid.)

    • @janziem3614
      @janziem3614 3 ปีที่แล้ว +6

      ​@@CrapE_DM The shown variant using it's class name and creation on demand is indeed a much cleaner version. I would use factories.get(key) to handle non-existent keys/requests gracefully. You'll use factories in larger projects containing multiple different services. How do you want to estimate the life span of an object or service, outside of your own context? You'll probably have no information about complexicity, startup, resources of such a service by instance creation. Projects grow in real world, sometimes really fast. So at this stage, creating objects might become bigger issue than you might expect. (Think about db connections, service/event registration etc pp)
      Passing additional information via *args or **kwargs is simple.

    • @masterluu8
      @masterluu8 3 ปีที่แล้ว +4

      Yes it does instantiate them all and always discards the majority of them unused. And yes your code is the correct way of implementing this. Likely just an oversight.

    • @janziem3614
      @janziem3614 3 ปีที่แล้ว +1

      ​@Andrew Ramshaw Hey Andrew, I think you misunderstood or mispelled sth.
      The factory method is a method (!) pattern and only encapsulated in a class at c#, java etc. because of their' OOP. You'll see that a factory method is always static, there will be never an instance of the factory itself - as this would'nt make any sense. Like a factory, the method creates suitable products according to specified parameters or configurations. At this point there is no dependency on parents or side effects, just a dependency on a common (abstract or interface) type per factory method.
      Do not mix multiple thoughts into a pattern, as one pattern (usually) addresses only one challenge.

  • @cabanford
    @cabanford 3 ปีที่แล้ว +9

    I so enjoy your presentation and delivery. Great job in explaining "why" things are used and not just the typical "how" (which is what geeks who already grokk something tend to do).
    I also like how you discuss what things a pattern doesn't do well and then you provide an alternative for such cases. ⭐⭐⭐

  • @lazyoracle
    @lazyoracle 3 ปีที่แล้ว +3

    I have been watching all your videos over the last week. I am glad I have reached a point where as soon as you started explaining the factory pattern for decoupling the main(), I thought that this would eventually lead back to dependency injection.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      Very good! These things are all connected by a set of basic principles in the end.

  • @JonMartins
    @JonMartins 3 ปีที่แล้ว

    I'm addicted to your channel man!
    Congrats. Cheers from Brazil.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank you, glad you like the content!

  • @m3hdim3hdi
    @m3hdim3hdi 3 ปีที่แล้ว +8

    this is the best python channel hands down, anyone can suggest other channels like this?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      Thanks Artur!

    • @jonathan3488
      @jonathan3488 3 ปีที่แล้ว +1

      tech with tim is also great

    • @RecursiveTriforce
      @RecursiveTriforce 3 ปีที่แล้ว +3

      You might like mCoding!

    • @mike4617
      @mike4617 7 หลายเดือนก่อน

      theprimetime neuralnine fireship

  • @mdunkman
    @mdunkman 3 ปีที่แล้ว +8

    I really enjoyed the video. Your pacing and amount of content is very good as a reference!
    In a future video, could you clarify the differences between a Factory Pattern and a Builder Pattern? I feel like the builder is a way to collect factories, but I would enjoy seeing a worked example.

  • @robertmccarthy1349
    @robertmccarthy1349 3 ปีที่แล้ว +1

    Amazing video! One SUPER small item I saw in read_explorer() is that export_quality is using in to check against the available factories. Using: if factories.get(export_quality) will not iterate through the dictionary but directly see if that key is available. Considering how few factories are available, this would never get noticed. I recently found your channel and binged a few videos already :) Subscribed!! Can't wait for more.

  • @UrbanAI
    @UrbanAI 3 ปีที่แล้ว +1

    My most frequently used pattern before your videos. Thank you!

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      Same here :). Glad you liked it!

  • @persfarhat
    @persfarhat 3 ปีที่แล้ว +4

    Thank you for what you are doing. It is really helpful. Keep going.

  • @judegomolina
    @judegomolina 2 ปีที่แล้ว

    Just providing a real world example here. I just solved an issue that I had where I needed to provide an implementation of an output port based on a given value with the factory pattern. In this case it was a Payment Processing Service and the code quality and maintainability was quite good with the implementation of the factory pattern, which comes super handy since Payment Processing Services are always likely to require updates or new integrations in the future.
    Thanks for the video, super useful as always!

    • @ArjanCodes
      @ArjanCodes  2 ปีที่แล้ว

      Thank you, Juan, glad you liked the video!

  • @JelleWolbers
    @JelleWolbers 3 ปีที่แล้ว +1

    Awesome videos man, really helps me understand design patterns that up till now sounded a bit vague and abstract to me. Bedankt!

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      Thank you Jelle - graag gedaan ☺️

  • @robertbrummayer4908
    @robertbrummayer4908 3 ปีที่แล้ว

    Your code examples and the way how you explain them is top.

  • @omarcrosby
    @omarcrosby หลายเดือนก่อน

    Another outstanding video Arjan!

  • @Mannershark
    @Mannershark 3 ปีที่แล้ว +4

    Design patterns are useful for giving common solutions a name, but I find that the 'standard' implementations often don't make for Pythonic code. In Java you need all these classes to satisfy the 'compiler', but thanks to Python's dynamic nature you can achieve the same with much less code.
    For example, a function get_exporters(quality: str) -> Tuple[VideoExporter, AudioExporter] would do the same, but in ~5 lines instead of ~30, and would be much easier to understand, while still removing the coupling. Add to that that classes are usually moved to separate files, and it becomes really hard to get an overview of the application without diagrams.
    There's a nice talk about this that motivates it better than I could: Stop writing classes.
    Though considering the intended audience is Python beginners and intermediates, I understand the focus on explaining the design patterns as they normally appear. Another section 'making it Pythonic' would be nice, but I guess that could get too complex for beginners.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +5

      I mostly agree with this, though classes are not completely useless. If for example you want to add some settings to a factory that influence how the instances are created, then a class is a good solution because it combines data with behavior.
      I'm using classes in most of my examples when explaining these design patterns to not make it too confusing for the viewers, but I'm seriously thinking about following up with a series where I try to reimagine these patterns, but then using more Pythonic features instead and see how that holds up.

    • @Mannershark
      @Mannershark 3 ปีที่แล้ว +1

      @@ArjanCodes Looking forward to it!

    • @atomic7680
      @atomic7680 2 ปีที่แล้ว

      Looking forward to this as well

  • @Wahlnetwork
    @Wahlnetwork 3 ปีที่แล้ว +3

    Another fantastic video!

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank you! Cheers!

  • @deeprony7
    @deeprony7 3 ปีที่แล้ว +1

    9:56 Say I wanted to add another factory to the factories object wouldn't that break the Open-Closed Principle? What's a way around that?

    • @anelm.5127
      @anelm.5127 3 ปีที่แล้ว +2

      No, not really.
      I guess you think that because you would have to add a new factory to the dict if violates the closed for modification principle.
      Open/Closed means you can modify the way a system works without modifying the code that already exists. You can extend the code and use it in different ways, but the old code is still in tact and doesn't need to be re-tested.
      The Factory Method pattern will create a different type of object based on specified parameters. Factory Method actually works well with the Open/Closed principle if done correctly. However, if you create a new class and then want the Factory Method to create a new object of that type you would have to change the Factory Method.

  • @le_alecs
    @le_alecs 3 ปีที่แล้ว +11

    When to use the factory pattern? Whenever you want to turn Python code into Java code.

    • @stevanmiladinovic4007
      @stevanmiladinovic4007 3 ปีที่แล้ว

      class WindowComponentGraphicsManagerBaseFactory extends AbstractWindowComponentGraphicsManagerFactory implements BasicGraphicsFactory

    • @Maric18
      @Maric18 3 ปีที่แล้ว

      BaseFactoryManagerFactory wants to know your location

  • @chrisxiao1728
    @chrisxiao1728 3 ปีที่แล้ว

    Really enjoy the video that talking about the design pattern in python, especially with a understandable example. Look forward to see more video with more difficult and useful pattern in python.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Glad to hear you like it, Chris!

  • @JimmySting
    @JimmySting 2 ปีที่แล้ว

    Might not be understanding correctly, but at 3:53 you mention that the main() function has weak/low cohesion because it is "doing a lot of things". Does that actually make it _low_ cohesion though since all of the video/audio functionality is within same area? I agree that this function has _high coupling_ with the other classes.

  • @zsoltsendula3648
    @zsoltsendula3648 ปีที่แล้ว

    As Arjan mentioned if you have wide variety of combinations then I use a factory controller class which can generate the proper factories. It is not so complicated.

  • @pawekostecki2406
    @pawekostecki2406 2 ปีที่แล้ว

    Master quality video on Factory pattern :)

  • @AsenovMiroslav
    @AsenovMiroslav ปีที่แล้ว +1

    I would like to propose the use of a factory dictionary approach, where the dictionary values store class names instead of actual instances. This can be more efficient, especially when creating instances is resource-intensive. The idea is to define a dictionary of factories like this:
    factories = {
    'one': FactoryOne,
    'two': FactoryTwo
    }
    Later, when you need to create an instance based on a specific key, you can use the stored class names to instantiate the desired objects. This is done as follows:
    return factories[key]()
    With this approach, you optimize memory usage by storing class names, and actual instances are only created when needed.

  • @goldenimper503
    @goldenimper503 3 ปีที่แล้ว +5

    Hey! First, thank you so much for your videos. I knew about patterns long time ago but never really understood how to put them in practice.
    I have a question about this... I don't see that much of a benefit.
    Basically what I see in this example is that the Factory pattern allows us to know about half the things we needed - before we needed to know about 3 video exporters and 3 audio exporters, now only 3 factories. But I still have to know about the factories.
    And yes, you can move that to a different function as you did with the read_exporter, but you could've also done the same without the factories and just have a dict with tuples, like `{"master": (LosslessVideoExporter(), WavAudioExporter()), ...}`
    What's the real benefit of this?

    • @pinakadhara7650
      @pinakadhara7650 ปีที่แล้ว

      You only have to know the Abstract Factory "ExporterFactory" but not the 3 factories themselves. You can keep adding as many factories as you want as long as they implement ExporterFactory.

  • @AndreiKononov-y5m
    @AndreiKononov-y5m ปีที่แล้ว

    Im a bit confused about terms and concepts so any help is appreciated.
    1) Is example from video an implementation of "Abstract factory" pattern?
    2) Does such thing as "Factory pattern" exist? Or maybe its not a "pattern", but something else? Because i mostly find "Factory method" and "Abstract Factory" among patterns.
    Great video, btw! As always on this channel.

  • @johnanih56
    @johnanih56 3 ปีที่แล้ว

    I love how you pieces them up! Awesome! please do more videos with classes :D

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank, glad you like it, and will do!

    • @johnanih56
      @johnanih56 3 ปีที่แล้ว

      @@ArjanCodes by the way do you have advanced courses for python on sale? Looking out for more advanced tips out there?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Not yet, but I am working on a course at the moment!

    • @johnanih56
      @johnanih56 3 ปีที่แล้ว

      @@ArjanCodes inform me about the ones tailored for advanced users. Thanks so much! Can't wait

  • @vether7219
    @vether7219 3 ปีที่แล้ว +3

    Function "read_exporter" initializes all exporters, which I think is bad. It is generally a bad idea to create a dict (or a list) containing instances instead of classes. WDYT?

    • @Naej7
      @Naej7 9 หลายเดือนก่อน

      The advantage of the factory is that they don’t weight anything in memory, they are just methods, no data

  • @Jaja111389
    @Jaja111389 ปีที่แล้ว

    For your factories object, why did you instantiate all 3 in the object? Would it not be better to instantiate on the return when the needed factory was pulled from the dict?

  • @rdustinlane
    @rdustinlane ปีที่แล้ว

    Would love a video on comparing the Factory and Builder design patterns and when to use one versus the other.

  • @williamrumbanichavula4815
    @williamrumbanichavula4815 3 ปีที่แล้ว +1

    Great video on the Factory Pattern. My question is, doesn’t the read_exporter function violate OCP in SOLID as we’ll have to keep changing it to add more Exporters?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      That's correct. I did this in this video to keep things simple. Optimally, you'd want a mechanism to be able to register these factories dynamically so that the code that uses them doesn't need to know which factories there are. I'm working on a video at the moment that addresses that particular issue.

    • @RatFace_MonkeyEar_FishEye
      @RatFace_MonkeyEar_FishEye 2 ปีที่แล้ว

      @@ArjanCodes for those looking for it: th-cam.com/video/zGbPd4ZP39Y/w-d-xo.html

  • @skycakecrunch
    @skycakecrunch 2 ปีที่แล้ว

    Do you want to instantiate all those exporter objects in the low/high/master dictionary? Wouldn't it be better to instantiate only the one that is called?

  • @Quynn-Oneal
    @Quynn-Oneal 3 ปีที่แล้ว

    9:52 are creating these exporters, like you did in the video, good for the memory? I thought lazy initialization was a better approach.

  • @JuanMiguelGarciaYuffra
    @JuanMiguelGarciaYuffra 10 หลายเดือนก่อน

    I strongly recommend you to use visualizations to introduce the patterns in a better way. Nice video.

  • @vikaspandey2879
    @vikaspandey2879 ปีที่แล้ว

    Thank you for your videos. Content is amazing have a question:
    At 10:21 you defined read_exporter. But if we call read_exporter then it will create objects of all 3 classes from factories dict. Won't that be a memory wastage cause at the end we are going to use only one object?
    Please correct me if I am wrong.

    • @koffiepot82
      @koffiepot82 ปีที่แล้ว

      lol, I was thinking the exact same.

  • @neagudan
    @neagudan ปีที่แล้ว

    Question: If the concrete classes require different parameters in the constructor, how can you implement this in the factories get_video/audio_exporter() methods?

  • @evertonc1448
    @evertonc1448 3 ปีที่แล้ว +1

    Thanks god I learned English, my man. I'm Brazilian and the tutorials we find in Portuguese are nowhere near as good as this one (aka how to make a CRUD, make an Animals class and crap like that), I programmed everything on main() for years back when I was a teen simply because there's nothing about code designing in the Portuguese side of the internet.

  • @jarquafelmu
    @jarquafelmu 2 ปีที่แล้ว

    Great video! You explain the concepts incredibly well.

  • @jayakrishnandamodaran218
    @jayakrishnandamodaran218 3 ปีที่แล้ว +1

    Thank you for the video. I do have one suggestion though. When you mentioned about the cases where factory pattern is not possible, such as when the user decides on the different params to get their desired exporter, I would use the Builder design pattern.

  • @davidkaftan5563
    @davidkaftan5563 3 ปีที่แล้ว

    You are a high quality video exporter.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Haha, good one 😁.

  • @arcsin4083
    @arcsin4083 ปีที่แล้ว

    What should I do if I need N objects that have the same methods, but each type of object has a different input args + partially some common properties?

  • @Vijay-Yarramsetty
    @Vijay-Yarramsetty ปีที่แล้ว

    Thanks Arjan. this is so authentic.

  • @Olegt0rr
    @Olegt0rr 3 ปีที่แล้ว

    Thanks for the video.
    Seems you shouldn't create all of available factory instances in the `factories` dict. Just remove brackets from dict (don't __call__ classes) and add call on return to create chosen class only

  • @DougLopes
    @DougLopes 8 หลายเดือนก่อน

    Instanciating the exporters in the dictionary is not alocating unecessary memory? I'm new in python so i don't really know, but if does, there is not a way to create the instances in execution time when necessary?

  • @muzafferckay2609
    @muzafferckay2609 ปีที่แล้ว

    This is also a good example of strategy pattern.

  • @elbanj
    @elbanj 2 ปีที่แล้ว

    Great video. Really helped me understand this pattern

  • @asnaeb2
    @asnaeb2 3 ปีที่แล้ว +4

    Why is the factory a class instead of a method? Also what's currently really missing on TH-cam is tutorials about compilers such as Nuitka and Pyinstaller, the whole professional side of shipping your code.

    • @comedyclub333
      @comedyclub333 3 ปีที่แล้ว

      Bruh, there are literally thousands of tutorials in PyInstaller out there. They are not even compilers, they just package all you python modules and an python executable into an executable file.
      (Btw there is no "professional way of shipping your code".)

    • @comedyclub333
      @comedyclub333 3 ปีที่แล้ว

      To your question why the factory is a class instead of a method (you mean function, don't you?): It's basically done to make it clear in the context of object oriented programming. The same functionality can be achieved by using functions (or even just dictionaries). In case of functions it makes the code less readable. That's it.

  • @kayakMike1000
    @kayakMike1000 3 ปีที่แล้ว

    That's a nuclear cooling tower in you thumbnail, not a factory. Ha ha. Just feeding the algorithm. I like your series, it's very good!! and you speak well with an accent that makes you sound very intelligent.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thanks Michael! I'm learning something new everyday, haha :).

  • @epsonprinter7821
    @epsonprinter7821 3 ปีที่แล้ว

    Hi, Can you please show how we pass object parameters of low , high , medium instead of input ()?

  • @cod-newbie9166
    @cod-newbie9166 2 ปีที่แล้ว

    If the factory class has a registry that takes up low, high or master, does that change it from being a factory to something else?

  • @jetra_h
    @jetra_h 3 ปีที่แล้ว

    Oh my gosh! you made cry because of the excitement

  • @TheWolverine1984
    @TheWolverine1984 3 ปีที่แล้ว

    Question: Why to use classes at all here? Why not just functions like "export_video(quality, path)",export_audio(quality,path)" and then use then just use them directly in the 'main'? In the above approach, you make an abstract factory, and a class for each of the combinations of qualities factories and then a separate class for each quality settings and an abstract class for them.
    Why is it a bad idea to just use a function instead all of this? If you need to group the video export and audio export together, you can just put them in another function. What am I missing here?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      It’s not a bad idea at all to rely on more Pythonic mechanisms that achieve the same result with less code. In this video I wanted to stick to the traditional pattern (which relies on classes and inheritance). However, I did a follow-up video where I explored a few alternatives, see: th-cam.com/video/zGbPd4ZP39Y/w-d-xo.html.

    • @TheWolverine1984
      @TheWolverine1984 3 ปีที่แล้ว

      @@ArjanCodes Thank you very much!

  • @VladimirTheAesthete
    @VladimirTheAesthete 2 ปีที่แล้ว

    Top notch content, keep it up.

  • @infinikeys
    @infinikeys 2 ปีที่แล้ว

    Great Python content. Thank you very much for content like this. Do you mind a silly question: why the ExporterFactory.get_video_exporter & ExporterFactory.get_audio_exporter don't have the decoractor @abstractmethod like the class VideoExporter?

    • @infinikeys
      @infinikeys 2 ปีที่แล้ว

      Oops, sorry for asking before looking at the final code on github. Those methods are indeed declared as abstract. :)

  • @max1cp
    @max1cp 3 ปีที่แล้ว +11

    I know that's probably not the point of this video but I feel like we should be using argpase instead of input for cmd scripts.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +2

      Yes, that’s probably the best option if you want to create a more complex CLI.

  • @keeratkhandpur5623
    @keeratkhandpur5623 3 ปีที่แล้ว

    I absolutely love your videos! Can you please guide me to master programming as a beginner.

  • @larussverris
    @larussverris 3 ปีที่แล้ว

    Underrated video

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank you, glad you liked it!

  • @epsonprinter7821
    @epsonprinter7821 3 ปีที่แล้ว

    Very high quality content .

  • @abubakar.khawaja
    @abubakar.khawaja 3 ปีที่แล้ว

    Finally founded QUALITY PYTHON DEVELOPER.

  • @АндрійКлюга
    @АндрійКлюга 7 หลายเดือนก่อน

    could someone explain why to declare variables without assignment?
    video_exporter: VideoExporter
    audio_exporter: Audio Exporter

  • @dimas-
    @dimas- 3 ปีที่แล้ว

    Amazing video, as always! Thanks, Arjan.
    I also learned Python has Protocol classes but seems to me it's the same as ABC.

  • @dmccrafter2367
    @dmccrafter2367 3 ปีที่แล้ว

    Het voelt alsof je veel meer code typt voor een niet veel beter eindresultaat. Wat is het voordeeld van het gebruik van een class voor elke soort exporter, inplaats van video- en audio-exporter in tuples te zetten, waarna je de tuples in een dictionary samenvoegt?

  • @bokistotel
    @bokistotel 3 ปีที่แล้ว

    That one was great!! Thanks for the help. you provide great content!!
    The only video I kinda dont get is the Observer one.. but I guess thats just me

  • @WalterVos
    @WalterVos 2 ปีที่แล้ว

    Could we consider read_exporter() to be a FactoryFactory?

  • @oghry
    @oghry 3 ปีที่แล้ว

    GOF is proud of you 😁

  • @littleconan7929
    @littleconan7929 2 ปีที่แล้ว

    I am a bit confused.
    Usually factories are used to generate instance of similar object no ?
    But here we have to create a different factory per class ! (well one factory for two classes, but let's start simple with just a family of video codec)
    What is the use of it ? Each time I create a new VideoExporter I have to create it's dedicated factory.
    The only improvement I see, is that the switch has been located in a different function, not in the main anymore.
    And I still would have to rewrite this switch after adding a new codec. The difference is that we have a switch of factories instead of codec... great.
    Shouldn't we use metaclass and each class using the relevant metaclass being automatically referenced with its associated keyword in to the factory when it is created ?
    And thus according to this exemple, we would have only two factories, one for video, one for audio, able to return the instance matching the good codec from the relevant keyword, with auto handled switch !

  •  3 ปีที่แล้ว

    This reminds me of a plugin registration architecture. Is the plugin architecture related to the factory pattern?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +2

      Often, plugin systems rely on a factory-like pattern. Each plugin basically defines a concrete factory that provides instances specific to the plugin. Combine that with a factory registration method + dynamic script loading and you have the basics of a plugin architecture.

    •  3 ปีที่แล้ว

      @@ArjanCodes I see, thanks for the explanation

  • @matteogolin5231
    @matteogolin5231 ปีที่แล้ว

    In your read_exporter function, you check if export_quality is in a set of possible quality options. Is there any reason why you use a set instead of a list?

    • @DrDeuteron
      @DrDeuteron ปีที่แล้ว

      because the choices are unordered and unique, so a set is a better match than a list. If there is no order, don't use a list.

  • @Ziboo30
    @Ziboo30 3 ปีที่แล้ว

    Juste discovered your channel. Awesome tutorials, thank you very much ! Subscribed ;)

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thanks Robin, glad you're enjoying the videos!

  • @comedyclub333
    @comedyclub333 3 ปีที่แล้ว +1

    But you could just map corresponding keys ("master", "fast", etc...) to tuples of audio and video exporter. This would reduce the overhead of having extra classes while keeping the same functionality. Am I missing something or could it really be substituted completely with ease(at least in this example)?
    What I mean:
    mapping = dict(master=(LosslessVideoExporter,WavAudioExporter), fast=(H264BPVideoExporter, AACAudioExporter), ...)
    I mean you have to map some kind of user interaction anyway. You even need that kind of dictionary anyway. What's the point having classes that neither store data nor compute anything (I mean, they do, but instancing an object is pretty trivial - using a separated method for this seems pretty bloated to me)?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +2

      Yes, you could probably also do this with tuples. I use a class here because that's how the Factory pattern is defined, so I prefer to stay close to the original pattern in order to avoid confusion. Another reason to use a class and not a tuple is that you might want to store data in the factory. For example, you could imagine that a Factory also stores some configuration settings or data that it needs to create the instances. This is exactly what classes are good at.

    • @comedyclub333
      @comedyclub333 3 ปีที่แล้ว

      @@ArjanCodes okay, so the fact that it's almost evenly convenient to use a dictionary instead is due to the chosen example an not generally the case?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      The goal of the factory pattern is to separate creation from use. If you can achieve that same thing with tuples or dicts and you don’t need class-specific features such as attributes, or dataclass behavior, then why not use that if it’s more convenient? The thing I’m concerned about is whether using typing will be as easy as with classes. I’m intrigued though by the idea. I might take up the challenge and do a video where I compare the two options.

  • @tanveersingh4217
    @tanveersingh4217 3 ปีที่แล้ว +1

    Increase the font size, can't see anything in my low res 240p video setting

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      Thanks for your feedback!

  • @sortof3337
    @sortof3337 3 ปีที่แล้ว

    Very high quality video. :) Subbed! I wanna see you use Starlette, which I love. :)
    Factory pattern with pydantic saves my life everyday when I am writing code. Factory pattern is also helpful, if you are trying to validate your types if you are doing graphql with something like ariadne.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Glad you enjoyed it and thank you for the suggestion! I don’t have experience with Starlette. How is it different from something like Flask?

  • @Yankzy
    @Yankzy 3 ปีที่แล้ว

    I came on youtube to brush up on the factory pattern, you did an awesome job! Definitely using it in my code today. Thanks.

  • @brunovial1075
    @brunovial1075 3 ปีที่แล้ว

    Awesome content, You got a new follower !

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Thank you - and welcome onboard!

  • @Ranoake
    @Ranoake 3 ปีที่แล้ว

    Is it considered bad practice to have a single factory and pass in the desired quality as a parameter rather than 3 separate factories?

  • @timresink1549
    @timresink1549 3 ปีที่แล้ว

    Great content Arjan! Could you add a video on OOP for data science? I see a lot of code with tightly coupled functions that alter a single giant pandas dataframe. It would be nice to see you shine your light on that

  • @momentouscrazynoob1709
    @momentouscrazynoob1709 2 ปีที่แล้ว

    Thank you so much! This helps a lot :D

    • @ArjanCodes
      @ArjanCodes  2 ปีที่แล้ว

      Thanks so much, glad the content is helpful!

  • @willemvdk4886
    @willemvdk4886 3 ปีที่แล้ว +1

    Excellent!

  • @CrapE_DM
    @CrapE_DM 3 ปีที่แล้ว

    My only issue is that the user input prompt is still hard-coded, so doesn't automatically adjust to changes in the export options.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      You're right. Fortunately, it's an easy fix:
      export_quality = input(
      f"Enter desired output quality ({', '.join(factories)}): "
      )

  • @sandrosixarulidze398
    @sandrosixarulidze398 3 ปีที่แล้ว

    A bit off topic. But I believe that prepare_export and do_export create an antipattern known as sequential coupling. Template method pattern should've been used here.

  • @christianherrera9524
    @christianherrera9524 3 ปีที่แล้ว

    Really great video

  • @TNeulaender
    @TNeulaender 3 ปีที่แล้ว +1

    Not a fan of "get_...". When I get sth from the fridge I expect it to be there and after I got it to not be there anymore.
    Imho "create_audio/video_exporter" is far better.
    Alternatively "construct/build/etc" - whatever the domain language might be.

    • @TNeulaender
      @TNeulaender 3 ปีที่แล้ว

      Oh and sorry didn't want to be the "just negative guy". It's actually a great video, but this one thing just itched :)

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +2

      No worries and that's a valid point! Get and create indeed mean different things. This is a great example of Phil Karltons quote "There are only two hard things in Computer Science: cache invalidation and naming things." ;).

  • @Voronza
    @Voronza 3 ปีที่แล้ว

    I always felt like keeping my __main__ part as light as possible. Now I see why it is cool and how to properly do it.

    • @chri-k
      @chri-k 3 ปีที่แล้ว +3

      main():
      main2()
      Problem avoided

    • @Voronza
      @Voronza 3 ปีที่แล้ว

      @@chri-k ahahaha, that's the way!!! :D

  • @megaing1322
    @megaing1322 3 ปีที่แล้ว +69

    While the general Point being made here is ok, the example is not at all pythonic. Python isn't Java. You shouldn't create a factory class that has no constructor and no internal state. You can instead replace every instance of a subclass with a tuple (or a namedtuple if you are fancy) of two functions (in this example, one can even just use the constructors of the Exporters themselves.). Python3.6+ Type hinting even gives you a good way of telling the user (and IDE) what a function expects.

    • @TsArun-qw6xn
      @TsArun-qw6xn 3 ปีที่แล้ว +2

      Can you put a github gist link of how to do it in pythonic way?

    • @jamie9926
      @jamie9926 3 ปีที่แล้ว +2

      @@TsArun-qw6xn he has just made a video with a pythonic version of this pattern

    • @ianliu88
      @ianliu88 3 ปีที่แล้ว +5

      Also, what is the point of having "prepare_export" and "do_export"? Why not have simple functions like export_h264(data, directory)? I feel like OOP forces you to create unneeded abstractions.

    • @davidlanda2324
      @davidlanda2324 3 ปีที่แล้ว +3

      @@ianliu88 This is not o problem of OOP. This is a problem in the head of designer ;)

    • @DeathBean89
      @DeathBean89 2 ปีที่แล้ว

      @@ianliu88 There might be differences in how you want to handle the result. You might want to save it to disk, or send it to a server, or compress the resulting video copy, etc. In this specific case, you probably want to save it to disk in all of those cases, but there may be other programs where you want to separate preparing something from actually doing something with the prepared object.

  • @avazart614
    @avazart614 3 ปีที่แล้ว

    I don`t understand. it is video about pattern factory or about factory function/method ?

  • @PaulJohnsonM
    @PaulJohnsonM 3 ปีที่แล้ว +1

    I don't really understand the benefit of writing factories to instantiate objects versus packing all of this functionality into a static class or even just a module, then creating "argument objects" and passing them into something that does the job, calling the correct methods, etc.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      In this video, I wanted to stick to the traditional Factory design pattern to show how it works. However, these design patterns were conceived in the 90s and programming languages have evolved since then. I’m currently working on a video that expands on the idea behind a pattern like the factory and then suggests a few alternatives using more modern Python features.

  • @xXHelsingGamingXx
    @xXHelsingGamingXx 3 ปีที่แล้ว

    hi, any chance you release an online course?

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว +1

      There is! I'm working on a course called Foundations of Software Design. It's still in the early stages though, so it will take a while before I can release it.

  • @bonbonpony
    @bonbonpony 3 ปีที่แล้ว

    01:30 If it doesn't really matter for this example, then it shouldn't really be in this example, because otherwise it unnecessarily obfuscates it and makes it more confusing, since the viewer's brain starts cracking things that don't really matter :q
    09:20 Not the best name for a function. Function names should express actions (verbs), not objects (nouns). Considering that, the name of this function may suggest that it reads some exporter instead of returning a read exporter object.
    09:50 Wouldn't it be returning the same instances from each call instead of a new one?
    11:08 Nope, it just says that it does ;)

  • @eldos704
    @eldos704 3 ปีที่แล้ว

    Thanks for this great video

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      You’re welcome - happy you liked it!

  • @Yankzy
    @Yankzy 3 ปีที่แล้ว

    You should do a video on Asynchronous in Python, it's little mysterious and not sure it's reliable.

  • @BrazenNL
    @BrazenNL 3 ปีที่แล้ว +2

    Being a friend of Uncle Bob, the comments in the code _really_ surprise me.

    • @BrazenNL
      @BrazenNL 3 ปีที่แล้ว +1

      @@ArjanCodes Since you're a friend of Uncle Bob, I'm assuming you've read _Clean Code_. Your methods already convey their intention, so the comments are redundant and distracting. The ultimate offender being "Main function." Your content is excellent, though.

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      Ah right, I see what you mean.
      I try to make sure that there are no pylint issues in my code examples. Pylint wants every class and method to have a docstring. I try to keep them as short as possible to not be distracting, but sometimes I go too far :).

    • @BrazenNL
      @BrazenNL 3 ปีที่แล้ว

      @@ArjanCodes That's why you can disable them in .pylintrc. 😄

    • @ArjanCodes
      @ArjanCodes  3 ปีที่แล้ว

      It kind of makes me feel dirty doing that. I’ll just have to get over it I guess ;).

    • @AR-ly5zt
      @AR-ly5zt 3 ปีที่แล้ว +1

      Take into account that is easier for the audience that are not that expert (like me) to have proper documented classes and functions :)

  • @lukocius
    @lukocius ปีที่แล้ว

    In this example an extra layer of inheritance was used. It increases the complexity in provided example without a reason :)
    Otherwise... nice.

  • @koustav2008
    @koustav2008 3 ปีที่แล้ว

    EXCELLENT!!!