5 ms·
So much over-engineering comes from the fear of changing already written code. Some programmers, I believe, have the impression that changing code any reason o
by wvenable 7y ago
So much over-engineering comes from the fear of changing already written code. Some programmers, I believe, have the impression that changing code any reason other than new features or requirements is wasted effort. So they try and build out all possibilities they can imagine first so they won't have to change it later.
If you eventually need that interface, you can change your existing code to use it. Making that change is relatively easy compared to maintaining a bunch of code that isn't needed. But still I find it hard for some programmers to get past that mentality.
- sna1l 7y ago+1 to this In my own progression as an engineer who writes Java, I read Clean Architecture by Robert Martin which lead to AbstractFactory(s) and interfaces up the wazoo. The reasoning would always be "this can change!" It definitely took me some time to understand that not everything will change, and if it does change, having some extra work for simplicity is a reasonable tradeoff sometimes. In general, knowing when to utilize OO design patterns takes time and experience.
- pscanf 7y ago> The reasoning would always be "this can change!" As I understood Uncle Bob's argument for using interfaces though, the main benefit is not supporting alternative implementations, but rather aiding in the enforcement of the Dependency Rule[1] and of the Single Responsibility Principle[2]. Interfaces make the relation between components explicit in two ways: - they make it clear what depends on what - they make it clear what are the responsibilities of the components on either side of the interface So aside from the fact that it might make it easier in the future to swap implementations, it first makes it easier when writing the code to decide how to organize its components (i.e. laying out its architecture). Of course I agree with you that interfaces can definitely be abused, and can make code more indirect and difficult to read. I just wanted to point out what I think is Uncle Bob's point. :) [1] https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html#the-dependency-rule https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-a... [2] https://en.wikipedia.org/wiki/Single_responsibility_principle https://en.wikipedia.org/wiki/Single_responsibility_principl...
- Sohcahtoa82 7y ago> Single Responsibility Principle Too many Java programmers take the SRE too far, IMO. If you have a class that only has a single function, then it probably should be a function, not a whole class. To give an example that I've seen, I've seen code with classes named UserGetter, UserCreator, UserDeleter, etc. All of these should have just been bundled up into a single User class.
- GordonS 7y agoI see a lot of interface abuse with C# too. My hope is that C#'s new default interface implementations will put an end to this mess.
- apta 7y agoJava also now has default interface implementations.
- cageface 7y agoThis is taken to a pathological degree in the VIPER architecture. Every thing is decomposed and wrapped in and interface. Unfortunately this has gained some popularity in the iOS world. It makes code so much harder to follow and maintain.
- dep_b 7y agoNever used VIPER. MVVM with navigation flows and layout handlers works well enough.
- jswizzy 7y agoMVI is the latest evolution of MVVM. It's basically MVVM with Reactive programming.
- dep_b 7y agoI do use Reactive (ReactiveKit) a lot now to prepare for Combine
- cageface 7y agoAppKit is pretty deeply MVC. I generally prefer to just work with the underlying APIs than try to invent a new paradigm on top of them. With VC containment I feel like I have enough abstraction power already.
- dep_b 7y agoIn my case the "Flows" are usually UINavigationControllers hidden behind a protocol. I tend to chop up my UI's really deeply into VC's but most of them get a VM because I like my VC's really, really small.
- mumblemumble 7y agoSimilar progression here. It took a long time before I realized that a lot of the changeability that come with writing aggressively SOLID code is actually a self-fulfilling prophecy: Some tightly intertwined chain of steps that might have been implemented as five consecutive (albeit tightly coupled) statements gets blown out into 10 or 15 modules and abstractions spread across as many files. All this added complexity was invariably designed to make it easy to change the code in a way that is not actually how you ended up needing to change it, so the end result is that it increased the difficulty of changing things: Instead of editing 5 lines, you now need to edit 10 files. And, since the logic is spread across 10 files whose members are, thanks to the magic of Java's access control facilities, all public, and whose connections to other parts of the codebase are all, thanks to the magic of dependency injection, loose (read: not explicit), it's hard to even understand the scope of impact of those changes without relying extensively on an IDE. I've since taken a big turn back toward procedural programming. Object-oriented and functional techniques have their place (and the best procedural languages will let you use both), and I've learned a lot from working in both paradigms. But most of what I learned is that no amount of abstraction can replace the KISS principle.
- GordonS 7y agoI've gone through the same learning process, and I've seen it happen with numerous devs - they go through a cargo-culting stage, where they see abstractions and patterns espoused by people they respect, only to later come to the conclusion that it makes for code that is anything but clear. Abstractions are not evil, but it takes experience to use just enough abstraction.
- ieatpies 7y agoThe cost of refactoring is dependent on the scale/stage of the project
- marcus_holmes 7y agoI catch myself doing this all the time. I'm never going to move this project off Postgres, so why the hell have I created an interface to abstract the database?
- pm90 7y agoUnit testing?
- yawgmoth 7y agoNot sure about Java, but at least in C# there are clear advantages to using interfaces over concrete classes when using Moq.
- GordonS 7y agoInterfaces are not the only option - you can also mark methods as virtual. But overuse of mocking is a very big problem in a lot of codebases. Often I look at a test, and all it seems to do is setup mocks, such that I'm not sure if anything is actually being tested! My hope is that C#'s new default interface implementations feature will put an end to this mess.
- tootie 7y agoAs mentioned elsewhere, refactoring a concrete class into an interface is actually pretty trivial using an IDE. At least within an codebase. The only time to really be diligent about interface design is if you're designing an API.
- acidictadpole 7y agoI've been in the workforce for nearly 10 years and I still have this issue when starting a new project. It takes a conscious effort to just move forward, and it still leaves a lingering thought in my mind about what I'm doing wrong while building exactly what I need.
- potta_coffee 7y agoThis is my main complaint with OOP. It's not a feature of OOP explicitly but I've only seen it in OOP codebases. And the most complicated, awful, snaggletoothed codebases I've had to unravel were all like this - heavily laden with abstractions that weren't really necessary.
- wvenable 7y agoOOP exists exactly to solve problems where abstraction is appropriate. So obviously it's going to be implicated in cases of over-abstraction. It's kind of like how cars are implicated in traffic problems. Everywhere you have heavy traffic, you'll find cars.
- potta_coffee 7y agoSo do you not believe that OOP practices can be abused?
- wvenable 7y agoI actually said the opposite. Any tool of sufficient power is going to more abused than a tool with less power. You can do more damage with a backhoe than a shovel. But the fact that you can do more damage with a backhoe than a shovel doesn't mean there is anything wrong with a backhoe or anything good about shovel. Same is true of OOP.
- potta_coffee 7y agoGot it. I don't have an issue with OOP, just the ways I've seen it abused, mostly by intermediate programmers that are too clever for their own good.
- bitbuilder 7y agoCouldn't agree more, and I feel like I've spent half my career tilting at windmills trying to get other engineers to use less abstraction, instead of more. I can't count the number of C#/Java projects I've walked into where it felt like I had to drill down through a dozen layers of abstraction just to find code that actually does something. Hundreds (thousands?) of files that contain nothing but autogenerated boilerplate crap. Layers upon layers of boilerplate, "just in case we need to swap something out later!" No. I promise you, you won't. And if you do, I promise you things aren't as loosely coupled as you think they are. You're going to have to do a bunch of rewriting anyway. Also, 9 times out of 10, by the time you realize some seemingly interchangeable piece of your architecture needs to be replaced, your team will be chomping at the bit to blow the whole thing up and rewrite from the ground up anyway. In the meantime, having a simple codebase that people actually enjoy working in will make everyone's job so much easier. And fun.
- minblaster 7y agoYAGNI was coined for a reason.