Epic Culture-Not Many Titles

4 min read

I routinely look at the “about” pages of startups and companies I’ve just learned about. A company of 5-30 people too frequently has a page of titles that are very similar to this:

The Startup Staff titles

In fact, I took inspiration from a few that I’d just looked at to make that graphic.

CEOs, VPs, CTOs, Senior VP of Human Resources, Chief Marketing Officer…

The list goes on and on. It’s hard to believe that anything gets done given introductions at meetings must take a half hour.

This type of culture and company isn’t the “gets stuff done” that I look for when researching companies or doing investing. The titles get in the way of a collaborative atmosphere. You can respect someone’s ideas, wisdom, knowledge, and accomplishments without needing a label or a title. If your company is bogged down in these titles, what other parts of the company are getting in the way of getting things done?

In late 1994 early 1995 at Epic, you can see below the titles that we generally had. Epic had been around for 15 years already at that point. Well beyond the startup phase. 😀

Epic Titles in 1994-1995

As you can see — there weren’t many. I may be forgetting one or two, but I think these capture the essence of what we had pretty well. Epic was very heavily invested in software development and it showed. Software developers made up the majority of the staff. We had no “levels” or titles for developers that had been on the staff for a decade or more. Software Developers were software developers.

Software developers, as generally defined by Epic at the time, focused on all aspects of creating software, from inspiration, design, to project completion and testing. Team leaders did not create designs and there were no architects on staff that were creating boring UML swim-lane diagrams to follow.

Epic was a small enough company that there wasn’t need for titles. We got things done. The things we created became our calling cards, not a title. An interesting side-effect of not having titles was that employees were not scratching and fighting their way for a new coveted title (definitely a story for later during my non-Epic years). Epic’s (unwritten?) policy was to provide opportunities to staff for them to experience growth in skills and responsibilities. Successful staff had more options.

The harder I worked, the more fun I had, with no new title required.

Honestly, it’s pretty easy to spot someone that talks about doing things and has a great title at a company compared to someone who builds software at a company. I understand some level of management, administration, etc., may be necessary part of doing business, but what about everyone else? Is the new hire more interested in their title or the work that they’ll be doing?

To be clear, even without titles, it wasn’t uncommon for more experienced R&D staff to concentrate on some particular aspect of software development and spend less time overall than another developer might on the same task. That’s natural and plays to an individual’s strengths and company needs. One developer might do more code review because the team had hired more staff for example (that’s likely my story for my next Epic post).

My challenge to new software startups: skip the titles and instead make a great product. Be concerned with titles another day (or maybe never?). Concentrate on the success of the people and the collaborative culture.

Thanks for reading my Epic post, but before you go… I have an email newsletter subscription with several support options now available! Please check it out and subscribe! I’ve had a lot of people tell me they enjoy the content but I’ve had so few subscribers it has been tough to be motivated to continue (and it’s a paid service to add to the demotivating factors). If you know of others who might enjoy this content, please tell them!

Cooked and Cored Apples Anyone?

10 min read

I’m hardly a fan of a traditional “American Apple Pie”. I’ll eat them, but I’ll look for a better dessert option before I select an apple pie (and most every pie for that matter). I like a good dessert, and if I’m going to eat a lot of calories, I’ll choose something else. In fact, my wife enjoys baking and made a Skillet Pan Apple Cake that was way better to me. But, this isn’t going to be thousands of words about some nonsense like ad farms recipe web site followed by 30 advertisements and finally the recipe. Well, there won’t be advertisements at least. 😏

On EpicCare, on Cadence, and on Tapestry!

The third Epic graphical user interface application launched was Tapestry, the Managed Care solution. The team started shortly after Cadence GUI got off the ground. As I was on the Cadence team at the time, we did quite a bit of initial code sharing—hello copy & paste—with them so that they could get going and save the step of trying to start from the far larger codebase of EpicCare ambulatory at the time. There wasn’t much code sharing at the time beyond the initial dupe and drop though.

I’ll clarify: when there was code sharing it was via copying a file (and whatever specific functionality was necessary). While every team had storage space on a shared networked drive, there absolutely was no real source control system in place. No Git. No SVN. No CVS. There were no Git forks. Some of you may be horrified. 🤯

Long Live the Mapped Drive

