76

Programming to an interface means that you should focus on what the code does, not how it is actually implemented. See Telastyn's answer to Understanding “programming to an interface”. Interface classes help to enforce this guideline, but this does not mean that you should never use concrete classes. I really like the zip code example: In 1963, the United ...


68

In your simple example, you know exactly the real type of the object on which you invoke the visitor and can therefore chose yourself the right visitor method: makeSoundVisitor.visitCat(cat); // You know that cat is a Cat makeSoundVisitor.visitDog(dog); // You know that dog is a Dog But what if you don't know the type of the object? For example ...


47

"Programming to an interface" does not require the language keyword interface. It means you care about the what promises the type provides about it's behaviour. You don't care how java.lang.String does all the things it does, only that you can write name = "aacceeggiikk"; age = 42; "Programming to an implementation" would be using reflection to get at the ...


31

This MainApp class is not per se a bad idea, but probably reinventing the wheel. Generally, you need one "central" component to orchestrate the whole idea of dependency injection. Also, you probably are better off with using a readymade solution (e.g. in Java a Weld container.) However, the services should not depend on MainApp, but on the other services ...


30

Saying that it is an anti-pattern to make public methods virtual or abstract because of the developer of a derived class that implements Method1 and overrides Method2 has to repeat the argument validation is mixing up cause and effect. It makes the assumption that every overrideable method requires a non-customizable argument validation. But it is ...


27

If I try to make a new method to handle B differently, it gets called out for code duplication. Not all code duplication is created equal. Say you have a method that takes two parameters and adds them together called total(). Say you have another one called add(). Their implementations look completely identical. Should they be merged into one method? NO!!! ...


27

I think the arguments presented in Eric Lippert's blog post from 2004 Why Are So Many Of The Framework Classes Sealed? apply to "final methods" (in the Java sense of that term) as well. Every time you write a method A (in a framework) which calls a non-final method B, A cannot rely on B on doing what it was originally doing any more, so A has to be designed ...


18

Very often, when you have a behavior where you cannot decide which of two objects should have it, that is because either the two objects should actually be one object or there is a third object missing. A great example is the classic "Bank account" that is so often used as an introduction to OO. In the typical example, balance is data and deposit is an ...


15

But I really don't see the point of that accept call. If you've got the visitor and the objects to be visited, why not just pass these objects directly to the visitor and avoid the indirection? Christophe's answer is on point, I just want to expand on that. Not knowing the runtime type of the object is actually an assumption of the Visitor pattern. You can ...


13

Behaviour is decisions being made. State is decisions being remembered. When OOP people talk about behaviour what they mean is the gooey sticky part of the code base that has to be changed every time a business rule changes. Rather than state, what this is usually contrasted with is dry structural cerimonial code that exists mostly because the system or ...


12

