An introduction to the C4 model

The C4 Model for Software Architecture
(Image source: The C4 Model for Software Architecture)

This week, I was introduced to a new (to me) methodology called the C4 model. Now, in this context, C4 does not refer to the high explosive. In this case, C4 refers to a development methodology. Mostly, it refers to software development, but it has other applications as well, and that includes document development.

As part of my indoctrination into this methodology, I was provided this link. So far, it looks like an interesting read. I’m still reading about it, but here’s my understanding of the methodology thus far.

First of all, C4 stands for context, containers, components, and code. Think of it as looking at something at four different levels, from the top level (context) that shows the big picture, all the way down to the most minute detail (code).

The top level (context) refers to the big picture. Using maps as an example, here is a map of the United States — for purposes of this example, the big picture. You’ll notice that I drew a black box around New York State, which indicates the next level to which I will zoom.

If we want to drill down to the next level (container), a state would be the next logical level. So for the next map, I’m drilling down to my home state of New York. Again, I’m drawing a black box around the area to where I will drill down next.

A city or region is the next logical step (component). Let’s drill down even further, this time to my home city of Troy. Again, I’m drawing a black box around the next level to which I will zoom.

The bottom level of this methodology (code) shows the minute detail. For personal privacy reasons, I’m not using my home location, so instead, I’ll use one of my favorite establishments: Brown’s.

You’ll notice that I did not draw a black box in the last illustration; this is because we are at the lowest level in this model. I suppose if I really wanted to get granular, I could drill down into building floor plans, but for the purposes of this example, I think the point is made.

From how I understand it, the C4 methodology appears to be used for diagramming and documentation. It addresses a shortcoming in many technical diagrams in which they can be confusing and difficult to follow. C4 addresses this by showing how components relate to the big picture.

While I haven’t (yet) come across this in my reading, I want to note something that I think is important. When I captured the maps you see above, I thought it was important to highlight the context to which each level was related. If you look only at the bottom code level, you only see a building and a street (although I did make it a point to also capture the street name and route number). If you don’t know what city or state this place is located, then this macro level is likely useless information. The same is true for technical documents. Each small piece fits into a larger puzzle. If you don’t understand how the puzzle piece fits, you don’t get a sense of how the piece relates to the rest of the puzzle, and it becomes confusing and hard to follow.

As I said, I’m still reading about this, so I’m not yet sure what additional intricacies about the methodology I need to learn. Nevertheless, the concept does sound interesting, and I’m looking forward to learning more about it as I improve my skills as a technical communicator.

Some links, for your (and my) reference:

Fixing the worst online job application

Earlier, I wrote about what may be one of the worst online job applications I’ve ever experienced (I’d suggest reading that article first; otherwise, this one might not make sense). It got me thinking: what if I had an opportunity to fix this horror show of an experience?

Here’s what I would do.

My first instinct would be to shut down this monstrosity of a system. However, it likely wouldn’t be a good idea to shut down what might be the only means for an applicant to contact the human resources department. That said, this system is so badly designed that it’s likely to deter anyone trying to apply for positions, anyway. That gives me two options: either leave it as is, or implement a simple temporary replacement. Personally, I wouldn’t want anyone else to experience the horror show that I experienced, so I would opt for a simple replacement. The simplest option would be “send your resume, cover letter, and the position to which you want to apply to <such and such email address>.” Or, if I wanted to kick it up slightly, I’d make it a simple form: name, email, and a place to upload your resume.

If I opted for the form option, that would preclude some back-end mechanism to handle it. The simplest option would be to take that form data and put it together into an email that would format it, attach the resume, and send it to an email address. Of course, this opens another can of worms. First, there’s the matter of security. Who knows what viruses or Trojan horses are lurking in an attachment? Most forms like these ask for specific file types — usually a Word doc or a PDF — so I’d only allow those formats. I would also make sure that all security and antivirus functions are up-to-date; if a message does include a virus, at least it can be caught at the email application level, and it would be a matter of the cybersecurity team to investigate it further.

Once the temporary option is in place, and the horrendous system is shut down, I’d look into whether it’d be better to implement a new system out of the box, or roll my own.