Just a folder on a mapped drive (for non-Windows folks, it just meant that Windows PCs had a remote drive available as a specific drive letter, like M — we had M\cadence for example. That location presented as if it were local to our workstations).

That’s all we had and all that was used. It was organized chaos 🤢 at best. We were STRONGLY discouraged from doing file searches on the network storage (as it wickedly thrashed the server drives), so if we wanted to take a sneak peak at another team’s codebase, we’d make a local copy.

I’ll loosely admit the shared folder “worked” because there were only a few of us using any given team’s source code.

Later a developer on EpicCare created a small front end to file copying and introduced the idea of a “locked” file so you could tag a file as being in use and expecting changes. Manual merges of source code were 🤬, high drama, significant pain, and unwelcome events.

Visual Basic 4 and earlier versions weren’t focused on or designed for monstrously large code bases (yet all these applications were rushing headlong into that very situation unfortunately). Further, Visual Basic wasn’t then targeting code sharing either. Sharing meant making a copy and adding a dash of luck and a pinch of hope.

If you knew that someone had snagged a copy of your code and you enhanced it or fixed an issue, the Midwest Nice thing to do was to notify them of what you’d done. Honestly, there wasn’t much of that. The code diverged quickly. Think two children, a box of crayons, and the same drawing to color. The end results may be … dissimilar.

We were young and foolish in many ways, and of course sought to improve and toss our opinionated coding styles into “our” copy of the code generally neglecting to share at all. There wasn’t time we justified (and there was absolute truth to that unfortunately).

As the code bases grew, it became clear that the lack of sharing was becoming a maintenance issue. The Cadence GUI changed the styles of editable controls. Images and icons. Database code. It was all moving along and the only real blessing at the time was that it still wasn’t common for users of one app to need to use another app. So, they wouldn’t see the differences.

We knew though. Oh we knew.

Independence did not mean the code was improving. My favorite recollection of how bad things had become is a highlight for the cultural and technical problem that we had collectively created.

The MUMPS programming language has a function that I am confident is used literally billions and billions of times every day across all Epic customers to this day. It’s fundamental to string parsing in MUMPS. It’s the spice of MUMPS that makes the universe code flow.

It works like this (in a commonly used form):

PIECE(SOURCE,DELIMITER,PIECE_NUMBER)

SOURCE (string) - Target string to be parsed for substrings based on DELIMITER

DELIMITER (string) - One or more characters to use to identify the substrings of the SOURCE string

PIECE_NUMBER (integer) - Given the SOURCE and the DELIMITER, this value represents the specific substring string based on a one-based index.

A few simple examples:

mumps
piece("this^is^the^way","^",3) = "the"
piece("this^is^the^way","-",1) = "this^is^the^way"

It’s extraordinarily common to reach for the piece function when storing data in MUMPS globals or even when passing data to functions or when doing RPCs to the server from the GUI application. It’s a useful way to pack data into a single value.

All the GUI applications needed a piece function to extract substrings that had been lovingly hand-crafted in MUMPS.

The Application Kitchens

Because we all knew better than our predecessors, each GUI team had their OWN piece function. You’d think something so fundamental would be shared. Mmm. No.

There was a reason other than hubris why Cadence GUI didn’t share the piece implementation that was used by EpicCare at the time. At first we shared like cousins once removed (“here — take this, I’ll see you at the next reunion!”). However, during a dark day of debugging an issue of code that seemed like it should be working from reading gobs of application code, I debugged into the piece function, baffled by what was happening. Step. Step. St…

WHAT THE FUNC IS HAPPENING???

The EpicCare piece function that we’d been using included a bug. When requesting the last substring from a string in several cases, it would improperly add a empty space character! Like finding a bug in an apple pie, it was just as unwanted in this code.

I rewrote the piece function to exclude the functionality of adding an extra space and tweaked some of the logic so that it would do fewer string concatenation operations leading to a measurable performance boost (the old 386SX/486 Intel chips along with the slow RAM of the day weren’t great at hiding mindless copies that I see far too frequently today in code).

Yes, I did make a journey over to the EpicCare team to discuss the discovery. They were interested and investigated, but … postponed a fix their version indefinitely. They had built a unfortunately surprising amount of logic that depended on the bug so fixing the issue would be far more impactful than desired. They stuck to their recipes.

