Object-oriented analysis in my eyes

Source: Internet
Author: User
Tags abstract definition

Object oriented

It seems that I have not learned any other way of thinking, object-oriented is a common way of thinking when I am programming, because I think it is more close to our life, it is easier to understand and define what the program wants to express. That's why I use that mindset to analyze and design programs whenever a project is to be opened. After years of discovering that it did have its charms, it helped me solve many of the problems in design. So I summed up, in the following section to talk about object-oriented use of some of the experience.

Give your program a "class"

The object-oriented foundation is the design of "class", which directly affects the structure of the program. So, how can we design a reasonable type? I think that we should start from the actual demand, extracting various entity objects in the demand, and finally form the objects used in the program. Some students like to bury their own programs, add a lot for future expansion of the type, in fact, I do not recommend over-design, I think can be mentioned in the requirements of entities to reserve some functional extensions, but not recommended for the requirements of the function point design type, because, You will never be sure what the future development of the product will look like, the final shape is how, it is possible that the point you buried before the time to achieve, the program needs to be reconstructed and so on will lead to your extra work becomes useless.

If the company asks you to make a nearby stranger friend app. From the app's needs, you can extract near , strangers , and dating three keywords, which are described in a relative geographical location so it should be a property of a class, A stranger is also a person-to-person relationship relative to someone, so this is broken down into a person entity, and a relationship to another person entity. And the last friend keyword actually implies a relationship-building behavior, which can be chat , or other ways to make friends. We further analyze, if the app is provided with chat functionality, then there is an implicit entity in the requirements, that is, the content of the chat. So, depending on the requirements, we can design two types :

//用户类型class User{    //地理位置    property location : Location;    //用户的好友    property friends : Array<User>;    //给某个用户发送消息    function sendMessage(user : User,  message : Message) : void;}//聊天内容class Message{}

This is the type that is driven by demand, and these types are the core classes that complement and expand the requirements to continually meet the needs of the future.

Make types also conform to database entity design

The third paradigm is often mentioned in relational database design, which is characterized by the removal of direct dependencies in the table . This means that two entity objects should not be designed in the same table, such as: The comment table has a record is a user post comments, may be the user name and other information classified into the comment table, which is not in line with the third normal form requirements, the correct way is to put the user information into the user table, A user ID can be retained in the comment table to identify user records in the user table, thereby eliminating the reliance on user information directly in the comment table, resulting in redundancy of user information.

In fact, I personally think that this paradigm requires a good division of the boundaries between entities, for the design of the class is also applicable. For example: You define a human being, which has the properties of limbs and the act of speaking. This is well understood, because people in reality have these traits. However, in the subsequent development process due to the change in demand, the emergence of human beings because of the flying props can fly. And the conduct of flight directly to human beings, this diagram of the easy way is actually a lot of drawbacks:

    • First of all, it is not easy to read, because the common sense that people can not fly, people will fly, it must be a bird man. So it's going to make people feel confused.

    • Another is that this definition often restricts other colleagues who are collaborating with you to develop. Because most of the situation we will be able to keep the old code as far as possible not to move, so as not to move the problem. So the design of you so that people have to follow the existing thinking to expand. Until one day there is no way, then a thorough reconstruction.

So a better approach would be to define a prop class. As for what function the prop implements, it is implemented by its subclasses:

// 道具基类class Item{    //道具的行为     function action(target : Person);}//飞行道具class FlyingItem :Item{    function action(target : Person)    {        //飞行的实现代码    }}

Such implementations can separate the coupling of human and prop types, and also increase the expansion of prop types. Therefore, it is important to distinguish the boundaries of the entity when designing the type.

Another database design uses more of the entity's relationship description. Entities have different relationships, and they differ when designing tables to store data. There are typically three entity relationships:

    • One-to-one, that is, the relationship between two entities is one by one corresponding. Such as: A Chinese citizen with his identity card is the only binding, know the identity card can find the corresponding person, the same corresponding person can also find their corresponding unique identity card. Similar to this, it is common to create two entity data tables, and then the relationship can be placed in two entity tables at the same time.

    • One-to-many, that is, between two entities, the first entity can correspond to multiple second entities, but the second entity can only correspond to the only first entity. As an example of user reviews, users can send multiple comments, but a comment can only be issued by a specific user. For this kind of relationship, it is usually the creation of two entity data tables, and then in the corresponding multiple entities in the data table record the relationship, take the example above, is the user table and the comment table, and then the comment table will be put into a userid and other identifiers to record the corresponding relationship with the user.

    • Many-to-many, that is, between two entities, the first entity can correspond to multiple second entities, and the second entity can also correspond to more than one first entity. For example, the relationship between the author and the book is a many-to-many relationship, where an author can write more than one book, while a book may be written together by several authors. For this relationship, you need to create two entity data tables and a relational table to describe them.

In fact, the most important thing to say about the entity relationship is that the analysis of the relationship is indispensable in the aspect of object-oriented analysis and design. But how to assess the division and attribution of relationships, I think it is a good idea to follow the relational design criteria of the database.

    • One-to-one, in this relationship, in fact, the description of the relationship can be placed in two types, such as the above mentioned Chinese citizens and ID card examples, using classes can be described as:
class  chinese   {// Name property name:     string ; // corresponding ID property idcard:  idcard ;} class  idcard   {// ID Number Property id:     string ; // corresponding person property person:  chinese ;}  
    • One-to-many, this kind of relationship, slightly different from the database table design, because the data table can be queried to find the entity corresponding to a number of other entities, which is beyond the class design phase of the category. Therefore, the types that correspond to multiple class instances need to define the properties of a collection to preserve the corresponding instances of the class. This can also be very well understood when reading the code, taking the example of user comments:
class User{    property comments:Set<Comment>;}class Comment{   property user:User;}

This is a good way to describe how many comments a user has made, and then which comment is the user's comment.

    • Many-to-many, this is a very complex relationship, mainly in many cases, we will ignore such a relationship, direct it into a one-to-many relationship design. In fact, in the case of a situation we can be the processing of its relationship to another type of processing, as the database table design, two entity types, a relationship type. Take the relationship between the author and the book, for example, can be designed to look like this:
//Author Book Relationship Management type class authorbookrelationshipmanager{   //Set author information for a book   Static  function setbookauthor(Book:book, authors:array<author>) : void;    //Get the author of the specified book    Static  function getauthors(book:book) : Array<Author>;    //Get a book for the specified author    Static  function getbooks(author:author) : Array<book >;}//Author type class Author{    //Author nameProperty name:string;//Get books published by authors     function getbooks() : Array<book > {        returnAuthorbookrelationshipmanager.getbooks (this); }}//book Type class book {    //Book nameProperty name:string;//Get author information for a book     function getauthors():Array<Author> {        returnAuthorbookrelationshipmanager.getauthors (this); }}

As you can see from the code above, a Authorbookrelationshipmanager type is used to manage the relationship between books and authors. The entity type is then no longer saved between the relationships, and the entity to get the related entities needs to be obtained through the Authorbookrelationshipmanager type.

The above mentioned entity Division and the relationship Division in the object-oriented has very important significance. Usually need more practice in the face of actual project development to make a reasonable classification, so that their development of the architecture more flexible and more powerful.

The above for the type of design is basically finished, it is time to say something about inheritance, this is a very powerful object-oriented features. It can improve the code structure of the problem, saving code writing workload. The following will be around it to talk about my opinion.

The ancestor of all things

In fact, whether it's written in C + +, C #, or Java, and so on, we'll find that as long as the classes are created, they inherit the class from object directly or indirectly. And this object class is the ancestor of all things that I want to say, which is inherited by all things as a root type. Object also has a very good name, which refers to all objects and gives an abstract definition without form. means that we, as the creator of the process, need to change this kind of inanimate object into something of a specific form, which requires inheritance .

So, the function in object does not actually have much, because it does not involve the specific function, so it is very often in the implementation above can only distinguish whether it is the same object isEqual , or tell us its description toString . However, this has a lot of guidance, because as long as you inherit the object type, then your type will get such a function, explain the power of inheritance, and you can also give your subtype object to an instance of object, because object is the root class, It can preserve arbitrary subclass type objects, which is the basic embodiment of object-oriented polymorphism.

With an example of object, it is even more clear that we should design the base class for the project's code during the development of the project. The base class here is a little more specific than the function of object. Because it involves specific requirements for the functionality to be implemented, it should be more than just a base class. Here's how I design the base class.

A contract with the base class.

How to design the base class, in fact, depends on the actual project needs. Assuming that the project you are developing contains a lot of background services, you should define a BaseService base class called, and then differentiate it into multiple service types through this base class. If your project involves a variety of UI processing, then you should consider the possible need for a basic UI management type (usually the UI component has its own base class, where the UI is required to manage and maintain the underlying type), such as: UIController . Then the various UI displays are differentiated according to this base class.

Basically, if the program has many features similar or similar function modules, then you should create a base class for these modules, in order to better expand later. It is not recommended to define a base class for a module that may have multiple approximate functions in the future, or the old adage that your hypothesis is not necessarily true. And wait until the emergence of such requirements in the definition is not too late, after all, to transform is only a type.

Above we know how to abstract out the base class, then the base class should be how to encapsulate the properties and methods, in fact, it can be dependent on its subclasses, because this is the most close to the requirements. As mentioned above, a variety of back-end services, assuming the following types of services:

 class servicea{    //Service nameProperty name:string;//Invoke service     function exec(config:dicationary): void {          //Execution Services}} class serviceb{    //Service nameProperty name:string;//Invoke service      function call(): void {          //Execution Services}}

The services described above are quite different from the code structure above, especially when receiving parameters on the behavior of executing services. If you want to abstract the base class from them, it is really confusing. However, since we are going to abstract the base class, we will certainly be transforming the subclass. I summarize some of the abstract rules myself:

    • The same properties and methods in the subclass to encapsulate into the base class.
    • For the properties and methods that exist for most subclasses (such as 3 or more of the 5 subclasses have the same properties and methods), you can consider encapsulating them in the base class, and no use of the type can ignore the properties and methods of the base class.
    • For attributes that are similar in meaning, consider merging or replacing attributes (for example, by using the ID or name attribute in a subclass to represent the object's uniqueness), then the base class may consider taking only one of the properties or creating a property definition of the set.
    • In the case of a subclass of the same behavior, if the number or type of method arguments declared is not the same, you can consider all the parameters in the method of the base class (that is, the set of parameters of the method) or consider defining the common parameters, the special parameters are converted to the attributes by the subclass (which can be designed in a sustainable way, such as the configuration of the system).

Based on the above, we can ServiceA ServiceB change and, through the abstract base class to look like this:

 class baseservice{    //Service nameProperty name:string;//Invoke servicefunction exec ():void;} class servicea extends baseservice{    //Set parameter as property hereProperty config:dictionary; function exec ():void{//Execution Services}} class serviceb extends baseservice{function exec ():void{//Execution Services}}

Similarly, we can abstract the base class.

Let the type evolve

In the process of developing and maintaining the code, it is inevitable that the product iterations will lead to significant changes in demand. Then there may be the abandonment of some functions or the merging or evolution of functions. At this time, the previously defined types will face the fate of emphasis or adjustment.

In the face of such a problem, let's not rush to reject everything before, and then rewrite it completely. Instead, consider whether there is still something available in the previous definition. To extract the modules that can be reused, the choice of modules is what we need to evaluate.

If the new requirements are deprecated, the types involved in the module can be discarded. For the processing of these modules, I personally prefer to delete the relevant types directly, and then compile, error after the direct modification of the code referenced to the type until the compilation is successful. For the method that needs to be reformed after missing this type, I will temporarily do not transform, but mark (such as TODO or warning macro), wait for the official development new function to look for these tags to solve each.

If the new requirements include this kind of functionality, but also incorporate some new elements, then our type cannot be used directly. To evaluate whether a new element is part of a type, or a new type. For example: A chat app that starts with private chat (one-to-one chats), then sends the message in the user type:

//用户类型class User{    //给某个用户发送消息    function sendMessage(user : User,  message : Message) : void;}

In the second version, the user may be able to send a message to a friend. Then, obviously the above code does not meet the requirements, this time the type needs to be modified:

//user type  class  user  { //send a message to a user  function  sendmessage   (User:user, message:message)  : void ;     //send messages to multiple users  function  sendMessage   (USERS:ARRRAY<USER>, message:message)  : void  { for  (user user in  users        {this . SendMessage (user, message); }    }}

Added a SendMessage polymorphic version of the method for mass messaging. This can not only ensure that the method of export unification, but also to ensure that the previous method is not modified, you can easily solve the problem of mass.

Then, to the third version of the concept of the chat room, this time there is more than one chat room keyword, using the method mentioned earlier, here should be a new type, not directly in the user type extension. Then, it can be designed to:

//聊天室class ChatRoom{    //聊天室名称    property name:String;    //聊天室用户    property users:Array<User>;    //发送消息    function sendMessage(user:User, message:Message):void;}

This adds a ChatRoom type that is primarily used to record which chat rooms those people are in. The type has a sendMessage method that indicates which user is going to speak in a chat room and what the content of the statement is.

As can be seen from the above example, product iterations sometimes need to be typed, and sometimes new types need to be born. To make that choice, you need to decide according to the product requirements.

As long as this polymorphic

Polymorphism in my understanding is a variety of states. Just like when we take things with our hands, if we take the ball, then we may want to play, and if we take an apple, we may have to eat it. We may make different reactions depending on the different things. Polymorphism in object-oriented is used to solve this kind of problem. Let's assume that when there is no polymorphism, our code looks like a bit of a setback:

function doSomething(obj:Object):void{    ifinstanceof ObjectA)    {        //do something by ObjectA    }    elseifinstanceof ObjectB)    {        //do something by ObjectB    }}

The more types you want to judge, the longer the IF statement. Then, with polymorphism, we can design it elegantly:

function doSomething(obj:ObjectA):void{    //do something by ObjectA}function doSomething(obj:ObjectB):void{    //do something by ObjectB}

Polymorphism can ensure that the code design of the export name is unified, do not need to call the external calls to different types of names according to different methods, for external calls only need to pass in different types to determine which method to invoke.

I do not recommend polymorphism if it is not the problem that is addressed above. Because polymorphism can complicate the type, if the polymorphic type is inherited and then the inherited subclass is polymorphic, it can affect the quality of the program, and the difficulty of troubleshooting will increase in the event of a problem.

Something

The above is what I personally understand in the development of these years, object-oriented this thing already exists in my mind many days and nights, always thinking about what to write, today finally finished it. Follow-up I will continue to write some other articles about the thinking of the program, I hope you support.

When writing this article, there is no reference to other information, there may be errors and omissions in the place. If you are a good-hearted ape/yuan, please correct me.

Object-oriented analysis in my eyes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.