Let’s start with rolling my own. I’d likely look into something using a SQL Server or Azure back-end (probably the latter, since everyone seems to be moving to the cloud, although that would require some brushing up on my part, since I don’t have a lot of cloud development experience). I’d probably put together a .NET front-end. Security, of course, would be a major issue to address, since we’d be dealing with applicant data. I would make sure that applicant data can be saved and pulled whenever an applicant applies for positions, eliminating the need for the applicant to continually re-entering his or her information, other than his or her login information. Again, the point is to make it easier, not harder, to apply for positions.

That said, there are a number of turnkey options that might be able to do the job better than I can. ICIMS is a popular SaaS product used by a number of employers. I would also look into other CMS systems that might exist. Other than ICIMS, I’m not sure of other applicant systems that can do what is required, but I don’t doubt that other systems exist that can maintain applicant data quite well. In this case, I’d switch my role from that of a developer to one of an analyst or consultant; what steps would I take to implement such a system? It would depend on the system and the environment.

Regardless of what system is used and how it’s implemented, any of these solutions would be better than the disaster of an application that I experienced.

Quarterly Bar Hop at River Street Market, March 18 #NYTechLoop #Networking

CASSUG member Susan Lundberg and our friends at NY Tech Loop are hosting the Quarterly Bar Hop at the River Street Market, 433 River Street, Troy, NY, on Wednesday, March 18, 2020, 5:30-7:30 pm!

Join us and other software professionals for beer, beverages, and networking!

For more information, see http://bit.ly/32JYXKG

Albany Code Camp — April 25 @AlbanyCodeCamp #albcc

I received an email over the weekend about a new event for this year — and for once, it isn’t related to PASS or SQL Saturday.

On Saturday April 25, the first (hopefully, annual) Albany Code Camp will be held!

I submitted four of my presentations. We’ll see if any of them are selected. Stay tuned!

Regardless of whether or not I’m selected to present, I will likely make the effort to attend. Hope to see you there!

Consistent code infrastructure

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”

— Martin Fowler

I’m currently working on a project in which I’m trying to deconstruct a database. In doing so, I’ve come across a number of things about it that, in the scope of databases, appall me. Who the hell creates a relational database with no defined primary or foreign key constraints??? And this thing is in a production environment, no less! While that’s a big part of my frustration, that’s another rant for another time. For this article, I want to focus on something else.

A big part of my task — and my frustration — is trying to figure out what the data columns are and how they’re being used in the application. I did come across a table that contains data as to what primary keys are defined (I have no idea why whomever built this thing didn’t actually create the primary keys), and I’m spending a lot of time trying to figure out how these tables relate to each other. As I already mentioned, there are no foreign key relationships defined. So a lot of my time is being spent trying to figure that out.

This is where my frustration — and the purpose of this article — kicks in. Whomever built this structure used names like “DataCounter,” “CrossReferenceCounter,” and so on, to define their “primary keys.” (I put it in quotes, because, like I said, they’re not actually there. And who uses the word “counter” to define them?) What I’m finding is that the corresponding foreign key isn’t exactly the same. For example, while the entity table uses ” DataCounter” for its “primary key,” other tables reference it using ” DataIDCounter.”

This might not seem like a big deal, but when you’re trying to figure out how to map large numbers of data tables and columns, you start questioning whether or not the relationships are correct. And I came across several others whose naming conventions are even worse.

Some of you might be saying, “that’s not a big deal. What’s your problem?” Well, trying writing an ad hoc query where you type in what you think is the column name, and it turns out to be something completely different. You end up wasting your time going back to look it up and trying to figure out what it is.

I remember a previous job in which I was looking at a piece of JavaScript code that contained two nested loops. You would think that the increment counter would use words that would make some sense, right? Wrong. Whomever programmed it named the variables “dog” and “cat.”

Explain to me how that is helpful to somebody trying to troubleshoot or edit the code.

In my previous life as a developer, I would write what I referred to as “open-ended code” — that is, I wrote it with the idea that it would likely be rewritten somewhere down the line. I wanted to make it easy for me (or someone else) to go back and edit or change the code, if necessary. I like to think that other developers have this same mindset, but, all too often, I come across examples like this that tell me that that is not the case.

If you’re a developer — whether it’s for an application, website, database, network, or whatever — keep your naming conventions and infrastructure consistent and meaningful. You will save another developer or support analyst a great deal of grief, frustration, and time.

First drafts are ugly

“The secret to life is editing. Write that down. Okay, now cross it out.”

William Safire, 1990 Syracuse University commencement speech

“No thinking – that comes later. You must write your first draft with your heart. You rewrite with your head. The first key to writing is… to write, not to think!”

William Forrester (Sean Connery), Finding Forrester

“Just do it.”

Nike

I will confess that this article is a reminder to myself as much as anything else.

Raise your hand if you’re a writer, and whatever it is you’re writing has to be perfect the first time around. Yeah, me too.

How many times have you tried writing something, but in doing so, you hit a wall (a.k.a. writer’s block) because you don’t quite know how to put something in writing? Or how often have you written a first draft, only to take a second look at it a second time and say, “what a piece of s**t!”

(And speaking as someone with application development experience, this happens with writing code, too. Don’t think that this is limited to just documentation. This is yet another example of how technical writing and application development are related.)

Someone (I don’t know whom) once said, “one of the stupidest phrases ever coined is, ‘get it right the first time.’ It’s almost never done right the first time!” In all likelihood, you need to go through several iterations — review, editing, rewriting, etc. — before a draft is ready for public consumption. It’s called a “draft” for a reason.

The fact is, nobody has to see what you write the first time around. If you’re trying to get started on a document, just write what’s on your mind, and worry about making it look nice later.

For every action, you need a reaction

I came across yet another example of bad interface design this morning.

After I logged into my computer, a pop-up window appeared. It was my Docker application, telling me that an update was available and ready to install. Okay, I said to myself, and clicked the button to proceed.

Except… nothing happened.

I clicked it again. And again. And again. I mashed the mouse button. Nothing. I decided there was a problem with the interface, went on with my work, and forgot all about it. At one point, I saw a Docker window appear, saying updates were being applied. Okay. Again, I went back to what I was doing.

I didn’t think anything of it — until I looked at my taskbar several minutes later. All along the taskbar were several new — and identical — icons that I hadn’t seen before, roughly one for each time that I had hit the mouse button. When I clicked each icon, I was greeted with a window that said “installation failed.” Well, almost all. The second-to-last one I clicked said, “installation succeeded.”

Yet another example of horrible design rears its ugly head.

As an application end user, if I click something where it says “click here,” I expect — and demand — that it does something. It doesn’t matter what it is. Granted, I would prefer that it performs the action that I expect when I click it, but even if all it does is change the mouse pointer, display an “in progress” icon, or display an error message, I expect some kind of response that indicates that my action did something.

An action that results in nothing is a huge pet peeve of mine, and, in my opinion, is extremely horrible design. A click that does nothing tells me that the application is doing exactly that: nothing. Having an action with no response is not only annoying, it can be potentially dangerous. What if — hypothetically — clicking a button resulted in lost data, but there was no indication as such?

A reaction is a form of feedback. If I click a button, a reaction — even if all it is is an in-progress icon — tells me that the application is doing something. If I click a button, and it does nothing, then I expect the application is doing nothing. An action without any reaction results in frustration on the part of the end user, and potentially dangerous side effects if the application performs an action that the user doesn’t expect.

If this is how you design your UX, then you need to rethink your design. When it comes to interfaces, every action must have a reaction.

Playing in the sandbox is important for documentation

While working on a user guide, I realized that I had administrative rights to the application I was trying to document. That was all well and good, except that I was trying to write a non-admin user guide, and I needed to know how someone who didn’t have admin rights saw the application. Fortunately, one of my co-workers sent me an application URL and a testing user login I could use that simulated exactly what I needed.

That brings me to today’s article. Many application development environments make use of a sandbox, or some other development, environment where a developer can play to their heart’s content — that is, some place where someone trying to test or develop applications can play with the app without having to worry about breaking anything important. That same testing environment is just as important for a technical writer.

Much of my work as a technical writer involves putting myself in an end user’s shoes. I’ll often go through an interface and document the steps a user might use, what a user might see on the screen, and the effects of certain buttons and links. One of my most frequent questions when I work on documenting an application is, “what happens when I click this?” After I do so, hopefully my next response isn’t “oh crap!”

