solid – Data handling in SRP (single responsibility principle)

I have read a lot about separating methods and function into “single reason to change” classes.
But when it comes to data, I find very little details.
I am not sure where to put the data, each separated part needs as Input and provides as Output

An example scenario:

I got a data source, a list of some kind, maybe in a csv or excel format.
Requirements could be:

  • import the file (Import)
  • check the list for certain conditions (business logic, validation)
  • calculate stuff based on a few fields (business logic)
  • convert the list to a different format, e.g. json (business logic, conversion)
  • write the changed list to the excel file (Output)
  • write the changed list to the json (Output)

I would divide the responsibility into following parts(Lets call them “Helpers”):

  • Import/Export of the List -> ListSerializer (produces List from disk)
  • Check the List ->ListChecker (takes List, produces ErrorList)
  • Apply business logic to the List->ListProcessor (takes List and ErrorList, produces List (with changes))
  • Convert the List to JSONList ->ListToJSONListConverter (takes List(with changes), produces JSONList)
  • Export the JSONList to file ->JSONListSerializer (takes JSONList, writes to disk)

AFAIK a classical SRP design. changes to the list format, check logic, business logic or JSONformat requiring to change very few classes

Now I want to implement it. All classes get Interfaces for exposing their function.
An Orchestrating Class (lets call it “Superior”) is created to handle user input/other triggers and calling the sub routines
This class needs to know every interface of the “Helpers”(so it can call the methods) and must be initialized with concrete objects (implementations of the interfaces) by the init logic lets call it “Boss”. Basic Dependency Injection stuff.

Basically the Boss creates the Helpers and the Superior and tells the Superior these are your Helpers, Jack ListSerializer as your ListSerializer, Amy ListChecker as ListChecker, …
When a new Task arrives, the Superior gets notified and he/she splits and delegates the task to the Helpers.
Lets take that picture a little further:

Now there are multiple variants how things could be done:

1st: Orchestrating class manages all data storing
Superior: Mr. ListSerializer please load the list.
Jack the ListSerializer: Superior, I have completed the task, here is the List.
Superior: Thanks. Mrs. ListChecker, please check this list, it is right here.

2nd: Every dataproducer stores its output for itself, the others know how to retrieve it
Superior: Mr. ListSerializer please load the list.
Jack the ListSerializer: Superior, I have completed the task
Superior: Thanks. Mrs. ListChecker, please check the list(, you can find it at the ListSerializers desk.)
..

3rd: One big variable data storage, where the helpers know how to access the info relevant to them
Superior: Mr. ListSerializer please load the list. Here is the magic drawer to put your results in.
Jack the ListSerializer: Superior, I have completed the task
Superior: Thanks. Mrs. ListChecker, please check the list, you can find it in the magic drawer, please put your results in there, too.

every variant has its advantages, but is bad to some degree

1st: The Superior needs to know the data objects up front, one could reason to use interfaces for that. feels little object oriented to store data centrally, but one could try to live with it

2nd: Feels more object oriented, the Superior doesn’t need to know the details, downside is the additional coupling between the Helpers they need to know each other

3rd: most decoupled, no Helper needs to know any other, only the way how to retrieve and store data from and to the all knowing data storage object

Does the SRP (or SOLID) provide a guideline for that?
What are best practices in that matter?

api design – SRP decision making on MVC project

I am trying to design an application and I would like to apply SOLID principles on it so before I start coding I want to have a rough idea on how to design it.
It will be a REST API following MVC so for now I have 2 main features.
Projects
Tickets associated to Projects

So my idea so far has been like this to create the Controller -> Service -> Repository

This is for Project:

ProjectController -> ProjectService -> ProjectRepository

This implementation can end with such methods:

getProject()
getProjects()
createProject()
updateProject()
deleteProject()
getProjectConfiguration()

This is for Ticket:

TicketController -> TicketService -> TicketRepository

This implementation can end with such methods

getTicket()
getTickets()
createTicket()
updateTicket()
deleteTicket()

Each of them are likely to be extended in the future. Maybe just updating a certain part of the Project or Ticket, so a new endpoint would be added and therefore new methods.

Once I have explained my plan I want to know how I can adapt this to Single Responsibility Principle. This states each class should do one thing and be changed for one thing. But I don’t know the level of abstraction of such thing.
Should I create a class for whatever involves the creation in Project, another for whatever involves updating in a Project and the same for deleting and retrieving as well as for Ticket?
Something like:
ProjectCreationXXX, ProjectUpdateXXX, ProjectRetrievalXXX, etc etc etc

Or since my original proposal is making a part for Project and another for Ticket that can be considered they are only doing one thing? Which would be the handling of a Project or a Ticket.