By postponing the fix, they of course made the impact larger over time. They may have decided to include the new bug-free and faster version as a Piece2 — I can’t remember for sure. Eventually, they fixed their function once tracking down all the locations dependent on the incorrect functionality. To be clear, the piece bug didn’t cause a bug in the application, as their code expected the bug. There was no end-user impact.

Tapestry learned of the bug and rather than using the version we’d created and tested on Cadence GUI, … they wrote their own. I don’t know why. I imagine a developer thought they could further improve the performance of the piece function for some edge cases.

I am skeptical that the amount of extra time spent to attempt further optimizations was realized as a benefit to end users especially given the cost of and loss of time to make and test the changes (and run comparisons, etc.).

In case you’d forgotten, Visual Basic did not have a unit-test or profiling infrastructure at all. If you wanted “test code”, you’d add it, and then remove it (or comment it out if it could be valuable in the future). There were many developers that used their watch or a stopwatch to do performance analysis back then. It was elementary at best.

I wish I could honestly say I’ve never spent time over-optimizing a function. Those who know me well also know that I later practiced and evangelized:

“optimize when you need to optimize and no earlier.” -A More Mature Me.

Or …

”Sometimes you’ve got to know when to hold back optimizations, and other times, know when to fold them in.” - Definitely NOT Kenny Rogers

The amount of duplicated yet diverging code grew until their was an upswell of interest in creating a new team to maintain and share application code. After a few meetings, it was a go. Not long after, the team was staffed by one developer full-time with assistance from all the GUI application teams.

It was called…

ApplCore

One of the primary motives of the ApplCore team was to release shared code with the applications which was a different strategy from the “Core” Foundations team. (Get it? Application Core vs Core? Yeah, not original.) ApplCore wasn’t a product as much as it was a “concept.”

The Foundations team was always working on a version ahead of products. Changes in Foundations would be made, tested, and then released on a specific date. Teams would then take that release, do their development during their development cycle, and ship a release.

The rationale was that the Foundations team wanted maximal “baking” time for their code. By releasing a full development cycle ahead, they could be generally assured that their code would be tested at Epic for a full application product development cycle.

But ApplCore would be different. The delay of doing coding a full release cycle ahead didn’t work well for application products. Requiring a massive amount of predictive coding was untenable: “what are we going to need in 18 months”?

Unlike Foundations, the ApplCore code still lived in its own source tree. There was no obligation to take the code at any particular time, but teams were expected to not make changes to a copy of the ApplCore code without contributing back to the original.

I’m going to save the details of why ApplCore was doomed to fail for a later post. Some of you may know. 😉

And now onto the tasty part …

Apple Pie Skillet Cake, Canned Apple Pie Filling version

This is not low calorie, healthy or low fat. This is tasty and straightforward. It’s not fancy. It uses canned apple pie filling. 😋

  • 1 10-inch iron skillet
  • 1 20oz can of apple pie filling (sweetened)
  • 1 cup unsalted butter (2 sticks)
  • 1 1/2 cups packed light brown sugar
  • 1/2 tsp. ground cinnamon, plus a little more for topping
  • 1 tsp. pure vanilla extract
  • 2 large eggs
  • 2 cups all-purpose flour
  • 1 tsp. baking powder
  • 1 tsp. kosher salt
  • Optional, but say YES to vanilla ice cream (or a cinnamon ice cream is also GREAT)
  1. Preheat Oven to 350F
  2. (Optionally stir in 1 tsp of cinnamon into the apples in a bowl)
  3. Melt 1 cup butter in a microwave safe bowl (or on stove)
  4. In large bowl, whisk in the vanilla, sugar, and 1/2 tsp. cinnamon
  5. Once well combined, whisk in eggs until smooth
  6. Add flour, baking powder and salt until just combined — don’t over-mix
  7. Fold approximate 1 1/2 of the can of apple pie filling into the bowl
  8. Pour batter into skillet
  9. Bake for about 25-30 minutes (check with a toothpick — should come out clean)
  10. The pan will be HOT 🔥 (and stay hot)
  11. Top with remaining apples and add extra cinnamon if desired

Enjoy!

Hi! Before you go...🙏

I really appreciate you stopping by and reading my blog!

You might not know that each Epic blog post takes me several hours to write and edit.

If you could help me by using my Amazon affiliate links, it would further encourage me to write these stories for you (and help justify the time spent). As always, the links don't add cost to the purchase you're making, I'll just get a little something from Amazon as a thanks.

