Using an object oriented approach in Ruby - ruby

I have two classes, Class A and Class B.
I've recently noticed that they share a lot of the same code. For example:
def viewable_by?(user)
super || clinic.has_staff_member?(user) || user.system_admin? || self.person == user.person
end
I want to minimize the code duplicated between the classes. But in refactoring, I've found that much of it doesn't fit neatly into one class that falls cleanly in the Single Responsibility Principle. I want to put it all into a single module, but the methods will have to do with time formatting, viewing permissions, and a few other things.
As I see it, I have a few choices. (And I bet you can suggest others.) From an object oriented point of view, which approach should I go with and why?
Use one single module shared between both of the classes. It may
not have a specific single responsibility, but it does clean up the
code significantly, and keeps it all in one place.
Make tiny classes and mix in to both classes as modules. They
will all have a single responsibility, but there will be many of
them, some of which may only have one method. Seems like a waste.
Perhaps use a presenter for things like time formatting, and a
permissions module shared between both classes. Perhaps "cleaner,"
but methods are going to be everywhere.
Another possibility I haven't yet considered?
EDIT
This question had previously mentioned Clinic::Appointment and Clinic::Visit classes, rather than A and B. Answers may refer to appointments and visits.

This is a neat question because it deals in a great way with the overall strucuture of your project. I understand that Appointment and Visit are separated things, and an Visit don't need to be linked to an Appointment.
For authorization methods, like viewable_by?, I recommend move all authorizations to other place - you might want to check the cancan structure, that have worked well for many Rails projects, and most likely will work well for any application, even coding an authorization system yourself. So in part, my answer for you is to use (3).
However, since not all code that is shared by the two classes are for authorization purposes, I would try to classify a set of methods, and give an answer for each class of methods you could think of. For method classes that have a similar behavior I would try to encapsulate in a module and include it (so just like (1), but in smaller parts). For example one module HasVisitors with methods like got_on_time? and was_conclusive? (well, maybe not the best examples, but you get it). When your model has a broader scope, like Authorization, that is present in most of your classes, then it is time to go to (3).
I suggest you stop and think again if you should have a Visit class apart from Appointment and it relationship, but not now. After got at home, have fun, take it off from your head, then think again next day.

Would the design be clearer if you shifted the responsibilities? e.g. user.can_view?(resource)

Related

Multiple Service in Spring Boot App, is it good practice?

I am writing my first bigger API, which is based on three entities (cinema, movies, movie properties). I try divide my methods like below:
MovieServiceImpl:
saveMovie(), findMovieByID(), deleteMovieByID,
showMovieWithCinemasList(), enrolledPropertyToMovie()
CinemaServiceImpl
saveCinema(), enrolledMovieToCinema(), showCinemasWithMovieList()
PropertyServiceImpl
saveProperty(), findPropertyByID()
ReservationServiceImpl
showFreePlaceOnMovie(), showDateChosenMovie(), showRepertoire(),
showCinemasWithMoviesLisT(), multiplePlaceReservation()
Question
Whether it is compatible with the Single Responsibility Principle (SRP).
And it is a good practice to divide it into smaller Services if not what should I do?
Your question is a bit unclear.
Single Responsibility Principle mandates single responsibility for a single structural unit of work (class, module, interface, method, whateverunityourlanguage has), i.e. one entity/unit responsible(/solving) one particular problem.
For instance, if you have a method:
Person getPersonById(int id) {...}
you should never implement validation or authentication logic in it; instead, you should delegate that responsibility to another layer/object.
This has almost nothing to do with "can I have several types in the application?", and to be honest, I can't think of any application (unless it's a really small console app), which doesn't have several structural units (entities, like class, interface, etc.) in itself.
Your example doesn't show anything about SRP, but rather solely demonstrates, that you have different types for different business domain models, and that's much, much better way of designing application/types, in contrast to having one messy class for working with different domain objects/logic.
If, however, you violate SRP in the methods of those classes, that's another story, and we can't address it here, as you don't show implementations.
I still think, that your question was more about having different types, instead of incorporating all of them in one (a horrible idea!), and in your example, Movie, Cinema and Property are three different domain entities, which is - again - good.
Regarding:
And it is a good practice to divide it into smaller Services if not what should I do?
It's unclear what do you mean in "smaller services" and what is your question about. It seems to me, that you're working with nTier/Layered architecture, and only thing I can tell you, that - yes, it's good to separate responsibility layers.
Blockquote
I still think, that your question was more about having different types, instead of incorporating all of them in one (a horrible idea!), and in your example, Movie, Cinema and Property are three different domain entities, which is - again - good.
Yes my question was just about it!
And by the way, you made me realize that it should separate the validations to other methods so that my code becomes better and meets the SRP as well.
Thanks for the answer, although it seemed logical to me, I needed confirmation from someone experienced. Thank you very much!!!

