Brief summary
How can we better define and clarify architectures to ensure consistency and control? If, as Neal Ford and Mark Richards discussed on a recent episode of the Technology Podcast, software architecture intersects with many different facets of software development and delivery, what can we do to better manage architectures that is adaptable and dynamic?
Neal and Mark return to the guest seats to speak again to host Prem Chandrasekaran about fitness functions and architecture as code, and explain why rethinking our approach to software architecture can help ensure greater alignment with organizational needs and objectives.
Episode transcript
Prem Chandrasekaran: Welcome, everyone. My name is Prem Chandrasekaran. I'm one of the regular co-hosts of the Thoughtworks Technology Podcast. It's great to be here yet again. Today, we have got Neal and Mark. Neal, do you want to quickly introduce yourself.
Neal Ford: Absolutely. My name is Neal Ford. I'm actually one of your other regular hosts, but today, I'm a guest because we're talking about some future IP that I'm working on with my frequent co-author and co-collaborator on things written and live, Mark Richards, who's also with us today.
Mark Richards: Hello, everyone. I've been a frequent visitor on these podcasts. I do not work at Thoughtworks, although I think a lot of people think I do because I appear with Neal on so many of these podcasts and other kinds of events. Again, Prem, thank you for having me back on the podcast.
Prem: Yes, great to have you, folks. Now, in a previous episode, which happened about a month ago, we started talking about the intersection between architecture intent and implementation. At that point, we grazed through the topic and then we introduced what it actually means, but we really didn't delve into the depths of it. We are doing this second episode on this topic because here is where we intend to talk about how this actually translates into real software, real systems, and actually provides value.
Neal: Makes it more concrete. You can go ahead and say it because architecture, very often, gets too abstract. One of the things that Mark and I realized when we were writing our Software Architecture Hard Parts book is that the real essence of software architecture is about trade-offs. When you talk in the abstract, everything is a possibility because there are no trade-offs, there's nothing concrete to trade-off. You have to have something concrete to tie those things to.
What we did, last time, was describe all these different intersections and really set the scope for what we're going to talk about today because what we've realized, over time, is that architecture intersects with all these different parts of the ecosystem in a unique way because it influences and is influenced by so many different tendrils within the organization. Mark and I set off, a couple of years ago, thinking about describing all of this stuff, but then we ran up on this problem of, "Well, how do you describe all these intersections?"
We could beat it to death with prose, but we wanted something more precise. That's where the real subject of today comes in, this idea of architecture as code. Many of you are familiar with and have probably heard me talk endlessly about architecture fitness functions, which myself and Dr. Rebecca Parsons and Pat Kua coined. It was Rebecca Parsons' idea, but it's this idea of basically tests and verifications for architecture characteristics, like unit tests, but uniquely focused on software architecture.
In fact, many of the structural tests that we were talking about last time, about implementation alignment, "Are we using the correct architecture style? Should these two components be able to talk to one another? Are all these tools and frameworks to allow you to be able to do that?" These are all these fitness functions, tools, and frameworks.
It turns out that, in the real world, a lot of the things you want to do, nobody has built a tool for you to do that, because every architecture is this incredible snowflake of good stuff and bad stuff and stuff we love and stuff we hate and some legacy stuff. I'm not even sure what that is, but we can't unplug it because people yell when we do, so we're not going to touch it. That's what the realization of architecture is, in most organizations.
The reality is, most fitness functions are not from some elaborate tool or framework, but rather 10 or 15 lines of scripting code. Here's the mantra that we're going to go back to over and over and over today that I try to teach people when we talk about fitness functions. "Where's the data and how do I get to it?" That's all you really need to know in many of these cases.
Unlike unit tests or functional tests, which are almost always written in the target platform that you're also implementing your software in, most fitness functions are not. They're either monitors or they may be GitHub Action, or they're 10 lines of Ruby code because I need to gather five log files together and do a union, and compare to see if these things are talking to one another or not. That's what we're talking about. We talk about architecture as code is a way of expressing those intersections we were talking about last week, in a very concrete way literally in source code. I'll let Mark interject his observations here before we go further down this path.
Mark: I want to really just add to that mantra, Neal, because it's, "Where is the data? How can I access it?" One of the important things, when we start talking about architecture as code, and actually applying measurements and source code for the alignments that we talked about in Part 1, I also want to add, do we have the data? This is a really important aspect because, as we start to look at ways of aligning architecture with the various intersections we talked about, there might come a point where we don't have the data available. It's not where is it, but do we have it?
This really gives importance to the whole aspect of observability, and something that teams should be prepared to do, which is we need additional information from our services, from our systems, from our products, and to treat that observability and this context as a first-class citizen and not just an afterthought once all the functionality is in place.
Neal: In fact, we'll see the primacy of observability toward the end, as we talk about infrastructure. Let's do some more concrete ways of thinking about architecture as code. We've gone down this path. One of the problems you run into, very often, and one of the reasons you see very little source code in books on software architecture is because, once you've committed to a particular set of source code, you've tied yourself to a particular platform or technology stack.
One of the things that I am known for saying, amongst the authors of technical books, is that every line of source code you put in a book halves its shelf life. Even the mighty Martin Fowler had to rewrite and do a second edition of refactoring because he got embarrassed that "java.util.Vector" showed up so much in it. Putting source code in your book ties it to a particular platform or technology stack.
One of the things that we wanted to be able to do is express architecture more generically than in one of these fitness function tools like ArchUnit or NetArchTest or one of the specific platforms. What Mark and I have been experimenting with a lot is this idea of a lightweight architecture definition language, a pseudocode that is useful for two things; One, it's a more precise way to define the constraints and the structure and the capabilities in your architecture.
It's almost like the next level beyond an ADR, which is mostly diagrams and prose. This is just structured code to describe that. The other great use that we have found of this is a way to express architecture concepts generally, but also to be able to hand that to a large language model and have it produce fitness functions in Java or .NET or Python or TypeScript or any of those other languages. Using it as a code generator because large language models are really, really good at translating languages one to the other.
Mark: This really enforces this notion that, in most cases, architecture tends to be orthogonal to the particular language or platform that we're writing in. The idea of being able to generate ArchUnit code, NetArchTest code, PyTestArch code, or any of these other tools we'll be talking about in this podcast, the problem is we have to know the language and platform.
In some cases, especially with microservices architectures, we may have multiple platforms and languages. This idea really does help cement this thought or this concept that we're able to describe our architecture agnostic to the language that we choose to implement that architecture in. The other thing I want to interject here, Neal, is this concept of architecture as code, how it differs from diagrams as code.
A lot of times, we describe architecture, and this is one of the ideas here is to be able to describe our software architecture. Most architects leverage drawing tools to be able to describe and show their architecture. A lot of these tools do allow you to export that diagram in source code. For example, PlantUML does this. We can use Structurizr on the C4 model. As a matter of fact, even ArchiMate allows us to export that entire diagram and information in that diagram to an XML-readable format.
Problem is, though, while that describes an architecture, we can't execute that particular diagram source code to enforce those constraints in the architecture. That's where we're taking this architecture as code to the next level beyond diagrams as code.
Prem: Let me ask you a clarifying question here. Are you talking about defining a language specifically meant to express architecture concerns and then make sure that those architecture concerns are being enforced and do it in a manner that is independent of the implementation language used or technology or runtime used? Is that what we're talking about here?
Neal: Yes, that is the intent. I won't SQL-like, but it's very specification-like. It's very lightweight. We've seen several flavors of this, that several of our friends and colleagues have created their variations of this, and some of them are for large finance companies, and not surprisingly, they're boiling the ocean with their architecture definition language. We don't want it to be Turing-complete or anything crazy like that, but we do want it to be read like a specification and be fairly terse.
Let's talk about what the utility of having some sort of ancillary language like that. One of the things that we talked about last time and talked about specific fitness functions were for things like the simplest kinds of obvious fitness functions, things like implementation details, component structures, and communication. Can these components talk to one another? Should they be able to talk to one another?
What we can do, in the lightweight architecture definition language, is rather than say, "Oh write a JUnit or an ArchUnit fitness function to make sure these don't couple to one another," instead define the architecture as, "Define a component as these things, as these classes, define these services as these components," and then have the tool generate the fitness functions to make sure that those rules are in place.
We're defining the structure of the architecture letting JAI or fitness functions validate that structure is in place. We're not building each fitness function for a wall, we're building the plan for the walls and letting it fill in the details for, "Is this a valid structure or not?"
Prem: One more question here. Let's call it a language now for lack of a better word. Is this something that you're planning to release as part of the work that you're doing? Is this something that's upcoming?
Neal: This will be in our next book, Architecture as Code. It's very much going to be, yes.
Prem: Got it. It's like a companion to the book that you write. Then you expect that language to live on from there on in.
Neal: Not in any pristine form. We're using it as a way to express architecture concepts in a cross-platform or a platform-agnostic way. Anybody that wants to take that and extend it for their own particular uses, there's not going to be a language spec or an ANT grammar or anything like that for it. We were thinking about calling it LADL, Lightweight Architecture Definition Language, but that's to be determined. We're floating that out there.
Prem: We'll look forward to it. Really, really keen to see how it shapes up.
Mark: One more thing about that architecture definition language. One of the things that we experimented quite a bit with, and as a matter of fact, are still experimenting with, is the construct of this pseudolanguage, the keywords, to be able to make it very concise, very lightweight, to be able to describe our software architecture, but be able to feed that ADL definition into something like ChatGPT or any LLM, and be able to have it produce the resulting fitness function that is executable.
For example, ArchUnit or ArchUnit NetArchTest, these kind of things. There is a-- I don't know, what would you call it, Neal? Not a specification, but a way of being able to form this ADL so that it could be used not only to describe an architecture, but also to generate the code.
Neal: I would say prompt-friendly.
Mark: Yes, there we go, prompt-friendly. There you go. Thank you, Neal. [laughs]
Neal: This is also a good example to illustrate what Mark was talking about, of where this is beyond something like a diagram, because in an architecture diagram, you can define the boxes that define components and all that sort of stuff, but in the architecture definition language, you can define that same thing in text, but you can also define things like what is a bounded context and what components make up the bounded context and the schemas in my architecture.
Now that's a completely different view or perspective on the architecture, that's very valuable to the intersection of business analyst and architect. Maybe less so for implementation, but having those different views of the architecture and being able to validate those views. Let's validate the DDD view, the transactional view, and the infrastructure view by running the fitness functions that validate all three of those views and they're not in conflict with each other. That's the kind of utility you get for...
Anytime you talk about anything as code, one of the things you're hoping to buy there is automation fast feedback, and that's what we're buying here. "I'm going to make a change to this component relationship. Is this changing my coupling in a bad way? Is this changing my bounded context in a bad way? Is this changing something about the way you have to deploy this in infrastructure?" If I could check that in 30 seconds or less, then I'm much more likely to make that change than if it's a roll of the dice of some kind.
Prem: What you folks seem to be saying is that now, as architects, I can use this architecture definition language to express a set of these fitness functions so that it's more than just an architect hand-waving it. Now if I'm an implementing team, I can take that definition language, maybe even use some sort of tool or generator or what have you to automate that process as well.
Now I've got a whole bunch of these fitness functions integrated into something like a continuous integration pipeline or a continuous deployment pipeline. Is that how you're thinking about it?
Neal: Yes. In fact, one of the things we're going to address here toward the end is where do these things live and where do they run? Continuous integration pipelines is one place, but there's another place too. That's exactly what we're getting at here.
Mark: As a matter of fact, Prem, on the last podcast that we did, Part 1, we talked about that intersection of architecture and implementation and really what that meant. What we're able to do now, in Part 2, is to be able to not only describe that architecture, but be able to enforce it through tests as well. Quite simply, to start getting a little bit more concrete into this concept.
Any kind of architecture, whether it be a system, a product, whatever, the logical architecture really can be described in three main layers, and that is the domains, subdomains within those particular domains of the system, and then under those subdomains, components, the building blocks of a system that we talked about it in the last podcast.
Once we define the structure of that system, we can now use the ADL to describe what domains have we identified through our domain-driven design efforts or not, which subdomains, and we could actually describe those in ADL, feed that into a prompt, and then generate the corresponding executable code that ensures that alignment, so that all the effort we put in during DDD efforts, Domain-Driven Design efforts, or modeling, or architecture itself, now is enforceable through executable source code. That's that way of ensuring that alignment using architecture as executable source code.
Prem: I do want to ask you one question. A long while back, people had this notion of what was called model-driven architecture. Now, the cynic in me might say, "Oh, hey, we have seen this before, we have heard this before, but how is this different from model-driven architecture, which I guess, it's safe to say that it did not, or it met with lukewarm success," let's say that.
Neal: You're right. Absolutely. I remember MDA quite well. In fact, there's still a huge amount of academic work done around MDA just because it's something you can throw a lot of useless effort against. The big problem with model-driven architecture is they had these very formal languages, sometimes diagramming languages, sometimes specification languages, and they were trying to generate software systems soup to nuts and have people go to a room and think really hard for months at a time with their diagrams and click a button and working software comes out.
We figured out that doesn't work because the world changes way faster than you can change the models behind those things. This is the ultimate agile version of that. This is a super lightweight dynamic scripting language compared to something like the first version of Java, a strongly typed language in comparison to those things. It's a legitimate concern. In fact, we're not trying to create an ecosystem where we define every single joint point in the architecture. We're looking for things that are high-value targets for things that we don't want to break. A little bearing walls, that's one of our common analogies we're using.
It's okay if you move some of the walls, but some of them are really critical for the structure of the application. Same is true for some architecture characteristics. You can fiddle around all you want, but if you start doing something that impacts scalability, and that's really important, then you're creating problems. That's the structure we're looking for, not everything under the sun.
Prem: No, I can completely relate to this because my experience with diagrams as code has been very, very pleasant. Not every diagram is still possible to do in code form, but my first thing is to see if it is possible to draw in code and then, if that is not possible, only then do I look at other tools like Draw.io or something like that. These days, my default is to first look at something like PlantUML or Mermaid.
Yes, I can see how this can be a very big game-changer for a lot of architects. In fact, I wish we had this. I'm on a gig right now at a client and it is an architecture gig. I wish we had access to this ADL, which would have probably made our lives a lot more easier, made our ability to communicate our intent a lot more explicit. Yes, I look forward to it.
Mark: Yes, I just wanted to make one more comment about the MDA, Model-Driven Architecture, in the sense that we're not trying to generate any source code at all. What we're trying to do is really enforce an architecture. Also, another one of my experiences with MDA that I think, in my opinion, started lending itself towards its demise was the two-way aspect of MDA.
It wasn't create a model and generate the code, but we can also modify the code and regenerate the model. This two-way communication piece just rubbed me the wrong way back then, because the model should drive the source code, not the other way around. If we start changing source code and the way we structure our source code to redefine that model, i.e. that structure or architecture, that's where we get misaligned. The exact stuff we talked about in the last podcast.
Neal: This is where we talk about, this is the irrelevant historical facts part of our podcast. One of the things that I wrote a million years ago was the Rational Rose plugin for the Borland tool, Delphi. You could do round-trip engineering for the model to the Object Pascal code and the Object Pascal back into Rational Rose, because it had an extension API. That's exactly the kind of stuff you're talking about is.
Prem: That was the architect's ultimate dream, I think, right? [chuckles]
Neal: It turned out it was a perfect example of an anti-pattern because it seems like a great idea and then it leads you into a forest filled with dragons and monsters and you never want to go back there again.
Prem: Yes, I can totally relate to it.
Neal: Let's talk about a few concrete examples here because we've still been very abstract so far, but I want to make this more concrete than the last time we were here. One of the things that we talked about last time was this perspective from an architect standpoint of, "Well, can I really start expressing constraints that I care about in architecture in some sort of declarative language-like way?"
One of the things that we talked about last time was, "I have a monorepo, but the thing that I'm worried about is accidental coupling across the monorepo because that's the danger. You can easily write one of these structural fitness functions that say, "At the component level, never let these components import one another." Now I'm using the architecture that's embedded in the code to prevent that engineering practice from causing a problem.
Here's a counter-example. Let's say we decided to do a repo per service. What's the danger when you go to repo per service? The big danger is rampant copying and pasting. Because we can't couple, now we're just going to copy and paste everywhere. What's the architectural structural constraint I can put in place for that? I've generated a GitHub Action that is a copy-paste detector.
I'll decide the threshold of how many lines and how many places am I going to put up with this copy and pasted code before, as an architect, I say, "No, stop. We're going to create a coupling point around that code because it's creating too much churn because it's being copy and pasted." That's the kind of trigger that you want as an architect that, "Okay, I've made a decision and now it's leading us into a bad place. Can I build a trigger in my system that says, 'Oh, the bad place is happening. Let's go and try to address that.'"
That's not written in code. That's a GitHub Action. That's looking at some characteristic of the engineering behaviors in my code to react to that.
Prem: What other examples? The ArchUnit dependency analyzer example has been used to death, if I may say that. Thank you for the monorepo and repo per service example. Are there other examples that we can look to use or think of?
Neal: So many. It all goes back to the mantra, is, "Where's the data and how do I get to it?" I'll let Mark describe. How do you do eventual referential integrity or eventual data consistency or eventual all these data things? That's another architectural concern you have to address.
Mark: Oh, yes. Exactly. Let's actually marry these two podcasts together because, in Part 1, we did a touch on this alignment of data and architecture. The data piece was really in the form of data topologies, whether we're using a monorepo, we're sharing all of the data with all the services, a domain topology where we partition our data by domain, and then the very-hard-to-achieve dedicated or database per service topology where each service has its own data in a bounded context.
We touched on this, in the last podcast. Now we can marry these two together because how do we know that the domain data topology was the right choice for us? Is it aligned? We went through a lot of qualitative analysis in the last podcast in Part 1 of this. Now in Part 2, we can do quantitative analysis because what I can do is I can measure the eventual consistency if we are replicating some data.
If we are breaking apart our database but necessarily have customer information or keys that we now can't enforce, foreign key, primary key, this is another test we can actually write to say, "Do all the keys, our customer keys, in this database match all of the foreign keys in this database?" Because we've broken apart our data regardless of its domain or database per service.
If we start to find that these measurements are showing inconsistencies, therein maybe we don't have the right mechanisms in place to ensure that consistency or the fact is combining that data might be a better approach if data consistency and integrity is more important than the drivers to break it apart.
Prem: Here's a crazy idea, okay? You tell me if this is too crazy. As architects, we also have to either define SLAs, SLOs, Service Level Agreements or specifically Service Level Objectives. Now, are you thinking that it would be possible for me as maybe an architect or even a stakeholder to say, "Okay, these are my SLOs, and here is the ADL spec for all of these SLOs, so that now I'm sure that these SLOs are being adhered to?" Is that something that's way too crazy or is that still in the realm of possibility?
Neal: No, and in fact, that's exactly where I think enterprise architecture should go because you don't want enterprise architects getting into the details of which frameworks and library, but they do care about scale, security, elasticity, five years down the road, what capabilities are there. Being able to express this in a technology-agnostic way, but express our intent in a very precise way is exactly where we'd like to go with this.
Mark: I love your example, Prem, about an SLA or advertised SLA or even a SLO because there are so many dimensions to a service level objective. It might be just being able to do a two-day turnaround of any bug that's identified from our customers. That's a good example of more of a softer kind of SLO other than a guaranteed response time or guaranteed scalability or that sort of aspect.
That really runs into the intersection of architecture and team topologies. Also, the intersection of architecture and engineering practices. The fact that we can actually measure the processes, procedures, the agility of our teams and find where we're coming close or maybe not even meeting our service level objectives, independent of any technology aspect. Those are intersections that we spoke about, in the last podcast, that would impact that service level objective in those cases, including infrastructure, even including data for that matter.
Another good example, Prem, is this; do we have any reporting system accessing a transactional database? Because right now we're meeting all of our SLAs. That's part of the definition of that architecture. It's a constraint. No reporting shall be done by or into a transactional database, only reporting databases. We can actually write that test to check to see if a reporting database is connecting to or acting on queries in there through automation.
This is yet another kind of a data fitness function using architecture as code term to be able to enforce those kinds of constraints as well. Because if we don't, we might not meet our SLA if, all of a sudden, we run a massive set of reports. No one saw that coming. [laughs]
Neal: Here's a really simple concrete example of, let's say we have a system that's using a single monolithic database, and for scalability concerns, we need to break it apart into two databases. We have customers and we have foreign keys for customers for tickets. Each ticket has to have a customer before it can exist. "I was using the relational database for referential integrity. Well, what happens now?"
This is pretty easy though, because somewhere in your architecture and in something like a service mesh running, you can say, "Give me a hash of all the keys and a hash of all the foreign keys. If those don't match, my referential integrity is off. Where's the data and where does it live?" The data is there. It's in both databases. It's just not in a single place anymore.
Now, three lines of Ruby code, I can compare those to the hashes of those two when the system is stable and see if my foreign key constraints are still in place. That's a very simple concrete example of an architecture and data intersection.
Mark: Yes, there's another aspect here, Neal, that just came to mind when you gave that example. That is, one of the common things that we can measure that most tools measure, for example, is responsiveness of a particular API call, let's say. We can measure and track that through a fitness function. This is one of the most basic fitness functions that can exist.
We start to notice that response time is starting to get worse. We see that, in that particular fitness function, but then we don't know why. Other kinds of fitness functions we can do from even a data perspective is to say, "Well, why don't we also, at the same time, measure database connection weights?" Because if we see those on the rise, what it means is, "Hmm, somehow we are connecting or using the database more than we did before." We can use these as identifying root cause of another particular kind of fitness function that we're running.
Neal: That's a great example because, is that a data intersection fitness function or an infrastructure fitness function intersection? Yes, it is. It's both. I want to start wrapping things up because obviously, this is an expansive topic, but I want to talk a little bit about the intersection of infrastructure and architecture. Obviously, we just gave a great example of infrastructure and architecture and how that might impact.
Another example of the dynamic nature of this is, especially now, when you start marrying things like infrastructure's code, now I can create a message queue that when scale hits and it starts filling up, I can have my architecture spin up another queue and start offloading to that and have dynamic growth if I need to. That's a self-healing an idea as architecture's code, as long as you have other things as code.
One of the persistent questions we get here is, "Where do these things run?" You brought up, before, deployment pipelines, but a lot of these fitness functions rely on things like logs, forensic logging. Observability is one of those great superpowers because if I have an observability, every single service writes to a known place of all their communication, I can easily write fitness functions that govern what those things do.
Observability is interesting because, in most distributed architectures, observability is handled by something like a service mesh. All the operational coupling is in the service mesh, things like monitoring and logging, authentication authorization, service discovery, et cetera. Of course, that was used as the basis for the idea of a data mesh. The thing in a data mesh is different though is that, in a data mesh, you have these data products that are cooperative services.
For every operational service, you have a data product because it encapsulates the analytical concerns versus the operational concerns. From an architectural pattern standpoint, data mesh is really a way of overlaying a cross-cutting concern on top of an existing architecture. There are two architectures here, an operational one and an analytical one with a very well-defined join point, which is the data pump from the operational data into the analytical data.
Now you can start seeing that a lot of this architecture as code business relies on things running inside the service mesh and a parallel construct that we can see growing right now. I have an operational service, but it needs AI facilities. It's not just an LLM. I'm going to need a RAG database. I need some guardrails. I need some evals to set context for it. I need a bunch of stuff to massage that operational data before I send it to the LLM. By the time I get it back, what does that look like? It looks exactly like data mesh.
Now we can start talking about that orthogonal, that cross-cutting architecture of having a cooperative gen AI nodes, just like we have data nodes, because that's another cross-cutting concern in our architecture. Now we have operational, we have analytical, and we have AI concerns with a well-known connection point running against that service mesh. This is what Mark and I are referring to as a governance mesh, running inside your service mesh that manages and runs all these fitness functions, either as monitors or when they need to run to manage this thing holistically.
Prem: I really, really like the whole idea of an architecture mesh, which sounds super exciting, but this is 2025, so I guess I have to ask the question of how gen AI can help or if gen AI does fit somewhere in this to make it easier.
Neal: It does fit in here in a lot of different places. For architects, there are two important aspects to gen AI, I think. One of them is utilizing gen AI to do stuff on behalf of architecture, and the other is how you operationalize it so that the domain can use it in a reasonable way. The AI mesh stuff I was talking about is really part of the operational side of, can we create architecture patterns that allow us to utilize AI from an operational or an analytical standpoint?
From a use-it-to-develop-stuff standpoint, one of the obvious uses we've been using it for is taking our lightweight definition language and generating concrete fitness functions. Man, is it good at that. It's amazing how good it is at that. We were pleasantly surprised. We've been running this against several of the LLMs, and they are surprisingly good at that. It's good for that.
The other thing that we found it really good for, I know you're familiar with, but some of our listeners may be familiar with this concept of an architectural quantum that we came up with in the Evolutionary Architecture book and have been growing that definition for a while. Once you've defined the kinds of things that you're interested in, from a quantum standpoint, for example, we were talking about observability earlier. If you can get every one of your services to log all of their dependencies somewhere, software build materials, for example, you can get Gen AI to produce a directed graph to show me how things are dependent on one another.
That directed graph was always there available. It was just too much trouble to create by hand. Similarly, you can use logging, and we've done this before. I'm really curious as to the extent of synchronous communication in my distributed architecture, because this system calls this other system synchronously and it locks them both up. You create a log that says, this one calls this one, sync or async, and then show me the directed graph of the largest extent of synchronous calls. That's a great thing for the pattern-matching part of generative AI to do. It's that utility use that we've been seeing a lot of this, to help us do the analysis that leads us to writing the architecture in code.
Prem: All right, this was very, very fun talking to both of you. Any parting thoughts from you, folks, or do you have anything else to discuss?
Neal: We're trying to generalize this idea as architecture as code, and this is just following the footsteps of a bunch of other things. I'm old enough to remember when infrastructure as code, we tried for a long time. We had virtual machines and we tried and tried and tried. With Puppet and Chef, we finally did it, infrastructure as code, and just the explosion of capabilities that provide for our ecosystem. That really led to containerization and all the other things that we see all the time now.
We hope the same kind of consistency happens with architecture as code because it allows you to automate things in architecture that you have to do by hand now. It allows scale and consistency across your architecture by building things and have confidence that they actually work. It allows holistic reactivity. I've made a change here. What other parts of my architecture are going to be affected by that? That's the essence of Agile in architecture, is fast feedback. This is giving us much faster feedback on the changes we make in our architecture and the things that potentially we might need to address to repair something.
Mark: I just wanted to also add, before we close, again, just to reinforce the context of really what we're talking about here. We could talk about architecture as code in general, but I want to, again, bring it back to the intersections of architecture because this concept of leveraging fitness functions, whether we're generating them through AI or not, is one way to, A, detect if we have an alignment problem, and B, to ensure that we're aligned with all those intersections.
It's one thing to talk about the need to align architecture with various other facets of the business environment. However, it's another thing to be able to show and demonstrate that alignment. That's really what we're trying to achieve here with this architecture as code. Implementation is one of the bigger ones because it's one that, I think, is most influential to both developers and architects. It has to do with the actual software system or product itself.
These other intersections though, I cannot emphasize enough, they are as important as the architecture and implementation intersection. It's one thing to be aligned with implementation, but if we're not aligned with any of these other facets we talked about, it still won't work, it being the architecture.
Neal: You can tell we're very excited about this topic. We're starting to write our next book on this topic, but we're also rolling this material out in bits and pieces in several workshops we're doing at conferences, mostly in Europe, around the summertime, in May and June. Anyone who's listening to this, is already in Europe, or wants to travel to Europe and wants to see a one or two-day workshop about this material, we're talking about it a lot because we're obviously very interested in it, and we'll have it out in the world as quickly as we can.
Prem: Thank you very much for that, Neal. If I can be in Europe, I would definitely be there. With that, we come to the wrap of yet another episode. It was great having you, Mark and Neal. Until next time, this is Prem signing off.
Neal: Thanks, Prem.