161

In such cases, it is best to use the type system of your language to help you with proper initialization. How can we prevent a FooManager from being used without being initialized? By preventing a FooManager from being created without the necessary information to properly initialize it. In particular, all initialization is the responsibility of the ...


151

Do not permit your class to be constructed without assigning a name.


113

One way to wrap your head around this is to imagine potential requirements changes in future projects and ask yourself what you will need to do to make them happen. For example: New business requirement: Users located in California get a special discount. Example of "good" change: I need to modify code in a class that computes discounts. ...


108

Frankly, I don't see the need for inheritance here. It doesn't make sense; Node is an ArrayList of Node? If this is just a recursive data structure, you would simply write something like: public class Node { public String item; public List<Node> children; } Which does make sense; node has a list of children or descendant nodes.


93

I could overload the constructor so that order [of the parameters] doesn't matter... But is that a good idea? No. Having different constructor overloads will have the opposite effect of what you are intending. The programmer coming after you expects different overloads to have different behavior, and will ask: "What sort of different behavior is being ...


79

The most effective and helpful way to prevent clients from "misusing" an object is by making it impossible. The simplest solution is to merge Initialize with the constructor. That way, the object will never be available for the client in the uninitialized state so the error is not possible. In case you cannot do the initialization in the constructor itself, ...


77

There is no need to have specific subclasses for every person. You're right, those should be instances instead. Goal of subclasses: to extend parent classes Subclasses are used to extend the functionality provided by the parent class. For example, you may have: A parent class Battery which can Power() something and can have a Voltage property, And a ...


75

The answer provided by DeadMG pretty much nails it, but let me phrase it a bit differently: Avoid having objects with invalid state. An object should be "whole" in the context of the task it fulfills. Or it should not exist. So if you want fluidity, use something like the Builder Pattern. Or anything else that is a separate reification of an object in ...


74

Practically speaking, responsibilities are bounded by those things that are likely to change. Thus, there's no scientific or formulaic way to arrive at what constitutes a responsibility, unfortunately. It's a judgement call. It's about what, in your experience, is likely to change. We tend to apply the language of the principle in a hyperbolic, literal, ...


67

In many cases, people use inheritance to provide a trait to a class. For example think of a Pegasus. With multiple inheritance you might be tempted to say the Pegasus extends Horse and Bird because you've classified the Bird as an animal with wings. However, Birds have other traits that Pegasi don't. For example, birds lay eggs, Pegasi have live birth. If ...


60

Is there something that I am not seeing here? Allowing multiple inheritence makes the rules about function overloads and virtual dispatch decidedly more tricky, as well as the language implementation around object layouts. These impact language designers/implementors quite a bit, and raise the already high bar to get a language done, stable and adopted. ...


59

The solution is to bundle up the parameters into composite types. Width and Height are conceptually related - they specify the dimensions of the enemy and will usually be needed together. They could be replaced with a Dimensions type, or perhaps a Rectangle type that also includes the position. On the other hand, it might make more sense to group position ...


57

The “horrible for memory” argument is entirely wrong, but it is an objectively “bad practice”. When you inherit from a class, you don't just inherit the fields and methods you are interested in. Instead, you inherit everything. Every method that it declares, even if it isn't useful for you. And most importantly, you also inherit all its contracts and ...


54

As others have mentioned, this isn't necessarily a bad practice, but you should pay attention that you're not breaking the layers' separation of concerns and passing layer-specific instances between layers. For instance: Database objects should never be passed up to higher layers. I've seen programs using .NET's DataAdapter class, a DB-access class, and ...


48

Calling a class method with some class variables is not necessarily bad. But doing so from outside the class is a very bad idea and suggests a fundamental flaw in your OO design, namely the absence of proper encapsulation: Any code using your class would need to know that len is the length of the array, and use it consistently. This goes against the ...


44

I'd say that this severly hinders your design space. Constructors are a great place to initialize and validate parameters passed in. If you can no longer use them for that, then initialization, state handling (or plain out denying constructor of "broken" objects) becomes a lot harder and partially impossible. For example, if every Foo object needs a ...


40

Prior to generics in .NET, it was common practice to create 'typed' collections so you would have class CarCollection etc for every type you needed to group. In .NET 2.0 with the introduction of Generics, a new class List<T> was introduced which saves you having to create CarCollection etc as you can create List<Car>. Most of the time, you will ...


39

I would normally just check for intiialisation and throw (say) an IllegalStateException if you try and use it whilst not initialised. However, if you want to be compile-time safe (and that is laudable and preferable), why not treat the initialisation as a factory method returning a constructed and initialised object e.g. ComponentBuilder builder = new ...


35

If the class has no state, you could consider turning it into a function or static method depending on your language.


33

There are may things with the class that I would do differently, but to answer the direct question, my answer would be yes, it is a bad idea My main reason for this is that you have no control over what is passed to the add function. Sure you hope it is one of the member arrays, but what happens if someone passes in a different array that has a smaller ...


32

The answer implied by the concept of classes is "no". Either whatever action, data or relation you're handling is part of all subclasses - then it should be handled in the superclass without checking the actual type. Or it applies only to some subclasses - then you'd have to perform run-time type checks to do the right thing, the superclass would have to ...


29

The only reason why it is disallowed is because it makes it easy for people to shoot themselves in the foot. What usually follows in this sort of a discussion is arguments as to whether the flexibility of having the tools is more important than the safety of not shooting off your foot. There is no decidedly correct answer to that argument, because like most ...


28

I follow "classes should have only one reason to change". For me, this means thinking of harebrained schemes that my product owner might come up with ("We need to support mobile!", "We need to go to the cloud!", "We need to support Chinese!"). Good designs will limit the impact of these schemes to smaller areas, and make them relatively easy to accomplish. ...


27

The reason is that the implementation of these interfaces is usually not relevant when handling them, therefore if you oblige the caller to pass a HashMap to a method, then you're essentially obliging which implementation to use. So as a general rule, you're supposed to handle its interface rather than the actual implementation and avoid the pain and ...


26

2 advantages to constructors: Constructors allow for the an object's construction steps to be done atomically. I could avoid a constructor and use setters for everything, but what about mandatory properties as Joachim Sauer suggested? With a constructor, an object owns its own construction logic so as to ensure that there are no invalid instances of such ...


25

No one knows. Or at least, we are unable to agree on one definition. That is what makes SPR (and other SOLID principles) quite controversial. I would argue being able to figure out what is or isn't a responsibility is one of the skills software developer has to learn over course of his career. The more code you write and review, the more experience you will ...


24

You might want to take a look at the Builder pattern. From the link (with an examples of the pattern versus alternatives): [The] Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters, especially if most of those parameters are optional. Client code is much easier ...


24

I prefer multiple constructors over default values and personally I don't like your two constructor example, it should be implemented differently. The reason for using multiple constructors is that the main one can just check if all parameters are not null and whether they are valid whereas other constructors can provide default values for the main one. ...


23

It is sometimes considered that the singleton is an anti-pattern. Unless the problem being solved specifically requires the use of the singleton pattern, it is generally best to avoid it. You mention that the function would have no state or other long lived requirements, so the immediate need for an object is not there either. A free function would be best ...


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