Is there a common convension to put new methods(on top or on bottom)?

If we omit visibility modifiers(let's say all methods are public), is there any common convension to put new methods in class? I mean if I put them on bottom it's logically correct, because methods are sorted by date. If I put them on top, it's easy to see and compare what methods are added if the class is very long.
Just depends on what you and your team are comfortable with. I usually have method at the top of my class followed by fields. If there are many method that do different thing you are better off organizing them in a new class. Now without seeing any code I'm simply guessing.
No, I don't think there is.
As Kalagen said it's up to you and your team to decide it.
I would keep any methods that share similar functionality together and keep the class definition short.
The short answer in my opinion is no. Coding style might vary depending on the language you are using and the team you are working with. In addition you might have your own preference as well. I tend to add new methods close to methods that are related to it (e.g. if method1 calls method2 then method1 is above method2). Then it is relatively easy to find the method that's being called. On the other hand, most IDEs can find the method with a mouse click.
If you're using version control, you can easily see what methods were added and in which order, so sorting by date is not needed.
And as others have mentioned, keep the class small. Take a look at the Single responsibility principle. If the methods you are adding are not related to the responsibility of the class, extract them and create a new class.

2 small questions regarding Laravel facades

I know it's an issue with a lot of debate, but there are two aspects about it that I haven't seen much reference to and would like to know the answers to:
We're using static functions all the time - I'm sure no one will ever stop using dd() helper for example, but obviously even pure PHP static functions like json_encode() or array(). Why doesn't it make sense to see laravel classes behind facades as similar helper functions and not as class dependencies?
More than that, many times we're using those dependencies in a narrow control flow (or conditions) inside the method and the class\method is truly not necessarily dependent on those helpers all the time (for example user class used only if user is authenticated etc.)
In his response to this debate, Taylor Otwel himself said that the use of facades may lead to responsibility bloat in your classes meaning we might be tempted to write classes\methods that do too much and not separate them - but I don't understand how using facades instead of injecting all those classes in the contractor or method is different in terms of responsibility - from what I understand it's just a change in where you "declare" those classes - in the method signature or inside it (I understand that has a lot of differences, but don't see one in class responsibility matter). Can someone explain this?
Bottom line I'm asking this because obviously I'm all for facades when they serve as helpers and not as a core part of the class\method purpose, and I want to know I'm not the only one... I'm mostly anxious of having to write every little piece of helpers I'm using as dependencies in my classes.
Thanks!
Since this discussion is swathed in controversy, I'll make this short and just answer directly the two points you raised:
The native PHP json_encode function can be considered a helper because it's idempotent. In short, it has no dependencies, and has a predictable output. So for example the date function is not a helper function. Many people shy away from it for that reason, and use the DateTime class instead.
What Taylor means by responsibility bloat is that since you're not declaring your dependencies up front, you don't realize how much your controllers do. If you're forced to declare your dependencies up front (via injection), you're more likely to realize when your controller has too many dependencies, and abstract some responsibilities into their own class.
Again, note that I'm not offering an opinion here; too much controversy around it. I'm just clarifying what you've asked so that you can form your own informed opinion.

Multiple Controllers appropriate with one entity in spring framework

I'm starting to develop website that use the spring framework.I have three controller.There are newCustomerController,editCustomerController and deleteCustomerController.These controllers are mapped with view that use for create update and delete, but I create only customer.
So, I would like to know.Is it appropriate to declare the controllers like this.
Thank
The answer to this question is subjective and maybe more a topic for https://softwareengineering.stackexchange.com/. However, there is something very spring related about it that I would like to comment.
There are a few principles that attempt at guiding developers of how to strike a good balance when thinking about designing the classes. One of those is the Single responsibility principle.
In object-oriented programming, the single responsibility principle
states that every class should have a single responsibility, and that
responsibility should be entirely encapsulated by the class. All its
services should be narrowly aligned with that responsibility
A catchier explanation is
A class or module should have one, and only one, reason to change.
However, its still often hard to reason about it properly.
Nevertheless, Spring gives you means for it (think of this statement as a poetic freedom of interpretation). Embrace constructor based dependency injection. There are quite a few reasons why you should consider constructor based dependency injection, but the part relevent to your question is adressed in the quote from the blog
An often faced argument I get is: “Constructors just get too verbose
if I have 6 or 7 dependencies. With fields only, this is fine”.
Awesome, you’ve effectively worked around a clear indicator that the
code you write is doing way too much. An increase in the number of
dependencies a type has should hurt, as it makes you think about
whether you should split up the component into multiple ones.
In other words, if you stick to constructor based injection, and your constructor turns a bit ugly, the class is most likely doing too much and you should consider redesigning.
The same works the other way around, if your operations are a part of the logical whole (like CRUD operations), and they use the same dependencies (now "measurable" by the count and the type of the injected deps) with no clear ideas of what can cause the operations to evolve independently of each other, than no reason to split to separate classes/components.
It should be better if you define one controller for Customer class and in that class you should have all methods related to customer operations (edit,delete,create and read).

Fat models, skinny controllers and the MVC design pattern

I just read a blog post that explains MVC with a banking analogy. I have a few months of experience with web application development with an MVC framework (CakePHP), so I get the basics, but I began to see a theme that made me think I'm taking a flawed approach to where I put my logic:
Fat models, skinny controllers
Keep as much business logic in the models as possible
In my app, models are anorexic and controllers are obese. I have all business logic in the controllers and nothing besides associations and validation rules in the models.
Scanning through my controllers, I can now identify a lot of logic that should probably go in a model:
The app has lists, which contain items, and the items can be ranked. The sorting logic which puts the list in ranked order is in a controller.
Similarly, items (Item model) also have images (Image model). Each item may have a default image (designated by image_id in the items table). When an item is displayed with its images, the default image should appear first. I have the logic that does this in a controller.
When a list is displayed, related lists are displayed in the sidebar. The logic to determine which lists are related is in a controller.
Now to my questions:
With the examples I gave above, am I on the right track in thinking that those are instances of logic presently in a controller that belongs in a model?
What are some other areas of logic, common to web apps, that should go into models?
I'm sure identifying this problem and changing my design pattern is half the battle, but even if I decide to take those examples I gave above and try to move that logic to a model, I wouldn't know where to begin. Can anyone point me in the right direction by posting some code here, or linking to some good learning resources? CakePHP specific help would be great, but I'm sure anything MVC will suffice.
It's a bit tough to give you the "right" answers, since some of them deal with the specifics of the framework (regardless of the ones you are working with).
At least in terms of CakePHP:
Yes
Anything that deals with data or data manipulation should be in a model. In terms of CakePHP what about a simple find() method? ... If there is a chance that it will do something "special" (i.e. recall a specific set of 'condition'), which you might need elsewhere, that's a good excuse to wrap inside a model's method.
Unfortunately there is never an easy answer, and refactoring of the code is a natural process. Sometimes you just wake up an go: "holy macaroni... that should be in the model!" (well maybe you don't do that, but I have :))
I'm using at least these two 'tests' to check if my logic is in the right place:
1) If I write a unittest, is is easy to only create the one 'real' object to do the test on (= the object that you are using in production) and not include lots of others, except for maybe some value objects. Needing both an actual model object and an actual controller object to do a test could be a signal you need to move functionality.
2) Ask myself the question: what if I added another way to use these classes, would I need to duplicate functionality in a way that is nearly copy-paste? ... That's also probably a good reason to move that functionality.
also interesting: http://www.martinfowler.com/bliki/AnemicDomainModel.html

Resources