I'll occasionally write a blog post with a recommendation and I've also added a page dedicated to some of my more well-liked things. While you can buy something I've recommended, you can also just jump to Amazon and make a purchase. Thanks again!

One Easy Way to Not Get the Pay Raise You Want

3 min read

I sat in Carl’s office. Nervous. I was working up to why I’d asked for the meeting through my mastery of small talk at the time (I wish!).

I’d decided that my last pay raise wasn’t enough and felt I deserved and needed more. It was time to ask. I’d never needed to do that before (and thankfully, I’ve only needed to have a similar conversation a few times over my career).

I’d been on the Cadence team for 6-9 months and was starting to get an itch for something different (more about that next time!). I had some confidence I was still excelling although it wasn’t because I was getting that feedback directly from my TL. That just wasn’t how he managed unfortunately. All I had to go on was my output: be it speed, quality, ideas, successes, challenges, etc.

In the days before the meeting with Carl, I worked myself into a nervous frenzy. I had a mental flow chart constructed of like 30 thousand different ways the conversation could go as soon as I made my request.

”I’d like to get a raise

[INSERT DRAMATIC PAUSE]

for no less than $$$…”

SERIOUSLY. I said that. “No less than …”

It doesn’t matter how much the request was for as I had established the rock bottom amount!

While I’d mentally prepared a low-end number that I was going to negotiate with if he outright refused (as I was prepared to declare that I would probably leave), I had never intended to say it out-loud except in flow chart branch #2102, “low-end-salary-requirement.”

And here I was giving away that number right away!

I tried to back-peddle a bit and provide a broader range, but it fell flat. There was no escaping the $ amount I’d already said.

Chit chat ended. I left, dejected, but a bit hopeful he’d see past that number and offer more.

Don’t do this. Ever. You may think it’s obvious. It was even to me! My nervous brain decided to give out all the facts right away.

Epic pays monthly for salaried staff, and the next pay period was only a week or so away.

I looked for my paycheck in my mailbox a LOT on payday. Finally, it appeared.

Cautiously, I opened the envelope to look at the check and pay stub. I could see that the check amount was larger, but given taxes, I didn’t have the math worked out without looking at the stub.

A Giant Slice of Humble Pie

A few days later, I was again in Carl’s office. My pay had increased by the exact minimum I’d asked for.

This time though, things were different. I was ready and I’d decided that I wasn’t going to negotiate like I’d tried earlier. I told him I’d messed up.

”I need $$$.”

The amount was twice what I’d just gotten.

Carl responded that he’d check with Judy, but didn’t see any reason that he couldn’t make it work. I got an extra check that month to make up the difference. That was a nice touch I admit.

While the humble pie was bitter and nasty, I learned a negotiating skill!

Have you done something like this? Or am I completely alone on this?

Hi! Before you go...🙏

I really appreciate you stopping by and reading my blog!

You might not know that each Epic blog post takes me several hours to write and edit.

If you could help me by using my Amazon affiliate links, it would further encourage me to write these stories for you (and help justify the time spent). As always, the links don't add cost to the purchase you're making, I'll just get a little something from Amazon as a thanks.

I'll occasionally write a blog post with a recommendation and I've also added a page dedicated to some of my more well-liked things. While you can buy something I've recommended, you can also just jump to Amazon and make a purchase. Thanks again!

My Favorite Screwdriver

2 min read

When I need a screwdriver for a project of length that exceeds a few twists, I will absolutely go get this screwdriver, every time. Even when I know it’s stored in a small bag/kit I use for tool transport in the basement several floors away, I get it. It makes me that happy to use.

The model (and name) number don’t roll off the tongue: Wera - 5051025001 KK 26 7-In-1 Bitholding Screwdriver, but that doesn’t matter. It’s just my Wera screwdriver.

Wera Screwdriver

Why I like it:

  • It feels great in my hands. It has some texture and not just a flat rounded shape.
  • It can be in a compact or expanded mode.
  • The bits that are included are generally what I need around the house. They’re extremely durable and I’ve not experienced any degradation of the metal material like I have with a lot of cheap bits. They’re sharp and precise (where needed).
  • The “head” of the screwdriver spins so you can maintain a firm grip near the screw while still spinning the driver freely with another hand.
  • The bits firmly snap in and snap out. They don’t fall out on their own and I don’t have any issues inserting or swapping a bit.
  • The bits all fit inside of the screwdriver when not in use (less to loose). I have several screwdrivers that have extra bits, but it seems that many of them require one bit to always be at the ready. I assure you — it’s rarely the one I need.

