Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My favorite example of really bad abstraction is add/edit crammed into single popup/model. You know edit is basically a copy paste of add so "ding ding ding here goes DRY!" in a junior mind. But quickly enough it shows up that some properties can be set in add, whereas in edit they have to be read only. Quite often you get also other business rules that can be applied only on edit or make sense only when adding new entity. But when you create first version they look a lot like the same code that should be reused.

For me this is really good example of how similar looking code is not the same because it has different use case.



> But quickly enough it shows up that some properties can be set in add, whereas in edit they have to be read only.

So? Just put in some conditionals.

What is the alternative? Duplicate most of the code with minor, non-explicit differences? What's the benefit? You just moved complexity around, you didn't get rid of it.

The drawback is that now anything you have to add, you have to add and maintain it in two places. And since your "add" and "edit" are probably 90% the same, it's going to happen 90% of the time. It's very annoying during development and you're likely to fuck it up at some point.


This is a good example of how this overall topic gets reduced to "How much abstraction?" instead of "In what ways should something be abstracted?"

Obviously an Add/Edit field are operating on the same record in a hypothetical database, so it makes little sense to duplicate the model.

On the other hand, if the conditionals within the abstracted version become too complex or keep referencing some notion of a mode of operation (like, ` if type(self) == EditType && last_name != null` lines of thinking), that is sometimes another type of smell.

But say you make some kind of abstract base class that validates all fields in memory before committing to the database, and then place all of your checking logic in a validate() method. That sounds like pretty clean abstractions to me.

And moreover, this is probably provided by an ORM system and documented by that system anyway--so that's a publicly documented and likely very common abstraction that you see even between different ORMs. That, I think, is the very best kind of abstraction, at least assuming you are already working in such an environment as a high-level language and ORM. Making raw SQL queries from C programs still contain their own levels of abstractions of course without buying whole sale into the many-layered abstraction that is a web framework or something.

This question becomes more important when you aren't just updating a database though. If you're writing some novel method with a very detailed algorithm, over abstraction through OOP can really obscure the algorithm. In such a case, I try to identify logical tangents within the algorithm, and prune/abstract them away into some property or function call, but retain a single function for the main algorithm itself.

The main algorithm gets its definition moved to the base class, and the logical tangents get some kind of stub/virtual method thingy in the base class so that they have to be defined by subclasses. The more nested tangents are frequently where detailed differences between use cases emerge, which makes logical sense. It's not just that it's abstract, but the logic is categorically separated.

It's a very general pattern supported by many languages, so you see it all over the place. That organization and consistency in itself helps you to understand new code. In that way, it also becomes a kind of "idiom" which in a sense is one more layer of abstraction, helping you to manage complexity.

As a counter of that, you see code where `a + x * y - b` becomes self.minus(self.xy_add(a), b). More abstract, but not more logical; not categorically separating; not conforming to common idioms; obscuring the algorithm; and so on...

And then there is performance! Let's not talk about the performance of runtime abstractions.


I mean, aren’t we just bikeshedding inheritance at this point?


Each to his own. If I found that a junior had created two separate popups, one for add and one for edit, I'd want to look into the code with them to understand if that was a good choice, because usually it wouldn't be for anything with more that one or two properties.


I just had a case of this last week in a web-app I’m writing.

In the frontend code I decided to use an abstraction and parametrization in the backend code I kept the logic separated.

It really depends on context. Specifically on the layer you are operating on.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: