It seems that if I strictly adhere to the Single Responsibility principle, then I may have to add public getters in order to split functionalities that may change. To me, this seems to violate encapsulation by exposing the objects internal structure.
For example, assume I have a class that represents an uploaded file. In the past I have used methods like toHtml() in order to avoid getters and maintain encapsulation:
public class UploadedFile() {
private String filename;
private String uri;
public String toHtml() {
return <html string>;
}
But I could see where one could argue that, based on SRP, you might want to include getters for filename and uri and generate the html elsewhere.
In this situation, filename and uri would be properties of your UploadedFile() class that it would be illogical to keep hidden, so providing getters for those doesn't violate encapsulation at all, in my opinion.
The encapsulation violation would occur if you made filename and uri public fields and just accessed them directly.
Related
This is one of a number of things that's been bugging me for a while and for which quibbling over the correct interpretation of this has been leading me in a number of attempted coding projects to more fussing around with design, than it has with making steady forward progress, because I want to make sure I've gotten it "right".
In this case, I have a question about the "interface segregation principle" (ISP) of the five "SOLID" principles of basic object oriented design. Its "canonical" statement is this:
Clients should not be forced to depend on methods they do not use.
However, the question here is, is what is the "client" - because this leads to very different interpretations, and also leads to a seeming dilemma when applied in practice, which is what I'd like to understand if first actually is one, and second, how to best solve it.
One interpretation of this is that it is a "single responsibility principle" for interfaces instead of just classes: i.e. if you have an interface IMessageReceiver, it better not include a Send method. Another possible interpretation is that it means that the implementer of an interface should not be required to implement empty methods, while a third interpretation is that the caller should not be able to see any more methods than it actually needs. And the thing is, I can see merit in all three of these interpretations, yet when you apply them all, it seems that in any suitably large project, highly counterintuitive and seemingly problematic things result. In particular, it's that third one that seems to be the rub.
For one, if something gets used in enough places, it is particularly that last one - the "caller" one - which generally tends to "bite" in that it results naturally in your interfaces being atomized down to single methods only. For example, consider a simple interface to a backend storage or database, which may have a load, save, and update method. Some callers of that, though, may not want to save anything. They may just want to peek at the data. Hence to avoid violating the caller interpretation, we must split off the load method. Add a few more use cases and now it's atomized into a IDataLoader, IDataSaver, and IDataUpdater which all have 1 method each.
And I can't help but feel this almost seems like an anti-pattern, particularly if it happens with enough objects owing to them being used in a suitably wide variety of places. Is it? Or am I misinterpreting something here? After all, nobody makes a generic container class (like the "list", "map", etc. things in a lot of languages) with single-method interfaces to be piecemealed out to whatever it gets passed to.
One interpretation of this is that it is a "single responsibility principle" for interfaces...
Robert Martin has addressed this question directly, and his answer is that ISP separates things that SRP does not, thus the two principles differ.
Another possible interpretation is that it means that the implementer of an interface...
We also see in his answer that the client is the caller of the interface, not the implementer. I've touched on that in another answer regarding default methods. The implementer should be implementing exactly as many methods as the caller needs: no more, no less.
a third interpretation is that the caller should not be able to see any more methods than it actually needs.
This is correct, and it is also correct to note that a single-method interface cannot violate the ISP. While this may result in a "lowest-common-denominator" approach where every interface is a single method, they should be highly composable in that case; i.e. implementations can select several interfaces to implement, making them highly customizable to client needs.
The database example of separating read from write is so common that is has its own pattern: CQRS. There are arguments both ways. Likewise, generic collections may choose to avoid creating too many interfaces, which is a design counter to the ISP.
I would suggest that in most applications (particularly service applications as opposed to libraries) if rigorously applying the ISP results exclusively in single-method interfaces, it indicates the clients are not cohesive and not complex. If this is an accurate description of the clients, then single-method interfaces are probably appropriate. You may also consider a different architecture such as a separate service for each client if their requirements have so little overlap.
When somebody wants to develop a feature, then he/she tries to map real world object to unit where code can be put. It is done to imitate behavior.
This unit can be called class. And this class has to have just one feature. It is place where we use SRP.
E.g., if programmer maps real world object person to class Person.
Then this class Person does not have to have methods/behavior of other objects. E.g. the Person class does not have to have methods of Car class. This is what SRP about.
Clients should not be forced to depend on methods they do not use.
We've created a Person class so far. Now we want to log all speech of person. So we need to log it. How? We can use interface ILogging with one method Log. Why does this interface have just one method?
Because clients will only have to know about the methods that are of interest to them.
Here Person class is client of interface ILogging.
SRP means that a class is responsible just for one feature. E.g. if you want to edit logging in Person class, then it is violation of SRP.
public class Person
{
public string FirstName { get; set; }
public void Say(string message)
{
File.WriteAllText("path", message); // violation of SRP
}
}
How can we avoid violation of SRP? We should create an abstraction of logging:
public interface ILogging
{
void Write(string address, string content);
}
and use it:
public class PersonWithSRP
{
private readonly ILogging _logging;
public string FirstName { get; set; }
public PersonWithSRP(ILogging logging)
{
_logging = logging;
}
public void Say(string message)
{
_logging.Write("path", message);
}
}
public class Logging : ILogging
{
public void Write(string address, string content)
{
File.WriteAllText(address, content);
}
}
By extracting logic of logging in separate class, we moved logic of logging in special, single class or place where we can edit only logic of logging on one place.
What is about ISP?
nobody makes a generic container class
yeah, you are right. Interface should have only necessary methods which client class needs.
An example with HDD that uses ISP:
public interface IReadable
{
string Read();
}
public interface IWriteable
{
void Write();
}
public class HDD : IReadable, IWriteable
{
public string Read() { }
public void Write() { }
}
By creating one interface for Read() and Write() methods, it would obligate class to implement both methods in class. But some classes only want to read data, others want to write data, and some to do both. So in this case it is better to create separate interfaces.
So let's look another example with CardReader. CardReader just reads data, it does not write data. So, if we inherit one interface with Read() and Write() methods, then we would violate ISP principle. An example of violation of ISP:
public interface IWriteReadable
{
string Read();
void Write();
}
public class CardReader : IWriteReadable
{
// this is a necessary method
public string Read() { }
// here we are obligating to implement unnecessary method of interface
public void Write() { }
}
So by applying ISP, you only puts methods in interface that are necessary for the client class. If your class/client just wants to read data, then you need to use IReadable interface, not IReadableWriteable.
Is it considered a bad practice? If it's not always a bad practice, when is it appropriate to create classes without attributes or methods?
It is not necessary for a class to contain methods as well as attributes. Suppose a secenerio in which some attributes are publicly defined for the meantime use so we can use this variable from anywhere outside the class. But to use encapsulation it is recommended to attributes to be private.
If you mean always, my answer is no, you shouldn't always do that.
If the language allows you to do so, there must be a reason. Consider the following factory class:
public class Factory : IFactory
{
public const string FactoryName = "StackOverflowFactory";
public IPerson GetPerson(PersonType type)
{
switch (type)
{
case PersonType.Rural:
return new Villager();
case PersonType.Urban:
return new CityPerson();
default:
throw new NotSupportedException(string.Format("{0} does not handle {1}", FactoryName, type));
}
}
}
In this case, a class contains an attribute and a method. And this is normal.
On the other hand, when we're talking about something like passive data structure, the objects and classes that are created to fulfill this kind of purpose, then you should not mix the attributes with the methods because the purpose of those objects is to store data, not manipulate it.
The Good or Bad is always relative, base on how the system is designed, the purpose of the classes, etc. If the system is designed using a pattern A but you violate that pattern when changing the code, then that may be a bad practice. If the class is just for storing data but you add some methods to manipulate it, then that may also be a bad practice too.
The Single Responsibility Principle states that:
A class should have one, and only one, reason to change.
The Open/Closed Principle states that:
You should be able to extend a classes behavior, without modifying it.
How can a developer respect both principles if a class should have only one reason to change, but should not be modified?
Example
The factory pattern is a good example here of something that has a single responsibility, but could violate the open/closed principle:
public abstract class Product
{
}
public class FooProduct : Product
{
}
public class BarProduct : Product
{
}
public class ProductFactory
{
public Product GetProduct(string type)
{
switch(type)
{
case "foo":
return new FooProduct();
case "bar":
return new BarProduct();
default:
throw new ArgumentException(...);
}
}
}
What happens when I need to add ZenProduct to the factory at a later stage?
Surely this violates the open/closed principle?
How can we prevent this violation?
This feels like a discussion of the semantics of 'extend a classes behaviour'. Adding the new type to the factory is modifying existing behaviour, it's not extending behaviour, because we haven't changed the one thing the factory does. We may need to extend the factory but we have not extended it's behaviour. Extending behaviour means introducing new behaviour and would be more along the lines of an event each time an instance of a type is created or authorising the caller of the factory - both these examples extend (introduce new) behaviour.
A class should have one, and only one, reason to change.
The example in the question is a factory for creating Product instances and the only valid reason for it to change is to change something about the Product instances it creates, such as adding a new ZenProduct.
You should be able to extend a classes behavior, without modifying it.
A really simple way to achieve this is through the use of a Decorator
The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.
public interface IProductFactory
{
Product GetProduct(string type);
}
public class ProductFactory : IProductFactory
{
public Product GetProduct(string type)
{
\\ find and return the type
}
}
public class ProductFactoryAuth : IProductFactory
{
IProductFactory decorated;
public ProductFactoryAuth(IProductFactory decorated)
{
this.decorated = decorated;
}
public Product GetProduct(string type)
{
\\ authenticate the caller
return this.decorated.GetProduct(type);
}
}
The decorator pattern is a powerful pattern when applying the SOLID principles. In the above example we've added authentication to the ProductFactory without changing the ProductFactory.
A class should have one, and only one, reason to change.
This basically means, your class should represent single responsibility and shouldn't be modified thereafter to accommodate new feature.
For example, if you have class, which is responsible to print report in pdf format. Later, you wanted to add new feature to support printing report in other formats. Then instead of modify the existing code, you should extend it to support other format, which also implies extend a classes behavior, without modifying it
I think it depends on your interpretation of the SRP. This stuff is always somewhat subjective. Ask 100 people to define "single responsibility" and you'll probably get 100 different answers.
Using the scenario in Ravi's answer, a typical solution might be to have a ReportGenerator class which exposes a GeneratePdf method. It could then be later extended with an additional GenerateWord method if required. Like yourself though, I think this has a whiff about it.
I would probably refactor the GeneratePdf method into a PdfReportGenerator class and then expose that through the ReportGenerator. That way the ReportGenerator only has a single responsibility; which is to expose the various report generation mechanisms (but not contain their logic). It could then be extended without expanding upon that responsibility.
I'd say that if you find a conflict, it might well be an architectural smell that warrants a quick review to see if it can be done in a better way.
I have a class StudentOrganiser class which takes IStudentRepository dependency. Interfaces exposed by IStudentRepository is say GetStudent(int studentId)
Class obeys SRP because it does not have any logic related to manage the connection with repository source.
Class obeys OCP because if we want to change repository source from SQL to XML, StudentOrganiser need not to undergo any changes => open for extension but closed for modification.
Consider if StudentOrganiser was designed to not take dependency of IStudentRepository, then method inside class itself must be taking care of instantiating new StudentSqlRepository() If later on requirement would have come to also support StudentXMLRepository on the basis of certain run time condition, your method would have ended with some case switch kind of paradigm and thus violating SRP as method is also indulged in actual repository deciding factor. By injecting repository dependency we taken off that responsibility from class. Now StudentOrganiser class can be extended to support StudentXMLRepository without any modification.
I'm relatively new to programming in general and I was wondering if anyone could help me understand the purpose of access modifiers? I understand the fact that they set different levels of access for classes and variables etc. but why would you want to limit what has access to these? What is the point in not allowing access for different things? why not just allow access for everything? Sorry if this is a stupid question!
There are thousands of reasons, but I'll quote a few from here and then expand on those:
Hiding the internals of the object protects its integrity by preventing users from setting the internal data of the component into an invalid or inconsistent state.
It is very common for a type to enforce certain invariants (e.g., A person's ID number must always be 8 characters long). If a client has full access to every member of a class, then there's no way you can enforce those constraints. Here's a concrete example:
public class Person
{
public string Id;
public void SetId(string newId)
{
if(newId.Length != 8)
throw new InvalidArgumentException("newId");
Id = newId;
}
}
There's nothing preventing me from just accessing the Id field and setting it to whatever I want! I could just do this:
Person p = new Person();
p.Id = "Invalid Id";
That's why your private state needs to be private.
A supposed benefit of encapsulation is that it can reduce system complexity, and thus increase robustness, by allowing the developer to limit the inter-dependencies between software component.
Say I develop a class which has 40 methods - 35 of which are needed to wire up the internals of the class and to implement its functionality, and 5 of which are actually important to the client. Now I give you this class for you to use - you look at its public interface and you see 40 methods, most of which are completely irrelevant to you, and you ask me "What the hell is this spaghetti of code??"
In order to make sure the intent of a type is clear, you restrain the access of any members that are not relevant to the client.
Also, more public members = greater public surface = more stuff that needs to be tested = harder to maintain.
As a rule of thumb, try to make your members as private as possible, and then work your way up from there. For example, start with private, and then:
Do/would derived classes need to access this member? If so, promote to protected
Do/would other classes need to access this member? If so, promote to public
Actually modifiers are for limiting Access for modeling like to real life objects.
Access Modifiers
private
protected
default
public
public access modifier
Fields, methods and constructors declared public (least restrictive) within a public class are visible to any class in the Java program, whether these classes are in the same package or in another package.
private access modifier
The private (most restrictive) fields or methods cannot be used for classes and Interfaces. It also cannot be used for fields and methods within an interface. Fields, methods or constructors declared private are strictly controlled, which means they cannot be accesses by anywhere outside the enclosing class. A standard design strategy is to make all fields private and provide public getter methods for them.
protected access modifier
The protected fields or methods cannot be used for classes and Interfaces. It also cannot be used for fields and methods within an interface. Fields, methods and constructors declared protected in a superclass can be accessed only by subclasses in other packages. Classes in the same package can also access protected fields, methods and constructors as well, even if they are not a subclass of the protected member’s class.
default access modifier
Java provides a default specifier which is used when no access modifier is present. Any class, field, method or constructor that has no declared access modifier is accessible only by classes in the same package. The default modifier is not used for fields and methods within an interface.
Since I started to study OOP encapsulation was always something that raised questions to me. Getters and setters in 99% of the cases seemed like a big lie: what does it matter to have setter if it changes the reference of the private field, and getter that returns reference to mutable object? Of course there are many things that make life easier with getters and setters pattern (like Hibernate that creates proxies on entities). In Scala there is some kind of solution: don't lie to yourself, if your field is val you have nothing to fear of and just make it public.
Still this doesn't solve the question of methods, should I ever declare a method private in Scala? Why would I declare a method private in Java? Mostly if it's a helper method and I don't want to pollute my class namespace, and if the method changes our internal state. The second issue doesn't apply (mostly & hopefully) to Scala, and the first one could be simply solved with appropriate traits. So when would I want to declare a method private in Scala? What is the convention for encapsulation in Scala? I would highly appreciate if you help me to order my thoughts on subject.
Getters and setters (or accessor/mutator methods) are used to encapsulate data, which is commonly considered one of the tenets of OOP.
They exist so that the underlying implementation of an object can change without compromising client code, as long as the interface contract remains unchanged.
This is a principle aiming to simplify maintenance and evolution of the codebase.
Even Scala has encapsulation, but it supports the Uniform Access Principle by avoiding explicit use of get/set (a JavaBean convention) by automatically creating accessor/mutator methods that mimics the attribute name (e.g. for a public val name attribute a corresponding def name public accessor is generated and for a var name you also have the def name_= mutator method).
For example if you define
class Encapsulation(hidden: Any, val readable: Any, var settable: Any)
the compiled .class is as follows
C:\devel\scala_code\stackoverflow>javap -cp . Encapsulation
Compiled from "encapsulation.scala"
public class Encapsulation {
public java.lang.Object readable();
public java.lang.Object settable();
public void settable_$eq(java.lang.Object);
public Encapsulation(java.lang.Object, java.lang.Object, java.lang.Object)
}
Scala is simply designed to avoid boilerplate by removing the necessity to define such methods.
Encapsulation (or information hiding) was not invented to support Hibernate or other frameworks. In fact in Hibernate you should be able to annotate the attribute field directly, all the while effectively breaking encapsulation.
As for the usefulness of private methods, it's once again a good design principle that leads to DRY code (if you have more than one method sharing a piece of logic), to better focusing the responsibility of each method, and to enable different composition of the same pieces.
This should be a general guideline for every method you define, and only a part of the encapsulated logic would come out at the public interface layer, leaving you with the rest being implemented as private (or even local) methods.
In scala (as in java) private constructors also allows you to restrict the way an object is instantiated through the use of factory methods.
Encapsulation is not only a matter of getter/setter methods or public/private accessor modifiers. That's a common misconception amongst Java developer who had to spend to much time with Hibernate (or similar JavaBean Specification based libraries).
In object-oriented programming, encapsulation not only refers to information hiding but it also refers to bundling both the data and the methods (operating on that data) together in the same object.
To achieve good encapsulation, there must a clear distinction between the those methods you wish to expose to the public (the so called public interface) and the internal state of an object which must comply with its data invariants.
In Scala the are many ways to achieve object-oriented encapulation. For example, one of my preferred is:
trait AnInterface {
def aMethod(): AType
}
object AnInterface {
def apply() = new AnHiddenImplementation()
private class AnHiddenImplementation {
var aVariable: AType = _
def aMethod(): AType = {
// operate on the internal aVariable
}
}
}
Firstly, define the trait (the public interface) so to make immediately clear what the clients will see. Then write its companion object to provide a factory method which instantiate a default concrete implementation. That implementation can be completely hidden from clients if defined private inside the companion object.
As you can see the Scala code is much more concise of any Java solution