tag:blogger.com,1999:blog-7821856652257554779.post829030656759083362..comments2025-09-20T09:27:07.510+02:00Comments on Andrzej on Software: Yes, Nick - class methods are evilAndrzej Krzywdahttp://www.blogger.com/profile/06399276063142826365noreply@blogger.comBlogger18125tag:blogger.com,1999:blog-7821856652257554779.post-32345419275265743962011-07-22T15:42:51.681+02:002011-07-22T15:42:51.681+02:00What's really wrong with class methods? I just...What's really wrong with class methods? I just see them as alternative initialization points, or an alternative to a separate Factory Class, they're not evil per se.<br /><br />"OO-purity" is not really a perfect measurement when you're using a mixed-paradigm language.<br /><br />I believe we should focus our energies on writing elegant implementations of class methods, not unelegant-but-by-the-books factories.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-25481919050176146192011-07-22T10:18:22.856+02:002011-07-22T10:18:22.856+02:00Although I like your point of view Andrzej, I also...Although I like your point of view Andrzej, I also think as Jeremy, that AR class methods are "special constructors". What's the difference between User.new and User.find(id)?<br /><br />Unless you always write something like Game.new_user, than ok - it makes sense :)Jan Dudulskihttps://www.blogger.com/profile/16925092071548166033noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-49313428353555184652011-07-21T20:25:55.703+02:002011-07-21T20:25:55.703+02:00I fail to see why you would want to create a manag...I fail to see why you would want to create a manager object. You're adding overhead where it is just not needed. When looking at AR its better to think of the class methods as specialized constructors, you get an object, or collection of objects back. It is a clean way to mimic a repository pattern. Your suggestion really just adds extra cost to the system, at what real benefit?Jeremynoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-26093419754586297932011-07-21T19:53:45.868+02:002011-07-21T19:53:45.868+02:00Test:
"I don't see what is to be gained ...Test:<br /><br />"I don't see what is to be gained by trying to introduce a factory/builder layer into your app just to avoid calling a class method."<br /><br />It's a matter of personal approach to clean code, object orientation and readability. I prefer shop.products because it makes sense to me and because this is how I view the business domain - there are products in the shop.<br /><br />Other people may prefer Product.all because they think of it in a more global way or because what they are modeling is not the business domain but the database below.<br /><br />Similarly, I prefer shop.add_product as way of, well adding new product to the shop. You may prefer Product.create(..)<br /><br />They way I was taught object oriented programming and the way I practice it is that when a noun appears very often in the conversation with the client or in the documentation then it should be a sign that there must be an object or class representing this concept.<br /><br />When I work on e-commerce projects then the noun Shop appears very often. Makes sense to have a class from it. When I talked to the customers the concept of adding a product to the shop appeared quite frequently, so shop.add_product(..) makes sense to me. <br /><br />I use OOP to help me represent the business domain in the source code. The better I do it, the less mistakes I may have.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-56818502620049380402011-07-21T17:42:38.839+02:002011-07-21T17:42:38.839+02:00I don't see what is to be gained by trying to ...I don't see what is to be gained by trying to introduce a factory/builder layer into your app just to avoid calling a class method.<br /><br />First of all, classes are objects so class methods really are instance methods on an object. There really isn't anything special about them other than that the classes themselves are singletons.<br /><br />The way I like to look at it is that the User ActiveRecord class is the factory/builder for creating User objects and a pretty logical place to put the necessary code. Ultimately the code needs to live in some method somewhere.Brian Durandhttps://www.blogger.com/profile/08696901538807006156noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-20054548656972780372011-07-21T13:37:07.347+02:002011-07-21T13:37:07.347+02:00Alex:
"Actualy I like very much ActiveRecord...Alex:<br /><br />"Actualy I like very much ActiveRecord approach. It's convenient to think of AR classes as database tables. It makes working with relational DB more transparent and OO."<br /><br />Thanks for your comment. Yes, exactly, AR is perfect for working with relational DBs and make them a little more OOP. <br /><br />In my opinion AR doesn't scale very well (in terms of the project size, not the speed). Its object orientation is limited and doesn't let you design you project easily. Things like DCI should help here, though.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-50569032498405487932011-07-21T13:34:02.211+02:002011-07-21T13:34:02.211+02:00Marcin:
What's the difference between Product...Marcin:<br /><br />What's the difference between Product.objects.get(id=14) and Product.find(14). Is it the same?<br /><br />The idea of a manager object sounds good. Need to read more about it.<br /><br />As for madeleine, it's not very mature and stable, be careful and don't use it in production :)Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-10003179649714638372011-07-21T13:25:45.001+02:002011-07-21T13:25:45.001+02:00For me Django looks more like this example Shop.pr...For me Django looks more like this example Shop.products, you have a Product.objects.get(id=14). And with all those filters and so one it's a very nice approach for me. This objects methods are served by special Manager object, it recalls me something like EntityManager in JPA. <br />Madeleine sound quite interesting, I'm gonna try it soon - thanks for a tip ;)Marcin Olichwirowiczhttps://www.blogger.com/profile/10938787272851880477noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-30586559953108578462011-07-21T13:13:24.275+02:002011-07-21T13:13:24.275+02:00Actualy I like very much ActiveRecord approach. It...Actualy I like very much ActiveRecord approach. It's convenient to think of AR classes as database tables. It makes working with relational DB more transparent and OO.<br />Thanks for all your posts btw.Alex Radhosehttp://lottestyle.denoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-47966513679795837322011-07-20T23:31:29.640+02:002011-07-20T23:31:29.640+02:00Marcin:
I never used Django, but from the link I ...Marcin:<br /><br />I never used Django, but from the link I can't see why it could be better. It's similar to ActiveRecord.<br /><br />As for the real ORM, I haven't found anything really good in my career. I think that the problem is inherent to ORM, you just can't do super-nice OOP with relational databases behind your app.<br /><br />I was most happy when I was using Prevayler with Java, and now when I experiment with Madeleine with Rails. Those are not real databases, you just keep objects in RAM and serialize them to the disk.<br /><br />Once you stop using class methods then even ActiveRecord can give you some OOP background.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-27651386014465160512011-07-20T23:14:44.762+02:002011-07-20T23:14:44.762+02:00So from the other side... Which ORMs could you guy...So from the other side... Which ORMs could you guys recommend as almost ideal in terms of pure OOP way of thinking? I was only dealing with PHP, Java, Python and Ruby ORMs. <br />Based on experience, in my opinion - Django has the most useful ORM with nice, object concept (but I didn't dive into the core so correct me if I'm wrong ;)). Samples of quering in Django - https://docs.djangoproject.com/en/dev/topics/db/queries/Marcin Olichwirowiczhttps://www.blogger.com/profile/10938787272851880477noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-10465280023322027142011-07-20T22:53:15.476+02:002011-07-20T22:53:15.476+02:00classes is not "global". constants is ...classes is not "global". constants is globalmetaclassnoreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-60891376533001353212011-07-20T22:24:47.909+02:002011-07-20T22:24:47.909+02:00Yep, I agree. Class methods on Rails models are al...Yep, I agree. Class methods on Rails models are almost always an indication that someone has been thinking in SQL instead of in objects.Avdi Grimmhttps://www.blogger.com/profile/10993900556434566800noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-58915987986078673482011-07-20T21:09:03.671+02:002011-07-20T21:09:03.671+02:00Bartosz:
"I'd say active record pattern ...Bartosz:<br /><br />"I'd say active record pattern is a different story and doesn't really represent the rest of OOP in ruby world."<br /><br />When you work with Rails and ActiveRecord, then you have to use the ActiveRecord-style OOP which to me is just sql but with nicer DSL.<br /><br />Just to be clear, I prefer ActiveRecord than using SQL directly. I'd love if there was a way of using better OOP with Rails, but the ideas presented in the post is the best I could find. I know it's not ideal.<br /><br />I think that it also happens to more experienced developers that after a few years of ActiveRecord programming you're almost unable to do proper OOP, without globals, static methods etc.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-65656643364416236682011-07-20T21:00:12.810+02:002011-07-20T21:00:12.810+02:00Nice examples 1 and 2 of trying to escape AR patte...Nice examples 1 and 2 of trying to escape AR pattern to be more OO. <br />Although, fighting rails conventions usually ends up bad, maybe these techniques don't fight them as much. Too early to judge for me, without more experimenting with them.Bartosz Blimkehttps://www.blogger.com/profile/08810234693165301502noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-49704742388423944652011-07-20T20:55:28.201+02:002011-07-20T20:55:28.201+02:00Hey Marcin, thanks for your comment!
I agree, the...Hey Marcin, thanks for your comment!<br /><br />I agree, the second way is not really nice, however it doesn't have the performance impact the first one has.<br /><br />Indeed, that's kind of a facade pattern here. I simply prefer the object-oriented thinking. <br /><br />To me shop.products is clearer that Product.all and is worth the additional layer. It simplifies designing and thinking what should belong where - just think of it as modeling the domain with objects.Andrzej Krzywdahttps://www.blogger.com/profile/06399276063142826365noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-71410743732284927192011-07-20T20:46:20.315+02:002011-07-20T20:46:20.315+02:00Class methods are sometimes misused but I wouldn&#...Class methods are sometimes misused but I wouldn't say they are evil.<br />Definitely not like static methods in Java were evil.<br /><br />I've seen many times (and possibly even used sometime) class objects used as singletons and class methods used as singleton methods. Not perfect in terms of OOP, but not as painful either (as it was in Java :). Still testable and maintainable.<br />As long as a singleton object doesn't mix multiple responsibilities.<br /><br />I'd say active record pattern is a different story and doesn't really represent the rest of OOP in ruby world. Maybe that's why some ruby programmers, having mostly experience with AR code, complain about class methods so much.<br />As you mentioned, in AR a class object represents a sql table, while and instance represents a row in that table. <br />This way, AR class fullfils at least responsibilities of a factory and of a collection. This often leads programmers to put all other methods related to managing objects of a class inside a class.<br />This end up with massive AR classes with dozens of methods.<br />Rails convention of "thin controllers, fat methods" multiplies this effect when (and actually very often) misunderstood.<br /><br />This is often done by new programmers who started their OOP career with Rails, without having good OOP experience before.<br /><br />If you consider evil as "in danger of being used by inexperienced OO programmer" to write evil code, then sure, it's evil :)Bartosz Blimkehttps://www.blogger.com/profile/08810234693165301502noreply@blogger.comtag:blogger.com,1999:blog-7821856652257554779.post-5526243585168042212011-07-20T20:25:47.495+02:002011-07-20T20:25:47.495+02:00Let me put some of my thoughts here if you don'...Let me put some of my thoughts here if you don't mind.<br /><br />I completely don't get why your approach is better than using class methods. I'm trying to avoid using class methods as much as I can, but it does not look for me like a solution.<br /><br />Second way it's just a running away and hiding class method invocation into wrapper object. It does not solve problem with avoiding class method calls.<br /><br />First way is a bit better but...<br />game.find_user(4) is pretty similar to User.find(id). It does not changing my way of thinking to be more object-oriented than sql. It's just recall me a facade pattern.<br /><br />What is more I think User.find(id) is much more flexible when you have more than 100 tables with a lot of relations, data, millions users. Every additional join is not desirable then and having one entry point like 'game' object could be a pain. Especially when you have to just get Pet.find_by_user(id).<br /><br />But after all is a really cool discussion. Big kudos to both of you guys!Marcin Olichwirowiczhttps://www.blogger.com/profile/10938787272851880477noreply@blogger.com