Tuesday, August 16, 2022

Describing vs Creating a Thing

What I’ve loved since the first day I discovered programming, is that it is an endless opportunity to create.


What has become more and more apparent over the intervening three decades, is that language is a terrible place to make the source of those creative ideas.


This is why I think “source code “is a terrible place to put software. More specifically, it’s a terrible place to put decisions about software.


The reason for this is that we are restricted to describing the thing, and to do this we first have to pick a specific language.  Anyone who doesn’t speak that language is going to struggle to understand what is being described. Put two or three languages in the same room, and the problem gets exponentially worse.


For computers offer us an opportunity that is inaccessible without them, and that is the ability to literally create an instance of what is being described, in about the same time as it takes to describe it.


This digital instance of the idea, this digital twin, serves as a language-independent definition of reality for the project. In other words, if the digital twin is a mockup of the app, anyone should be able to use the app and understand the idea implicitly. Not because they read a well written description of the thing, but because they can literally interact with an instance of it directly. 


With that understanding, they should be able to request various development assets, in a specific technical context, that can be unambiguously interpreted to provide a layer of derived code based directly on the digital twin.


So if a widget in the project has a name, Date of manufacture, and serial number, our digital twin had better also have widgets, with a name, date of manufacture, and a serial number.


In fact, ideally widgets would have those three attributes anywhere that they exist within the system including the specifications, the backend code, the front end code, any test infrastructure, documentation, etc.


Each of those places will describe, in whatever language they are using, this widget again. Over and over and over again.


So when the notion of ‘what a widget is’ changes in any way, all of those different descriptions have to be updated to describe a now slightly modified widget.


But the reason I called the digital twin a single source of truth, is that with a single source of truth (as the name implies), we only have to update the notion of what a widget is in one place. 


And having updated the template example of what a widget is, it then becomes very easy to use that template to describe the widget in English, and C-sharp, and Python, and Java, etc.


If we don’t have a single, authoritative, template example of the idea, every time the idea changes our only option is to laboriously go through pages and pages of the English description, and tens or potentially hundreds of thousands of lines of code, to try and realign those descriptions with the new rules.


This is an exercise in futility. It would be like a world without sheet music!


Wednesday, August 3, 2022

Imagine a world without sheet music!

 Imagine a world where sheet music has never been invented.


Instead, each instrument has its own language, specifically designed to describe exactly how to play a specific song, on that specific instrument.


So violin music, would be in a different language than piano music, which would be in a different language still than flute music.


The implications of this are hopefully clear. If we had an orchestra and wanted to add a flute, playing exactly the same thing as the violin part, we should first have to hire a human being who knew both flute and violin Music, who could translate the music from one to the other. 


This kind of translation would be necessary anytime the composer changed the music when it is actively being developed.


This is obviously absurd, and I hope that no one would advocate for such a model.


And yet…


It seems to me that is largely the world that we live in when it comes to technology. There is absolutely nothing that is equivalent to sheet music in the tech industry!


Just to be clear, I am NOT suggesting some kind of universal language. I think that’s equally, or possibly more absurd than a world without sheet music, insofar as people have been trying to create such a language for 70 years and have failed entirely.


AI is the one obvious and notable exception to this, as eventually, AI will be able to simply take an English prompt for a program and give us code that does that. We are not there yet, but we’re getting pretty close.


But again… to be clear, I am definitely not talking about a linguistic description of some app or service - because that's not what sheet music does.


Sheet music just describes an abstraction of the song. It does not describe how to play that song on any particular instrument, and rather provides information that is going to be true about the song completely independent of which instrument it is played on.


It essentially just tells you the frequency and duration of each note that needs to be played.


The equivalent of sheet music in technology is a normalized, multi-dimensional, data-based, non-linguistic instance of the idea itself. 


Literally, at the end of the day, it’s just a database. 


At runtime, it will typically present as a json or xml configuration file, for example, but the source of it should be a relational database such as Airtable or SQLonAir.com.


The reason is that in Airtable, for example, we can create a language independent digital example of whatever is being described, at virtually the speed of speech. In other words the digital example can be created approximately as fast as that thing can be described in English.


And that thing could literally be ANYTHING. It could be an app. It could be a website or online service. It could be an organization, nonprofit, or other business venture. It could be a philosophical discussion about the nature of reality. 


The essential structure of *any* idea can be unambiguously constrained and defined by a normalized database representation of the idea, including detailed calculations on said data with lookups, aggregations and calculated fields.


This digital twin then, immediately and unambiguously, removes the idea from each of the participants' heads, to an external shared location (in the cloud) that everyone can either agree or disagree with, about how closely it does or does not line up with their understanding of the idea.   


What this addresses, is that without it, everyone has this model in their own head, and they assume that everyone else shares the same model.


But they don’t.


In reality, without a shared single source of truth, everyone’s model is going to be slightly different, and it’s like a big long game of telephone trying to communicate to understand how each person's understanding does or does not line up.


This underlying, language based approach is fundamentally broken at its core.


If the English description is essentially just reporting on the current state of the digital example of the idea, then anytime we change the digital instance, adding a model number, for example, We can immediately expect the English to be up-to-date because it is simply reporting on the state of the instance, and the instance now has a model number.


In the same way we can expect any code which has been written about widgets to also be updated, because their internal representation of widget should not be defined in that “source code”, because the python isn’t the source – the digital example we created is the source, And any linguistic description of widget, in any language, whether human or machine focused, should be directly derived from the digital twin so that all the linguistic descriptions simply “follow along” as the idea changes over time.


We know change is gonna happen, so let’s plan for it.


Saturday, July 9, 2022

Stop doing Design Time WORK at Runtime!

The problem with a traditional approach to development is that facts, which are always true about the idea being developed, end up being continuously recalculated in each context where that fact is needed, because it isn't just written down once at the beginning. 

If we take the time to write down once, in a machine queryable format, then we can query those details, calculate, and write down those facts which are going to be true in every technical context, once.  That’s why it’s called a Single Source of Truth.

Let’s take an example where a 3 character ID value is embedded inside of a longer string of text, starting an Index 5.  To extract that value you would take the substring with characters [5..7]. 

Original String: “01234567890123456789”

ID = 567

The value 7 is computed by adding the starting index 5 + the length of the parameter being extracted, but because of the "Fence Post Situation" the developer has to remember to remove 1 to correctly get the ending index. 

StartingIndex = 5
Length = 3
EndingIndex = StartIndex + Length - 1

         ^  

     Problem

This value must be recomputed, at runtime, on every platform ... correctly!

Consider however, that in fact EndingIndex = 7 is always going to be true.  It’s going to be true in Android, iOS, Windows, Web, Front-End, Back-End, Documentation, Testing.  The ending index is always 7 - as long as the starting index is 5 and the length is 3.  So why does this value typically need to be constantly recomputed at runtime?  Because it doesn’t usually get computed and written down once, at design time.


So - when that starting index is set, and the length is set - a Single Source of Truth can re-calculate the Ending Index once - at design time, before a single line of code has been written, and then shared liberally with all of the tech which needs it. 

Because those indexes are not going to change, unless the length changes.  Those are things which can be calculated once, at design time, and written down and then shared among every technical context that might need to parse that string.  And since it was just calculated once, and then written down, now it never has to be recomputed, or even understood in all of the places that might need to interact with those numbers.  Every technical context can just take that section of the string and that is going to be the appropriate part of the string for its parameter value.  This has the effect of simplifying the logic in all of the downstream tech which is going to interact with this technology.

If we don't do that work once, upfront, then every time that string needs to be parsed, the ending index based on the starting index and length has to be recomputed. 

It has to be recomputed in Android … correctly. 

It has to be reproduced accurately in Swift for iOS,. 

The Web app has to also accurately recalculate this value. 