You would prevent those misleading exceptions from bubbling up by catching them and converting them to a non-misleading exception. public class CustomizedFileManager : MyFileManager { protected override string DecorateFilename(string filename) { try { string decoratedFilename = base.DecorateFilename(filename); var ...


10

It's only a guideline Just as a concept like KISS is a guideline. If you follow the guideline to "program to an interface, not an implementation", you'd be violating the KISS principle. But by making a bunch of simple classes that repeat some code or actions, you'd be violating the DRY principle. There's no way to adhere to every single guideline, ...


10

However, some components need access to other components, there is one component that is needed for almost all other components. To solve this I used dependency injection, but this makes these components dependent on MainApp. It feels like MainApp just became a big mediator class for all components. Using MainApp as the Composition Root for Dependency ...


9

If the class is truly simplified to the point that it's just providing a controlled sequence to the operations, and the complexity of each operation is managed by the dependent classes, then I don't think there is a problem here to solve. If the sequence of operations for this process is truly 8 steps, then the constructor with 8 dependencies adequately ...


8

Actually, that last example is legitimate. Its probably an Adaptor. It could also be a Command, or a Facade, or .... There are cases where it makes good sense to encapsulate another implementation. Such as: offering an immutable version of a mutable object. The constructor could make a copy of a received B, and only expose/support immutable operations. ...


8

Your question seems to be based on a misunderstanding. Fowler does not "dislike temps" in general. Quite the opposite, he provided a specific refactoring for introducing such variables, he called it Extract Variable (a.k.a. "Introduce Explaining Variable") Of course, he also gave the inverse operation a name: Inline Variable From this I hope it gets ...


7

It is an advantage if you want to create a command processor for a specialized command type. E.g. you have an interface public interface IUndoableCommand : ICommand { void Undo(); } Now you can use it like this: public class UndoableCommandProcessor : ICommandProcessor<IUndoableCommand> { public void Process(IUndoableCommand command) { ...


7

The usual saying that we all read here and there is: All problems can be solved by adding another layer of abstraction. Well, this is not true ! Your example shows it. I’d therefore propose the slightly modified statement (feel free to reuse ;-) ): Every problem can be solved by using THE RIGHT level of abstraction. There are two different problems ...


7

Programming to an interface concerns objects, entities that can also have primitive-typed properties like boolean, int, BigDecimal and String, to name some. On that level programming to an interface no longer applies. There is an other principal however, that is based on the experience that primitive types are used where there should be a wrapper to a more ...


7

Essentially, it boils down to whether or not you can come up with a useful generalized interface for the call site(s), in a way that decouples parameter passing from the actual call - by encapsulating those parameters in the transform object and relying on polymorphism. You can do this if you can determine the parameters at creation time, but it may require ...


6

Doing it the way your colleague suggests does provide more flexibility to the implementor of the base class. But with it also comes more complexity which is typically not justified by the presumed benefits. Mind that the increased flexibility for the base class implementer comes at the expense of less flexibility to the overriding party. They get some ...


6

That's not quite right. I mean, you're right that explicitly declaring a method's inputs and outputs is very good. I think a language that actually declares it's types is better than your Python example even. But you're not right that OO's are implicit. In an OO world the reads and writes are constrained to the instance the method is on. And since data ...


6

The advantage of a 'pure' language of any paradigm is that you (ideally) don't have to keep reminding yourself to follow the paradigm since the language won't let you get anything done if you don't. For example, Java is a 'pure' structural language. Which is just a fancy way of saying it has no goto. Instead you have while, do while, for, break, and ...


6

To quote a colleague of mine - "You can spend hours designing a car on a computer, but at some point, the wheels actually have to touch the ground.". i.e. not everything can/should be abstracted out, at some point you need a concrete type. For your class with your zipcode, the question really should be what is a zipcode (in terms of your application)? ...


6

Is there a name for this pattern? Let's start with this question as the its name gives a succinct answer to your more general question. This is known as the Bastard Injection (Anti) Pattern. Unhelpfully, the term "poor man's DI" is also sometimes used to describe it, despite that term also commonly being used to describe pure/vanilla DI. Unsurprisingly, ...


6

These are using these terms in a slightly different way, but they are trying to convey similar underlying ideas. Here's a quote from the book you referenced (emphasis mine): Going back to the ShoppingBasket example, you would expect this class to have responsibilities such as add item to basket; remove item from basket; show items ...


6

There is a frequent confusion between having only one and must absolutely have only one. While the latter certainly requires a singleton, the former only requires some discipline to create a configuration object and inject it where it is used. If you think that your configuration object must absolutely exist only once, it might probably be because you use a ...


6

It feels like a good number of things are missing, to be honest. A Team has many Players. A Match is played between two Teams. A Season is composed of many Matches. A Season is managed by a SportsAssociation (think: National Basketball League [USA], FIFA, etc...) A SportsAssociation compiles a Team's SeasonRecord A SeasonRecord references a Team and a list ...


6

Whenever you have tightly coupled objects with circular dependencies, you have one of three cases (in an order of likelihood that I just pulled out of thin air, but sounds plausible): You are missing an object, and the two objects are actually three objects. The two objects are actually one object. The business domain you are modeling is indeed circular, ...


5

You catch the exception and re-interpret it. public class CustomizedFileManager : MyFileManager { protected override string DecorateFilename(string filename) { string decoratedFilename = base.DecorateFilename(filename); try { var allowedNames = File.ReadAllLines("ListOfAllowedFilenames.txt"); } catch (...


Only top voted, non community-wiki answers of a minimum length are eligible