I hope my question is clear, if not, please, let me know and I will try to express myself more clear.

Unity – Understanding the SRP batcher

Im trying to understand the SRP batcher. I have a scene with 300 fairly low-poly models.

These are my rendering stats with SRP Batcher:

enter image description here

And this is without SRP Batcher:
enter image description here

Some observations (This is all with dynamic batching enabled, models share a GPU instanced material):

  1. With SRP Batcher the Tris and Verts seem to lower almost impossibly low, sitting at the low thousands, while without the SRP Batcher they are almost 5 million.
  2. With SRP Batcher the draw calls are at almost 3000, with none being batched. On the other hand, without SRP Batcher the draw calls are at 103, with almost 2500 being batched.

I cannot really make sense of this. I see no noticable effect on the FPS. I have no idea which is actually better for performance. The stats above make no real sense to me, seems strange that enabling SRP batcher removes all batched calls… Can someone help me understand which is better and when to use what?

Everything is tested on latest unity and URP versions.

authentication – How do SRP (and PAKE generally) protect against verifier leak

I have been reading into PAKE protocols, specifically starting with SRP RFC2945

The gist of the requirement on the server is that the server saves triplet (username, verifier (v), salt (s)) in the credentials table.

Where verifier v = g^x % N (the ^ operator is the exponentiation operation)
and x = SHA(<salt> | SHA(<username> | ":" | <raw password>))

Now during the authentication dance, the client obtains the salt (s) from the server and computes the same verifier (v) that the server is using. It can compute this value because it collects the username and password from the user themselves.

In the next few steps the client can subtract the component v from the servers challenge B = (v + g^b) % N and arrive at a key derived from S.

Client: S = (B - g^x) ^ (a + u * x) % N

My question is that if someone hacks my database and dumps the credential table with (username, verifier (v), salt (s)) they immediately have access to all verifiers for each username. Then what stops them from using the obtained verifiers to imitate a client and complete the client side authentication steps? So instead of computing the verifier (v) from the real username and password, they can simply use the verifier obtained maliciously from the server to continue the client side computation and arrive at the same key as the server.

Disclaimer: I admit I do not understand fully the maths but generally the concept that such crypto protocols rely on the property of exponents that (g^a)^b = (g^b)^a = g^ab

python: clean code, reduction rule and SRP

I'm currently reading Uncle Bob Clean code and I wonder what would be the "cleaner" implementation of the following:

Let's say I want to implement a HTTPRequest class that handles the execution of (well, obviously) http requests.

This was my initial implementation:

class HTTPRequest(object):
    def __init__(self, url, method, **kwds):
        self.logger = logger.get_logger(__name__)
        self.url = url
        self.method = method
        self.request_kwds = kwds
        self.execution_time_seconds = 0.0
        self.response = None
        self.logger.debug("Created instance %s" % self)

    def execute(self):
        self.logger.debug("%s starting request" % self)
        start_time = time.time()
        self.response = HTTPResponse(
            request=self,
            request_response=requests.request(url=self.url, method=self.method, **self.request_kwds)
        )
        self.execution_time_seconds = time.time() - start_time
        self.logger.debug(
            "%s received response %s after %.4f seconds" % (self, self.response, self.execution_time_seconds)
        )
        self.response.raise_for_status()
        return self.response

the execute The method currently does two things: issue the request and capture the response, and measure execution time.
First of all, this would be a violation of the Single liability principle.
Furthermore, it is highly detailed and has a low level of abstraction.

Now, you could break this down into different child methods, like this:

class HTTPRequest(object):
    def __init__(self, url, method, **kwds):
        self.logger = logger.get_logger(__name__)
        self.url = url
        self.method = method
        self.request_kwds = kwds
        self._start_time = 0
        self.execution_time_seconds = 0.0
        self.response = None
        self.logger.debug("Created instance %s" % self)

    def execute(self):
        self.logger.debug("%s starting request" % self)
        self._start_time_measurement()
        self._execute_request()
        self._stop_time_measurement()
        self.logger.debug(
            "%s received response %s after %.4f seconds" % (self, self.response, self.execution_time_seconds)
        )
        return self.response

    def _start_time_measurement(self):
        self._start_time = time.time()

    def _execute_request(self):
        self.response = HTTPResponse(
            request=self,
            request_response=requests.request(url=self.url, method=self.method, **self.request_kwds)
        )
        self.response.raise_for_status()

    def _stop_time_measurement(self):
        self.execution_time_seconds = time.time() - self._start_time

In addition to having separated the logic of timing and request execution, from what I've read so far, this version should be considered "cleaner".