And each of these contexts is an opportunity for one or more of them to do it wrong.  And when that happens, it introduces a bug.   So now we must rigorously test all of the code, in order to find that bug.  Additionally, every time that length changes, the starting and ending index that the length influences have to be updated and they have to be typically updated in the Android, and the iOS, and the Web app, and the unit tests. 

Because in all those places the code, which compute the ending index based on the length = 3, is considered to be “source code”.  This is true even though it clearly isn't the source of that length - which will change whenever we change the length of the parameter at the specification level of the project.

That happens once at design time and we could, if we had a single source of truth, just compute that new ending index once, and then write it down. 

And now the new ending index can be shared with any platform that needs to parse that string.  All they need to do is take the start index through the ending index and they will get the right value.


Friday, May 27, 2022

English is Purple and One Dimensional

English is Purple and One Dimensional

and why "Source Code" is a terrible place to put Software

Everyone agrees that a Picture is Worth a Thousand Words, but have you really stopped to think about why? 

An obvious reason is that pictures are 2 dimensional, and can make use of all the colors of the rainbow, while if I were to assign English a color and a shape it would have to be strictly Purple and quite Linear in nature.  Allow me to explain... 

It is purple because while we think of English as a Primary Color, English is in fact composed of two completely separate and distinct things, just like purple is actually a mixture of blue and red. 

What I mean is that English can be disambiguated into two completely separate and distinct parts.  A Blue Abstract Model representing the underlying facts and data about the idea being expressed, along with a Red Algorithm, that can interpret the meaning embedded in the underlying facts and generate the purple English that us human beings want to read, when given the Blue Abstract Model as an input.  We'll dig into exactly how this works below.

Additionally, the shape of an English document is very linear and one dimensional in it's nature.  In other words, when we read a book we read all the words in a big long line of words, starting with the first word, and then the next word, and the next, sequentially until "The End." 

We can read faster or slower.  We can skip over parts and move forward and backwards along the line - but in general, the meaning of language is conferred through it's vocabulary, syntax and grammar, rather than through it's physical location on the page or within a book.

These two facts about English, and about language in general are what make it such a terrible place to put software, technical systems, protocols, and complex ideas in general.

Instead, the English technical specification that human beings need and expect for any given project should actually be a report, written against an abstract model of the idea - which can be shared amongst all languages, including English, French, German, Spanish, C#, Python, SQL, etc.  All of these languages are purple, and one dimensional, and they are not a good format to assign as the "source" for complex ideas.

What's the Alternative?

At this point, you're probably asking... "Well, that's great EJ - but what's the alternative?", and that's a completely reasonable question.

While we might start with a Purple English description of an idea, literally the next step should be to extract a Blue, Data-Based, Abstract Model of the idea from the purple language (as described below,) that includes enough fidelity to unambiguously represent the strict facts about the underlying concepts.

Step 3 is then to validate that we have successfully accomplished this by creating a Red Algorithm (basically a "report") that reassembles the Blue Model back into the original Purple English.  Doing this proves, by it's very existence, that the model has enough internal detail to accurately represent the original idea.

The key is that by pulling apart the Purple into these two separate parts, a different "report", i.e. a different Red Algorithm, can take the same underlying facts from the model - but construct longer, possibly more detailed report about the idea... possibly in French, or German.  It would use the same underlying facts.  The same underlying elements and details.  The same information being communicated - but arranged into a different syntax, grammar - and possibly using a different vocabulary, i.e. possibly a completely different language.

Each of these different reports however hopefully represents exactly the same idea - the same underlying facts - which should be Language IndependentTruth should be language independent.

What is "Truth"

Answering this question may seem academic, but having a shared understanding of what makes something "true" is essential for meaningfully differentiating between a Linguistic Description of a system and a Blue Model or "Digital Twin" of the system as described below.

The best description I've heard for the definition of truth is that...

Something is True if it Comports with "Reality".

The problem with this definition is that of course everyone creates their own version of reality. 

