DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • The Importance of Semantics for Data Lakehouses
  • 6 Easy Ways to Start Coding Accessibly
  • HTTP for Inter-Service Communication?
  • Three Approximations You Should Never Use When Coding

Trending

  • Machine Learning Libraries For Any Project
  • Auto-Scaling DynamoDB Streams Applications on Kubernetes
  • Database Monitoring: Key Metrics and Considerations
  • Demystifying Enterprise Integration Patterns: Bridging the Gap Between Systems

Dealing with Semantic Conflict

Martin Fowler user avatar by
Martin Fowler
·
Aug. 05, 11 · News
Like (0)
Save
Tweet
Share
7.70K Views

Join the DZone community and get the full member experience.

Join For Free

Those who hear my colleagues and I talk about FeatureBranch know that we're not big fans of that pattern. An important part of our objection is the observation that branching is easy, but merging is hard. One argument we hear from time to time is that modern VersionControlTools make merging sufficiently easy that feature branching is worthwhile.

Certainly modern tools do a much better job of merging than in my youth. A good example of this power is merge-through-rename which can properly merge the situation where I change some of the contents of lorem.rb, while Jez changes its name to ipsum.rb.

This is all very well, but it only solves textual conflicts and does not help with semantic conflicts. By a semantic conflict I mean a situation where Jez and I make changes which can be safely merged on a textual level but cause the program to behave differently

The simplest example is that of renaming a function. Say I think that the method clcBl would be easier to work with if it were called calculateBill. With modern refactoring tools this is trivial: just press Shift+F6, type the new name, and the tool then changes all the callers. The problem appears, however, if Jez adds more calls to this method on his feature branch. When the two get merged, the textual merge will work fine, but the program will not run the same way.

A method rename is a simple example, and is also easy to find in a statically typed language as it will fail to compile. But there are plenty of subtler semantic conflicts that won't merge so cleanly. Let's imagine I'm looking at that calculateBill method and realize that as well as calculating the bill, it also sends off accounting entries to the accounting system. I don't like the side effect, so I pull it out into a separate notifyAccounting method. I can then find all the callers of calculateBill and add a call to notifyAccounting. But Jez doesn't know about that in his branch.

So the first point here is that however powerful your tooling is, it will only protect you from textual conflicts [1]. The particularly annoying point is that semantic conflicts are harder to spot and harder to fix.

We can't automatically resolve semantic conflicts. Maybe some day tools will be able to tackle some of them, but I suspect some gnarly ones will always be with us - at least until computers can read our mind and automatically deduce our intentions. There are, however, a couple of strategies that can significantly help us deal with them

The first of these is SelfTestingCode. Tests are effectively probing our code to see if their view of the code's semantics are consistent with what the code actually does. If Jez is expecting certain things to happen with the code he's calling and has tests for that, then they will break when he integrates. It's not a perfect response, of course. Tests can never be perfect, but they catch lots of semantic conflicts in practice. They also don't help with fixing the conflict once you've discovered it, but finding it is a big part of the battle

The other technique that helps is to merge more often. Jez's difficulties are much less if he discovers my change in a few hours rather than in a few days. That way he's no longer building a lot of code on the old semantics. This is why we are such big fans of continuous integration.

There seem to be two groups of people who promote the notion of tools make feature branching tolerable. One is purveyors of "enterprise grade" VCSs. We don't really care about them. The other group is fans of DVCSs (Distributed Version Control Systems). I get a bit more concerned about the latter group. Often people try to justify DVCSs based on how they make feature branching easy. But that misses the issues of semantic conflicts [2]. There are lots of good reasons to use a DVCS, so there's no reason to couple a good tool to a problematic technique.

1: And if we change the exact same text, the merge tool usually can't help either unless you have something like git rerere. But that problem is much smaller than semantic conflicts.

2: If your features are built quickly, within a couple of days, then you'll run into less semantic conflicts (and if less than a day, then it's in effect the same as CI). However we don't see such short feature branches very often.

Semantics (computer science)

Published at DZone with permission of Martin Fowler, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Importance of Semantics for Data Lakehouses
  • 6 Easy Ways to Start Coding Accessibly
  • HTTP for Inter-Service Communication?
  • Three Approximations You Should Never Use When Coding

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: