5 ms·
Yeah, but "let the IDE handle it" is a perfectly valid way to code. When you want to run water to your house, you don't hire someone to design new pipes for
by aston 18y ago
Yeah, but "let the IDE handle it" is a perfectly valid way to code.
When you want to run water to your house, you don't hire someone to design new pipes for you; you use the ones pipe companies kick out. The boilerplate is just plumbing your IDE manufactures for you. The only difference between it and the magic that happens in dynamic languages with stuff like RoR is that boilerplate code is explicit rather than implicit. I prefer the former, truthfully, so I don't have to understand the whole stack to work on a small piece of the code.
- Zak 18y agoGood abstractions don't require you to understand the whole stack. Effective use of a function, for example requires you to know: * What the valid arguments are * What will be returned * What, if any side effects calling the function will cause * (sometimes) What resources the function will utilize Use of most other data types is simpler. Your framework or library should give you this information in the documentation. If your development environment is reasonably friendly, it will give you the arguments, and in many cases, you'll be able to guess the rest of it based on the function name. If you have to RTFS to figure out how to use your libraries, something is wrong. Institutionalizing that by always putting the source right in front of you is a Bad Thing.
- aston 18y agoI'm not arguing against abstraction. I'm arguing that explicitly wiring between components is better than implicit. To make this concrete, take the example of implementing getters for a class in Python. If my class has four fields class GetterDone: a = 1 b = 2 c = 3 d = 4 I can do something like this inside the class to implement getters: def get_a(self): return self.a def get_b(self): return self.b def get_c(self): return self.c def get_d(self): return self.d Or I can do something like this: def __getattr__(self, attr): if attr.startswith("get_"): return lambda: getattr(self, attr[4:]) raise AttributeError The latter does a good job of eliminating boilerplate, but at the cost of making it near impossible for me to find out how get_a() is implemented (assuming this was buried in a huge codebase).
- lisper 18y agoOr you can just realize that get_X is the Wrong Thing and you should just write GetterDoneInstance.X instead.
- aston 18y agoGreat job ignoring the substance. I thought it'd be better to come up with an unrealistic but simple example rather than to paste in the source for Pylons... Just play along and imagine a more complex world. If it makes you happier, pretend the getter is intended to return the string version of the numbers or some other operation that would make just using instance.a wrong.
- lisper 18y agoBut using instance.a is not wrong because you can override __getattr__. And if overriding __getattr__ is not the right thing then what you are writing is not a getter. Under no circumstances is it justified IMHO to write a get_X method. (And if your language doesn't let you override __getattr__ then you need a better language.) IMHO of course.
- DougBTX 18y agoAssuming you know the core Ruby library, would you call this explicit or implicit? class GetterDone attr_reader :a, :b, :c, :d end Rather than being a runtime attr.startswith check, this will generate actual "return self.foo" methods in the class. Think of this as generating code using a UI, except you record the minimal UI commands, rather than putting the full output into your source files. The commands themselves are still explicit, it's just that they contain only the interesting information with the minimum amount of boilerplate.
- aston 18y agoWhat you're talking about is essentially a syntax specifically for getters, I think (I don't know Ruby that well). I guess my general point about "too much magic" goes away when the magic is part of the language, just on semantics. That is, you don't know the language if you don't know what magic its syntax does.
- arockwell 18y agoIf the code is so simple that I can hit a button and have my IDE generate my code for me then I really question why I need to write the code in the first place. A simple example of this is generating getters/setters. Autogenerating the code works great 99% percent of the time. The problem comes in for that 1% case where a non-templated getter or setter is needed. That special case is easy to lose track of in the forest of automatically generated code. Groovy solves this problem by automatically generating all of the getters/setters for you, but if you need to you can still override the automatic definition with a specific implementation. I won't argue you with that too much magic can be a bad thing. However, for the code I typically generate with my IDE I really think I'm wasting time and bloating my code.
- DanWeinreb 18y agoExactly. If your IDE can just generate it, then why is it needed at all? And, as I said, it makes the code harder to read. You have to look over all the boilerplate and see if it's all exactly the usual boilerplate, or whether one or two methods in there were manually improved. If the IDE has to generate it, it means that the programming language is expressing your wishes at too low a level of abstraction, rather than more-directly reflecting what you were trying to say in the first place. So you have hit the nail precisely on the head.