Object orientation - how to find the right abstractions?

Actually the question I'm wanting to ask is exactly this: how to identify classes in an object-oriented system?. However, I would like to ask for two additions to her accepted answer.

  1. It seems to describe so-called OOA&d (Object-Oriented Analysis and Design) or Object-Oriented Analysis and design. I don't know if this is a request suitable to the format of the OS, but I would like to ask for a canonical reference regarding the subject matter, and accepting material complementary to the canonical (if possible indicating why I should prefer one material over another). If it makes a difference, I have more experience with Java. I am currently in doubt among the following references:

    • Applying UML and Patterns (Craig Larman) - textbook adopted by my university after I graduated; it doesn't seem to go into much detail when it comes to finding the right abstractions, but in its text the author recommends the Responsibility-Driven Design that is described in the book below;
    • Object Design: Roles, Responsibilities, and Collaborations (Rebecca Wirfs-Brock, Alan McKean) - the author is a reference in OO; the book introduces RDD, which seems to be accurate on how to choose the right abstractions when modeling classes;
    • Object-Oriented Software Construction (Bertrand Meyer) - the author is reference in OO, but the latest edition is not much recent;
    • Object-Oriented Analysis and Design with Applications (Grady Booch et al.)- interesting because it compares classical and modern approaches to Object-Oriented Analysis and devotes Chapter 4 to "finding the right abstractions";
    • Head First Object-Oriented Analysis & Design (Brett D. McLaughlin et al) - no special recommendation, just like the style of the Head first series.
  2. A more specific question to respect of class modeling. I confess that although I thought I had "programmed OO" for many years, because I had studied my Oo discipline, learned my share of design patterns, read about SOLID, know cohesion/coupling, favor composition to inheritance and everything else, I actually had a lot of freedom with my classes and did not really understand the original philosophy behind object orientation. If I understood, I would have known for a long time why they made right sense "rules of thumb" as Tell Don't Ask (which in its mildest form warns against leaking business logic out of the object through unnecessary getters) or the er-er Principle, or Robert Martin's Dance You Imps post. Objects go beyond joining state and behavior in defiance of our intuition and individual experience; they would be more like "mini-machines" that provide an API of commands for your clients (your public methods, which should usually be more than one; otherwise it's probably a procedure disguised as an object), let a minimum of State (this is encapsulation; it has nothing to do with simply creating getters for private variables) and self-manage. You don't create classes by default; you find the classes that are most appropriate, often having to discard the choices initially more obvious. For me these concepts are not at all intuitive and I believe that there is material regarding how to design classes correctly either in the books above or somewhere else, so the title question: "How to find the right abstractions?", which must take into account this correct philosophy of object orientation. In fact I would like to break this question into two parts: one for the long term, in which the answers indicate reading on the subject; and one for the short term, since I am starting the coding of a new project, with business rules, architecture, bank modeling and individual services already specified and since I noticed this deficiency I am feeling insecure about how to design the classes within these services. Since the correct philosophy is not intuitive for so many programmers (it is what the connoisseurs of the subject say, and what testifies to the wide ignorance of this canonical material that @Maniero spoke, and See also the erroneous analogy that objects must precisely reflect the real world[1] [2]), and since creating the your Class Diagram by intuition instead of finding the most appropriate one is also incorrect, finding the right abstractions seems a little harder than before.

Author: Maniero, 2016-01-19

4 answers

I will risk a simplistic answer to the main question:

How to find the right abstractions?

Top-down approach

In a personal reflection, I came to the conclusion that one of the ways to solve problems that is most efficient for me is a top-down approach, going from the most abstract and generic concept to the most concrete and specific.

For example, let's assume that the client wants a program to control a robot that prepares juices. Going back to the most basic principle of computing ( input, processing and output ), I have:

  • entrees: fruit, water and sugar (ingredients)
  • processing: robot uses the liquifier, there may be different types of "recipes"
  • output: drink

So, at a high level, I can determine the main interface of the system:

class Robo {
    Suco preparar(Ingredientes, Procedimento)
]

Basically, you ask the robot to make the juice, it provides the ingredients and tells what the procedure, receiving as a result the vitamin.

Sure, it's something very simple, but here's the advantage. Good modeling, in the definition I'm using, includes two main elements:

  1. the fact that many details are not represented gives great freedom to how everything will be implemented. Processes can be broken into subprocesses, more abstract objects can be composed with other simpler objects, the main interfaces or classes can have specialized versions, interactions between elements are not fully defined, and so on.
  2. at the same time we have a well-defined "public interface" for the "customers" of this class to make their vitamins.

Summarizing:

The "correct" abstraction would be the one that allows you to implement and specialize existing functionality with freedom without changing the most high.

Considerations

Object orientation vs. other paradigms

In various questions that have arisen these days, the question of advantages of oop against some other paradigm has been raised.

In no way should we see this as a competition. The different paradigms can and should be used together.

Oop, with its classes and attributes, does not replace "procedural" or imperative programming nor does it prevent the use of programming functional, but adds encapsulation and abstraction capabilities that would be more difficult to express in other paradigms.

Nothing prevents, for example, a "procedural" code from building a collection of objects and performing a Map-reduce operation to get a consolidation of the collection data.

Data Structures vs abstraction

Note that in my "modeling", I did not even get into the question of the data structures used, that is, what attributes represent an ingredient, etc.

The trump card of OOP is not in organizing data sets, nor (in my opinion) in representing real-life entities, but rather in abstraction or in what is possible to specify without defining the details.

Real-life attributes can be represented in "lifeless" data structures and processed by independent functions or routines.

On the other hand the elegance of a good class modeling is, in my opinion, not in the modeling itself, but in how easy and intuitive it is for the other people who will access, implement and extend it. From this, no purely procedural language has come close to this day.

Making knowledge concrete

I will not recommend a specific literature of the subject. In fact, I do not know and do not think there is anything that is definitive. Any text or book will address at most some aspects of what it is to model the problem on objects.

The only way I know to do a "correct" modeling is:

  1. read everything you can on the subject
  2. try to apply this to a problem in the best way you can
  3. prove use in practice and collect feedback
  4. identify problems and search for solutions to them
  5. redo the model trying to solve the items found in item #4 to have a "more correct" modeling
  6. repeat everything dozens of times

A creative process

Contrary to what is described in the question, I would not say that someone finds the correct abstraction, as if this is something that exists independent of the programmer.

Programming is a creative process. An artist does not find the right way to paint or model something, he does it arbitrarily within the limits that he imposes on himself and, of course, within his own capacity.

 6
Author: utluiz, 2016-01-22 02:03:19

Although many people interpret in a simplistic way the verse "object orientation helps to represent the real world", the fact is that it is exactly this idea that will help you find the right abstractions.

Demystifying the"representation of the real world"

  • Does the map with the names of streets and neighborhoods pasted on the wall there at home represent my real city?

  • The plaster cast my dentist made represents my mouth real?

  • The plan that the architect made of the building where I work represents the real place where I work?

The answer to all these questions is yes and No :

  • The map helps me find an address but does not tell me which streets have good sidewalks so I can walk quietly.

  • The dentist's mold helps him solve my teething problems but couldn't help another doctor diagnose a mucosal problem.

  • The architectural plan of the building where I work helps in a renovation or in the rearrangement of the furniture but does not speak anything about the cooling in the office, the relationship between people, the projects on which we work, etc.

I.e.:

A model actually represents a real-world object, depending on the perspective or abstraction that interests the solution of a particular problem.

No type of model in this universe is able to represent an object with all its features and functions. No model is even capable of representing only the most important features and functions of an object!

Each model needs to represent only the characteristics and functions of an object that are of interest in solving a specific problem. This is what OOP is for and it is with this idea in mind that you will be able to find the right abstractions.

A is minimal, ridiculously small set of features and functions of real objects that interest us when drawing a solution, we can call it domain of the problem; or, for brevity, we can call only Domain.

Already the drawing of the solution, the translation of the domain to objects, we can call model, and the activity of drawing the model we can call modeling.

I think what I wrote So far you already knew, but it's good to line up. So that you also know that the next topic, instead of calling itself how to transform the real world into a model of objects , it is called:

How to model the domain?

Object orientation is not the most difficult.

Representing the real world (within the concept already explained here) using object orientation is also not.

What is more difficult is to convince the programmer to forget about the technology for a moment and focus on the problem of the real world that needs to be solved.

When the topic is "object orientation", you hear a lot of people talking about" inheritance"," polymorphism"," interface"," generics","Orm"...

Programmers don't spend an extra minute to get a deeper understanding of a business requirement, but they don't mind spending hours trying to map via Orm a (unnecessary) entity inheritance to the database.

It turns out that it is the business requirements, the domain of the problem, that it will deliver the information you need to find the right abstractions.

Careful conversation about the domain, with people who understand the domain, will reveal the names of the objects, the delimitations of these objects, their attributes and functions; and will also reveal the interactions between these objects and how they should be coordinated for the solution of the problem.

Many programmers impose on themselves the limiting belief that the client does not know what whether. Working with this premise leads to poorly designed software, overly complex, marked by waste and that does not solve the problem well.

Engaging the customer (see "product owner" and "domain experts") is what will help you understand the domain and therefore identify the correct abstractions.

Knowledge and experience

It is clear that technical knowledge of object orientation is indispensable, since the domain expert does not he'll teach you how to program.

Knowledge of design patterns (formal knowledge or just by experience itself), it is also fundamental for you to make good decisions about how to coordinate the work of objects.

But this kind of technical knowledge is not what will determine a good or bad modeling; it is just a prerequisite. The determining factor is the knowledge of the domain and, logically, the application of this knowledge in modeling.

As material of study, if you already have experience with OOP and design patterns and everything else, I recommend Eric Evans ' Domain-Driven Design.

I point to this book when the programmer has already reached the maturity of realizing that his technical knowledge is not being enough to successfully design and implement great software.

It is always good to remember that the whole philosophy contained in this book only makes sense in complex domains (which is not the case for example of small mobile applications, more registration or consultation websites, or even large and distributed systems with millions of users but with low business complexity).

 5
Author: Caffé, 2020-06-11 14:45:34

Object-Oriented Design: historical context and current situation

In the early 90s there was an explosion of object-oriented application development methodologies competing with each other, many with CASE tools of their own, called "method wars". Among the books cited in the Question, Object-Oriented Analysis and Design with Applications describes Booch's method, and Object Design is the updated version of the proposed RDD method initially in the book Designing Object-Oriented Software . Also noteworthy are the UNWTO, by James Rumbaugh, and the oose, by Ivar Jacobson. 1 2

Booch, Rumbaugh, and Jacobson ("the three friends") came together with the intention of developing a unified method, but what stood out was the creation of a unified notation for their and other individual methods, the UML (Unified Modeling Language ). 3

Therefore remains the question of which of the methods to use, in parallel with the growing adoption of Agile software development methods/frameworks that do not establish a specific design approach. The methods of the 90s are considered more "planned design", as opposed to the so-called "evolutionary/continuous/emerging design" which can be done more ad hoc during development. Martin Fowler suggests combining the two approaches. 4

If there is something wrong please correct me.

Specific points

I will finish answering the question with what I have learned so far after some checks and correcting some wrong impressions I had when I did it.

  • For a problem there are many reasonable solutions and some great ones. In addition, different design approaches (RDD, DDD, etc.) can even be combined with each other in a beneficial way. So @utluiz is right, there is no such thing as correct design and not a canonical material, we have to read as much as we can on the subject. Often though, says Rebecca, you first make the code work and then worry about making the objects simpler.

  • Yes, objects are like mini-machines, but there is no impediment to them providing a single command. The principle er-er does not actually generalize the idea that objects terminated at - er are bad, this is a misinterpretation of it. Bertrand Meyer warns for objects with a command only but only in the case that they do not even have a parameterized constructor (yes, it is probably a procedure disguised as an object).

  • The spirit of the principle Tell Don't Ask (keeping the data and the behaviors that manipulate it in the same place) is good and valid for the general case according to Fowler and Rebecca, but there are some situations where it is interesting to separate them (by example, in the DDD standard Specification).

  • Personally I have the almost automatic habit of applying DRY as soon as the first sign of duplication appears in the code, creating functions or new class hierarchies. This is part of my problem in saying that I create classes by default, and it has the name of premature generalization. Every design decision must be made carefully because it engenders the code and generates a cascade effect on other design decisions. Be then times when it is better to let duplicity happen for a while until you have a good view of the code so that the decision to generalize is more correct.

 3
Author: Piovezan, 2020-01-22 22:59:03

Well, although I think that no answer is adequate to your question, I will risk helping you on the path you want to walk.

The direct answer to your question " How to identify classes in an object-oriented system?", would be "what makes sense with regard to the separation of responsibilities of your application, focusing on reuse seeking not to duplicate unnecessary code".

In a broader context, the identification of classes in an application, although some techniques passed by some authors can help you in various ways, in the end it is really their experience and systemic vision that will hit the hammer.

I would say that identifying these classes and the relationship between them (inheritance, polymorphism, attributes) is a combination of common sense, knowledge and mainly, Experience.

I always say that programming and designing systems is not like "building a wall," it's much more like "painting a wall." framework". Someone can even teach you how to apply colors, but only you, using your common sense, knowledge and experience can decide which color to use at what time to use them, and I would say more, only after applying the colors a few times you will pick up the way of which are better to use at the most appropriate times.

As for your doubt regarding references, I would say, read them all. The first one will give you a cool view of UML, which is an interesting step to better understand object orientation and also an interesting way to learn how to identify classes, since the use case identification exercise is an important step in this path. The other references are very technical, and I even highlight Heads First, despite finding a technical and massaging literature (reading, exercise, small questions... for those seeking certification).

Still I recommend for you the book " the Pragmatic Programmer " by some reasons:

1-it is not a book focused on language and knowledge of OO has no direct connection with the language you use. 2-it is a book that explains everyday situations of a programmer, presents playful scenarios and concepts of "Broken Window", "Bend or Break" and " Stone Soup" 3-I see as mandatory literature for any programmer who wants to design architectures and accumulate good practices as it seems to me to be your case.

As to the final excerpt of your question, I believe I answered a good part of it in the initial introduction and throughout this extensive response.

I end here leaving two precious tips for you:

  1. Security about technical decisions made correctly, whether they are OO or not, come with experience in technology and thousands of wrong decisions made. Both of the others, and yours. Do not be afraid to make a mistake, but also do not make a mistake by not consulting the people around you.
  2. books help you to apply the colors and are essential in this walk, because they help you build a conceptual baggage that day to day can not. I know many programmers who do things in automatic and do not know why they are doing it. Those days even one of the guys here applied a Singleton pattern to me and didn't know it was a pattern design, he just knew it solved his problem. On the other hand, only day to day will give you the feeling of how to apply each of these concept.

Hugs and good luck

 2
Author: Thiesen, 2016-01-19 18:53:35