So, while trying to communicate an idea with Bob, Alice will say some words, which hopefully have the same meaning to Bob as they do to her.  And then, based on Bob's understanding of Alice's purple words, he will say words back to her to convey what he think's she meant. 

And if Bob seems to be thinking of the same thing as Alice, then she may agree.  And if not, she might disagree and say more purple words back to Bob, in order to attempt to update his understanding to more accurately match her understanding of the idea that they're trying to communicate about. 

But this is all clearly an exercise futility,  even when both parties are speaking the same language, because "reality" is completely Subjective.  And all of this becomes dramatically more difficult when the parties are speaking different languages, like English and Python or C#, for example.

By contrast, the blue model described above can actually serve as "digital twin" (more below) of the idea - and then all we each have to do is agree that it accurately represents our understanding of the idea in question. 

This opens the door to simply define this "digital twin" as being "Reality" - at which point the truthiness of literally any linguistic statement, can be Objectively Tested by simply checking if it "comports with reality" - where reality is defined as our Digital Twin. 

Creating a "Digital Twin" for the underlying idea

Language's Purple and One Dimensional nature make it an undesirable candidate to be the "Source" encoding of complex ideas.  It is so inefficient at communicating complexity because all it can do is dance around an idea, relying on the parties consuming the idea to share the same understanding of every word and inference of the language being used.

The Blue Model described above, by contrast, is not a linguistic description of the idea.  It is not a language at all, in fact.  Instead, it is digital instantiation of the idea.  A digital example of the idea that really serves as the platonic ideal of the idea that we are ultimately trying to capture with Language, and as a result, provides us with the the opportunity to agree on a shared "reality". 

This "digital twin" can be created in virtually any no-code tool, from databases, to spreadsheets, to no-code services like Airtable, Tray.io, Bubble.io or others.  The only requirement is that it is not "code".  I.e. that it is just the decisions about how a system should behave, and should generally be exportable to json, xml, csv or a similar data-based, non-linguistic format.

This multi-dimensional data structure literally forms a physical picture in space.  Not a description, but a digital instantiation of the idea being discussed..

With this digital twin in hand, all the project stakeholders can agree that it is an accurate representation of the idea.  No words are needed.  They can simply look at the Digital Twin - and it if looks, and acts, and behaves as expected - everyone can give a simple thumbs up or a thumbs down. 

You could literally have 10 people approve the Digital Twin - and they could each literally speak a different language - and never actually communicate with each other directly in any way.  Instead, they all simply look at the model and give a thumbs up or a thumbs down.

Once everyone involved agrees, at an abstract level, that the digital twin accurately represents the system, protocol, or software that we are trying to actually build - everything else gets dramatically easier.

Mail Merge

Think of a simple mail merge, where we want to send the following email to Mary a Graphic Designer, along with Bob and Juanita who are applying to work in Sales.  

Dear Mary,
Thank you for your recent application to work with us as a Graphic Designer.  We will review your application and be in touch shortly.  Sincerely, HR Manager Ellen.
So while we want the same basic content within each of the emails, we actually need 3 different versions of the email, each one including candidate specific details like their name and job.  And, this email is just one of many different things that we need to do with this list of candidates.

We could do this by creating an email to Mary, and then copying and pasting it twice more, replacing Mary with Bob and Graphic Designer with Salesperson - and this is largely how software get's written, even in 2022.

Instead, however, we could also take the lessons learned in the 1980's, and split that 3 page purple content into it's two constituent parts. 

A list of candidates, along with the job they are applying for,   (a blue model)

Applicant  Phone     Job               Address...

Sunday, November 22, 2020

Low-Code works best with a No-Code Model

One of the most common arguments against No-Code / Low-Code development is that software is just too complex to fit into a "database."  This perspective makes sense because there are definitely elements of code that do not fit comfortably into a database, however - the scaffolding and basic architecture of most systems certainly do.  Let me try to persuade you that writing code without a No-Code model is like walking a tightrope without a safety net!

