Concept-Oriented Programming - Introduction

Discussions

News: Concept-Oriented Programming - Introduction

  1. Concept-Oriented Programming - Introduction (16 messages)

    In Informal Introduction into the Concept-Oriented Programming, Alexandr Savinov describes a new approach to programming based on using concepts instead of conventional classes and inclusion relation instead of inheritance. It generalizes OOP and allows the programmer to modularize cross-cutting concerns. In CoP, a great deal of functions is executed implicitly during object access via custom references with custom behaviour. There are several important points about this new approach briefly outlined below. Concepts instead of classes Use concepts instead of classes in OOP where a concept is defined as a pair of two classes: one reference class and one object class. If a concept does not define its reference class then it is equivalent to a conventional class. Both objects and references possess some structure and behavioral methods. One simple consequence of having concepts is that objects are represented and accessed indirectly using custom references with arbitrary domain-specific structure and functions. Inclusion instead of inheritance Inclusion relation is used in CoP where inheritance is used in OOP. Inclusion generalizes inheritance and, if a concept does not define its reference class (and hence is equivalent to a class), then inclusion is equivalent to inheritance. In the general case inclusion relation is interpreted as IS-IN relation while inheritance is interpreted as IS-A. As a consequence, a parent object may have many children. Another consequence is that object references have a hierarchical structure, i.e., they consist of several segments similar to postal addresses. Thus objects exist in a hierarchical address space which is modeled by the programmer. Dual methods Each concept has two definitions for each method provided in its reference class and object class. However, when methods are used they are applied to variables without any indication what definition to call, i.e., methods are used precisely as it is done in OOP. In order to resolve this ambiguity CoP introduces the mechanism of dual methods which specifies the necessary sequence of access. One property of this mechanism is that it is still possible to override parent methods by children but in addition it is also possible to override child methods from the existing parent. In the latter case the parent object will be able to actively intervene into the sequence of access by intercepting incoming method calls. Cross-cutting concerns The ability of parents to intercept all access requests independent of the type of the target child object makes it possible to modularize cross-cutting concerns existing in the program. This means that parent concepts play a role of aspects in AOP but do it completely differently. They are able to transparently inject the necessary intermediate functions when target object are about to be accessed. In this sense CoP can be viewed as an alternative to AOP. Data modelling CoP is part of a new approach to data modelling, which is called concept-oriented data model (CoM). This data model consists of two parts: identity modeling and entity modeling (just because concept is defined as consisting of two parts). CoP is deals with identity modeling (while entity modeling is based on other principles). Therefore it looks quite promising from the point of view of integrating programming and data modeling (so called impedance mismatch in its different forms).

    Threaded Messages (16)

  2. Interesting concept[ Go to top ]

    This sounds a bit like a DSL for semantic-driven programming, typically to describe knowledge and relationships in things like Topic Maps or Semantical Networks. Lots of work has been done in this field with frameworks written in Python, Perl, Java and so on... Can you elaborate a bit more on this? What are the practical benefits/experiences so far in terms of describing, representing and mapping models from concept to actual code the CoP way? Would the code be easier to read, write? Would there be less code? Would this mean a new language all together or an conceptual extension to already existing languages like AOP was/is to Java for example? Nice... /Mikael
  3. Re: Interesting concept[ Go to top ]

    This sounds a bit like a DSL for semantic-driven programming, typically to describe knowledge and relationships in things like Topic Maps or Semantical Networks. Lots of work has been done in this field with frameworks written in Python, Perl, Java and so on...

    Can you elaborate a bit more on this?
    In its current form, CoP has nothing to do with DSLs and LOP. Yet, there exist some ideas how CoP can be adapted for that purposes. It is one of the goals for future work but integrating language-oriented features will requires significant changes in the conception. As usual, the main problem consists in providing more meaning without adding new features/mechanisms.
    Would the code be easier to read, write? Would there be less code?
    Hopefully. As usual, we will get the advantages only if we follow the corresponding design principles behind this approach.
    Would this mean a new language all together or an conceptual extension to already existing languages like AOP was/is to Java for example?
    It is intended to be a new language which generalizes OOP, i.e., one of the primary design goals consisted in avoiding new features/mechanisms but rather generalizing existing mechanisms by modifying their behaviour.
  4. My first impression after reading this article is that COP took bunch of OOP and AOP concepts and simply renamed them Inclusion instead of inheritance: Has the same meaning as composition vs. inheritance. Can be implemented as an inner class or an instance variable Dual methods: Can be accomplished by calling a super class Cross-cutting concerns: This a simple use of AOP. Saying that COP provides an alternative to AOP would be equivalent to saying that using logging a cross-cutting concern is an alternative to AOP Thanks, Sergey
  5. Inclusion instead of inheritance: Has the same meaning as composition vs. inheritance. Can be implemented as an inner class or an instance variable
    There is a fundamental difference between storing a reference to our parent and to having some object as a parent. In general, parent cannot be changed, it cannot be stored by reference. An object is thought of as existing in its parent physically. Existence means having its identity within this parent and hence objects are born within some parent and die within this same parent. So strictly speaking, the phrase "referencing a parent" is meaningless or it means some other mechanism or pattern different from the logic of inheritance. In the same way a parent cannot be included by value into its child - it is already some other mechanism.
    Dual methods: Can be accomplished by calling a super class
    This leads to repeating code because numerous children have to make one and the same super method call (although it might be not their business logic = mix of concerns). Another problem is that we want to enforce the intervention of the parent so that child objects cannot overcome that (say, security checks). In other words, we want to do something implicitly by the parent as soon as any its child is about to be accessed.
  6. Inclusion instead of inheritance: Has the same meaning as composition vs. inheritance. Can be implemented as an inner class or an instance variable

    There is a fundamental difference between storing a reference to our parent and to having some object as a parent. In general, parent cannot be changed, it cannot be stored by reference. An object is thought of as existing in its parent physically. Existence means having its identity within this parent and hence objects are born within some parent and die within this same parent. So strictly speaking, the phrase "referencing a parent" is meaningless or it means some other mechanism or pattern different from the logic of inheritance. In the same way a parent cannot be included by value into its child - it is already some other mechanism.
    Hi Alexandr it is quite possible that I am simply not getting it. I had the same thing with AOP, before I grocked it and started using it. So, please take my comments with a grain of salt. When I was commenting on composition vs. inheritance or what you are calling an inclusion vs. inheritance I have listed two options: instance variable or inner class. Inner class is a true inclusion since it is born with a parent object and dies with a parent object. In other words the parent controls entire lifecycle of the child object. It is modeled as a shaded diamond in UML.
    Dual methods: Can be accomplished by calling a super class

    This leads to repeating code because numerous children have to make one and the same super method call (although it might be not their business logic = mix of concerns). Another problem is that we want to enforce the intervention of the parent so that child objects cannot overcome that (say, security checks). In other words, we want to do something implicitly by the parent as soon as any its child is about to be accessed.
    This is can be easily accomplished by before or around advise. You can implement custom security for the children. You can invoke custom code on the parent when a method on a child is invoked. Thanks, Sergey
  7. When I was commenting on composition vs. inheritance or what you are calling an inclusion vs. inheritance I have listed two options: instance variable or inner class. Inner class is a true inclusion since it is born with a parent object and dies with a parent object. In other words the parent controls entire lifecycle of the child object. It is modeled as a shaded diamond in UML.
    Here a list of some properties of inclusion relation in CoP:
    • Objects exist within a hierarchy at run-time which is modelled by concept hierarchy using inclusion relation. In other words, a parent may have many children and vice versa many children can share one parent object.
    • Parent can exist without children at all while children can be added later (created in its context and distinguished by their own local references). A fully qualified reference then consists of the parent reference as high segment and child reference as low segment.
    • When a completely new child is created, its parent is created before it.
    • Parent constructor will be called before any its child constructor will be called.
    • Parent can be viewed as a container for its children.
    • Inclusion hierarchy consists of reference-object pairs. A fully qualified reference of an object is a sequence of reference starting from the root and ending with this object.
    This is can be easily accomplished by before or around advise. You can implement custom security for the children. You can invoke custom code on the parent when a method on a child is invoked.
    Sure, AOP can solve this problem. Moreover, AOP provides much more flexibility in injecting arbitrary code in arbitrary points of the program. Yet, it is precisely what we do not want to have in CoP because this results in spaghetti code. Instead of this almost complete freedom of code injection, we want to impose strong constraints on this mechanism and for that purpose a completely different set of basic assumptions is used. In particular, we are talking about a well defined sequence of access which must be followed by any access request. As an access request (say, method call) follows this sequence it triggers some intermediate functionality. In terms of AOP this functionality is injected while we say that our access path intersects some point on its way to the target. Let us assume that from point A we want to access point C (say, we apply a method to object C). In AOP we can use advices in order to execute some intermediate function (say, print a message) before C is reached. These intermediate functions are described in aspect B which involves C in its specification. In CoP, the target point C is included into parent concept B and B is unaware of C. Now any access path leading to C will necessarily cross B before it reaches the target and hence B can do its intermediate job.
  8. Alexandr, I would be interested in seeing exactly where OOP & AOP are weak, using a *real world example*; for instance maybe you've taken an existing piece of software, written in Java and utilizing AOP, and rewrote it using COP concepts? If you don't have this already, it might be a good topic for a paper (I've glanced over the documents on conceptoriented.com, and didn't see anything like this, so if I've missed it, please feel free to point it out). Thanks, Thomas
  9. Let us assume that from point A we want to access point C (say, we apply a method to object C). In AOP we can use advices in order to execute some intermediate function (say, print a message) before C is reached. These intermediate functions are described in aspect B which involves C in its specification. In CoP, the target point C is included into parent concept B and B is unaware of C. Now any access path leading to C will necessarily cross B before it reaches the target and hence B can do its intermediate job.
    Alexandr, do you mean your aspect bindings are done outside the aspect definition? -- Bill Burke http://bill.burkecentral.com
  10. Alexandr, do you mean your aspect bindings are done outside the aspect definition?
    What I mean is that in AOP two tasks - (i) writing code to be injected (advice) and (ii) declaring target points for injection (pointcut) - are made within one module (aspect). As a result, aspect has to be able to somehow guess where its help might be needed after it is written, i.e., it has to be able to predict future. (As a solution, the mechanism of patterns is introduced which allows us to intensionally outline the border describing the pointcut.) If we were using these AOP terms then CoP would follow the opposite direction for declaring dependencies. Namely, each "aspect" would be responsible for only defining its advice(s), i.e., the code that can be used somewhere in the program/system. Yet, "aspects" do not know where this code will be "injected" and do not care how it will be used - describing pointcuts is not their task. It is the responsibility of the "join point" itself to declare the need in getting some support from an "aspect". Now if a new module is added, then it declares an "aspect" from which an "advice" has to be "injected". In such a reversed approach the direction of declaration is from the target (join point) to the aspect while in AOP it is aspect that point to the target. Of course, such a modified (reversed) version is not already AOP (this is why I used quotes) but I have described it to illustrate differences from CoP. It should be noted that CoP itself has a little to do with AOP because its main goal is indirection of representation and access. Yet, at some general level they might well be compared. Here is how CoP approach could be projected to AOP terms: aspect Logging { advice { print("Begin. \n"); proceed(); // Go to the target method print("End. \n"); } // No pointcuts - no forward links } class Target1 i_need_help Logging { void myMethod() { ... } } class Target2 i_need_help Logging { void myMethod() { ... } }
  11. Excuse me for being blunt but this is an honest question, what problem is CoP trying to solve? What pain points in the current OOP approach that CoP try to solve that haven't been solve by AOP or any other approach? I couldn't find any in this post, nor the linked article.
  12. Excuse me for being blunt but this is an honest question, what problem is CoP trying to solve? What pain points in the current OOP approach that CoP try to solve that haven't been solve by AOP or any other approach? I couldn't find any in this post, nor the linked article.
    Consider the following two major problems:
    • Indirection of object access - we want something to happen when an object is being accessed. We reject the assumption of instantaneous action and switch to the view where any access means execution of some intermediate code which cross-cuts the whole system. This intermediate code executed during object access is one of the primary concerns in CoP.
    • Indirection of object representation - we want to represent objects using custom addresses rather than primitive references. In system design this means that we create a virtual address space where objects can live (identity modelling). These addresses should be active elements and in CoP they have structure and behaviour (just as objects). In particular, a system may possess quite complex functionality even if it does not have objects in it.
    So CoP is about how objects are represented and accessed (indirectly). Yet, it is backward compatible with OOP, i.e., it is reduced to OOP if we do not need and do not use these mechanisms.
  13. Why do I need this?[ Go to top ]

    Seriously, is there some *simple* example showing pain points in Java and correspondingly a better COP equivalent example. Like one of the other posters in this forum, I didn't get AOP for a while, and so am interested to get the main point of COP so I don't miss the boat if there is in fact a point to it. I don't feel like I have any pain points with Java/Spring/AOP/DI at the moment (don't want to turn this into a Spring post!). I also read a fair bit of the material on the linked site but ended up just imagining what some equivalent might be in Java. With DI, there was the MovieFinder example, which I believe Martin Fowler may have contributed -- which leads to easier wiring up of code, unit testing, etc. With AOP, there was logging, security, transactions, which centralises a concern into a small number of classes. What's the elevator pitch benefits of COP?
  14. Is there any relationship between this version of concept-oriented programming and the version described in this -99 article: http://www.ddj.com/184410968?
  15. Serializable proxies[ Go to top ]

    Is CoP more than a mechanism of serializable proxies?
  16. Re: Serializable proxies[ Go to top ]

    Is CoP more than a mechanism of serializable proxies?
    Both proxies and CoP could be characterized as means of indirection. However, proxy is a design pattern that can be implemented in various ways within different approaches. In contrast, CoP is a methodology which actually postulates indirection as one of the primary concerns and then derives the necessary programming constructs, mechanisms and patterns. Essentially, CoP says that (in complex programs) it is more important what happens in-between during object access rather than in the target object and hence its facilities are aimed at modelling indirection and intermediate behaviour. There are many more specific differences between proxies and CoP. For example, proxy is used explicitly, i.e., we call methods of proxy in the program and then the proxy can delegate their execution to other (target) object. In CoP, we use target object while the intermediate element ("proxy") intervenes automatically. Another difference is that CoP is aimed at modelling references while proxy is an object. In other words, the main design goal of CoP consists in modelling a hierarchical address space of nested containers where objects are going to live. And one of the properties of this system of containers is that they are able to serve as proxies by intercepting external requests. As to serializability then it is quite subtle topic. From the CoP point of view, the term "serializable object" is a kind of non-sense. Why? Because it is the property of references to be serializable while objects cannot change their location (and even cannot be directly observed and accessed). We introduce references as first class citizen in order to have a mechanism of data transfer (by-value or by-serialization). If we serialize an object then this means that we take data from it and then (normally) create its clone which is however a different object. In OOP, proxies are objects which are intended to represent other objects and hence they play a role of references so it is a simulation of references using objects. In CoP, we have references as a means of representing objects and hence we do not need the mechanism of "object serialization" because reference are passed by-value by definition.
  17. I think the inclusion relation fundamentally changes everything and a lot of people here miss that. Keep up the good work!