While I wouldn’t buy it because of the included carrying case and don’t feel it’s necessary, I’m not ashamed to admit that I put it back in the case when I’m done. It needs a nap occasionally after hard use and it’s a great place for it to rest (and to prevent unnecessary wear and tear in my tool bag).

Wera Screwdriver-Open

Because my needs occasionally stray beyond the included bits, I bought the BC-30 Universal Rapidaptor set as well. It includes not only 29 extra bits, but it can improve many ordinary screwdrivers that have replaceable bits.

Wera Screwdriver-Extras

I do have a bit of screwdriver envy though as I’d like to try the ratchet version: Kraftform Kompakt. I 🥰 ratcheting screwdrivers as well (but don’t have a favorite that has warmed me over yet).

If you buy something from a link, Acorn Talk may earn a commission. See my Affiliate Programs statement.

You won't believe what color they selected ...!

4 min read

Of the numbered choices below, which color combination was used as the “read-only” data entry field in EpicCare Ambulatory/Legacy?

Select the color combination you think was used

The background color of most of the UI was “battleship gray” as shown above.

You may remember from my post The App is Too Fast!, that Visual Basic 3 (and Windows 3.11) had a very limited color palette. Even as I created that sample application in Visual Basic 3 for this post, I was again surprised how few colors we had to choose from!

In any case, I’m waiting for your answer.

Come on. Stop trying to skim ahead to see the answer before you pick.

It’s definitely not #14. As the background color is a dithered orange, there wasn’t a reasonable color combination that worked well for showing text on it correctly (as you can see from the screen shot).

Have you guessed?

There were very few (if any) design guidelines for how a graphical user interface should LOOK back then.

OK, alright. It was #3. A yellow background and black text.

It was Yellow!

I never heard a concrete and well-reasoned explanation for the choice of yellow. What this meant was that if there were fields/inputs on a form that were not currently available due to configuration or selections made by the user, instead of a typical white background, the input background would be yellow.

On a screen like EpicCare Ambulatory Order Entry back then, where 95% of all the fields that might be used by any combination of an order (labs, prescriptions, tests) were placed, many of the fields would be shown as yellow at any given time.

”White means work.” —Nurse from Kaiser Permanente NW

During a few day site visit to Kaiser Permanente NW (many years before the big sale to Kaiser Permanente National), I and a few other developers were following a nurse around during her shift. She had just walked up to a shared terminal and started to place an order. That’s when she said that.

”White means work.”

What was interesting about that was that she had just landed on one of the most complex screens in all of EpicCare Ambulatory at the time. It was a chaotic orchestration of labels and inputs and list boxes, and tables and … literally everything seemed like it was on this form. Imagine the drawer we all seem to have, the one with every miscellaneous thing in it to handle nearly anything that life throws at us.

That drawer was Order Entry back then. If you could find it all, you could finish the task.

As she moved through the necessary selections of the particular order she was placing, the seemingly endless fields on the screen changed to “white” and that’s when she uttered that amazingly memorable phrase.

She was disappointed by how much of the screen was going to require active input and energy from her. When we asked for specifics, she mentioned how the “old way” was faster because there was far less tedious fill-in-the-blank to make the computer happy.

Her complaint wasn’t about the yellow — it was about the fact that this modern system frustrated her and signaled that she’d need to do extra work to satisfy the computer.

Is the work that the customer is doing for your software or for them?

Think about that as you create your next app or workflow. Please.

The Yellow Rectangle Road …

During our initial Cadence GUI design sessions, we avoided the “yellow” backgrounds for read-only fields. While it was a departure from the established style of EpicCare, the users of these applications would have zero cross-over at that time. We picked #10. There was some internal moaning, but we held fast.

”Hold the grays!”

I know there were limited color choices, but for me and the way I’m wired, bright yellow rectangles drew my attention unnecessarily when these should have been no more prominent than the white text input fields. In fact, I see them first as I suspect is the case with many others.

The yellow background remained part of EpicCare for more than a few years. Thankfully, it didn’t continue through the EpicDesktop/Hyperspace transition.

What color would you have picked (given the choices above)?