But I have two concerns about it:

  • This class is still extremely simple. This refactoring made it significantly longer (replacing two single-line declarations with a function call that takes up two lines (+1 for spacing). Doing this type of refactoring to a "real" class with a lot of business logic could ruin it) until indefinitely (which is later considered "impure")

  • The original version was, in my opinion, readable enough as it used telltale intent names for the variables, making it clear that there is some kind of time measurement during the request.

So the question is:
Which version do you prefer and why? How much logic extraction in submethods is too much?

Import SRP package to URP?

I upgraded from LWRP to URP and some active materials don't work "pinkie". They told me to import the SRP package into URP. I do not understand this ? How to do this step?

Design – Is this a violation of SRP?

The SRP is not about doing one thing, but about reasons to change.

The case he describes is on one side. Tree class that manages elements and, on the other hand, a State class that makes use of a specific tree.

At first glance, creating an overload to enrich Tree with a add at the root level it does not seem to break the SRP: this overload does not create a new reason for the change. It is just a convenience.

Unfortunately, it is not completely clear how root it relates to a node of the Tree:

  • Is there only one root by all the Tree elements? In this case, it is not about SRP, but about OCP and extending Tree to allow reuse.
  • Are there several trees, each with its own root? In this case, how do you find the correct root? There are two variants:
    • There is no direct relationship: the context of use has to know its root. In this case, State It would have a root. But other classes could have a different root. Then you add() the overload would belong to State since it is directed to an encapsulated element. But add() the firm would depend on the Tree::add(). In this case, it would break SRP.
    • There is a relationship. For example, each tree would point to a root node. Or each tree would point to a parent tree, which allows it to return to the root. Or the tree maintains the root trail, and the tree elements are a nested class. Whatever the design, then you could have a add() for the root level without breaking any SOLID principle.

SRP confirmation of shared keys

SRP (secure remote password) needs an exchange of hash signatures to verify that both parties have the same shared key (RFC2945):

At this point, the client and server must have a common session key
That is certain (that is, not known by an external party). To end
authentication, they must prove to each other that their keys are
identical.

    M = H(H(N) XOR H(g) | H(U) | s | A | B | K)
                                -->
                                <--    H(A | M | K)

The server will calculate M using its own K and compare it with
The customer response. If they do not match, the server MUST abort
and point out an error before you try to answer the client's question
challenge. Failure to do so could compromise user security
password.

With respect to the last sentence above, why answering an invalid M would compromise the user's password?

design patterns – SOLID – Principle of Unique Responsibility (SRP), applied to functions of a class or the whole class?

I have doubts with the principle of sole responsibility (SRP).

As it says "Every object in the system must have a simple responsibility, and all object services must fulfill that simple responsibility."

What I don't understand is, should I apply this principle to each function within a class? Or is it that each class should be responsible for only one thing? What makes me noise is: If the class has only one responsibility, it would mean that it would have one, two or very few functions and I don't know if that's okay.

java – Should a Move and a Tracker be separate classes to maintain SRP?

I am practicing a Java code to better understand the principle of sole responsibility. Currently, I am working with a network of data structures, where each structure implements an interface called Location.

public interface Location {

    void removeObject(Object o);
    void addObject(Object o);
}

Different locations store and retrieve objects differently, so everyone needs their own method to add / delete them. The goal is to be able to freely move objects between locations and find where the objects are currently. I have two classes called to move the Objects, one to make the actual movement of the Objects (the Move) and another to keep track of where the Objects are so that they can be retrieved for the Move class (the Tracker).

public class Database {

private Mover mover;
private Tracker tracker;

//Contains methods for moving specific Objects to specific Locations.

}

public class Mover {

void moveObject(Object o, Location a, Location b)
{
  a.removeObject(o);
  b.addObject(o);
}

}

public class Tracker {

Map> trackerMap;

void updateTracker(Object o, Location a, Location b)
{
    trackerMap.remove(a);
    trackerMap.put(b, o);
}

Object lookupObject(Location l, Object o)
{
    List objects = trackerMap.get(l);
    return objects.get(o);
}

}

However, I have some concerns about this design. Because Move and Tracker have been divided into separate classes, data structures are essentially stored twice. Once for the Tracker map and once for the actual data structures, the Move is modifying. It seems prone to errors. If the two were out of sync for any reason, the Move could end up trying to move things that do not exist, and the Tracker may be unable to find them. I still have the feeling that the Move should be directly modifying the Tracker map when moving Objects, to ensure they remain synchronized. However, if the Move begins to modify the Tracker, then the Tracker does not need to be its own class. And combining the two, from what I understand, would violate the SRP.

How can I improve the design of this database while maintaining the SRP?