As someone who falls into very easy trappings to be elegant and descriptive in my code, this video is a must revisit to remember what matters is keeping it simple, instead of using fancy coding paradigms. Classes are fun to play with, but I am increasingly convinced for most tasks, especially in regards to computation and data science, it is better to use them sparingly
Take aways from this talk and the comment section (note: I am including several quotes from the Zen of Python and PEP 8). 1. Classes are useful, but foolish consistency is the hobgoblin of simple minds. 2. Simple is better than complex, complex is better than complicated. 3. Practicality beats purity 4. When the tools you have already work: use and adapt them for your use-case. Don't reinvent the wheel with a class every time you happen upon a new problem. 5. People will miss the message because their beliefs and tools are attacked.
@@oysteinsoreide4323 Yes, but the unnecessary verbosity of (e.g.) The MuffinMail example in Jack's talk is far from readable. Whereas, his reduced version is both readable and quickly understandable.
I think the take away here is simply that very often people tend to overdo some code steps systematically just because they learned that this was "the proper way" whereas it might actually just be making the code complicated and large uselessly. This guy isn't the first I see to make the point that this whole deal of making your code super complex for the pretended sake of future flexibility and time saving is a bunch of garbage and typically just ends up eating more time than it saves. I think there's truth to this. Also you gotta remember that everytime you complexify one of your APIs you're making the learning process longer for any new employee in your organization. I think over the years there's been a dogmatic approach that's built up in OOP and not always for the better.
The key takeaway for me is: Don't foolishly design everything as classes. Functional programming is way more efficient to read, write and test. Only use classes if you need complex objects.
I agree with a lot of this, but not at all the exceptions part. I like it when 3rd party libraries define their own exceptions. It makes it much easier for me to figure out the cause of the error.
Edit: three years on, I don't think my comment here is correct at all. It might read convincingly but I didn't know what I was talking about. I wrote garbage code because of this mentality. Someone in the replies said I was conflating abstraction and good naming, and that's exactly right. --- This presentation is an attempt by someone who has a good point to overstretch that point way beyond reason. His game of life rework is very confusing (19:48). I have no idea what it's actually doing. I don't know how the game of life works, so I can't look at it with the luxury of already knowing what it does. I have to read it line by line and hold all kinds of information in my head at once to understand it. One of his lines has 4 steps' worth of nested function calls. Wtf? That's not simple code. If he abstracted those steps into individual logical leaps, each contained in a function with a _descriptive_ name, it would be so much easier to read. And, when you have a bunch of functions that depend on one another... You guessed it. You should put it in a class. He's using the complete wrong metric to judge whether classes are good or not. Classes allow you to compartmentalise a problem. If it assists you in compartmentalising the problem, *it's good*. If it makes the problem more complicated, *it's bad.* That's it. Obviously, the MuffinHash example is bad, but the reason has nothing to do with whether they used classes. The reason is that those classes make it _more difficult_ to conceptualise the solution.
I don't know why you find his Game Of Life code confusing. It took me 20 seconds to read and understand it. I assume you just aren't used to functional programming paradigm. But it is not his fault. With practice you can read it as easily as 100% imperative code. I find that I can read his code as a book: read it line by line, never look back. It is very easy and pleasant to read. And if he had 5-10 functions/classes it would take me longer to read and understand it, having to jump from one place to another. My only problem with his code is it's performance (obviously, I hope). But in exchange for this ineffectiveness you get GOOD readability and development speed. P.S.: If i wanted speed, I'd use C.
The _point_ of an abstraction is to allow you to understand the solution without understanding the lowest level of detail. You can still delve into it if you want to. Being able to paper over your ignorance is a _good_ thing. Programs that force you to understand the entire program just so you can understand a part of the program are bad programs.
I don't know python, but I was able to read and understand what that code does. The only part that was hard to understand was `board | set(itertools.chain(*map(neighbors, board)))`. But that's fixable, just add an extra local variable, and it'll become easy to read. And probably one more variable for `(neigh in board) for neigh in neighbors(point)`. > You want to code quickly and with minimal abstraction, I want to code in a way that's easier to maintain Eeh, I don't see a collision here. Minimal abstraction = easier to maintain.
Over-compartmentalization and over-abstraction is a sin to be avoided. I would not want to maintain your code. It's probably about 10 times more verbose than needed, inefficient, hard to read and therefore buggy. Smaller and simpler is better. The problem with OOP is that everybody thinks *their* problem is so *special* and needs special classes. Not so. Do us all a favor and use as few classes, methods, functions and lines of code as will get the job done.
Hmm, this guy has some good points. 1: Mostly no point in abstract base classes in duck-typed languages. 2: No point in making function objects (functors) when there is no interface concept. 3: Less code is mostly better, but only if it is simpler. 4: Preparing the code for the future is ok, if it requires minimal effort. Otherwise it is pointless. 5: Namespaces should not be abused. But they are helpful sometimes, for organization purposes. In auto-completion lists they are crucial.
"Code is read more times than it is written", and in production environments the programmer is not the one reading it. This quote, thanks to whoever said it first, is the first principle for whether to use classes or not. Whatever makes the code more readable and therefore maintainable should be used.
Not an expert by any means (self-taught), but for most cases where I've been tempted to innovate something fancy, I just start by typing out what I want the user of my code to be able to type as instructions. Work my way backwards from there and figure out the "how" of the implementation as long as I already know the "what". I have used classes so far to help me conceal non-user methods (implementation hiding I guess; less options for users means easier learning curve and Python doesn't appear to have access modifiers as an alternative option). Has also helped with the purpose of some abstractions too.
Keeping it simple is why Python is so appealing to me. Life is easier when you don't have to wade through 1000s of lines of boilerplate and code-bloat.
Yes, but you can also write code without boilerplate and bloat in C++. Python however makes writting, debugging and maintaining any reasonably complex project near impossible. It turns out types and identifiers make things easier, not harder, in the long run. The easier it is to write wrong code that still compiles and executes, the much harder it gets to write nontrivial programs.
Adding "Exception" to the name of an Exception does help. It helps if you're facing a library that has numerous exceptions and you just want to search for those. You could open the type hierarchy, but you could also just search for the type name, like "*Exception" and it will list you all of them. Programming is not just typing, it's also searching.
A curious thing about this presentation (though it is an old one), is that what actually happens when some java/c# programmer accidentally starts writing in python/ruby scripting language.
@@harrypadarri6349 in Ruby everything is an object. In python you can get alot done with just imperative. It doesn't lean on the OO style anywhere near as much as C# and Java. Most Python dependencies are very OO though. I once tried to write functional Python code. It didn't go well.
@whossname You’re right with that. Python has so many built in datastructures and additional libaries that you can write pretty nice code that appears to be imperative. I once wrote a programm that did use only one single self-written class in over ten thousand lines of code. I am not talking about style but the inner workings of python. There everything is an object. Including functions used for functional programming. Unlike C where variables just point to a place in memory where a value is stored. In my CS lectures professors meant that distinction when saying „everything is an object“.
No? I've done Java and C# for forever and my first time with Python I just ran code directly without any classes. Just because I'm very used to it doesn't mean I can only code in classes
You, every time I turn around someone sais the contrary of I was told before. "Divide and conquer to solve your problems and make your program as easy to mantain as possible", then "Don't overuse classes, they reduce eficiency and stuff".....
"I hate code and I want as little of it as possible in our product" - Jack Diederich "We usually think of code as an ASSET, a valuable thing that we shouldn't delete. Code is a LIABILITY - all code is cost " - Dan North
I don't tend to enjoy tech conference talks, but I've watched this one several times. I'd guess most of us have encountered many different arguments for simplicity in software design, but I really enjoy this one in particular for some reason
I love what he's saying.. but when I go out for a programming interviews 99% of the time... they want me to write things as classes to solve the given coding test. No matter how inappropriate it would be to the test.
This is an indication that you are interviewing with a company that doesn't share your values (and lacks common sense). Filtering out bad employers is a great outcome for interviews.
That's how you know where not to work. Classes create bloat in terms of code complexity, execution time, and computer memory. Everytime a class is written, make sure you have a good reason for it.
His message was not to stop using classes but stop using classes for simple things. Lot of people misunderstood. Classes are useful when they are needed but too much of class objects with bigger code makes it slower. No Offense.
@@cwill6491 the things is lot of people are here fighting against each other one who likes classes and one who don't and some python haters! I don't know why this people just learn something new and appreciate it instead of fighting over each other. Why hating python in comments btw? What you think about this brother.
@@lordtejas9659 python breaks a lot of conventions. For example, declaring a variable globally doesn't necessarily make it global. You have to use the keyword global in every scope you want to use it in. Some people might not like stuff like that. If you can put that aside though, python is so useful. You can ignore many programming issues and get a prototype working quickly.
@@cwill6491 well I never got an issue with local and global in python. I have coded more than 100k lines in both python and C++ within this years. I use C/C++ as well as Python. What I was saying that to stop people for fighting over stupid things like they are tools and people misunderstood the message of the video. But this students from IT and freshers don't understand the basic concepts of Programming and starts fighting. If C++ was good for prototyping then why we even needed python in first place..thanks for your opinion friend. Have a nice day. Hope this message stops this new kids from fighting. It feels like civil war.
@@biskitpagladata classes are a shame in the world of OOP. They break encapsulation, introduce mutable state and result in functionality being spread across the codebase. Burn it with fire.
@@МаксимГорюнов-м7и Spaghetti code is when you see a simple function call, but actually it is a dynamic dispatch over an inheritance hierarchy. Spaghetti code is when numerous layers of indirection are pretending to be "simple" linear code. OOP is spaghetti code.
I don't know. I feel Exceptions are the exception (hehe). Having a Stacktrace where the first word already tells me what is the problem. Having an UpdateException(MyModuleException), DownloadFailedException(UpdateException), and InstallFailedException(UpdateException) giving me the alternative of what to try/except is quite important. Or let's say it otherwise. I simply don't know how I would do that exception handling stuff without all the subclassing.
The important lesson. Do not creat abstractions "just in case". It is easy to add them in the future if needed. Keep it as simple as possible. No wrappers. No custom base classes. Things like debugging and tracing can be solved other ways.
Maybe it comes from the C/C++/Java days where it was hard to patch things in when you needed them. No new means no need for factory methods, properties means no need for getters/setters, closures can be upgraded to objects with __call__, optional arguments, no difference between classes, objects, or modules, duck typing means no need to rewrite your code when you change your class hierarchy, classes/objects/modules can be swapped around, dynamic typing works sort of like duck typing and mypy's errors can be ignored..., iterators is the default, you can add data to classes, decorators, context managers changing globals, __getattr__... However, Common Lisp is even more hardcore than Python in that you could always use something like JQuery on your s-expressions to refactor it, optional return values and you could locally change progn, let, defun, etc... and turn functions into macros that alter the expression trees of their arguments...
I agree to a certain extend but we did not mention was the fact that Classes have a fundamental task of making Business Logic look readable and easy to implement for less technical people, often functional administrators.
22:33 I think this guy has a point with regards to implementation hiding. If you use a plain old dictionary everywhere in your code, but then later on realize you actually need some other data structure instead of a dict, you're going to have to change a hell of a lot of code. If you hid what data structure you were actually using behind some interface, then you can swap it out easily, only changing the code in 1 place. Is there a way to do that without interfaces/classes?
@@trampflips101 There is another way (and it is probably older than interfaces and classes). The translation units! In C you can easily hide data structure you use just by not defining it in header and defining it in source file. The same goes with functions that deal with that data structure. Make them small (their only purpose should be to deal with the data structure) and static (so they are hidden), and whenever you need a different data structure replace them with new functions working for the new data structure. Or make your project modular and that data structure and its "methods" as just another module - you can still replace that module any time you want, but it will not be hidden that way Just ask yourself if it needs to be hidden, if yes then you have the first solution, if no - probably the latter one is better The first solution is the best when the data structure is so small and easy to implement that creating another module is an overkill
Did I just watch 25 minutes of talking that can be compressed to the two sentences: "Think before you write" and "Look at the standard library to see how a language was intended to be written"?
most programmers don't use too many ideas from functional programming or aren't well acquainted with it. since he's using a few fp functions in the main function, so the code seems barely readable, but if you look closely it's actually quite okay. implementing it with classes would just slow down the code considerably while not adding anything useful.
I goda disagree with what he was saying at 4:30, information hiding, encapsulation, seperation of concerns, etc are very important, and it is extremely difficult to make easy to understand, maintainable software without them.. However, what he says about speculative design is very true.
No, information hiding makes code unmaintainable. What makes code maintainable is readability and clarity, first and foremost. Obfuscating simple code behind layers of classes makes code a maintainability nightmare.
When including an external library that has a bad or illogical interface, encapsulating it (facade pattern) lets you hide the bad parts and ensure that your team only uses it right - it can also allow you to add correct logging, error handling, etc. to code you can’t refactor because it’s third party
Separation of concerns: actually usually creates simpler more readable and more reusable code with fewer side effects; I find that when this comes up in real life it’s usually not because someone is trying to pull a fast one, but rather because a more junior dev is doing something like putting API input validation logic into a DB stored procedure where it can’t be reused.
Of course you should always be wary of premature optimization and overengineering, but this guy sounds like a lazy/semi-skilled dev who never found that balance. He elevates simplicity before all else and throws out decoupling, encapsulation with the bathwater when there are very good reasons why those are best practices
Classes have there place in programming as the questioner in 23-25 minute indicated but I do agree that many programmers do overkill. Helper functions can just be functions instead of a class with loads of static functions.
I think at least part of it is because so many people learn Java as their first programming language. Python has classes and objects as a feature but they're used to programming in a language which is built on classes and objects from top to bottom.
4:25 -- never had to use "decoupling" since graduating? That's on you, presenter. When coding in a large codebase you really need to be careful about decoupling if you want your code to be reusable ever again; do you want your code to be reusable? Don't answer that. Also, coupling is the single worst root of creating what we all know and dread as legacy shit that nobody can untangle and refactor. If it's bad but decoupled, then it's really easy to refactor 20 years later, or even to replace with an external future-modern component. If it's coupled, you are basically fucking 50 other guys down the line single handedly.
Although in the game of life he has reduced the number of lines, I don't think it necessarily made the code easier to understand. It's easier to reason about cells in a board than reason about an "advance" function. Adding more possible cell types would already make this advance function too complicated. Anyways, I got the idea of the talk, always good to keep in mind that Python is not Java and that not everything must be a class
I have seen Game of Life's with different rulesets aka advance functions, but I have never seen one with different cell types. Don't generalize, if you don't know for sure, that you'll need it tomorrow.
His point at 5:55 or so was great. If you know for a fact that you will need to use something later, then of course writing a class may be useful. But if you don't have any reason to need it later right now then don't try to plan for a 100k line project that will probably only ever be 1k lines max
GogL0L C++ doesn’t force you to do anything, that’s half the problem collaborating with it. I don’t do OO. I do data oriented design, which C++ is great at.
But idiomatic Python code is different from idiomatic C++. When working in a "data oriented" fashion (in Java or Python), I tend to only use build-in types and write classes only when necessary. All those terms are pretty much related to C++, Java [,...], or C# styles of OOP, as you get pretty much no coupling at all when you use to build-in types and write classes only when necessary.
You write code for people to read, not for computers to save space. I'd rather have 10 times as many lines of code that I understand instantly, then one tenth that I need to ponder for hours about until I get all the edge cases
@@Amine-gz7gq Seriosly? How is it crap? Objectivly or subjectivly? Is is the comment itself that you think is crap or is it the information it is trying to convey?
That glider code and his admission that he hasn't had a single discussion about decoupled and cohesive system design with another engineer in >15 years pretty much tells me everything I need to know.
@Michael David lol. You're an idiot. You're making a big deal out of nothing. Okay, "recalc" isn't a perfect name. So what? Any idiot can still see what it means and what data it holds: it's the set of all points that need checking to see if they're alive in the next state (or all the points that need to be "recalculated"). Also, I've seen professional code with much worse variable names, so your assertions about "any second year comp sci student" are full of crap anyway.
I've been using dataclasses quite a bit recently. I like them better than dictionaries when I need mutable named tuples or want to define data schemas. The typing library and typehints work nicely them as well. I wonder what Jack's opinion would be about using a dataclass when you could have used a dict or a tuple?
@@williamkmanire His talk is more about unnecessary use of classes as pure method holders. I doubt he'd object to a data class that defines a record or otherwise combines multiple related pieces of information. That said, I find I almost never need those classes to be mutable. Allowing them to be mutated usually makes the code more difficult to reason about (especially if you're stuffing intermediate values into its attributes), and avoiding that is usually a simple matter of doing any computation using local variables or another function before calling the constructor. (The dataclasses module has replace for if you actually need to change values for some reason.)
Code in C. If you feel the urge to create an unnecessary class it will be a little more difficult and this will give you more time to come to your senses.
@@eecarres That's true but since "neighbors" is used exactly once, you can add a skip clause (if dx==dy==0: continue) in the body of the loop and the whole thing would still be simpler.
@@dionbridger5944 It's used twice: once in generating all the points to recalc and once in the live neighbor counting. I like the fact his solution avoids invoking an if condition on every loop.
@@BladeOfLight16 18 evaluations of a signed int equality test is computationally speaking, nothing, unless maybe you are running your program on a clockwork Babbage engine. Even for a million iterations, it comes to 18 million operations, which on a puny 18 mhz CPU is a total of 1 seconds worth of CPU time.
BTW you can get away with a succinct 2 line function without any equality test: for i in range(8): yield x+[-1,1,0][(i//3)], y+[-1,1,0][(i%3)] And the fact that the "function" is only 2 lines means you can probably get away with not having it be a function at all ( depending on where it's called from ) and just in-lining those 2 lines. So not only do you save on the if-clause, but you spare your Babbage engine the cost of doing a jump operation too ;)
It is ridiculous how far fetched this is. He gives examples of bad code and says why you shouldnt use classes for something they are not meant for. Yeah, no shit...
Yea I don't think this guys as smart as he thinks he is. He advocates useing global variables to store URLS and API keys. Apparently we've been doing it wrong the whole time by writing a config file reader function and using that to populate the parameters of the __init__ constructure of a rest API client class. I don't know how much more of this I can stomach.
Except this is exactly how people use them in the wild. And people coming from languages like Java or C# are convinced that _everything_ should be a class because they don't even have a concept of things like functools.partial or having late binding for non-class methods. This is all really great advice.
@serpathius The fact that you think OOP is somehow more powerful than any of the techniques he discusses (comparing it to airplanes vs. cars) is exactly why he's talking about all this. OOP is not more powerful. It does not do more. It does not scale better. It's mostly only necessary as a kludge around the fact that OOP languages don't support late binding of methods that aren't bound to an instance (static methods).
@serpathius ..... I literally explained that in parentheses right in the sentence you're asking about. Did you bother to read the message? You claimed that OOP compares to other approaches in the same way airplanes compare to cars. That is clearly claiming that OOP is more powerful.
Very useful message. Scala is probably one of the best languages to strive for the balance the author suggests between classes and functions. Python is moving that way, but it lacks the type safety. Very interesting and actually useful for every day work with python. Thanks!
Class Flow may be empty, but there's at least two reasons I can think of to keep it: 1) You want a way to test an object to see if it is a "Flow" (via isinsance, for example) 2) You want to allow the users of your code to subclass it and implement their own Flow class. Mr. Diederich doesn't seem to give the "benefit of the doubt", or even attempt to see why the code was written this way. The first audience question hinted at that, but the speaker never gave a real answer.
Classes are great but they are also overused. This talk describes examples of class overuse taken from real world code and refactor the unnecessary classes, exceptions, and modules out of them.
The majority of this errors, of the code is shown, is not about Classes, is not about OOP. Is about bad refactoring or not refactoring AT ALL. Dont stop writing Classes, just think, write and refactor!
I find it amusing that my first impressions of what this guy had to say were completely off. I thought he was completely against classes in code, but what he was really speaking out against was a flagrant misuse of them that I hadn't even been aware existed.
This is more of a "Know Your Standard Libraries and Use Them" video. That is probably how he did the first "amazing" code side reductions. Also my heapq module does not have pushleft and popleft methods in his heapq, plus I think there's a bug in his popleft method if the user did not define a key function. (He passes the second element of a tuple which is only created if there is a defined function). I guess the main thing I agree with him on is I hate typing long identifiers...
If the user fails to define a key function, the key function defaults to 'lambda x: None'. It's right in the __init__ argument list. So there is no way to get into the guts of the class without having a key function of some sort defined.
Python had functions before it had classes. This is a Good Thing, because it means functions are powerful, first-class objects. Take advantage of this. Use them in conjunction with classes, by all means.
That is one of the best seminars on programming I have heard in years: you should travel the United States and give seminars on programming: How To and How Not To.
Object Oriented is not meant to write less code, but a maintainable one. I can replace 5 classes and 500 LOC with 5 lines compressed in a python function, yes. But that will be completely unreadable. Examples presented here are extreme and doesn't help to support the topic, which has got sense in some cases.
+D. Nappo the code on his site/examples, are impenetrable automatically use the philosophy / design of the community/toolset - make it work. Don't walk away with your own. This person is not an authority. He appears to have presentation, but who is he? What is this?
Then why does OO produce things that look like Enterprise Fizz Buzz? No. OO (as it is actually used in practice, which is perhaps not what it's supposed to be in theory) is a way of trying to build code off rules and platitudes instead of off common sense. Anyone can grok 5 lines of code more easily than 500 lines of code. This should not be controversial. Sure, you might have to stare at it a few minutes, but it's gonna take me time to walk with 500 lines of code, too. In fact, it'll take more, and it will be much harder for me to see how the different pieces are supposed to work together.
Of course. I'm a big "fan" of C and Assembly since I come from an embedded background and only recently have I started getting into C#. Considering what I know until now, and it's not a lot, I can really see the usefulness of classes if you want structured code.
"Sure, you might have to stare at it a few minutes, but it's gonna take me time to walk with 500 lines of code, too." If the 500 lines of code are well written and properly abstracted, you don't even need to read the majority of them in the first place. Looking for an error? With the right decoupling and abstraction, you can easily narrow down the class and even method responsible for it. Looking to modify some of the functionality? Find the spot in the code that relates to what you're actually modifying and have at it.
You obviously have no experience maintaining code. Yes, you're going to have to read a *lot* of code before you find the one line that is miscoded, assuming that it's only one line that's in error. Often its conflicting assumptions made in different places in the code. Always, the more code there is, the worse it is to maintain. Never prefer 500 lines of code to 5. That's completely idiotic. Yes, you dearly hope that it's been factored appropriately. But that never means adding unnecessary classes and exceptions. Verbosity is the primary enemy of maintainability in OOP code.
this guy has a point, even if at first he sounded like weird. In my time, I had to suffer tracing unnecessary class abstractions in C++ made by some kid (the management thought was a superstar) and now left for singapore. And when i looked and followed thru his abstractions, i began to realize that this OOP thing along with its power to create artificial abstractions is rearing a generation of ignorant developers later building on top of these abstractions. The BSD socket beauties and tcp/ip headers are hidden and instead exposing some get/set methods. It is true, that abstractions are powerful tools, but if you are not careful it can also lead to ignorance and decadence. To me, the first thing is the electrons and their properties of producing boolean logic. If you are aware at this level, then you will fear the days ahead when quantum computing comes. This is then followed on by protocols, and then the core libraries. It was from that experience that I started to move away from C++...
But, this guy also has some silly points: 1: His Web API is simple, but it doesn't tell the coder what verbs/nouns exist. This requires looking a documentation instead of using auto-completion lists. 2. All of the "words he hasn't used in 15 years" allow for using 3rd party modules a lot simpler and quicker for most devs. 3. His implementation of the Game of Life is very clever, but it will be a maintainence nightmare as it just seems obfuscated, and changing certain parts of it will suck.
"His implementation of the Game of Life is very clever, but it will be a maintainence nightmare as it just seems obfuscated, and changing certain parts of it will suck." Quite the opposite. Its brevity and clarity are the very things that _produce_ maintainability. If your code is bloated, it will be hard to figure out. You could make a case that an extra `Coordinate` named tuple class would make it slightly more intuitive, but beyond that, no introduction of classes would improve this implementation. A couple of additional functions just to name certain pieces might be a small improvement, but the underlying style and approach are the pieces you should draw out from it. Namely, using the existing, conventional tools for the problem and keeping the code simple are always massive wins. And this is why your point 2 is also wrong. Those concepts _do not_ help you write better code. They are, at best, ex post facto descriptions of the final product. You cannot write code that achieves those ideals by trying to think about them. You must think in terms of simplifying your code with meaningful abstractions to achieve all those qualities, and that is precisely the mindset for which he is advocating. Don't worry about those lofty, ivory tower academic principles. Just worry about writing simple, easy to figure out code that uses the standard approaches to your common problems. (And most of your problems are common.) As for point 1, I'll admit that's a disadvantage, but that doesn't necessitate a ton of classes. At most, it warrants a method per operation.
@@BladeOfLight16 The point is that abstractions are meant to simplify things for us humans, they are easier for us to grasp and reason about. A Cell and a Board are something we understand, the behavior of the game is way easier to grasp written explicitly and clearly as OO code. You can think of the smaller parts separately, understand them, and then see the game logic implemented in its own class/function. The cognitive load is lower, and testability is improved in such small pieces of code as well. Look at this monstrosity: ```recalc = board | set(itertools.chain(*map(neighbors, board))``` A lot is happening here, in this single line. What is recalc eventually? How does it compare to board? Or to newstate? How do you modify the rules of the game? The number of neighbours to keep you alive or to kill you? Does the code here require change in such cases? Moreover, this code requires you to stop and think when reading kt, to try to imagine what it does, to execute it in your mind. Understanding is not instantaneous, even if you originally wrote it. This makes going over this code more difficult, compared to more explicit, well divided OO code. The OO code can be maintained by fairly junior developers. The functional code is way harder for most developers, especially ones that are not engineers. I prefer simplicity, less magic, less premature optimization. I will optimize when I see it is required, but in general I will always prefer saving developer time over execution time.
@@advance512 OO doesn't provide that clarity. The task objects are good at is enforcing constraints on state, and there's nothing like that to do here. OO seeks to make behaviors subservient to data, but programming is primarily an art of specifying the sequence of computations to arrive at a solution. Good programming makes data subservient to the behavior. Clarity comes from grouping those steps in a coherent way that properly emphasizes the mental model (the reasoning) that leads the programmer to choose the steps that he does. recalc = board | set(itertools.chain(*map(neighbors, board)) is a simple 5 step computation: 1. map: executes the neighbors function against each element of board. 2. *: Expand the iterable into an argument list (This could be avoided by using chain.from_iterable, if we wanted.) 3. chain: concatenate the iterables of the neighbors together into a single iterable 4. set: Eliminate duplications 5: board |: Union the resulting points with the neighbor points So this is just all the points on the board and their neighbors, and the "recalc" name tells us this is all the points that need to be checked for inclusion in the next round. Sure, it's kind of dense, but it takes about 2 minutes to figure that out. Worst case, you could factor it out into a named function to communicate its intended purpose a little more directly. There's no way OO could improve on this line of code.
@@BladeOfLight16 Strongly disagree that the single line is simpler to understand, reason about and modify/maintain compared to: ``` for (x, y), cell in self.cells.items(): if len(cell.neighbors) > 3: cell.next = False ``` and I doubt most programmers will agree with your claim. And this is for a tiny code base. Imagine how terrible it can get with many such instances, that do several massive operations in a single line of code. Way less readable. I think both OO and functional can shine in various situations. In my opinion, the example we have here is a good one where OO is indeed preferable. Another issue is soft type safety - type hints. The functional implementation of CGoL uses a dict as the board, which is passed into a function. There is no type safety of any kind here, compared to using classes with methods to contain state, or at least - dataclasses with functions that have type hints. Type hints are great and prevent tons of bugs. So, another reason to not go with his implementation.
@@advance512 The fundamental complexity of a program does not come from single lines of code. It comes from _how different parts of code interact._ OO strongly favors vastly more complex and more difficult to discover relationships between different portions of code than procedural or functional code, which are geared toward making the execution sequence and call stack obvious. That isn't surprising because, as a I said, OO takes the focus away from execution and tries to put it on taxonomies. This makes OO heavy code a complete nightmare to decipher. The fact that many programmers fail to recognize this does not make it any less true. Furthermore, using bog standard, conventional data types and library functions makes it vastly easier to decipher any single line of code as compared to using custom objects. In your example, I have no idea what the data types of self, cells, or neighbors even are, much less how they or their functions behave. I have no idea what effect setting cell.next has on execution later. (Does the cell get removed? Does it prevent printing? I don't know.) This all means I need to study a much broader portion of the code base to figure any of it out. By comparison, every single portion of Jack's line consists entirely of data types and functions I am intimately familiar with, and the function does not modify any nonlocal state. This makes understanding it a much simpler task. I already understand the behavior of the data types involved, and I know that any later effects on execution will be found _in the caller_ where the returned value gets used, rather than divided between different sections of code.
If the languages i coded in (primarily, C#, Javascript and TypeScript) implemented classes, scope and lambdas as poorly as Python, I wouldn’t want to use them either. i don’t mean that to be snarky, Python just has a really poor implementation of these concepts. Having to have self as the first argument to your methods is one of several things that make classes in Python so convoluted and why people come to the conclusions that this guy did. Pre-ES6 javascript’s prototypes and such made OOP more trouble than it was worth too. Opinions like this (which are still alive and well in 2018) make me think the Python community has had its head in the sand for the last 15 years and hasn’t seen how much cleaner the syntax could be in Python with a little syntactic sugar. The speaker reminds me of myself back in 1989 arguing with a friend about how much simpler and better Amiga BASIC was than C and C++. I just didn’t understand why someone would need all that complexity of multiple files and such. I get that the point of this was to remind everyone to keep things simple and don’t over-architect. I completely agree.
Well said. People rave about Python and that it's the best thing since sliced bread (as the saying goes). Next year. no doubt, it will be some other language that becomes flavour of the month. Sure Python has it's uses but it's not the be all and end all of computer languages. I've not seen anything done in Python that can't be done elsewhere, and sometimes better. Less code is not necessarily a good thing, especially when the original code is so difficult to comprehend. Finally, the thing I didn't like what his constant sniggering at what he considered bad code. That's HIS opinion not mine. I for having programmed many languages over the years and translating code from one language to another would much prefer code that was readable and not the reduced and difficult to understand concept he came up with.
I still don't understand why you need all that complexity of multiple header files etc. I have wondered since 1986, when I saw my first C-program. I worked as an Assembly, Pascal, Simula, PL/M and Modula programmer when the printer at my room suddenly goes crasy with those peculiar two character combinations (== && | | ++ [ ] () **) all over the place.
The only complaint you can think of is having "self" as the first parameter? That's so trivial. That's like complaining about semicolons or curly braces. If you think javascript has a better implementation of classes than python I seriously question how much time you have spent with either language. Any syntactic sugar that eliminates "self" in method signatures would also severely restrict the use decorators and metaclasses. Self is necessary because python is dynamically typed; it is not practical to specify a receiver type like in Go or Kotlin. > had its head in the sand for the last 15 years This is ironic since object oriented programming is on the decline. Is your head in the sand? It will take a long time to transition our enterprise infrastructure, including multiple generations of indoctrinated engineers who are incapable of thinking outside the object, but it's just a matter of time until OOP is history.
@@megamaser OOP history? I'm not personally very fond of it, especially not as the religion it has been since 1995. But why not use it where it makes sense? I mean things like GUI interfaces, that quite natually fits that model, or the contexts for which it was invented, i.e. simulation. (The language Simula, in the 60s.)
@Adithya R The latest versions of JavaScript (ES6) has a much improved OOP syntax as compared to the primitive OOP features we have had to struggle with in the past. If you have not seen JS lately, it's worth look at some videos on JS ES6 OOP programming.
“If implementation is hard to explain then it may be good” Reminds me of pthread vs c++ thread. It is easy to implement in c++ but unless you program in pthread, various multithreading problems, you will not learn the conceptual ideas related to it. It’s about whether you are becoming code money for corporations or actually becoming a good programmer.
That’s both because a lot of errors are at compile time and raising exceptions is slow when compared to error codes. If it wasn’t that raising exceptions is (comparatively) slow I’m sure there’d be a lot more.
damn... still or even more relevant these days after 10 years. No fancy words, straightforward. Great honor to have good people on python in the past although today many went to other lang and communities.
This is like complaining about the .NET framework being too big because all you use is a string in your hello world application. I am positive that the initial API had features that you were not using, so after extracting out the only function you wanted, you tossed the rest saying it was code bloat....
I advocate for good design and structure, but also I strongly agree with not over design, one should plan for the future but not invest too much effort on it. for example I'll model this as a class because it has a good chance to be overload or subclassed, but I'm not creating the whole inheritance structure.
Right, there is a nice quote (I think of the French Voltaire): "A book isn't finished when you can't _add_ any more words, but when you can't _remove_ any more."
I disagree with the idea that that small, simple classes are a bad idea. I find the greatest thing about classes is that it allows one to carefully control state much better than without classes. Functional programming is correct when it says that state causes many bugs, yet I find that classes are much more effective at controlling and isolating state (at least if you try to avoid abusing them. In particular, I intensely disagree with your dismissal of classes with only one or two state variables. I find that those classes are usually the best written since they manage state very carefully and are the most focused in what they do rather than trying to provide everything and turn into a god class.
@@masynchin Yeah, but in Python everything is an object so you don't need to write class to make objects you can use dictionaries, function decorators, or closures (lambda and def...nonlocal is nice at this).
It all comes down to using your judgement to arrive at a balance between all the tools and concepts that are available to you. I didn't like his implementation of Conway's game of life because I prefer code that I can read and understand at a glance. Based on my interpretation of the Zen of Python (and equivalent ideals in other languages) his approach is difficult to understand.
You need to learn to read code better if you think that game of life was hard to read. It was dead simple. Far simpler than having to refer to multiple classes and methods which continue on for pages and pages.
+Kaleb Sagehorn Your complaint is invalid because this is information you need before you can even start implementing. If you don't know the requirements of the software, you should learn about those before trying to mess with the implementation.
+Danny C "Code" is an uncountable noun. "Codes" (when referring to code in the programming sense) is incorrect grammar. Yes, this is a pet peeve of mine. Also, you can't read any code when there's no code to read and you're developing a product from scratch. So anyone implementing something new instead of maintaining an existing code base. Understanding your actual requirements is not a luxury. It's a necessity to avoid building the wrong thing. Building code without doing so is sheer and utter incompetence. Sure, for a less defined problem, you'll flush out some parts of requirements as you go; even then, you darn well better have _some_ idea what they are up front. But GOL is not that. We're dealing with a very small, very well known, well documented, not that hard to figure out problem. There is literally no excuse for not looking into it before trying to implement it or understand an implementation of it. We don't need an Enterprise Fizz Buzz here. Also, "real software engineers" do a lot of stupid things and produce a lot of unmaintainable, overly complex code. Ever read Daily Worse than Failure? Anyway, simplicity is golden. Over complicating the system does not help you or anyone else.
Maybe I am wrong, but he does not seem to have a vast experience in programming complex systems. When you develop a library you want to establish some interfaces. You may also want your code to allow for changing behavior for many different reasons - one is for injecting mock-up implementations. You can do that using classes. What if you care about specific types of exceptions and do not want to rely only on exception's messages, but on their actual types? You derive your own exceptions and watch out for them specifically (this is what one of the people from the audience mentioned). What he said applies mainly to some small applications development, which you may not want to extend much in future. Or maybe I have been in OO world just for too long..;)
I agree, he's playing fast and loose with his code. It's not too bad since he has a small product in a small company, but if it was a big system I'd be very skeptical about the product.
***** size isn't what I was saying matters, I just said on a small scale you can easily manage it, but on a large scale I doubt it would be as reliable.
I agree many design patterns were just used to justify solving a difficult problem in an ugly way and get away with it. ;) But nowadays, C++, C# and Java(Script) support many functional concepts (like map/reduce/anonymous functions etc.) and have been adapting syntactic sugar concepts from everywhere (for example string interpolation). In my opinion, these functional extensions combined with dependency injection lead to that the only right way to write OO code today is to have classes wich are 'services' (functions) and objects that contain state. 'services' use dependency injection and aggregation (i.e. no inheritance), state objects can still use inheritance if it makes sense. Imho, this produces very maintainable, testable, decoupled (mockable) code which is what you need in large scale systems.
"...one is for injecting mock-up implementations. You can do that using classes." In Python, you can do it without classes, too. Look into how its mock library works; it patches anything bound to a name (modules, classes, methods) with a dummy before the test starts and then restores them at the end of the test. All name references are late bound in Python, even functions not attached to a class. C# and Java don't support late binding of non-instance methods. This is one of the very few valid reasons to use classes pervasively in languages like them. But then using classes pervasively comes at a cost, namely now you have the new problem of instantiating all those instances. Python avoids that cost by providing the late binding directly. It is true that his advice is not completely applicable outside of Python, but this, in my opinion, reflects badly on the language design rather than his advice. "You derive your own exceptions and watch out for them specifically (this is what one of the people from the audience mentioned)." Jack isn't objecting to that. That's a case where you need exceptions. If you want to catch an error only in a specific case, then you need a specific exception to indicate it. If you're not catching an exception explicitly anywhere, though, there's usually no reason to create a custom type for it. I agree he could have articulated this point better.
"It does the exact same thing with fewer lines" But 'fewer lines' is not a metric or goal that matters at all. Is it more readable or easier to maintain? Not necessarily. Does it execute quicker or with less resources? Not necessarily. Is it faster to write? Not necessarily.
Less lines of boilerplate is the point: boilerplate dilutes the code and when you look at it, it’s harder to comprehend. It’s the same thing with excessive vertical white space and silly “function start” comments that harken from COBOL days. There’s a big open source project, with proprietary roots, where the coding rule proudly states that all functions and methods must be preceded by a 4-line comment (at minimum), where said comment has two horizontal lines built out of “=“ characters, one line that repeats the name of the function, and the final line that states the purpose, and 95% of those lines regurgitate either the action implied by the name of the function, or describe the purpose such that it doesn’t add anything to what you read in the body of the function itself. Those 95% are out of a sample of a 1000, and I did do it carefully. Said project also has thousands of source files that declare or define short classes that are 5-10 lines long. It’s a C++ project and this is nonsense: entire subdirectories of “modules”, each with a multitude of files, could be often boiled down to a single header file, since the methods are either getters/setters or defaults. It’s nuts. And people claim that this is “discipline” - yeah, in self-flagellation. I have a general rule that source files shorter than 250-500 lines should be viewed with suspicion, as are sources over 2000 lines. Exceptions to those rules of thumb arise, but infrequently. Short files with nothing that boilerplate should be burninated with gusto, and the heads of the projects such files comprise viewed with suitable suspicion. Good comments should describe the purpose and must not regurgitate the obvious. Good classes introduce abstractions that are helpful, that improve the understanding. Having a base class just so that at some point in the future we may change the underlying container is silly. Never mind that the container may need to be changed only on a few derived classes - as might reasonably be expected with the mentioned descendants of the Flow class.
Actually, the fact that you have to create exceptions (most of the times) is because that would make it easier for documentation, when you have to create a document with all error cases with their respective error message, it is easier to create a package for exceptions only and have a custom exception for each error possible, also, OOP is on developer's option, Django framework (for example) is full of classes, and you actually follow MVC pattern which is an OOP pattern, and people still complain, I just don't see why, I mean, it's not everyone else's fault if your co-workers doesn't know when to write a class or not (or even how to do it properly), just saying..
No, history started in 2005. (Don't mention the structured and recursive Algol with nested scopes from 1960, or the object oriented Simula from 1967. That's the Jura age, after all.)
@@herrbonk3635 Well, the only answer possible here is a quote from Santayana's The Life or Reason: "Progress, far from consisting in change, depends on retentiveness. When change is absolute there remains no being to improve and no direction is set for possible improvement: and when experience is not retained, as among savages, infancy is perpetual. Those who cannot remember the past are condemned to repeat it."
Shit code is not an argument against using classes. It is an argument against shit code. It's nice to now and then be reminded to not write shitty code though. Thanks for the examples.
This is a great talk. Part of me died a little bit inside though when he says he wanted to use a URLShortener and in order to do so he had to go away and read 10K lines of code. He opens with the quote "don't do hard things in the first place" 🤷🏼♂ also, if he reads the 10K, does he have to read the code of whatever libs / dependency that is using et al?
the main problem in this industry is that we have less and less coders, and more and more scripters using others code. So basically, this isn t going to be any better.
On the plus side, most of the script kiddies stick to calling code rather than writing classes :P But we also have totally ridiculous things going on in the industry where something like PyTorch took years to get a stable C++ interface while having it for ages for Python (it is written in C++). Apparently ML people suck at real code so they putz about in Python while another group of programmers need to write the fast C++ code for them. And nonsense like how Julia goes around claiming super speed while pretty much all the code being run in Julia is calling C, C++, and Fortran. Being compiled, I'm sure Julia can be faster than Python, and maybe it could be faster in some edge cases (??), but they seem to pretend it is all Julia when anyone that looks at the actually packages in use finds things like the Sundials code for differential equation solving... etc... Hardly any Julia code is actually Julia code. It yet another glue language. We can argue about what sorts of glue languages are better than others, but maybe it is time we just stop serving things up for script kiddies and make C, C++, and Fortran 1st class programming languages again. That is, if you're writing a library in one of these, give it a stable interface to its own language before you do for the popular flavor of the day glue language. And document it for goodness sake. It's incredibly irritating to see how poor the PyTorch C++ documentation is compared with their Python documentation. And I'm picking on PyTorch a bit here, but at least they've made some progress, now having a stable C++ API. TensorFlow still doesn't, apparently because they did some stupid crap where it was mostly C++ but then they did the autograd Python or something... just really dumb nonsense.
@@zvxcvxcz can't agree more. Man itts everywhere. At least Apple got serious about swift and c++ but man. Everything else is just layers of nonsense. Take flutter for example. The whole framework runs 100 times slower than it should in c and has no state management.
@@zvxcvxcz and regarding ml. Once u get deep into it it's just some stats management using simple functions like sigmoids.i don't understand how come there's still almost nothing in c++ while everybody complains about ressources and performance
I see the idea as not optimizing your design beyond what is currently needed. You can make it a class later if you want to and you may often find that you never want to. So the problem is when you're trying to guess the future for some reason - trying to make an API that will account for all future needs.
Instead of making it for all needs, set it up in a way that it can change This message was lost along the way Or never discussed in the first place (ie university) or told its not important (agile and scrum consultants)
I'm not sure , but Python does NOT offer static classes, which are great way of ORGANIZING similar functions that do not require an instance. I look at the file where the residing function exist as static classes in Python. Classes are great for organize a common DATA STRUCTURE... To say to stop using classes is a bit extreme...
How does print glider, where glider looks like a 5x2 staggered array of ints, magically turn into circles in a moving grid (the advance function changes the contents of the array, not draw anything)? Unless print has been overridden with a custom screen rendering routine.
I was wondering how they were going to graph their raw data, too. Any suggestions? Anyone? Guess maybe i'll have to look at some other people's GOL programs to see how they like to graph things in Python. Maybe Turtle Graphics (my speed).
@@Kolyasisan Did you even watch the video? He tells that you shouldn't use classes when unneeded, there was only one piece where he shown good use of classes.
@@ishdx9374 exactly, and the title says "Stop Writing Classes" when in reality the talk is about not creating classes when unnecessary, when an obscene amount of them will result in a clutter. Seems like a bait to me.
In python, i only use classes to define complex entities or objects and hold their respective attribute data. Doing this it helps maintaining the code and reduces code repetition. Example: function overriding is repetition.
The person who asked the first question about functools proves why you should uses classes whenever possible. Having access to data is the best reason to use classes. Functions have local variables that you have no access to, but with a class you can access all the local variables. Data science!
My understanding is that OO is chiefly about extensibility. Yeah, you could always make it extensible later but extension often happens in small increments, and for any given small change you are likely to make the extension in non extensible ways. By the time you wake up and realize your code should be in an extensible format all along, you'll have a lot to rewrite since all those small changes added up.
OOP Code which uses Classes and Inheritance is usually some of the least extensible code I've ever seen. The only thing you want to allow in OOP if you want extensibility is Interfaces. Sadly most Java Programmers I know seem to be unaware such a concept exists, using abstract base classes even where it's equivalent to an interface. OOP in general tends to overspecify and reinvent... All the things constantly. Even their own terms. Look at the famous "strategy pattern". It sure is great, I agree. Now look at how an interface is meant to be used. Oops. Thats the same fucking thing. Maybe just learn how to use a fucking interface before coming up with new design patterns.
At a time a programmer realizes he does not need classes, it's too late: he is a team leader, he has to support his reputation of a "man who masters OOP", and so on... On another side is an effective code, but a complete loneliness. This scares.
I like using classes, so I watched the video with an open mind, to see what could be wrong with that. I found the game of life example very enlightening because I just hate reading the example without the classes, I have to read line by line and be very focused, with the classes I could get a grasp of the situation very fast even without reading the details. I wonder if people who like functions better actually understand the function example with more ease? Maybe people prefer classes or function because of the way they think?
I think you probably find the game of life class-less version difficult to read because you aren't familiar with functional programming. If you learn a functional programming language like Haskell, that code will make more sense to you.
I think it has more to do with how confortable you are with certain concepts. His function used map, itertools.chain, set, and set union, sum, and generators. To understand the the class based version you have to understand tuples and dictionaries. It is about what you are familiar with. If you had more time to unpack it, it would make more sense
@@UnleadedPadyak The code in the example only prints out the glider once after 1000 iterations have passed. If you wanted to see it, you would need to have a way of printing out the grid, and print the glider after each step. The key takeaway was using functions and appropriate data structures to express Conway's Game of Life as directly as possible.
The game of life example in OOP makes no sense because the rules of processing the game of life have to do with several objects (neighbors) interacting getting data from the board. Swapping out cell with other cell makes no sense because that cell would have to interact with other cells, and functions are objects in Python so instead needing to build lots of classes you could split the code into higher order functions.
@@edwin-jq4dp Google uses Python not just for machine learning, but for almost everything that isn't ultra performance-critical (in which case they'll use a bit of C++). www.quora.com/What-is-Python-used-for-at-Google The very site you're writing on (TH-cam) is written in Python.
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
- Antoine de Saint-Exupery
my amputee friend disagrees
Great Quote.
@@touchestoomuch Me, and other poor people disagree!
Same thing said Michelangelo: that sculpture is finished when there is nothing more to remove.
I must add that to be true to this ideal you must not target solving everybody's problem.
As someone who falls into very easy trappings to be elegant and descriptive in my code, this video is a must revisit to remember what matters is keeping it simple, instead of using fancy coding paradigms.
Classes are fun to play with, but I am increasingly convinced for most tasks, especially in regards to computation and data science, it is better to use them sparingly
Functional style with sprinkles of classes to hide functionality
Take aways from this talk and the comment section (note: I am including several quotes from the Zen of Python and PEP 8).
1. Classes are useful, but foolish consistency is the hobgoblin of simple minds.
2. Simple is better than complex, complex is better than complicated.
3. Practicality beats purity
4. When the tools you have already work: use and adapt them for your use-case. Don't reinvent the wheel with a class every time you happen upon a new problem.
5. People will miss the message because their beliefs and tools are attacked.
Zen also says "Readability counts". That Game of Life implementation, short though it is, is not readable.
@@soberhippie i think it was readable... code is like poetry -> some like, some don't
@@ZapOKill most coders aren't making art, they're making systems. Consistency is always going to win out.
@@soberhippie Exactly. Readability is the most important measure of a good program. Not how long or short it is.
@@oysteinsoreide4323 Yes, but the unnecessary verbosity of (e.g.) The MuffinMail example in Jack's talk is far from readable.
Whereas, his reduced version is both readable and quickly understandable.
I think the take away here is simply that very often people tend to overdo some code steps systematically just because they learned that this was "the proper way" whereas it might actually just be making the code complicated and large uselessly.
This guy isn't the first I see to make the point that this whole deal of making your code super complex for the pretended sake of future flexibility and time saving is a bunch of garbage and typically just ends up eating more time than it saves. I think there's truth to this.
Also you gotta remember that everytime you complexify one of your APIs you're making the learning process longer for any new employee in your organization. I think over the years there's been a dogmatic approach that's built up in OOP and not always for the better.
The key takeaway for me is: Don't foolishly design everything as classes. Functional programming is way more efficient to read, write and test. Only use classes if you need complex objects.
Pair programming is one way to reduce this problem
Pair programming is one way to reduce this problem
I agree with a lot of this, but not at all the exceptions part. I like it when 3rd party libraries define their own exceptions. It makes it much easier for me to figure out the cause of the error.
And much more, to catch them specifically and not some unrelated one.
Edit: three years on, I don't think my comment here is correct at all. It might read convincingly but I didn't know what I was talking about. I wrote garbage code because of this mentality. Someone in the replies said I was conflating abstraction and good naming, and that's exactly right.
---
This presentation is an attempt by someone who has a good point to overstretch that point way beyond reason.
His game of life rework is very confusing (19:48). I have no idea what it's actually doing. I don't know how the game of life works, so I can't look at it with the luxury of already knowing what it does. I have to read it line by line and hold all kinds of information in my head at once to understand it.
One of his lines has 4 steps' worth of nested function calls. Wtf? That's not simple code.
If he abstracted those steps into individual logical leaps, each contained in a function with a _descriptive_ name, it would be so much easier to read. And, when you have a bunch of functions that depend on one another... You guessed it. You should put it in a class.
He's using the complete wrong metric to judge whether classes are good or not. Classes allow you to compartmentalise a problem. If it assists you in compartmentalising the problem, *it's good*. If it makes the problem more complicated, *it's bad.* That's it. Obviously, the MuffinHash example is bad, but the reason has nothing to do with whether they used classes. The reason is that those classes make it _more difficult_ to conceptualise the solution.
I don't know why you find his Game Of Life code confusing. It took me 20 seconds to read and understand it. I assume you just aren't used to functional programming paradigm. But it is not his fault. With practice you can read it as easily as 100% imperative code.
I find that I can read his code as a book: read it line by line, never look back. It is very easy and pleasant to read. And if he had 5-10 functions/classes it would take me longer to read and understand it, having to jump from one place to another.
My only problem with his code is it's performance (obviously, I hope). But in exchange for this ineffectiveness you get GOOD readability and development speed.
P.S.: If i wanted speed, I'd use C.
The _point_ of an abstraction is to allow you to understand the solution without understanding the lowest level of detail.
You can still delve into it if you want to. Being able to paper over your ignorance is a _good_ thing.
Programs that force you to understand the entire program just so you can understand a part of the program are bad programs.
I don't know python, but I was able to read and understand what that code does. The only part that was hard to understand was `board | set(itertools.chain(*map(neighbors, board)))`. But that's fixable, just add an extra local variable, and it'll become easy to read. And probably one more variable for `(neigh in board) for neigh in neighbors(point)`.
> You want to code quickly and with minimal abstraction, I want to code in a way that's easier to maintain
Eeh, I don't see a collision here. Minimal abstraction = easier to maintain.
Minimal abstraction is not easier to maintain for any significantly sized system.
Over-compartmentalization and over-abstraction is a sin to be avoided. I would not want to maintain your code. It's probably about 10 times more verbose than needed, inefficient, hard to read and therefore buggy. Smaller and simpler is better. The problem with OOP is that everybody thinks *their* problem is so *special* and needs special classes. Not so. Do us all a favor and use as few classes, methods, functions and lines of code as will get the job done.
Hmm, this guy has some good points.
1: Mostly no point in abstract base classes in duck-typed languages.
2: No point in making function objects (functors) when there is no interface concept.
3: Less code is mostly better, but only if it is simpler.
4: Preparing the code for the future is ok, if it requires minimal effort. Otherwise it is pointless.
5: Namespaces should not be abused. But they are helpful sometimes, for organization purposes. In auto-completion lists they are crucial.
"Code is read more times than it is written", and in production environments the programmer is not the one reading it. This quote, thanks to whoever said it first, is the first principle for whether to use classes or not. Whatever makes the code more readable and therefore maintainable should be used.
And, do classes make code more or less readable?
@@jeroenvermunt3372 Both
@@jeroenvermunt3372 Sometimes they do, sometimes they don't.
Not an expert by any means (self-taught), but for most cases where I've been tempted to innovate something fancy, I just start by typing out what I want the user of my code to be able to type as instructions. Work my way backwards from there and figure out the "how" of the implementation as long as I already know the "what". I have used classes so far to help me conceal non-user methods (implementation hiding I guess; less options for users means easier learning curve and Python doesn't appear to have access modifiers as an alternative option). Has also helped with the purpose of some abstractions too.
self, nice one
This is the correct mindset and curiously very rare
Even though this talk is older, I find it so relevant and interesting still today
Judging by the comments that are "more recent" a lot of people still don't get it.
Keeping it simple is why Python is so appealing to me. Life is easier when you don't have to wade through 1000s of lines of boilerplate and code-bloat.
@It’s me again Nooooo we never hear that word anywhere!!! It cant be½!!!1§
Yes, but you can also write code without boilerplate and bloat in C++.
Python however makes writting, debugging and maintaining any reasonably complex project near impossible.
It turns out types and identifiers make things easier, not harder, in the long run. The easier it is to write wrong code that still compiles and executes, the much harder it gets to write nontrivial programs.
@@KilgoreTroutAsf I subscribe this
public static constant main void covid let get set x = 5;
@@_caracalla_ @override
Adding "Exception" to the name of an Exception does help. It helps if you're facing a library that has numerous exceptions and you just want to search for those. You could open the type hierarchy, but you could also just search for the type name, like "*Exception" and it will list you all of them. Programming is not just typing, it's also searching.
A curious thing about this presentation (though it is an old one), is that what actually happens when some java/c# programmer accidentally starts writing in python/ruby scripting language.
Artem Zhuravlev he realizes waste of time and effort, his engineering was over engineering.... It's really a heart breaker
@Joe Boxter
Uhm, especially in languages like Python everything actually is an object.
@@harrypadarri6349 in Ruby everything is an object. In python you can get alot done with just imperative. It doesn't lean on the OO style anywhere near as much as C# and Java. Most Python dependencies are very OO though. I once tried to write functional Python code. It didn't go well.
@whossname
You’re right with that. Python has so many built in datastructures and additional libaries that you can write pretty nice code that appears to be imperative.
I once wrote a programm that did use only one single self-written class in over ten thousand lines of code.
I am not talking about style but the inner workings of python. There everything is an object. Including functions used for functional programming.
Unlike C where variables just point to a place in memory where a value is stored.
In my CS lectures professors meant that distinction when saying „everything is an object“.
No? I've done Java and C# for forever and my first time with Python I just ran code directly without any classes. Just because I'm very used to it doesn't mean I can only code in classes
One of my favorite Python videos. Every example is so on point.
You, every time I turn around someone sais the contrary of I was told before. "Divide and conquer to solve your problems and make your program as easy to mantain as possible", then "Don't overuse classes, they reduce eficiency and stuff".....
"I hate code and I want as little of it as possible in our product" - Jack Diederich
"We usually think of code as an ASSET, a valuable thing that we shouldn't delete. Code is a LIABILITY - all code is cost " - Dan North
I don't tend to enjoy tech conference talks, but I've watched this one several times. I'd guess most of us have encountered many different arguments for simplicity in software design, but I really enjoy this one in particular for some reason
making a mental note to pronounce 'dict' as 'dictionary' in real life.
@@alexanderzerka8477 that was a joke but i'm glad you pinged me a year later to make a snotty comment!
@@alexanderzerka8477 uh, okay. sounds good!
I love what he's saying.. but when I go out for a programming interviews
99% of the time... they want me to write things as classes to solve the given coding test. No matter how inappropriate it would be to the test.
+Kobe Wild What kind of contests?
This is an indication that you are interviewing with a company that doesn't share your values (and lacks common sense). Filtering out bad employers is a great outcome for interviews.
Yeah but, y'know, working for a bad employer is a hell of a lot more lucrative than working for no employer at all.
@@edgeeffect Hahahaa. VERY TRUE LOL
That's how you know where not to work. Classes create bloat in terms of code complexity, execution time, and computer memory. Everytime a class is written, make sure you have a good reason for it.
His message was not to stop using classes but stop using classes for simple things. Lot of people misunderstood. Classes are useful when they are needed but too much of class objects with bigger code makes it slower. No Offense.
Exactly. Why make a class just to call it's methods.
@@cwill6491 the things is lot of people are here fighting against each other one who likes classes and one who don't and some python haters! I don't know why this people just learn something new and appreciate it instead of fighting over each other. Why hating python in comments btw? What you think about this brother.
@@lordtejas9659 python breaks a lot of conventions. For example, declaring a variable globally doesn't necessarily make it global. You have to use the keyword global in every scope you want to use it in. Some people might not like stuff like that. If you can put that aside though, python is so useful. You can ignore many programming issues and get a prototype working quickly.
@@cwill6491 well I never got an issue with local and global in python. I have coded more than 100k lines in both python and C++ within this years. I use C/C++ as well as Python. What I was saying that to stop people for fighting over stupid things like they are tools and people misunderstood the message of the video. But this students from IT and freshers don't understand the basic concepts of Programming and starts fighting. If C++ was good for prototyping then why we even needed python in first place..thanks for your opinion friend. Have a nice day. Hope this message stops this new kids from fighting. It feels like civil war.
Well, you know what they say "the headlines tell the story" in this case the title "stop writing classes". LOL
After 10 years, with the introduction of type hintings and pattern match in newer python versions, the idea of less classes seems more true
protocols, data classes, single dispatch are also pretty useful
Want to write spagetti code?
@@biskitpagladata classes are a shame in the world of OOP. They break encapsulation, introduce mutable state and result in functionality being spread across the codebase. Burn it with fire.
@@МаксимГорюнов-м7и Spaghetti code is when you see a simple function call, but actually it is a dynamic dispatch over an inheritance hierarchy. Spaghetti code is when numerous layers of indirection are pretending to be "simple" linear code. OOP is spaghetti code.
@@youtubeenjoyer1743 if you don't know how to write OO code, yeah, it turns into procedural garbage.
I don't know. I feel Exceptions are the exception (hehe). Having a Stacktrace where the first word already tells me what is the problem. Having an UpdateException(MyModuleException), DownloadFailedException(UpdateException), and InstallFailedException(UpdateException) giving me the alternative of what to try/except is quite important. Or let's say it otherwise. I simply don't know how I would do that exception handling stuff without all the subclassing.
But when you Throw an exception you can pass the error message.
You are right and the developers of Python agree with you
The important lesson. Do not creat abstractions "just in case". It is easy to add them in the future if needed. Keep it as simple as possible. No wrappers. No custom base classes.
Things like debugging and tracing can be solved other ways.
Maybe it comes from the C/C++/Java days where it was hard to patch things in when you needed them. No new means no need for factory methods, properties means no need for getters/setters, closures can be upgraded to objects with __call__, optional arguments, no difference between classes, objects, or modules, duck typing means no need to rewrite your code when you change your class hierarchy, classes/objects/modules can be swapped around, dynamic typing works sort of like duck typing and mypy's errors can be ignored..., iterators is the default, you can add data to classes, decorators, context managers changing globals, __getattr__... However, Common Lisp is even more hardcore than Python in that you could always use something like JQuery on your s-expressions to refactor it, optional return values and you could locally change progn, let, defun, etc... and turn functions into macros that alter the expression trees of their arguments...
Sometimes you need wrappers and interfaces for your code to become testable.
@@Dacusx Standalone functions are probably easiest to test. :)
@@movax20h Only if they are pure. :)
I agree to a certain extend but we did not mention was the fact that Classes have a fundamental task of making Business Logic look readable and easy to implement for less technical people, often functional administrators.
in none of the examples mentioned OO achieved that task.
22:33 I think this guy has a point with regards to implementation hiding. If you use a plain old dictionary everywhere in your code, but then later on realize you actually need some other data structure instead of a dict, you're going to have to change a hell of a lot of code. If you hid what data structure you were actually using behind some interface, then you can swap it out easily, only changing the code in 1 place.
Is there a way to do that without interfaces/classes?
For any language or just Python?
@@r.t.5767 Any language
@@trampflips101 There is another way (and it is probably older than interfaces and classes). The translation units!
In C you can easily hide data structure you use just by not defining it in header and defining it in source file. The same goes with functions that deal with that data structure. Make them small (their only purpose should be to deal with the data structure) and static (so they are hidden), and whenever you need a different data structure replace them with new functions working for the new data structure.
Or make your project modular and that data structure and its "methods" as just another module - you can still replace that module any time you want, but it will not be hidden that way
Just ask yourself if it needs to be hidden, if yes then you have the first solution, if no - probably the latter one is better
The first solution is the best when the data structure is so small and easy to implement that creating another module is an overkill
It can be as simple as Find & Replace
@@vicatucd It would still largely be a manual process though. But yeah, it probably wouldn't take that long.
love it - so relevant even today in 2020
Did I just watch 25 minutes of talking that can be compressed to the two sentences:
"Think before you write" and
"Look at the standard library to see how a language was intended to be written"?
porffiry
I had no problem with what he said i just don't think it is worth talking so long about it.
Mr8blacklp: Vidcon 2017: "Stop writing sentences!"
"Write good code!"
There, now you don't have to watch any more software talks ever. I just summarized it all for you ;-)
what is the good code?
"Think before you write" is very vague...
The game of life implementation is simplistic, but barely readable like that.
most programmers don't use too many ideas from functional programming or aren't well acquainted with it. since he's using a few fp functions in the main function, so the code seems barely readable, but if you look closely it's actually quite okay. implementing it with classes would just slow down the code considerably while not adding anything useful.
it look like code I was making when I first started programming... tbh its a fugly mess.
I'm new to python and I had no problem reading it
The OO code is much easier to read, reason about and modify.
Hence, in my opinion, much more maintainable in the long run.
I was thinking the same thing
I goda disagree with what he was saying at 4:30, information hiding, encapsulation, seperation of concerns, etc are very important, and it is extremely difficult to make easy to understand, maintainable software without them..
However, what he says about speculative design is very true.
+Bejamin Rood Heh, after nearly 30 years of programming I might come up with a few, but it's a short list. Well said.
No, information hiding makes code unmaintainable.
What makes code maintainable is readability and clarity, first and foremost.
Obfuscating simple code behind layers of classes makes code a maintainability nightmare.
When including an external library that has a bad or illogical interface, encapsulating it (facade pattern) lets you hide the bad parts and ensure that your team only uses it right - it can also allow you to add correct logging, error handling, etc. to code you can’t refactor because it’s third party
Separation of concerns: actually usually creates simpler more readable and more reusable code with fewer side effects; I find that when this comes up in real life it’s usually not because someone is trying to pull a fast one, but rather because a more junior dev is doing something like putting API input validation logic into a DB stored procedure where it can’t be reused.
Of course you should always be wary of premature optimization and overengineering, but this guy sounds like a lazy/semi-skilled dev who never found that balance. He elevates simplicity before all else and throws out decoupling, encapsulation with the bathwater when there are very good reasons why those are best practices
10 year later and we still have these problems lol
The Agile(TM) consultants said that architecture and design could be done later
Lol
Whoops
Classes have there place in programming as the questioner in 23-25 minute indicated but I do agree that many programmers do overkill. Helper functions can just be functions instead of a class with loads of static functions.
I think at least part of it is because so many people learn Java as their first programming language. Python has classes and objects as a feature but they're used to programming in a language which is built on classes and objects from top to bottom.
University CS education is stuck around 1988
Re the question starting at 21:19 you can (now) introspect a partial object without using an undocumented dunder, it has args and keywords attributes.
4:25 -- never had to use "decoupling" since graduating? That's on you, presenter. When coding in a large codebase you really need to be careful about decoupling if you want your code to be reusable ever again; do you want your code to be reusable? Don't answer that. Also, coupling is the single worst root of creating what we all know and dread as legacy shit that nobody can untangle and refactor. If it's bad but decoupled, then it's really easy to refactor 20 years later, or even to replace with an external future-modern component. If it's coupled, you are basically fucking 50 other guys down the line single handedly.
Why is your codebase big in the first place?
reusable code lmao
Although in the game of life he has reduced the number of lines, I don't think it necessarily made the code easier to understand.
It's easier to reason about cells in a board than reason about an "advance" function. Adding more possible cell types would already make this advance function too complicated.
Anyways, I got the idea of the talk, always good to keep in mind that Python is not Java and that not everything must be a class
I have seen Game of Life's with different rulesets aka advance functions, but I have never seen one with different cell types. Don't generalize, if you don't know for sure, that you'll need it tomorrow.
His point at 5:55 or so was great. If you know for a fact that you will need to use something later, then of course writing a class may be useful. But if you don't have any reason to need it later right now then don't try to plan for a 100k line project that will probably only ever be 1k lines max
He hasn't used "Separation of concerns", "decoupling", "encapsulation" or "implementation hiding" in 15 years of programming? Ok bud.
As a C++ person all those terms are the core principles, to me at least. I’m completely baffled watching this presentation.
GogL0L C++ doesn’t force you to do anything, that’s half the problem collaborating with it. I don’t do OO. I do data oriented design, which C++ is great at.
@@smallbluemachine [deleted it because I confused c++ with c# lol]
But idiomatic Python code is different from idiomatic C++. When working in a "data oriented" fashion (in Java or Python), I tend to only use build-in types and write classes only when necessary. All those terms are pretty much related to C++, Java [,...], or C# styles of OOP, as you get pretty much no coupling at all when you use to build-in types and write classes only when necessary.
You write code for people to read, not for computers to save space. I'd rather have 10 times as many lines of code that I understand instantly, then one tenth that I need to ponder for hours about until I get all the edge cases
except that the code you have to read is often crap like your comment
@@Amine-gz7gq Seriosly? How is it crap? Objectivly or subjectivly? Is is the comment itself that you think is crap or is it the information it is trying to convey?
You Tube recommended me this because i watched Monty Python's sketch... let us turn off recommendations.
That glider code and his admission that he hasn't had a single discussion about decoupled and cohesive system design with another engineer in >15 years pretty much tells me everything I need to know.
what do you mean he hasn't had a discussion?
Watching this in 2020 and all the rules still apply. Great talk.
They apply even more because we have more standard tools to deal with the problems people tried to use classes to solve.
@Michael David lol. You're an idiot. You're making a big deal out of nothing. Okay, "recalc" isn't a perfect name. So what? Any idiot can still see what it means and what data it holds: it's the set of all points that need checking to see if they're alive in the next state (or all the points that need to be "recalculated"). Also, I've seen professional code with much worse variable names, so your assertions about "any second year comp sci student" are full of crap anyway.
I've been using dataclasses quite a bit recently. I like them better than dictionaries when I need mutable named tuples or want to define data schemas. The typing library and typehints work nicely them as well. I wonder what Jack's opinion would be about using a dataclass when you could have used a dict or a tuple?
@@williamkmanire His talk is more about unnecessary use of classes as pure method holders. I doubt he'd object to a data class that defines a record or otherwise combines multiple related pieces of information. That said, I find I almost never need those classes to be mutable. Allowing them to be mutated usually makes the code more difficult to reason about (especially if you're stuffing intermediate values into its attributes), and avoiding that is usually a simple matter of doing any computation using local variables or another function before calling the constructor. (The dataclasses module has replace for if you actually need to change values for some reason.)
Code in C. If you feel the urge to create an unnecessary class it will be a little more difficult and this will give you more time to come to your senses.
That "very succinct" neighbours function is a bit silly
for dx in [-1,0,1]: for dy in [-1,0,1]: yield x+dx,y+dy
You're returning the point itself whereas his implementation does not (although yes, the neighbours function could be simpler)
@@eecarres
That's true but since "neighbors" is used exactly once, you can add a skip clause (if dx==dy==0: continue) in the body of the loop and the whole thing would still be simpler.
@@dionbridger5944 It's used twice: once in generating all the points to recalc and once in the live neighbor counting. I like the fact his solution avoids invoking an if condition on every loop.
@@BladeOfLight16
18 evaluations of a signed int equality test is computationally speaking, nothing, unless maybe you are running your program on a clockwork Babbage engine. Even for a million iterations, it comes to 18 million operations, which on a puny 18 mhz CPU is a total of 1 seconds worth of CPU time.
BTW you can get away with a succinct 2 line function without any equality test:
for i in range(8):
yield x+[-1,1,0][(i//3)], y+[-1,1,0][(i%3)]
And the fact that the "function" is only 2 lines means you can probably get away with not having it be a function at all ( depending on where it's called from ) and just in-lining those 2 lines. So not only do you save on the if-clause, but you spare your Babbage engine the cost of doing a jump operation too ;)
0:05 R.I.P. Jack, you're going to be missed
Lol dude. I said the same thing. Probably gonna email him to wish him my condolences. Truly heartbreaking...
Lool
maybe he is cheating with death telling that he already dead?
To get the curried arguments from a partially applied function, use the partial.args, and partial.keywords properties
You can also use lambda for partially applied functions, or changing the order of arguments, or to add more arguments to something
I kinda like his implementation of conway's game of life, very neat and concise.
It is ridiculous how far fetched this is. He gives examples of bad code and says why you shouldnt use classes for something they are not meant for.
Yeah, no shit...
Yea I don't think this guys as smart as he thinks he is. He advocates useing global variables to store URLS and API keys. Apparently we've been doing it wrong the whole time by writing a config file reader function and using that to populate the parameters of the __init__ constructure of a rest API client class. I don't know how much more of this I can stomach.
Except this is exactly how people use them in the wild. And people coming from languages like Java or C# are convinced that _everything_ should be a class because they don't even have a concept of things like functools.partial or having late binding for non-class methods. This is all really great advice.
@serpathius The fact that you think OOP is somehow more powerful than any of the techniques he discusses (comparing it to airplanes vs. cars) is exactly why he's talking about all this. OOP is not more powerful. It does not do more. It does not scale better. It's mostly only necessary as a kludge around the fact that OOP languages don't support late binding of methods that aren't bound to an instance (static methods).
@serpathius ..... I literally explained that in parentheses right in the sentence you're asking about. Did you bother to read the message? You claimed that OOP compares to other approaches in the same way airplanes compare to cars. That is clearly claiming that OOP is more powerful.
This was the whole point of the talk... Not to use classes when you don't need the
Very useful message. Scala is probably one of the best languages to strive for the balance the author suggests between classes and functions. Python is moving that way, but it lacks the type safety. Very interesting and actually useful for every day work with python. Thanks!
Class Flow may be empty, but there's at least two reasons I can think of to keep it:
1) You want a way to test an object to see if it is a "Flow" (via isinsance, for example)
2) You want to allow the users of your code to subclass it and implement their own Flow class.
Mr. Diederich doesn't seem to give the "benefit of the doubt", or even attempt to see why the code was written this way. The first audience question hinted at that, but the speaker never gave a real answer.
Agreed, this makes the talk a bit weak to be honest.
Classes are great but they are also overused. This talk describes examples of class overuse taken from real world code and refactor the unnecessary classes, exceptions, and modules out of them.
The majority of this errors, of the code is shown, is not about Classes, is not about OOP. Is about bad refactoring or not refactoring AT ALL.
Dont stop writing Classes, just think, write and refactor!
You're taking the title far too literally and not really listening to the talk.
Do you think so?
Sometimes writing OOP-as-a-lifestyle leads to infinifactoring. Then there's FOMO-refactoring. Then there's ... %
...and practice TDD
@@ElenaDotNET I do not think so; I agree with you.
I find it amusing that my first impressions of what this guy had to say were completely off. I thought he was completely against classes in code, but what he was really speaking out against was a flagrant misuse of them that I hadn't even been aware existed.
This is more of a "Know Your Standard Libraries and Use Them" video. That is probably how he did the first "amazing" code side reductions. Also my heapq module does not have pushleft and popleft methods in his heapq, plus I think there's a bug in his popleft method if the user did not define a key function. (He passes the second element of a tuple which is only created if there is a defined function). I guess the main thing I agree with him on is I hate typing long identifiers...
If the user fails to define a key function, the key function defaults to 'lambda x: None'. It's right in the __init__ argument list. So there is no way to get into the guts of the class without having a key function of some sort defined.
12:55 ...so the title "stop writing classes" is missleading. Thx for that. The talk is great it deserves a more suitable video title.
Like "Let's snigger at some code I wrote"?
Say "Iterate on a random dict" five times fast. Thanks commentary guy!
11:38 but the PEP 8 says I should add an Error suffix to exceptions that are errors
Great talk. I like the simplicity.
Python had functions before it had classes. This is a Good Thing, because it means functions are powerful, first-class objects. Take advantage of this. Use them in conjunction with classes, by all means.
That is one of the best seminars on programming I have heard in years: you should travel the United States and give seminars on programming: How To and How Not To.
I want to work on this guys team. Can't believe that all the questions are from resistant people that just don't get it
Going against the classic CS training is very difficult
How software development is taught is totally ass backwards and should be considered harmful
Object Oriented is not meant to write less code, but a maintainable one. I can replace 5 classes and 500 LOC with 5 lines compressed in a python function, yes. But that will be completely unreadable. Examples presented here are extreme and doesn't help to support the topic, which has got sense in some cases.
+D. Nappo the code on his site/examples, are impenetrable automatically
use the philosophy / design of the community/toolset - make it work. Don't walk away with your own. This person is not an authority. He appears to have presentation, but who is he? What is this?
Then why does OO produce things that look like Enterprise Fizz Buzz? No. OO (as it is actually used in practice, which is perhaps not what it's supposed to be in theory) is a way of trying to build code off rules and platitudes instead of off common sense.
Anyone can grok 5 lines of code more easily than 500 lines of code. This should not be controversial. Sure, you might have to stare at it a few minutes, but it's gonna take me time to walk with 500 lines of code, too. In fact, it'll take more, and it will be much harder for me to see how the different pieces are supposed to work together.
Of course. I'm a big "fan" of C and Assembly since I come from an embedded background and only recently have I started getting into C#. Considering what I know until now, and it's not a lot, I can really see the usefulness of classes if you want structured code.
"Sure, you might have to stare at it a few minutes, but it's gonna take me time to walk with 500 lines of code, too."
If the 500 lines of code are well written and properly abstracted, you don't even need to read the majority of them in the first place. Looking for an error? With the right decoupling and abstraction, you can easily narrow down the class and even method responsible for it. Looking to modify some of the functionality? Find the spot in the code that relates to what you're actually modifying and have at it.
You obviously have no experience maintaining code. Yes, you're going to have to read a *lot* of code before you find the one line that is miscoded, assuming that it's only one line that's in error. Often its conflicting assumptions made in different places in the code. Always, the more code there is, the worse it is to maintain. Never prefer 500 lines of code to 5. That's completely idiotic. Yes, you dearly hope that it's been factored appropriately. But that never means adding unnecessary classes and exceptions. Verbosity is the primary enemy of maintainability in OOP code.
Version 3 of the Muffin API is not thread-save. Two threads using it with two different keys wont work, while it works with Version 2.
Great talk. I recommend it. Q&A is skipable though.
That is true for almost every Q&A ever.
this guy has a point, even if at first he sounded like weird. In my time, I had to suffer tracing unnecessary class abstractions in C++ made by some kid (the management thought was a superstar) and now left for singapore. And when i looked and followed thru his abstractions, i began to realize that this OOP thing along with its power to create artificial abstractions is rearing a generation of ignorant developers later building on top of these abstractions. The BSD socket beauties and tcp/ip headers are hidden and instead exposing some get/set methods. It is true, that abstractions are powerful tools, but if you are not careful it can also lead to ignorance and decadence. To me, the first thing is the electrons and their properties of producing boolean logic. If you are aware at this level, then you will fear the days ahead when quantum computing comes. This is then followed on by protocols, and then the core libraries. It was from that experience that I started to move away from C++...
+Eigenfield Aparicio save me, tell me where to go from here.
I hope you're following Jonathan Blow and _his_ language, he's gonna use as C++ replacement. ^^
th-cam.com/video/De0Am_QcZiQ/w-d-xo.html
@@ericmacleod8605 we are all looking for the promised land
Its happen when you use your keyboard more than your brain.
I felt the greatest sense of disappointment, when you disclosed that the company from the 1st example was not actually called 'Muffin' :`(
Dreams crushed
My god I wish the engineers at my work understood this
Me too. I'm currently working on a single file that has 860 classes, 99% of which say pass.
kek'd
@@SinCityGT3 wow
has it been any better now?
But, this guy also has some silly points:
1: His Web API is simple, but it doesn't tell the coder what verbs/nouns exist. This requires looking a documentation instead of using auto-completion lists.
2. All of the "words he hasn't used in 15 years" allow for using 3rd party modules a lot simpler and quicker for most devs.
3. His implementation of the Game of Life is very clever, but it will be a maintainence nightmare as it just seems obfuscated, and changing certain parts of it will suck.
"His implementation of the Game of Life is very clever, but it will be a maintainence nightmare as it just seems obfuscated, and changing certain parts of it will suck."
Quite the opposite. Its brevity and clarity are the very things that _produce_ maintainability. If your code is bloated, it will be hard to figure out. You could make a case that an extra `Coordinate` named tuple class would make it slightly more intuitive, but beyond that, no introduction of classes would improve this implementation. A couple of additional functions just to name certain pieces might be a small improvement, but the underlying style and approach are the pieces you should draw out from it. Namely, using the existing, conventional tools for the problem and keeping the code simple are always massive wins.
And this is why your point 2 is also wrong. Those concepts _do not_ help you write better code. They are, at best, ex post facto descriptions of the final product. You cannot write code that achieves those ideals by trying to think about them. You must think in terms of simplifying your code with meaningful abstractions to achieve all those qualities, and that is precisely the mindset for which he is advocating. Don't worry about those lofty, ivory tower academic principles. Just worry about writing simple, easy to figure out code that uses the standard approaches to your common problems. (And most of your problems are common.)
As for point 1, I'll admit that's a disadvantage, but that doesn't necessitate a ton of classes. At most, it warrants a method per operation.
@@BladeOfLight16
The point is that abstractions are meant to simplify things for us humans, they are easier for us to grasp and reason about.
A Cell and a Board are something we understand, the behavior of the game is way easier to grasp written explicitly and clearly as OO code. You can think of the smaller parts separately, understand them, and then see the game logic implemented in its own class/function. The cognitive load is lower, and testability is improved in such small pieces of code as well.
Look at this monstrosity:
```recalc = board | set(itertools.chain(*map(neighbors, board))```
A lot is happening here, in this single line. What is recalc eventually? How does it compare to board? Or to newstate? How do you modify the rules of the game? The number of neighbours to keep you alive or to kill you? Does the code here require change in such cases? Moreover, this code requires you to stop and think when reading kt, to try to imagine what it does, to execute it in your mind. Understanding is not instantaneous, even if you originally wrote it. This makes going over this code more difficult, compared to more explicit, well divided OO code. The OO code can be maintained by fairly junior developers. The functional code is way harder for most developers, especially ones that are not engineers.
I prefer simplicity, less magic, less premature optimization. I will optimize when I see it is required, but in general I will always prefer saving developer time over execution time.
@@advance512 OO doesn't provide that clarity. The task objects are good at is enforcing constraints on state, and there's nothing like that to do here. OO seeks to make behaviors subservient to data, but programming is primarily an art of specifying the sequence of computations to arrive at a solution. Good programming makes data subservient to the behavior. Clarity comes from grouping those steps in a coherent way that properly emphasizes the mental model (the reasoning) that leads the programmer to choose the steps that he does.
recalc = board | set(itertools.chain(*map(neighbors, board)) is a simple 5 step computation:
1. map: executes the neighbors function against each element of board.
2. *: Expand the iterable into an argument list (This could be avoided by using chain.from_iterable, if we wanted.)
3. chain: concatenate the iterables of the neighbors together into a single iterable
4. set: Eliminate duplications
5: board |: Union the resulting points with the neighbor points
So this is just all the points on the board and their neighbors, and the "recalc" name tells us this is all the points that need to be checked for inclusion in the next round. Sure, it's kind of dense, but it takes about 2 minutes to figure that out. Worst case, you could factor it out into a named function to communicate its intended purpose a little more directly. There's no way OO could improve on this line of code.
@@BladeOfLight16
Strongly disagree that the single line is simpler to understand, reason about and modify/maintain compared to:
```
for (x, y), cell in self.cells.items():
if len(cell.neighbors) > 3:
cell.next = False
```
and I doubt most programmers will agree with your claim.
And this is for a tiny code base. Imagine how terrible it can get with many such instances, that do several massive operations in a single line of code. Way less readable.
I think both OO and functional can shine in various situations. In my opinion, the example we have here is a good one where OO is indeed preferable.
Another issue is soft type safety - type hints. The functional implementation of CGoL uses a dict as the board, which is passed into a function. There is no type safety of any kind here, compared to using classes with methods to contain state, or at least - dataclasses with functions that have type hints. Type hints are great and prevent tons of bugs. So, another reason to not go with his implementation.
@@advance512 The fundamental complexity of a program does not come from single lines of code. It comes from _how different parts of code interact._ OO strongly favors vastly more complex and more difficult to discover relationships between different portions of code than procedural or functional code, which are geared toward making the execution sequence and call stack obvious. That isn't surprising because, as a I said, OO takes the focus away from execution and tries to put it on taxonomies. This makes OO heavy code a complete nightmare to decipher. The fact that many programmers fail to recognize this does not make it any less true. Furthermore, using bog standard, conventional data types and library functions makes it vastly easier to decipher any single line of code as compared to using custom objects.
In your example, I have no idea what the data types of self, cells, or neighbors even are, much less how they or their functions behave. I have no idea what effect setting cell.next has on execution later. (Does the cell get removed? Does it prevent printing? I don't know.) This all means I need to study a much broader portion of the code base to figure any of it out. By comparison, every single portion of Jack's line consists entirely of data types and functions I am intimately familiar with, and the function does not modify any nonlocal state. This makes understanding it a much simpler task. I already understand the behavior of the data types involved, and I know that any later effects on execution will be found _in the caller_ where the returned value gets used, rather than divided between different sections of code.
If the languages i coded in (primarily, C#, Javascript and TypeScript) implemented classes, scope and lambdas as poorly as Python, I wouldn’t want to use them either. i don’t mean that to be snarky, Python just has a really poor implementation of these concepts. Having to have self as the first argument to your methods is one of several things that make classes in Python so convoluted and why people come to the conclusions that this guy did. Pre-ES6 javascript’s prototypes and such made OOP more trouble than it was worth too. Opinions like this (which are still alive and well in 2018) make me think the Python community has had its head in the sand for the last 15 years and hasn’t seen how much cleaner the syntax could be in Python with a little syntactic sugar. The speaker reminds me of myself back in 1989 arguing with a friend about how much simpler and better Amiga BASIC was than C and C++. I just didn’t understand why someone would need all that complexity of multiple files and such. I get that the point of this was to remind everyone to keep things simple and don’t over-architect. I completely agree.
Well said. People rave about Python and that it's the best thing since sliced bread (as the saying goes). Next year. no doubt, it will be some other language that becomes flavour of the month. Sure Python has it's uses but it's not the be all and end all of computer languages. I've not seen anything done in Python that can't be done elsewhere, and sometimes better. Less code is not necessarily a good thing, especially when the original code is so difficult to comprehend. Finally, the thing I didn't like what his constant sniggering at what he considered bad code. That's HIS opinion not mine. I for having programmed many languages over the years and translating code from one language to another would much prefer code that was readable and not the reduced and difficult to understand concept he came up with.
I still don't understand why you need all that complexity of multiple header files etc. I have wondered since 1986, when I saw my first C-program. I worked as an Assembly, Pascal, Simula, PL/M and Modula programmer when the printer at my room suddenly goes crasy with those peculiar two character combinations (== && | | ++ [ ] () **) all over the place.
The only complaint you can think of is having "self" as the first parameter? That's so trivial. That's like complaining about semicolons or curly braces. If you think javascript has a better implementation of classes than python I seriously question how much time you have spent with either language. Any syntactic sugar that eliminates "self" in method signatures would also severely restrict the use decorators and metaclasses. Self is necessary because python is dynamically typed; it is not practical to specify a receiver type like in Go or Kotlin.
> had its head in the sand for the last 15 years
This is ironic since object oriented programming is on the decline. Is your head in the sand? It will take a long time to transition our enterprise infrastructure, including multiple generations of indoctrinated engineers who are incapable of thinking outside the object, but it's just a matter of time until OOP is history.
@@megamaser OOP history? I'm not personally very fond of it, especially not as the religion it has been since 1995. But why not use it where it makes sense? I mean things like GUI interfaces, that quite natually fits that model, or the contexts for which it was invented, i.e. simulation. (The language Simula, in the 60s.)
@Adithya R The latest versions of JavaScript (ES6) has a much improved OOP syntax as compared to the primitive OOP features we have had to struggle with in the past. If you have not seen JS lately, it's worth look at some videos on JS ES6 OOP programming.
“If implementation is hard to explain then it may be good”
Reminds me of pthread vs c++ thread. It is easy to implement in c++ but unless you program in pthread, various multithreading problems, you will not learn the conceptual ideas related to it. It’s about whether you are becoming code money for corporations or actually becoming a good programmer.
12:40 lol. C++ defines like 5 exceptions...
That’s both because a lot of errors are at compile time and raising exceptions is slow when compared to error codes. If it wasn’t that raising exceptions is (comparatively) slow I’m sure there’d be a lot more.
Michael David that’s completely unrelated to the comment, but I agree
damn... still or even more relevant these days after 10 years. No fancy words, straightforward. Great honor to have good people on python in the past although today many went to other lang and communities.
This is like complaining about the .NET framework being too big because all you use is a string in your hello world application.
I am positive that the initial API had features that you were not using, so after extracting out the only function you wanted, you tossed the rest saying it was code bloat....
I advocate for good design and structure, but also I strongly agree with not over design, one should plan for the future but not invest too much effort on it. for example I'll model this as a class because it has a good chance to be overload or subclassed, but I'm not creating the whole inheritance structure.
Its quite amusing - We all love to code...but still we love if there is LESS to code :D
That's because we love "our own" code. The others's code, not so much. ^^
Right, there is a nice quote (I think of the French Voltaire):
"A book isn't finished when you can't _add_ any more words, but when you can't _remove_ any more."
I disagree with the idea that that small, simple classes are a bad idea. I find the greatest thing about classes is that it allows one to carefully control state much better than without classes. Functional programming is correct when it says that state causes many bugs, yet I find that classes are much more effective at controlling and isolating state (at least if you try to avoid abusing them. In particular, I intensely disagree with your dismissal of classes with only one or two state variables. I find that those classes are usually the best written since they manage state very carefully and are the most focused in what they do rather than trying to provide everything and turn into a god class.
This!
@@masynchin Yeah, but in Python everything is an object so you don't need to write class to make objects you can use dictionaries, function decorators, or closures (lambda and def...nonlocal is nice at this).
@@aoeu256 But if you use lambda and nonlocal, you're code is going to be incomprehensible
It all comes down to using your judgement to arrive at a balance between all the tools and concepts that are available to you. I didn't like his implementation of Conway's game of life because I prefer code that I can read and understand at a glance. Based on my interpretation of the Zen of Python (and equivalent ideals in other languages) his approach is difficult to understand.
You need to learn to read code better if you think that game of life was hard to read. It was dead simple. Far simpler than having to refer to multiple classes and methods which continue on for pages and pages.
+Kaleb Sagehorn Your complaint is invalid because this is information you need before you can even start implementing. If you don't know the requirements of the software, you should learn about those before trying to mess with the implementation.
+Danny C "Code" is an uncountable noun. "Codes" (when referring to code in the programming sense) is incorrect grammar. Yes, this is a pet peeve of mine.
Also, you can't read any code when there's no code to read and you're developing a product from scratch. So anyone implementing something new instead of maintaining an existing code base.
Understanding your actual requirements is not a luxury. It's a necessity to avoid building the wrong thing. Building code without doing so is sheer and utter incompetence. Sure, for a less defined problem, you'll flush out some parts of requirements as you go; even then, you darn well better have _some_ idea what they are up front. But GOL is not that. We're dealing with a very small, very well known, well documented, not that hard to figure out problem. There is literally no excuse for not looking into it before trying to implement it or understand an implementation of it. We don't need an Enterprise Fizz Buzz here.
Also, "real software engineers" do a lot of stupid things and produce a lot of unmaintainable, overly complex code. Ever read Daily Worse than Failure? Anyway, simplicity is golden. Over complicating the system does not help you or anyone else.
Show me where I can plug a debug script into his GOL implementation, then we'll see about how his way is "so much better".
The fact that he used a generator is a bit unusual indeed.
Maybe I am wrong, but he does not seem to have a vast experience in programming complex systems. When you develop a library you want to establish some interfaces. You may also want your code to allow for changing behavior for many different reasons - one is for injecting mock-up implementations. You can do that using classes. What if you care about specific types of exceptions and do not want to rely only on exception's messages, but on their actual types? You derive your own exceptions and watch out for them specifically (this is what one of the people from the audience mentioned).
What he said applies mainly to some small applications development, which you may not want to extend much in future. Or maybe I have been in OO world just for too long..;)
I agree, he's playing fast and loose with his code. It's not too bad since he has a small product in a small company, but if it was a big system I'd be very skeptical about the product.
***** size isn't what I was saying matters, I just said on a small scale you can easily manage it, but on a large scale I doubt it would be as reliable.
I agree many design patterns were just used to justify solving a difficult problem in an ugly way and get away with it. ;)
But nowadays, C++, C# and Java(Script) support many functional concepts (like map/reduce/anonymous functions etc.) and have been adapting syntactic sugar concepts from everywhere (for example string interpolation).
In my opinion, these functional extensions combined with dependency injection lead to that the only right way to write OO code today is to have classes wich are 'services' (functions) and objects that contain state. 'services' use dependency injection and aggregation (i.e. no inheritance), state objects can still use inheritance if it makes sense. Imho, this produces very maintainable, testable, decoupled (mockable) code which is what you need in large scale systems.
"...one is for injecting mock-up implementations. You can do that using classes." In Python, you can do it without classes, too. Look into how its mock library works; it patches anything bound to a name (modules, classes, methods) with a dummy before the test starts and then restores them at the end of the test. All name references are late bound in Python, even functions not attached to a class.
C# and Java don't support late binding of non-instance methods. This is one of the very few valid reasons to use classes pervasively in languages like them. But then using classes pervasively comes at a cost, namely now you have the new problem of instantiating all those instances. Python avoids that cost by providing the late binding directly. It is true that his advice is not completely applicable outside of Python, but this, in my opinion, reflects badly on the language design rather than his advice.
"You derive your own exceptions and watch out for them specifically (this is what one of the people from the audience mentioned)."
Jack isn't objecting to that. That's a case where you need exceptions. If you want to catch an error only in a specific case, then you need a specific exception to indicate it. If you're not catching an exception explicitly anywhere, though, there's usually no reason to create a custom type for it. I agree he could have articulated this point better.
"It does the exact same thing with fewer lines"
But 'fewer lines' is not a metric or goal that matters at all.
Is it more readable or easier to maintain? Not necessarily.
Does it execute quicker or with less resources? Not necessarily.
Is it faster to write? Not necessarily.
Less lines of boilerplate is the point: boilerplate dilutes the code and when you look at it, it’s harder to comprehend. It’s the same thing with excessive vertical white space and silly “function start” comments that harken from COBOL days.
There’s a big open source project, with proprietary roots, where the coding rule proudly states that all functions and methods must be preceded by a 4-line comment (at minimum), where said comment has two horizontal lines built out of “=“ characters, one line that repeats the name of the function, and the final line that states the purpose, and 95% of those lines regurgitate either the action implied by the name of the function, or describe the purpose such that it doesn’t add anything to what you read in the body of the function itself. Those 95% are out of a sample of a 1000, and I did do it carefully.
Said project also has thousands of source files that declare or define short classes that are 5-10 lines long. It’s a C++ project and this is nonsense: entire subdirectories of “modules”, each with a multitude of files, could be often boiled down to a single header file, since the methods are either getters/setters or defaults. It’s nuts. And people claim that this is “discipline” - yeah, in self-flagellation. I have a general rule that source files shorter than 250-500 lines should be viewed with suspicion, as are sources over 2000 lines. Exceptions to those rules of thumb arise, but infrequently. Short files with nothing that boilerplate should be burninated with gusto, and the heads of the projects such files comprise viewed with suitable suspicion.
Good comments should describe the purpose and must not regurgitate the obvious. Good classes introduce abstractions that are helpful, that improve the understanding. Having a base class just so that at some point in the future we may change the underlying container is silly. Never mind that the container may need to be changed only on a few derived classes - as might reasonably be expected with the mentioned descendants of the Flow class.
Its not just fewer lines of code all of the code to do the tasks aren't spread out.
A great talk.. Thanks a lot for sharing .
Actually, the fact that you have to create exceptions (most of the times) is because that would make it easier for documentation, when you have to create a document with all error cases with their respective error message, it is easier to create a package for exceptions only and have a custom exception for each error possible, also, OOP is on developer's option, Django framework (for example) is full of classes, and you actually follow MVC pattern which is an OOP pattern, and people still complain, I just don't see why, I mean, it's not everyone else's fault if your co-workers doesn't know when to write a class or not (or even how to do it properly), just saying..
"Separation of concerns" existed even before the notion of OOP even "structured programming".
No, history started in 2005. (Don't mention the structured and recursive Algol with nested scopes from 1960, or the object oriented Simula from 1967. That's the Jura age, after all.)
@@herrbonk3635 Well, the only answer possible here is a quote from Santayana's The Life or Reason: "Progress, far from consisting in change, depends on retentiveness. When change is absolute there remains no being to improve and no direction is set for possible improvement: and when experience is not retained, as among savages, infancy is perpetual. Those who cannot remember the past are condemned to repeat it."
Shit code is not an argument against using classes. It is an argument against shit code. It's nice to now and then be reminded to not write shitty code though. Thanks for the examples.
This is a great talk. Part of me died a little bit inside though when he says he wanted to use a URLShortener and in order to do so he had to go away and read 10K lines of code. He opens with the quote "don't do hard things in the first place" 🤷🏼♂ also, if he reads the 10K, does he have to read the code of whatever libs / dependency that is using et al?
the main problem in this industry is that we have less and less coders, and more and more scripters using others code. So basically, this isn t going to be any better.
AMEN u understood the deceiving nature of a Python "Programmer"
you got a like by me.
On the plus side, most of the script kiddies stick to calling code rather than writing classes :P But we also have totally ridiculous things going on in the industry where something like PyTorch took years to get a stable C++ interface while having it for ages for Python (it is written in C++). Apparently ML people suck at real code so they putz about in Python while another group of programmers need to write the fast C++ code for them. And nonsense like how Julia goes around claiming super speed while pretty much all the code being run in Julia is calling C, C++, and Fortran. Being compiled, I'm sure Julia can be faster than Python, and maybe it could be faster in some edge cases (??), but they seem to pretend it is all Julia when anyone that looks at the actually packages in use finds things like the Sundials code for differential equation solving... etc... Hardly any Julia code is actually Julia code. It yet another glue language. We can argue about what sorts of glue languages are better than others, but maybe it is time we just stop serving things up for script kiddies and make C, C++, and Fortran 1st class programming languages again. That is, if you're writing a library in one of these, give it a stable interface to its own language before you do for the popular flavor of the day glue language. And document it for goodness sake. It's incredibly irritating to see how poor the PyTorch C++ documentation is compared with their Python documentation. And I'm picking on PyTorch a bit here, but at least they've made some progress, now having a stable C++ API. TensorFlow still doesn't, apparently because they did some stupid crap where it was mostly C++ but then they did the autograd Python or something... just really dumb nonsense.
@@zvxcvxcz can't agree more. Man itts everywhere. At least Apple got serious about swift and c++ but man. Everything else is just layers of nonsense. Take flutter for example. The whole framework runs 100 times slower than it should in c and has no state management.
@@zvxcvxcz and regarding ml. Once u get deep into it it's just some stats management using simple functions like sigmoids.i don't understand how come there's still almost nothing in c++ while everybody complains about ressources and performance
I see the idea as not optimizing your design beyond what is currently needed. You can make it a class later if you want to and you may often find that you never want to. So the problem is when you're trying to guess the future for some reason - trying to make an API that will account for all future needs.
Instead of making it for all needs, set it up in a way that it can change
This message was lost along the way
Or never discussed in the first place (ie university) or told its not important (agile and scrum consultants)
I'm not sure , but Python does NOT offer static classes, which are great way of ORGANIZING similar functions that do not require an instance.
I look at the file where the residing function exist as static classes in Python. Classes are great for organize a common DATA STRUCTURE... To say to stop using classes is a bit extreme...
+Zackery Fix just put those functions in their own module.
do NOT use static. static is a horrible way to store data and instances. Use parameters.
How does print glider, where glider looks like a 5x2 staggered array of ints, magically turn into circles in a moving grid (the advance function changes the contents of the array, not draw anything)? Unless print has been overridden with a custom screen rendering routine.
I was wondering how they were going to graph their raw data, too. Any suggestions? Anyone? Guess maybe i'll have to look at some other people's GOL programs to see how they like to graph things in Python. Maybe Turtle Graphics (my speed).
@@randmorf same issue. probably not the code. hope they included some source.
aaaaaand... Yep, the title is most definitely a bait.
No?
@@ishdx9374
>"Stop Writing Classes"
>The speaker acknowledges that classes are very useful tools and that people should use them
@@Kolyasisan Did you even watch the video? He tells that you shouldn't use classes when unneeded, there was only one piece where he shown good use of classes.
@@ishdx9374 exactly, and the title says "Stop Writing Classes" when in reality the talk is about not creating classes when unnecessary, when an obscene amount of them will result in a clutter. Seems like a bait to me.
@@Kolyasisan You are being too literal with the title. Read between the lines..
Glad someone said it: OOP in Python is a nightmare
typelessness was a terrible design choice in python
@@ipotrick6686 How come?
A more accurate statement would be "OOP is a nightmare".
Someone was thinking that way... And then Typescript rescued him.
In python, i only use classes to define complex entities or objects and hold their respective attribute data. Doing this it helps maintaining the code and reduces code repetition. Example: function overriding is repetition.
It's freakin' Gavin Belson!
The person who asked the first question about functools proves why you should uses classes whenever possible. Having access to data is the best reason to use classes. Functions have local variables that you have no access to, but with a class you can access all the local variables. Data science!
My understanding is that OO is chiefly about extensibility. Yeah, you could always make it extensible later but extension often happens in small increments, and for any given small change you are likely to make the extension in non extensible ways. By the time you wake up and realize your code should be in an extensible format all along, you'll have a lot to rewrite since all those small changes added up.
OOP Code which uses Classes and Inheritance is usually some of the least extensible code I've ever seen.
The only thing you want to allow in OOP if you want extensibility is Interfaces.
Sadly most Java Programmers I know seem to be unaware such a concept exists, using abstract base classes even where it's equivalent to an interface.
OOP in general tends to overspecify and reinvent... All the things constantly. Even their own terms. Look at the famous "strategy pattern". It sure is great, I agree.
Now look at how an interface is meant to be used.
Oops. Thats the same fucking thing. Maybe just learn how to use a fucking interface before coming up with new design patterns.
@@9SMTM6 there is a ton of cargo cult practices in the industry
Man the guy seemed nervous at times. But sometimes having a point (and some examples so bad they're funny) is all you need to make a talk great.
At a time a programmer realizes he does not need classes, it's too late: he is a team leader, he has to support his reputation of a "man who masters OOP", and so on... On another side is an effective code, but a complete loneliness. This scares.
I like using classes, so I watched the video with an open mind, to see what could be wrong with that. I found the game of life example very enlightening because I just hate reading the example without the classes, I have to read line by line and be very focused, with the classes I could get a grasp of the situation very fast even without reading the details.
I wonder if people who like functions better actually understand the function example with more ease?
Maybe people prefer classes or function because of the way they think?
I think you probably find the game of life class-less version difficult to read because you aren't familiar with functional programming. If you learn a functional programming language like Haskell, that code will make more sense to you.
I think it has more to do with how confortable you are with certain concepts. His function used map, itertools.chain, set, and set union, sum, and generators. To understand the the class based version you have to understand tuples and dictionaries.
It is about what you are familiar with. If you had more time to unpack it, it would make more sense
@@johngibson4874 minimal python experience here. typed the code in IDLE, all I got is printed line of the glider. What am I missing?
@@UnleadedPadyak The code in the example only prints out the glider once after 1000 iterations have passed. If you wanted to see it, you would need to have a way of printing out the grid, and print the glider after each step.
The key takeaway was using functions and appropriate data structures to express Conway's Game of Life as directly as possible.
The game of life example in OOP makes no sense because the rules of processing the game of life have to do with several objects (neighbors) interacting getting data from the board. Swapping out cell with other cell makes no sense because that cell would have to interact with other cells, and functions are objects in Python so instead needing to build lots of classes you could split the code into higher order functions.
OKAY IMMA STOP WRITING CLASSES IN JAVA THANK YOU
Better yet, stop writing Java.
@@edwin-jq4dp I guess Google isn't a serious company then.
@@WhateverYouLove
> No serious company writes anything serious in Python *apart from machine learning.*
@@edwin-jq4dp Google uses Python not just for machine learning, but for almost everything that isn't ultra performance-critical (in which case they'll use a bit of C++).
www.quora.com/What-is-Python-used-for-at-Google
The very site you're writing on (TH-cam) is written in Python.
@@WhateverYouLove Djangooo
Fast forward to 2022.... we still use Class for most cases... and its pain in the ass.