Representing a single narrowly defined business function. Person, or rather, a single tightly coupled group of people When you write a software module, you want to make sure that whenĬhanges are requested, those changes can only originate from a single When Uncle Bob writes about this, he suggests that we think of "responsibility" in terms of "who's asking for the change." In other words, we don't want Party A to lose their jobs because Party B asked for a change. And both are matters of judgement-hopefully seasoned judgement. So again, if the divisions aren't driven by likely changes, they're not truly in service to the SRP 1 if YAGNI is more applicable. (The latter reason isn't inherently bad.) But, the SRP does not exist for its own sake it's in service to creating maintainable software. We tend to split classes because they could change, or along lines that simply help us break problems down. We tend to apply the language of the principle in a hyperbolic, literal, zealous rage. It's about what, in your experience, is likely to change. Thus, there's no scientific or formulaic way to arrive at what constitutes a responsibility, unfortunately. Practically speaking, responsibilities are bounded by those things that are likely to change. Then later on we can add, say, an XmlWriter, without needing to re-implement it for memory, file, and network separately. By separating them this way, we avoid combinatoric explosion: instead of needing FileStreamTextWriter, FileStreamBinaryWriter, NetworkStreamTextWriter, NetworkStreamBinaryWriter, MemoryStreamTextWriter, and MemoryStreamBinaryWriter, you just hook up the writer and the stream and you can have what you want. FileStream, MemoryStream, or NetworkStream) and various readers and writers ( BinaryWriter, TextWriter) that work on a logical level. A great set of examples can be found in the System.IO namespace: there we can find a various kinds of physical streams (e.g. The idea is to minimize the footprint of future potential changes, restricting code modifications to one area of code per area of change.Īt the very minimum, your classes should separate logical concerns from physical concerns. New nonfunctional requirement: We'll start using Oracle instead of SQL ServerĮxample of good change: Just need to modify a single class in the data access layer that determines how to persist the data in the DTOs.īad change: I need to modify all of my business layer classes because they contain SQL Server-specific logic. New business requirement: Users located in California get a special discount.Įxample of "good" change: I need to modify code in a class that computes discounts.Įxample of bad changes: I need to modify code in the User class, and that change will have a cascading effect on other classes that use the User class, including classes that have nothing to do with discounts, e.g. Dumb structs can be better than pointless getter and setters-especially if you're not building a reusable library that has ABI compatibility requirements.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. OOP is overrated, we all know it, and you shouldn't feel any need to apologize if free functions work in your use case. Of course the credentials may be invalid, but that can be checked by some method which might be called in one of the constructors.Īs an aside, there is nothing wrong with free functions. There is here no way to configure a Camera without a password for example, so calling take_snapshot() without credentials is simply not possible. This also makes it more obvious what to do if someone wants to make a USB session for a different camera, etc.Ī secondary idea here is that objects are created with valid state from the beginning. The virtualization of the camera is elsewhere, on its own. The class Camera now more closely models a real camera: it has something like a power button and a shutter button. The main idea here is to separate authentication and session/endpoint definition (and perhaps connection) from the camera controls. Session(string url, string user, string password) I'd write your example this way: class Session How do you balance between convenience and idea was shown as an answer by Zwinck which begs the question as to why we need OOP in the first place. Here stuffs are neatly separated in terms of responsabilities, but now it looks very much like C with dumb structs and functions. Following the SRP, you could write it like this: class Camera This looks natural, but it looks like the Camera class has 3 responsabilties: store metadata, take snapshot, reboot. How do you decide when and how to violate the single responsability principle?įor example, let's say I have a network camera with the following interface (interface kept stupid and "wrong" for simplicity): class Camera
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |