Record of experiments, readings, links, videos and other things that I find on the long road.
Registro de experimentos, lecturas, links, vídeos y otras cosas que voy encontrando en el largo camino.
Wednesday, November 19, 2025
Interesting Talk: Beyond design patterns and principles - writing good OO code
Wednesday, August 15, 2018
Interesting Talk: "About Don't Think of an Elephant"
Sunday, January 21, 2018
Interesting Talk: "Patterns Failed. Why? Should We Care?"
Tuesday, December 19, 2017
Interesting Talk: "En mi equipo esto funciona pero no se por qué"
Tuesday, December 12, 2017
Interesting Talk: "What We Actually Know About Software Development, and Why We Believe It’s True"
Wednesday, December 6, 2017
Wednesday, November 22, 2017
Wednesday, October 11, 2017
Tuesday, August 22, 2017
In a small piece of code
In a previous post we talked about positional parameters and how they can suffer from Connascence of Position, (CoP). Then we saw how, in some cases, we might introduce named parameters to remove the CoP and transform it into Connascence of Name, (CoN), but always being careful to not hiding cases of Connascence of Meaning, (CoM). In this post we’ll focus on languages that don’t provide named parameters and see different techniquess to remove the CoP.
Let’s see an example of a method suffering of CoP:
In languages without named parameters (the example is written in Java), we can apply a classic[1] refactoring technique, Introduce Parameter Object, that can transform CoP into CoN. In this example, we introduced the ClusteringParameters object:
which eliminates the CoP transforming it into CoN:
In this particular case, all the parameters passed to the function were semantically related, since they all were parameters of the clustering algorithm, but in many other cases all the parameters aren’t related. So, as we saw in our previous post for named parameters, we have to be careful of not accidentally sweeping hidden CoM in the form of data clumps under the rug when we use the Introduce Parameter Object refactoring.
In any case, what it’s clear is that introducing a parameter object produces much less expressive code than introducing named parameters. So how to gain semantics while removing CoP in languages without named parameters?
One answer is using fluent interfaces[2] which is a technique that is much more common than you think. Let’s have a look at the following small piece of code:
This is just a simple test. However, just in this small piece of code, we can find two examples of removing CoP using fluent interfaces and another example that, while not removing CoP, completely removes its impact on expressiveness. Let’s look at them with more detail.
The first example is an application of the builder pattern using a fluent interface[3].
Applying the builder pattern provides a very specific[4] internal DSL that we can use to create a complex object avoiding CoP and also getting an expressiveness comparable or even superior to the one we’d get using named parameters.
In this case we composed two builders, one for the SafetyRange class:
and another for the Alarm class:
Composing builders you can manage to create very complex objects in a maintanable and very expressive way.
Let’s see now the second interesting example in our small piece of code:
This assertion using hamcrest is so simple that the JUnit alternative is much clearer:
but for more than one parameter the JUnit interface starts having problems:
Which one is the expected value and which one is the actual one? We never manage to remember…
Using hamcrest removes that expressiveness problem:
Thanks to the semantics introduced by hamcrest[6], it’s very clear that the first parameter is the actual value and the second parameter is the expected one. The internal DSL defined by hamcrest produces declarative code with high expressiveness. To be clear hamcrest is not removing the CoP, but since there are only two parameters, the degree of CoP is very low[7]. The real problem of the code using the JUnit assertion was its low expressiveness and using hamcrest fixes that.
For us it’s curious to see how, in trying to achieve expressiveness, some assertion libraries that use fluent interfaces have (probably not being aware of it) eliminate CoP as well. See this other example using Jasmine:
Finally, let’s have a look at the last example in our initial small piece of code which is also using a fluent interface:
This is Mockito’s way of defining a stub for a method call. It’s another example of fluent interface which produces highly expressive code and avoids CoP.
Summary.
We started seeing how, in languages that don’t allow named parameters, we can remove CoP by applying the Introduce Parameter Object refactoring and how the resulting code was much less expressive than the one using the Introducing Named Parameters refactoring. Then we saw how we can leverage fluent interfaces to remove CoP while writing highly expressive code, mentioned internal DSLs and showed you how this technique is more common that one can think at first by examining a small piece of code.
References.
Books.
- Refactoring: Improving the Design of Existing Code, Martin Fowler
- Growing Object-Oriented Software Guided by Tests, Nat Pryce and Steve Freeman.
- Refactoring Ruby, Jay Fields, Kent Beck, Martin Fowler, Shane Harvie
Posts.
- Refactoring Ruby: Bad Smells in Code, Jay Fields, Kent Beck, Martin Fowler, Shane Harvie
- Builders vs option maps, Kyle Kingsbury
- Refactoring tests using builder functions in Clojure/ClojureScript, Manuel Rivero
- Remove data structures noise from your tests with builders, Carlos Blé
- Two examples of Connascence of Position, Manuel Rivero, Fran reyes
- About Connascence, Manuel Rivero
Footnotes:
Thursday, January 26, 2017
About Connascence
Lately at Codesai we’ve been studying and applying the concept of connascence in our code and even have done an introductory talk about it. We’d like this post to be the first of a series of posts about connascence.
1. Origin.
The concept of connascence is not new at all. Meilir Page-Jones introduced it in 1992 in his paper Comparing Techniques by Means of Encapsulation and Connascence. Later, he elaborated more on the idea of connascence in his What every programmer should know about object-oriented design book from 1995, and its more modern version (same book but using UML) Fundamentals of Object-Oriented Design in UML from 1999.Ten years later, Jim Weirich, brought connascence back from oblivion in a series of talks: Grand Unified Theory of Software Design, The Building Blocks of Modularity and Connascence Examined. As we’ll see later in this post, he did not only bring connascence back to live, but also improved its exposition.
More recently, Kevin Rutherford, wrote a very interesting series of posts, in which he talked about using connascence as a guide to choose the most effective refactorings and about how connascence can be a more objective and useful tool than code smells to identify design problems[1].
2. What is connascence?
The concept of connascence appeared in a time, early nineties, when OO was starting its path to become the dominant programming paradigm, as a general way to evaluate design decisions in an OO design. In the previous dominant paradigm, structured programming, fan-out, coupling and cohesion were fundamental design criteria used to evaluate design decisions. To make clear what Page-Jones understood by these terms, let’s see the definitions he used:Fan-out is a measure of the number of references to other procedures by lines of code within a given procedure.According to Page-Jones, these design criteria govern the interactions between the levels of encapsulation that are present in structured programming: level-1 encapsulation (the subroutine) and level-0 (lines of code), as can be seen in the following table from Fundamentals of Object-Oriented Design in UML.
Coupling is a measure of the number and strength of connections between procedures.
Cohesion is a measure of the “single-mindedness” of the lines of code within a given procedure in meeting the purpose of that procedure.
However, OO introduces at least level-2 encapsulation, (the class), which encapsulates level-1 constructs (methods) together with attributes. This introduces many new interdependencies among encapsulation levels, which will require new design criteria to be defined, (see the following table from Fundamentals of Object-Oriented Design in UML).
Two of these new design criteria are class cohesion and class coupling, which are analogue to the structured programing’s procedure cohesion and procedure coupling, but, as you can see, there are other ones in the table for which there isn’t even a name.
Connascence is meant to be a deeper criterion behind all of them and, as such, it is a general way to evaluate design decisions in an OO design. This is the formal definition of connascence by Page-Jones:
Connascence between two software elements A and B means eitherIn other words, there is connascence between two software elements when they must change together in order for the software to keep working correctly.
- that you can postulate some change to A that would require B to be changed (or at least carefully checked) in order to preserve overall correctness, or
- that you can postulate some change that would require both A and B to be changed together in order to preserve overall correctness.
We can see how this new design criteria can be used for any of the interdependencies among encapsulation levels present in OO. Moreover, it can also be used for higher levels of encapsulation (packages, modules, components, bounded contexts, etc). In fact, according to Page-Jones, connascence is applicable to any design paradigm with partitioning, encapsulation and visibility rules[2].
3. Forms of connascence.
Page-Jones distinguishes several forms (or types) of connascence.Connascence can be static, when it can be assessed from the lexical structure of the code, or dynamic, when it depends on the execution patterns of the code at run-time.
There are several types of static connascence:
-
Connascence of Name (CoN): when multiple components must agree on the name of an entity.
-
Connascence of Type (CoT): when multiple components must agree on the type of an entity.
-
Connascence of Meaning (CoM): when multiple components must agree on the meaning of specific values.
-
Connascence of Position (CoP): when multiple components must agree on the order of values.
-
Connascence of Algorithm (CoA): when multiple components must agree on a particular algorithm.
-
Connascence of Execution (order) (CoE): when the order of execution of multiple components is important.
-
Connascence of Timing (CoTm): when the timing of the execution of multiple components is important.
-
Connascence of Value (CoV): when there are constraints on the possible values some shared elements can take. It’s usually related to invariants.
-
Connascence of Identity (CoI): when multiple components must reference the entity.
4. Properties of connascence.
Page-Jones talks about two important properties of connascence that help measure its impact on maintanability:- Degree of explicitness: the more explicit a connascence form is, the weaker it is.
- Locality: connascence across encapsulation boundaries is much worse than connascence between elements inside the same encapsulation boundary.
4.1. Degree.
The degree of an instance of connascence is related to the size of its impact. For instance, a software element that is connascent with hundreds of elements is likely to become a larger problem than one that is connascent to only a few.4.2 Locality.
The locality of an instance of connascence talks about how close the two software elements are to each other. Elements that are close together (in the same encapsulation boundary) should typically present more, and higher forms of connascence than elements that are far apart (in different encapsulation boundaries). In other words, as the distance between software elements increases, the forms of connascence should be weaker.4.3 Stregth.
Page-Jones states that connascence has a spectrum of explicitness. The more implicit a form of connascence is, the more time consuming and costly it is to detect. Also a stronger form of connascence is usually harder to refactor. Following this reasoning, we have that stronger forms of connascence are harder to detect and/or refactor. This is why static forms of connascence are weaker (easier to detect) than the dynamic ones, or, for example, why CoN is much weaker (easier to refactor) than CoP.The following figure by Kevin Rutherford shows the different forms of connascence we saw before, but sorted by descending strength.
5. Connascence, design principles and refactoring.
Connascence is simpler than other design principles, such as, the SOLID principles, Law of Demeter, etc. In fact, it can be used to see those principles in a different light, as they can be seen using more fundamental principles like the ones in the first chapter of Kent Beck’s Implementation Patterns book.We use code smells, which are a collection of code quality antipatterns, to guide our refactorings and improve our design, but, according to Kevin Rutherford, they are not the ideal tool for this task[4]. Sometimes connascence might be a better metric to reason about coupling than the somewhat fuzzy concept of code smells.
Connascence gives us a more precise vocabulary to talk and reason about coupling and cohesion[5], and thus helps us to better judge our designs in terms of coupling and cohesion, and decide how to improve them. In words of Gregory Brown, “this allows us to be much more specific about the problems we’re dealing with, which makes it it easier to reason about the types of refactorings that can be used to weaken the connascence between components”.
It provides a classification of forms of coupling in a system, and even better, a scale of the relative strength of the coupling each form of connascence generates. It’s precisely that scale of relative strengths what makes connascence a much better guide for refactoring. As Kevin Rutherford says:
"because it classifies the relative strength of that coupling, connascence can be used as a tool to help prioritize what should be refactored first"Connascence explains why doing a given refactoring is a good idea.
6. How should we apply connascence?
Page-Jones offers three guidelines for using connascence to improve systems maintanability:-
Minimize overall connascence by breaking the system into encapsulated elements.
-
Minimize any remaining connascence that crosses encapsulation boundaries.
-
Maximize the connascence within encapsulation boundaries.
These guidelines generalize the structured design ideals of low coupling and high cohesion and is applicable to OO, or, as it was said before, to any other paradigm with partitioning, encapsulation and visibility rules.
They might still be a little subjective, so some of us, prefer a more concrete way to apply connascence using, Jim Weirich’s two principles or rules:
- Rule of Degree[7]: Convert strong forms of connascence into weaker forms of connascence.
- Rule of Locality: As the distance between software elements increases, use weaker forms of connascence.
7. What’s next?
In future posts, we’ll see examples of concrete forms of conasscence relating them with design principles, code smells, and refactorings that might improve the design.Footnotes:
References.
Books.
- Fundamentals of Object-Oriented Design in UML, Meilir Page-Jones
- What every programmer should know about object-oriented design, Meilir Page-Jones
- Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design by Edward Yourdon and Larry L. Constantine
Papers.
Talks.
- The Building Blocks of Modularity, Jim Weirich (slides)
- Grand Unified Theory of Software Design, Jim Weirich (slides)
- Connascence Examined, Jim Weirich
- Connascence Examined (newer version, it goes into considerable detail of the various types of connascence), Jim Weirich (slides)
- Understanding Coupling and Cohesion hangout, Corey Haines, Curtis Cooley, Dale Emery, J. B. Rainsberger, Jim Weirich, Kent Beck, Nat Pryce, Ron Jeffries.
- Red, Green, … now what ?!, Kevin Rutherford (slides)
- Connascence, Fran Reyes y Alfredo Casado (slides)
- Connascence: How to Measure Coupling, Nick Hodges
Posts.
- Connascence as a Software Design Metric, by Gregory Brown.
- The problem with code smells, Kevin Rutherford
- A problem with Primitive Obsession, Kevin Rutherford
- The Page-Jones refactoring algorithm, Kevin Rutherford
- Connascence – Some examples, Mark Needham
Others.
Monday, January 9, 2017
Thursday, December 1, 2016
Interesting Talk: "Code Symbiosis, a technical keynote"
Thursday, November 17, 2016
Quotes from "Why should physicists study history?"
"History is not a list of names and dates. It's a way of thinking that can be powerful and illuminating."
"Social interactions really do influence what scientist produce."
"How a community tells its history changes the way it thinks about itself."
"A historical perspective on science can help physicists understand what is going on when they practice their craft, and it provides numerous tools that are useful for physicists themselves."
"Physics is a social endeavor."
"Research is done by people. And people have likes and dislikes, egos and prejudices. Physicists, like everyone else get attached to their favorite ideas and hang on them perhaps long after they should let them go."
"The history of science can help dismantle the myth of the purely rational genius living outside the everyday world. It makes physics more human."
"And a more human physics is a good thing. For starters, it makes physics more accessible."
"A field in which people are aknowledged as people is much more appealing than one in which they are just calculating machines."
"Physics only work when people talk to each other and communication is not always easy."
"Everything seems obvious in retrospect."
"The history of physics can remind us how difficult is to justify ideas that now seem obvious."
"Complexity, not simplicity , has ruled the practice of science."
"Every discovery has come out of a messy mix of people, ideas, accidents and arguments."
"Students and young researchers are often heartened to learn that physics is hard work and that it is ok for their own efforts not to look like a text-boo presentation. Messiness is a standard. Mistakes are normal. The results of physics are not self-evident."
"The history of physics suggests that there are usually several ways to approach a problem."
"Turning complexity into good physics requires creativity. You can never tell what weird idea will help clarify a confusing observation or provide the key to interpreting an equation. History uncovers the strange stew of concepts that were necessary for the development of physics."
"The interplay of various approaches is what brought us a modern view."
"Strange but ultimately useful perspectives come from fields and disciplines apparently distant from the problem at hand."
"The history of science shows how important it is for scientists across different fields to talk to each other. Conversations among separate groups are healthy. Apparently isolated problems are often closedly tied together, and you never know where you will find the weird idea that solves your difficulty."
"The best strategy for encouraging diverse ideas is to cultivate a diverse community."
"Underrepresented groups that offer different ways of thingking are often the source of fresh insights and novel methods."
"Underrepresented groups are usually marginalized because of cultural inertia or deliberate decisions made long ago."
"The diversity of ideas and interpretations serves as a reminder that physics is a work in progress. Knowledge is provisional. There are always new ways to tackle a problem, and there is always more to be learned."
"Accepting uncertainty would require changes in how science is taught."
"Curiosity should be revered, and everyone should be encouraged to ask, what else?"
"If scientist are not explicit and honest about their doubts, a crisis of confidence arises when that uncertainty is revealed."
"Physics wasn't always as it is."
"The flip side of accepting physics will be different in the future is accepting that it was different in the past. Everyone has a tendency to assume that the way things are now is the norm. But history makes it clear that things were not always this way. An understanding of why people used to think differently is a powerful tool for understanding people today. By drawing attention to older, usnpoken assumptions, history shows us how to start paying attention to our own."
"A knowledge of the historic and physical background, gives the kind of independence from prejudices of his generation from which most scientists are suffering" Einstein
"..they should study the history of those ideas and understand the circumstances in which they were justified and found useful."
"History trains you to think critically about received ideas. History provides evidence of roads not taken."
"Science's plurality of interpretation can make the history of science a resource for modern scientific research." Hasok Chang"Complementary Science -> recovering forgotten and unsolved puzzles from the past."
"Putting complementary science into practice demands difficult self-examination. Thinking deeply about assumptions and accepted knowledge can be hard to do in professional scientific contexts, but history is a mode in which it's encouraged."
"The simple realization that people used to think differently can be quite powerful."
"Physics doesn't have rigid rules."
"Scientist simply don't follow a rigid, linear problem-solving system. Sometimes they start with a hypothesis, sometimes with a strange observation, sometimes with a weird anomaly in an otherwise straightforward experiment."
"... a scientist must be an "unscrupulous opportunist", adopting and adapting various approaches as new challenges arise."
"History teaches that knowledge is not fixed."
"Engaging with history will teach you to understand ideas on their own terms."
"Historical thinking makes its subject dynamic. It helps you think about science as a series of questions rather than a series of statements. Those questions will continue into the future, and it is helpful to know what has been asked so far." "In the end, history of science exposes scientists to new ways of thinking and forces them to reexamine what is already known. Such intellectual flexibility is essential for any discipline, but it's particularly important for fields as influential and authoritative as physics and other sciences."
Tuesday, November 1, 2016
Interesting Paper: "Design Methodology for Reliable Software Systems"
Friday, July 22, 2016
Interesting Paper: "Why should physicists study history?"
Saturday, September 26, 2015
Interesting Talk: "Maintaining Balance While Reducing Duplication"
Saturday, May 10, 2014
Values without practices
"All of this high-minded talk is well and good, but if there isn't some way to reduce it to practice, to reinforce it, to make the values a natural habit, then all we will have is yet another brave leap into the swamp of methodological good intentions."Kent Beck, Extreme Programming Explained
Tuesday, May 6, 2014
Interesting Talk: "The Architecture of Uncertainty"
Lately I've been reading and thinking a lot about this after reading Sandi Metz great book on OO design and several interesting discussions with @remosu.
Some intuitions are growing in my head but they are still quite fuzzy.
Wednesday, June 19, 2013
Saturday, June 15, 2013
Notes to myself: "Kent Beck's Theory of Programming"
- Communication.
- Simplicity.
- Flexibility.
Principles.
- Local Consequences.
- Minimize Repetition.
- Logic and Data Together.
- Symmetry.
- Declarative Expression.
- Rate of Change.