Platform Thinking

Effective email is either a pointer or notification

Email is the only decentralized communication platform that has widespread usage. And this is more amazing considering it was invented in 1971. Email is an amazing technology and has stood the test of time.

However, there are challenges with email:

  1. It can be difficult to find information in emails at a later date.
  2. Visibility is limited to the recipes of the email.
  3. Discussions often don’t happen in the context of the work being done.
  4. Information is not organized very well.

I follow a few rules regarding email:

  • Whenever possible, don’t send information in email, but rather point people to information in a more permanent location (Git repo, Wiki, Discourse forum, etc.). If the information does not exist, create it, and then send the email.
  • Keep project-related discussions in Git pull requests, issues, forums, etc.
  • For transient discussions, use chat tools like Discourse chat, Signal, Discord, Slack, etc. This is more fun, and keeps email from clogging up with chatty stuff.
    This keeps the information accessible to everyone involved. It is also way more efficient as discussions and information are stored in the context of the work.

It is still very useful to receive email notifications when a piece of information or a discussion is updated. This is quick to process and gives everyone interested the opportunity to watch the stream of activity as it flows by. Most systems give you options for tuning how many email notifications you receive based on your time/interest.

Accessibility and context – the keys to effective communication and information.

envsetup.sh – a very useful automation technique

During a Android development stint, I learned about the envsetup.sh concept. This is a script that contains numerous functions get populated in a shell envrionment when the script is sourced. There two ways to source the file – you can type:

source envsetup.sh

Or use a ‘.’ for a shortcut for source and type:

. envsetup.sh

Most of my projects and Git repos now contain a envsetup.sh file (examples: Simple IoT, Yoe, TMPDIR Podcast). Typically all of the functions in the file have a common prefix. This gives them a namespace and allows you to see all the functions quickly in your terminal by typing <prefix><tab><tab>.

Why shell functions instead of something like Make, Earthly, Nix, Task, Mage, Pants, Bazel, Python …? Shell script is about the simplest abstraction on top of typing commands. Thus, if mostly what you need to do is execute a sequence of terminal commands, then shell functions are very efficient at doing this. A shell function is often the best documentation for how to do something – it is almost like a powerful checklist. There are no dependencies – every Linux and MacOS system comes with a shell built-in. envsetup.sh functions can often be used directly in CI/CD and other build systems (like Yocto/Bitbake tasks).

There are some common objections …

Shell is not cross-platform to Windows. That is unfortunate, but I rarely use Windows, and most developers I interact with use either Linux or MacOS systems. However, this may change with Zephyr as MCU developers traditionally have used Windows.

Why not use something more powerful like Make? With modern programming languages and build systems like Go, Rust, and Yocto, the is no need for yet another build system. The complex issues like dependencies are already handled. Thus, all you need to do is remember how to kick it off.

Why not use Python – everyone uses Python for everything – it is the most popular programming language ever! Python is great if you need to do something more complex, but it is a more complex programming abstraction. And mostly what you need to do is record a sequence of commands, any abstraction costs you more than benefits.

Why not a shell script that you execute instead of sourcing a script that populates functions? I’m not sure – the sourcing just seems more ergonomic to me and simpler. If you need to run a script to execute a command, then you need to process command line arguments, etc. You are now programming, and programming is what we are trying to avoid in envsetup.sh. Also, the functions are not as discoverable as when they are populated in your environment.

Shell scripting is not without its tradeoffs – when you do need to program something in shell, it can be very painful and errors can be subtle and hard to catch. However, AI tools are very effective at writing shell script, so this can be a big help. Linters and formatters are also very good at catching problems early and making your scripts more readable (more on this later).

In summary, think of your envsetup.sh file primarily as documentation. Create one in every project and instead of documentation how to do something, create a shell function. Your future self will thank you.

Thinking, Designing, Developing, Engineering …

If we are thinking without writing, are we really thinking?

If we are designing without sketching/drawing, are we really designing?

If we are developing software without iterations/testing, are we really developing?

If we are engineering without building prototypes, are we really engineering?

Something happens when our work is implemented in an external form that is staring back at us. It speaks to us, exposes the flaws, and shows us where improvements are possible. When our work is good, we can recognize it and find motivation for the next phase.

Yes, it is possible to do some things without shipping, but when we ship our work in the form of writing, drawing, prototyping, and iterating, a world opens up that we could never see before. New connections are made.

Optimize your habits/processes for shipping something – your work will get better.

The importance of Git Commit/Push often

There are many forms of “shipping” your work as we recently discussed

Shipping does not necessarily mean a product release, but rather releasing your work external to you. It can be a Git push, running tests in CI, a prototype, a document that others can read – basically something of lasting value that others can interact with. (Email does not count).

As a developer, the simplest way to ship your work is a Git push. It does not have to be perfect. In most cases, it does not even have to be done. That is the beauty of software, it is soft – it can be improved/finished later. A Git commit does not even have to be code – it can be documentation, specs, etc. A Git commit/push is the simplest and most effective way to demonstrate you are providing value to the project or organization. Yet how many of us are consumed with ephemeral activities that in the end provide no lasting value?

100 daily emails

Today marks the 100th “daily” email I’ve sent out. (I don’t actually send on weekends, or days when I’m out of the office). Some observations:

  1. Daily is easier than weekly – I was skeptical when others said this, but I think it is true.
  2. If I skip a few days, it can be hard to get going again. There is something about the process of doing something daily that energizes the creative process and keeps it going.
  3. Ideas are everywhere – when I write consistently, the mind starts to see ideas everywhere. There are 32 article ideas in my backlog – Ideas come in much faster than they go out.
  4. I spend 10-20 minutes a day writing these posts. Often writing one will spur the idea for the next, and I’ll write that one too. I think it could be even faster.
  5. Tooling is important. I have scripts that automate creating a post and publishing it. Kit is configured to pick up the post from my site’s RSS feed and then mail it out. There is nothing slow or painful about the process that pushes me away from doing it.

If you have feedback, please let me know! I’d love to know what topics are interesting to you or not.

The importance of small Git commits/pull-requests

Why are small Git commits/pull-requests important?

  1. small changes are easier to review. Large PRs are painful to review, thus they tend to be rubber-stamped and not reviewed, or rejected in OSS projects.
  2. you get to ship more often.
  3. other people are motivated by seeing work get done (positive peer pressure).
  4. if we are heading down the wrong path, this can be corrected earlier before wasting a lot of time.
  5. our work is more transparent, and transparency is a powerful tool.

Even if we are working on a personal project that no one else sees, small commits helps us organize our thoughts, reflect on what we’ve done, and receive the motivation boost that comes from incrementally shipping, even if only to ourself.

The three legs of YOUR Platform

Automation – start with a checklist.

Collaboration#1 rule is don’t view email as a permanent place to store information.

Process – the habits of your organization.

Demos vs. Products

I’m a huge fan of demos – so is Khem. They are a very important part of product development. They are a way to ship early and get critical feedback. Demos during the course of real product development are essential.

There are some challenges or risks with demos. One is that when managers see a demo, they sometimes assume the product is nearly done when this is rarely the case.

Other demos are for the purpose of evaluating some technology with little concern as to how it is implemented. The world has exploded with “maker” stuff (Arduinos, Raspberry PIs, etc). These are very useful for one-off lab experiments, but experience has taught me that it is generally a bad idea to ship products (at least industrial products) based on “maker” technology.

Products have considerations like cost, manufacturability, maintainability, reliability, and availability over a lifecycle that can be 5, 10, or more years for industrial products. We can ignore these concerns for the demo, but they can’t be ignored for the product.

Documentation is part of the process, not an afterthought

One of the best productivity hacks ever is to change your thinking about documentation. Most documentation is done after the fact, which is a rather distasteful task at this phase.

If we learn to use documentation as part of our thinking/design/implementation process, it can be enjoyable, and help us do a better job in the first place. A few ideas:

  • Write code comments before we write the code, describe what we are going to do, etc.
  • In a schematic, document constraints and design criteria as a note in the schematic before drawing a new section of the schematic. As you go, think in your notes.
  • Write the user documentation before implementing a feature – this may help us think more from the user perspective upfront.
  • If we are stuck on a problem, write documentation about it and check it into Git. This allows us to still ship something.
  • As we are doing something, create careful notes about all the resources we need to do the job, summarize important parts with screenshots, etc. It will be much easier next time.
  • Create a checklist before you do something.
  • When someone asks you about something, instead of writing an answer in an email, create a document and point them do it.

A small shift in our habits can have a big impact!

Two classes of tools

There are two classes of tools: Personal tools and Common tools.

A personal tool might be your editor – each developer has his own preferences and what editor one person uses does not affect another.

However, it is important to have a common tool for formatting code. So you decide on a formatting tool and everyone configures their editor to use that.

Some more examples:

Personal Common
Computer OS File/doc formats
Phone Git PR/Issue system
Notes system Build systems
Email client CI/CD
Browser CAD Tools
Git client/setup Compilers

Sometimes sticking with the common stuff is slightly less convenient than doing it “my way.” However, you need to decide if you want to be part of a sustainable business or just a few talented individuals.

Selecting tools

There are many considerations when selecting a tool:

  • will it do the job?
  • what does it cost?
  • can I get support?
  • is there a community around it?
  • will it be available and maintained long-term?
  • what does the future look like for new features?
  • is it accessible/available to others?

The last point is often overlooked – “That is not my problem.” However, if you are building a platform, this should be a primary consideration as tool accessibility is important for collaboration and maintenance. This is the difference between a sustainable business and a few talented individuals.

Handling the small details

We’ve discussed the necessity to fulfill your small commitments as a stepping stone for fulfilling larger commitments. We can expand this thinking – handling the small details well enables you to focus on bigger things.

In product development, we have many details to be concerned about:

  • consistent code formatting
  • testing new code
  • testing the system
  • ensuring there are no errors or DRC violations on a PCB layout
  • generating a documentation package (including BOM) for each PCB release
  • generating documentation for each project release
  • notifying relevant people when things change
  • reviewing code changes
  • organizing parts in the lab and in production
  • deploying software updates
  • publishing various communications
  • ensuring everyone on the team has access to needed information

We can do all of the above manually, and it is not a big deal to do once. However, these details soon start to pile up until pretty soon that can be all a person does. Fortunately, there is a better way – all of the above can be handled to some degree with intelligent workflow, automation, and tooling.

We have so many good options for automation available today – scripting languages, APIs, CI/CD systems, flexible DRC engines in CAD tools, Git based workflows, commercial tools and services, etc. Implementing and using these tools is not always easy and requires an investment in time and learning. However, this is much easier than manually managing tons of details forever and frees you to focus on more important things.

Simple to use vs simple to implement

To make something simple to use, often it is not simple to implement. For example, in the SimpleIoT UI, the following line of code is all that is required to add a text input field to a node. No handlers need to be attached, etc.

textInput Point.typeDescription "Description" ""

However, the code that implements the textInput function is a little more involved.

Generally, the better you want the user experience to be (even if your users are developers using your API or library), the more work you’ll need to put into things behind the scenes. There is a fundamental tension between “Simple to use” vs. “Simple to implement” – you can have one or the other – usually not both. We all use many “components” in product development, but an excessive off-the-shelf mental, especially at the top hardware and software levels of your product, won’t get you very far.

Simple != Easy

Integrate early

Integration is where we bring together separate parts of a system.

When things come together, problems appear: performance problems, stability problems, electromagnetic noise issues, mechanical interference, incompatibilities, manufacturing issues, usability issues, aesthetic issues, etc.

It is much better to discover these problems early, and the only way to do this is to integrate everything early in the project. And the only way this happens is if it is prioritized by management and supported by process.

Iterate Hardware Like Software

Simple to maintain vs simple to implement

Recently we talked about the tension between simple to use vs. simple to implement.

Maintenance is similar. If you want something that is easy to maintain, you need to put in the work upfront.

The Elm programming is a classic example of this. The initial coding takes longer than generating some Javascript from AI prompt. You need to figure out how to best represent the problem with Types. But after you get it right, it is so easy to maintain.

Simple – from whose perspective?

“Just keep it simple” – we sometimes hear this. But from whose perspective?

  • Legal/IP
  • management
  • IT
  • Financial
  • R&D
  • Security
  • Sustaining engineering
  • Purchasing
  • Manufacturing
  • Quality
  • Sales/Marketing
  • Customer support
  • End User/Customer

How do we prioritize simplicity for the above list?

Hint, the one at the bottom is probably the most important. Do you constantly keep your customers in mind as you make decisions? “Customer” may include multiple from the above list.

Confusion about when we are the customer

In our modern, entitled, self-serving consumer culture, we tend to be confused about when we are the customer or not. If we work for pay, our job is to do something to benefit someone else – our customer. We are not the customer in this scenario, someone else is. We are supposed to make someone else’s life easier or better. In our job role, are we serving our customer, or do we expect to be served? This mindset probably does more than anything to determine if we are useful.

Who is the customer in organizational hierarchy?

In a business organization hierarchy, where E (engineer) reports to M (manager), who is the customer in the E - M relationship? Our first inclination may be to think M is the customer – M is the boss, E should make M happy. But, lets think about this a bit more. Who does E create business value for? Is E writing code that benefits M, or producing a printed circuit board that M will directly use? Hmm, does not seem so. E’s customer is probably purchasing and manufacturing (in the case of a PCB). M does not directly produce tangible outputs. M’s job is to help E get the job done. Therefore, it would follow that E is M’s customer. Certainly, M has authority and needs to make decisions at times. But, in the end, the job must get done. Business value must be produced. In product development, authority or decision-making in themselves do not produce business value. The more people we have under us, the more people we serve. Do we exist to serve, or be served? The higher up we go, the more important it is to understand servant-leadership.

1 Like

Who is a changelog for?

Most projects have releases, and with each release, we describe what is new/changed/fixed in a changelog file. keep a changelog has a lot of good ideas.

Who is a changelog for? It is for our customers – those who use whatever we produce. The changelog communicates to our customers what is new and valuable for them in each release.

Once we realize who the changelog is for, then this can influence how we write changelog entries. A few ideas:

  • keep it is as succinct as possible (don’t waste people’s time)

  • does use technical jargon that our customers don’t understand

  • be humble – if there are bugs that got fixed, acknowledge they were bugs. Don’t try to embellish or gloss over bug fixes by calling them features, etc. People can see right through this.

  • explain changes from the lens of benefits to the customer/user, not from the developer’s perspective

Why are releases important?

Since many products/systems run software these days, they can be improved after the initial release. Most software projects have “releases” when a new version of the software is deployed or made available.

Why are releases so important? Some reasons:

  • Communicates to customers an update is available and what changed.

  • Provides a cadence for doing work.

  • Encourages development teams to “ship”. Shipping is motivating.

  • Delivers more value to the customer.

  • Helps us isolate problems if we know what is running and what changed.