The Argument 

  1. Hand Code (aka “source code”) isn’t going anywhere.

  2. Applications At Rest (i.e., in the DB) are usually great Single Sources of Truth.

  3. An SSoT is essentially a Cross-Platform Interface

  4. Defining Right and Wrong

  5. A quick example shows WHAT might go in a Specification Database.

  6. Production DB (at rest) vs. Specification Database

  7. Traditional Vs. Low Code User (developer) Experience

  8. Low Code Development Flow

  9. In Conclusion


1. Hand Code (aka “source code”) isn’t going anywhere

In the low-code model that I'm proposing, there is still totally 'source code" - though it's more accurate to call it Hand Code, I think.  I'm a developer - I want to write code.  I just don't want to write even a single line of code that a tool could write for me instead.  I want to write the actual function body in most cases.

Still, the context in which I'm writing the code, the names of things, the structure of parameters and return types, the purpose - at least for top-level behaviors, should be predetermined by the spec, and I simply have to provide the implementation.  And when I'm writing that implementation code, I should always have code completion for the vast majority of the structure for the system I'm operating within.  On any project, in any language, today, tomorrow, and in 5 years.  By the time I'm writing code by hand - I want my IDE to have most/all of the scaffolding needed such that I always have code completion.

All that said, if we're writing a function to convert text ToUpperCase - at some point, some code has to loop over the string and create and a new version of the String with uppercase letters.  I would never, not in a hundred years, attempt to put that actual logic or any such a function body into a database.  That is clearly something that belongs as source code. 

When first considering low-code technology, it is quite common for developers to quickly find several specific examples of “source code” that does not easily fit into a database.  Incorrectly though, this leads them to believe that it is valid to then dismiss the entire approach as being infeasible.


2. Applications At Rest (i.e., in the DB) are usually great Single Sources of Truth.

Yet think about the fact that we can stop most/all applications.  That they can somehow always come to rest, And then, when they restart, they can simply reload their state, usually from a database of some kind, regardless of how sophisticated or complex the application or underlying ideas are.  This fact seems to imply that virtually any concept, independent of its complexity, can be unambiguously represented in a well-defined, well-structured database.

In other words, when the system is turned off/at rest - many aspects of its behavior can be stored/saved to a database.  As a result, the specific size/shape of that database inevitably almost always confers a massive amount of context about what the system is, what it does, and what it is and is not capable of doing.


Even simple questions like the relationship of contacts with phone numbers may/may not be quickly answered by looking at the python or the Java code for the system.  But if you look at the database and see something called PhoneNumbers, with a single link/relationship to a specific Contact - then you know each contact can have N phone numbers.  

If, by contrast, the phone numbers entity has no link directly to any contact, then the relationships might be more complicated.  Suppose instead you find that there is a ContactPhoneNumber entity along with a CompanyPhoneNumber entity. In that case, we can probably infer that each Contact can have many phone numbers and that even multiple contacts and companies can potentially share the same phone numbers.  


All of this logic, the entities involved, their structure, their names, attributes, and relationships, usually provide a detailed context for understanding the limits of what the system can/can not do. Any system which allows you to export all of your data to (for example, a JSON file) will inevitably leak a massive amount of detail about their internal design/model.  Not because they accidentally made you a contributor in their repository but because they simply exported your data.


3. An SSoT is essentially a Cross-Platform Interface

What fits comfortably in a database is not the implementation - but rather the architecture.  What tends to fit comfortably are the names, attributes, and relationships between things the code is responsible for handling.  It's a little bit like an interface that crosses all of the languages in a given project.  It is a single source of truth - and is an essential ingredient needed to fill in an entire layer of code that is entirely absent from most “traditional” project repositories at this point. 


It's a question of where we choose to save all of the many decisions that we make when designing and implementing software - and many aspects of what the software does - just fits much more comfortably in a database than into "source code.”


