How We Work
We build user-friendly software for the energy industry.
We say it a few times on this website, but really, that’s precisely what we do.
We also wanted to add some details around our processes and beliefs. These are part expectations and part aspirations of Bellawatt's work philosophy.
Generally, we deliver business solutions, not just product, and definitely not just code. Our technical team is not separate from our product team, business team, or clients. When we deliver something, we are thinking about its end value. If we see a potential improvement for the end-user in a design or implementation, we act on it.
To deliver quality solutions, we prioritize learning. This means continuously digging deeper into our industry and current tools, as well as regularly stepping out of our comfort zones to try new concepts or technologies. Given a choice, we lean towards generalization and away from hyper-specialization, but we aggressively push for both.
How We Spend Time
We often and regularly cut scope. We would much rather cut our scope (and yes, short-term profitability) than deliver something that we don’t believe the client needs. We've done this for all of our long-standing clients, and we try to do it internally, too.
Executing, Learning, and Creating
We work hard, we love to learn, and we encourage creativity. This document focuses heavily on how we execute projects. There are also some concrete ways (like pair programming) that we approach learning and sharing knowledge. What you won’t see (yet) are concrete processes on how we foster creativity. Both learning and creating are areas in which we are still experimenting to find systems that work for us as a team, and this section will evolve as we identify our preferred methods.
We’re remote, do not believe in a 9-5, and avoid meetings at all costs. We work best with individuals that are capable of getting the job done on their own. Our team members have wide latitude to work in a way that fits their lifestyle. The expectation is that we all deliver quality while keeping our commitments to customers and team members."
How We Communicate
Focus on Deep Work
We fight distraction head on to give our team the space to get deep work done. We ask our team to delete slack from their phone and to disable email notifications, and even our CEO often works with these programs closed.
We do check in a few times a day so that nothing slips, and for emergencies, we encourage anyone to call or text us.
We don’t do daily standups, and hold team-wide meetings just once a week. Mornings and all of Monday are reserved for deep work, and we'll only schedule meetings the rest of the time to resolve critical issues. And if we can, we'll batch all of the meetings into one afternoon.
We also meet in person twice a year for an international company-wide retreat, where we spend time together talking, coding, and dreaming.
We communicate primarily through writing for a few reasons:
- Written communication requires a specificity that verbal communication can skip.
- We want to avoid he-said/she-said misunderstandings.
- When a misunderstanding does happen, everyone can look at the same sentence or diagram and learn how to avoid such misunderstandings in the future.
- When calls do happen, no one is forced to take notes.
- Most importantly, written back-and-forth builds a full picture of the problem, allowing the individual and/or the team to create a holistic solution.
There are of course downsides to written communication, such as:
- It often takes more time to write something simple than to say it. We’re comfortable with that trade-off because a single call/distraction can zap an entire day’s worth of creative energy.
- Without a daily stand-up, status updates can slip, and the team gets out of sync. Therefore, we ask that on at least a daily basis, everyone shares what they’re doing.
Here are some conversational shortcuts we find ourselves frequently using:
"Problem land" / "Solution land": Used to switch focus between requirements and implementations. Often, teams try to evaluate a specific implementation before truly grasping the issue at hand. For example, “Picking an authentication gem is jumping into solution land. What's the problem? Why does a user have to log in?”
"Famous last words": Used to acknowledge the fragility of estimates, such as “famous last words, but this schedule looks reasonable.”
"Thinking out loud...": Meant to preface inconclusive ideas and thoughts that are absolutely not final or even suggestive.
"We’ll see I guess": Sometimes results and outcomes are not yet clear, and it becomes unproductive to continue talking about them. Instead of getting to an answer that satisfies all parties, we say "we'll see I guess" and move on, especially when the outcome will be evident shortly.
"Spike": The coding cousin of "we'll see I guess", we use "spike" when we believe that writing some code may give more clarity than continuing to talk about it. For example, "I think I know how that report should look, let me spike on it." It is understood that spikes can be discarded if results don't quite work out.
"Colleague": our preferred method for referring to each other. Titles may work for large siloed organizations, but we're trying to remain flat as long as we can and believe our titles should reflect that.
"Bump": A friendly way to remind someone to respond to a thread or email, without any passive aggression. We all have more notifications coming in than we can handle and it's ok to miss one sometimes.
"Thanks" / "Thank you": Say it often and like you mean it. Colleagues can often take each other for granted, especially when they're miles apart.
How We Code
A Manager of One
Each of us wants to be a manager of one. We expect one another to be disciplined and capable of delivery without explicit guidance. This does not mean we don’t come to each other for help, but it does mean we expect one another to make diagnoses, even on issues that aren’t part of our current skillset. For example:
Not preferred: “Hey team, Webpack won’t build the project. I can’t continue this ticket”.
Preferred: “Hey team, Webpack won’t build the project. The error message it’s giving says that Object.getOwnPropertyDescriptor is undefined. I’ve found [some Github issue] and [some StackOverflow article] which talk about something related, but I’m really at a loss for what to try next. [Here’s a link] to the Webpack config file. Can anyone point me in a direction to pursue?”
The second example is not only more explicit but also takes more responsibility for the problem. With that, our team’s time together can be spent on the bigger picture rather than digging into the full background on a Webpack issue.
We are a small team, so we prefer to deliver solutions in technologies that we will not have to debug ourselves such as Docker, Ruby, and React. We plan for our work to be long-lived, and we want the technology we use today to still be relevant in 5 or even 10 years. But these preferences are just that - preferences. We try our best to be non-dogmatic - we don’t believe that VSCode is better than Vim or Atom, we appreciate things about both object-oriented and functional programming, and we do not automatically rule out one programming language or another “just because.” Everything, even this document, is up for discussion and revision. We fully expect our preferences to evolve.
We try to write solutions that are modular and predictable. Simplicity is a promised virtue of functional programming, but we believe the principle can be applied to any programming language, and even further to our business processes.
We deliver to production deliberately. We don’t abide by the “move fast and break things” mentality, especially when we are deploying to production. We prefer a careful and deliberate approach from start to finish. This is as much cultural (it’s who we are) as it is necessitated by our industry and clients.
A deliberate approach also means truly understanding the core problem, not just how to implement the solution. Of course, the occasional time constraint requires us to execute a hurried solution, but that is not our preferred approach. We try to spend ample time in “problem land” before we jump into “solution land.”
While not an exhaustive list of technologies we have used, these stand out as some of our favorites:
- Ruby: We love its expressiveness. Rails remains a compelling option for getting an application up and running quickly, and the community is still healthy and active. We have also used Laravel, and while we don't love PHP, we were pleasantly surprised with Laravel's design and ease of use."
- React: We love its core concepts: UI as a value, and modularity. We like being able to separate UI into its own concern.
- Docker: We try to make it easy for developers to spin up an environment with minimal machine dependencies.
- Elasticsearch: When appropriately used, a full text search engine can provide an awesome user and developer experience for navigating large amounts of data.
- Twitter Bootstrap: We love the design power that a CSS framework can lend to developers.
- Github/CircleCI: Our code lives in Github. We typically use a pull request workflow with a CircleCI build process.
At the same time, we’re very curious about:
- Elixir / Phoenix: functional programming with Ruby-ish syntax? Consider us intrigued.
- Rules Engines: we work on products which have a lot of clearly defined business rules. Programming in a way that clearly expresses those rules could be an internal improvement.
- Functional and Declarative programming: we love the idea of communicating with simple values without side effects. While we haven’t deployed any code in a functional language, we try to use functional concepts even within our OO code.
- GraphQL: we’re increasingly building UI’s that interact with backend APIs, and we like the idea of a more flexible interface between the two.
Finally, some of our favorite resources that have influenced our growth:
- Simple Made Easy - Rich Hickey
- Things I Don’t Know as of 2018 - Dan Abramov
- Boundaries (Functional Core, Imperative Shell) - Gary Bernhardt
- Controlling Complexity - Andy Matuschak
- Growing Rails Applications in Practice - Makandra
- Practical Object-Oriented Design in Ruby
- RailsConf 2018: Opening Keynote: FIXME by David Heinemeier Hansson
- The Wrong Abstraction - Sandi Metz
- Abstraction vs Duplication. Why DRY is bad advice – fluent.software
- A Philosophy of Software Design, Part 0: Introduction - DEV Community
- How To Write Better Code - Johannes Brodwall
How We Set Goals
Vision can be such a silly word, almost as if one of us is some three-eyed raven with a master plan he/she disperses for everyone to follow. We don’t have that here, and it’s really quite the opposite - we hope to all figure out where we're going together.
What we do know is our strenghts - we're strong technologists with deep energy experience, and every day that we come to work we're implementing the digital transformation for electric utilities.
Every quarter, we set “rocks” that serve as our most important goals for each quarter. There are usually 3-4 rocks per quarter, and each is assigned to a single individual to ensure accountability. A recent example of a rock was to launch SCE's Fleet Fuel Calculator.
We set rocks to alleviate the desire for frequent company-wide pivots. A product and its UI may evolve quickly to adapt to user research and feedback, but the company as a whole shouldn’t change weekly. We won’t abandon a current quarterly priority for a shiny new opportunity.
We will often add stretch goals to achieve nice-to-have outcomes for each quarter. These are not driven by firm deadlines and typically take less time to complete, but are crucial for the business long-term.
Every week, we get together to ensure the rocks are on pace to be completed by the end of the quarter. If we see a rock slipping, we may shift staff and priorities.
The rest of the time, we catch up. With all of the nitty gritty covered in slack & github, we often go on long tangents during our heartbeats. And we think that's a good thing - work isn't the only thing that matters.