focusing on design patterns leads to premature abstraction, which leads to overcomplicated code. in the examples shown, nothing really invites abstraction, neither functional, nor object-oriented. you can do it w/o higher order functions or classes, and it will be just as short and simple as functional version. there is literally no reason for any of this abstraction, if you don't dynamically switch strategies, add/delete observers, change templates. as long as your code does nothing, it does not matter, how it's written or which abstractions it uses. of course, it's much easier to write textbook-style code example that does abstraction for the sake of abstraction, but that does not mean, you should. you could have built something like a simplified version of gnu-make or a small unit-testing framework, that should have demonstrated a good portion of real-life strategy / observer / template scenarios.
This was great. One thing I will offer is that sometimes more lines of code is “less code” in the sense that it can be less complicated to understand and therefore more valuable. Not always, and I would agree that often a functional style is the right solution.
For people less familiar with design patterns, the side effect of such a video is that it explains them very well. By looking at the patterns from both the class and function implementation view, I really got the gist of the patterns. I'd like to see more videos like this with some of the other patterns, thanks! 😊
Same! Thank you Arjan - to see these patterns demonstrated in both class based and functional implementations really makes it easier to learn. Most clear and efficient explanation for these patterns I’ve ever seen. Would love to see you run through more patterns in this way!
I am using most of these. It all comes down to the specific problem. For example, I use classes when I need to hold a context; for the observer example from the video, when you do email notifications, you will need a handler for email (probably a http endpoint or something); for that handler, you will need some api key or credentials or other specific information; if the observer is a class, then these informations can easily be stored in it's private attributes, but if we use functions, then we would need to store them in a global variable near the function and I believe that it is a messy solution; another solution would be to get the informations from a global module, but this introduces coupling between the config module and the notification handler function. Another thing that I consider important is that if we use abstract classes, using the IDE (pycharm), we can easily see all the classes that are derived from the base class. If we use functions, we can't do that. This is useful for when you need to change the abstract method in base to pass additional information and you also need to change it in all derived classes.
I do really like juggling with functions, but when working with a team you've got to consider if the code remains readable for your team mates. In general I try to use functions when the class based version would be stateless. When dealing with state, and operating on that state, OO feels better. This is entirely different when working in a functional first language by the way! From my experimentation with fsharp, using types and related functions felt entirely natural.
fortunately, functions are super readable to teammates, mathematicians, and the computer. the problem is, if it's too different from what some noob did, the noob will blame you for it
@@sebaperalta2001 knowing dependency injection and using a DI framework are two separate things. The DI concept is quite simple, but then usage and configuration of a proper DI framework isnt that simple
From your examples, I definitely prefer oo versions. Imo, its a lot easier to solve a problem when you think about creating objects with their unique state and logic.
I didn't watch the video because he believes in crimes against computer science BUT this is really wrong! you definitely don't want to create a unique state in order to access your logic, the function. instead, make a unique state with structs, and don't nest your functions in them! put your functions outside the class/struct so that you can always call them. If someone says 'what if you dont want to call your function?'. you can ask 'when?', right? do a little critical thinking and be sure to ignore books like 'design patterns' and 80% of CS education, make sure you can ask the right questions when someone introduces a new concept. The software industry bought into 'object oriented see plus plus' for 20 years before coming to terms that it's a big scam and mistake, so everyone really needs to be hyper critical going forward.
I wrote one of the few commercial Modula-2 programs - a logic simulator that took gate delays into account, but also trace lengths, capacitance, and inductance. I used it because it was one of the few languages that had the necessary scientific chops, while at the same time could talk directly to Mac handles. I haven't heard of anyone using Modula-2 since.
Decorators are a great example of use of functions as arguments and as return values. It can make the code look much better, but when used wrong it very hard to understand.
Functional programming rocks. Thanks for refreshing the GOF design pattern with a functional take. Would you mind covering a few more of those patterns?
Using oo programming for a CAD system in the 1990ies was an eye opener. But the kind of religion that design patterns involved into never felt necessary. It is interesting that the programmer world is going back a little on patterns and I feel that the solutions have to be designed for the problem. I feel that patterns is a way to rewire the programmers brain and then when you analyze the problem you can reap from that knowledge for oo or functional as you fine best. It is interesting that PCs nowdays need 64GB of ram to do anything meaningful is in my opinion a result of patterns and there are OSs that run on 1,4mB whith graphics which is incredible. Programming now feels bloathed and we need to go back to the basics.
You make a really good case for how functional programming has superseded the need for most of the design patterns. I still find objects a more useful holder of state than curried functions in a lot of cases, so which to use really depends on the details of the problem you are solving.
This is not functional programming though. This is procedural vs OO programming. Using functions looks great when the code base is small but it can become really messy and unmaintainable really fast when the code base is growing, especially when there are multiple code contributors. Saving a few lines of boiler plate code, that modern IDEs take care of for you anyway, isn't as big of a win as one might think. OO has the big advantage of helping organise your code, create clear abstractions, and semantic isolation. It's not an accident why still to this day the biggest code bases are in Java and C++ (and why most modern languages support OO programming, including python).
When returning functions I make extensive use of the typing system to make it easy to understand. Make types using TypeAlias, NewType, and NamedTuple and also make higher level functions to work with the types. Hook type, RequiredOperation type, and named tuples that contain them if limited, (if there are two operations there must be a reason or why, but for simplicity let’s call it first and second). So the returned function would take in a named tuple of Hooks, and the template function would take in a named tuple of RequiredOp, and returns callable that takes in Named tuple of hooks. Etc.
Thank you Arjan for this very instructive video on design patterns in Python using OO approach and functional approach. I learnt a bit about functional programming using TypeScript, and it helped me understand that you were using "Callable" to define a "function type". I believe that by convention you use a capital letter for the first letter in the name of that "function type". Functional programming is terse and comments would definitely help.
This is literally something I have unconsciously done, I think I've used all 3 of your examples purely with functions in js and C#, in the C# it was so that I could use OO to handle Managed Resources, and then used the function based strategy pattern to pass a predicate for use filtering things used in within the managed resource :) Mixing OO and functional programming, using the best of both worlds makes me happy
I recommend using functions instead of classes whenever the class you have has just 1 function and that's it, and I recommend to use functions when passing hooks around instead of classes. I also wanna mention that the writing and reading burden of classes is not necessarily big, your mind really adjusts to filter out a lot of the noise. In my opinion, the best way to develop, is to use the methods you are already good at, while looking out for points of weakness, in order to do anything.
if the language genuine idea tellin the same then, maybe, but wast majority if the language build around classes structs and interfaces and this ide will just make the implementation less intuitive and possible slower, need to be tested though. I am working on a project when properties of the class/struct are declared as function...no way i would do that in my project :)
Word. I used to work with a java 'developer' who thought 1, 3, 5, and even 15 minute startup times for local servers was ok, that project delays were merely a matter of working long hours to fix, and that 'nothing could be done' about a 2 day project taking 8 months. Bible-thumping belief in random garbage including 'abstract object oriented programming interface provider managers', full of mistakes and very terrible problem solving ability, but believed in his own ideas and in 'java' so, so much, that he could not stop talking about how 'useful' all of the ecosystems were within it, and his entire identity was built on it. This man was so ruined by failing to look out for his points of weakness, that now he is better off sticking to what he's good at rather than destroying his identity by learning functions and minimalism
If a language supports using functions similar to how interfaces work in OOP, I find it totally reasonable as using an interface implementation in a class just to get a singular function out of it is superfluous. It is unnecessary fluff to achieve the same thing. Now, if there's more than that and you have internal state to keep track of or some other fancy stuff you need to do on the side, logging or whatever else it may be, I think using a class can make a lot of sense. However, if you just need a function to do the thing, just use a function. Just ensure you have a type definition for it (Python 3.5+ supports it for example) and you will have a much easier time writing maintainable code without requiring classes.
@@andreypopov6166 If your project becomes that much slower by switching between classes and functions you're either doing something awfully wrong or the language has horrible performance. Also, classes should generally not make your code slower. In the case of JavaScript it can even make it faster, because then instead of creating new function instances, they can all point to a singular function while being encapsulated in objects. So it mostly depends on language implementation and how you write your code rather than what you actually use. The reason why you'd make singular functions instead of classes is really because if you only need a function to do the thing, just make a type definition, create a function, do the thing through dependency injection. Having an interface implemented by a class just to have a singular function is unnecessary. It is possible to achieve the same thing with less work and the same maintainability. However, my experience with people who say things like you do is that they do not write maintainable code regardless of paradigm. The things you say are usually used as excuses to write lazy code that is almost impossible to get rid of a year or two later for one reason or another.
This is great material. While viewing it I was thinking this is basically another way of doing dependency injection. For example, the strategy pattern is injecting a dependency on a particular algorithm. Similarly, the template method is injecting dependencies on particular methods. Of course, the best explanation of dependency injection is also to be found in this channel.
Thanks Arjan! That's really interesting! In my case, what works very well for me is a mixed approach of having functions and classes. For example, I could have some concrete classes, but I would use a function as a factory to generate these objects.
The main reason for the simplification is that (classic) Java does not have standalone functions. With functions, you can certainly make things simpler. However, some patterns require tracking state, in which case you cannot use functions. Good video.
@@RunForPeace-hk1cu sounds like a good reason not to use python..... if true. You can use a closure in a class and you can use a closure outside of a class. Therefore, in c++, don't use a 'class', because you're not isolating your variables and you're just making the computer hotter.
Personally I would use the class-based approaches more. When debugging & inspecting the types of variables, they will give you much more information. Especially while the functions are simple, `Callable[[int, int], int]` isn't giving you much to go on. Compare that to having a class named `TemperatureSummingStrategy`.
That's so interesting. I've been using some of these things without knowing it. I sometimes have an update method in my class that will rerun a series of methods when I assign a new value to a property. I also use a dictionary to navigate context by running different class methods or the same with different arguments based on the key that's used. You've taught me a lot and I really appreciate it! I always look forward to your videos
protip move your function outside of the class, turn the class into a struct, and if need be, the struct can be a parameter to your function. Now you can access your functions without first instantiating memory, from anywhere in your code. That's the noob mistake. You follow the book(the ONLY book on trial for crimes against computer science), you waste a ton of time dealing with this mistake, and it'll be 15 years before you stop being a noob, and your programmer colleagues will hate you less
@@willtheoct the issue is more that I have data set structure typec A, B, and C. Each has unique needs when I clean and process the data, but they all go through the same steps. For instance, I drop columns from each but the list of columns is different for each dataset type. So I just create a class arg and assign to an attribute as an identifier for each dataset type. My logic has been that keeping it in the class means that I don't have to pass it into a function every time I want to do something for a particular dataset. I just apply the method and it already has the context manager stored in the object. Would you still recommend separate functions?
@@anti-despot2887 whatever you're doing, has at least 3 different steps. they all run under a main function anyway. thus, your function is your main, and any 'classes' with a function inside them only guarantee that you cannot test, call, or iterate on your function without first accessing (a new instance of) the class. So, yes. If you refactor your old work, it would be easier to modify and remove and isolate useless bits, which helps with the scalability of your application. If you don't refactor, you'll hit technical limits way sooner. For your particular case, If you wanted to write 'data.function()' in your code, well guess what, you already have the function outside of any 'object', and you can assign the address of the function to a member of that 'object', which should really be called a 'struct' to be C-compatible.
Yep I have the same opinion, firstable the from my opinion in the functional programming the closure are the new classes, but functional programming can be a headache for example when there are alot dependencies, and inject all them into all functions somethings is hard, so the class has all the scope to access without inject or update all functions. so from my perspective when there is a complex data structure I prefer use classes because we have all that we need inside of the class,
18:53 says we get the same output as before (i assume OO version's output). However, the function version is missing a override of hook 2 that the OO version did. It also shows in the output, where the function version is missing 1 line about hook 2 compared to OO version
Functions don't make design pattern obsolete, thinking in terms of degrees of freedom does. Which pieces of code is it useful to make interchangeable? How easily? What should the interface be when providing those interchangeable pieces - i.e. who should see what? Design patterns always seemed to me like a catalog of combinations of answers to such questions - but then again I'm not big on memorizing, I prefer to come up with things.
'design patterns' is a book of crimes against computer science, none of the stuff presented in it is useful, they are all workarounds for a self-imposed problem - you cannot use functions without first 'instantiating' something containing them, which is very anti-mathematical. The solution is to use C(no plus plus), JS, and python functions.
I love the video, and the comparisons between the two styles are very insightful. However, when I have a pipeline implementation that has 3 plugin startagies, and the code is being written by different people, in different parts of the organization, it is very difficult to make sure that they are implementing the correct interface. IDEs have automatic quick refactors for implementing abstract methods, and so it does the work of communicating the signature much better than a function type hint. Also, I can put documentation on the class, that you can see is linked via the override hint from the IDE. For these reasons, I would not say that using "10 extra lines" is that much better. It depends.
protip don't use abstract methods! writing something twice is a big problem, if you need to change it 10-50 times! the method itself is a function, and should be written outside of the class, in what you might call 'global scope'. It could be overridden if the language supports it, but not all of them do(JS), but importantly the class should be turned to a struct, containing stateful values. The function should not require this struct to exist, before the function can be used, and so the function/method must be outside the scope of the struct. Nevermind 'abstract'. Yikes. someone call the polymorphic public private inherited abstract object oriented exception handler pointer interface provider extender manager and tell him you're looking for work
@@willtheoct I don't see what this has to do with my comment. I would love to use functions without the extra line boilerplate (class definition). But the function is the plugin, written by a different part of the organization and wired up using factories, and the person writing the function has no IDE support to know what are the expected signiture of the function. Also - if the person who is responsible for the usage of the plugins wants to update the capabilities of the plugin - how does he find all the plugins? (functions) absolutly no IDE support. With class interfaces (didn't say anythong about storing data) you get both - The person writing the plugin justs implements the interface with an IDE quick action, and the person using the plugins can do search all implementors - also an easy search. Random functions in random global scopes are not discoverable in a structured way.
When I started coding in the 60s no such things existed. I still write code, and seem to have survived all these years without design patterns. But I work with bespoke / never the same twice systems. Reuse has few opportunities other than the simplest, but these seem so straightforward that they are, well, trivial. I do use modules of proven code nowadays - when it suits.
4:27 I just want еще note that this is actually is not a quicksort algorithm, although it looks like one. The most important property of quicksort is that it is made in-place and thus uses O(log n) memory.
I'm from that time as well, the Gand of Four book was great, I did my final project on a system at my work using most of the design patterns. I'm new to python, and my question using functions instead of classes is that on the examples you gave they are all in the same file. In the case of a library/framework to be used by someone else how would you "overload" these functions?
Arjan,thank you again for new info and insight. Would you consider showing a FUNCTIONAL OBSERVER PATTERN when the observer functions are SCATTERED in multiple modules?
this is a good point. The core advantage (and disadvantage) of objects is they maintain state. The OO Subject class can maintain state about all registered Observers. A 3rd party can register Observers with the Subject, so neither knows about the other. A pure-functional approach doesn't maintain state, so how do you deal with the dependency / coupling created by having to pass all the Observers to the notification function?
very helpful. problems start when modules are scattered and you don't even know how to hard code function names and their input types. it will require another layer of coding logic, hence increasing LoC.
Agree about need to use design patterns with functional programming. However, I liked more template method with oop. It uses enheretance. Function version uses if/else and many args
I'm a Salesforce developer. Unfortunately, there's no support for higher-level functions in Apex (the backend language for Salesforce), so I have to create interfaces everywhere to do simple things to make the code more scalable and decoupled. Languages that support the functional paradigm are much simpler. There's nothing better then using JS map, filter and reduce functions, for example.
Haven't watched yet, but this seems the perfect video that I needed lately. Everyone talks about design patterns, which are really confusing, since the first GENERAL language that I learned was Python. So, half the time I don't understand what some of these patterns do and why are they better than using functions (maybe functions mapped to a dictionary).
Design patterns are still relevant and necessary when it comes to building large software systems. Functions alone probably won't be good enough when you need class encapsulation to properly segregate and organize your code. That being said, mixing classes with pure functions would still be considered as a good practice in most situations, IMHO.
i think many programmers are using patterns without realizing themselves using it. Not knowing what patterns you are using doesn't mean you are not already using them.
@@RunForPeace-hk1cu Design doesn't mean OOP patterns. Most people has been teached to think inside the OOP box and doesn't realize how many good projects have been done without those weird techniques and how easy projects can be designed when you use your time to think about data and data transformations instead of asking philosophical questions about your code
I was using a mix of the strategy pattern (that i learned on the other video, thanks for sharing!) and the template method (this one i didn't knew it had this name hehe) these days ... The problem i was trying to solve was on how to construct a mathematical model which i could access the elements i was summing over individually (it was a mixture model with 3 pieces, similar to a gaussian mixture model) that i would them pass on to an optimization procedure. For the model first i tried with closures but it became cumbersome, because i needed to access the elements from within the closure ... then i separated the components and passed into a master function that would make the calculation ... but it felt weird because it looked as if they we're separated pieces and i had to use partials over the three pieces even though they shared the arguments ... finally i converged to an object with the __call__ method implemented on it on which the three pieces were 3 methods and the __call__ method would call them. It felt like a function and i implemented an ABC to help me remember exactly how to implement a new model when i happen to find a model with the qualities i want hehe Best of both worlds. And the optimization method i started with a class and ended up with a function ... that looked like a template method on functions... The function would receive an object that would implement an initial kick policy and a mixture model object do the stuff in order and return the optimal parameters that i would pass to other function to calculate the quantities i need for my research.
and if you have a vast, interconnected system, functions keep the system working, for 20+ years. on the side against functions, object oriented programming is what keeps YOU working
My point on it is it depends on your background. I came from C#, for me this is natural. For me It was in my training to recognise common problems and solve it in a common way. (Like with design patterns.) But I run into a bunch of researchers who thinks can develop software, but the truth is they can just write code (I mean those guys are super smart researcher guys!). Usually they wrote a big unscalable monolith, and praised about how good it is (which in some times the good solution, but often not in today's business). Those people just use patterns by mistake, without knowing it at all, if you are lucky (and if your job to make their code scalable and maintainable). So, my opinion again is really depends on your training/background. Ps.: I found researchers more pedant on adding metrics.
So, the thing is. I came from C++, C#. spent 15 years learning 'programming' in the style of the book 'Design Patterns'. I made lots of mistakes. Today, I no longer make mistakes. What changed? I stopped using object-oriented programming. No more C++, C#, Java, none of that. Never has an 'interface' been a thing in math. Learn to be minimal and isolate your variables. A lot of what you learn will be trash, maybe higher than 80% of it. Good standards exist, for human convenience. You need to have historical knowledge to piece the development of these standards and tech advancing bodies. These are Bell labs, IEEE, Assembly(instruction booklets are still standard if you have old machines), Unix, C(including stdio which your teachers would have heard of in their youth), Quake, OpenGL, then finally the V8 engine, JS, and the web, with Raytracing being the only real technical improvement in recent years. Linear algebra(AI) has been a subject of exploration recently because it requires a lot of wealth, inputs, and computational power to explore, so standards may soon come out of these to make sure devices can run AI. I'm sure I'm missing a lot of important standards, but honey, 80% of what you see online is useless bs, and it's really easy to tell, because it doesn't follow the tech improving standards. If it did, it would (probably) already be done and no one would be making money off of it. So when you see my big, 'unscalable monolith' that still works 50 years later, remember that its a big pyramid built out of scalable blocks of functions. And then filled out with spaghetti, for neat access to the spaghetti. And if you don't like engineering that looks like spaghetti, I suggest you don't open your computer and look at the motherboard.
I notice that when comparing the OOP and the FP examples , the OOP’s “interface with a single method” is replaced in FP by a callable. It seems like this is a limitation of OOP languages that don’t have first-class functions, like Java. Java however does have functional interfaces which allow us a nice lambda syntactic sugar
lambdas are the way out. Oracle and Microsoft will remove lambdas when they realize functional programmers can actually use them Get to typescript quickly, it's like C#/java but for the web, and it's best feature is that it runs JS, which is actually the functional language everyone needs.
Design Patterns were created to solve a problem from languages like Java. Python usually doesn't strictly need them (because it's a language that groups a lot of different programming models), but can use them to make code more scalable and maintainable. SOLID, on the other hand, is a generic set of principles that can be leveraged by any OOP language. Nice video as usual!
'Design Patterns' is a book of crimes against computer science. SOLID is also a crime against computer science and so is OOP, but they've never been on trial for it. now you know not to trust 80% of what you learn
When I learn design pattern (note the lower case), I did not bound to the class implementation in GoF's Design Patterns. To me design patterns are best practices/tools that can be implemented in any language/paradigm (as seen in hte video).
In my opinion the answer is simple and short: Yes!
ปีที่แล้ว
I use functional approach like passing functions as arguments only when its justified, eg. when building plugin systems or when logic of the system has to be very flexible. Otherwise, i prefer simple conditional branching as thats what everyone understands
if.. branching can also be expressed as a dot product if you're a function purist. Unfortunately for you, your sillicon hardware is turning your 'simple conditional branching' into a physics+engineering function involving a dot product. So you are still using functions when you write 'if' and that makes it ok
Only an ignorant developer will think that design patterns are obsolete. Stating this in an interview is one sure way for me to ignore you as a viable prospect. While the actual design patterns might change over time as languages change and evolve, the concept of design patterns will always be valid.
'Design Patterns' is actually a book, full of crimes against computer science. The whole book can be ignored if you put your functions outside your structs, but so many weirdos keep thumping the book because to them, it's the holy bible of things that work around this one problem.
I would prefer objects when i need to keep track of an internal state and functions if not needed. For exemple, i can"t see how to use subject as a function in the function observer exemple. imo, most of the time, the "subcribe" action and the he "notify" one are in different part of the code. If i have to manage a list/collection somewhere, i would prefer to attach it on my subject object. Great video by the way, I totally agree with your vision on design patterns usefullness
That was a great and instructive video ! But does that mean that classes are obsolete ? (I am planning to use a OOP language that has a sound type system) For the last case, a good way to simplify the implementation is to use currying. Some languages like haskell as that implemented by default
You will always need objects/classes to hold state information and such In complicated code design, classes are still useful It’s not either or. You can mix and match to suit the problem at hand
shouldn't that say objects/structs, since structs hold state information, and work perfectly fine in complicated code design? the use of the word 'class' here implies that you didn't learn C, but maybe you learned C++ and the garbage associated with it. In which case, I would recommend putting your stateful information in a struct, and your functions outside of the struct, so that you can reuse them. 'Class' commonly implies the two are bundled together and that you cannot use a function without having some stateful data set up beforehand.
Stuff like strategy patterns i think will never be obsolete by the simple case of readability. Huge if else / case statements with all the logic inside these are incredibly unreadable. And if you are gonna use a function for each statement anyways, then you're just missing an interface to be at the exact same place. I do wish that Python could add interface as a statement instead of using ABC classes, but that doesn't really matter in the end.
I use templates a lot. In practice, concrete implementations of a base template almost always need each of the overridden components to access the same shared state. Not sure how the functional version achieves this. The state schema is specific to implementation, so we can’t just add it to the base template. Bind all overridden func components to “self” (or any state-carrying object) - and you’re back in OOP world. Wrap them all inside another func so that they share its scope - and this is just hacky OOP again…Could you please address this design problem in the next videos (if any) about the template pattern?
If you want to see a super in depth video at this precise topic watch thios conference: Classic Design Patterns: Where Are They Now - Brandon Rhodes - code::dive 2022
then you definitely dont want to read the book 'Design Patterns' by the gang of four, known for their crimes against computer science. Whole thing can be skipped by putting functions outside of structs and state. if you hear someone say 'abstract object oriented public private interface instance override provider manager' you know they've got mental issues
i saw that you use vscode with python, do you know why i cant debug in vscode if a venv is used. if i switch to system local python it works. every time i use a venv the debugging mode dont stop at a break point. the same behavior after installing all new in a virtual machine.
"people who apparently consumed way more drinks than humanly possible" sounds like your average college student, but jokes aside very good video with good points.
I've been looking for a convincing reason to use classes since they were first added to PHP and I've never found one. I almost exclusively pass 2 objects to every function, the input object and the output object which allows me to string together any number of functions to build the output object into some type of overall response. This avoids all problems with the order and quantity of the arguments. Also every function validates it's own inputs and rather than throwing an error, failures are added to the output object skipping the remaining and subsequent function code. After the execution, say for an API call, failures are assessed/logged and the API response adjusted for return. So an api call such as /api/v1/calculate_account {'account_id': 1} would call the calculate_account($input=['account_id'=>1], $output=[]), calculate_account extracts account_id as an integer and runs any number of nested functions eventually returning the modified output object with the response.
When a perrson wasnt able to master (or based on the tittle even understand why they are needed) design patterns such strange questions arises, yes :) The next one will be will the functions make architectural patterns/approaches obsolete...
I think the examples in this video are flawed. The classes are either stateless or are used in a way that doesn't make use of their state. But equipping data (that is, state) with functions that set, get or generally deal with it in one way or another is the purpose of classes. So if you don't have data, of course classes are just a waste then.
Where did you get that, lol. GoF patterns are as old as time and most are not about state but encapsulation, maintainability and reusability. Object oriented patterns, classes are just the tool most languages expose to build them. When Alan Key described them there were no classes as some understand them now (something like set category but in programming).
observer pattern is a good concept but it pretty useless in real world applications. Since we have to design our apps to be reliable we should provide consistency of actions like sending emails or smss. And observer pattern itself don't help us with that. It's better to use external message broker
Your voice reminds me: … At that time, in Germany, in '69, '70 They had already discotheques So I would take my car, would go to a discotheque ... … My name is Giovanni Giorgio, but everybody calls me Giorgio
Functions are more concise at the cost of readability and ease of reverse engineering. Everything shares a common global state, so the code feels very spaghetti-like. Classes, at least, provide some sense of structure that represents the topology of the system. just my $0.02
Can you show real code using this patterns and not examples, it seems all of this stuff works only in pseudo vacuum and in real world applications just creating mess of abstractions that slowdown, performance, readability, and TIME TO LEARN everyone to stay on one the same page)
even before then, C was super useful, widely used, and stuff written in it still works perfect today. If you narrowly missed the C era and were in the hellscape that is c++, dang that sucks. Java is no better - a 'hello world' webserver in java is 43 lines, while in JS it's 3 and in C probably around 6-10.
Design patterns are a thing of OOP, OOP is so bad that requires special techniques to achieve what it could be previously done with pure imperative or pure functional programming
👷 Join the FREE Code Diagnosis Workshop to help you review code more effectively using my 3-Factor Diagnosis Framework: www.arjancodes.com/diagnosis
focusing on design patterns leads to premature abstraction, which leads to overcomplicated code.
in the examples shown, nothing really invites abstraction, neither functional, nor object-oriented. you can do it w/o higher order functions or classes, and it will be just as short and simple as functional version. there is literally no reason for any of this abstraction, if you don't dynamically switch strategies, add/delete observers, change templates.
as long as your code does nothing, it does not matter, how it's written or which abstractions it uses. of course, it's much easier to write textbook-style code example that does abstraction for the sake of abstraction, but that does not mean, you should.
you could have built something like a simplified version of gnu-make or a small unit-testing framework, that should have demonstrated a good portion of real-life strategy / observer / template scenarios.
This was great. One thing I will offer is that sometimes more lines of code is “less code” in the sense that it can be less complicated to understand and therefore more valuable. Not always, and I would agree that often a functional style is the right solution.
For people less familiar with design patterns, the side effect of such a video is that it explains them very well. By looking at the patterns from both the class and function implementation view, I really got the gist of the patterns. I'd like to see more videos like this with some of the other patterns, thanks! 😊
This!
I concur. More varieties of the same thing to help it sink in (for me, a series of design patterns to better recognize the ones others use)
Same! Thank you Arjan - to see these patterns demonstrated in both class based and functional implementations really makes it easier to learn. Most clear and efficient explanation for these patterns I’ve ever seen. Would love to see you run through more patterns in this way!
我最喜欢你最后一句话,这也是我本人坚守的编程思想。
I am using most of these. It all comes down to the specific problem. For example, I use classes when I need to hold a context; for the observer example from the video, when you do email notifications, you will need a handler for email (probably a http endpoint or something); for that handler, you will need some api key or credentials or other specific information; if the observer is a class, then these informations can easily be stored in it's private attributes, but if we use functions, then we would need to store them in a global variable near the function and I believe that it is a messy solution; another solution would be to get the informations from a global module, but this introduces coupling between the config module and the notification handler function.
Another thing that I consider important is that if we use abstract classes, using the IDE (pycharm), we can easily see all the classes that are derived from the base class. If we use functions, we can't do that. This is useful for when you need to change the abstract method in base to pass additional information and you also need to change it in all derived classes.
Insightful, would love a book on Design patterns and SOLID principles how they apply in Python ❤
There is a book called "Design Patterns in Python"
I do really like juggling with functions, but when working with a team you've got to consider if the code remains readable for your team mates. In general I try to use functions when the class based version would be stateless. When dealing with state, and operating on that state, OO feels better.
This is entirely different when working in a functional first language by the way! From my experimentation with fsharp, using types and related functions felt entirely natural.
fortunately, functions are super readable to teammates, mathematicians, and the computer. the problem is, if it's too different from what some noob did, the noob will blame you for it
@@willtheoctMost importantly, the team needs members that don't call each other "noobs".
@@Toopa88 that's pure conjecture
This is one of my favourite videos. Will come again to this again and again. It has sparked many ideas for my team already!
Thank you for these kind words! I'm glad to hear it inspired you so much.
Would be cool if you showcased dependency injection framework too, since people hopefully don't all have to reinvent the wheel.
With functions, I think you can do dependency injection with partial functions, like in the example.
He already have videos regarding dependency injection
@@sebaperalta2001 knowing dependency injection and using a DI framework are two separate things. The DI concept is quite simple, but then usage and configuration of a proper DI framework isnt that simple
th-cam.com/video/2ejbLVkCndI/w-d-xo.html
From your examples, I definitely prefer oo versions. Imo, its a lot easier to solve a problem when you think about creating objects with their unique state and logic.
I didn't watch the video because he believes in crimes against computer science BUT this is really wrong! you definitely don't want to create a unique state in order to access your logic, the function.
instead, make a unique state with structs, and don't nest your functions in them! put your functions outside the class/struct so that you can always call them. If someone says 'what if you dont want to call your function?'. you can ask 'when?', right? do a little critical thinking and be sure to ignore books like 'design patterns' and 80% of CS education, make sure you can ask the right questions when someone introduces a new concept. The software industry bought into 'object oriented see plus plus' for 20 years before coming to terms that it's a big scam and mistake, so everyone really needs to be hyper critical going forward.
I wrote one of the few commercial Modula-2 programs - a logic simulator that took gate delays into account, but also trace lengths, capacitance, and inductance. I used it because it was one of the few languages that had the necessary scientific chops, while at the same time could talk directly to Mac handles. I haven't heard of anyone using Modula-2 since.
love your videos on design patterns. 23 min flew by in a sec. I hope to see more
Decorators are a great example of use of functions as arguments and as return values. It can make the code look much better, but when used wrong it very hard to understand.
Functional programming rocks. Thanks for refreshing the GOF design pattern with a functional take. Would you mind covering a few more of those patterns?
check out bob martin's book on functional programming design
Using oo programming for a CAD system in the 1990ies was an eye opener. But the kind of religion that design patterns involved into never felt necessary. It is interesting that the programmer world is going back a little on patterns and I feel that the solutions have to be designed for the problem. I feel that patterns is a way to rewire the programmers brain and then when you analyze the problem you can reap from that knowledge for oo or functional as you fine best. It is interesting that PCs nowdays need 64GB of ram to do anything meaningful is in my opinion a result of patterns and there are OSs that run on 1,4mB whith graphics which is incredible. Programming now feels bloathed and we need to go back to the basics.
Fully agree with this
You make a really good case for how functional programming has superseded the need for most of the design patterns. I still find objects a more useful holder of state than curried functions in a lot of cases, so which to use really depends on the details of the problem you are solving.
'Design Patterns' is a specific book, the first and only one on trial for crimes against computer science.
This is not functional programming though. This is procedural vs OO programming. Using functions looks great when the code base is small but it can become really messy and unmaintainable really fast when the code base is growing, especially when there are multiple code contributors.
Saving a few lines of boiler plate code, that modern IDEs take care of for you anyway, isn't as big of a win as one might think.
OO has the big advantage of helping organise your code, create clear abstractions, and semantic isolation. It's not an accident why still to this day the biggest code bases are in Java and C++ (and why most modern languages support OO programming, including python).
When returning functions I make extensive use of the typing system to make it easy to understand. Make types using TypeAlias, NewType, and NamedTuple and also make higher level functions to work with the types.
Hook type, RequiredOperation type, and named tuples that contain them if limited, (if there are two operations there must be a reason or why, but for simplicity let’s call it first and second). So the returned function would take in a named tuple of Hooks, and the template function would take in a named tuple of RequiredOp, and returns callable that takes in Named tuple of hooks. Etc.
Thank you Arjan for this very instructive video on design patterns in Python using OO approach and functional approach. I learnt a bit about functional programming using TypeScript, and it helped me understand that you were using "Callable" to define a "function type". I believe that by convention you use a capital letter for the first letter in the name of that "function type". Functional programming is terse and comments would definitely help.
This is literally something I have unconsciously done, I think I've used all 3 of your examples purely with functions in js and C#, in the C# it was so that I could use OO to handle Managed Resources, and then used the function based strategy pattern to pass a predicate for use filtering things used in within the managed resource :)
Mixing OO and functional programming, using the best of both worlds makes me happy
I ditched C# so I wouldn't have to use OO again. see you in 5 years buddy
I recommend using functions instead of classes whenever the class you have has just 1 function and that's it, and I recommend to use functions when passing hooks around instead of classes.
I also wanna mention that the writing and reading burden of classes is not necessarily big, your mind really adjusts to filter out a lot of the noise. In my opinion, the best way to develop, is to use the methods you are already good at, while looking out for points of weakness, in order to do anything.
if the language genuine idea tellin the same then, maybe, but wast majority if the language build around classes structs and interfaces and this ide will just make the implementation less intuitive and possible slower, need to be tested though. I am working on a project when properties of the class/struct are declared as function...no way i would do that in my project :)
Depends on the language and use case. In some cases classes are a must
Word. I used to work with a java 'developer' who thought 1, 3, 5, and even 15 minute startup times for local servers was ok, that project delays were merely a matter of working long hours to fix, and that 'nothing could be done' about a 2 day project taking 8 months. Bible-thumping belief in random garbage including 'abstract object oriented programming interface provider managers', full of mistakes and very terrible problem solving ability, but believed in his own ideas and in 'java' so, so much, that he could not stop talking about how 'useful' all of the ecosystems were within it, and his entire identity was built on it.
This man was so ruined by failing to look out for his points of weakness, that now he is better off sticking to what he's good at rather than destroying his identity by learning functions and minimalism
If a language supports using functions similar to how interfaces work in OOP, I find it totally reasonable as using an interface implementation in a class just to get a singular function out of it is superfluous. It is unnecessary fluff to achieve the same thing. Now, if there's more than that and you have internal state to keep track of or some other fancy stuff you need to do on the side, logging or whatever else it may be, I think using a class can make a lot of sense.
However, if you just need a function to do the thing, just use a function. Just ensure you have a type definition for it (Python 3.5+ supports it for example) and you will have a much easier time writing maintainable code without requiring classes.
@@andreypopov6166 If your project becomes that much slower by switching between classes and functions you're either doing something awfully wrong or the language has horrible performance. Also, classes should generally not make your code slower. In the case of JavaScript it can even make it faster, because then instead of creating new function instances, they can all point to a singular function while being encapsulated in objects. So it mostly depends on language implementation and how you write your code rather than what you actually use.
The reason why you'd make singular functions instead of classes is really because if you only need a function to do the thing, just make a type definition, create a function, do the thing through dependency injection. Having an interface implemented by a class just to have a singular function is unnecessary. It is possible to achieve the same thing with less work and the same maintainability.
However, my experience with people who say things like you do is that they do not write maintainable code regardless of paradigm. The things you say are usually used as excuses to write lazy code that is almost impossible to get rid of a year or two later for one reason or another.
This is great material. While viewing it I was thinking this is basically another way of doing dependency injection.
For example, the strategy pattern is injecting a dependency on a particular algorithm. Similarly, the template method is injecting dependencies on particular methods.
Of course, the best explanation of dependency injection is also to be found in this channel.
crimes against computer science
Thanks Arjan! That's really interesting! In my case, what works very well for me is a mixed approach of having functions and classes. For example, I could have some concrete classes, but I would use a function as a factory to generate these objects.
The main reason for the simplification is that (classic) Java does not have standalone functions. With functions, you can certainly make things simpler. However, some patterns require tracking state, in which case you cannot use functions. Good video.
You could actually closures which are functions with state
@@faysoufoxmany features in python don’t support closures
@@faysoufoxand you can use closures in classes too … it’s not mutually exclusive thing
@@RunForPeace-hk1cu sounds like a good reason not to use python..... if true.
You can use a closure in a class and you can use a closure outside of a class. Therefore, in c++, don't use a 'class', because you're not isolating your variables and you're just making the computer hotter.
Golden video, Arjan. Thanks for sharing!
Glad you enjoyed it!
Personally I would use the class-based approaches more. When debugging & inspecting the types of variables, they will give you much more information. Especially while the functions are simple, `Callable[[int, int], int]` isn't giving you much to go on. Compare that to having a class named `TemperatureSummingStrategy`.
That's so interesting. I've been using some of these things without knowing it. I sometimes have an update method in my class that will rerun a series of methods when I assign a new value to a property. I also use a dictionary to navigate context by running different class methods or the same with different arguments based on the key that's used.
You've taught me a lot and I really appreciate it! I always look forward to your videos
protip move your function outside of the class, turn the class into a struct, and if need be, the struct can be a parameter to your function. Now you can access your functions without first instantiating memory, from anywhere in your code.
That's the noob mistake. You follow the book(the ONLY book on trial for crimes against computer science), you waste a ton of time dealing with this mistake, and it'll be 15 years before you stop being a noob, and your programmer colleagues will hate you less
@@willtheoct the issue is more that I have data set structure typec A, B, and C. Each has unique needs when I clean and process the data, but they all go through the same steps. For instance, I drop columns from each but the list of columns is different for each dataset type. So I just create a class arg and assign to an attribute as an identifier for each dataset type. My logic has been that keeping it in the class means that I don't have to pass it into a function every time I want to do something for a particular dataset. I just apply the method and it already has the context manager stored in the object. Would you still recommend separate functions?
@@anti-despot2887 whatever you're doing, has at least 3 different steps. they all run under a main function anyway. thus, your function is your main, and any 'classes' with a function inside them only guarantee that you cannot test, call, or iterate on your function without first accessing (a new instance of) the class.
So, yes. If you refactor your old work, it would be easier to modify and remove and isolate useless bits, which helps with the scalability of your application. If you don't refactor, you'll hit technical limits way sooner.
For your particular case, If you wanted to write 'data.function()' in your code, well guess what, you already have the function outside of any 'object', and you can assign the address of the function to a member of that 'object', which should really be called a 'struct' to be C-compatible.
Yep I have the same opinion, firstable the from my opinion in the functional programming the closure are the new classes, but functional programming can be a headache for example when there are alot dependencies, and inject all them into all functions somethings is hard, so the class has all the scope to access without inject or update all functions. so from my perspective when there is a complex data structure I prefer use classes because we have all that we need inside of the class,
18:53 says we get the same output as before (i assume OO version's output). However, the function version is missing a override of hook 2 that the OO version did. It also shows in the output, where the function version is missing 1 line about hook 2 compared to OO version
Functions don't make design pattern obsolete, thinking in terms of degrees of freedom does. Which pieces of code is it useful to make interchangeable? How easily? What should the interface be when providing those interchangeable pieces - i.e. who should see what? Design patterns always seemed to me like a catalog of combinations of answers to such questions - but then again I'm not big on memorizing, I prefer to come up with things.
'design patterns' is a book of crimes against computer science, none of the stuff presented in it is useful, they are all workarounds for a self-imposed problem - you cannot use functions without first 'instantiating' something containing them, which is very anti-mathematical.
The solution is to use C(no plus plus), JS, and python functions.
I love the video, and the comparisons between the two styles are very insightful.
However, when I have a pipeline implementation that has 3 plugin startagies, and the code is being written by different people, in different parts of the organization, it is very difficult to make sure that they are implementing the correct interface.
IDEs have automatic quick refactors for implementing abstract methods, and so it does the work of communicating the signature much better than a function type hint. Also, I can put documentation on the class, that you can see is linked via the override hint from the IDE.
For these reasons, I would not say that using "10 extra lines" is that much better. It depends.
protip don't use abstract methods! writing something twice is a big problem, if you need to change it 10-50 times!
the method itself is a function, and should be written outside of the class, in what you might call 'global scope'. It could be overridden if the language supports it, but not all of them do(JS), but importantly the class should be turned to a struct, containing stateful values. The function should not require this struct to exist, before the function can be used, and so the function/method must be outside the scope of the struct.
Nevermind 'abstract'. Yikes. someone call the polymorphic public private inherited abstract object oriented exception handler pointer interface provider extender manager and tell him you're looking for work
@@willtheoct I don't see what this has to do with my comment. I would love to use functions without the extra line boilerplate (class definition). But the function is the plugin, written by a different part of the organization and wired up using factories, and the person writing the function has no IDE support to know what are the expected signiture of the function. Also - if the person who is responsible for the usage of the plugins wants to update the capabilities of the plugin - how does he find all the plugins? (functions) absolutly no IDE support.
With class interfaces (didn't say anythong about storing data) you get both -
The person writing the plugin justs implements the interface with an IDE quick action,
and the person using the plugins can do search all implementors - also an easy search.
Random functions in random global scopes are not discoverable in a structured way.
When I started coding in the 60s no such things existed. I still write code, and seem to have survived all these years without design patterns. But I work with bespoke / never the same twice systems. Reuse has few opportunities other than the simplest, but these seem so straightforward that they are, well, trivial. I do use modules of proven code nowadays - when it suits.
4:27 I just want еще note that this is actually is not a quicksort algorithm, although it looks like one. The most important property of quicksort is that it is made in-place and thus uses O(log n) memory.
I'm from that time as well, the Gand of Four book was great, I did my final project on a system at my work using most of the design patterns. I'm new to python, and my question using functions instead of classes is that on the examples you gave they are all in the same file. In the case of a library/framework to be used by someone else how would you "overload" these functions?
wtf?
is this a joke? no other book has been on trial for crimes against computer science
Arjan,thank you again for new info and insight. Would you consider showing a FUNCTIONAL OBSERVER PATTERN when the observer functions are SCATTERED in multiple modules?
this is a good point. The core advantage (and disadvantage) of objects is they maintain state. The OO Subject class can maintain state about all registered Observers. A 3rd party can register Observers with the Subject, so neither knows about the other. A pure-functional approach doesn't maintain state, so how do you deal with the dependency / coupling created by having to pass all the Observers to the notification function?
@@gonecoastaltoo I was about to write the same comment. Functional version of Observer Pattern is not doing the same thing as OOP version.
Would be awesome if you’d write a book about this Arjan!
very helpful. problems start when modules are scattered and you don't even know how to hard code function names and their input types. it will require another layer of coding logic, hence increasing LoC.
what is a module? that doesn't sound very scientific.
Agree about need to use design patterns with functional programming. However, I liked more template method with oop. It uses enheretance. Function version uses if/else and many args
Loved the intro! Great video, thank you Arjan
Thanks Shanil, I'm glad you liked it!
I'm a Salesforce developer. Unfortunately, there's no support for higher-level functions in Apex (the backend language for Salesforce), so I have to create interfaces everywhere to do simple things to make the code more scalable and decoupled.
Languages that support the functional paradigm are much simpler. There's nothing better then using JS map, filter and reduce functions, for example.
Haven't watched yet, but this seems the perfect video that I needed lately. Everyone talks about design patterns, which are really confusing, since the first GENERAL language that I learned was Python. So, half the time I don't understand what some of these patterns do and why are they better than using functions (maybe functions mapped to a dictionary).
Loved the Intro. I wonder how did you not fear having a computer next to a fridge where the people got drunk.
More content on design patterns!! 💪💪
On it!
Wonderful video as usual, thanks Arjan!!!
Thank you Miguel, I'm happy you enjoyed it!
Design patterns are still relevant and necessary when it comes to building large software systems. Functions alone probably won't be good enough when you need class encapsulation to properly segregate and organize your code. That being said, mixing classes with pure functions would still be considered as a good practice in most situations, IMHO.
That's what different files and modules are for. The biggest programming project that has ever existed doesn't use those famous patterns
i think many programmers are using patterns without realizing themselves using it. Not knowing what patterns you are using doesn't mean you are not already using them.
@@ALIENdrifter66they use patterns
Nobody writes a million LOC without a design structure
@@RunForPeace-hk1cu Design doesn't mean OOP patterns.
Most people has been teached to think inside the OOP box and doesn't realize how many good projects have been done without those weird techniques and how easy projects can be designed when you use your time to think about data and data transformations instead of asking philosophical questions about your code
@@ALIENdrifter66 agreed that some OO patterns are weird and may lead to overly complicated code structure. Btw, functional has patterns too..
I was using a mix of the strategy pattern (that i learned on the other video, thanks for sharing!) and the template method (this one i didn't knew it had this name hehe) these days ...
The problem i was trying to solve was on how to construct a mathematical model which i could access the elements i was summing over individually (it was a mixture model with 3 pieces, similar to a gaussian mixture model) that i would them pass on to an optimization procedure.
For the model first i tried with closures but it became cumbersome, because i needed to access the elements from within the closure ... then i separated the components and passed into a master function that would make the calculation ... but it felt weird because it looked as if they we're separated pieces and i had to use partials over the three pieces even though they shared the arguments ... finally i converged to an object with the __call__ method implemented on it on which the three pieces were 3 methods and the __call__ method would call them. It felt like a function and i implemented an ABC to help me remember exactly how to implement a new model when i happen to find a model with the qualities i want hehe Best of both worlds.
And the optimization method i started with a class and ended up with a function ... that looked like a template method on functions... The function would receive an object that would implement an initial kick policy and a mixture model object do the stuff in order and return the optimal parameters that i would pass to other function to calculate the quantities i need for my research.
I vote in favor of functions. Especially if you don't have a vast interconnected system. For straight up processing and tasks, functions first!
and if you have a vast, interconnected system, functions keep the system working, for 20+ years.
on the side against functions, object oriented programming is what keeps YOU working
My point on it is it depends on your background. I came from C#, for me this is natural. For me It was in my training to recognise common problems and solve it in a common way. (Like with design patterns.) But I run into a bunch of researchers who thinks can develop software, but the truth is they can just write code (I mean those guys are super smart researcher guys!). Usually they wrote a big unscalable monolith, and praised about how good it is (which in some times the good solution, but often not in today's business). Those people just use patterns by mistake, without knowing it at all, if you are lucky (and if your job to make their code scalable and maintainable). So, my opinion again is really depends on your training/background.
Ps.: I found researchers more pedant on adding metrics.
So, the thing is.
I came from C++, C#. spent 15 years learning 'programming' in the style of the book 'Design Patterns'. I made lots of mistakes.
Today, I no longer make mistakes. What changed? I stopped using object-oriented programming. No more C++, C#, Java, none of that. Never has an 'interface' been a thing in math. Learn to be minimal and isolate your variables. A lot of what you learn will be trash, maybe higher than 80% of it.
Good standards exist, for human convenience. You need to have historical knowledge to piece the development of these standards and tech advancing bodies. These are Bell labs, IEEE, Assembly(instruction booklets are still standard if you have old machines), Unix, C(including stdio which your teachers would have heard of in their youth), Quake, OpenGL, then finally the V8 engine, JS, and the web, with Raytracing being the only real technical improvement in recent years. Linear algebra(AI) has been a subject of exploration recently because it requires a lot of wealth, inputs, and computational power to explore, so standards may soon come out of these to make sure devices can run AI.
I'm sure I'm missing a lot of important standards, but honey, 80% of what you see online is useless bs, and it's really easy to tell, because it doesn't follow the tech improving standards. If it did, it would (probably) already be done and no one would be making money off of it.
So when you see my big, 'unscalable monolith' that still works 50 years later, remember that its a big pyramid built out of scalable blocks of functions. And then filled out with spaghetti, for neat access to the spaghetti. And if you don't like engineering that looks like spaghetti, I suggest you don't open your computer and look at the motherboard.
absolutely amazing examples
Glad you enjoyed the content!
I notice that when comparing the OOP and the FP examples , the OOP’s “interface with a single method” is replaced in FP by a callable.
It seems like this is a limitation of OOP languages that don’t have first-class functions, like Java. Java however does have functional interfaces which allow us a nice lambda syntactic sugar
lambdas are the way out. Oracle and Microsoft will remove lambdas when they realize functional programmers can actually use them
Get to typescript quickly, it's like C#/java but for the web, and it's best feature is that it runs JS, which is actually the functional language everyone needs.
Design Patterns were created to solve a problem from languages like Java. Python usually doesn't strictly need them (because it's a language that groups a lot of different programming models), but can use them to make code more scalable and maintainable. SOLID, on the other hand, is a generic set of principles that can be leveraged by any OOP language. Nice video as usual!
'Design Patterns' is a book of crimes against computer science.
SOLID is also a crime against computer science and so is OOP, but they've never been on trial for it.
now you know not to trust 80% of what you learn
When I learn design pattern (note the lower case), I did not bound to the class implementation in GoF's Design Patterns.
To me design patterns are best practices/tools that can be implemented in any language/paradigm (as seen in hte video).
This topic is super interesting
Glad you enjoyed the video!
In my opinion the answer is simple and short: Yes!
I use functional approach like passing functions as arguments only when its justified, eg. when building plugin systems or when logic of the system has to be very flexible. Otherwise, i prefer simple conditional branching as thats what everyone understands
if.. branching can also be expressed as a dot product if you're a function purist.
Unfortunately for you, your sillicon hardware is turning your 'simple conditional branching' into a physics+engineering function involving a dot product. So you are still using functions when you write 'if' and that makes it ok
Only an ignorant developer will think that design patterns are obsolete. Stating this in an interview is one sure way for me to ignore you as a viable prospect. While the actual design patterns might change over time as languages change and evolve, the concept of design patterns will always be valid.
'Design Patterns' is actually a book, full of crimes against computer science.
The whole book can be ignored if you put your functions outside your structs, but so many weirdos keep thumping the book because to them, it's the holy bible of things that work around this one problem.
They are becoming obsolete and will continue to change, design patterns were born because of programming language limitations
I would prefer objects when i need to keep track of an internal state and functions if not needed. For exemple, i can"t see how to use subject as a function in the function observer exemple. imo, most of the time, the "subcribe" action and the he "notify" one are in different part of the code. If i have to manage a list/collection somewhere, i would prefer to attach it on my subject object. Great video by the way, I totally agree with your vision on design patterns usefullness
just call the objects 'structs' and youre golden. not needing state to use a function is the important part
I also learned pogramming in Modula 2
Very helpful to me. Thank you for sharing.
Glad it was helpful!
That was a great and instructive video ! But does that mean that classes are obsolete ? (I am planning to use a OOP language that has a sound type system)
For the last case, a good way to simplify the implementation is to use currying. Some languages like haskell as that implemented by default
the class based aproach looks cleaner and easier to read.
if it looks easier, then the demonstrator made a mistake. No I'm not watching the whole video, his favorite book is a crime against computer science.
Would be funny to take your Modula 2 code - aka the "beer app" - and recode it in Python with a video...
You will always need objects/classes to hold state information and such
In complicated code design, classes are still useful
It’s not either or.
You can mix and match to suit the problem at hand
shouldn't that say objects/structs, since structs hold state information, and work perfectly fine in complicated code design?
the use of the word 'class' here implies that you didn't learn C, but maybe you learned C++ and the garbage associated with it. In which case, I would recommend putting your stateful information in a struct, and your functions outside of the struct, so that you can reuse them. 'Class' commonly implies the two are bundled together and that you cannot use a function without having some stateful data set up beforehand.
which switches are you using? it’s so clicky. want my keyboard to sound similar
Stuff like strategy patterns i think will never be obsolete by the simple case of readability. Huge if else / case statements with all the logic inside these are incredibly unreadable.
And if you are gonna use a function for each statement anyways, then you're just missing an interface to be at the exact same place.
I do wish that Python could add interface as a statement instead of using ABC classes, but that doesn't really matter in the end.
Hah! Modula2. Was it Wirth it?
great story! also the fact that your first production software was used to count beers is very northern European 😅
I use templates a lot. In practice, concrete implementations of a base template almost always need each of the overridden components to access the same shared state. Not sure how the functional version achieves this. The state schema is specific to implementation, so we can’t just add it to the base template. Bind all overridden func components to “self” (or any state-carrying object) - and you’re back in OOP world. Wrap them all inside another func so that they share its scope - and this is just hacky OOP again…Could you please address this design problem in the next videos (if any) about the template pattern?
Sorry for spamming here, but can you make a video on MyPY please? Or a series of videos?😊
What is your keyboard
If you want to see a super in depth video at this precise topic watch thios conference:
Classic Design Patterns: Where Are They Now - Brandon Rhodes - code::dive 2022
This is why I don’t like design patterns that introduces noisy words like context or strategy. Just write business logic and chill please
then you definitely dont want to read the book 'Design Patterns' by the gang of four, known for their crimes against computer science. Whole thing can be skipped by putting functions outside of structs and state.
if you hear someone say 'abstract object oriented public private interface instance override provider manager' you know they've got mental issues
i saw that you use vscode with python, do you know why i cant debug in vscode if a venv is used. if i switch to system local python it works. every time i use a venv the debugging mode dont stop at a break point. the same behavior after installing all new in a virtual machine.
Funny enough, passing functions to functions is a pattern in itself, which is DI.
"people who apparently consumed way more drinks than humanly possible" sounds like your average college student, but jokes aside very good video with good points.
I've been looking for a convincing reason to use classes since they were first added to PHP and I've never found one. I almost exclusively pass 2 objects to every function, the input object and the output object which allows me to string together any number of functions to build the output object into some type of overall response. This avoids all problems with the order and quantity of the arguments. Also every function validates it's own inputs and rather than throwing an error, failures are added to the output object skipping the remaining and subsequent function code. After the execution, say for an API call, failures are assessed/logged and the API response adjusted for return.
So an api call such as /api/v1/calculate_account {'account_id': 1} would call the calculate_account($input=['account_id'=>1], $output=[]), calculate_account extracts account_id as an integer and runs any number of nested functions eventually returning the modified output object with the response.
the technique shown at 21:00 could be achieved also using partial
Edit: I continued ghe video and find out it's already explained lol
wow, you actually watched the video?
if you ever see a book from that publisher, you can immediately ignore all opinions from the person thumping it.
When a perrson wasnt able to master (or based on the tittle even understand why they are needed) design patterns such strange questions arises, yes :) The next one will be will the functions make architectural patterns/approaches obsolete...
Instead of using the partial function, I prefer to use a class that implements __call__
precompiling assets will be fun
I think the examples in this video are flawed. The classes are either stateless or are used in a way that doesn't make use of their state. But equipping data (that is, state) with functions that set, get or generally deal with it in one way or another is the purpose of classes. So if you don't have data, of course classes are just a waste then.
Where did you get that, lol. GoF patterns are as old as time and most are not about state but encapsulation, maintainability and reusability. Object oriented patterns, classes are just the tool most languages expose to build them.
When Alan Key described them there were no classes as some understand them now (something like set category but in programming).
observer pattern is a good concept but it pretty useless in real world applications. Since we have to design our apps to be reliable we should provide consistency of actions like sending emails or smss. And observer pattern itself don't help us with that. It's better to use external message broker
2:35 design patterns was one of the worst courses I had because the lecturers didn't care.
Passing all the functions to main function can be avoided using the builder pattern, a pattern heavily used in functional programming
That's what Functional Programming is right?
Your voice reminds me:
… At that time, in Germany, in '69, '70
They had already discotheques
So I would take my car, would go to a discotheque
...
… My name is Giovanni Giorgio, but everybody calls me Giorgio
Love that album!
great
Maybe I'll never understand why all of this is ever needed.
Functions are more concise at the cost of readability and ease of reverse engineering. Everything shares a common global state, so the code feels very spaghetti-like. Classes, at least, provide some sense of structure that represents the topology of the system. just my $0.02
> Everything shares a common global state
Just write functions, not mutable procedures. Problem solved.
Closures have entered the chat...
Should rename this video: "How to fall for MyPy traps while pretending to know how to code in Python"
Can you show real code using this patterns and not examples, it seems all of this stuff works only in pseudo vacuum and in real world applications just creating mess of abstractions that slowdown, performance, readability, and TIME TO LEARN everyone to stay on one the same page)
Before Java. Wow. I remember those days. LMAO!
even before then, C was super useful, widely used, and stuff written in it still works perfect today. If you narrowly missed the C era and were in the hellscape that is c++, dang that sucks. Java is no better - a 'hello world' webserver in java is 43 lines, while in JS it's 3 and in C probably around 6-10.
@@willtheoct C is one of those things I was referring to. :)
Not exactly, if you had enough experience you'd understand that.
Design patterns are a thing of OOP, OOP is so bad that requires special techniques to achieve what it could be previously done with pure imperative or pure functional programming
wait..... do you seriously take 'design patterns' as anything but a sad joke?
All languages have functions. What kind of question is this!!
Neither Java nor C# has functions.