So on one end of the spectrum, we do (and always will) have code that is and deserves to be written by hand.  That's hand code - and is one component of the "source code" - so in that way, we entirely agree.  Even those functions that we should be writing by hand, though, almost always belong to and exist as part of a more extensive system.  We really should define at least the actual size/shape of as much of that system as possible, outside of code. 


We honestly can pull the description of what that system needs to do apart from the details about how to do that in a specific context, and, as it turns out, the WHAT parts tend to be those that fit comfortably into a database, and the remaining “source code” then does fit comfortably in code. 

In a "traditional development" - the square “WHAT” and the round “HOW” get squeezed into one triangular hole called "SOURCE CODE" - and it is just a costly way to approach the problem.

4. Defining Right and Wrong
A Single Source of Truth, by contrast, which authoritatively defines the system’s behavior and is entirely absent in most "traditional" models, allows for many other benefits.  By far, the biggest is that it enables us to look at any part of the system and apply the label "RIGHT" or "WRONG" in a way that is almost always utterly unrealistic in most "traditional" environments. 

Specifically, we can label it "RIGHT" if it matches the single source of truth, and if it does not, we can mark it "WRONG.”  This process is simply not typically possible in a traditional model, at least in my experience, because it is not uncommon to have often considerable variation between the Specification and what gets implemented in the end.  Additionally, there is often variation between the "Back-end,” the API, the UI, the Documentation, and the Sales Materials within the final implementation.

Without rigorous process management and oversight - the “source code” is usually a complete hodgepodge of inconsistency between all these different layers.  So in a traditional model, there is simply is no "Right" and "Wrong.”  There is no right or wrong because the spec usually says one thing, but that gets changed during implementation and changed again when presented in the UI.  And we wrote the docs against a beta version, so they don’t match how the final version works - i.e., there's no "right" or "wrong,” there's just the way it works in each layer of the stack.



5. A Quick Example show WHAT might go in a SpecDB:

Picture a thought experiment where we are building a simple String Library.  We can decide that it will include a ToUpperCaase and a ToLowercase function - and describe what those functions will do in different situations - and what their parameters and return types will be - before we pick which language or languages in which to implement the library. 

We can define many of these parameters before we start writing a single line of code.  And in fact, once we pick a language - a simple tool can provide stub functions that just throw "not implemented" exceptions until we write the implementation code by hand.  Another conversion-tool can write simple unit tests that call each of those functions.


It's important to note, though, that if we choose to call the function ToUpperCase - we are going to want that function, with that name, to convert the input string To Upper Case in Python, and C# and Java, and JavaScript, Today, tomorrow, in 5 years in 100 years.  And if there's an entirely new language created in 5 years, and we port our library over to the brand new language - we're still going to want the function in that language to be called ToUpperCase, to take a string, and return a string. 


Maybe that language will instead call a String a tokenArray - but it will have an input TokenArray, and will likely also return a TokenArray. The general notion of what it should do will not change, though.  And we should define this description in a format that we can easily share between any language, any operating system, any technical environment/context. 

PHP is just not such an animal.  A JSON file, or XML file, or CSV file or a DBMS, a NoSQL Data Store,  or virtually any other easily other Queryable datastore - is a perfect place to put the structure and shared static contents of the system.  Not the implementation, the architecture.  The moving parts.  The actors.  The User Stories.  Shared Static Data. 


6. Production DB (at rest) vs. Specification Database

We should model the production system off of a non-production, single, shared, Specification Database - and any change made in “the system” should always start in the specification database.  If there's a new thing - we probably need an additional table to represent that thing.  If one or more entities have additional or different attributes, we probably need to add or change columns or relationships to other things.  Suppose there are new instances of things (states, categories, roles, activities, conditions, limits, configuration values). In that case, we probably need to add or modify rows to one of the specification database tables. Or even if the rules change about who can access what and when It should be possible to encode those details into the project specification DB.


One way or the other, though, any idea, however complex, whatever it's implementation languages or final operating environments will run in (iOS, Android, Web, Windows, Mac, Embedded System, Saas tool - whatever), is representable at rest.  In other words, the vast majority of the complexity of said systems can be represented, at rest, unambiguously in a well-defined database. And this can be designed thought out before we start to write any "code.”  A Single Source of Truth. 