This is why a tech writer needs access to a testing environment. Like application developers who need to test within a safe environment, a person documenting the system needs to be able to document the system and be able to do so knowing that (s)he won’t adversely affect the application by playing with the system.

I wrote previously that a tech writer can help an application developer, and vice versa. Indeed, the tech writer can function as an in-house QA analyst. In order to write good documentation, the writer needs a realistic environment in which (s)he experiences what an end user might see. Having a sandbox environment in which a writer can “play” provides exactly that type of environment. As an added bonus, not only does this allow the tech writer to produce better documentation, it allows that person to provide feedback regarding the application, which ultimately results in a better application.

Testing something? What’s the test plan?

Imagine if you will that you’ve been asked to test a product. The product could be anything — software, a car, a kitchen appliance, a piece of sports equipment, whatever. For the purposes of this article, we’ll say you’re working at some company, and you’ve been asked to test a piece of software.

You’re told to go into an application, and you’re given this instruction.

“Okay, test it and see if it works.”

That’s it.

How would you feel? Vague? Confused? Frustrated? Abandoned? All of the above? Something else?

Well, I, myself, have been put into this situation more times than I care to admit. It’s one of the most frustrating job situations I’ve ever been thrust into.

What, exactly, constitutes “see if it works”? I could simply start the application, see if it starts, and say, “okay, it works.” I suspect that that’s not what the people who make the request are looking for. Yet time and again, I get a request from a developer or a designer to test something, and that’s the only instruction I’m given.

And it’s frustrating like you wouldn’t believe.

What’s even more frustrating is when (not if) the application comes back with some kind of problem, and the people who asked you to test come back with, “you said you tested this! Why is this broken?”

Want to know why there’s so much friction between developers and QA personnel? This is a likely reason. This is something that definitely falls under my list of documentation pet peeves.

The fact is, if you develop a product, and you need to test it for functionality, you need to specify what it is you’re looking to test. You need to define — and spell out — what constitutes a “working product” from one that’s “defective.” Just because a car starts doesn’t mean it’s working. You still need to put it in gear, drive it, steer it, and make sure that it can stop.

If you are creating a product, you need to describe what parameters are required for it to pass testing. If you’re asking someone in quality control to test your product, provide the tester with guidelines as to what should be checked to ensure the product is functional. Better, provide him or her with a checklist to determine whether or not your product can be released. If you discover additional items that need to be tested, then update the checklist.

(If you want to know more about checklists, I highly recommend The Checklist Manifesto by Atul Gawande. It’s actually a surprisingly excellent read.)

So any time you release a product for testing, tell the testers what it is that constitutes a “good” product. Don’t just send it off with vague instructions to “make sure it works” and expect it to be tested. More often that not, that will result in a failed product — and defeat the entire purpose of why you’re looking to test it in the first place.

Don’t forget to edit your system messages

One of my current work projects is a administrative guide for our application. After a recent status meeting, one of the developers sent me a list of validation error messages that might appear during data imports. I was asked to make sure the validation messages were included with the documentation.

While going through the validation messages, I noticed that they were filled with grammatical, capitalization, and spelling errors. I asked the developer if he wanted me to edit the messages, to which he responded, “yes, please!”

People don’t think about checking output messages for correctness during application development. It is often a part of applications that is overlooked. For what it’s worth, I, myself, didn’t even think about it until I was asked about these validations. Nevertheless, reviewing and editing output messages is probably a pretty good idea.

For one thing, and I’ve stated this before, good writing reflects upon your organization. Well-written documentation can be indicative that a company cares enough about their product and their reputation that they make the effort to produce quality documentation as well. Well-written system messages indicate that you care enough to address even the little things.

Well-written error messages can also ensure better application usage and UX. A good output message can direct an end user to properly use the application or make any needed adjustments. Messages that are confusing, misleading, badly-written, or ambiguous could potentially result in things like application misuse, corrupted data, accidental security breaches, and user frustration.

Ensure your application development review and testing also includes a review of your system messages. It may be a small thing, but it could potentially address a number of issues. As someone once said, it’s the little things that count.