An object’s state, describes its current condition. If object was a human, this could be their emotional state (e.g happy, sad, angry). To think a bit further, the height value in an object’s field is not a state, but the height’s value help us to define it’s height category (e.g tall, short, average), that is actually the state. And it is the state, based on the context we, as society, have set on defining when someone is considered tall or not.
An OO software system is an objects graph. Objects exchange messages, and based on the message content an object changes it’s state or not. Other objects do not directly read or write the state of another object. The state itself, must never leak out of the object to another. In short, objects do not share any references to state, but instead only report to each other with copies of stateful data. In this fashion, each object is the sole manager of its own state.
But this only half of the story. If we are too strict with the state management, we will not finally have a graph of objects, but rather a strict flow of composition (object B has no meaning or purpose in the system without A) or aggregation (B exists independently (conceptually) from A).
The state will be concentrated to a root object, itself composed by a number of stateful objects, which in turn may be composed of stateful objects. The objects of this hierarchy may pass messages to their immediate children, but not to their ancestors, siblings, or further descendants.
How fragile is the object’s state?
I am sure, that all of us, have worked with source code of a flexible or nonexistent hierarchical pattern at all. We need indeed to be (maybe more) flexible in our everyday work, and the source code is a part of it, but we might end up with objects leaking state.
But a wonderful clean hierarchy is needed when the specifications ask for it. While we organize our objects into a specific hierarchy, the state management is enforced to follow the same pattern. If our business logic is something trivial, probably we will have no trouble at all.
How do we handle use cases that involve multiple objects that are not directly related? One solution could be a common ancestor, other possible solutions is to use the Mediator pattern of the actor model. The larger the software, the more complexity there is, so we have to be really careful with the objects state management. Shallow hierarchies as possible, allow us to successfully manage state . For more information please read here.
Types of immutability
Object itself has no fields or properties that can be changed. This object will remain totally unchanged through its life cycle. For reference types the field must be read only and the type must also meet the immutable guidelines. Types that meet the immutable guidelines, are inherently thread safe. They are not subject to race conditions because they cannot be changed and thus viewed differently between threads .
The direct contents of this object must be immutable in the sense that they cannot be changed to point to another object. However there is no guarantee that all of the fields are themselves immutable. All of the fields in the object must be read only. For primitive values this is enough to guarantee them meeting the Immutable guidelines and hence Shallow Immutable. For reference types this will ensure they will point to the same object thus doing all that is needed to meet the Shallow Immutable Guarantee. Types with this guarantee are thread safe to a degree. They are thread safe as long as you are accessing the fields with meet the Immutable guarantee. You can also access the references which are read only as long as you do not call any instance methods. For instance a Null check is thread safe .
Shallow Safe Immutable
Slightly stronger guarantee than Shallow Immutable. For all fields that are read only but not immutable, the type must be thread safe. Types which meet this guarantee are thread safe also to a degree. They are as thread safe as the fields which are guaranteed to be thread safe .
Benefits and a drawback of immutability
No matter if we decide to use immutability a lot, or enforce it, or use it partially, the goal has always to be the minimization of state usage. Immutability is not a binary decision. It depends on the requirements we have in hand. There is not a specific decision threshold on picking strict immutability or not. The benefits of immutable objects could be summarized to the following (probably incomplete list):
Immutable objects always return new objects and not copies
Immutable objects and caching. The cached object is the same with the one in the execution flow. It doesn’t change.
* An immutable object throws an exception, it will never result with the object left in an indeterminate state. This term was coined by Joshua Bloch.
However, if a modified version of an immutable object is needed, we have to suffer the penalty of creating a new object. This must be handled with care in terms of Garbage Collection (GC).
Examples of immutability
Instead of writing numerous examples, I provide you Jon Skeet‘s excellent presentation about immutability. He explains, in details with source code examples, whatever is mentioned, more or less, in this article.
And a bonus video regarding the fundamentals and how data structures affect the way we develop. They effect immutability as part of the big picture.
Immutability is like a big ship. Skills are needed to pilot it, but you have to be careful. A good solid knowledge of OOP is necessary. Try to keep the objects graphs as small as possible, and minimize the dependencies between the objects. We will discuss about the degree of dependency in a future article.
The next episode
In the next episode, we will discuss again about the object’s state and its (im)mutability and its relationship with Inversion of Control and especially with Dependency Injection.
Live without your sunlight, love without your heartbeat
Jareth the Goblin King – Labyrinth (1986)
A small article about the internet object. Internet object is one more format for sending data over the wire. Specifically:
It is designed for transferring data over internet, Internet Object is a new age serialization/data-interchange format. It is human readable, thin, self explanatory, robust and schema oriented. It was developed by Mohamed Aamir Maniar out of frustrations associated with JSON.
The internet object is separated is two parts: The schema and the values (internet) object.
Please pay attention to the age part of the template. It has a restriction of minimum twenty years of age. The schema includes it’s own validations. Additionally it explicitly refers to the required types: active?: bool, tags?: [string]
The internet object’s goal are the following
Thin & Lightweight: The internet object‘s author, declares that compared with JSON, it reduces the data size to around 40%.
Built-in Schema & Validations: Internet Object was designed with a robust schema support in mind. It checks the data and saves developers’ time by providing built-in data validation support at both ends (Sending and Receiving).
Well Planned & Designed: “Designed after carefully considering the needs; Internet Object encourages the separation of definitions and metadata from data, favors minimalism, supports streaming of large collection and much more“.
Well, in principle, I support this notion, but we have to see how internet object will be able to handle complex responses objects
Simple & Easy: “Internet Object is a minimalistic, text-based, language-independent and human-readable data-interchange format. It is easy on the eyes and quick to start”.
At least for small objects, this is true.
Based on their benchmarks, we have the following results.
For 1 Record(s) =============== IO Data: 495 IO Data with Header: 671 JSON: 887 IO is 44.19% smaller than JSON! IO with header is 24.34% smaller than JSON! For 100 record(s) ================= IO Data: 50862 IO Data with Header: 51038 JSON: 89963 IO is 43.46% smaller than JSON! IO with header is 43.27% smaller than JSON! For 1000 record(s) ================== IO Data: 506234 IO Data with Header: 506410 JSON: 897235 IO is 43.58% smaller than JSON! IO with header is 43.56% smaller than JSON!
It’s been almost twenty years, since JSON and its derivatives came into our lifes, like JSON-RPC and SOAPjr. Other alternatives are YAML and the oldest of all, XML that was dominant during the SOAP era.
If you want to read more about it, here is and article from internet object’s author. Enjoy!
FIWARE is an open source initiative defining a universal set of standards for context data management which facilitate the development of Smart Solutions for different domains such as Smart Cities, Smart Industry, Smart Agrifood, and Smart Energy .
In any smart solution there is a need to gather and manage context information, processing that information and informing external actors, enabling them to actuate and therefore alter or enrich the current context. The FIWARE Context Broker component is the core component. It enables the system to perform updates and access to the current state of context .
The Context Broker in turn is surrounded by a suite of additional platform components, which may be supplying context data (from diverse sources such as a CRM system, social networks, mobile apps or IoT sensors for example), supporting processing, analysis and visualization of data or bringing support to data access control, publication or monetization .
What is context information?
Initially we will describe at how researchers have attempted to define context in the past. While most people tacitly understand what context is, they find it hard to elucidate. Previous definitions of context are done by enumeration of examples or by choosing synonyms for context .
In the work that first introduces the term ‘context-aware,’ Schilit and Theimer refer to context as location, identities of nearby people and objects, and changes to those objects. These types of definitions that define context by example are difficult to apply. When we want to determine whether a type of information not listed in the definition is context or not, it is not clear how we can use the definition to solve the dilemma .
Other definitions have simply provided synonyms for context; for example, referring to context as the environment or situation. As with the definitions by example, definitions that simply use synonyms for context are extremely difficult to apply in practice .
The definitions by Schilit et al. and Pascoe are closest in spirit to the operational definition we desire. Schilit claims that the important aspects of context are: where you are, who you are with, and what resources are nearby.
Pascoe defines context to be the subset of physical and conceptual states of interest to a particular entity. These definitions are too specific. Context is all about the whole situation relevant to an application and its set of users. We cannot enumerate which aspects of all situations are important, as this will change from situation to situation .
Anind K. Dey provides the following definition:
Context is any information that can be used to characterize the situation of an entity. An entity is a person, place, or object that is considered relevant to the interaction between a user and an application, including the user and applications themselves .
Anind K. Dey
If a piece of information can be used to characterize the situation of a participant in an interaction, then that information is context .
Take the canonical context-aware application, an indoor mobile tour guide, as an example. The obvious entities in this example are the user, the application and the tour sites. We will look at two pieces of information – weather and the presence of other people – and use the definition to determine whether either one is context .
The weather does not affect the application because it is being used indoors. Therefore, it is not context. The presence of other people, however, can be used to characterize the user’s situation. If a user is traveling with other people, then the sites they visit may be of particular interest to her. Therefore, the presence of other people is context because it can be used to characterize the user’s situation .
Context aware computing
Context-aware computing was first discussed by Schilit and Theimer in 1994 to be software that adapts according to its location of use, the collection of nearby people and objects, as well as changes to those objects over time .
Anind K. Dey provides the following definition for context aware computing:
A system is context-aware if it uses context to provide relevant information and/or services to the user, where relevancy depends on the user’s task.
Anind K. Dey
Similar to the problem of defining context-aware, researchers have also tried to specify the important features of a context-aware application. Again, these features have tended to be too specific to particular applications .
The categorization combines the ideas from previous taxonomies and attempts to generalize them to satisfy all existing context-aware applications. There are three categories of features that a context-aware application can support :
presentation of information and services to a user
automatic execution of a service for a user
tagging of context to information to support later retrieval
Features of a context aware app
It encapsulates changes and the impact of changes, so applications do not need to be modified. A context related functionality is responsible for acquiring a certain type of context information and it makes that information available to the rest of the system in a generic manner, regardless of how it is actually sensed .
An example is interpreting context from all the devices in a conference room to determine that a meeting is occurring. For example, an indoor infrared positioning system may consist of many infrared emitters and detectors in a building. The sensors must be physically distributed and cannot all be directly connected to a single machine .
Context aggregators aggregate context. We defined context as information used to characterized the situation of an entity. A context aggregator, is responsible for all the context for a single entity. Aggregators gather the context about an entity (e.g., a person), behaving as a proxy for other applications .
What is NGSI?
The FIWARE NGSI (Next Generation Service Interface) API defines:
a data model for context information, based on a simple information model using the notion of context entities 
a context data interface for exchanging information by means of query, subscription, and update operations 
a context availability interface for exchanging information on how to obtain context information (whether to separate the two interfaces is currently under discussion) 
Context entities, are the center of gravity in the FIWARE NGSI information model. An entity represents a thing, i.e., any physical or logical object (e.g., a sensor, a person, a room, an issue in a ticketing system, etc.). Each entity has an entity id. Furthermore, the type system of FIWARE NGSI enables entities to have an entity type. Entity types are semantic types; they are intended to describe the type of thing represented by the entity. For example, a context entity with id sensor-365 could have the type temperatureSensor. Each entity is uniquely identified by the combination of its id and type .
Context attributes are properties of context entities. For example, the current speed of a car could be modeled as attribute current_speed of entity car-104.In the NGSI data model, attributes have an attribute name, an attribute type, an attribute value and metadata.
The attribute name describes what kind of property the attribute value represents of the entity, for example current_speed 
The attribute type represents the NGSI value type of the attribute value. Note that FIWARE NGSI has its own type system for attribute values, so NGSI value types are not the same as JSON types 
The attribute value finally contains
the actual data
optional metadata describing properties of the attribute value like e.g. accuracy, provider, or a timestamp 
The API response payloads in this specification are based on application/json and (for attribute value type operation) text/plain MIME types. Clients issuing HTTP requests with accept types different than those will get a 406 Not Acceptable error.
What is a (Orion context) broker?
A message broker is an architectural pattern for message validation, transformation, and routing. It mediates communication among applications, minimizing the mutual awareness that applications should have of each other in order to be able to exchange messages, effectively implementing decoupling.
The primary purpose of a broker is to take incoming messages from applications and perform some action on them. Message brokers can decouple end-points, meet specific non-functional requirements, and facilitate reuse of intermediary functions. For example, a message broker may be used to manage a workload queue or message queue for multiple receivers, providing reliable storage, guaranteed message delivery and perhaps transaction management. The following represent other examples of actions that might be handled by the broker :
Route messages to one or more destinations
Transform messages to an alternative representation
Perform message aggregation, decomposing messages into multiple messages and sending them to their destination, then recomposing the responses into one message to return to the user
Interact with an external repository to augment a message or store it
Invoke web services to retrieve data
Respond to events or errors
Provide content and topic-based message routing using the publish–subscribe pattern
Message brokers are generally based on one of two fundamental architectures: hub-and-spoke and message bus. In the first, a central server acts as the mechanism that provides integration services, whereas with the latter, the message broker is a communication backbone or distributed service that acts on the bus. Additionally, a more scalable multi-hub approach can be used to integrate multiple brokers  .
So, Orion is a C++ implementation of the NGSIv2 REST API binding developed as a part of the FIWARE platform. The Orion context broker allows us to manage the entire lifecycle of context information including updates, queries, registrations and subscriptions. Using the Orion Context Broker, you are able to create context elements and manage them through updates and queries. In addition, you can subscribe to context information so when some condition occurs (e.g. the context elements have changed) you receive a notification .
The next episode
We will provide detailed information about the Orion context broker, and how to communicate with it a C# client.
I don’t throw darts at a board. I bet on sure things. Read Sun Tzu, ‘The Art of War.’ Every war is won before it is ever fought
Gordon Gekko – Wallstreet (1987) Image from Letterboxd
Let’s assume you are hired to develop a software system for a pharmaceutical company. Till that time, you knew nothing about that specific domain, no more than everybody knows about the pharmaceutical sector and medicines.And the knowledge you carry is from the side of the patient-client.
You start gathering information to build the requirements, but you come to point that you feel ready to start writing code. Well, don’t hurry that much. Are you sure the information you have in your hands is right, and at the same time is the one you actually need?
Lack of domain expertise
Programmers, unfortunately, sometimes change domains a lot. Take for example! I was working for a company that develops HR and payroll software, and now I work for European funded R&D projects related to Industry 4.0. Far from similar. But no matter what I have to adapt, to learn and be productive as fast as possible.
In the agile world, the product owner represents a range of stakeholders, not just end users, and in practice it isn’t reasonable to expect them to be experts at everything in the domain. As a result the product owner will bring in domain experts to work with the team. The programmers responsibility is to be open minded and learn from every word information that comes from the expert. Also don’t be a “know all” person. Trust the domain expert and work with them.
Understanding the domain helps you design a better software. A software with the expected, by the stakeholders, behavior as the stakeholders and not assumptions.
The pharmaceutical example
The moment comes that you have to create a class for medicines. What you will take under consideration for the fields (state) and the methods (behavior) of the class? Most medicines come in a variety of types or formats. The types of medicines are the following:
Implants or patches
Buccal or sublingual tablets or liquids
Have you been aware of that? Probably you knew some of them… but we need all of them, cause this is what the pharmaceutical company asked for! Are we done? Far from there! We still have to decide about the the methods of the class. Methods denote actions. A medicine what kind of actions does it carry? The “every X hours” frequency action is part of the Medicine class or the Prescription class? Of course is part of the Prescription class! But I believe that all of us agree, that some programmer would do that mistake. I could carry with many more examples, but I am confident that you got the point.
What if… there is no domain expert?
Well, if I were you, I wouldn’t accept the role, of let them hire me. In the past two years, I wouldn’t be able to develop software that matters with the support of the domain experts (electrical, mechanical and chemical engineers). It’s not easy to model a problem without the concrete knowledge of the domain.
Additionally, the domain expert has to have a basic IT knowledge. It is, at least unacceptable, to work with people who do not understand the basics of how a computer or a software system works. And believe me, there are a lot of them!
A piece of advice. All domains, no matter how easy or boring might seem in the beginning, they all carry knowledge and history. Understanding the domain, doesn’t just make you a better programmer, but it helps you understand how things work in a more insightful way. You become a better citizen in the end.
This is our world now. The world of the electron and the switch; the beauty of the baud. We exist without nationality, skin color, or religious bias. You wage wars, murder, cheat, lie to us and try to make us believe it’s for our own good, yet we’re the criminals. Yes, I am a criminal. My crime is that of curiosity. I am a hacker, and this is my manifesto.” Huh? Right? Manifesto? “You may stop me, but you can’t stop us all.
Static method and classes are one of the OOP world’s drawbacks. I am not implying that you shouldn’t use it at all, but in long term I believe a source code full of static methods and classes add more burden into the maintenance process.
How does static code look like?
Worker methods. Good for Simple calculations / processing, i.e b MyUtilityClass.ConvertAtoB(a)
Factory methods. Used to return preconfigured instances of a class, i.e. MyClass MyClass.GetInstanceOfClass()**
Singleton methods. Used to enforce a single global instance of a class, i.e. MyClass MyClass.SharedInstance()
Global variables. Used to store configuration values, i.e. int MyClass.TimeoutDuration
** Do not confuse it with Factory design pattern!
Why do we prefer the easy way out?
Suppose we have two classes A and B, and have a method M() that both must use, then the most naive approach is to repeat the method in both classes. However, this violates the “Don’t repeat yourself” (DRY) approach. It’s not just about reducing work: if both classes truly need the same method, then it should be the same method.
The most natural solution is inheritance, but it’s not always beneficial for A and B to be sub classes of some parent class. The bad and easy alternative is to define a “Utility” class: a public static class that sits in the global namespace, awaiting anyone to “borrow” them.
Static classes and methods imply relationships between data that are not explicitly defined. Also, if the static classes have any static variables, then A and B have no idea which object called them.
Where do static methods belong?
A class in OOP has state. When we look at our classes from the Single Responsibility Principle (SRP) viewpoint, a static method is usually a violation because it tends to have a responsibility that is not the same of the class it is attached on. So it ends up sitting out there trying to belong to the class it is on, but it doesn’t really belong, because it doesn’t use the internal state of the class.
Furthermore, based again on SRP, a class should have one and only one reason to change. But if we end up designing huge utility classes that contain any method the developer could think of, (e.g. a class containing a helper method for URL encoding, a method for looking up a password, and a method for writing an update to the config file) this is crystal clear violation of the Single Responsibility Principle.
Static methods and the rest of S.O.L.I.D.
Liskov Substitution Principle. Derived classes must be substitut-able for their base classes — If a class has only static methods , can not have a derived class. Maybe it’s not a direct violation, but every time we loose, we loose more and more destroying the project’s architecture.
Interface Segregation Principle. Class interfaces should be fine-grained and client specific. Since static classes do not derive from an interface, it is difficult to apply this principle with any degree of separation from the Single Responsibility Principle.
The Open Closed Principle. Classes should be open for extension and closed for modification. We cannot extend a helper class. Since all methods are static, we cannot derive anything that extends from it. In addition, the code that uses it doesn’t create an object, so there is no way to create a child object that modifies any of the algorithms in a helper class.
They are all “unchangable”. As such, a helper class simply fails to provide one of the key aspects of object oriented design: the ability for the original developer to create a general answer, and for another developer to extend it, change it, make it more applicable. If we assume that we do not know everything, and that we may not be creating the “perfect” class for every person, then helper classes will be an anathema to we .
The Dependency Inversion Principle. Depend on abstractions, not concrete implementations. This is a simple and powerful principle that produces more testable code and better systems. If we minimize the coupling between a class and the classes that it depends upon, we produce code that can be used more flexibly, and reused more easily.
With static classes/methods we have a clear violation of DIP. A class like that, cannot participate in the Dependency Inversion Principle. It cannot derive from an interface, nor implement a base class. No one creates an object that can be extended with a static class.
Static code and architecture
What is inside static methods? Well no one knows, and that is the problem. Static code must not keep inside it any meaningful state to the project . It should only carry out calculations statements like Math.Abs(), or String.ToUppercase(). We give an input, it works on that, generates the output. That’s it!
But unfortunately, reality is different. People always want more, and end up hurting their projects. Static methods might end up being huge, with complex code in them, with state, and sometimes create and manipulate objects, thus the complexity of the application is increased. The more static methods there are, the more a programmer working in the application has to know where is what and what’s in there. And this is only part of the problem.
Another part is naming static classes and methods. A static method with the name CalculateHolidays which calendar satisfies? Gregorian you will say!And you are right… most of the times! But there are seven calendars in regular current use around the world.
They are the following:
The Gregorian (Is used worldwide for business and legal reasons)
The Chinese (The Chinese calendar is not used in China but is used in various countries of south east Asia, usually with local variations. For example the calendar used in Japan is a variation of the Chinese one. It is also used socially by ethnic Chinese around the world.)
The Hebrew (The Hebrew calendar is used, of course, in Israel, as well as by Jews around the world for their religious observances)
The Islamic (is used by Muslims around the world for setting the dates of religious celebrations)
The Persian (Iran and Afghanistan)
The Ethiopian (Ethiopia)
The Balinese Pawukon (Bali).
So 7 static methods with the appropriate names might one say ! Wrong! We have enums, factory design pattern, we can’t just drop all of them away and being lazy. Plus, renaming or replacing the class containing static methods necessarily requires refactoring all references to it.
Another issue we must address is memory management. Referring to a static class, the class itself is guaranteed to be loaded and have all of the necessary fields inside instantiated before it is ever referenced with the code. Its constructor will only be called a single time.So, this class and methods will remain in memory for the lifetime of the application’s domain.
Static code and unit testing
Unit testing assumes that we can instantiate a piece of the application in isolation. During the instantiation we replace any dependencies with mocks/fakes/stubs. We prevent the execution of the normal code path and is how we achieve isolation of the class under test. With static code we can’t away from the normal path, we can’t replace the static code, because there are no objects to replace.
Also, sometimes static methods is a factory for creating other objects. In tests we rely on the fact replacing important dependencies with mocks. A caller of such a static factory is permanently bound to the concrete classes which the static factory method produced.
In unit testing, we intent to test the monkey and how it eats the banana. With the static code, we are forced to add in the act, the tree the monkey sits on, the plantains the banana grew, and even worse the jungle itself. In the end, this is not unit testing…
Maybe the solution is interfaces! Composition or aggregation of objects over inheritance! Both of them are fairly easy to understand, we can see composition in everyday life: a chair has legs, a wall is composed of bricks and mortar, and so on.
Inheritance is more of an abstraction. Though it is possible to mimic inheritance using composition in many situations, it is often unwieldy to do so. The purpose of composition is obvious: make wholes out of parts. The purpose of inheritance is a bit more complex because inheritance serves two purposes, semantics and mechanics.
Inheritance captures semantics (meaning) in a classification hierarchy (a taxonomy), arranging concepts from generalized to specialized, grouping related concepts in sub trees, and so on. The semantics of a class are mostly captured in its interface, the set of messages to which it responds, but a portion of the semantics also resides in the set of messages that the class sends.
When inheriting from a class, we are accepting responsibility for all of the messages that the super class sends on our behalf, not just the messages that it can receive. This makes the subclass more tightly coupled to its super class than it would be if it merely used an instance of the super class as a component instead of inheriting from it. Note that even in classes that don’t “do” much, the name of the class imparts significant semantic information about the domain to the developer.
Inheritance captures mechanics by encoding the representation of the data/state (fields) and behavior (methods) of a class and making it available for reuse and augmentation in sub classes. Mechanically, the subclass will inherit the implementation of the super class and thus also its interface.
The dual purpose of inheritance can cause more confusion. Many people think that “code reuse” is the primary purpose of inheritance, but that is not its only purpose. An overemphasis on reuse can lead to tragically flawed designs.
Functional programming is how programming should be. We want behaviours (functionalities), that receive an input and produce an output. Simple as that. Of course we might need to process again and again the data in hand, but this is also part of the expected behaviour: one’s function output is the other one’s input.
The ultimate goal is to deliver a software product built with reliable code, and the best way to do that is simplicity. Therefore programmers’ main responsibility is to to reduce code complexity. The whole picture is that OOP doesn’t deliver as excepted, nor in code quality nor in deadlines. It looks good in diagrams, but once the complexity starts increasing ,things, slower or faster, are getting out of hand. Especially when the state is mutable and shared, then a chaos is on the loose. Even full test coverage worth nothing, if the source code is complex and not maintainable.
In the seventies, the idea of “real OOP” was hugely powerful, but what was implemented was far from a complete set of ideas, especially with regard to scaling, networking, etc. How dynamic objects intertwined with ontologies and inference was explored by Goldstein and Bobrow at Parc. Their four papers on PIE and their implementation were the best extensions ever done to Smalltalk, and two of the ideas transcended the Smalltalk structure and deserved to be the start of a new language, and perhaps have a new term coined for it.
Alan Kay’s original idea about OOP
The term “Object Oriented Programming” was first coined in 1996 by Alan Kay. Based on his answers in 2003, via email Stefan Ram’s (a German computer science professor in Berlin at that time), his ideas on OOP were completely different from what we have today in our hands as OOP languages.
At Utah sometime after Nov 66 when, influenced by Sketchpad, Simula, the design for the ARPAnet, the Burroughs B5000, and my background in Biology and Mathematics, I thought of an architecture for programming. It was probably in 1967 when someone asked me what I was doing, and I said: “It’s object-oriented programming”.
– I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning – it took a while to see how to do messaging in a programming language efficiently enough to be useful).
– I wanted to get rid of data. I realized that the cell/whole-computer metaphor would get rid of data, and that “<-” would be just another message token (it took me quite a while to think this out because I really thought of all these symbols as names for functions and procedures.
– My math background made me realize that each object could have several algebras associated with it, and there could be families of these, and that these would be very very useful.
Alan Kay answering to Paul Ram in 2003
So far, based on Alan Kay’s answers, he focuses on cells (objects) exchanging messages to each other. His true goal was messaging.
The term “polymorphism” was imposed much later (I think by Peter Wegner) and it isn’t quite valid, since it really comes from the nomenclature of functions, and I wanted quite a bit more than functions. I made up a term “genericity” for dealing with generic behaviors in a quasi-algebraic form. […]
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I’m not aware of them.
Alan Kay answering to Paul Ram in 2003
Inheritance and polymorphism are not even mentioned! In the end, according to Alan Kay, the three pillars of OOP are:
Combining message passing and encapsulation we try to achieve the following:
Stop sharing mutable state among objects, by encapsulating it and allow only local state changes. State changes are at a local, cellular level rather than exposed to shared access.
A messaging API is the only way the objects communicate. Thus the objects are decoupled. The messages sender is loosely or not coupled at all to the message receiver.
Resilience and adaptability to changes at runtime via late binding.
[…] the whole point of OOP is not to have to worry about what is inside an object. Objects made on different machines and with different languages should be able to talk to each other […]
Alan Kay – The Early History Of Smalltalk
This sentence actually is talking about distributed and concurrent systems. Objects hide their states from each other and they just communicate (“talk to each other”) by exchanging messages. In simple words, objects should be able to broadcast that they did things (changed their state actually) and the other objects can ignore them or respond. This concept reminds of agents modelling or even actors. The key point that can improve the isolation among objects, is that the receiver is free to ignore any messages it doesn’t understand or care about.
Finally, let’s remember one more of Alan Kay’s quotes
I made up the term object-oriented, and I can tell you I did not have C++ in mind.
It was in the eighties that “object-oriented languages” started to appear. C++ was part of a set of ideas starting around 1979 by Bjarne Stroustrup. C++ was designed to provide Simula’s facilities for program organization together with C’s efficiency and flexibility for systems programming. His approach was via “Abstract Data Types”, and this is the way “classes” in C++ are generally used. C++ was a pre-processor to C language. “Classes” were program code structuring conventions but didn’t show up as objects during run time.
Hence the quote, as Alan Kay states in Quora, which is not so much about C++ per se but about the term that we had been using to label a particular approach to program language and systems design.
OOP and human cognition
In 1995 a paper was published by Bill Curtis under the name ” Objects of Our Desire: Empirical Research on Object-Oriented Development“. Among others, there is the following sentence:
In careful experiments, Gentner (1981; Gentner & France, 1988) showed that, when people are asked to repair a simple sentence with an anomalous subject-verb combination, they almost always change the verb and leave the noun as it is, independent of their relative positions. This suggests that people take the noun (i.e. the object) as the basic reference point. Models based on objects may be superior to models based on other primitives, such as behaviours.
Objects of Our Desire: Empirical Research on Object-Oriented Development, Bill Curtis
So a paper published in the nineties cites experiments that were run in the eighties, to support OOP concept. Well, in the nineties that might made sense, based on how the software industry was at that time, but not today. Today’s software is moving towards serverless applications, which are functions as a service, rather than to complicated objects communicating to each other.
The line of business software in our times is so complex, that OOP + TDD, OOP + DDD or OOP + BDD are concepts that programmers still struggle with. What is the right number of objects? How deep the granularity of objects should be? How mutable the objects should be? What is the right architecture to follow? Although there are tons of books and articles about those issues, software projects fail, due to complexity.
Additionally Bill Curtis paper includes the following:
Miller (1991) described how nouns and verbs differ in their cognitive organizational form. Nouns – and hence the concepts associated with them – tend to be organized into hierarchically structured taxonomies, with class inclusion and part-whole relations as the most common linkages. These are also, of course, the most common relations in OO representations.
In human cognition, these hierarchies tend to be fairly deep for nouns – often six to seven layers. These hierarchies support a variety of important cognitive behaviours, including the inheritance of properties from super ordinate classes. In contrast, verbs tend to be organized in very flat and bushy structures. This again suggest a central place for objects, in that building inheritance hierarchies will mirror the way humans represent natural categories only if the basic building blocks are objects rather than processes or behaviours.
Objects of Our Desire: Empirical Research on Object-Oriented Development, Bill Curtis
So through linguistics principles, the paper supports OOP, that is objects (nouns), verbs (methods) and the hierarchy among them. But a thing missing here, is what about those programmers, whose native tongue is not English? How their brains work? Can they adapt easily, to the OOP logic or not? Even today sometimes I see variables named in other languages that English.
You will not find a single medical article that denotes that the human brain thinks, organizes, structures based on objects. We carry a “todo list”, not an “item hierarchy list”. Human brains can only hold about five items at a time in working memory. It is much easier to explain a piece of code based on what it does, rather than based on what variables change around the source code. Each language has a set or rules to constraint you, in order to speak and write correctly, it is called grammar! On the other hand in OOP programming you have so many options to solve the same problem, that in the end you can just throw any “grammar” out of the window.
Additionally, OOP code is non- deterministic. You can verify that by installing a cyclomatic complexity extension to your IDE and run it. Dependencies, null checking, type checking, conditional statements, all of them combined produce more outputs than expected. Let’s not forget Mock object in unit testing, you have to predefine its behaviour. So even if you have an a grammar, a structure of your objects, there is no guarantee that the functionalities implementation is going to be according to the grammar.
Finally, we have dependencies hell. And it”s only about nuget packages or maven dependencies. It’s the source code’s internal hierarchy. Inheritance, methods, constructors parameters, Law of Demeter, etc. So how nouns and verbs and objects hierarchy are equal to simple code without extra complexity is still a mystery.
Why Functional Programming (FP)?
Functional programming is a programming paradigm: a different way of thinking about programs than the mainstream, imperative paradigm you’re probably used to. FP is based on lambda calculus. Functions tend to provide a level of code modularity and reusability It manages nullability much better, and gives us a better way of error handling.
FP provides the following:
Power.—This simply means that you can get more done with less code. FP raises the level of abstraction, allowing you to write high-level code while freeing you from low-level technicalities that add complexity but no value.
Safety. This is especially true when dealing with concurrency. A program written in the imperative style may work well in a single-threaded implementation but cause all sorts of bugs when concurrency comes in. Functional code offers much better guarantees in concurrent scenarios cause of immutability, so it’s only natural that we’re seeing a surge of interest in FP in the era of multi core processors.
Clarity. We spend more time maintaining and consuming existing code than writing new code, so it’s important that our code be clear and intention-revealing.
So how functional a language is C#? Functions are first-class values in C#. C# had support for functions as first-class values from the earliest version of the language through the Delegate type, and the subsequent introduction of lambda expressions made the syntactic support even better. There are some quirks and limitations, but we will discuss about them in time.
Today we have LINQ. Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language. Traditionally, queries against data are expressed as simple strings without type checking at compile time or IntelliSense support. With LINQ, a query is a first-class language construct, just like classes, methods, events. You write queries against strongly typed collections of objects by using language keywords and familiar operators. The LINQ family of technologies provides a consistent query experience for objects (LINQ to Objects), relational databases (LINQ to SQL), and XML (LINQ to XML).
Query expressions are written in a declarative query syntax. By using query syntax, you can perform filtering, ordering, and grouping operations on data sources with a minimum of code. You use the same basic query expression patterns to query and transform data in SQL databases, ADO .NET Datasets, XML documents and streams, and .NET collections.
The disadvantage in the C# + FP try, is that everything is mutable by default, and the programmer has to put in a substantial amount of effort to achieve immutability. Fields and variables must explicitly be marked read-only to prevent mutation. (Compare this to F#, where variables are immutable by default and must explicitly be marked mutable to allow mutation.) Finally, collections in the framework are mutable, but a solid library of immutable collections is available.
To highlight the difference between are in OOP and FP, I provide an example: You run a company and you just decided to give all your employees a $10,000.00 raise.
OOP (imperative way)
1. Create Employee class which initializes with name and salary, has a change salary instance method
2. Create instances of employees
3. Use the each method to change salary attribute of employees by +10,000
1. Create employees array, which is an array of arrays with name and corresponding salary
2. Create a change_salary function which returns a copy of a single employee with the salary field updated
3. Create a change_salaries function which maps through the employee array and delegates the calculation of the new salary to change_salary
The FP approach uses pure functions and adheres to immutability by using map With OOP, we cannot easily identify if the object has had the function called on it unless we start from the beginning and track if this has happened, whereas in FP, the object itself is now a new object, which makes it considerably easier to know what changes have been made.
FP leans heavily on methods that do one small part of a larger job, delegating the details to other methods. This combining of small methods into a larger task is composition. In our example, change_salaries has a single job: call change_salary for each employee in the employees array and return those values as a new array. change_salary also has one job: return a copy of a single employee with the salary field updated. change_salaries delegates the calculation of the new salary to change_salary, allowing change_salaries to focus entirely on handling the set of employees and change_salary to focus on updating a single employee.
I believe that anyone of you have understood, that the main key words are code simplicity, state immutability, messaging. From distributed mutable state around the source code (objects), to code organized by expected behaviours (functions).
FP is a programming parading as OOP is. OOP is alive and it will be for next years. But can we rely on it anymore? After 10 years as a software developer, I believe not anymore. Maybe I am wrong!
But instead of asking a better OOP language, I try to smoothly move to FP. Unfortunately I can’t completely move away from C#, due to business restrictions, but I do my best to find a better alternative.
The next episode
In the next episode, the topic is “OOP today” and an analysis about objects state.