We get unmatched cross-platform symmetry by sharing one machine-readable, easily queryable specification database across the N technologies in the project.  By doing this, the implementations across even expansive projects will all tend to all match each other in precisely the same way that N technologies in most "traditional" environments will tend not to match each other.  At least until they are each vigorously tested and validated.  Trying to achieve that symmetry “by hand” is just an extraordinarily costly way to do it - and it gets even more expensive as the project gets larger.  Thus with every additional "player,” whether it's a new language, a new system, or API, the complexity increases. 


7. Traditional Vs. Low Code User (developer) Experience

Specifically, the parts that will tend to fit comfortably in a database are the system’s parts, which will be true completely independently of which language or operating environment they are running in.  For example, the ToUpperCase function is part of a library that also includes a ToLowerCase method.  The existence of those two functions - and we can put a precise (English) description of what they will do into a database.  And we can add additional metadata about our string library in other rows.  In this way - before we've even decided whether this will be a JavaScript, C#, Python library - or maybe all three - we can enumerate the specific details of what the library will include. Perhaps we can split the list of 50 possible string functions into 3 phases/versions - the essential functions in version 1.  And then less critical parts in version v1.1 and v1.2. 


A simple report written against this metadata lists the three planned versions - and describes which specific functions to include in each version of the software.  


A simple, often reusable low code tool can convert that same metadata into, say, a Python module, with a template for each function that simply throws a "Not Implemented" exception.  The human developer then only has to write the actual "source code" for what happens when you call StringLib.ToUppercase("foo").  Or, what happens when the StringLib.ToLowerCase("FOO") is called.  Or - and this is actually the important bit - what happens when you call StringLib.DoFoo("abc").


8. Low Code Development Flow

When we add “SubString” to the list of supported functions in the SSoT, here's what a low code development context looks like - most of which would simply not be possible in a "traditional" development environment.


  1. 5 Unit Tests would immediately start failing

    1. Python StringLib.SubString(...) fails with error: "Not Implemented Exception."

    2. C# StringLib.SubString(...) fails with the error "NotImplementedException thrown by the target of the invocation."

    3. Javascript/TypeScript fails....

    4. PHP fails...

    5. Java fails...

  2. The next time the human developers log in on any of those platforms - they see their CI errors - and would now have, each in their own language, an empty "SubString(...)" function - which simply throws a not implemented exception.

  3. Once each developer writes their version of the function - and checks in that code, the UnitTest resolves itself.

  4. The documentation now shows four functions - at least for those languages which have passed the unit test.  The documentation can list those that do not yet pass as functions that are "Still in development.”

  5. Everywhere that used to previously mention the three functions that the string lib supports would now list 4.  

  6. We can link bug reports and feature improvements to the specific item in the specification database (the actual "source" of each of these functions) to get metrics, per function, of how they are doing.  

9. In Conclusion
The key is that the entire "system" is defined and managed outside of the code.  I.e., in a No-Code model. Ideally then, only the actual creative bits (how do we convert text from one form to another) need to be written by hand. 

For as much as possible of the entire system, though, the definition and planning details for the specific behaviors are all stored outside of the code.  With this abstract model in hand, low-code-tools can then create most/all of the infrastructure/plumbing/scaffolding along with much of the testing/documentation, i.e., the connective tissue - which is essential in virtually every system I’ve ever encountered.


In addressing your concerns about future-proofing, the key is that it is possible to add a 6th language at any time - and that new language can automatically start with placeholders for ToUpperCase, ToLowerCase, DoFoo, and SubString.  Additionally, there would immediately also be four failing unit tests - one for each of the functions which we have not yet implemented in that new language.


We can attempt to manage these problems with appropriate oversight and things like agile development methodologies. However, it is still a really expensive way to do it, like, an order of magnitude more costly than it needs to be.