One of the great usages I get from generative AI is to use it for checking that my messages come across as I want them to do. ChatGPT, Midjourney and their likes are trained from vast amounts of human communication. To note how they interpret something gets to be a measure on how it would be received by fellow human travelers. At least I contend it is so.
Additionally I can “carve out”, with pretty good precision, the specific target group I want to reach with my article, picture, video, email, or whatnot.
My experience is that pasting a wall of text to ChatGPT will mostly stir the sycophant and produce general and pretty useless feedback.I still do it sometimes, to frame the discussion. I will write an article about this someday soon. For now suffice it to say that to get quality answers from the bot I focus on one thing at a time. The most important pieces first. Like the headline, or the description, or the final call-to-action. Or, which is the subject of today, an important picture. Since a few weeks, ChatGPT can read images.
I’m helping1 Joakim Tengstrand, the inventor of the Polylith software architecture, with an article describing the benefits of Polylith as seen from a certain target group of people. An important vehicle in the article is a diagram showing the important concepts of the architecture
I brought many versions of the diagram to ChatGPT. This is from when I showed it one of the final versions:
The target audience here is software architects. Which is anyone who writes software, but there is also a subset of developers who specialize on the structural and overarching aspects and help us other mere mortals find leverage through good architectural decisions.
The first answer is pretty impressive:
Impressive, though pretty general and shallow. Also it talks about some “vertical repetition” and draws significance from it (largely wrong, as far as I know Polylith). But let’s fix the shallow thing first. It is tempting to pick up some detail in an answer like this, but often it is more effective to ask ChatGPT to try again, or rather, dig deeper. For some reason that often produces the high quality answer I was first hoping for.
So, without giving it more details:
I’ll paste its answer to this as text, because it’s easier to consume that way. You’ll have to trust me I haven’t edited the text. (As if I couldn’t fake the images.)
ChatGPT: Certainly! Let’s delve deeper into the architecture based on the given diagram and infer more about its characteristics and implications:
Modularity and Reusability: The ‘Bricks’ represent modular components. This modularity suggests a focus on reusability, allowing for efficient resource allocation and easier maintenance. This also implies that when a change or improvement is made to one of these bricks, it could potentially benefit all projects using that brick.
Functional Coverage: The wide range of functionalities (“db”, “file”, “rest”, “cli”, “lmda”) suggests a comprehensive system capable of handling a variety of tasks. This breadth indicates a versatile architecture, adaptable to various requirements.
Project Specificity: Each project seems to have its own focus and usage pattern of the bricks, implying specialized functionalities or domains. For instance, the “email-lambda” project seems to rely heavily on REST and Lambda functionalities, possibly indicating it’s a cloud-based email service relying on serverless computations.
Redundancy and High Availability: The repeated vertical bricks hint at redundancy. In practical terms, this could mean that there are multiple instances of a service running concurrently. This is often a design choice for high availability, ensuring that if one instance fails, others can take over.
Optimization Opportunities: The distinction between ‘used’ and ‘unused’ bricks within projects provides a clear visualization of potential inefficiencies. If certain bricks are consistently unused across projects, it might be worth reconsidering their inclusion in the architecture, or at least re-evaluating their current implementation.
Consistency in Design: There’s a consistent design pattern, especially in the ‘Projects’ section. This could simplify onboarding for developers or architects who are new to the system. Once they understand one project’s layout, they can easily grasp others.
Potential for Microservices: The clear separation of functionalities within bricks hints at a potential microservices architecture. Each functionality (e.g., “db”, “rest”) could be a separate service that communicates with others via well-defined interfaces.
Evolution and Scalability: The grid layout suggests that as new functionalities or bricks are developed, they can be added to the system with relative ease, making the architecture scalable. Similarly, new projects can be introduced without drastic changes to the existing setup.
Inter-project Dependencies: If bricks represent shared services or resources, there could be inter-project dependencies. It would be essential to ensure that changes in one project or service don’t inadvertently affect others.
In conclusion, the architecture appears well-structured, with a clear focus on modularity, scalability, and redundancy. It offers a comprehensive suite of functionalities, catering to varied project requirements. However, regular reviews might be beneficial to ensure that all components remain relevant and optimized for current and future needs.
Except for “4. Redundancy and High Availability”, which comes from that “vertical repetition” it thought it saw from start, this is amazingly in line with what I know about Polylith.
I proceeded by asking it to target its description at software architects fond of Ports & Adapters (Hexagonal architecture), the very audience that Joakim is targeting with the article in question. Without a minute’s thought, the bot wrote large parts of Joakims article! I will not paste that answer here, because you may be like me and find ChatGPT’s prose extremely boring, but here’s my prompt.
I’d like you to present the important features for someone who is familiar with, and fond of, ports and adapters. Present it with the intention to spur interest and curiosity, even call-to-action in trying this architecture, that we can call Polylith. Try to keep the marketing tone down. Keep it to the point and honest.
You can try this conversation yourself, by starting with the same image and using my prompts. Here’s the image:
My conclusions from this particular exchanges with ChatGPT:
It is very good at finding the essence of a message, if the message is clear and focused enough.
Asking ChatGPT to think more, without adding any details, is very effective (and crucial if you are using it to test your messaging).
It can sometimes find, and stick to, irrelevant things.
- When it seemingly does so, confirm that it is not actually part of your message. I had many starting-from-blank conversations with the bot about this diagram and this was the only time it went out on that High Availability tangent.
A picture says more than a thousand words
In the conversation with the bot, I was careful not to give it any more information than the picture. I have just been asking questions. I happen to know that a big thing about Polylith is developer ergonomics. ChatGPT seems to have missed this part, even though I would say the picture at least hints at that development is important. I decided to direct its focus on it. Sorry for falling back on images. It was a lot of work reformatting the output in my word processor…
OMG. Spot on is almost an understatement. To test my advice on urging ChatGPT on, without adding any details, to get even higher quality answers, let’s make it chew on this one more turn!
Yes, yes, yes, and freaking yes!. Polylith offers all this! How can the AI deduce this from just that picture? Could it be that software architects are particularly good at blogging and sharing their thoughts, so that there is a large corpus for ChatGPT to draw from?
I just have to quote that summary:
The “development” project isn’t just a workspace; it’s the heart of the Polylith architecture. It upholds the architectural principles, facilitates best practices, and serves as a dynamic environment catering to both the current needs and future evolution of the system.
Writing this makes me so excited I now need to do yet another experiment. Let’s break the rule of not giving it more information than it has itself deduced from the diagram. I want to see what it will do with these insights (if we can call them that) if it also imagines the Clojure REPL to be in play.
A text answer again.I want the old school search engines to find it. 😀
ChatGPT: Ah, if Polylith is particularly well-supported for Clojure projects, then the “development” project takes on even more significance in the context of Clojure’s unique features and ecosystem. Here’s how:
Interactive Development with REPL: Clojure is renowned for its REPL-driven development, allowing developers to interactively experiment with code. The “development” project in Polylith serves as an ideal playground for REPL sessions. With all bricks in one place, developers can easily experiment, test interactions, and refine their code in real-time without leaving the REPL.
Immutable Data Structures: Clojure’s emphasis on immutable data structures ensures that side-effects are minimized. In the “development” project, this means any interaction between bricks can be tested and verified without concerns about unintended state changes or side-effects affecting other parts of the system.
Namespace Management: Clojure’s namespace system facilitates clear organization of functions and data. Within the “development” project, this aids in understanding the structure of various bricks and how they interact. It also means that dependency management and refactoring become more transparent and less error-prone.
Data-centric Design: Clojure places a strong emphasis on treating data as a first-class citizen. The “development” project can serve as a place where data flow and transformations across various bricks are visualized, tested, and refined.
Macro System: Clojure’s powerful macro system allows developers to create domain-specific languages (DSLs) or extend the language itself. Within the “development” project, custom macros that cater to specific architectural or business needs can be tested and iterated upon with ease.
Concise and Expressive Code: Clojure’s syntax and functional programming paradigm allow for concise and expressive code. The “development” project becomes a space where the clarity and simplicity of the code across bricks can be maintained and optimized.
Rich Ecosystem: The Clojure ecosystem has a rich set of libraries and tools. With the “development” project, integration of these libraries, or experimenting with new ones, becomes straightforward, ensuring the best tools are used for the job without disrupting the overall architecture.
Optimized for Multithreading: Given Clojure’s capabilities for concurrent programming, the “development” project can be a testing ground for ensuring that bricks interact correctly in multi-threaded environments, taking full advantage of modern hardware.
In essence, combining Clojure with the “development” project in a Polylith architecture leverages the strengths of both. It allows for a fluid, interactive, and robust development experience, tapping into Clojure’s powerful features while maintaining the architectural integrity and modularity of Polylith.
There. As a Clojure programmer, somewhat familiar with the Polylith software architecture, I can tell you that this is what you would get if you built your system with Clojure and Polylith.
I took to the keyboard to share some learnings about using generative AI that I’ve made over the last few weeks. Funny that it would result in ChatGPT blowing my mind again!
Since I wrote this blog post the article in question has been published here: https://medium.com/@joakimtengstrand/understanding-polylith-through-the-lens-of-hexagonal-architecture-8e7c8757dab1↩︎